From df46d8827cc3c1ffd60ea5524b1074c014cd304b Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Thu, 16 Nov 2017 11:26:00 +0800
Subject: [PATCH] refactor-struct-lws-hdr

Migrate what used to be in lws_hdr_related into either the ah
or the wsi, and eliminate it along with the three different ways
used to access things inside it.

Eg wsi->u.hdr.ah and wsi->u.http.ah become wsi->ah

These changes are internal-only, in private-libwebsockets.h and lib.
---
 lib/client/client-handshake.c |  72 ++++-----
 lib/client/client.c           |  34 ++--
 lib/handshake.c               |   2 +-
 lib/http2/hpack.c             |  52 +++----
 lib/http2/http2.c             |  12 +-
 lib/http2/ssl-http2.c         |   4 +-
 lib/libwebsockets.c           |   6 +-
 lib/plat/lws-plat-esp8266.c   |   2 +-
 lib/private-libwebsockets.h   |  70 +++------
 lib/server/cgi.c              |   2 +-
 lib/server/parsers.c          | 283 +++++++++++++++++-----------------
 lib/server/server.c           |  61 +++-----
 lib/service.c                 |  14 +-
 13 files changed, 286 insertions(+), 328 deletions(-)

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';
-
-	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);
+	wsi->stash->origin[0] = '\0';
+	wsi->stash->protocol[0] = '\0';
+	wsi->stash->method[0] = '\0';
+	wsi->stash->iface[0] = '\0';
+
+	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
+#ifndef LWS_NO_CLIENT
+	char initial_handshake_hash_base64[30];
+#endif
 
-	int16_t rxpos;
-	int16_t rxlen;
 	uint32_t pos;
 	uint32_t http_response;
+	uint32_t current_token_limit;
 	int hdr_token_idx;
 
-#ifndef LWS_NO_CLIENT
-	char initial_handshake_hash_base64[30];
-#endif
+	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
-- 
GitLab