interpreter: support unchunked mode when h2 connection

This commit is contained in:
Andy Green 2018-01-14 20:09:41 +08:00
parent 673e3aa549
commit a3bbb0a374
4 changed files with 46 additions and 35 deletions

View file

@ -3687,6 +3687,7 @@ struct lws_process_html_args {
int len; /**< length of the original data at p */
int max_len; /**< maximum length we can grow the data to */
int final; /**< set if this is the last chunk of the file */
int chunked; /**< 0 == unchunked, 1 == produce chunk headers (incompatible with HTTP/2) */
};
typedef const char *(*lws_process_html_state_cb)(void *data, int index);

View file

@ -663,8 +663,9 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
poss = context->pt_serv_buf_size - n - LWS_H2_FRAME_HEADER_LENGTH;
if (poss > wsi->http.tx_content_remain)
poss = wsi->http.tx_content_remain;
if (wsi->http.tx_content_length)
if (poss > wsi->http.tx_content_remain)
poss = wsi->http.tx_content_remain;
/*
* if there is a hint about how much we will do well to send at one time,
@ -717,12 +718,13 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
context->timeout_secs);
if (wsi->sending_chunked) {
if (wsi->interpreting) {
args.p = (char *)p;
args.len = n;
args.max_len = (unsigned int)poss + 128;
args.final = wsi->http.filepos + n ==
wsi->http.filelen;
args.chunked = wsi->sending_chunked;
if (user_callback_handle_rxflow(
wsi->vhost->protocols[
(int)wsi->protocol_interpret_idx].callback,
@ -745,7 +747,7 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
}
#endif
m = lws_write(wsi, p, n,
wsi->http.filepos == wsi->http.filelen ?
wsi->http.filepos + amount == wsi->http.filelen ?
LWS_WRITE_HTTP_FINAL :
LWS_WRITE_HTTP
);

View file

@ -1921,6 +1921,7 @@ struct lws {
unsigned int cache_intermediaries:1;
unsigned int favoured_pollin:1;
unsigned int sending_chunked:1;
unsigned int interpreting:1;
unsigned int already_did_cce:1;
unsigned int told_user_closed:1;
unsigned int waiting_to_send_close_frame:1;

View file

@ -531,7 +531,9 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
n = (int)strlen(path);
if (n > (int)strlen(pvo->name) &&
!strcmp(&path[n - strlen(pvo->name)], pvo->name)) {
wsi->sending_chunked = 1;
wsi->interpreting = 1;
if (!wsi->http2_substream)
wsi->sending_chunked = 1;
wsi->protocol_interpret_idx =
(char)(lws_intptr_t)pvo->value;
lwsl_info("want %s interpreted by %s\n", path,
@ -1125,6 +1127,7 @@ lws_http_action(struct lws *wsi)
args.len = uri_len;
args.max_len = hit->auth_mask;
args.final = 0; /* used to signal callback dealt with it */
args.chunked = 0;
n = wsi->protocol->callback(wsi,
LWS_CALLBACK_CHECK_ACCESS_RIGHTS,
@ -2865,17 +2868,19 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
return -1;
#endif
if (!wsi->sending_chunked) {
if (lws_add_http_header_content_length(wsi,
total_content_length,
&p, end))
return -1;
} else {
if (lws_add_http_header_by_token(wsi,
if (!wsi->http2_substream) {
if (!wsi->sending_chunked) {
if (lws_add_http_header_content_length(wsi,
total_content_length,
&p, end))
return -1;
} else {
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_TRANSFER_ENCODING,
(unsigned char *)"chunked",
7, &p, end))
return -1;
return -1;
}
}
if (wsi->cache_secs && wsi->cache_reuse) {
@ -3075,31 +3080,33 @@ skip:
sp++;
}
/* no space left for final chunk trailer */
if (args->final && args->len + 7 >= args->max_len)
return -1;
if (args->chunked) {
/* no space left for final chunk trailer */
if (args->final && args->len + 7 >= args->max_len)
return -1;
n = sprintf(buffer, "%X\x0d\x0a", args->len);
n = sprintf(buffer, "%X\x0d\x0a", args->len);
args->p -= n;
memcpy(args->p, buffer, n);
args->len += n;
args->p -= n;
memcpy(args->p, buffer, n);
args->len += n;
if (args->final) {
sp = args->p + args->len;
*sp++ = '\x0d';
*sp++ = '\x0a';
*sp++ = '0';
*sp++ = '\x0d';
*sp++ = '\x0a';
*sp++ = '\x0d';
*sp++ = '\x0a';
args->len += 7;
} else {
sp = args->p + args->len;
*sp++ = '\x0d';
*sp++ = '\x0a';
args->len += 2;
if (args->final) {
sp = args->p + args->len;
*sp++ = '\x0d';
*sp++ = '\x0a';
*sp++ = '0';
*sp++ = '\x0d';
*sp++ = '\x0a';
*sp++ = '\x0d';
*sp++ = '\x0a';
args->len += 7;
} else {
sp = args->p + args->len;
*sp++ = '\x0d';
*sp++ = '\x0a';
args->len += 2;
}
}
return 0;