Skip to content

Commit b1c0e74

Browse files
google-labs-jules[bot]lws-team
authored andcommitted
Fix race condition in http reverse proxy for websockets
When a WebSocket connection is established through the lws http reverse proxy, the LWS_CALLBACK_ESTABLISHED callback was being called immediately. Under load, this could lead to a race condition where the user code would write to the socket before the connection was fully established on the other side of the proxy, causing the connection to be dropped. This patch fixes the issue by deferring the LWS_CALLBACK_ESTABLISHED callback for proxied WebSocket connections. An lws_sul is added in order to ensure the caller completed setting up the proxy connection before we try to do anything with it.
1 parent 9e9367b commit b1c0e74

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

lib/core-net/private-lib-core-net.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,9 @@ struct lws {
669669
lws_sorted_usec_list_t sul_timeout;
670670
lws_sorted_usec_list_t sul_hrtimer;
671671
lws_sorted_usec_list_t sul_validity;
672+
#if defined(LWS_WITH_HTTP_PROXY)
673+
lws_sorted_usec_list_t sul_ws_proxy_est;
674+
#endif
672675
lws_sorted_usec_list_t sul_connect_timeout;
673676
#if defined(WIN32)
674677
lws_sorted_usec_list_t win32_sul_connect_async_check;

lib/core-net/wsi-timeout.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ __lws_wsi_remove_from_sul(struct lws *wsi)
3030
lws_sul_cancel(&wsi->sul_timeout);
3131
lws_sul_cancel(&wsi->sul_hrtimer);
3232
lws_sul_cancel(&wsi->sul_validity);
33+
#if defined(LWS_WITH_HTTP_PROXY)
34+
lws_sul_cancel(&wsi->sul_ws_proxy_est);
35+
#endif
3336
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
3437
lws_sul_cancel(&wsi->sul_fault_timedclose);
3538
#endif

lib/roles/ws/ops-ws.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@
2424

2525
#include <private-lib-core.h>
2626

27+
#if defined(LWS_WITH_HTTP_PROXY)
28+
static void
29+
lws_ws_proxy_est_cb(lws_sorted_usec_list_t *sul)
30+
{
31+
struct lws *wsi = lws_container_of(sul, struct lws, sul_ws_proxy_est);
32+
33+
if (wsi->a.protocol->callback)
34+
if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
35+
wsi->user_space,
36+
#ifdef LWS_WITH_TLS
37+
wsi->tls.ssl,
38+
#else
39+
NULL,
40+
#endif
41+
wsi->h2_stream_carries_ws))
42+
lws_wsi_close(wsi, LWS_TO_KILL_ASYNC);
43+
}
44+
#endif
45+
2746
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
2847

2948
/*
@@ -861,7 +880,15 @@ lws_server_init_wsi_for_ws(struct lws *wsi)
861880

862881
/* notify user code that we're ready to roll */
863882

864-
if (wsi->a.protocol->callback)
883+
if (wsi->a.protocol->callback) {
884+
#if defined(LWS_WITH_HTTP_PROXY)
885+
if (wsi->proxied_ws_parent) {
886+
lws_sul_schedule(wsi->a.context, wsi->tsi,
887+
&wsi->sul_ws_proxy_est,
888+
lws_ws_proxy_est_cb, 5000);
889+
goto validity;
890+
}
891+
#endif
865892
if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
866893
wsi->user_space,
867894
#ifdef LWS_WITH_TLS
@@ -871,6 +898,10 @@ lws_server_init_wsi_for_ws(struct lws *wsi)
871898
#endif
872899
wsi->h2_stream_carries_ws))
873900
return 1;
901+
}
902+
#if defined(LWS_WITH_HTTP_PROXY)
903+
validity:
904+
#endif
874905

875906
lws_validity_confirmed(wsi);
876907
lwsl_debug("ws established\n");

0 commit comments

Comments
 (0)