1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

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.
This commit is contained in:
Andy Green 2017-11-16 11:26:00 +08:00
parent 93846135f2
commit df46d8827c
13 changed files with 287 additions and 329 deletions

View file

@ -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:

View file

@ -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 */

View file

@ -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);
}

View file

@ -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)

View file

@ -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++;

View file

@ -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)

View file

@ -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",

View file

@ -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;

View file

@ -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 */

View file

@ -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,

View file

@ -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;

View file

@ -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 &&

View file

@ -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