From fa0f7ee6dba3ba14a6fc1172e04a161f514d94b0 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Tue, 27 Oct 2026 03:05:43 +0100 Subject: Revive http keep alive to save tcp connection setup costs --- opentracker.c | 17 ++++++++++++----- ot_http.c | 26 ++++++++++++++++++-------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/opentracker.c b/opentracker.c index 21eeb42..11da486 100644 --- a/opentracker.c +++ b/opentracker.c @@ -177,12 +177,13 @@ static void handle_read(const int64_t sock, struct ot_workstruct *ws) { } static void handle_write(const int64_t sock) { - struct http_data *cookie = fdstate_cookie(sock); - int chunked = 0; + struct http_data *cookie = fdstate_cookie(sock); + int chunked = 0; + int keep_alive = 0; if (cookie) { - if (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) - chunked = 1; + chunked = (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) != 0; + keep_alive = (cookie->flag & STRUCT_HTTP_FLAG_KEEPALIVE) != 0; if (cookie->batch) { if (batch_send(sock, cookie->batch) == BATCH_FAILED) { @@ -197,7 +198,13 @@ static void handle_write(const int64_t sock) { /* In a chunked transfer, wait for the next piece once everything queued has gone out */ if (chunked) http_interest_drop(sock, cookie, EVENT_OUT); - else + else if (keep_alive) { + /* The reply is out and the client asked to keep the connection, so stop + waiting to write and go back to waiting for the next request */ + http_interest_drop(sock, cookie, EVENT_OUT); + http_interest_add(sock, cookie, EVENT_IN); + fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT); + } else handle_dead(sock); } diff --git a/ot_http.c b/ot_http.c index 36819c7..14952b5 100644 --- a/ot_http.c +++ b/ot_http.c @@ -727,6 +727,24 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { /* Tell subroutines where to put reply data */ ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH; + /* Find out if the client wants to keep this connection alive, before any + subroutine gets to answer: an error reply finishes with the connection + on its way out, and ws outlives the connection it was serving */ + ws->keep_alive = 0; +#ifdef WANT_KEEPALIVE + if ((write_ptr = http_header(ws->request, ws->header_size, "connection")) && (*write_ptr == 'K' || *write_ptr == 'k')) + ws->keep_alive = 1; +#endif + { + struct http_data *connection = fdstate_cookie(sock); + if (connection) { + if (ws->keep_alive) + connection->flag |= STRUCT_HTTP_FLAG_KEEPALIVE; + else + connection->flag &= ~STRUCT_HTTP_FLAG_KEEPALIVE; + } + } + /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ if (memcmp(read_ptr, "GET /", 5)) HTTPERROR_400; @@ -763,14 +781,6 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { else HTTPERROR_404; - /* Find out if the client wants to keep this connection alive */ - ws->keep_alive = 0; -#ifdef WANT_KEEPALIVE - read_ptr = http_header(ws->request, ws->header_size, "connection"); - if (read_ptr && (*read_ptr == 'K' || *read_ptr == 'k')) - ws->keep_alive = 1; -#endif - /* If routines handled sending themselves, just return */ if (ws->reply_size == -2) return 0; -- cgit v1.3