From 440cfeee71829308fa1cc9b5aef63beb7ab756dc Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Sat, 31 Oct 2026 01:24:18 +0100 Subject: Refactor all tcp specific code into the ot_tcp module to prepare for multiple concurrent workers --- opentracker.c | 143 ++-------------------------------------------------------- 1 file changed, 4 insertions(+), 139 deletions(-) (limited to 'opentracker.c') diff --git a/opentracker.c b/opentracker.c index b47759e..2eaf988 100644 --- a/opentracker.c +++ b/opentracker.c @@ -35,6 +35,7 @@ #include "ot_fdstate.h" #include "ot_socket.h" #include "ot_stats.h" +#include "ot_tcp.h" #include "ot_udp.h" #include "trackerlogic.h" @@ -96,142 +97,6 @@ static void install_signal_handlers(void) { } -static ssize_t header_complete(char *request, ssize_t byte_count) { - ssize_t i = 0, state = 0; - - for (i = 1; i < byte_count; i += 2) - if (request[i] <= 13) { - i--; - for (state = 0; i < byte_count; ++i) { - char c = request[i]; - if (c == '\r' || c == '\n') - state = (state >> 2) | ((c << 6) & 0xc0); - else - break; - if (state >= 0xa0 || state == 0x99) - return i + 1; - } - } - return 0; -} - -static void handle_read(const int64_t sock, struct ot_workstruct *ws) { - struct http_data *cookie = fdstate_cookie(sock); - ssize_t byte_count = read((int)sock, ws->inbuf, G_INBUF_SIZE); - - if (byte_count == 0 || (byte_count == -1 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)) { - http_close(sock); - return; - } - - if (byte_count == -1) - return; - - ws->request = NULL; - ws->request_size = 0; - ws->header_size = 0; - ws->keep_alive = 0; - - /* If we get the whole request in one packet, handle it without copying */ - if (!cookie->request.data) { - if ((ws->header_size = header_complete(ws->inbuf, byte_count))) { - ws->request = ws->inbuf; - ws->request_size = byte_count; - http_handle_request(sock, ws); - } else if (buf_cat(&cookie->request, ws->inbuf, (size_t)byte_count)) - http_close(sock); - return; - } - - if (buf_cat(&cookie->request, ws->inbuf, (size_t)byte_count) || cookie->request.size > G_INBUF_SIZE) { - http_issue_error(sock, ws, CODE_HTTPERROR_500); - return; - } - - while ((ws->header_size = header_complete(cookie->request.data, (ssize_t)cookie->request.size))) { - ws->request = cookie->request.data; - ws->request_size = (ssize_t)cookie->request.size; - http_handle_request(sock, ws); -#ifdef WANT_KEEPALIVE - if (!ws->keep_alive) -#endif - return; - } -} - -static void handle_write(const int64_t sock) { - struct http_data *cookie = fdstate_cookie(sock); - int chunked = 0; - int keep_alive = 0; - - if (cookie) { - 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) { - http_close(sock); - return; - } - if (batch_pending(cookie->batch)) - return; - } - } - - /* In a chunked transfer, wait for the next piece once everything queued has gone out */ - if (chunked) - http_interest_set(sock, cookie, 0); - else if (keep_alive) { - /* The reply is out and the client asked to keep the connection, so go - back to waiting for the next request */ - http_interest_set(sock, cookie, EVENT_IN); - fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT)); - } else - http_close(sock); -} - -/* The fast path, assuming that the complete request has usually arrived by the time a - connection is accepted, so it is answered here outside the event loop. The more load - a tracker has, the more likely it is that by the time it accepts, the roundtrip to - the peer has completed. - If the request could not be completely handled, the stack cookie is promoted to heap - and the connection handed over to the event loop to finish */ -static void handle_accept(const int64_t serversocket, struct ot_workstruct *ws) { - int64_t sock; - ot_ip6 ip; - uint16_t port; - - while ((sock = socket_accept(serversocket, ip, &port)) != -1) { - struct http_data cookie; - uint32_t generation; - - memset(&cookie, 0, sizeof(cookie)); - memcpy(cookie.ip, ip, sizeof(ot_ip6)); - cookie.interest = EVENT_IN; - cookie.flag = STRUCT_HTTP_FLAG_ONSTACK; - - generation = fdstate_open(sock, &cookie, time_future_seconds(OT_CLIENT_TIMEOUT)); - if (!fdstate_claim((int)sock, generation)) { - fdstate_close(sock); - event_close((int)sock); - continue; - } - - stats_issue_event(ws, EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip); - - handle_read(sock, ws); - - /* Gone already if it was answered and closed inline */ - if (fdstate_generation((int)sock) != generation) - continue; - - if (http_adopt(sock, &cookie) == -1) - http_close(sock); - else - fdstate_release((int)sock); - } -} - /* How many ready descriptors one wait hands back at a time */ #define OT_EVENT_BATCH 512 @@ -277,7 +142,7 @@ static void *server_mainloop(void *args) { cookie = fdstate_cookie((int)sock); if ((intptr_t)cookie == FLAG_TCP) - handle_accept(sock, &ws); + tcp_accept(sock, &ws); else if ((intptr_t)cookie == FLAG_UDP) handle_udp6(sock, &ws); else if ((intptr_t)cookie == FLAG_SELFPIPE) @@ -285,10 +150,10 @@ static void *server_mainloop(void *args) { ; else { if (ready[i].what & EVENT_IN) - handle_read(sock, &ws); + tcp_read(sock, &ws); /* The read may have closed it, so look again before writing */ if ((ready[i].what & EVENT_OUT) && fdstate_generation((int)sock) == ready[i].generation) - handle_write(sock); + tcp_write(sock); } } -- cgit v1.3