diff --git a/lib/misc/peer-limits.c b/lib/misc/peer-limits.c index 707454fe..2fcb8bb8 100644 --- a/lib/misc/peer-limits.c +++ b/lib/misc/peer-limits.c @@ -248,7 +248,9 @@ lws_peer_track_ah_detach(struct lws_context *context, struct lws_peer *peer) if (!peer) return; + lws_context_lock(context); /* <====================================== */ assert(peer->count_ah); peer->count_ah--; + lws_context_unlock(context); /* ====================================> */ } diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index c6ab7539..965da436 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1675,7 +1675,7 @@ lws_client_reset(struct lws **wsi, int ssl, const char *address, int port, const char *path, const char *host); LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT -lws_create_new_server_wsi(struct lws_vhost *vhost); +lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi); LWS_EXTERN char * LWS_WARN_UNUSED_RESULT lws_generate_client_handshake(struct lws *wsi, char *pkt); diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 69e248b8..b0a45578 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -175,7 +175,7 @@ lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi, lwsl_notice("reached concurrent stream limit\n"); return NULL; } - wsi = lws_create_new_server_wsi(vh); + wsi = lws_create_new_server_wsi(vh, parent_wsi->tsi); if (!wsi) { lwsl_notice("new server wsi failed (vh %p)\n", vh); return NULL; diff --git a/lib/roles/http/server/parsers.c b/lib/roles/http/server/parsers.c index 4546cefd..67c8dd60 100644 --- a/lib/roles/http/server/parsers.c +++ b/lib/roles/http/server/parsers.c @@ -298,8 +298,7 @@ int __lws_header_table_detach(struct lws *wsi, int autoservice) * unreasonably long time */ lwsl_debug("%s: wsi %p: ah held %ds, role/state 0x%x 0x%x," - "\n", __func__, wsi, - (int)(now - ah->assigned), + "\n", __func__, wsi, (int)(now - ah->assigned), lwsi_role(wsi), lwsi_state(wsi)); } @@ -310,10 +309,12 @@ int __lws_header_table_detach(struct lws *wsi, int autoservice) /* and this specific one should have been in use */ assert(ah->in_use); memset(&wsi->ah, 0, sizeof(wsi->ah)); - ah->wsi = NULL; /* no owner */ + #if defined(LWS_WITH_PEER_LIMITS) - lws_peer_track_ah_detach(context, wsi->peer); + if (ah->wsi) + lws_peer_track_ah_detach(context, wsi->peer); #endif + ah->wsi = NULL; /* no owner */ pwsi = &pt->ah_wait_list; @@ -357,8 +358,10 @@ int __lws_header_table_detach(struct lws *wsi, int autoservice) __lws_header_table_reset(wsi, autoservice); #if defined(LWS_WITH_PEER_LIMITS) + lws_context_lock(context); /* <====================================== */ if (wsi->peer) wsi->peer->count_ah++; + lws_context_unlock(context); /* ====================================> */ #endif /* clients acquire the ah and then insert themselves in fds table... */ diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index d4ec9ebc..fac864e7 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1644,10 +1644,13 @@ lws_get_idlest_tsi(struct lws_context *context) } struct lws * -lws_create_new_server_wsi(struct lws_vhost *vhost) +lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi) { struct lws *new_wsi; - int n = lws_get_idlest_tsi(vhost->context); + int n = fixed_tsi; + + if (n < 0) + n = lws_get_idlest_tsi(vhost->context); if (n < 0) { lwsl_err("no space for new conn\n"); @@ -1840,7 +1843,10 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type, } #endif - new_wsi = lws_create_new_server_wsi(vh); + n = -1; + if (parent) + n = parent->tsi; + new_wsi = lws_create_new_server_wsi(vh, n); if (!new_wsi) { if (type & LWS_ADOPT_SOCKET && !(type & LWS_ADOPT_WS_PARENTIO)) compatible_close(fd.sockfd);