Skip to content

Commit 56a1d4b

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 56a1d4b

4 files changed

Lines changed: 45 additions & 3 deletions

File tree

lib/core-net/dummy-callback.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason,
125125
* If the parent has started to close, don't try to
126126
* upgrade it, just let it go.
127127
*/
128-
if (lwsi_state(wsi->parent) >= LRS_RETURNED_CLOSE)
128+
if ((lwsi_state(wsi->parent) & 0xff) >= LRS_RETURNED_CLOSE)
129129
return -1;
130130

131131
if (lws_process_ws_upgrade2(wsi->parent))

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: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,27 @@
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+
lwsi_set_state(wsi, LRS_ESTABLISHED);
34+
35+
if (wsi->a.protocol->callback)
36+
if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
37+
wsi->user_space,
38+
#ifdef LWS_WITH_TLS
39+
wsi->tls.ssl,
40+
#else
41+
NULL,
42+
#endif
43+
wsi->h2_stream_carries_ws))
44+
lws_wsi_close(wsi, LWS_TO_KILL_ASYNC);
45+
}
46+
#endif
47+
2748
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
2849

2950
/*
@@ -840,7 +861,10 @@ lws_server_init_wsi_for_ws(struct lws *wsi)
840861
{
841862
int n;
842863

843-
lwsi_set_state(wsi, LRS_ESTABLISHED);
864+
#if defined(LWS_WITH_HTTP_PROXY)
865+
if (!wsi->proxied_ws_parent)
866+
lwsi_set_state(wsi, LRS_ESTABLISHED);
867+
#endif
844868

845869
/*
846870
* create the frame buffer for this connection according to the
@@ -861,7 +885,15 @@ lws_server_init_wsi_for_ws(struct lws *wsi)
861885

862886
/* notify user code that we're ready to roll */
863887

864-
if (wsi->a.protocol->callback)
888+
if (wsi->a.protocol->callback) {
889+
#if defined(LWS_WITH_HTTP_PROXY)
890+
if (wsi->proxied_ws_parent) {
891+
lws_sul_schedule(wsi->a.context, wsi->tsi,
892+
&wsi->sul_ws_proxy_est,
893+
lws_ws_proxy_est_cb, 5000);
894+
goto validity;
895+
}
896+
#endif
865897
if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
866898
wsi->user_space,
867899
#ifdef LWS_WITH_TLS
@@ -871,6 +903,10 @@ lws_server_init_wsi_for_ws(struct lws *wsi)
871903
#endif
872904
wsi->h2_stream_carries_ws))
873905
return 1;
906+
}
907+
#if defined(LWS_WITH_HTTP_PROXY)
908+
validity:
909+
#endif
874910

875911
lws_validity_confirmed(wsi);
876912
lwsl_debug("ws established\n");

0 commit comments

Comments
 (0)