mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
http2 track content length add END_STREAM
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
91b0589795
commit
200f385716
7 changed files with 244 additions and 31 deletions
137
lib/hpack.c
137
lib/hpack.c
|
@ -238,25 +238,96 @@ static void lws_dump_header(struct libwebsocket *wsi, int hdr)
|
|||
char s[200];
|
||||
int len = lws_hdr_copy(wsi, s, sizeof(s) - 1, hdr);
|
||||
s[len] = '\0';
|
||||
lwsl_info(" hdr tok %d '%s'\n", hdr, s);
|
||||
lwsl_info(" hdr tok %d (%s) = '%s'\n", hdr, lws_token_to_string(hdr), s);
|
||||
}
|
||||
|
||||
static int lws_token_from_index(struct libwebsocket *wsi, int index)
|
||||
static int lws_token_from_index(struct libwebsocket *wsi, int index, char **arg, int *len)
|
||||
{
|
||||
struct hpack_dynamic_table *dyn;
|
||||
|
||||
/* dynamic table only belongs to network wsi */
|
||||
|
||||
wsi = lws_http2_get_network_wsi(wsi);
|
||||
|
||||
dyn = wsi->u.http2.hpack_dyn_table;
|
||||
|
||||
if (index < ARRAY_SIZE(static_token))
|
||||
return static_token[index];
|
||||
|
||||
if (!dyn)
|
||||
return 0;
|
||||
|
||||
// dynamic indexes
|
||||
index -= ARRAY_SIZE(static_token);
|
||||
if (index >= dyn->num_entries)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
if (arg && len) {
|
||||
*arg = dyn->args + dyn->entries[index].arg_offset;
|
||||
*len = dyn->entries[index].arg_len;
|
||||
}
|
||||
|
||||
return dyn->entries[index].token;
|
||||
}
|
||||
|
||||
static int lws_add_indexed_hdr(struct libwebsocket *wsi, int idx)
|
||||
static int lws_hpack_add_dynamic_header(struct libwebsocket *wsi, int token, char *arg, int len)
|
||||
{
|
||||
struct hpack_dynamic_table *dyn;
|
||||
int ret = 1;
|
||||
|
||||
wsi = lws_http2_get_network_wsi(wsi);
|
||||
dyn = wsi->u.http2.hpack_dyn_table;
|
||||
|
||||
if (!dyn) {
|
||||
dyn = malloc(sizeof(*dyn));
|
||||
if (!dyn)
|
||||
return 1;
|
||||
memset(dyn, 0, sizeof(*dyn));
|
||||
wsi->u.http2.hpack_dyn_table = dyn;
|
||||
|
||||
dyn->args = malloc(1024);
|
||||
if (!dyn->args)
|
||||
goto bail1;
|
||||
dyn->args_length = 1024;
|
||||
dyn->entries = malloc(sizeof(dyn->entries[0]) * 20);
|
||||
if (!dyn->entries)
|
||||
goto bail2;
|
||||
dyn->num_entries = 20;
|
||||
}
|
||||
|
||||
if (dyn->next == dyn->num_entries)
|
||||
return 1;
|
||||
|
||||
if (dyn->args_length - dyn->pos < len)
|
||||
return 1;
|
||||
|
||||
dyn->entries[dyn->next].token = token;
|
||||
dyn->entries[dyn->next].arg_offset = dyn->pos;
|
||||
if (len)
|
||||
memcpy(dyn->args + dyn->pos, arg, len);
|
||||
dyn->entries[dyn->next].arg_len = len;
|
||||
|
||||
lwsl_info("%s: added dynamic hdr %d, token %d (%s), len %d\n", __func__, dyn->next, token, lws_token_to_string(token), len);
|
||||
|
||||
dyn->pos += len;
|
||||
dyn->next++;
|
||||
|
||||
return 0;
|
||||
|
||||
bail2:
|
||||
free(dyn->args);
|
||||
bail1:
|
||||
free(dyn);
|
||||
wsi->u.http2.hpack_dyn_table = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lws_write_indexed_hdr(struct libwebsocket *wsi, int idx)
|
||||
{
|
||||
const char *p;
|
||||
int tok = lws_token_from_index(wsi, idx);
|
||||
int tok = lws_token_from_index(wsi, idx, NULL, 0);
|
||||
|
||||
lwsl_info("adding indexed hdr %d (tok %d)\n", idx, tok);
|
||||
lwsl_info("writing indexed hdr %d (tok %d '%s')\n", idx, tok, lws_token_to_string(tok));
|
||||
|
||||
if (lws_frag_start(wsi, tok))
|
||||
return 1;
|
||||
|
@ -283,6 +354,28 @@ int lws_hpack_interpret(struct libwebsocket_context *context,
|
|||
int n;
|
||||
|
||||
switch (wsi->u.http2.hpack) {
|
||||
case HPKS_OPT_PADDING:
|
||||
wsi->u.http2.padding = c;
|
||||
lwsl_info("padding %d\n", c);
|
||||
if (wsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
|
||||
wsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
|
||||
wsi->u.http2.hpack_m = 4;
|
||||
} else
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
break;
|
||||
case HKPS_OPT_E_DEPENDENCY:
|
||||
wsi->u.http2.hpack_e_dep <<= 8;
|
||||
wsi->u.http2.hpack_e_dep |= c;
|
||||
if (! --wsi->u.http2.hpack_m) {
|
||||
lwsl_info("hpack_e_dep = 0x%x\n", wsi->u.http2.hpack_e_dep);
|
||||
wsi->u.http2.hpack = HKPS_OPT_WEIGHT;
|
||||
}
|
||||
break;
|
||||
case HKPS_OPT_WEIGHT:
|
||||
/* weight */
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
break;
|
||||
|
||||
case HPKS_TYPE:
|
||||
if (c & 0x80) { /* indexed header field only */
|
||||
/* just a possibly-extended integer */
|
||||
|
@ -294,7 +387,7 @@ int lws_hpack_interpret(struct libwebsocket_context *context,
|
|||
wsi->u.http2.hpack = HPKS_IDX_EXT;
|
||||
break;
|
||||
}
|
||||
if (lws_add_indexed_hdr(wsi, c & 0x7f))
|
||||
if (lws_write_indexed_hdr(wsi, c & 0x7f))
|
||||
return 1;
|
||||
/* stay at same state */
|
||||
break;
|
||||
|
@ -374,7 +467,7 @@ int lws_hpack_interpret(struct libwebsocket_context *context,
|
|||
if (!(c & 0x80)) {
|
||||
switch (wsi->u.http2.hpack_type) {
|
||||
case HPKT_INDEXED_HDR_7:
|
||||
if (lws_add_indexed_hdr(wsi, wsi->u.http2.hpack_len))
|
||||
if (lws_write_indexed_hdr(wsi, wsi->u.http2.hpack_len))
|
||||
return 1;
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
break;
|
||||
|
@ -396,7 +489,7 @@ pre_data:
|
|||
if (wsi->u.http2.value) {
|
||||
if (lws_frag_start(wsi,
|
||||
lws_token_from_index(wsi,
|
||||
wsi->u.http2.header_index)))
|
||||
wsi->u.http2.header_index, NULL, NULL)))
|
||||
return 1;
|
||||
} else
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
|
@ -448,14 +541,27 @@ pre_data:
|
|||
}
|
||||
}
|
||||
if (--wsi->u.http2.hpack_len == 0) {
|
||||
|
||||
switch (wsi->u.http2.hpack_type) {
|
||||
case HPKT_LITERAL_HDR_VALUE_INCR:
|
||||
case HPKT_INDEXED_HDR_6_VALUE_INCR: // !!!
|
||||
if (lws_hpack_add_dynamic_header(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index, NULL, NULL), NULL, 0))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
n = 8;
|
||||
if (wsi->u.http2.value) {
|
||||
if (lws_frag_end(wsi))
|
||||
return 1;
|
||||
|
||||
lws_dump_header(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index));
|
||||
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
lws_dump_header(wsi, lws_token_from_index(wsi, wsi->u.http2.header_index, NULL, NULL));
|
||||
if (wsi->u.http2.count + wsi->u.http2.padding == wsi->u.http2.length)
|
||||
wsi->u.http2.hpack = HKPS_OPT_DISCARD_PADDING;
|
||||
else
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
} else { /* name */
|
||||
if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT)
|
||||
|
||||
|
@ -464,6 +570,11 @@ pre_data:
|
|||
}
|
||||
}
|
||||
break;
|
||||
case HKPS_OPT_DISCARD_PADDING:
|
||||
lwsl_info("eating padding %x\n", c);
|
||||
if (! --wsi->u.http2.padding)
|
||||
wsi->u.http2.hpack = HPKS_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
44
lib/http2.c
44
lib/http2.c
|
@ -128,14 +128,19 @@ lws_http2_interpret_settings_payload(struct http2_settings *settings, unsigned c
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct libwebsocket *lws_http2_get_network_wsi(struct libwebsocket *wsi)
|
||||
{
|
||||
while (wsi->u.http2.parent_wsi)
|
||||
wsi = wsi->u.http2.parent_wsi;
|
||||
|
||||
return wsi;
|
||||
}
|
||||
|
||||
int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf)
|
||||
{
|
||||
struct libwebsocket *wsi_eff = wsi;
|
||||
struct libwebsocket *wsi_eff = lws_http2_get_network_wsi(wsi);
|
||||
unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH];
|
||||
int n;
|
||||
|
||||
while (wsi_eff->u.http2.parent_wsi)
|
||||
wsi_eff = wsi_eff->u.http2.parent_wsi;
|
||||
|
||||
*p++ = len >> 16;
|
||||
*p++ = len >> 8;
|
||||
|
@ -174,6 +179,7 @@ int
|
|||
lws_http2_parser(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
struct libwebsocket *swsi;
|
||||
int n;
|
||||
//dstruct libwebsocket *wsi_new;
|
||||
|
||||
|
@ -200,6 +206,8 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
case WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS:
|
||||
case WSI_STATE_HTTP2_ESTABLISHED:
|
||||
if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { // payload
|
||||
wsi->u.http2.count++;
|
||||
wsi->u.http2.stream_wsi->u.http2.count = wsi->u.http2.count;
|
||||
/* applies to wsi->u.http2.stream_wsi which may be wsi*/
|
||||
switch(wsi->u.http2.type) {
|
||||
case LWS_HTTP2_FRAME_TYPE_SETTINGS:
|
||||
|
@ -217,7 +225,6 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
return 1;
|
||||
break;
|
||||
}
|
||||
wsi->u.http2.count++;
|
||||
if (wsi->u.http2.count != wsi->u.http2.length)
|
||||
break;
|
||||
|
||||
|
@ -294,15 +301,34 @@ lws_http2_parser(struct libwebsocket_context *context,
|
|||
wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id);
|
||||
if (!wsi->u.http2.stream_wsi)
|
||||
wsi->u.http2.stream_wsi = lws_create_server_child_wsi(context, wsi, wsi->u.http2.stream_id);
|
||||
|
||||
if (!wsi->u.http2.stream_wsi)
|
||||
return 1;
|
||||
|
||||
|
||||
/* END_STREAM means after servicing this, close the stream */
|
||||
wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM);
|
||||
lwsl_info("%s: headers END_STREAM = %d\n",__func__, wsi->u.http2.END_STREAM);
|
||||
update_end_headers:
|
||||
/* no END_HEADERS means CONTINUATION must come */
|
||||
wsi->u.http2.END_HEADERS = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_HEADERS);
|
||||
|
||||
swsi = wsi->u.http2.stream_wsi;
|
||||
if (!swsi)
|
||||
return 1;
|
||||
|
||||
|
||||
/* prepare the hpack parser at the right start */
|
||||
|
||||
swsi->u.http2.flags = wsi->u.http2.flags;
|
||||
swsi->u.http2.length = wsi->u.http2.length;
|
||||
swsi->u.http2.END_STREAM = wsi->u.http2.END_STREAM;
|
||||
|
||||
if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PADDED)
|
||||
swsi->u.http2.hpack = HPKS_OPT_PADDING;
|
||||
else
|
||||
if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
|
||||
swsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
|
||||
swsi->u.http2.hpack_m = 4;
|
||||
} else
|
||||
swsi->u.http2.hpack = HPKS_TYPE;
|
||||
lwsl_info("initial hpack state %d\n", swsi->u.http2.hpack);
|
||||
break;
|
||||
}
|
||||
if (wsi->u.http2.length == 0)
|
||||
|
|
|
@ -265,6 +265,9 @@ enum libwebsocket_write_protocol {
|
|||
LWS_WRITE_PING,
|
||||
LWS_WRITE_PONG,
|
||||
|
||||
/* Same as write_http but we know this write ends the transaction */
|
||||
LWS_WRITE_HTTP_FINAL,
|
||||
|
||||
/* HTTP2 */
|
||||
|
||||
LWS_WRITE_HTTP_HEADERS,
|
||||
|
@ -1082,6 +1085,11 @@ lws_add_http_header_by_token(struct libwebsocket_context *context,
|
|||
int length,
|
||||
unsigned char **p,
|
||||
unsigned char *end);
|
||||
LWS_VISIBLE LWS_EXTERN int lws_add_http_header_content_length(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
unsigned long content_length,
|
||||
unsigned char **p,
|
||||
unsigned char *end);
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_add_http_header_status(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
|
|
24
lib/output.c
24
lib/output.c
|
@ -264,7 +264,9 @@ LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (protocol == LWS_WRITE_HTTP || protocol == LWS_WRITE_HTTP_HEADERS)
|
||||
if (protocol == LWS_WRITE_HTTP ||
|
||||
protocol == LWS_WRITE_HTTP_FINAL ||
|
||||
protocol == LWS_WRITE_HTTP_HEADERS)
|
||||
goto send_raw;
|
||||
|
||||
/* websocket protocol, either binary or text */
|
||||
|
@ -431,6 +433,7 @@ send_raw:
|
|||
case LWS_WRITE_CLOSE:
|
||||
/* lwsl_hexdump(&buf[-pre], len + post); */
|
||||
case LWS_WRITE_HTTP:
|
||||
case LWS_WRITE_HTTP_FINAL:
|
||||
case LWS_WRITE_HTTP_HEADERS:
|
||||
case LWS_WRITE_PONG:
|
||||
case LWS_WRITE_PING:
|
||||
|
@ -443,6 +446,21 @@ send_raw:
|
|||
n = LWS_HTTP2_FRAME_TYPE_HEADERS;
|
||||
flags = LWS_HTTP2_FLAG_END_HEADERS;
|
||||
}
|
||||
|
||||
if ((protocol == LWS_WRITE_HTTP || protocol == LWS_WRITE_HTTP_FINAL) && wsi->u.http.content_length) {
|
||||
wsi->u.http.content_remain -= len;
|
||||
lwsl_info("%s: content_remain = %lu\n", __func__, wsi->u.http.content_remain);
|
||||
if (!wsi->u.http.content_remain) {
|
||||
lwsl_info("%s: selecting final write mode\n", __func__);
|
||||
protocol = LWS_WRITE_HTTP_FINAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol == LWS_WRITE_HTTP_FINAL && wsi->u.http2.END_STREAM) {
|
||||
lwsl_info("%s: setting END_STREAM\n", __func__);
|
||||
flags |= LWS_HTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
|
||||
return lws_http2_frame_write(wsi, n, flags, wsi->u.http2.my_stream_id, len, buf);
|
||||
}
|
||||
#endif
|
||||
|
@ -519,12 +537,12 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
|
|||
if (n < 0)
|
||||
return -1; /* caller will close */
|
||||
if (n) {
|
||||
wsi->u.http.filepos += n;
|
||||
m = libwebsocket_write(wsi, context->service_buffer, n,
|
||||
LWS_WRITE_HTTP);
|
||||
wsi->u.http.filepos == wsi->u.http.filelen ? LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
|
||||
wsi->u.http.filepos += m;
|
||||
if (m != n)
|
||||
/* adjust for what was not sent */
|
||||
compatible_file_seek_cur(wsi->u.http.fd, m - n);
|
||||
|
|
|
@ -626,6 +626,13 @@ struct http2_settings {
|
|||
};
|
||||
|
||||
enum http2_hpack_state {
|
||||
|
||||
/* optional before first header block */
|
||||
HPKS_OPT_PADDING,
|
||||
HKPS_OPT_E_DEPENDENCY,
|
||||
HKPS_OPT_WEIGHT,
|
||||
|
||||
/* header block */
|
||||
HPKS_TYPE,
|
||||
|
||||
HPKS_IDX_EXT,
|
||||
|
@ -634,6 +641,9 @@ enum http2_hpack_state {
|
|||
HPKS_HLEN_EXT,
|
||||
|
||||
HPKS_DATA,
|
||||
|
||||
/* optional after last header block */
|
||||
HKPS_OPT_DISCARD_PADDING,
|
||||
};
|
||||
|
||||
enum http2_hpack_type {
|
||||
|
@ -645,6 +655,21 @@ enum http2_hpack_type {
|
|||
HPKT_SIZE_5
|
||||
};
|
||||
|
||||
struct hpack_dt_entry {
|
||||
int token; /* additions that don't map to a token are ignored */
|
||||
int arg_offset;
|
||||
int arg_len;
|
||||
};
|
||||
|
||||
struct hpack_dynamic_table {
|
||||
struct hpack_dt_entry *entries;
|
||||
char *args;
|
||||
int pos;
|
||||
int next;
|
||||
int num_entries;
|
||||
int args_length;
|
||||
};
|
||||
|
||||
struct _lws_http2_related {
|
||||
/*
|
||||
* having this first lets us also re-use all HTTP union code
|
||||
|
@ -659,6 +684,8 @@ struct _lws_http2_related {
|
|||
struct libwebsocket *parent_wsi;
|
||||
struct libwebsocket *next_child_wsi;
|
||||
|
||||
struct hpack_dynamic_table *hpack_dyn_table;
|
||||
|
||||
unsigned int count;
|
||||
|
||||
/* frame */
|
||||
|
@ -668,6 +695,7 @@ struct _lws_http2_related {
|
|||
unsigned char type;
|
||||
unsigned char flags;
|
||||
unsigned char frame_state;
|
||||
unsigned char padding;
|
||||
|
||||
unsigned int END_STREAM:1;
|
||||
unsigned int END_HEADERS:1;
|
||||
|
@ -679,6 +707,7 @@ struct _lws_http2_related {
|
|||
unsigned int hpack_len;
|
||||
unsigned short hpack_pos;
|
||||
unsigned char hpack_m;
|
||||
unsigned int hpack_e_dep;
|
||||
unsigned int huff:1;
|
||||
unsigned int value:1;
|
||||
|
||||
|
@ -923,6 +952,7 @@ user_callback_handle_rxflow(callback_function,
|
|||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
#ifdef LWS_USE_HTTP2
|
||||
LWS_EXTERN struct libwebsocket *lws_http2_get_network_wsi(struct libwebsocket *wsi);
|
||||
LWS_EXTERN int
|
||||
lws_http2_interpret_settings_payload(struct http2_settings *settings, unsigned char *buf, int len);
|
||||
LWS_EXTERN void lws_http2_init(struct http2_settings *settings);
|
||||
|
|
23
lib/server.c
23
lib/server.c
|
@ -943,6 +943,24 @@ int lws_add_http_header_by_token(struct libwebsocket_context *context,
|
|||
return lws_add_http_header_by_name(context, wsi, name, value, length, p, end);
|
||||
}
|
||||
|
||||
int lws_add_http_header_content_length(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
unsigned long content_length,
|
||||
unsigned char **p,
|
||||
unsigned char *end)
|
||||
{
|
||||
char b[24];
|
||||
int n;
|
||||
|
||||
n = sprintf(b, "%lu", content_length);
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)b, n, p, end))
|
||||
return 1;
|
||||
wsi->u.http.content_length = content_length;
|
||||
wsi->u.http.content_remain = content_length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *err400[] = {
|
||||
"Bad Request",
|
||||
"Unauthorized",
|
||||
|
@ -1069,9 +1087,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file(
|
|||
unsigned char *p = response;
|
||||
unsigned char *end = p + sizeof(context->service_buffer) -
|
||||
LWS_SEND_BUFFER_PRE_PADDING;
|
||||
unsigned char clen[10];
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen);
|
||||
|
||||
|
@ -1088,8 +1104,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file(
|
|||
return -1;
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)content_type, strlen(content_type), &p, end))
|
||||
return -1;
|
||||
n = sprintf((char *)clen, "%lu", (unsigned long)wsi->u.http.filelen);
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, clen, n, &p, end))
|
||||
if (lws_add_http_header_content_length(context, wsi, wsi->u.http.filelen, &p, end))
|
||||
return -1;
|
||||
|
||||
if (other_headers) {
|
||||
|
|
|
@ -234,8 +234,7 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
return 1;
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"image/jpeg", 10, &p, end))
|
||||
return 1;
|
||||
n = sprintf(b64, "%u", (unsigned int)stat_buf.st_size);
|
||||
if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)b64, n, &p, end))
|
||||
if (lws_add_http_header_content_length(context, wsi,stat_buf.st_size, &p, end))
|
||||
return 1;
|
||||
if (lws_finalize_http_header(context, wsi, &p, end))
|
||||
return 1;
|
||||
|
@ -356,8 +355,10 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
/* sent it all, close conn */
|
||||
if (n == 0)
|
||||
goto flush_bail;
|
||||
|
||||
/*
|
||||
* To support HTTP2, must take care about preamble space
|
||||
* and identify when we send the last frame
|
||||
*/
|
||||
m = libwebsocket_write(wsi,
|
||||
buffer + LWS_SEND_BUFFER_PRE_PADDING,
|
||||
|
@ -365,6 +366,9 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
if (m < 0)
|
||||
/* write failed, close conn */
|
||||
goto bail;
|
||||
/*
|
||||
* http2 won't do this
|
||||
*/
|
||||
if (m != n)
|
||||
/* partial write, adjust */
|
||||
lseek(pss->fd, m - n, SEEK_CUR);
|
||||
|
@ -378,6 +382,7 @@ static int callback_http(struct libwebsocket_context *context,
|
|||
break;
|
||||
|
||||
} while (!lws_send_pipe_choked(wsi));
|
||||
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
flush_bail:
|
||||
|
|
Loading…
Add table
Reference in a new issue