From f94bef42c4e8939c8646c83292611ce1efb4a779 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 29 Sep 2016 10:31:06 +0800 Subject: [PATCH] lws_header_table_reset: make caller responsibility to clear down ah rx buffer There are two kinds of reaason to call lws_header_table_reset(), one is we are reallocating a destroyed ah to another wsi, and the other is we are moving to the next pipelined header set still on the same wsi, and we need a "weaker" reset that only clears down the state related to the header parsing, not everything about the ah context including the ah rx buffer. This patch moves the ah rxbuffer rxpos and rxlen resetting out of lws_header_table_reset() and to be the responsibility of the caller. Callers who are moving the ah to another wsi are patched to deal with resetting rxpos and rxlen and lws_http_transaction_completed() who only resets the ah when moving to the next pipelined headers, no longer wrongly clears the ah rxbuf. https://github.com/warmcat/libwebsockets/issues/638 --- lib/parsers.c | 14 ++++++++++---- lib/server.c | 4 ++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/parsers.c b/lib/parsers.c index f73918d6..5dfcc170 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -60,6 +60,8 @@ lextable_decode(int pos, char c) } } +// doesn't scrub the ah rxbuffer by default, parent must do if needed + void lws_header_table_reset(struct lws *wsi, int autoservice) { @@ -77,10 +79,6 @@ lws_header_table_reset(struct lws *wsi, int autoservice) ah->nfrag = 0; ah->pos = 0; - /* and reset the rx state */ - ah->rxpos = 0; - ah->rxlen = 0; - /* since we will restart the ah, our new headers are not completed */ // wsi->hdr_parsing_completed = 0; @@ -182,6 +180,11 @@ lws_header_table_attach(struct lws *wsi, int autoservice) lws_pt_unlock(pt); reset: + + /* and reset the rx state */ + wsi->u.hdr.ah->rxpos = 0; + wsi->u.hdr.ah->rxlen = 0; + lws_header_table_reset(wsi, autoservice); time(&wsi->u.hdr.ah->assigned); @@ -288,6 +291,9 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) wsi->u.hdr.ah = ah; ah->wsi = wsi; /* new owner */ + /* and reset the rx state */ + ah->rxpos = 0; + ah->rxlen = 0; lws_header_table_reset(wsi, autoservice); time(&wsi->u.hdr.ah->assigned); diff --git a/lib/server.c b/lib/server.c index 7f79ad25..25c43477 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1791,11 +1791,15 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi, if ( wsi->u.hdr.ah->rxlen) wsi->u.hdr.ah->rxpos += n; + lwsl_debug("%s: wsi %p: ah read rxpos %d, rxlen %d\n", __func__, wsi, wsi->u.hdr.ah->rxpos, wsi->u.hdr.ah->rxlen); + if (wsi->u.hdr.ah->rxpos == wsi->u.hdr.ah->rxlen && (wsi->mode != LWSCM_HTTP_SERVING && wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED && wsi->mode != LWSCM_HTTP2_SERVING)) lws_header_table_detach(wsi, 1); + else + wsi->more_rx_waiting = 1; } break; }