From ca9b8388260032ffe79824ff0f2b5cadfc2459bd Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 4 Aug 2026 11:18:43 +0000 Subject: [PATCH] fix(webchat): align WebSocket payload limit with agent response buffer Raise WS_TEXT_MAX to 32KiB to match dispatch RESPONSE_BUF_SIZE so agent replies between 8KiB and 32KiB are delivered instead of silently dropped. Co-authored-by: esadrianno --- src/channels/webchat.c | 2 +- src/gateway/http_lws.c | 4 ++-- src/gateway/ws.c | 4 +--- src/gateway/ws.h | 3 +++ tests/test_ws.c | 36 ++++++++++++++++++++++++++++-------- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/channels/webchat.c b/src/channels/webchat.c index 830273e..0aa356a 100644 --- a/src/channels/webchat.c +++ b/src/channels/webchat.c @@ -25,7 +25,7 @@ static int webchat_poll(channel_incoming_msg_t *out, int timeout_ms) if (!out) return -1; memset(out, 0, sizeof(*out)); char session_id[128]; - char text[8192]; + char text[WS_TEXT_MAX]; int r = ws_pop_incoming(session_id, sizeof(session_id), text, sizeof(text), timeout_ms); if (r != 1) return r; out->session_id = strdup(session_id); diff --git a/src/gateway/http_lws.c b/src/gateway/http_lws.c index c272284..da4bea1 100644 --- a/src/gateway/http_lws.c +++ b/src/gateway/http_lws.c @@ -493,10 +493,10 @@ int ws_callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_SERVER_WRITEABLE: { int conn_id = (int)(intptr_t)lws_wsi_user(wsi); if (conn_id <= 0) break; - char buf[8192]; + char buf[WS_TEXT_MAX]; size_t len_out = 0; if (ws_dequeue_outgoing(conn_id, buf, sizeof(buf), &len_out)) { - unsigned char frame[LWS_PRE + 8192]; + unsigned char frame[LWS_PRE + WS_TEXT_MAX]; if (len_out < sizeof(frame) - LWS_PRE) { memcpy(frame + LWS_PRE, buf, len_out); if (lws_write(wsi, frame + LWS_PRE, len_out, LWS_WRITE_TEXT) < 0) diff --git a/src/gateway/ws.c b/src/gateway/ws.c index 207b0fd..67f6cc0 100644 --- a/src/gateway/ws.c +++ b/src/gateway/ws.c @@ -23,14 +23,12 @@ static void lws_callback_on_writable(struct lws *wsi) { (void)wsi; } #define MAX_CONNECTIONS 16 #define MAX_QUEUE 64 -#define MSG_MAX 8192 - static size_t ws_text_len_ok(const char *text) { size_t len; if (!text) return 0; len = strlen(text); - return len > 0 && len <= (size_t)MSG_MAX; + return len > 0 && len <= (size_t)WS_TEXT_MAX; } typedef struct ws_msg { diff --git a/src/gateway/ws.h b/src/gateway/ws.h index b8b19e1..d80274a 100644 --- a/src/gateway/ws.h +++ b/src/gateway/ws.h @@ -12,6 +12,9 @@ extern "C" { #endif +/** Max WebSocket text payload (matches RESPONSE_BUF_SIZE in dispatch.c). */ +#define WS_TEXT_MAX (32 * 1024) + /** Opaque WebSocket connection handle (lws wsi cast to void*). */ typedef void *ws_conn_t; diff --git a/tests/test_ws.c b/tests/test_ws.c index 38cd7d4..86f8476 100644 --- a/tests/test_ws.c +++ b/tests/test_ws.c @@ -24,8 +24,27 @@ return _r; \ } while (0) -/** Must match MSG_MAX in src/gateway/ws.c */ -#define WS_MSG_MAX 8192 +/** Must match WS_TEXT_MAX in src/gateway/ws.h */ + +static int test_send_to_accepts_dispatch_sized_payload(void) +{ + char *payload; + char buf[WS_TEXT_MAX]; + size_t len_out; + ws_cleanup(); + ASSERT(ws_register_conn(3, (ws_conn_t)(intptr_t)3) == 0); + payload = malloc(10000); + ASSERT(payload != NULL); + memset(payload, 'c', 9999); + payload[9999] = '\0'; + ASSERT(ws_send_to("webchat:3", payload) == 0); + ASSERT(ws_dequeue_outgoing(3, buf, sizeof(buf), &len_out) == 1); + ASSERT(len_out == 9999); + ASSERT(memcmp(buf, payload, 9999) == 0); + free(payload); + ws_cleanup(); + return 0; +} static int test_register_conn_full_table(void) { @@ -46,10 +65,10 @@ static int test_push_incoming_msg_max(void) int got; ws_cleanup(); ASSERT(ws_register_conn(1, (ws_conn_t)(intptr_t)1) == 0); - big = malloc((size_t)WS_MSG_MAX + 2); + big = malloc((size_t)WS_TEXT_MAX + 2); ASSERT(big != NULL); - memset(big, 'a', (size_t)WS_MSG_MAX + 1); - big[WS_MSG_MAX + 1] = '\0'; + memset(big, 'a', (size_t)WS_TEXT_MAX + 1); + big[WS_TEXT_MAX + 1] = '\0'; ws_push_incoming(1, big); got = ws_pop_incoming(session, sizeof(session), text, sizeof(text), 50); ASSERT(got == 0); @@ -67,10 +86,10 @@ static int test_send_to_rejects_oversized(void) char *big; ws_cleanup(); ASSERT(ws_register_conn(2, (ws_conn_t)(intptr_t)2) == 0); - big = malloc((size_t)WS_MSG_MAX + 2); + big = malloc((size_t)WS_TEXT_MAX + 2); ASSERT(big != NULL); - memset(big, 'b', (size_t)WS_MSG_MAX + 1); - big[WS_MSG_MAX + 1] = '\0'; + memset(big, 'b', (size_t)WS_TEXT_MAX + 1); + big[WS_TEXT_MAX + 1] = '\0'; ASSERT(ws_send_to("webchat:2", big) != 0); ASSERT(ws_send_to("webchat:2", "hi") == 0); free(big); @@ -83,6 +102,7 @@ int main(void) RUN(test_register_conn_full_table()); RUN(test_push_incoming_msg_max()); RUN(test_send_to_rejects_oversized()); + RUN(test_send_to_accepts_dispatch_sized_payload()); printf("test_ws: all tests passed\n"); return 0; }