mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
lws_bind_protocol
When using http/1.1+ keepalive and mounts, the relationship between a connection and a protocol becomes dynamic. The same connection might visit different bits of the url space served by different mounts using different protocols. This patch ensures protocols can cleanly manage their per-connection allocations by using the following callbacks when the protocol changes LWS_CALLBACK_HTTP_BIND_PROTOCOL LWS_CALLBACK_HTTP_DROP_PROTOCOL For example if the pss wants to malloc stuff at runtime, it should do it in LWS_CALLBACK_HTTP_BIND_PROTOCOL or later, and clean it up in ...DROP_PROTOCOL. Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
7a2fc442b6
commit
7f92ee802c
4 changed files with 73 additions and 55 deletions
|
@ -475,13 +475,14 @@ enum lws_callback_reasons {
|
|||
LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46,
|
||||
LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47,
|
||||
LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ = 48,
|
||||
LWS_CALLBACK_HTTP_DROP_PROTOCOL = 49,
|
||||
LWS_CALLBACK_CHECK_ACCESS_RIGHTS = 50,
|
||||
LWS_CALLBACK_PROCESS_HTML = 51,
|
||||
LWS_CALLBACK_ADD_HEADERS = 52,
|
||||
LWS_CALLBACK_SESSION_INFO = 53,
|
||||
LWS_CALLBACK_HTTP_BIND_PROTOCOL = 49,
|
||||
LWS_CALLBACK_HTTP_DROP_PROTOCOL = 50,
|
||||
LWS_CALLBACK_CHECK_ACCESS_RIGHTS = 51,
|
||||
LWS_CALLBACK_PROCESS_HTML = 52,
|
||||
LWS_CALLBACK_ADD_HEADERS = 53,
|
||||
LWS_CALLBACK_SESSION_INFO = 54,
|
||||
|
||||
LWS_CALLBACK_GS_EVENT = 54,
|
||||
LWS_CALLBACK_GS_EVENT = 55,
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
|
|
@ -1734,6 +1734,9 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt);
|
|||
int
|
||||
lws_protocol_init(struct lws_context *context);
|
||||
|
||||
int
|
||||
lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p);
|
||||
|
||||
/*
|
||||
* custom allocator
|
||||
*/
|
||||
|
|
104
lib/server.c
104
lib/server.c
|
@ -412,9 +412,8 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
|
|||
const struct lws_protocols *pp = lws_vhost_name_to_protocol(
|
||||
wsi->vhost, m->protocol);
|
||||
|
||||
wsi->protocol = pp;
|
||||
if (lws_ensure_user_space(wsi))
|
||||
return -1;
|
||||
if (lws_bind_protocol(wsi, pp))
|
||||
return 1;
|
||||
args.p = (char *)p;
|
||||
args.max_len = end - p;
|
||||
if (pp->callback(wsi, LWS_CALLBACK_ADD_HEADERS,
|
||||
|
@ -702,11 +701,8 @@ lws_http_action(struct lws *wsi)
|
|||
return 1;
|
||||
}
|
||||
|
||||
wsi->protocol = pp;
|
||||
if (lws_ensure_user_space(wsi)) {
|
||||
lwsl_err("Unable to allocate user space\n");
|
||||
if (lws_bind_protocol(wsi, pp))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
lwsl_info("wsi %s protocol '%s'\n", uri_ptr, wsi->protocol->name);
|
||||
|
||||
|
@ -791,16 +787,8 @@ lws_http_action(struct lws *wsi)
|
|||
for (n = 0; n < (unsigned int)wsi->vhost->count_protocols; n++)
|
||||
if (!strcmp(wsi->vhost->protocols[n].name,
|
||||
hit->origin)) {
|
||||
|
||||
if (wsi->protocol != &wsi->vhost->protocols[n])
|
||||
if (!wsi->user_space_externally_allocated)
|
||||
lws_free_set_NULL(wsi->user_space);
|
||||
wsi->protocol = &wsi->vhost->protocols[n];
|
||||
if (lws_ensure_user_space(wsi)) {
|
||||
lwsl_err("Unable to allocate user space\n");
|
||||
|
||||
if (lws_bind_protocol(wsi, &wsi->vhost->protocols[n]))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -877,11 +865,8 @@ lws_http_action(struct lws *wsi)
|
|||
const struct lws_protocols *pp = lws_vhost_name_to_protocol(
|
||||
wsi->vhost, hit->protocol);
|
||||
|
||||
wsi->protocol = pp;
|
||||
if (lws_ensure_user_space(wsi)) {
|
||||
lwsl_err("Unable to allocate user space\n");
|
||||
if (lws_bind_protocol(wsi, pp))
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = pp->callback(wsi, LWS_CALLBACK_HTTP,
|
||||
wsi->user_space,
|
||||
|
@ -896,10 +881,8 @@ lws_http_action(struct lws *wsi)
|
|||
|
||||
lwsl_notice("no hit\n");
|
||||
|
||||
if (wsi->protocol != &wsi->vhost->protocols[0])
|
||||
if (!wsi->user_space_externally_allocated)
|
||||
lws_free_set_NULL(wsi->user_space);
|
||||
wsi->protocol = &wsi->vhost->protocols[0];
|
||||
if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
|
||||
return 1;
|
||||
|
||||
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
|
||||
wsi->user_space, uri_ptr, uri_len);
|
||||
|
@ -937,6 +920,32 @@ bail_nuke_ah:
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
|
||||
{
|
||||
// if (wsi->protocol == p)
|
||||
// return 0;
|
||||
|
||||
if (wsi->protocol)
|
||||
wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
|
||||
wsi->user_space, NULL, 0);
|
||||
if (!wsi->user_space_externally_allocated)
|
||||
lws_free_set_NULL(wsi->user_space);
|
||||
|
||||
wsi->protocol = p;
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
if (lws_ensure_user_space(wsi))
|
||||
return 1;
|
||||
|
||||
if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
|
||||
wsi->user_space, NULL, 0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
||||
|
@ -1391,13 +1400,8 @@ lws_http_transaction_completed(struct lws *wsi)
|
|||
return 1;
|
||||
}
|
||||
|
||||
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
if (!wsi->user_space_externally_allocated)
|
||||
lws_free_set_NULL(wsi->user_space);
|
||||
|
||||
wsi->protocol = &wsi->vhost->protocols[0];
|
||||
if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
|
||||
return 1;
|
||||
|
||||
/* otherwise set ourselves up ready to go again */
|
||||
wsi->state = LWSS_HTTP;
|
||||
|
@ -2151,7 +2155,7 @@ static int
|
|||
lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int len)
|
||||
{
|
||||
int n, m, hit = 0;
|
||||
char sum = 0;
|
||||
char sum = 0, c;
|
||||
|
||||
while (len--) {
|
||||
if (s->pos == s->out_len - s->mp - 1) {
|
||||
|
@ -2160,13 +2164,11 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int le
|
|||
|
||||
s->pos = 0;
|
||||
}
|
||||
|
||||
switch (s->state) {
|
||||
|
||||
/* states for url arg style */
|
||||
|
||||
case US_NAME:
|
||||
//lwsl_notice("US_NAME: %c\n", *in);
|
||||
s->inside_quote = 0;
|
||||
if (*in == '=') {
|
||||
s->name[s->pos] = '\0';
|
||||
|
@ -2191,7 +2193,6 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int le
|
|||
s->name[s->pos++] = *in++;
|
||||
break;
|
||||
case US_IDLE:
|
||||
//lwsl_notice("US_IDLE: %c\n", *in);
|
||||
if (*in == '%') {
|
||||
s->state++;
|
||||
in++;
|
||||
|
@ -2237,7 +2238,6 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int le
|
|||
/* states for multipart / mime style */
|
||||
|
||||
case MT_LOOK_BOUND_IN:
|
||||
// lwsl_notice("MT_LOOK_BOUND_IN: %02x (%d)\n", *in, s->mp);
|
||||
if (*in == s->mime_boundary[s->mp] &&
|
||||
s->mime_boundary[s->mp]) {
|
||||
in++;
|
||||
|
@ -2274,29 +2274,27 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int le
|
|||
break;
|
||||
|
||||
case MT_HNAME:
|
||||
|
||||
m = 0;
|
||||
c =*in;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
for (n = 0; n < ARRAY_SIZE(mp_hdr); n++)
|
||||
if (tolower(*in) == mp_hdr[n][s->mp]) {
|
||||
if (c == mp_hdr[n][s->mp]) {
|
||||
m++;
|
||||
hit = n;
|
||||
}
|
||||
|
||||
in++;
|
||||
if (m > 1) {
|
||||
s->mp++;
|
||||
continue;
|
||||
}
|
||||
if (!m) {
|
||||
s->mp = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
s->mp++;
|
||||
if (mp_hdr[hit][s->mp])
|
||||
if (m != 1)
|
||||
continue;
|
||||
|
||||
/* ie, m == 1 */
|
||||
if (mp_hdr[hit][s->mp])
|
||||
continue;
|
||||
|
||||
s->mp = 0;
|
||||
s->temp[0] = '\0';
|
||||
|
@ -2312,9 +2310,9 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int le
|
|||
/* form-data; name="file"; filename="t.txt" */
|
||||
|
||||
if (*in == '\x0d') {
|
||||
lwsl_debug("disp: '%s', '%s', '%s'\n",
|
||||
s->content_disp, s->name,
|
||||
s->content_disp_filename);
|
||||
// lwsl_notice("disp: '%s', '%s', '%s'\n",
|
||||
// s->content_disp, s->name,
|
||||
// s->content_disp_filename);
|
||||
|
||||
if (s->content_disp_filename[0])
|
||||
if (s->output(s->data, s->name,
|
||||
|
@ -2512,7 +2510,7 @@ lws_spa_create(struct lws *wsi, const char * const *param_names,
|
|||
int count_params, int max_storage,
|
||||
lws_spa_fileupload_cb opt_cb, void *opt_data)
|
||||
{
|
||||
struct lws_spa *spa = lws_malloc(sizeof(*spa));
|
||||
struct lws_spa *spa = lws_zalloc(sizeof(*spa));
|
||||
|
||||
if (!spa)
|
||||
return NULL;
|
||||
|
@ -2541,6 +2539,8 @@ lws_spa_create(struct lws *wsi, const char * const *param_names,
|
|||
if (!spa->param_length)
|
||||
goto bail5;
|
||||
|
||||
lwsl_notice("%s: Created SPA %p\n", __func__, spa);
|
||||
|
||||
return spa;
|
||||
|
||||
bail5:
|
||||
|
@ -2566,6 +2566,10 @@ bail2:
|
|||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_spa_process(struct lws_spa *ludspa, const char *in, int len)
|
||||
{
|
||||
if (!ludspa) {
|
||||
lwsl_err("%s: NULL spa\n");
|
||||
return -1;
|
||||
}
|
||||
return lws_urldecode_s_process(ludspa->s, in, len);
|
||||
}
|
||||
|
||||
|
@ -2629,6 +2633,8 @@ lws_spa_destroy(struct lws_spa *spa)
|
|||
{
|
||||
int n = 0;
|
||||
|
||||
lwsl_notice("%s: destroy spa %p\n", __func__, spa);
|
||||
|
||||
if (spa->s)
|
||||
lws_urldecode_s_destroy(spa->s);
|
||||
|
||||
|
|
|
@ -496,7 +496,15 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
if (n < 0)
|
||||
return 1;
|
||||
goto try_to_reuse;
|
||||
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
|
||||
lwsl_notice("LWS_CALLBACK_HTTP_DROP_PROTOCOL\n");
|
||||
|
||||
/* called when our wsi user_space is going to be destroyed */
|
||||
if (pss->spa) {
|
||||
lws_spa_destroy(pss->spa);
|
||||
pss->spa = NULL;
|
||||
}
|
||||
break;
|
||||
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||
goto try_to_reuse;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue