From 8f4f692945205eca9410f5a37da5d5cd7b8a3c74 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 28 Jun 2017 12:13:13 +0800 Subject: [PATCH] ah: require parsing complete before detach Introduce helpers to force to detachable state and to test the ah is in a detachable state. Require not only the ah rx buffer is all used, but that the wsi has completed a full set of headers. --- lib/client-handshake.c | 4 ++-- lib/client.c | 4 ++-- lib/libwebsockets.c | 7 +++---- lib/parsers.c | 29 ++++++++++++++++++++++++----- lib/private-libwebsockets.h | 5 +++++ lib/server.c | 12 ++++++------ lib/service.c | 3 +-- 7 files changed, 43 insertions(+), 21 deletions(-) diff --git a/lib/client-handshake.c b/lib/client-handshake.c index 4fb9d4c..ea402f4 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -402,8 +402,8 @@ lws_client_connect_2(struct lws *wsi) oom4: /* we're closing, losing some rx is OK */ - if (wsi->u.hdr.ah) - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); + if (wsi->mode == LWSCM_HTTP_CLIENT || wsi->mode == LWSCM_HTTP_CLIENT_ACCEPTED || wsi->mode == LWSCM_WSCL_WAITING_CONNECT) { diff --git a/lib/client.c b/lib/client.c index 3092f3b..0af13aa 100755 --- a/lib/client.c +++ b/lib/client.c @@ -583,7 +583,7 @@ lws_http_transaction_completed_client(struct lws *wsi) * we can drop the ah, if any */ if (wsi->u.hdr.ah) { - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); lws_header_table_detach(wsi, 0); } @@ -1258,7 +1258,7 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) wsi->user_space, NULL, 0)) return NULL; - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); lws_union_transition(wsi, LWSCM_RAW); lws_header_table_detach(wsi, 1); diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index d51f29e..6643eea 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -243,9 +243,8 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) } #endif - if (wsi->u.hdr.ah) - /* we're closing, losing some rx is OK */ - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + /* we're closing, losing some rx is OK */ + lws_header_table_force_to_detachable_state(wsi); context = wsi->context; pt = &context->pt[(int)wsi->tsi]; @@ -2552,7 +2551,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len * Actually having made the env, as a cgi we don't need the ah * any more */ - if (wsi->u.hdr.ah->rxpos == wsi->u.hdr.ah->rxlen) + if (lws_header_table_is_in_detachable_state(wsi)) lws_header_table_detach(wsi, 0); /* we are ready with the redirection pipes... run the thing */ diff --git a/lib/parsers.c b/lib/parsers.c index 5630daa..9699218 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -215,6 +215,24 @@ bail: return 1; } +void +lws_header_table_force_to_detachable_state(struct lws *wsi) +{ + if (wsi->u.hdr.ah) { + wsi->u.hdr.ah->rxpos = -1; + wsi->u.hdr.ah->rxlen = -1; + wsi->hdr_parsing_completed = 1; + } +} + +int +lws_header_table_is_in_detachable_state(struct lws *wsi) +{ + struct allocated_headers *ah = wsi->u.hdr.ah; + + return ah && ah->rxpos == ah->rxlen && wsi->hdr_parsing_completed; +} + int lws_header_table_detach(struct lws *wsi, int autoservice) { struct lws_context *context = wsi->context; @@ -224,6 +242,9 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) struct lws **pwsi; time_t now; + if (!ah) + return 0; + lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__, (void *)wsi, (void *)ah, wsi->tsi, pt->ah_count_in_use); @@ -232,11 +253,9 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) lws_free_set_NULL(wsi->u.hdr.preamble_rx); /* may not be detached while he still has unprocessed rx */ - if (ah && ah->rxpos != ah->rxlen) { - lwsl_err("%s: %p: CANNOT DETACH rxpos:%d, rxlen:%d\n", __func__, wsi, - ah->rxpos, ah->rxlen); - assert(ah->rxpos == ah->rxlen); - + if (!lws_header_table_is_in_detachable_state(wsi)) { + lwsl_err("%s: %p: CANNOT DETACH rxpos:%d, rxlen:%d, wsi->hdr_parsing_completed = %d\n", __func__, wsi, + ah->rxpos, ah->rxlen, wsi->hdr_parsing_completed); return 0; } diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 1cee7c2..f8471a0 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1904,6 +1904,11 @@ lws_header_table_reset(struct lws *wsi, int autoservice); void _lws_header_table_reset(struct allocated_headers *ah); +void +lws_header_table_force_to_detachable_state(struct lws *wsi); +int +lws_header_table_is_in_detachable_state(struct lws *wsi); + LWS_EXTERN char * LWS_WARN_UNUSED_RESULT lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h); diff --git a/lib/server.c b/lib/server.c index 9db2ec2..76c914c 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1271,7 +1271,7 @@ deal_body: bail_nuke_ah: /* we're closing, losing some rx is OK */ - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); // lwsl_notice("%s: drop1\n", __func__); lws_header_table_detach(wsi, 1); @@ -1338,7 +1338,7 @@ raw_transition: wsi->user_space, NULL, 0)) goto bail_nuke_ah; - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); lws_union_transition(wsi, LWSCM_RAW); lws_header_table_detach(wsi, 1); @@ -1697,7 +1697,7 @@ upgrade_ws: /* !!! drop ah unreservedly after ESTABLISHED */ if (!wsi->more_rx_waiting) { - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); //lwsl_notice("%p: dropping ah EST\n", wsi); lws_header_table_detach(wsi, 1); @@ -1711,7 +1711,7 @@ upgrade_ws: bail_nuke_ah: /* drop the header info */ /* we're closing, losing some rx is OK */ - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); //lwsl_notice("%s: drop2\n", __func__); lws_header_table_detach(wsi, 1); @@ -1847,7 +1847,7 @@ lws_http_transaction_completed(struct lws *wsi) wsi->more_rx_waiting); if (!wsi->more_rx_waiting) { - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); lws_header_table_detach(wsi, 1); #ifdef LWS_OPENSSL_SUPPORT /* @@ -2260,7 +2260,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi, 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 && + if (lws_header_table_is_in_detachable_state(wsi) && (wsi->mode != LWSCM_HTTP_SERVING && wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED && wsi->mode != LWSCM_HTTP2_SERVING)) diff --git a/lib/service.c b/lib/service.c index 6d7e538..1614ea3 100644 --- a/lib/service.c +++ b/lib/service.c @@ -1257,8 +1257,7 @@ drain: if (wsi->u.hdr.ah) { lwsl_notice("%s: %p: detaching\n", __func__, wsi); - /* show we used all the pending rx up */ - wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + lws_header_table_force_to_detachable_state(wsi); /* we can run the normal ah detach flow despite * being in ws union mode, since all union members * start with hdr */ -- 2.7.4