raw: take care about same vh protocol linked list
authorAndy Green <andy@warmcat.com>
Thu, 6 Apr 2017 05:49:17 +0000 (13:49 +0800)
committerAndy Green <andy@warmcat.com>
Thu, 6 Apr 2017 05:49:17 +0000 (13:49 +0800)
lib/libwebsockets.c
lib/pollfd.c
lib/private-libwebsockets.h
lib/server.c

index b19e493..e4a42dc 100755 (executable)
@@ -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;
index 841019f..b43f791 100644 (file)
@@ -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)
index abe4671..d59bd7b 100644 (file)
@@ -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
 };
index 3a8ea2a..472e0e0 100644 (file)
@@ -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