diff --git a/lib/client/client-handshake.c b/lib/client/client-handshake.c index c07a630e..f3593e6e 100644 --- a/lib/client/client-handshake.c +++ b/lib/client/client-handshake.c @@ -50,7 +50,7 @@ lws_client_connect_2(struct lws *wsi) lwsl_client("%s\n", __func__); - if (!wsi->u.hdr.ah) { + if (!wsi->ah) { cce = "ah was NULL at cc2"; lwsl_err("%s\n", cce); goto oom4; @@ -519,7 +519,7 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, wsi->pending_timeout = NO_PENDING_TIMEOUT; wsi->c_port = port; wsi->hdr_parsing_completed = 0; - _lws_header_table_reset(wsi->u.hdr.ah); + _lws_header_table_reset(wsi->ah); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address)) return NULL; @@ -760,43 +760,43 @@ lws_client_connect_via_info(struct lws_client_connect_info *i) * things pointed to have gone out of scope. */ - wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash), "client stash"); - if (!wsi->u.hdr.stash) { + wsi->stash = lws_malloc(sizeof(*wsi->stash), "client stash"); + if (!wsi->stash) { lwsl_err("%s: OOM\n", __func__); goto bail; } - wsi->u.hdr.stash->origin[0] = '\0'; - wsi->u.hdr.stash->protocol[0] = '\0'; - wsi->u.hdr.stash->method[0] = '\0'; - wsi->u.hdr.stash->iface[0] = '\0'; + wsi->stash->origin[0] = '\0'; + wsi->stash->protocol[0] = '\0'; + wsi->stash->method[0] = '\0'; + wsi->stash->iface[0] = '\0'; - strncpy(wsi->u.hdr.stash->address, i->address, - sizeof(wsi->u.hdr.stash->address) - 1); - strncpy(wsi->u.hdr.stash->path, i->path, - sizeof(wsi->u.hdr.stash->path) - 1); - strncpy(wsi->u.hdr.stash->host, i->host, - sizeof(wsi->u.hdr.stash->host) - 1); + strncpy(wsi->stash->address, i->address, + sizeof(wsi->stash->address) - 1); + strncpy(wsi->stash->path, i->path, + sizeof(wsi->stash->path) - 1); + strncpy(wsi->stash->host, i->host, + sizeof(wsi->stash->host) - 1); if (i->origin) - strncpy(wsi->u.hdr.stash->origin, i->origin, - sizeof(wsi->u.hdr.stash->origin) - 1); + strncpy(wsi->stash->origin, i->origin, + sizeof(wsi->stash->origin) - 1); if (i->protocol) - strncpy(wsi->u.hdr.stash->protocol, i->protocol, - sizeof(wsi->u.hdr.stash->protocol) - 1); + strncpy(wsi->stash->protocol, i->protocol, + sizeof(wsi->stash->protocol) - 1); if (i->method) - strncpy(wsi->u.hdr.stash->method, i->method, - sizeof(wsi->u.hdr.stash->method) - 1); + strncpy(wsi->stash->method, i->method, + sizeof(wsi->stash->method) - 1); if (i->iface) - strncpy(wsi->u.hdr.stash->iface, i->iface, - sizeof(wsi->u.hdr.stash->iface) - 1); + strncpy(wsi->stash->iface, i->iface, + sizeof(wsi->stash->iface) - 1); - wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0'; - wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0'; - wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0'; - wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0'; - wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0'; - wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0'; - wsi->u.hdr.stash->iface[sizeof(wsi->u.hdr.stash->iface) - 1] = '\0'; + wsi->stash->address[sizeof(wsi->stash->address) - 1] = '\0'; + wsi->stash->path[sizeof(wsi->stash->path) - 1] = '\0'; + wsi->stash->host[sizeof(wsi->stash->host) - 1] = '\0'; + wsi->stash->origin[sizeof(wsi->stash->origin) - 1] = '\0'; + wsi->stash->protocol[sizeof(wsi->stash->protocol) - 1] = '\0'; + wsi->stash->method[sizeof(wsi->stash->method) - 1] = '\0'; + wsi->stash->iface[sizeof(wsi->stash->iface) - 1] = '\0'; if (i->pwsi) *i->pwsi = wsi; @@ -842,7 +842,7 @@ bail1: struct lws * lws_client_connect_via_info2(struct lws *wsi) { - struct client_info_stash *stash = wsi->u.hdr.stash; + struct client_info_stash *stash = wsi->stash; if (!stash) return wsi; @@ -886,7 +886,7 @@ lws_client_connect_via_info2(struct lws *wsi) #if defined(LWS_WITH_SOCKS5) if (!wsi->vhost->socks_proxy_port) - lws_free_set_NULL(wsi->u.hdr.stash); + lws_free_set_NULL(wsi->stash); #endif /* @@ -917,7 +917,7 @@ lws_client_connect_via_info2(struct lws *wsi) bail1: #if defined(LWS_WITH_SOCKS5) if (!wsi->vhost->socks_proxy_port) - lws_free_set_NULL(wsi->u.hdr.stash); + lws_free_set_NULL(wsi->stash); #endif return NULL; @@ -1029,9 +1029,9 @@ void socks_generate_msg(struct lws *wsi, enum socks_msg_type type, n = len++; /* the address we tell SOCKS proxy to connect to */ - strncpy((char *)&(pt->serv_buf[len]), wsi->u.hdr.stash->address, + strncpy((char *)&(pt->serv_buf[len]), wsi->stash->address, context->pt_serv_buf_size - len); - len += strlen(wsi->u.hdr.stash->address); + len += strlen(wsi->stash->address); net_num = htons(wsi->c_port); /* the port we tell SOCKS proxy to connect to */ @@ -1039,7 +1039,7 @@ void socks_generate_msg(struct lws *wsi, enum socks_msg_type type, pt->serv_buf[len++] = p[1]; /* the length of the address, excluding port */ - pt->serv_buf[n] = strlen(wsi->u.hdr.stash->address); + pt->serv_buf[n] = strlen(wsi->stash->address); break; default: diff --git a/lib/client/client.c b/lib/client/client.c index 98365725..4a5c23fa 100644 --- a/lib/client/client.c +++ b/lib/client/client.c @@ -196,7 +196,7 @@ socks_reply_fail: lwsl_client("socks connect OK\n"); /* free stash since we are done with it */ - lws_free_set_NULL(wsi->u.hdr.stash); + lws_free_set_NULL(wsi->stash); if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, wsi->vhost->socks_proxy_address)) @@ -350,8 +350,8 @@ start_ws_handshake: break; } client_http_body_sent: - wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; - wsi->u.hdr.lextable_pos = 0; + wsi->ah->parser_state = WSI_TOKEN_NAME_PART; + wsi->ah->lextable_pos = 0; wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, context->timeout_secs); @@ -391,7 +391,7 @@ client_http_body_sent: * definitively ready from browser pov. */ len = 1; - while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE && + while (wsi->ah->parser_state != WSI_PARSING_COMPLETE && len > 0) { n = lws_ssl_capable_read(wsi, &c, 1); lws_latency(context, wsi, "send lws_issue_raw", n, @@ -416,7 +416,7 @@ client_http_body_sent: * libwebsocket timeout still active here too, so if parsing did * not complete just wait for next packet coming in this state */ - if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) + if (wsi->ah->parser_state != WSI_PARSING_COMPLETE) break; /* @@ -495,13 +495,13 @@ lws_http_transaction_completed_client(struct lws *wsi) * As client, nothing new is going to come until we ask for it * we can drop the ah, if any */ - if (wsi->u.hdr.ah) { + if (wsi->ah) { lws_header_table_force_to_detachable_state(wsi); lws_header_table_detach(wsi, 0); } /* If we're (re)starting on headers, need other implied init */ - wsi->u.hdr.ues = URIES_IDLE; + wsi->ues = URIES_IDLE; lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi); @@ -512,10 +512,10 @@ lws_http_transaction_completed_client(struct lws *wsi) LWS_VISIBLE LWS_EXTERN unsigned int lws_http_client_http_response(struct lws *wsi) { - if (!wsi->u.http.ah) + if (!wsi->ah) return 0; - return wsi->u.http.ah->http_response; + return wsi->ah->http_response; } int @@ -539,16 +539,16 @@ lws_client_interpret_server_handshake(struct lws *wsi) int more = 1; void *v; #endif - if (wsi->u.hdr.stash) - lws_free_set_NULL(wsi->u.hdr.stash); + if (wsi->stash) + lws_free_set_NULL(wsi->stash); - ah = wsi->u.hdr.ah; + ah = wsi->ah; if (!wsi->do_ws) { /* we are being an http client... */ lws_union_transition(wsi, LWSCM_HTTP_CLIENT_ACCEPTED); wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED; - wsi->u.http.ah = ah; + wsi->ah = ah; ah->http_response = 0; } @@ -1017,9 +1017,9 @@ check_accept: */ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT); - if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) { + if (strcmp(p, wsi->ah->initial_handshake_hash_base64)) { lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p, - wsi->u.hdr.ah->initial_handshake_hash_base64); + wsi->ah->initial_handshake_hash_base64); cce = "HS: Accept hash wrong"; goto bail2; } @@ -1300,8 +1300,8 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) lws_SHA1((unsigned char *)buf, n, (unsigned char *)hash); lws_b64_encode_string(hash, 20, - wsi->u.hdr.ah->initial_handshake_hash_base64, - sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64)); + wsi->ah->initial_handshake_hash_base64, + sizeof(wsi->ah->initial_handshake_hash_base64)); } /* give userland a chance to append, eg, cookies */ diff --git a/lib/handshake.c b/lib/handshake.c index 04a421d9..74396f55 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -114,7 +114,7 @@ lws_read(struct lws *wsi, unsigned char *buf, lws_filepos_t len) /* fallthru */ case LWSS_HTTP_HEADERS: - if (!wsi->u.hdr.ah) { + if (!wsi->ah) { lwsl_err("%s: LWSS_HTTP_HEADERS: NULL ah\n", __func__); assert(0); } diff --git a/lib/http2/hpack.c b/lib/http2/hpack.c index f9cbe29c..6ed3ee46 100644 --- a/lib/http2/hpack.c +++ b/lib/http2/hpack.c @@ -202,7 +202,7 @@ static int huftable_decode(int pos, char c) static int lws_frag_start(struct lws *wsi, int hdr_token_idx) { - struct allocated_headers *ah = wsi->u.h2.http.ah; + struct allocated_headers *ah = wsi->ah; if (!ah) { lwsl_notice("%s: no ah\n", __func__); @@ -274,7 +274,7 @@ static int lws_frag_start(struct lws *wsi, int hdr_token_idx) static int lws_frag_append(struct lws *wsi, unsigned char c) { - struct allocated_headers * ah = wsi->u.h2.http.ah; + struct allocated_headers *ah = wsi->ah; ah->data[ah->pos++] = c; ah->frags[ah->nfrag].len++; @@ -289,16 +289,16 @@ static int lws_frag_end(struct lws *wsi) return 1; /* don't account for the terminating NUL in the logical length */ - wsi->u.h2.http.ah->frags[wsi->u.h2.http.ah->nfrag].len--; + wsi->ah->frags[wsi->ah->nfrag].len--; - wsi->u.h2.http.ah->nfrag++; + wsi->ah->nfrag++; return 0; } int lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h) { - struct allocated_headers *ah = wsi->u.h2.http.ah; + struct allocated_headers *ah = wsi->ah; int n; if (!ah) @@ -768,7 +768,7 @@ int lws_hpack_interpret(struct lws *wsi, unsigned char c) { struct lws *nwsi = lws_get_network_wsi(wsi); struct lws_h2_netconn *h2n = nwsi->u.h2.h2n; - struct allocated_headers *ah = wsi->u.h2.http.ah; + struct allocated_headers *ah = wsi->ah; unsigned int prev; unsigned char c1; int n, m; @@ -795,7 +795,7 @@ int lws_hpack_interpret(struct lws *wsi, unsigned char c) h2n->ext_count = 0; h2n->hpack_hdr_len = 0; h2n->unknown_header = 0; - wsi->u.hdr.parser_state = 255; + ah->parser_state = 255; if (c & 0x80) { /* 1.... indexed header field only */ /* just a possibly-extended integer */ @@ -983,8 +983,8 @@ int lws_hpack_interpret(struct lws *wsi, unsigned char c) pre_data: h2n->hpack = HPKS_DATA; if (!h2n->value || !h2n->hdr_idx) { - wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; - wsi->u.hdr.lextable_pos = 0; + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->lextable_pos = 0; h2n->unknown_header = 0; break; } @@ -992,7 +992,7 @@ pre_data: if (h2n->hpack_type == HPKT_LITERAL_HDR_VALUE || h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR || h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER) { - n = wsi->u.hdr.parser_state; + n = ah->parser_state; if (n == 255) { n = -1; h2n->hdr_idx = -1; @@ -1111,7 +1111,7 @@ pre_data: /* * Convert name using existing parser, * If h2n->unknown_header == 0, result is - * in wsi->u.hdr.parser_state + * in wsi->parser_state * using WSI_TOKEN_GET_URI. * * If unknown header h2n->unknown_header @@ -1159,19 +1159,19 @@ swallow: h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR || h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER)) { h2n->hdr_idx = LWS_HPACK_IGNORE_ENTRY; - lwsl_header("wsi->u.hdr.parser_state: %d\n", - wsi->u.hdr.parser_state); + lwsl_header("wsi->parser_state: %d\n", + ah->parser_state); - if (wsi->u.hdr.parser_state == WSI_TOKEN_NAME_PART) { + if (ah->parser_state == WSI_TOKEN_NAME_PART) { /* h2 headers come without the colon */ n = lws_parse(wsi, ':'); (void)n; } - if (wsi->u.hdr.parser_state == WSI_TOKEN_NAME_PART || - wsi->u.hdr.parser_state == WSI_TOKEN_SKIPPING) { + if (ah->parser_state == WSI_TOKEN_NAME_PART || + ah->parser_state == WSI_TOKEN_SKIPPING) { h2n->unknown_header = 1; - wsi->u.hdr.parser_state = -1; + ah->parser_state = -1; wsi->seen_nonpseudoheader = 1; } } @@ -1209,14 +1209,14 @@ swallow: * hdr is a new literal, so length is already in * h2n->hpack_hdr_len */ - m = wsi->u.hdr.parser_state; + m = ah->parser_state; if (h2n->unknown_header || - wsi->u.hdr.parser_state == WSI_TOKEN_NAME_PART || - wsi->u.hdr.parser_state == WSI_TOKEN_SKIPPING) { + ah->parser_state == WSI_TOKEN_NAME_PART || + ah->parser_state == WSI_TOKEN_SKIPPING) { if (h2n->first_hdr_char == ':') { lwsl_info("HPKT_LITERAL_HDR_VALUE_INCR:" " end state %d unk hdr %d\n", - wsi->u.hdr.parser_state, + ah->parser_state, h2n->unknown_header); /* unknown pseudoheaders are illegal */ lws_h2_goaway(nwsi, @@ -1253,14 +1253,12 @@ add_it: if (h2n->hpack_type == HPKT_LITERAL_HDR_VALUE || h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR || h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_NEVER) { - m = wsi->u.hdr.parser_state; + m = ah->parser_state; if (m == 255) m = -1; - } else { - m = lws_token_from_index(wsi, h2n->hdr_idx, NULL, NULL, - NULL); - //lwsl_notice("token from index(%d) says %d\n", h2n->hdr_idx, m); - } + } else + m = lws_token_from_index(wsi, h2n->hdr_idx, + NULL, NULL, NULL); } if (m != -1 && m != LWS_HPACK_IGNORE_ENTRY) diff --git a/lib/http2/http2.c b/lib/http2/http2.c index bae5c961..6956aa7c 100644 --- a/lib/http2/http2.c +++ b/lib/http2/http2.c @@ -581,11 +581,11 @@ int lws_h2_do_pps_send(struct lws *wsi) goto bail; /* pass on the initial headers to SID 1 */ - h2n->swsi->u.http.ah = wsi->u.http.ah; - wsi->u.http.ah = NULL; + h2n->swsi->ah = wsi->ah; + wsi->ah = NULL; lwsl_info("%s: inherited headers %p\n", __func__, - h2n->swsi->u.http.ah); + h2n->swsi->ah); h2n->swsi->u.h2.tx_cr = h2n->set.s[H2SET_INITIAL_WINDOW_SIZE]; lwsl_info("initial tx credit on conn %p: %d\n", @@ -973,7 +973,7 @@ lws_h2_parse_frame_header(struct lws *wsi) * ah needs attaching to child wsi, even though * we only fill it from network wsi */ - if (!h2n->swsi->u.hdr.ah) + if (!h2n->swsi->ah) if (lws_header_table_attach(h2n->swsi, 0)) { lwsl_err("%s: Failed to get ah\n", __func__); return 1; @@ -1191,8 +1191,8 @@ lws_h2_parse_end_of_frame(struct lws *wsi) p = lws_hdr_simple_ptr(h2n->swsi, WSI_TOKEN_HTTP_COLON_METHOD); if (!strcmp(p, "POST")) - h2n->swsi->u.hdr.ah->frag_index[WSI_TOKEN_POST_URI] = - h2n->swsi->u.hdr.ah->frag_index[WSI_TOKEN_HTTP_COLON_PATH]; + h2n->swsi->ah->frag_index[WSI_TOKEN_POST_URI] = + h2n->swsi->ah->frag_index[WSI_TOKEN_HTTP_COLON_PATH]; wsi->vhost->conn_stats.h2_trans++; diff --git a/lib/http2/ssl-http2.c b/lib/http2/ssl-http2.c index cb131eca..37e47862 100644 --- a/lib/http2/ssl-http2.c +++ b/lib/http2/ssl-http2.c @@ -127,13 +127,13 @@ int lws_h2_configure_if_upgraded(struct lws *wsi) /* adopt the header info */ - ah = wsi->u.hdr.ah; + ah = wsi->ah; lws_union_transition(wsi, LWSCM_HTTP2_SERVING); wsi->state = LWSS_HTTP2_AWAIT_CLIENT_PREFACE; /* http2 union member has http union struct at start */ - wsi->u.http.ah = ah; + wsi->ah = ah; wsi->u.h2.h2n = lws_zalloc(sizeof(*wsi->u.h2.h2n), "h2n"); if (!wsi->u.h2.h2n) diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 3486ad0c..a5e7b857 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -433,8 +433,8 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) wsi->mode == LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY || wsi->mode == LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY || wsi->mode == LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY) - if (wsi->u.hdr.stash) - lws_free_set_NULL(wsi->u.hdr.stash); + if (wsi->stash) + lws_free_set_NULL(wsi->stash); #endif if (wsi->mode == LWSCM_RAW) { @@ -3076,7 +3076,7 @@ lws_stats_log_dump(struct lws_context *context) wl = pt->ah_wait_list; while (wl) { m++; - wl = wl->u.hdr.ah_wait_list; + wl = wl->ah_wait_list; } lwsl_notice(" AH wait list count / actual: %d / %d\n", diff --git a/lib/plat/lws-plat-esp8266.c b/lib/plat/lws-plat-esp8266.c index e4130c7c..74375798 100644 --- a/lib/plat/lws-plat-esp8266.c +++ b/lib/plat/lws-plat-esp8266.c @@ -326,7 +326,7 @@ esp8266_cb_rx(void *arg, char *data, unsigned short len) * if we're doing HTTP headers, and we have no ah, check if there is * a free ah, if not, have to buffer it */ - if (!wsi->hdr_parsing_completed && !wsi->u.hdr.ah) { + if (!wsi->hdr_parsing_completed && !wsi->ah) { for (n = 0; n < wsi->context->max_http_header_pool; n++) if (!pt->ah_pool[n].in_use) break; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index cd93b804..35dbc762 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -843,19 +843,27 @@ struct allocated_headers { #else uint8_t rx[2048]; #endif - - int16_t rxpos; - int16_t rxlen; - uint32_t pos; - uint32_t http_response; - int hdr_token_idx; - #ifndef LWS_NO_CLIENT char initial_handshake_hash_base64[30]; #endif + uint32_t pos; + uint32_t http_response; + uint32_t current_token_limit; + int hdr_token_idx; + + int16_t rxpos; + int16_t rxlen; + int16_t lextable_pos; + uint8_t in_use; uint8_t nfrag; + char /*enum uri_path_states */ ups; + char /*enum uri_esc_states */ ues; + + char esc_stash; + char post_literal_equal; + uint8_t /* enum lws_token_indexes */ parser_state; }; /* @@ -1384,18 +1392,6 @@ enum uri_esc_states { URIES_SEEN_PERCENT_H1, }; -/* notice that these union members: - * - * hdr - * http - * http2 - * - * all have a pointer to allocated_headers struct as their first member. - * - * It means for allocated_headers access, the three union paths can all be - * used interchangeably to access the same data - */ - #ifndef LWS_NO_CLIENT struct client_info_stash { @@ -1409,25 +1405,6 @@ struct client_info_stash { }; #endif -struct _lws_header_related { - /* MUST be first in struct */ - struct allocated_headers *ah; - struct lws *ah_wait_list; - unsigned char *preamble_rx; -#ifndef LWS_NO_CLIENT - struct client_info_stash *stash; -#endif - unsigned int preamble_rx_len; - enum uri_path_states ups; - enum uri_esc_states ues; - short lextable_pos; - unsigned int current_token_limit; - - char esc_stash; - char post_literal_equal; - unsigned char parser_state; /* enum lws_token_indexes */ -}; - #if defined(LWS_WITH_RANGES) enum range_states { LWSRS_NO_ACTIVE_RANGE, @@ -1456,14 +1433,6 @@ lws_ranges_reset(struct lws_range_parsing *rp); #endif struct _lws_http_mode_related { - /* MUST be first in struct */ - struct allocated_headers *ah; /* mirroring _lws_header_related */ - struct lws *ah_wait_list; - unsigned char *preamble_rx; -#ifndef LWS_NO_CLIENT - struct client_info_stash *stash; -#endif - unsigned int preamble_rx_len; struct lws *new_wsi_list; lws_filepos_t filepos; lws_filepos_t filelen; @@ -1796,8 +1765,6 @@ struct _lws_h2_related { #endif struct _lws_websocket_related { - /* cheapest way to deal with ah overlap with ws union transition */ - struct _lws_header_related hdr; char *rx_ubuf; unsigned int rx_ubuf_alloc; struct lws *rx_draining_ext_list; @@ -1912,8 +1879,8 @@ struct lws_access_log { #endif struct lws { - /* structs */ + /* members with mutually exclusive lifetimes are unionized */ union u { @@ -1921,7 +1888,6 @@ struct lws { #ifdef LWS_WITH_HTTP2 struct _lws_h2_related h2; #endif - struct _lws_header_related hdr; struct _lws_websocket_related ws; } u; @@ -1955,7 +1921,12 @@ struct lws { #if defined(LWS_WITH_PEER_LIMITS) struct lws_peer *peer; #endif - + struct allocated_headers *ah; + struct lws *ah_wait_list; + unsigned char *preamble_rx; +#ifndef LWS_NO_CLIENT + struct client_info_stash *stash; +#endif void *user_space; void *opaque_parent_data; /* rxflow handling */ @@ -1996,6 +1967,7 @@ struct lws { int position_in_fds_table; uint32_t rxflow_len; uint32_t rxflow_pos; + uint32_t preamble_rx_len; unsigned int trunc_alloc_len; /* size of malloc */ unsigned int trunc_offset; /* where we are in terms of spilling */ unsigned int trunc_len; /* how much is buffered */ diff --git a/lib/server/cgi.c b/lib/server/cgi.c index 106d98c0..6b089e7b 100644 --- a/lib/server/cgi.c +++ b/lib/server/cgi.c @@ -196,7 +196,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len if (lws_is_ssl(wsi)) env_array[n++] = "HTTPS=ON"; - if (wsi->u.hdr.ah) { + if (wsi->ah) { static const unsigned char meths[] = { WSI_TOKEN_GET_URI, WSI_TOKEN_POST_URI, diff --git a/lib/server/parsers.c b/lib/server/parsers.c index 872fda0d..859af77d 100644 --- a/lib/server/parsers.c +++ b/lib/server/parsers.c @@ -121,7 +121,7 @@ _lws_header_table_reset(struct allocated_headers *ah) void lws_header_table_reset(struct lws *wsi, int autoservice) { - struct allocated_headers *ah = wsi->u.hdr.ah; + struct allocated_headers *ah = wsi->ah; struct lws_context_per_thread *pt; struct lws_pollfd *pfd; @@ -132,8 +132,8 @@ lws_header_table_reset(struct lws *wsi, int autoservice) _lws_header_table_reset(ah); - wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; - wsi->u.hdr.lextable_pos = 0; + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->lextable_pos = 0; /* since we will restart the ah, our new headers are not completed */ wsi->hdr_parsing_completed = 0; @@ -148,11 +148,10 @@ lws_header_table_reset(struct lws *wsi, int autoservice) * if we inherited pending rx (from socket adoption deferred * processing), apply and free it. */ - if (wsi->u.hdr.preamble_rx) { - memcpy(ah->rx, wsi->u.hdr.preamble_rx, - wsi->u.hdr.preamble_rx_len); - ah->rxlen = wsi->u.hdr.preamble_rx_len; - lws_free_set_NULL(wsi->u.hdr.preamble_rx); + if (wsi->preamble_rx) { + memcpy(ah->rx, wsi->preamble_rx, wsi->preamble_rx_len); + ah->rxlen = wsi->preamble_rx_len; + lws_free_set_NULL(wsi->preamble_rx); if (autoservice) { lwsl_debug("%s: service on readbuf ah\n", __func__); @@ -180,11 +179,11 @@ _lws_header_ensure_we_are_on_waiting_list(struct lws *wsi) while (*pwsi) { if (*pwsi == wsi) return; - pwsi = &(*pwsi)->u.hdr.ah_wait_list; + pwsi = &(*pwsi)->ah_wait_list; } lwsl_info("%s: wsi: %p\n", __func__, wsi); - wsi->u.hdr.ah_wait_list = pt->ah_wait_list; + wsi->ah_wait_list = pt->ah_wait_list; pt->ah_wait_list = wsi; pt->ah_wait_list_length++; @@ -203,14 +202,14 @@ __lws_remove_from_ah_waiting_list(struct lws *wsi) if (*pwsi == wsi) { lwsl_info("%s: wsi %p\n", __func__, wsi); /* point prev guy to our next */ - *pwsi = wsi->u.hdr.ah_wait_list; + *pwsi = wsi->ah_wait_list; /* we shouldn't point anywhere now */ - wsi->u.hdr.ah_wait_list = NULL; + wsi->ah_wait_list = NULL; pt->ah_wait_list_length--; return 1; } - pwsi = &(*pwsi)->u.hdr.ah_wait_list; + pwsi = &(*pwsi)->ah_wait_list; } return 0; @@ -225,11 +224,11 @@ lws_header_table_attach(struct lws *wsi, int autoservice) int n; lwsl_info("%s: wsi %p: ah %p (tsi %d, count = %d) in\n", __func__, - (void *)wsi, (void *)wsi->u.hdr.ah, wsi->tsi, + (void *)wsi, (void *)wsi->ah, wsi->tsi, pt->ah_count_in_use); /* if we are already bound to one, just clear it down */ - if (wsi->u.hdr.ah) { + if (wsi->ah) { lwsl_info("%s: cleardown\n", __func__); goto reset; } @@ -260,15 +259,15 @@ lws_header_table_attach(struct lws *wsi, int autoservice) __lws_remove_from_ah_waiting_list(wsi); - wsi->u.hdr.ah = _lws_create_ah(pt, context->max_http_header_data); - if (!wsi->u.hdr.ah) { /* we could not create an ah */ + wsi->ah = _lws_create_ah(pt, context->max_http_header_data); + if (!wsi->ah) { /* we could not create an ah */ _lws_header_ensure_we_are_on_waiting_list(wsi); goto bail; } - wsi->u.hdr.ah->in_use = 1; - wsi->u.hdr.ah->wsi = wsi; /* mark our owner */ + wsi->ah->in_use = 1; + wsi->ah->wsi = wsi; /* mark our owner */ pt->ah_count_in_use++; #if defined(LWS_WITH_PEER_LIMITS) @@ -279,15 +278,15 @@ lws_header_table_attach(struct lws *wsi, int autoservice) _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa); lwsl_info("%s: did attach wsi %p: ah %p: count %d (on exit)\n", __func__, - (void *)wsi, (void *)wsi->u.hdr.ah, pt->ah_count_in_use); + (void *)wsi, (void *)wsi->ah, pt->ah_count_in_use); lws_pt_unlock(pt); reset: /* and reset the rx state */ - wsi->u.hdr.ah->rxpos = 0; - wsi->u.hdr.ah->rxlen = 0; + wsi->ah->rxpos = 0; + wsi->ah->rxlen = 0; lws_header_table_reset(wsi, autoservice); @@ -311,9 +310,9 @@ bail: 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; + if (wsi->ah) { + wsi->ah->rxpos = -1; + wsi->ah->rxlen = -1; wsi->hdr_parsing_completed = 1; } } @@ -321,7 +320,7 @@ lws_header_table_force_to_detachable_state(struct lws *wsi) int lws_header_table_is_in_detachable_state(struct lws *wsi) { - struct allocated_headers *ah = wsi->u.hdr.ah; + struct allocated_headers *ah = wsi->ah; return ah && ah->rxpos == ah->rxlen && wsi->hdr_parsing_completed; } @@ -329,7 +328,7 @@ lws_header_table_is_in_detachable_state(struct lws *wsi) int lws_header_table_detach(struct lws *wsi, int autoservice) { struct lws_context *context = wsi->context; - struct allocated_headers *ah = wsi->u.hdr.ah; + struct allocated_headers *ah = wsi->ah; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; struct lws_pollargs pa; struct lws **pwsi, **pwsi_eligible; @@ -346,8 +345,8 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) (void *)wsi, (void *)ah, wsi->tsi, pt->ah_count_in_use); - if (wsi->u.hdr.preamble_rx) - lws_free_set_NULL(wsi->u.hdr.preamble_rx); + if (wsi->preamble_rx) + lws_free_set_NULL(wsi->preamble_rx); /* may not be detached while he still has unprocessed rx */ if (!lws_header_table_is_in_detachable_state(wsi)) { @@ -380,7 +379,7 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) assert(pt->ah_count_in_use > 0); /* and this specific one should have been in use */ assert(ah->in_use); - wsi->u.hdr.ah = NULL; + memset(&wsi->ah, 0, sizeof(wsi->ah)); ah->wsi = NULL; /* no owner */ #if defined(LWS_WITH_PEER_LIMITS) lws_peer_track_ah_detach(context, wsi->peer); @@ -411,11 +410,11 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) } #if defined(LWS_WITH_PEER_LIMITS) else - if (!(*pwsi)->u.hdr.ah_wait_list) + if (!(*pwsi)->ah_wait_list) lws_stats_atomic_bump(context, pt, LWSSTATS_C_PEER_LIMIT_AH_DENIED, 1); #endif - pwsi = &(*pwsi)->u.hdr.ah_wait_list; + pwsi = &(*pwsi)->ah_wait_list; } if (!wsi) /* everybody waiting already has too many ah... */ @@ -423,7 +422,7 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) lwsl_info("%s: last eligible wsi in wait list %p\n", __func__, wsi); - wsi->u.hdr.ah = ah; + wsi->ah = ah; ah->wsi = wsi; /* new owner */ /* and reset the rx state */ @@ -446,9 +445,9 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) } /* point prev guy to next guy in list instead */ - *pwsi_eligible = wsi->u.hdr.ah_wait_list; + *pwsi_eligible = wsi->ah_wait_list; /* the guy who got one is out of the list */ - wsi->u.hdr.ah_wait_list = NULL; + wsi->ah_wait_list = NULL; pt->ah_wait_list_length--; #ifndef LWS_NO_CLIENT @@ -488,16 +487,16 @@ lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx) { int n; - if (!wsi->u.hdr.ah) + if (!wsi->ah) return 0; - n = wsi->u.hdr.ah->frag_index[h]; + n = wsi->ah->frag_index[h]; if (!n) return 0; do { if (!frag_idx) - return wsi->u.hdr.ah->frags[n].len; - n = wsi->u.hdr.ah->frags[n].nfrag; + return wsi->ah->frags[n].len; + n = wsi->ah->frags[n].nfrag; } while (frag_idx-- && n); return 0; @@ -508,15 +507,15 @@ LWS_VISIBLE int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h) int n; int len = 0; - if (!wsi->u.hdr.ah) + if (!wsi->ah) return 0; - n = wsi->u.hdr.ah->frag_index[h]; + n = wsi->ah->frag_index[h]; if (!n) return 0; do { - len += wsi->u.hdr.ah->frags[n].len; - n = wsi->u.hdr.ah->frags[n].nfrag; + len += wsi->ah->frags[n].len; + n = wsi->ah->frags[n].nfrag; } while (n); return len; @@ -528,29 +527,29 @@ LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len, int n = 0; int f; - if (!wsi->u.hdr.ah) + if (!wsi->ah) return -1; - f = wsi->u.hdr.ah->frag_index[h]; + f = wsi->ah->frag_index[h]; if (!f) return -1; while (n < frag_idx) { - f = wsi->u.hdr.ah->frags[f].nfrag; + f = wsi->ah->frags[f].nfrag; if (!f) return -1; n++; } - if (wsi->u.hdr.ah->frags[f].len >= len) + if (wsi->ah->frags[f].len >= len) return -1; - memcpy(dst, wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[f].offset, - wsi->u.hdr.ah->frags[f].len); - dst[wsi->u.hdr.ah->frags[f].len] = '\0'; + memcpy(dst, wsi->ah->data + wsi->ah->frags[f].offset, + wsi->ah->frags[f].len); + dst[wsi->ah->frags[f].len] = '\0'; - return wsi->u.hdr.ah->frags[f].len; + return wsi->ah->frags[f].len; } LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len, @@ -562,21 +561,21 @@ LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len, if (toklen >= len) return -1; - if (!wsi->u.hdr.ah) + if (!wsi->ah) return -1; - n = wsi->u.hdr.ah->frag_index[h]; + n = wsi->ah->frag_index[h]; if (!n) return 0; do { - if (wsi->u.hdr.ah->frags[n].len >= len) + if (wsi->ah->frags[n].len >= len) return -1; - strncpy(dst, &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset], - wsi->u.hdr.ah->frags[n].len); - dst += wsi->u.hdr.ah->frags[n].len; - len -= wsi->u.hdr.ah->frags[n].len; - n = wsi->u.hdr.ah->frags[n].nfrag; + strncpy(dst, &wsi->ah->data[wsi->ah->frags[n].offset], + wsi->ah->frags[n].len); + dst += wsi->ah->frags[n].len; + len -= wsi->ah->frags[n].len; + n = wsi->ah->frags[n].nfrag; } while (n); *dst = '\0'; @@ -587,21 +586,21 @@ char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h) { int n; - n = wsi->u.hdr.ah->frag_index[h]; + n = wsi->ah->frag_index[h]; if (!n) return NULL; - return wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[n].offset; + return wsi->ah->data + wsi->ah->frags[n].offset; } int LWS_WARN_UNUSED_RESULT lws_pos_in_bounds(struct lws *wsi) { - if (wsi->u.hdr.ah->pos < + if (wsi->ah->pos < (unsigned int)wsi->context->max_http_header_data) return 0; - if ((int)wsi->u.hdr.ah->pos == wsi->context->max_http_header_data) { + if ((int)wsi->ah->pos == wsi->context->max_http_header_data) { lwsl_err("Ran out of header data space\n"); return 1; } @@ -610,7 +609,7 @@ lws_pos_in_bounds(struct lws *wsi) * with these tests everywhere, it should never be able to exceed * the limit, only meet it */ - lwsl_err("%s: pos %d, limit %d\n", __func__, wsi->u.hdr.ah->pos, + lwsl_err("%s: pos %d, limit %d\n", __func__, wsi->ah->pos, wsi->context->max_http_header_data); assert(0); @@ -620,25 +619,25 @@ lws_pos_in_bounds(struct lws *wsi) int LWS_WARN_UNUSED_RESULT lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s) { - wsi->u.hdr.ah->nfrag++; - if (wsi->u.hdr.ah->nfrag == ARRAY_SIZE(wsi->u.hdr.ah->frags)) { + wsi->ah->nfrag++; + if (wsi->ah->nfrag == ARRAY_SIZE(wsi->ah->frags)) { lwsl_warn("More hdr frags than we can deal with, dropping\n"); return -1; } - wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->nfrag; + wsi->ah->frag_index[h] = wsi->ah->nfrag; - wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].offset = wsi->u.hdr.ah->pos; - wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len = 0; - wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].nfrag = 0; + wsi->ah->frags[wsi->ah->nfrag].offset = wsi->ah->pos; + wsi->ah->frags[wsi->ah->nfrag].len = 0; + wsi->ah->frags[wsi->ah->nfrag].nfrag = 0; do { if (lws_pos_in_bounds(wsi)) return -1; - wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s; + wsi->ah->data[wsi->ah->pos++] = *s; if (*s) - wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len++; + wsi->ah->frags[wsi->ah->nfrag].len++; } while (*s++); return 0; @@ -666,27 +665,27 @@ issue_char(struct lws *wsi, unsigned char c) if (lws_pos_in_bounds(wsi)) return -1; - frag_len = wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len; + frag_len = wsi->ah->frags[wsi->ah->nfrag].len; /* * If we haven't hit the token limit, just copy the character into * the header */ - if (frag_len < wsi->u.hdr.current_token_limit) { - wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c; + if (frag_len < wsi->ah->current_token_limit) { + wsi->ah->data[wsi->ah->pos++] = c; if (c) - wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].len++; + wsi->ah->frags[wsi->ah->nfrag].len++; return 0; } /* Insert a null character when we *hit* the limit: */ - if (frag_len == wsi->u.hdr.current_token_limit) { + if (frag_len == wsi->ah->current_token_limit) { if (lws_pos_in_bounds(wsi)) return -1; - wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0'; + wsi->ah->data[wsi->ah->pos++] = '\0'; lwsl_warn("header %i exceeds limit %d\n", - wsi->u.hdr.parser_state, - wsi->u.hdr.current_token_limit); + wsi->ah->parser_state, + wsi->ah->current_token_limit); } return 1; @@ -695,18 +694,20 @@ issue_char(struct lws *wsi, unsigned char c) int lws_parse_urldecode(struct lws *wsi, uint8_t *_c) { - struct allocated_headers *ah = wsi->u.hdr.ah; + struct allocated_headers *ah = wsi->ah; unsigned int enc = 0; uint8_t c = *_c; + // lwsl_notice("ah->ups %d\n", ah->ups); + /* * PRIORITY 1 * special URI processing... convert %xx */ - switch (wsi->u.hdr.ues) { + switch (ah->ues) { case URIES_IDLE: if (c == '%') { - wsi->u.hdr.ues = URIES_SEEN_PERCENT; + ah->ues = URIES_SEEN_PERCENT; goto swallow; } break; @@ -715,8 +716,8 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) /* illegal post-% char */ goto forbid; - wsi->u.hdr.esc_stash = c; - wsi->u.hdr.ues = URIES_SEEN_PERCENT_H1; + ah->esc_stash = c; + ah->ues = URIES_SEEN_PERCENT_H1; goto swallow; case URIES_SEEN_PERCENT_H1: @@ -724,11 +725,11 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) /* illegal post-% char */ goto forbid; - *_c = (char_to_hex(wsi->u.hdr.esc_stash) << 4) | + *_c = (char_to_hex(ah->esc_stash) << 4) | char_to_hex(c); c = *_c; enc = 1; - wsi->u.hdr.ues = URIES_IDLE; + ah->ues = URIES_IDLE; break; } @@ -741,7 +742,7 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) * leave /.dir or whatever alone */ - switch (wsi->u.hdr.ups) { + switch (ah->ups) { case URIPS_IDLE: if (!c) return -1; @@ -757,7 +758,7 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) if (ah->nfrag >= ARRAY_SIZE(ah->frags)) goto excessive; /* start next fragment after the & */ - wsi->u.hdr.post_literal_equal = 0; + ah->post_literal_equal = 0; ah->frags[ah->nfrag].offset = ah->pos; ah->frags[ah->nfrag].len = 0; ah->frags[ah->nfrag].nfrag = 0; @@ -766,14 +767,14 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) /* uriencoded = in the name part, disallow */ if (c == '=' && enc && ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] && - !wsi->u.hdr.post_literal_equal) { + !ah->post_literal_equal) { c = '_'; *_c =c; } /* after the real =, we don't care how many = */ if (c == '=' && !enc) - wsi->u.hdr.post_literal_equal = 1; + ah->post_literal_equal = 1; /* + to space */ if (c == '+' && !enc) { @@ -782,7 +783,7 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) } /* issue the first / always */ if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) - wsi->u.hdr.ups = URIPS_SEEN_SLASH; + ah->ups = URIPS_SEEN_SLASH; break; case URIPS_SEEN_SLASH: /* swallow subsequent slashes */ @@ -790,24 +791,24 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) goto swallow; /* track and swallow the first . after / */ if (c == '.') { - wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT; + ah->ups = URIPS_SEEN_SLASH_DOT; goto swallow; } - wsi->u.hdr.ups = URIPS_IDLE; + ah->ups = URIPS_IDLE; break; case URIPS_SEEN_SLASH_DOT: /* swallow second . */ if (c == '.') { - wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT; + ah->ups = URIPS_SEEN_SLASH_DOT_DOT; goto swallow; } /* change /./ to / */ if (c == '/') { - wsi->u.hdr.ups = URIPS_SEEN_SLASH; + ah->ups = URIPS_SEEN_SLASH; goto swallow; } /* it was like /.dir ... regurgitate the . */ - wsi->u.hdr.ups = URIPS_IDLE; + ah->ups = URIPS_IDLE; if (issue_char(wsi, '.') < 0) return -1; break; @@ -830,7 +831,7 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) } while (ah->frags[ah->nfrag].len > 1 && ah->data[ah->pos] != '/'); } - wsi->u.hdr.ups = URIPS_SEEN_SLASH; + ah->ups = URIPS_SEEN_SLASH; if (ah->frags[ah->nfrag].len > 1) break; goto swallow; @@ -842,13 +843,13 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) return -1; if (issue_char(wsi, '.') < 0) return -1; - wsi->u.hdr.ups = URIPS_IDLE; + ah->ups = URIPS_IDLE; break; } if (c == '?' && !enc && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI arguments */ - if (wsi->u.hdr.ues != URIES_IDLE) + if (ah->ues != URIES_IDLE) goto forbid; /* seal off uri header */ @@ -863,9 +864,9 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c) ah->frags[ah->nfrag].len = 0; ah->frags[ah->nfrag].nfrag = 0; - wsi->u.hdr.post_literal_equal = 0; + ah->post_literal_equal = 0; ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag; - wsi->u.hdr.ups = URIPS_IDLE; + ah->ups = URIPS_IDLE; goto swallow; } @@ -895,26 +896,26 @@ static const unsigned char methods[] = { int LWS_WARN_UNUSED_RESULT lws_parse(struct lws *wsi, unsigned char c) { - struct allocated_headers *ah = wsi->u.hdr.ah; + struct allocated_headers *ah = wsi->ah; struct lws_context *context = wsi->context; unsigned int n, m; int r; - assert(wsi->u.hdr.ah); + assert(wsi->ah); - switch (wsi->u.hdr.parser_state) { + switch (ah->parser_state) { default: - lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c); + lwsl_parser("WSI_TOK_(%d) '%c'\n", ah->parser_state, c); /* collect into malloc'd buffers */ /* optional initial space swallow */ - if (!ah->frags[ah->frag_index[wsi->u.hdr.parser_state]].len && + if (!ah->frags[ah->frag_index[ah->parser_state]].len && c == ' ') break; for (m = 0; m < ARRAY_SIZE(methods); m++) - if (wsi->u.hdr.parser_state == methods[m]) + if (ah->parser_state == methods[m]) break; if (m == ARRAY_SIZE(methods)) /* it was not any of the methods */ @@ -928,7 +929,7 @@ lws_parse(struct lws *wsi, unsigned char c) if (issue_char(wsi, '/') < 0) return -1; - if (wsi->u.hdr.ups == URIPS_SEEN_SLASH_DOT_DOT) { + if (ah->ups == URIPS_SEEN_SLASH_DOT_DOT) { /* * back up one dir level if possible * safe against header fragmentation because @@ -948,7 +949,7 @@ lws_parse(struct lws *wsi, unsigned char c) /* begin parsing HTTP version: */ if (issue_char(wsi, '\0') < 0) return -1; - wsi->u.hdr.parser_state = WSI_TOKEN_HTTP; + ah->parser_state = WSI_TOKEN_HTTP; goto start_fragment; } @@ -967,13 +968,13 @@ lws_parse(struct lws *wsi, unsigned char c) } check_eol: /* bail at EOL */ - if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE && + if (ah->parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') { - if (wsi->u.hdr.ues != URIES_IDLE) + if (ah->ues != URIES_IDLE) goto forbid; c = '\0'; - wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR; + ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; lwsl_parser("*\n"); } @@ -981,25 +982,26 @@ check_eol: if ((int)n < 0) return -1; if (n > 0) - wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; + ah->parser_state = WSI_TOKEN_SKIPPING; swallow: /* per-protocol end of headers management */ - if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE) + if (ah->parser_state == WSI_TOKEN_CHALLENGE) goto set_parsing_complete; break; /* collecting and checking a name part */ case WSI_TOKEN_NAME_PART: - lwsl_parser("WSI_TOKEN_NAME_PART '%c' 0x%02X (mode=%d) wsi->u.hdr.lextable_pos=%d\n", c, c, wsi->mode, wsi->u.hdr.lextable_pos); + lwsl_parser("WSI_TOKEN_NAME_PART '%c' 0x%02X (mode=%d) " + "wsi->lextable_pos=%d\n", c, c, wsi->mode, + ah->lextable_pos); - wsi->u.hdr.lextable_pos = - lextable_decode(wsi->u.hdr.lextable_pos, c); + ah->lextable_pos = lextable_decode(ah->lextable_pos, c); /* * Server needs to look out for unknown methods... */ - if (wsi->u.hdr.lextable_pos < 0 && + if (ah->lextable_pos < 0 && (wsi->mode == LWSCM_HTTP_SERVING)) { /* this is not a header we know about */ for (m = 0; m < ARRAY_SIZE(methods); m++) @@ -1008,7 +1010,7 @@ swallow: * already had the method, no idea what * this crap from the client is, ignore */ - wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; + ah->parser_state = WSI_TOKEN_SKIPPING; break; } /* @@ -1032,16 +1034,16 @@ swallow: * ...otherwise for a client, let him ignore unknown headers * coming from the server */ - if (wsi->u.hdr.lextable_pos < 0) { - wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; + if (ah->lextable_pos < 0) { + ah->parser_state = WSI_TOKEN_SKIPPING; break; } - if (lextable[wsi->u.hdr.lextable_pos] < FAIL_CHAR) { + if (lextable[ah->lextable_pos] < FAIL_CHAR) { /* terminal state */ - n = ((unsigned int)lextable[wsi->u.hdr.lextable_pos] << 8) | - lextable[wsi->u.hdr.lextable_pos + 1]; + n = ((unsigned int)lextable[ah->lextable_pos] << 8) | + lextable[ah->lextable_pos + 1]; lwsl_parser("known hdr %d\n", n); for (m = 0; m < ARRAY_SIZE(methods); m++) @@ -1058,18 +1060,19 @@ swallow: if (n == WSI_TOKEN_SWORIGIN) n = WSI_TOKEN_ORIGIN; - wsi->u.hdr.parser_state = (enum lws_token_indexes) + ah->parser_state = (enum lws_token_indexes) (WSI_TOKEN_GET_URI + n); + ah->ups = URIPS_IDLE; if (context->token_limits) - wsi->u.hdr.current_token_limit = + ah->current_token_limit = context->token_limits->token_limit[ - wsi->u.hdr.parser_state]; + ah->parser_state]; else - wsi->u.hdr.current_token_limit = + ah->current_token_limit = wsi->context->max_http_header_data; - if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE) + if (ah->parser_state == WSI_TOKEN_CHALLENGE) goto set_parsing_complete; goto start_fragment; @@ -1089,10 +1092,10 @@ excessive: ah->frags[ah->nfrag].nfrag = 0; ah->frags[ah->nfrag].flags = 2; - n = ah->frag_index[wsi->u.hdr.parser_state]; + n = ah->frag_index[ah->parser_state]; if (!n) { /* first fragment */ - ah->frag_index[wsi->u.hdr.parser_state] = ah->nfrag; - ah->hdr_token_idx = wsi->u.hdr.parser_state; + ah->frag_index[ah->parser_state] = ah->nfrag; + ah->hdr_token_idx = ah->parser_state; break; } /* continuation */ @@ -1109,18 +1112,18 @@ excessive: lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c); if (c == '\x0d') - wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR; + ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; break; case WSI_TOKEN_SKIPPING_SAW_CR: lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c); - if (wsi->u.hdr.ues != URIES_IDLE) + if (ah->ues != URIES_IDLE) goto forbid; if (c == '\x0a') { - wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; - wsi->u.hdr.lextable_pos = 0; + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->lextable_pos = 0; } else - wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; + ah->parser_state = WSI_TOKEN_SKIPPING; break; /* we're done, ignore anything else */ @@ -1132,7 +1135,7 @@ excessive: return 0; set_parsing_complete: - if (wsi->u.hdr.ues != URIES_IDLE) + if (ah->ues != URIES_IDLE) goto forbid; if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) { if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION)) @@ -1141,7 +1144,7 @@ set_parsing_complete: lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision); } - wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE; + ah->parser_state = WSI_PARSING_COMPLETE; wsi->hdr_parsing_completed = 1; return 0; diff --git a/lib/server/server.c b/lib/server/server.c index 2aa53d7c..1f46d206 100644 --- a/lib/server/server.c +++ b/lib/server/server.c @@ -488,7 +488,7 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin, if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_RANGE)) if (strcmp(sym, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_IF_RANGE))) /* differs - defeat Range: */ - wsi->u.http.ah->frag_index[WSI_TOKEN_HTTP_RANGE] = 0; + wsi->ah->frag_index[WSI_TOKEN_HTTP_RANGE] = 0; if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_NONE_MATCH)) { /* @@ -1334,11 +1334,9 @@ lws_server_init_wsi_for_ws(struct lws *wsi) int lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) { - int protocol_len, n = 0, hit, non_space_char_found = 0, m; struct lws_context *context = lws_get_context(wsi); struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; - struct _lws_header_related hdr; - struct allocated_headers *ah; + int protocol_len, n = 0, hit, non_space_char_found = 0, m; unsigned char *obuf = *buf; char protocol_list[128]; char protocol_name[64]; @@ -1350,7 +1348,7 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) assert(0); } - if (!wsi->u.hdr.ah) { + if (!wsi->ah) { lwsl_err("%s: assert: NULL ah\n", __func__); assert(0); } @@ -1401,7 +1399,7 @@ raw_transition: goto bail_nuke_ah; } - if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) + if (wsi->ah->parser_state != WSI_PARSING_COMPLETE) continue; lwsl_parser("%s: lws_parse sees parsing complete\n", __func__); @@ -1511,16 +1509,13 @@ raw_transition: /* no upgrade ack... he remained as HTTP */ lwsl_info("No upgrade\n"); - ah = wsi->u.hdr.ah; lws_union_transition(wsi, LWSCM_HTTP_SERVING_ACCEPTED); wsi->state = LWSS_HTTP; wsi->u.http.fop_fd = NULL; - /* expose it at the same offset as u.hdr */ - wsi->u.http.ah = ah; lwsl_debug("%s: wsi %p: ah %p\n", __func__, (void *)wsi, - (void *)wsi->u.hdr.ah); + (void *)wsi->ah); n = lws_http_action(wsi); @@ -1546,13 +1541,8 @@ upgrade_h2c: /* adopt the header info */ - ah = wsi->u.hdr.ah; - lws_union_transition(wsi, LWSCM_HTTP2_SERVING); - /* http2 union member has http union struct at start */ - wsi->u.http.ah = ah; - if (!wsi->u.h2.h2n) { wsi->u.h2.h2n = lws_zalloc(sizeof(*wsi->u.h2.h2n), "h2n"); @@ -1712,10 +1702,9 @@ upgrade_ws: */ lwsl_info("%s: %p: inheriting ws ah (rxpos:%d, rxlen:%d)\n", - __func__, wsi, wsi->u.hdr.ah->rxpos, - wsi->u.hdr.ah->rxlen); + __func__, wsi, wsi->ah->rxpos, + wsi->ah->rxlen); lws_pt_lock(pt); - hdr = wsi->u.hdr; lws_union_transition(wsi, LWSCM_WS_SERVING); /* @@ -1726,12 +1715,8 @@ upgrade_ws: * * Because rxpos/rxlen shows something in the ah, we will get * service guaranteed next time around the event loop - * - * All union members begin with hdr, so we can use it even - * though we transitioned to ws union mode (the ah detach - * code uses it anyway). */ - wsi->u.hdr = hdr; + lws_pt_unlock(pt); lws_server_init_wsi_for_ws(wsi); @@ -1893,7 +1878,7 @@ lws_http_transaction_completed(struct lws *wsi) * that is already at least the start of another header set, simply * reset the existing header table and keep it. */ - if (wsi->u.hdr.ah) { + if (wsi->ah) { lwsl_debug("%s: wsi->more_rx_waiting=%d\n", __func__, wsi->more_rx_waiting); @@ -1930,7 +1915,7 @@ lws_http_transaction_completed(struct lws *wsi) } /* If we're (re)starting on headers, need other implied init */ - wsi->u.hdr.ues = URIES_IDLE; + wsi->ah->ues = URIES_IDLE; lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi); @@ -2173,8 +2158,8 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len) * readbuf data to wsi or ah yet, and we will do it next if we get * the ah. */ - if (wsi->u.hdr.ah || !lws_header_table_attach(wsi, 0)) { - ah = wsi->u.hdr.ah; + if (wsi->ah || !lws_header_table_attach(wsi, 0)) { + ah = wsi->ah; memcpy(ah->rx, readbuf, len); ah->rxpos = 0; ah->rxlen = (int16_t)len; @@ -2204,13 +2189,13 @@ adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len) * later successful lws_header_table_attach() will apply the * below to the rx buffer (via lws_header_table_reset()). */ - wsi->u.hdr.preamble_rx = lws_malloc(len, "preamble_rx"); - if (!wsi->u.hdr.preamble_rx) { + wsi->preamble_rx = lws_malloc(len, "preamble_rx"); + if (!wsi->preamble_rx) { lwsl_err("OOM\n"); goto bail; } - memcpy(wsi->u.hdr.preamble_rx, readbuf, len); - wsi->u.hdr.preamble_rx_len = (int)len; + memcpy(wsi->preamble_rx, readbuf, len); + wsi->preamble_rx_len = (int)len; return wsi; @@ -2304,14 +2289,14 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi, if (wsi->mode != LWSCM_RAW && (wsi->state == LWSS_HTTP || wsi->state == LWSS_HTTP_ISSUING_FILE || wsi->state == LWSS_HTTP_HEADERS)) { - if (!wsi->u.hdr.ah) { + if (!wsi->ah) { /* no autoservice beacuse we will do it next */ if (lws_header_table_attach(wsi, 0)) { lwsl_info("wsi %p: ah get fail\n", wsi); goto try_pollout; } } - ah = wsi->u.hdr.ah; + ah = wsi->ah; /* if nothing in ah rx buffer, get some fresh rx */ if (ah->rxpos == ah->rxlen) { @@ -2363,14 +2348,14 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi, if (n < 0) /* we closed wsi */ return 1; - if (!wsi->u.hdr.ah) + if (!wsi->ah) break; - if ( wsi->u.hdr.ah->rxlen) - wsi->u.hdr.ah->rxpos += n; + if ( wsi->ah->rxlen) + wsi->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); + __func__, wsi, wsi->ah->rxpos, + wsi->ah->rxlen); if (lws_header_table_is_in_detachable_state(wsi) && (wsi->mode != LWSCM_HTTP_SERVING && diff --git a/lib/service.c b/lib/service.c index aed1ac78..ec449d09 100644 --- a/lib/service.c +++ b/lib/service.c @@ -601,7 +601,7 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec) "(did hdr %d, ah %p, wl %d, pfd " "events %d) %llu vs %llu\n", (void *)wsi, wsi->pending_timeout, - wsi->hdr_parsing_completed, wsi->u.hdr.ah, + wsi->hdr_parsing_completed, wsi->ah, pt->ah_wait_list_length, n, (unsigned long long)sec, (unsigned long long)wsi->pending_timeout_limit); @@ -1470,12 +1470,12 @@ read: /* all the union members start with hdr, so even in ws mode * we can deal with the ah via u.hdr */ - if (wsi->u.hdr.ah) { + if (wsi->ah) { lwsl_info("%s: %p: inherited ah rx\n", __func__, wsi); - eff_buf.token_len = wsi->u.hdr.ah->rxlen - - wsi->u.hdr.ah->rxpos; - eff_buf.token = (char *)wsi->u.hdr.ah->rx + - wsi->u.hdr.ah->rxpos; + eff_buf.token_len = wsi->ah->rxlen - + wsi->ah->rxpos; + eff_buf.token = (char *)wsi->ah->rx + + wsi->ah->rxpos; } else { if (wsi->mode != LWSCM_HTTP_CLIENT_ACCEPTED) { /* @@ -1618,7 +1618,7 @@ drain: eff_buf.token_len = 0; } while (more); - if (wsi->u.hdr.ah) { + if (wsi->ah) { lwsl_debug("%s: %p: detaching\n", __func__, wsi); lws_header_table_force_to_detachable_state(wsi); /* we can run the normal ah detach flow despite