diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index b19e493e..e4a42dc2 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -174,6 +174,7 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p) { // if (wsi->protocol == p) // return 0; + const struct lws_protocols *vp = wsi->vhost->protocols, *vpo; if (wsi->protocol) wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL, @@ -181,6 +182,8 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p) if (!wsi->user_space_externally_allocated) lws_free_set_NULL(wsi->user_space); + lws_same_vh_protocol_remove(wsi); + wsi->protocol = p; if (!p) return 0; @@ -188,6 +191,27 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p) if (lws_ensure_user_space(wsi)) return 1; + if (p > vp && p < &vp[wsi->vhost->count_protocols]) + lws_same_vh_protocol_insert(wsi, p - vp); + else { + int n = wsi->vhost->count_protocols; + int hit = 0; + + vpo = vp; + + while (n--) { + if (!strcmp(p->name, vp->name)) { + hit = 1; + lws_same_vh_protocol_insert(wsi, vp - vpo); + break; + } + vp++; + } + if (!hit) + lwsl_err("%s: protocol %p is not in vhost %s protocols list\n", + __func__, p, wsi->vhost->name); + } + if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL, wsi->user_space, NULL, 0)) return 1; diff --git a/lib/pollfd.c b/lib/pollfd.c index 841019f5..b43f7913 100644 --- a/lib/pollfd.c +++ b/lib/pollfd.c @@ -247,31 +247,7 @@ remove_wsi_socket_from_fds(struct lws *wsi) wsi->user_space, (void *)&pa, 1)) return -1; - /* - * detach ourselves from vh protocol list if we're on one - * A -> B -> C - * A -> C , or, B -> C, or A -> B - */ - lwsl_info("%s: removing same prot wsi %p\n", __func__, wsi); - if (wsi->same_vh_protocol_prev) { - assert (*(wsi->same_vh_protocol_prev) == wsi); - lwsl_info("have prev %p, setting him to our next %p\n", - wsi->same_vh_protocol_prev, - wsi->same_vh_protocol_next); - - /* guy who pointed to us should point to our next */ - *(wsi->same_vh_protocol_prev) = wsi->same_vh_protocol_next; - } //else - //lwsl_err("null wsi->prev\n"); - /* our next should point back to our prev */ - if (wsi->same_vh_protocol_next) { - wsi->same_vh_protocol_next->same_vh_protocol_prev = - wsi->same_vh_protocol_prev; - } //else - //lwsl_err("null wsi->next\n"); - - wsi->same_vh_protocol_prev = NULL; - wsi->same_vh_protocol_next = NULL; + lws_same_vh_protocol_remove(wsi); /* the guy who is to be deleted's slot index in pt->fds */ m = wsi->position_in_fds_table; @@ -430,6 +406,74 @@ network_sock: return 1; } +/* + * stitch protocol choice into the vh protocol linked list + * We always insert ourselves at the start of the list + * + * X <-> B + * X <-> pAn <-> pB + * + * Illegal to attach more than once without detach inbetween + */ +void +lws_same_vh_protocol_insert(struct lws *wsi, int n) +{ + //lwsl_err("%s: pre insert vhost start wsi %p, that wsi prev == %p\n", + // __func__, + // wsi->vhost->same_vh_protocol_list[n], + // wsi->same_vh_protocol_prev); + + if (wsi->same_vh_protocol_prev || wsi->same_vh_protocol_next) { + lwsl_err("Attempted to attach wsi twice to same vh prot\n"); + assert(0); + } + + wsi->same_vh_protocol_prev = /* guy who points to us */ + &wsi->vhost->same_vh_protocol_list[n]; + wsi->same_vh_protocol_next = /* old first guy is our next */ + wsi->vhost->same_vh_protocol_list[n]; + /* we become the new first guy */ + wsi->vhost->same_vh_protocol_list[n] = wsi; + + if (wsi->same_vh_protocol_next) + /* old first guy points back to us now */ + wsi->same_vh_protocol_next->same_vh_protocol_prev = + &wsi->same_vh_protocol_next; +} + +void +lws_same_vh_protocol_remove(struct lws *wsi) +{ + /* + * detach ourselves from vh protocol list if we're on one + * A -> B -> C + * A -> C , or, B -> C, or A -> B + * + * OK to call on already-detached wsi + */ + lwsl_info("%s: removing same prot wsi %p\n", __func__, wsi); + + if (wsi->same_vh_protocol_prev) { + assert (*(wsi->same_vh_protocol_prev) == wsi); + lwsl_info("have prev %p, setting him to our next %p\n", + wsi->same_vh_protocol_prev, + wsi->same_vh_protocol_next); + + /* guy who pointed to us should point to our next */ + *(wsi->same_vh_protocol_prev) = wsi->same_vh_protocol_next; + } + + /* our next should point back to our prev */ + if (wsi->same_vh_protocol_next) { + wsi->same_vh_protocol_next->same_vh_protocol_prev = + wsi->same_vh_protocol_prev; + } + + wsi->same_vh_protocol_prev = NULL; + wsi->same_vh_protocol_next = NULL; +} + + LWS_VISIBLE int lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost, const struct lws_protocols *protocol) diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index abe4671a..d59bd7b3 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -2067,6 +2067,10 @@ LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len); LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount); +LWS_EXTERN void +lws_same_vh_protocol_remove(struct lws *wsi); +LWS_EXTERN void +lws_same_vh_protocol_insert(struct lws *wsi, int n); #ifdef __cplusplus }; diff --git a/lib/server.c b/lib/server.c index 3a8ea2a3..472e0e01 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1161,7 +1161,6 @@ transaction_result_n: #endif } - int lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) { @@ -1498,30 +1497,7 @@ upgrade_ws: goto bail_nuke_ah; } - /* - * stitch protocol choice into the vh protocol linked list - * We always insert ourselves at the start of the list - * - * X <-> B - * X <-> pAn <-> pB - */ - //lwsl_err("%s: pre insert vhost start wsi %p, that wsi prev == %p\n", - // __func__, - // wsi->vhost->same_vh_protocol_list[n], - // wsi->same_vh_protocol_prev); - wsi->same_vh_protocol_prev = /* guy who points to us */ - &wsi->vhost->same_vh_protocol_list[n]; - wsi->same_vh_protocol_next = /* old first guy is our next */ - wsi->vhost->same_vh_protocol_list[n]; - /* we become the new first guy */ - wsi->vhost->same_vh_protocol_list[n] = wsi; - - if (wsi->same_vh_protocol_next) - /* old first guy points back to us now */ - wsi->same_vh_protocol_next->same_vh_protocol_prev = - &wsi->same_vh_protocol_next; - - + lws_same_vh_protocol_insert(wsi, n); /* we are upgrading to ws, so http/1.1 and keepalive + * pipelined header considerations about keeping the ah around