mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
http header malloc pool implement pool
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
b3d21f164d
commit
3df580066b
12 changed files with 243 additions and 75 deletions
35
changelog
35
changelog
|
@ -1,6 +1,41 @@
|
|||
Changelog
|
||||
---------
|
||||
|
||||
User api additions
|
||||
------------------
|
||||
|
||||
The info struct gained two new members
|
||||
|
||||
- max_http_header_data: 0 for default (1024) or set the maximum amount of known
|
||||
http header payload that lws can deal with. Payload in unknown http
|
||||
headers is dropped silently. If for some reason you need to send huge
|
||||
cookies or other HTTP-level headers, you can now increase this at context-
|
||||
creation time.
|
||||
|
||||
- max_http_header_pool: 0 for default (16) or set the maximum amount of http
|
||||
headers that can be tracked by lws in this context. For the server, if
|
||||
the header pool is completely in use then accepts on the listen socket
|
||||
are disabled until one becomes free. For the client, if you simultaneously
|
||||
have pending connects for more than this number of client connections,
|
||||
additional connects will fail until some of the pending connections timeout
|
||||
or complete.
|
||||
|
||||
HTTP header processing in lws only exists until just after the first main
|
||||
callback after the HTTP handshake... for ws connections that is ESTABLISHED and
|
||||
for HTTP connections the HTTP callback.
|
||||
|
||||
So these settings are not related to the maximum number of simultaneous
|
||||
connections but the number of HTTP handshakes that may be expected or ongoing,
|
||||
or have just completed, at one time. The reason it's useful is it changes the
|
||||
memory allocation for header processing to be one-time at context creation
|
||||
instead of every time there is a new connection, and gives you control over
|
||||
the peak allocation.
|
||||
|
||||
Setting max_http_header_pool to 1 is fine it will just queue incoming
|
||||
connections before the accept as necessary, you can still have as many
|
||||
simultaneous post-header connections as you like.
|
||||
|
||||
|
||||
v1.6.0-chrome48-firefox42
|
||||
=======================
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ lws_client_connect_2(struct lws *wsi)
|
|||
return wsi;
|
||||
|
||||
oom4:
|
||||
lws_free(wsi->u.hdr.ah);
|
||||
lws_free_header_table(wsi);
|
||||
lws_free(wsi);
|
||||
|
||||
return NULL;
|
||||
|
@ -423,10 +423,10 @@ lws_client_connect(struct lws_context *context, const char *address,
|
|||
}
|
||||
lwsl_client("lws_client_connect: direct conn\n");
|
||||
|
||||
return lws_client_connect_2(wsi);
|
||||
return lws_client_connect_2(wsi);
|
||||
|
||||
bail1:
|
||||
lws_free(wsi->u.hdr.ah);
|
||||
lws_free_header_table(wsi);
|
||||
bail:
|
||||
lws_free(wsi);
|
||||
|
||||
|
|
|
@ -724,12 +724,10 @@ check_accept:
|
|||
goto bail2;
|
||||
|
||||
/* clear his proxy connection timeout */
|
||||
|
||||
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
/* free up his parsing allocations */
|
||||
|
||||
lws_free(wsi->u.hdr.ah);
|
||||
lws_free_header_table(wsi);
|
||||
|
||||
lws_union_transition(wsi, LWSCM_WS_CLIENT);
|
||||
wsi->state = LWSS_ESTABLISHED;
|
||||
|
@ -809,7 +807,7 @@ bail2:
|
|||
lwsl_info("closing connection due to bail2 connection error\n");
|
||||
|
||||
/* free up his parsing allocations */
|
||||
lws_free_set_NULL(wsi->u.hdr.ah);
|
||||
lws_free_header_table(wsi);
|
||||
lws_close_free_wsi(wsi, close_reason);
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -80,6 +80,7 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
int pid_daemon = get_daemonize_pid();
|
||||
#endif
|
||||
char *p;
|
||||
int n;
|
||||
|
||||
lwsl_notice("Initial logging level %d\n", log_level);
|
||||
|
||||
|
@ -150,11 +151,42 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
context->lws_ev_sigint_cb = &lws_sigint_cb;
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
|
||||
/* to reduce this allocation, */
|
||||
lwsl_info(" mem: context: %5u bytes\n", sizeof(struct lws_context));
|
||||
|
||||
/*
|
||||
* allocate and initialize the pool of
|
||||
* allocated_header structs + data
|
||||
*/
|
||||
if (info->max_http_header_data)
|
||||
context->max_http_header_data = info->max_http_header_data;
|
||||
else
|
||||
context->max_http_header_data = LWS_MAX_HEADER_LEN;
|
||||
if (info->max_http_header_pool)
|
||||
context->max_http_header_pool = info->max_http_header_pool;
|
||||
else
|
||||
context->max_http_header_pool = LWS_MAX_HEADER_POOL;
|
||||
|
||||
context->http_header_data = lws_malloc(context->max_http_header_data *
|
||||
context->max_http_header_pool);
|
||||
if (!context->http_header_data)
|
||||
goto bail;
|
||||
context->ah_pool = lws_zalloc(sizeof(struct allocated_headers) *
|
||||
context->max_http_header_pool);
|
||||
if (!context->ah_pool)
|
||||
goto bail;
|
||||
|
||||
for (n = 0; n < context->max_http_header_pool; n++)
|
||||
context->ah_pool[n].data = (char *)context->http_header_data +
|
||||
(n * context->max_http_header_data);
|
||||
|
||||
/* this is per context */
|
||||
lwsl_info(" mem: http hdr rsvd: %5u bytes ((%u + %u) x %u)\n",
|
||||
(context->max_http_header_data + sizeof(struct allocated_headers)) *
|
||||
context->max_http_header_pool,
|
||||
context->max_http_header_data, sizeof(struct allocated_headers),
|
||||
context->max_http_header_pool);
|
||||
|
||||
context->max_fds = getdtablesize();
|
||||
lwsl_notice(" ctx mem: %u bytes\n", sizeof(struct lws_context) +
|
||||
((sizeof(struct lws_pollfd) + sizeof(struct lws *)) *
|
||||
context->max_fds));
|
||||
|
||||
context->fds = lws_zalloc(sizeof(struct lws_pollfd) * context->max_fds);
|
||||
if (context->fds == NULL) {
|
||||
|
@ -162,6 +194,9 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
goto bail;
|
||||
}
|
||||
|
||||
lwsl_info(" mem: pollfd map: %5u\n",
|
||||
sizeof(struct lws_pollfd) * context->max_fds);
|
||||
|
||||
if (lws_plat_init(context, info))
|
||||
goto bail;
|
||||
|
||||
|
@ -169,8 +204,10 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
context->user_space = info->user;
|
||||
|
||||
strcpy(context->canonical_hostname, "unknown");
|
||||
lwsl_notice(" mem: per-conn: %5u bytes + protocol rx buf\n",
|
||||
sizeof(struct lws));
|
||||
|
||||
strcpy(context->canonical_hostname, "unknown");
|
||||
lws_server_get_canonical_hostname(context, info);
|
||||
|
||||
/* either use proxy from info, or try get it from env var */
|
||||
|
@ -188,9 +225,6 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
#endif
|
||||
}
|
||||
|
||||
lwsl_notice(" per-conn mem: %u + %u headers + protocol rx buf\n",
|
||||
sizeof(struct lws), sizeof(struct allocated_headers));
|
||||
|
||||
if (lws_context_init_server_ssl(info, context))
|
||||
goto bail;
|
||||
|
||||
|
@ -311,9 +345,12 @@ lws_context_destroy(struct lws_context *context)
|
|||
|
||||
lws_plat_context_early_destroy(context);
|
||||
lws_ssl_context_destroy(context);
|
||||
|
||||
if (context->fds)
|
||||
lws_free(context->fds);
|
||||
if (context->ah_pool)
|
||||
lws_free(context->ah_pool);
|
||||
if (context->http_header_data)
|
||||
lws_free(context->http_header_data);
|
||||
|
||||
lws_plat_context_late_destroy(context);
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ static int lws_frag_append(struct lws *wsi, unsigned char c)
|
|||
ah->data[ah->pos++] = c;
|
||||
ah->frags[ah->nfrag].len++;
|
||||
|
||||
return ah->pos >= sizeof(ah->data);
|
||||
return ah->pos >= wsi->context->max_http_header_data;
|
||||
}
|
||||
|
||||
static int lws_frag_end(struct lws *wsi)
|
||||
|
|
|
@ -52,7 +52,19 @@ lws_free_wsi(struct lws *wsi)
|
|||
|
||||
lws_free_set_NULL(wsi->rxflow_buffer);
|
||||
lws_free_set_NULL(wsi->trunc_alloc);
|
||||
lws_free_header_table(wsi);
|
||||
/*
|
||||
* These union members have an ah at the start
|
||||
*
|
||||
* struct _lws_http_mode_related http;
|
||||
* struct _lws_http2_related http2;
|
||||
* struct _lws_header_related hdr;
|
||||
*
|
||||
* basically ws-related union member does not
|
||||
*/
|
||||
if (wsi->mode != LWSCM_WS_CLIENT &&
|
||||
wsi->mode != LWSCM_WS_SERVING)
|
||||
if (wsi->u.hdr.ah)
|
||||
lws_free_header_table(wsi);
|
||||
lws_free(wsi);
|
||||
}
|
||||
|
||||
|
@ -222,7 +234,6 @@ just_kill_connection:
|
|||
wsi->state = LWSS_DEAD_SOCKET;
|
||||
|
||||
lws_free_set_NULL(wsi->rxflow_buffer);
|
||||
lws_free_header_table(wsi);
|
||||
|
||||
if (old_state == LWSS_ESTABLISHED ||
|
||||
wsi->mode == LWSCM_WS_SERVING ||
|
||||
|
@ -912,6 +923,7 @@ lws_get_peer_write_allowance(struct lws *wsi)
|
|||
LWS_VISIBLE void
|
||||
lws_union_transition(struct lws *wsi, enum connection_mode mode)
|
||||
{
|
||||
lwsl_debug("%s: %p: mode %d\n", __func__, wsi, mode);
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
wsi->mode = mode;
|
||||
}
|
||||
|
|
|
@ -1249,6 +1249,13 @@ struct lws_extension {
|
|||
* implementation for the one provided by provided_ssl_ctx.
|
||||
* Libwebsockets no longer is responsible for freeing the context
|
||||
* if this option is selected.
|
||||
* @max_http_header_data: The max amount of header payload that can be handled
|
||||
* in an http request (unrecognized header payload is dropped)
|
||||
* @max_http_header_pool: The max number of connections with http headers that
|
||||
* can be processed simultaneously (the corresponding memory is
|
||||
* allocated for the lifetime of the context). If the pool is
|
||||
* busy new incoming connections must wait for accept until one
|
||||
* becomes free.
|
||||
*/
|
||||
|
||||
struct lws_context_creation_info {
|
||||
|
@ -1274,9 +1281,12 @@ struct lws_context_creation_info {
|
|||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
SSL_CTX *provided_client_ssl_ctx;
|
||||
#else /* maintain structure layout either way */
|
||||
void *provided_client_ssl_ctx;
|
||||
void *provided_client_ssl_ctx;
|
||||
#endif
|
||||
|
||||
short max_http_header_data;
|
||||
short max_http_header_pool;
|
||||
|
||||
/* Add new things just above here ---^
|
||||
* This is part of the ABI, don't needlessly break compatibility
|
||||
*
|
||||
|
@ -1285,7 +1295,7 @@ struct lws_context_creation_info {
|
|||
* was not built against the newer headers.
|
||||
*/
|
||||
|
||||
void *_unused[9];
|
||||
void *_unused[8];
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
|
|
|
@ -498,6 +498,9 @@ lws_plat_init(struct lws_context *context,
|
|||
return 1;
|
||||
}
|
||||
|
||||
lwsl_notice(" mem: platform fd map: %5u bytes\n",
|
||||
sizeof(struct lws *) * context->max_fds);
|
||||
|
||||
context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
|
||||
if (context->fd_random < 0) {
|
||||
lwsl_err("Unable to open random device %s %d\n",
|
||||
|
|
|
@ -60,13 +60,47 @@ int lextable_decode(int pos, char c)
|
|||
|
||||
int lws_allocate_header_table(struct lws *wsi)
|
||||
{
|
||||
/* Be sure to free any existing header data to avoid mem leak: */
|
||||
lws_free_header_table(wsi);
|
||||
wsi->u.hdr.ah = lws_malloc(sizeof(*wsi->u.hdr.ah));
|
||||
if (wsi->u.hdr.ah == NULL) {
|
||||
lwsl_err("Out of memory\n");
|
||||
struct lws_context *context = wsi->context;
|
||||
int n;
|
||||
|
||||
lwsl_debug("%s: wsi %p: ah %p\n", __func__, (void *)wsi,
|
||||
(void *)wsi->u.hdr.ah);
|
||||
|
||||
/* if we are already bound to one, just clear it down */
|
||||
if (wsi->u.hdr.ah)
|
||||
goto reset;
|
||||
/*
|
||||
* server should have suppressed the accept of a new wsi before this
|
||||
* became the case. If initiating multiple client connects, make sure
|
||||
* the ah pool is big enough to cope, or be prepared to retry
|
||||
*/
|
||||
if (context->ah_count_in_use == context->max_http_header_pool) {
|
||||
lwsl_err("No free ah\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (n = 0; n < context->max_http_header_pool; n++)
|
||||
if (!context->ah_pool[n].in_use)
|
||||
break;
|
||||
|
||||
/* if the count of in use said something free... */
|
||||
assert(n != context->max_http_header_pool);
|
||||
|
||||
wsi->u.hdr.ah = &context->ah_pool[n];
|
||||
wsi->u.hdr.ah->in_use = 1;
|
||||
|
||||
context->ah_count_in_use++;
|
||||
/* if we used up all the ah, defeat accepting new server connections */
|
||||
if (context->ah_count_in_use == context->max_http_header_pool)
|
||||
if (_lws_server_listen_accept_flow_control(context, 0))
|
||||
return 1;
|
||||
|
||||
lwsl_debug("%s: wsi %p: ah %p: count %d (on exit)\n",
|
||||
__func__, (void *)wsi, (void *)wsi->u.hdr.ah,
|
||||
context->ah_count_in_use);
|
||||
|
||||
reset:
|
||||
/* init the ah to reflect no headers or data have appeared yet */
|
||||
memset(wsi->u.hdr.ah->frag_index, 0, sizeof(wsi->u.hdr.ah->frag_index));
|
||||
wsi->u.hdr.ah->nfrag = 0;
|
||||
wsi->u.hdr.ah->pos = 0;
|
||||
|
@ -76,10 +110,31 @@ int lws_allocate_header_table(struct lws *wsi)
|
|||
|
||||
int lws_free_header_table(struct lws *wsi)
|
||||
{
|
||||
lws_free_set_NULL(wsi->u.hdr.ah);
|
||||
struct lws_context *context = wsi->context;
|
||||
|
||||
lwsl_debug("%s: wsi %p: ah %p (count = %d)\n", __func__, (void *)wsi,
|
||||
(void *)wsi->u.hdr.ah, context->ah_count_in_use);
|
||||
|
||||
assert(wsi->u.hdr.ah);
|
||||
if (!wsi->u.hdr.ah)
|
||||
return 0;
|
||||
|
||||
/* if we think we're freeing one, there should be one to free */
|
||||
assert(context->ah_count_in_use > 0);
|
||||
|
||||
assert(wsi->u.hdr.ah->in_use);
|
||||
wsi->u.hdr.ah->in_use = 0;
|
||||
|
||||
/* if we just freed up one ah, allow new server connection */
|
||||
if (context->ah_count_in_use == context->max_http_header_pool)
|
||||
if (_lws_server_listen_accept_flow_control(context, 1))
|
||||
return 1;
|
||||
|
||||
context->ah_count_in_use--;
|
||||
wsi->u.hdr.ah = NULL;
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
|
||||
|
@ -130,7 +185,7 @@ LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
|
|||
if (wsi->u.hdr.ah->frags[f].len >= len)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[f].offset],
|
||||
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';
|
||||
|
||||
|
@ -167,7 +222,7 @@ char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h)
|
|||
if (!n)
|
||||
return NULL;
|
||||
|
||||
return &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset];
|
||||
return wsi->u.hdr.ah->data + wsi->u.hdr.ah->frags[n].offset;
|
||||
}
|
||||
|
||||
int lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h,
|
||||
|
@ -186,7 +241,7 @@ int lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h,
|
|||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->nfrag].nfrag = 0;
|
||||
|
||||
do {
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
if (wsi->u.hdr.ah->pos == wsi->context->max_http_header_data) {
|
||||
lwsl_err("Ran out of header data space\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -216,7 +271,7 @@ static int issue_char(struct lws *wsi, unsigned char c)
|
|||
{
|
||||
unsigned short frag_len;
|
||||
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
if (wsi->u.hdr.ah->pos == wsi->context->max_http_header_data) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -236,8 +291,8 @@ static int issue_char(struct lws *wsi, unsigned char c)
|
|||
/* Insert a null character when we *hit* the limit: */
|
||||
if (frag_len == wsi->u.hdr.current_token_limit) {
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
|
||||
lwsl_warn("header %i exceeds limit\n",
|
||||
wsi->u.hdr.parser_state);
|
||||
lwsl_warn("header %i exceeds limit %d\n",
|
||||
wsi->u.hdr.parser_state, wsi->u.hdr.current_token_limit);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -538,7 +593,8 @@ swallow:
|
|||
context->token_limits->token_limit[
|
||||
wsi->u.hdr.parser_state];
|
||||
else
|
||||
wsi->u.hdr.current_token_limit = sizeof(ah->data);
|
||||
wsi->u.hdr.current_token_limit =
|
||||
wsi->context->max_http_header_data;
|
||||
|
||||
if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
|
||||
goto set_parsing_complete;
|
||||
|
@ -569,7 +625,7 @@ excessive:
|
|||
n = ah->frags[n].nfrag;
|
||||
ah->frags[n].nfrag = ah->nfrag;
|
||||
|
||||
if (ah->pos == sizeof(ah->data)) {
|
||||
if (ah->pos == wsi->context->max_http_header_data) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -283,6 +283,9 @@ extern "C" {
|
|||
#ifndef LWS_MAX_HEADER_LEN
|
||||
#define LWS_MAX_HEADER_LEN 1024
|
||||
#endif
|
||||
#ifndef LWS_MAX_HEADER_POOL
|
||||
#define LWS_MAX_HEADER_POOL 16
|
||||
#endif
|
||||
#ifndef LWS_MAX_PROTOCOLS
|
||||
#define LWS_MAX_PROTOCOLS 5
|
||||
#endif
|
||||
|
@ -451,6 +454,46 @@ struct lws_fd_hashtable {
|
|||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is totally opaque to code using the library. It's exported as a
|
||||
* forward-reference pointer-only declaration; the user can use the pointer with
|
||||
* other APIs to get information out of it.
|
||||
*/
|
||||
|
||||
struct lws_fragments {
|
||||
unsigned short offset;
|
||||
unsigned short len;
|
||||
unsigned char nfrag; /* which ah->frag[] continues this content, or 0 */
|
||||
};
|
||||
|
||||
/*
|
||||
* these are assigned from a pool held in the context.
|
||||
* Both client and server mode uses them for http header analysis
|
||||
*/
|
||||
|
||||
struct allocated_headers {
|
||||
unsigned char in_use;
|
||||
unsigned char nfrag;
|
||||
unsigned short pos;
|
||||
/*
|
||||
* for each recognized token, frag_index says which frag[] his data
|
||||
* starts in (0 means the token did not appear)
|
||||
* the actual header data gets dumped as it comes in, into data[]
|
||||
*/
|
||||
unsigned char frag_index[WSI_TOKEN_COUNT];
|
||||
/*
|
||||
* the randomly ordered fragments, indexed by frag_index and
|
||||
* lws_fragments->nfrag for continuation.
|
||||
*/
|
||||
struct lws_fragments frags[WSI_TOKEN_COUNT * 2];
|
||||
char *data; /* prepared by context init to point to dedicated storage */
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char initial_handshake_hash_base64[30];
|
||||
unsigned short c_port;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct lws_context {
|
||||
#ifdef _WIN32
|
||||
WSAEVENT *events;
|
||||
|
@ -539,6 +582,11 @@ struct lws_context {
|
|||
#ifndef LWS_NO_SERVER
|
||||
struct lws *wsi_listening;
|
||||
#endif
|
||||
short max_http_header_data;
|
||||
short max_http_header_pool;
|
||||
short ah_count_in_use;
|
||||
void *http_header_data;
|
||||
struct allocated_headers *ah_pool;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -593,18 +641,6 @@ enum uri_esc_states {
|
|||
URIES_SEEN_PERCENT_H1,
|
||||
};
|
||||
|
||||
/*
|
||||
* This is totally opaque to code using the library. It's exported as a
|
||||
* forward-reference pointer-only declaration; the user can use the pointer with
|
||||
* other APIs to get information out of it.
|
||||
*/
|
||||
|
||||
struct lws_fragments {
|
||||
unsigned short offset;
|
||||
unsigned short len;
|
||||
unsigned char nfrag; /* which ah->frag[] continues this content, or 0 */
|
||||
};
|
||||
|
||||
/* notice that these union members:
|
||||
*
|
||||
* hdr
|
||||
|
@ -617,28 +653,6 @@ struct lws_fragments {
|
|||
* used interchangeably to access the same data
|
||||
*/
|
||||
|
||||
struct allocated_headers {
|
||||
unsigned char nfrag;
|
||||
unsigned short pos;
|
||||
/*
|
||||
* for each recognized token, frag_index says which frag[] his data
|
||||
* starts in (0 means the token did not appear)
|
||||
* the actual header data gets dumped as it comes in, into data[]
|
||||
*/
|
||||
unsigned char frag_index[WSI_TOKEN_COUNT];
|
||||
/*
|
||||
* the randomly ordered fragments, indexed by frag_index and
|
||||
* lws_fragments->nfrag for continuation.
|
||||
*/
|
||||
struct lws_fragments frags[WSI_TOKEN_COUNT * 2];
|
||||
char data[LWS_MAX_HEADER_LEN];
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char initial_handshake_hash_base64[30];
|
||||
unsigned short c_port;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _lws_http_mode_related {
|
||||
/* MUST be first in struct */
|
||||
struct allocated_headers *ah; /* mirroring _lws_header_related */
|
||||
|
@ -1104,7 +1118,7 @@ lws_change_pollfd(struct lws *wsi, int _and, int _or);
|
|||
|
||||
#ifndef LWS_NO_SERVER
|
||||
int lws_context_init_server(struct lws_context_creation_info *info,
|
||||
struct lws_context *context);
|
||||
struct lws_context *context);;
|
||||
LWS_EXTERN int
|
||||
handshake_0405(struct lws_context *context, struct lws *wsi);
|
||||
LWS_EXTERN int
|
||||
|
|
10
lib/server.c
10
lib/server.c
|
@ -111,7 +111,6 @@ int lws_context_init_server(struct lws_context_creation_info *info,
|
|||
else
|
||||
info->port = ntohs(sin.sin_port);
|
||||
#endif
|
||||
|
||||
context->listen_port = info->port;
|
||||
|
||||
wsi = lws_zalloc(sizeof(struct lws));
|
||||
|
@ -191,6 +190,8 @@ _lws_server_listen_accept_flow_control(struct lws_context *context, int on)
|
|||
if (!wsi)
|
||||
return 0;
|
||||
|
||||
lwsl_debug("%s: wsi %p: state %d\n", __func__, (void *)wsi, on);
|
||||
|
||||
if (on)
|
||||
n = lws_change_pollfd(wsi, 0, LWS_POLLIN);
|
||||
else
|
||||
|
@ -321,7 +322,7 @@ int lws_http_action(struct lws *wsi)
|
|||
}
|
||||
|
||||
/* now drop the header info we kept a pointer to */
|
||||
lws_free_set_NULL(wsi->u.http.ah);
|
||||
lws_free_header_table(wsi);
|
||||
|
||||
if (n) {
|
||||
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
||||
|
@ -343,8 +344,7 @@ int lws_http_action(struct lws *wsi)
|
|||
return 0;
|
||||
|
||||
bail_nuke_ah:
|
||||
/* drop the header info */
|
||||
lws_free_set_NULL(wsi->u.hdr.ah);
|
||||
lws_free_header_table(wsi);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -388,6 +388,7 @@ int lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
|
||||
/* 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);
|
||||
|
||||
n = lws_http_action(wsi);
|
||||
|
||||
|
@ -667,6 +668,7 @@ lws_create_new_server_wsi(struct lws_context *context)
|
|||
LWS_VISIBLE
|
||||
int lws_http_transaction_completed(struct lws *wsi)
|
||||
{
|
||||
lwsl_debug("%s: wsi %p\n", __func__, wsi);
|
||||
/* if we can't go back to accept new headers, drop the connection */
|
||||
if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
|
||||
lwsl_info("%s: close connection\n", __func__);
|
||||
|
|
|
@ -284,6 +284,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.max_http_header_pool = 1;
|
||||
info.options = opts;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
|
Loading…
Add table
Reference in a new issue