aboutsummaryrefslogtreecommitdiff
path: root/lib/roles/h1
diff options
context:
space:
mode:
authorAndy Green <andy@warmcat.com>2020-12-20 08:39:49 +0000
committerAndy Green <andy@warmcat.com>2020-12-24 16:14:36 +0000
commitc6cb8211651fd83e6c1ec1ebdebce517e897da0c (patch)
tree426a4a29e583228cdfb6d8607ce18237271a8f5a /lib/roles/h1
parent677b6e370cec4b1d60ad5ef2419c00c64b611b33 (diff)
downloadlibwebsockets-c6cb8211651fd83e6c1ec1ebdebce517e897da0c.tar.gz
h2: post: handle no content length better
http content-length is not mandatory on POST, making a whole bunch of difficulties. On h2, the client will set the stream half-closed by DATA with END_STREAM flag when it is done. Improve the post data tracking to understand that situation properly.
Diffstat (limited to 'lib/roles/h1')
-rw-r--r--lib/roles/h1/ops-h1.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c
index 2157e23e..f0ade7f0 100644
--- a/lib/roles/h1/ops-h1.c
+++ b/lib/roles/h1/ops-h1.c
@@ -125,18 +125,22 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
case LRS_DISCARD_BODY:
case LRS_BODY:
http_postbody:
- lwsl_debug("%s: http post body: remain %d\n", __func__,
- (int)wsi->http.rx_content_remain);
+ lwsl_info("%s: http post body: cl set %d, remain %d, len %d\n", __func__,
+ (int)wsi->http.content_length_given,
+ (int)wsi->http.rx_content_remain, (int)len);
- if (!wsi->http.rx_content_remain)
+ if (wsi->http.content_length_given && !wsi->http.rx_content_remain)
goto postbody_completion;
- while (len && wsi->http.rx_content_remain) {
+ while (len && (!wsi->http.content_length_given || wsi->http.rx_content_remain)) {
/* Copy as much as possible, up to the limit of:
* what we have in the read buffer (len)
* remaining portion of the POST body (content_remain)
*/
- body_chunk_len = min(wsi->http.rx_content_remain, len);
+ if (wsi->http.content_length_given)
+ body_chunk_len = min(wsi->http.rx_content_remain, len);
+ else
+ body_chunk_len = len;
wsi->http.rx_content_remain -= body_chunk_len;
// len -= body_chunk_len;
#ifdef LWS_WITH_CGI
@@ -159,18 +163,38 @@ http_postbody:
} else {
#endif
if (lwsi_state(wsi) != LRS_DISCARD_BODY) {
- n = wsi->a.protocol->callback(wsi,
- LWS_CALLBACK_HTTP_BODY, wsi->user_space,
- buf, (size_t)body_chunk_len);
- if (n)
- goto bail;
+ lwsl_info("%s: HTTP_BODY %d\n", __func__, (int)body_chunk_len);
+ n = (unsigned int)wsi->a.protocol->callback(wsi,
+ LWS_CALLBACK_HTTP_BODY, wsi->user_space,
+ buf, (size_t)body_chunk_len);
+ if (n)
+ goto bail;
}
n = (size_t)body_chunk_len;
#ifdef LWS_WITH_CGI
}
#endif
+ lwsl_info("%s: advancing buf by %d\n", __func__, (int)n);
buf += n;
+#if defined(LWS_ROLE_H2)
+ if (lwsi_role_h2(wsi) && !wsi->http.content_length_given) {
+ struct lws *w = lws_get_network_wsi(wsi);
+
+ lwsl_info("%s: h2: nwsi h2 flags %d\n", __func__,
+ w->h2.h2n ? w->h2.h2n->flags: -1);
+
+ if (w && w->h2.h2n && !(w->h2.h2n->flags & 1)) {
+ lwsl_info("%s: h2, no cl, not END_STREAM, continuing\n", __func__);
+ lws_set_timeout(wsi,
+ PENDING_TIMEOUT_HTTP_CONTENT,
+ (int)wsi->a.context->timeout_secs);
+ break;
+ }
+ goto postbody_completion;
+ }
+#endif
+
if (wsi->http.rx_content_remain) {
lws_set_timeout(wsi,
PENDING_TIMEOUT_HTTP_CONTENT,
@@ -213,8 +237,10 @@ postbody_completion:
n = wsi->a.protocol->callback(wsi,
LWS_CALLBACK_HTTP_BODY_COMPLETION,
wsi->user_space, NULL, 0);
- if (n)
+ if (n) {
+ lwsl_info("%s: bailing after BODY_COMPLETION\n", __func__);
goto bail;
+ }
if (wsi->mux_substream)
lwsi_set_state(wsi, LRS_ESTABLISHED);