From e686e477e21dc59ccc9c927f9e2bfce6d8e8f59e Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Wed, 3 Dec 2025 18:40:14 +0100 Subject: [PATCH] Ignore socket events when an HTTP response is being built by the user --- chttp.c | 26 ++++++++++++++++++++++++++ chttp.h | 6 ++++++ src/server.c | 6 ++++++ src/socket.c | 20 ++++++++++++++++++++ src/socket.h | 6 ++++++ 5 files changed, 64 insertions(+) diff --git a/chttp.c b/chttp.c index 9d76058..7c5465c 100644 --- a/chttp.c +++ b/chttp.c @@ -2676,6 +2676,9 @@ void socket_manager_register_events( continue; j++; + if (s->silent) + continue; + // If at least one socket can be processed, return an // empty list. if (s->state == SOCKET_STATE_DIED || s->state == SOCKET_STATE_ESTABLISHED_READY) { @@ -2754,6 +2757,7 @@ int socket_manager_translate_events( s->sock = sock; s->events = 0; s->user = NULL; + s->silent = false; #ifdef HTTPS_ENABLED // Determine whether the event came from // the encrypted listener or not. @@ -2789,7 +2793,10 @@ int socket_manager_translate_events( #endif } else { + Socket *s = reg.ptrs[i]; + assert(!s->silent); + socket_update(s); } } @@ -2800,6 +2807,9 @@ int socket_manager_translate_events( continue; j++; + if (s->silent) + continue; + if (s->state == SOCKET_STATE_DIED) { events[num_events++] = (SocketEvent) { @@ -2989,6 +2999,7 @@ int socket_connect(SocketManager *sm, int num_targets, UPDATE_STATE(s->state, SOCKET_STATE_PENDING); s->sock = NATIVE_SOCKET_INVALID; s->user = user; + s->silent = false; #ifdef HTTPS_ENABLED s->server_secure_context = NULL; s->client_secure_context = NULL; @@ -3173,6 +3184,15 @@ bool socket_ready(SocketManager *sm, SocketHandle handle) return false; } +void socket_silent(SocketManager *sm, SocketHandle handle, bool value) +{ + Socket *s = handle_to_socket(sm, handle); + if (s == NULL) + return; + + s->silent = value; +} + //////////////////////////////////////////////////////////////////////////////////////// // src/byte_queue.c //////////////////////////////////////////////////////////////////////////////////////// @@ -4592,6 +4612,9 @@ check_request_buffer(HTTP_Server *server, HTTP_ServerConn *conn) // Ready assert(ret > 0); + // Stop receiving I/O events while we are building the response + socket_silent(&server->sockets, conn->handle, true); + conn->state = HTTP_SERVER_CONN_WAIT_STATUS; conn->request_len = ret; conn->response_offset = byte_queue_offset(&conn->output); @@ -5022,6 +5045,9 @@ void http_response_builder_send(HTTP_ResponseBuilder builder) conn->state = HTTP_SERVER_CONN_FLUSHING; conn->gen++; + // Enable back I/O events + socket_silent(&builder.server->sockets, conn->handle, false); + http_server_conn_process_events(builder.server, conn); } diff --git a/chttp.h b/chttp.h index 3c0b911..2a82e2f 100644 --- a/chttp.h +++ b/chttp.h @@ -481,6 +481,9 @@ typedef struct { // Native socket events that need to be monitored int events; + // If this is set, the raw socket handle shouldn't be monitored + bool silent; + // Generation counter to invalidate any SocketHandle // referring to this socket when it is freed. // Note that this counter may wrap but always skips @@ -668,6 +671,9 @@ void socket_set_user(SocketManager *sm, SocketHandle handle, void *user); // writing. bool socket_ready(SocketManager *sm, SocketHandle handle); +// When a socket is marked as silent it will not generate events +void socket_silent(SocketManager *sm, SocketHandle handle, bool value); + //////////////////////////////////////////////////////////////////////////////////////// // src/byte_queue.h //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/server.c b/src/server.c index 10be1d0..9fff397 100644 --- a/src/server.c +++ b/src/server.c @@ -144,6 +144,9 @@ check_request_buffer(HTTP_Server *server, HTTP_ServerConn *conn) // Ready assert(ret > 0); + // Stop receiving I/O events while we are building the response + socket_silent(&server->sockets, conn->handle, true); + conn->state = HTTP_SERVER_CONN_WAIT_STATUS; conn->request_len = ret; conn->response_offset = byte_queue_offset(&conn->output); @@ -574,5 +577,8 @@ void http_response_builder_send(HTTP_ResponseBuilder builder) conn->state = HTTP_SERVER_CONN_FLUSHING; conn->gen++; + // Enable back I/O events + socket_silent(&builder.server->sockets, conn->handle, false); + http_server_conn_process_events(builder.server, conn); } diff --git a/src/socket.c b/src/socket.c index 319c078..d88acc7 100644 --- a/src/socket.c +++ b/src/socket.c @@ -744,6 +744,9 @@ void socket_manager_register_events( continue; j++; + if (s->silent) + continue; + // If at least one socket can be processed, return an // empty list. if (s->state == SOCKET_STATE_DIED || s->state == SOCKET_STATE_ESTABLISHED_READY) { @@ -822,6 +825,7 @@ int socket_manager_translate_events( s->sock = sock; s->events = 0; s->user = NULL; + s->silent = false; #ifdef HTTPS_ENABLED // Determine whether the event came from // the encrypted listener or not. @@ -857,7 +861,10 @@ int socket_manager_translate_events( #endif } else { + Socket *s = reg.ptrs[i]; + assert(!s->silent); + socket_update(s); } } @@ -868,6 +875,9 @@ int socket_manager_translate_events( continue; j++; + if (s->silent) + continue; + if (s->state == SOCKET_STATE_DIED) { events[num_events++] = (SocketEvent) { @@ -1057,6 +1067,7 @@ int socket_connect(SocketManager *sm, int num_targets, UPDATE_STATE(s->state, SOCKET_STATE_PENDING); s->sock = NATIVE_SOCKET_INVALID; s->user = user; + s->silent = false; #ifdef HTTPS_ENABLED s->server_secure_context = NULL; s->client_secure_context = NULL; @@ -1240,3 +1251,12 @@ bool socket_ready(SocketManager *sm, SocketHandle handle) return false; } + +void socket_silent(SocketManager *sm, SocketHandle handle, bool value) +{ + Socket *s = handle_to_socket(sm, handle); + if (s == NULL) + return; + + s->silent = value; +} diff --git a/src/socket.h b/src/socket.h index c1b21ac..adaf4e5 100644 --- a/src/socket.h +++ b/src/socket.h @@ -149,6 +149,9 @@ typedef struct { // Native socket events that need to be monitored int events; + // If this is set, the raw socket handle shouldn't be monitored + bool silent; + // Generation counter to invalidate any SocketHandle // referring to this socket when it is freed. // Note that this counter may wrap but always skips @@ -335,3 +338,6 @@ void socket_set_user(SocketManager *sm, SocketHandle handle, void *user); // Returns true iff the socket is ready for reading or // writing. bool socket_ready(SocketManager *sm, SocketHandle handle); + +// When a socket is marked as silent it will not generate events +void socket_silent(SocketManager *sm, SocketHandle handle, bool value);