diff --git a/lib/client-handshake.c b/lib/client-handshake.c index d41777ce..235ee07a 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -40,6 +40,8 @@ struct libwebsocket * __libwebsocket_client_connect_2( * prepare the actual connection (to the proxy, if any) */ + fprintf(stderr, "__libwebsocket_client_connect_2: address %s", wsi->c_address); + server_hostent = gethostbyname(wsi->c_address); if (server_hostent == NULL) { fprintf(stderr, "Unable to get host name from %s\n", diff --git a/lib/extension-x-google-mux.c b/lib/extension-x-google-mux.c index 1f56994d..006f404c 100644 --- a/lib/extension-x-google-mux.c +++ b/lib/extension-x-google-mux.c @@ -342,11 +342,11 @@ bail2: wsi_child = conn->wsi_children[conn->block_subchannel]; - muxdebug("Server LWS_EXT_XGM_STATE__ADDCHANNEL_HEADERS in\n"); + muxdebug("Server LWS_EXT_XGM_STATE__ADDCHANNEL_HEADERS in %d\n", conn->length); libwebsocket_read(context, wsi_child, &c, 1); - if (--conn->length >= 0) + if (--conn->length > 0) break; muxdebug("Server LWS_EXT_XGM_STATE__ADDCHANNEL_HEADERS done\n"); @@ -359,7 +359,10 @@ bail2: /* reply with ADDCHANNEL to ack it */ wsi->xor_mask = xor_no_mask; + child_conn = lws_get_extension_user_matching_ext(wsi_child, this_ext); + child_conn->wsi_parent = wsi; + muxdebug("Setting child conn parent to %p\n", (void *)wsi); // lws_ext_x_google_mux__send_addchannel(context, wsi, wsi_child, // conn->block_subchannel, "url-parsing-not-done-yet"); @@ -450,7 +453,12 @@ bail2: case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY: case LWS_CONNMODE_WS_CLIENT: // fprintf(stderr, " client\n"); - libwebsocket_client_rx_sm(wsi_child, c); + if (libwebsocket_client_rx_sm(wsi_child, c) < 0) { + libwebsocket_close_and_free_session( + context, + wsi_child, + LWS_CLOSE_STATUS_GOINGAWAY); + } return 0; @@ -458,9 +466,13 @@ bail2: default: // fprintf(stderr, " server\n"); - if (libwebsocket_rx_sm(wsi_child, c) < 0) + if (libwebsocket_rx_sm(wsi_child, c) < 0) { fprintf(stderr, "probs\n"); - + libwebsocket_close_and_free_session( + context, + wsi_child, + LWS_CLOSE_STATUS_GOINGAWAY); + } break; } break; @@ -611,28 +623,17 @@ int lws_extension_callback_x_google_mux( * connection */ - conn->wsi_parent = wsi_parent; - parent_conn->wsi_children[ - parent_conn->count_children] = wsi; + wsi->candidate_children_list = wsi_parent->candidate_children_list; + wsi_parent->candidate_children_list = wsi; + wsi->mode = LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD; - /* - * and now we have to ask the server to allow us to do - * this - */ + fprintf(stderr, "attaching to existing mux\n"); - if (lws_ext_x_google_mux__send_addchannel(context, - wsi_parent, wsi, parent_conn->count_children, - (const char *)in) < 0) { - fprintf(stderr, "Addchannel failed\n"); - continue; - } + conn = parent_conn; + wsi = wsi_parent; - parent_conn->count_children++; + goto handle_additions; - fprintf(stderr, "!x-google-mux: muxing connection! CHILD ADD %d to %p\n", parent_conn->count_children - 1, (void *)wsi); - - done = 1; - n = mux_ctx->active_conns; } /* @@ -663,6 +664,28 @@ int lws_extension_callback_x_google_mux( case LWS_EXT_CALLBACK_DESTROY: muxdebug("LWS_EXT_CALLBACK_DESTROY\n"); + + /* + * remove us from parent if noted in parent + */ + + if (conn->wsi_parent) { + + parent_conn = lws_get_extension_user_matching_ext(conn->wsi_parent, ext); + if (parent_conn == 0) { + fprintf(stderr, "failed to get parent conn\n"); + break; + } + for (n = 0; n < parent_conn->count_children; n++) + if (parent_conn->wsi_children[n] == wsi) { + parent_conn->count_children--; + while (n < parent_conn->count_children) { + parent_conn->wsi_children[n] = parent_conn->wsi_children[n + 1]; + n++; + } + } + } + break; case LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING: @@ -694,6 +717,7 @@ int lws_extension_callback_x_google_mux( case LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED: muxdebug("LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED\n"); +handle_additions: /* * did this putative parent get x-google-mux authorized in the * end? @@ -716,7 +740,7 @@ int lws_extension_callback_x_google_mux( wsi_parent = wsi_temp; } - break; + return 1; } /* @@ -741,7 +765,7 @@ int lws_extension_callback_x_google_mux( wsi_parent = wsi_temp; } wsi->candidate_children_list = NULL; - break; + return 1; /* * whenever we receive something on a muxed link @@ -776,8 +800,10 @@ int lws_extension_callback_x_google_mux( * he's not a child connection of a mux */ - if (!conn->wsi_parent) + if (!conn->wsi_parent) { +// fprintf(stderr, "conn %p has no parent\n", (void *)conn); return 0; + } /* * get parent / transport mux context @@ -794,8 +820,10 @@ int lws_extension_callback_x_google_mux( * no more muxified than it already is */ - if (parent_conn->count_children == 0) + if (parent_conn->count_children == 0) { +// fprintf(stderr, "parent in singular mode\n"); return 0; + } /* * otherwise we need to take care of the sending action using diff --git a/lib/handshake.c b/lib/handshake.c index 14adbba4..d41414bc 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -721,7 +721,8 @@ libwebsocket_read(struct libwebsocket_context *context, struct libwebsocket *wsi switch (wsi->mode) { case LWS_CONNMODE_WS_CLIENT: for (n = 0; n < len; n++) - libwebsocket_client_rx_sm(wsi, *buf++); + if (libwebsocket_client_rx_sm(wsi, *buf++) < 0) + goto bail; return 0; default: diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index f3bee809..7de11dab 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -222,6 +222,9 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, if (old_state == WSI_STATE_ESTABLISHED && reason != LWS_CLOSE_STATUS_NOSTATUS) { + + fprintf(stderr, "sending close indication...\n"); + n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0, LWS_WRITE_CLOSE); if (!n) { @@ -246,6 +249,9 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, } just_kill_connection: + + fprintf(stderr, "libwebsocket_close_and_free_session: just_kill_connection\n"); + /* * we won't be servicing or receiving anything further from this guy * remove this fd from wsi mapping hashtable @@ -278,9 +284,15 @@ just_kill_connection: /* tell the user it's all over for this guy */ if (wsi->protocol && wsi->protocol->callback && - old_state == WSI_STATE_ESTABLISHED) + ((old_state == WSI_STATE_ESTABLISHED) || + (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) || + (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) { + fprintf(stderr, "calling back CLOSED\n"); wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED, wsi->user_space, NULL, 0); + } else { + fprintf(stderr, "not calling back closed due to old_state=%d\n", old_state); + } /* deallocate any active extension contexts */ @@ -334,9 +346,11 @@ just_kill_connection: #endif shutdown(wsi->sock, SHUT_RDWR); #ifdef WIN32 - closesocket(wsi->sock); + if (wsi->sock) + closesocket(wsi->sock); #else - close(wsi->sock); + if (wsi->sock) + close(wsi->sock); #endif #ifdef LWS_OPENSSL_SUPPORT } diff --git a/lib/parsers.c b/lib/parsers.c index 2c2b603a..3e3ac19d 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -1409,8 +1409,14 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len) fprintf(stderr, "Extension reports fatal error\n"); return -1; } - if (m) /* handled */ + if (m) /* handled */ { +// fprintf(stderr, "ext sent it\n"); return 0; + } + } + + if (!wsi->sock) { + fprintf(stderr, "** error 0 sock but expected to send\n"); } /* diff --git a/test-server/test-server-extpoll.c b/test-server/test-server-extpoll.c index f2594d98..f550ff64 100644 --- a/test-server/test-server-extpoll.c +++ b/test-server/test-server-extpoll.c @@ -192,6 +192,7 @@ dump_handshake_info(struct lws_tokens *lwst) [WSI_TOKEN_ACCEPT] = "Accept", [WSI_TOKEN_NONCE] = "Nonce", [WSI_TOKEN_HTTP] = "Http", + [WSI_TOKEN_MUXURL] = "MuxURL", }; for (n = 0; n < WSI_TOKEN_COUNT; n++) {