aboutsummaryrefslogtreecommitdiff
path: root/lib/core-net
diff options
context:
space:
mode:
authorAndy Green <andy@warmcat.com>2021-06-17 10:07:04 +0100
committerAndy Green <andy@warmcat.com>2021-06-22 15:55:29 +0100
commit272dba83073e93870bcd8ea566d1af7818de9c52 (patch)
tree3ee1fd0574ec028a2a30a8bcbdf0cc15ed79a91a /lib/core-net
parent2f9bb7a30afd505935959664bf90c13bcb569a45 (diff)
downloadlibwebsockets-272dba83073e93870bcd8ea566d1af7818de9c52.tar.gz
http: redo redirects to follow close flow
Until now although we can follow redirects, and they can promote the protocol from h1->h2, we couldn't handle h2 wsi reuse since there are many states in the wsi affected by being h2. This wipes the related states in lws_wsi_reset() and follows the generic wsi close flow before deviating into the redirect really close to the end, ensuring we cleaned out evidence of our previous life properly. h2->h2 redirects work properly after this. The max number of redirects is increased from 3 -> 4 since this was seen in the wild with www and then geographic-based redirects.
Diffstat (limited to 'lib/core-net')
-rw-r--r--lib/core-net/client/connect.c109
-rw-r--r--lib/core-net/client/connect2.c40
-rw-r--r--lib/core-net/client/connect3.c2
-rw-r--r--lib/core-net/client/connect4.c49
-rw-r--r--lib/core-net/close.c139
-rw-r--r--lib/core-net/private-lib-core-net.h10
-rw-r--r--lib/core-net/vhost.c15
-rw-r--r--lib/core-net/wsi.c10
8 files changed, 265 insertions, 109 deletions
diff --git a/lib/core-net/client/connect.c b/lib/core-net/client/connect.c
index 1e18cbbe..2298fa21 100644
--- a/lib/core-net/client/connect.c
+++ b/lib/core-net/client/connect.c
@@ -60,7 +60,7 @@ lws_http_client_connect_via_info2(struct lws *wsi)
for (n = 0; n < (int)LWS_ARRAY_SIZE(hnames); n++)
if (hnames[n] && stash->cis[n] &&
lws_hdr_simple_create(wsi, hnames[n], stash->cis[n]))
- goto bail1;
+ goto bail;
#if defined(LWS_WITH_SOCKS5)
if (!wsi->a.vhost->socks_proxy_port)
@@ -70,15 +70,58 @@ lws_http_client_connect_via_info2(struct lws *wsi)
no_ah:
return lws_client_connect_2_dnsreq(wsi);
-bail1:
+bail:
#if defined(LWS_WITH_SOCKS5)
if (!wsi->a.vhost->socks_proxy_port)
lws_free_set_NULL(wsi->stash);
#endif
+ lws_free_set_NULL(wsi->stash);
+
return NULL;
}
+int
+lws_client_stash_create(struct lws *wsi, const char **cisin)
+{
+ size_t size;
+ char *pc;
+ int n;
+
+ size = sizeof(*wsi->stash);
+
+ /*
+ * Let's overallocate the stash object with space for all the args
+ * in one hit.
+ */
+ for (n = 0; n < CIS_COUNT; n++)
+ if (cisin[n])
+ size += strlen(cisin[n]) + 1;
+
+ if (wsi->stash)
+ lws_free_set_NULL(wsi->stash);
+
+ wsi->stash = lws_malloc(size, "client stash");
+ if (!wsi->stash)
+ return 1;
+
+ /* all the pointers default to NULL, but no need to zero the args */
+ memset(wsi->stash, 0, sizeof(*wsi->stash));
+
+ pc = (char *)&wsi->stash[1];
+
+ for (n = 0; n < CIS_COUNT; n++)
+ if (cisin[n]) {
+ size_t mm;
+ wsi->stash->cis[n] = pc;
+ mm = strlen(cisin[n]) + 1;
+ memcpy(pc, cisin[n], mm);
+ pc += mm;
+ }
+
+ return 0;
+}
+
struct lws *
lws_client_connect_via_info(const struct lws_client_connect_info *i)
{
@@ -86,10 +129,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
struct lws *wsi, *safe = NULL;
const struct lws_protocols *p;
const char *cisin[CIS_COUNT];
- struct lws_vhost *vh, *v;
- size_t size;
- int n, tsi;
- char *pc;
+ struct lws_vhost *vh;
+ int tsi;
if (i->context->requested_stop_internal_loops)
return NULL;
@@ -118,11 +159,10 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
wsi = __lws_wsi_create_with_role(i->context, tsi, NULL);
lws_context_unlock(i->context);
if (wsi == NULL)
- goto bail;
+ return NULL;
vh = i->vhost;
if (!vh) {
-
#if defined(LWS_WITH_TLS_JIT_TRUST)
if (lws_tls_jit_trust_vhost_bind(i->context, i->address, &vh))
#endif
@@ -199,23 +239,11 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
if (i->ssl_connection & LCCSCF_WAKE_SUSPEND__VALIDITY)
wsi->conn_validity_wakesuspend = 1;
- if (!i->vhost) {
- v = i->context->vhost_list;
-
- if (!v) { /* coverity */
- lwsl_err("%s: no vhost\n", __func__);
- goto bail;
- }
- if (!strcmp(v->name, "system"))
- v = v->vhost_next;
- } else
- v = i->vhost;
-
- lws_vhost_bind_wsi(v, wsi);
+ lws_vhost_bind_wsi(vh, wsi);
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
/* additionally inerit from vhost we bound to */
- lws_fi_inherit_copy(&wsi->fic, &v->fic, "wsi", i->fi_wsi_name);
+ lws_fi_inherit_copy(&wsi->fic, &vh->fic, "wsi", i->fi_wsi_name);
#endif
if (!wsi->a.vhost) {
@@ -324,23 +352,13 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
cisin[CIS_IFACE] = i->iface;
cisin[CIS_ALPN] = i->alpn;
- size = sizeof(*wsi->stash);
-
- /*
- * Let's overallocate the stash object with space for all the args
- * in one hit.
- */
- for (n = 0; n < CIS_COUNT; n++)
- if (cisin[n])
- size += strlen(cisin[n]) + 1;
+ if (lws_client_stash_create(wsi, cisin))
+ goto bail;
- wsi->stash = lws_malloc(size, "client stash");
- if (!wsi->stash) {
- lwsl_err("%s: OOM\n", __func__);
- goto bail1;
- }
- /* all the pointers default to NULL, but no need to zero the args */
- memset(wsi->stash, 0, sizeof(*wsi->stash));
+#if defined(LWS_WITH_TLS)
+ if (i->alpn)
+ lws_strncpy(wsi->alpn, i->alpn, sizeof(wsi->alpn));
+#endif
wsi->a.opaque_user_data = wsi->stash->opaque_user_data =
i->opaque_user_data;
@@ -382,17 +400,6 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
lws_metrics_tag_wsi_add(wsi, "vh", wsi->a.vhost->name);
- pc = (char *)&wsi->stash[1];
-
- for (n = 0; n < CIS_COUNT; n++)
- if (cisin[n]) {
- size_t mm;
- wsi->stash->cis[n] = pc;
- mm = strlen(cisin[n]) + 1;
- memcpy(pc, cisin[n], mm);
- pc += mm;
- }
-
/*
* at this point user callbacks like
* LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER will be interested to
@@ -519,10 +526,8 @@ bail3:
return NULL;
#endif
-bail1:
- lws_free_set_NULL(wsi->stash);
-
bail:
+ lws_free_set_NULL(wsi->stash);
lws_fi_destroy(&wsi->fic);
lws_free(wsi);
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
diff --git a/lib/core-net/client/connect2.c b/lib/core-net/client/connect2.c
index d08f8981..39428353 100644
--- a/lib/core-net/client/connect2.c
+++ b/lib/core-net/client/connect2.c
@@ -145,6 +145,26 @@ lws_client_connect_2_dnsreq(struct lws *wsi)
}
/*
+ * clients who will create their own fresh connection keep a copy of
+ * the hostname they originally connected to, in case other connections
+ * want to use it too
+ */
+
+ if (!wsi->cli_hostname_copy) {
+ if (wsi->stash && wsi->stash->cis[CIS_HOST])
+ wsi->cli_hostname_copy =
+ lws_strdup(wsi->stash->cis[CIS_HOST]);
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ else {
+ char *pa = lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_PEER_ADDRESS);
+ if (pa)
+ wsi->cli_hostname_copy = lws_strdup(pa);
+ }
+#endif
+ }
+
+ /*
* The first job is figure out if we want to pipeline on or just join
* an existing "active connection" to the same place
*/
@@ -214,26 +234,6 @@ lws_client_connect_2_dnsreq(struct lws *wsi)
solo:
/*
- * clients who will create their own fresh connection keep a copy of
- * the hostname they originally connected to, in case other connections
- * want to use it too
- */
-
- if (!wsi->cli_hostname_copy) {
- if (wsi->stash && wsi->stash->cis[CIS_HOST])
- wsi->cli_hostname_copy =
- lws_strdup(wsi->stash->cis[CIS_HOST]);
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- else {
- char *pa = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS);
- if (pa)
- wsi->cli_hostname_copy = lws_strdup(pa);
- }
-#endif
- }
-
- /*
* If we made our own connection, and we're doing a method that can
* take a pipeline, we are an "active client connection".
*
diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c
index 0f6b901b..98fff5ba 100644
--- a/lib/core-net/client/connect3.c
+++ b/lib/core-net/client/connect3.c
@@ -475,7 +475,7 @@ ads_known:
errno_copy = 999;
#endif
- lwsl_debug("%s: connect: errno: %d\n", __func__, errno_copy);
+ lwsl_debug("%s: connect: fd %d errno: %d\n", __func__, wsi->desc.sockfd, errno_copy);
if (errno_copy &&
errno_copy != LWS_EALREADY &&
diff --git a/lib/core-net/client/connect4.c b/lib/core-net/client/connect4.c
index 89611202..8e13dc03 100644
--- a/lib/core-net/client/connect4.c
+++ b/lib/core-net/client/connect4.c
@@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
- * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -95,7 +95,8 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
goto failed;
wsi->c_port = (uint16_t)wsi->a.vhost->http.http_proxy_port;
- n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf, (unsigned int)plen,
+ n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf,
+ (unsigned int)plen,
MSG_NOSIGNAL);
if (n < 0) {
lwsl_debug("ERROR writing to proxy socket\n");
@@ -161,14 +162,18 @@ send_hs:
__func__, wsi->lc.gutag, lwsi_state(wsi_piggyback));
} else {
lwsl_info("%s: %s: %s %s client created own conn "
- "(raw %d) vh %sm st 0x%x\n",
- __func__, wsi->lc.gutag, wsi->role_ops->name,
- wsi->a.protocol->name, rawish, wsi->a.vhost->name,
- lwsi_state(wsi));
+ "(raw %d) vh %sm st 0x%x\n", __func__, wsi->lc.gutag,
+ wsi->role_ops->name, wsi->a.protocol->name, rawish,
+ wsi->a.vhost->name, lwsi_state(wsi));
/* we are making our own connection */
- if (!rawish) {
+ if (!rawish
+#if defined(LWS_WITH_TLS)
+ // && (!(wsi->tls.use_ssl & LCCSCF_USE_SSL) || wsi->tls.ssl)
+#endif
+ ) {
+
if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2)
lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
} else {
@@ -183,20 +188,24 @@ send_hs:
(wsi->tls.use_ssl & LCCSCF_USE_SSL)) {
int result;
+ //lwsi_set_state(wsi, LRS_WAITING_SSL);
+
/*
* We can retry this... just cook the SSL BIO
* the first time
*/
result = lws_client_create_tls(wsi, &cce, 1);
- lwsl_debug("%s: create_tls said %d\n",
- __func__, result);
switch (result) {
case CCTLS_RETURN_DONE:
break;
case CCTLS_RETURN_RETRY:
+ lwsl_debug("%s: create_tls RETRY\n",
+ __func__);
return wsi;
default:
+ lwsl_debug("%s: create_tls FAIL\n",
+ __func__);
goto failed;
}
@@ -207,9 +216,10 @@ send_hs:
* LRS_H2_WAITING_TO_SEND_HEADERS already.
*/
- lwsl_notice("%s: %s: "
- "tls established st 0x%x\n",
- __func__, wsi->lc.gutag, lwsi_state(wsi));
+ lwsl_notice("%s: %s: tls established st 0x%x, "
+ "client_h2_alpn %d\n", __func__,
+ wsi->lc.gutag, lwsi_state(wsi),
+ wsi->client_h2_alpn);
if (lwsi_state(wsi) !=
LRS_H2_WAITING_TO_SEND_HEADERS)
@@ -217,7 +227,13 @@ send_hs:
LRS_H1C_ISSUE_HANDSHAKE2);
lws_set_timeout(wsi,
PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
- (int)wsi->a.context->timeout_secs);
+ (int)wsi->a.context->timeout_secs);
+#if 0
+ /* ensure pollin enabled */
+ if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
+ lwsl_notice("%s: unable to set POLLIN\n",
+ __func__);
+#endif
goto provoke_service;
}
@@ -230,7 +246,8 @@ send_hs:
if (m) {
n = user_callback_handle_rxflow(
wsi->a.protocol->callback, wsi,
- (enum lws_callback_reasons)m, wsi->user_space, NULL, 0);
+ (enum lws_callback_reasons)m,
+ wsi->user_space, NULL, 0);
if (n < 0) {
lwsl_info("RAW_PROXY_CLI_ADOPT err\n");
goto failed;
@@ -240,7 +257,7 @@ send_hs:
/* service.c pollout processing wants this */
wsi->hdr_parsing_completed = 1;
#if defined(LWS_ROLE_MQTT)
- if (!strcmp(meth, "MQTT")) {
+ if (meth && !strcmp(meth, "MQTT")) {
#if defined(LWS_WITH_TLS)
if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
lwsi_set_state(wsi, LRS_WAITING_SSL);
@@ -320,7 +337,7 @@ provoke_service:
failed:
lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
+ lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect4");
return NULL;
}
diff --git a/lib/core-net/close.c b/lib/core-net/close.c
index 06e1266b..45c88c9e 100644
--- a/lib/core-net/close.c
+++ b/lib/core-net/close.c
@@ -123,6 +123,8 @@ __lws_reset_wsi(struct lws *wsi)
#if defined(LWS_WITH_CLIENT)
lws_dll2_remove(&wsi->dll2_cli_txn_queue);
lws_dll2_remove(&wsi->dll_cli_active_conns);
+ if (wsi->cli_hostname_copy)
+ lws_free_set_NULL(wsi->cli_hostname_copy);
#endif
#if defined(LWS_WITH_SYS_ASYNC_DNS)
@@ -143,7 +145,7 @@ __lws_reset_wsi(struct lws *wsi)
__lws_same_vh_protocol_remove(wsi);
#if defined(LWS_WITH_CLIENT)
- lws_free_set_NULL(wsi->stash);
+ //lws_free_set_NULL(wsi->stash);
lws_free_set_NULL(wsi->cli_hostname_copy);
#endif
@@ -166,6 +168,34 @@ __lws_reset_wsi(struct lws *wsi)
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
__lws_header_table_detach(wsi, 0);
#endif
+
+#if defined(LWS_ROLE_H2)
+ /*
+ * Let's try to clean out the h2-ness of the wsi
+ */
+
+ memset(&wsi->h2, 0, sizeof(wsi->h2));
+
+ wsi->hdr_parsing_completed = wsi->mux_substream =
+ wsi->upgraded_to_http2 = wsi->mux_stream_immortal =
+ wsi->h2_acked_settings = wsi->seen_nonpseudoheader =
+ wsi->socket_is_permanently_unusable = wsi->favoured_pollin =
+ wsi->already_did_cce = wsi->told_user_closed =
+ wsi->waiting_to_send_close_frame = wsi->close_needs_ack =
+ wsi->parent_pending_cb_on_writable = wsi->seen_zero_length_recv =
+ wsi->close_when_buffered_out_drained = wsi->could_have_pending = 0;
+#endif
+
+#if defined(LWS_WITH_CLIENT)
+ wsi->do_ws = wsi->chunked = wsi->client_rx_avail =
+ wsi->client_http_body_pending = wsi->transaction_from_pipeline_queue =
+ wsi->keepalive_active = wsi->keepalive_rejected =
+ wsi->redirected_to_get = wsi->client_pipeline = wsi->client_h2_alpn =
+ wsi->client_mux_substream = wsi->client_mux_migrated =
+ wsi->tls_session_reused = wsi->perf_done = 0;
+
+ wsi->immortal_substream_count = 0;
+#endif
}
/* req cx lock */
@@ -194,17 +224,23 @@ __lws_free_wsi(struct lws *wsi)
}
#endif
+ vh = wsi->a.vhost;
+
__lws_reset_wsi(wsi);
__lws_wsi_remove_from_sul(wsi);
- vh = wsi->a.vhost;
+ if (vh)
+ /* this may destroy vh */
+ __lws_vhost_unbind_wsi(wsi); /* req cx + vh lock */
+
+#if defined(LWS_WITH_CLIENT)
+ if (wsi->stash)
+ lws_free_set_NULL(wsi->stash);
+#endif
if (wsi->a.context->event_loop_ops->destroy_wsi)
wsi->a.context->event_loop_ops->destroy_wsi(wsi);
- if (vh)
- __lws_vhost_unbind_wsi(wsi); /* req cx + vh lock */
-
lwsl_debug("%s: %s, tsi fds count %d\n", __func__,
lws_wsi_tag(wsi),
wsi->a.context->pt[(int)wsi->tsi].fds_count);
@@ -339,6 +375,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
#if defined(LWS_WITH_CLIENT)
lws_free_set_NULL(wsi->cli_hostname_copy);
+ wsi->client_mux_substream_was = wsi->client_mux_substream;
lws_addrinfo_clean(wsi);
#endif
@@ -407,7 +444,8 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
#endif
#if defined(LWS_WITH_CLIENT)
- lws_free_set_NULL(wsi->stash);
+ if (!wsi->close_is_redirect)
+ lws_free_set_NULL(wsi->stash);
#endif
if (wsi->role_ops == &role_ops_raw_skt) {
@@ -565,7 +603,8 @@ just_kill_connection:
#endif
lwsi_state(wsi) == LRS_WAITING_DNS ||
lwsi_state(wsi) == LRS_WAITING_CONNECT) &&
- !wsi->already_did_cce && wsi->a.protocol) {
+ !wsi->already_did_cce && wsi->a.protocol &&
+ !wsi->close_is_redirect) {
static const char _reason[] = "closed before established";
lwsl_debug("%s: closing in unestablished state 0x%x\n",
@@ -624,6 +663,9 @@ just_kill_connection:
#if !defined(_WIN32_WCE) && !defined(LWS_PLAT_FREERTOS)
/* libuv: no event available to guarantee completion */
if (!wsi->socket_is_permanently_unusable &&
+#if defined(LWS_WITH_CLIENT)
+ !wsi->close_is_redirect &&
+#endif
lws_socket_is_valid(wsi->desc.sockfd) &&
lwsi_state(wsi) != LRS_SHUTDOWN &&
(context->event_loop_ops->flags & LELOF_ISPOLL)) {
@@ -696,7 +738,7 @@ just_kill_connection:
/*
* He's a guy who go started with dns, but failed or is
* caught with a shutdown before he got the result. We have
- * to issue him a close cb
+ * to issclient_mux_substream_wasue him a close cb
*/
ccb = 1;
@@ -712,12 +754,17 @@ just_kill_connection:
ccb = 0;
#if defined(LWS_WITH_CLIENT)
- if (!ccb && (lwsi_state_PRE_CLOSE(wsi) & LWSIFS_NOT_EST) &&
+ if (!wsi->close_is_redirect && !ccb &&
+ (lwsi_state_PRE_CLOSE(wsi) & LWSIFS_NOT_EST) &&
lwsi_role_client(wsi)) {
lws_inform_client_conn_fail(wsi, "Closed before conn", 18);
}
#endif
- if (ccb) {
+ if (ccb
+#if defined(LWS_WITH_CLIENT)
+ && !wsi->close_is_redirect
+#endif
+ ) {
if (!wsi->a.protocol && wsi->a.vhost && wsi->a.vhost->protocols)
pro = &wsi->a.vhost->protocols[0];
@@ -831,9 +878,79 @@ __lws_close_free_wsi_final(struct lws *wsi)
#endif
sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd);
+ }
+
+ wsi->desc.sockfd = LWS_SOCK_INVALID;
+
+#if defined(LWS_WITH_CLIENT)
+ if (wsi->close_is_redirect) {
+
+ wsi->close_is_redirect = 0;
+
+ lwsl_info("%s: picking up redirection %s\n", __func__,
+ wsi->lc.gutag);
+
+ lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
+ &role_ops_h1);
+
+#if defined(LWS_WITH_HTTP2)
+ if (wsi->client_mux_substream_was)
+ wsi->h2.END_STREAM = wsi->h2.END_HEADERS = 0;
+#endif
+#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
+ if (wsi->mux.parent_wsi) {
+ lws_wsi_mux_sibling_disconnect(wsi);
+ wsi->mux.parent_wsi = NULL;
+ }
+#endif
+
+#if defined(LWS_WITH_TLS)
+ memset(&wsi->tls, 0, sizeof(wsi->tls));
+#endif
+
+ // wsi->a.protocol = NULL;
+ if (wsi->a.protocol)
+ lws_bind_protocol(wsi, wsi->a.protocol, "client_reset");
+ wsi->pending_timeout = NO_PENDING_TIMEOUT;
+ wsi->hdr_parsing_completed = 0;
- wsi->desc.sockfd = LWS_SOCK_INVALID;
+#if defined(LWS_WITH_TLS)
+ if (wsi->stash->cis[CIS_ALPN])
+ lws_strncpy(wsi->alpn, wsi->stash->cis[CIS_ALPN],
+ sizeof(wsi->alpn));
+#endif
+
+ if (lws_header_table_attach(wsi, 0)) {
+ lwsl_err("%s: failed to get ah\n", __func__);
+ return;
+ }
+// }
+ //_lws_header_table_reset(wsi->http.ah);
+
+#if defined(LWS_WITH_TLS)
+ wsi->tls.use_ssl = wsi->flags & LCCSCF_USE_SSL;
+#endif
+
+#if defined(LWS_WITH_TLS_JIT_TRUST)
+ if (wsi->stash && wsi->stash->cis[CIS_ADDRESS]) {
+ struct lws_vhost *vh = NULL;
+ lws_tls_jit_trust_vhost_bind(wsi->a.context,
+ wsi->stash->cis[CIS_ADDRESS],
+ &vh);
+ if (vh) {
+ if (!vh->count_bound_wsi && vh->grace_after_unref) {
+ lwsl_info("%s: %s: in use\n", __func__, vh->lc.gutag);
+ lws_sul_cancel(&vh->sul_unref);
+ }
+ vh->count_bound_wsi++;
+ wsi->a.vhost = vh;
+ }
+ }
+#endif
+
+ return;
}
+#endif
/* outermost destroy notification for wsi (user_space still intact) */
if (wsi->a.vhost)
diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h
index eec38e60..38073bae 100644
--- a/lib/core-net/private-lib-core-net.h
+++ b/lib/core-net/private-lib-core-net.h
@@ -540,7 +540,7 @@ struct lws_vhost {
#endif
#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
- int8_t ss_refcount;
+ int8_t ss_refcount;
/**< refcount of number of ss connections with streamtypes using this
* trust store */
#endif
@@ -742,6 +742,7 @@ struct lws {
#if defined(LWS_WITH_TLS)
struct lws_lws_tls tls;
+ char alpn[24];
#endif
lws_sock_file_fd_type desc; /* .filefd / .sockfd */
@@ -759,6 +760,8 @@ struct lws {
#endif
unsigned int cache_secs;
+ short bugcatcher;
+
unsigned int hdr_parsing_completed:1;
unsigned int mux_substream:1;
unsigned int upgraded_to_http2:1;
@@ -837,6 +840,8 @@ struct lws {
* this activity, and will report the failure */
unsigned int tls_session_reused:1;
unsigned int perf_done:1;
+ unsigned int close_is_redirect:1;
+ unsigned int client_mux_substream_was:1;
#endif
#ifdef _WIN32
@@ -1351,6 +1356,9 @@ __lws_same_vh_protocol_remove(struct lws *wsi);
void
lws_same_vh_protocol_insert(struct lws *wsi, int n);
+int
+lws_client_stash_create(struct lws *wsi, const char **cisin);
+
void
lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt);
diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c
index 5e751a21..7654faaf 100644
--- a/lib/core-net/vhost.c
+++ b/lib/core-net/vhost.c
@@ -557,6 +557,7 @@ lws_create_vhost(struct lws_context *context,
#endif
struct lws_protocols *lwsp;
int m, f = !info->pvo, fx = 0, abs_pcol_count = 0, sec_pcol_count = 0;
+ const char *name = "default";
char buf[96];
char *p;
#if defined(LWS_WITH_SYS_ASYNC_DNS)
@@ -564,10 +565,13 @@ lws_create_vhost(struct lws_context *context,
#endif
int n;
+ if (info->vhost_name)
+ name = info->vhost_name;
+
if (lws_fi(&info->fic, "vh_create_oom"))
vh = NULL;
else
- vh = lws_zalloc(sizeof(*vh)
+ vh = lws_zalloc(sizeof(*vh) + strlen(name) + 1
#if defined(LWS_WITH_EVENT_LIBS)
+ context->event_loop_ops->evlib_size_vh
#endif
@@ -577,7 +581,12 @@ lws_create_vhost(struct lws_context *context,
#if defined(LWS_WITH_EVENT_LIBS)
vh->evlib_vh = (void *)&vh[1];
+ vh->name = (const char *)vh->evlib_vh +
+ context->event_loop_ops->evlib_size_vh;
+#else
+ vh->name = (const char *)&vh[1];
#endif
+ memcpy((char *)vh->name, name, strlen(name) + 1);
#if LWS_MAX_SMP > 1
lws_mutex_refcount_init(&vh->mr);
@@ -587,10 +596,6 @@ lws_create_vhost(struct lws_context *context,
pcols = &protocols_dummy[0];
vh->context = context;
- if (!info->vhost_name)
- vh->name = "default";
- else
- vh->name = info->vhost_name;
{
char *end = buf + sizeof(buf) - 1;
p = buf;
diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c
index e67a98be..07d60554 100644
--- a/lib/core-net/wsi.c
+++ b/lib/core-net/wsi.c
@@ -43,10 +43,12 @@ void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)
{
- wsi->wsistate = (wsi->wsistate & (unsigned int)(~LRS_MASK)) | lrs;
+ lws_wsi_state_t old = wsi->wsistate;
- lwsl_debug("lwsi_set_state(%s, 0x%lx)\n", lws_wsi_tag(wsi),
- (unsigned long)wsi->wsistate);
+ wsi->wsistate = (old & (unsigned int)(~LRS_MASK)) | lrs;
+
+ lwsl_debug("lwsi_set_state(%s): 0x%lx -> 0x%lx)\n", lws_wsi_tag(wsi),
+ (unsigned long)old, (unsigned long)wsi->wsistate);
}
#endif
@@ -56,6 +58,7 @@ lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi)
{
if (wsi->a.vhost == vh)
return;
+
lws_context_lock(vh->context, __func__); /* ---------- context { */
wsi->a.vhost = vh;
@@ -68,6 +71,7 @@ lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi)
vh->count_bound_wsi++;
lws_context_unlock(vh->context); /* } context ---------- */
+
lwsl_debug("%s: vh %s: wsi %s/%s, count_bound_wsi %d\n", __func__,
vh->name, wsi->role_ops ? wsi->role_ops->name : "none",
wsi->a.protocol ? wsi->a.protocol->name : "none",