summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-30 13:17:39 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-30 13:17:39 +0100
commitcbf4b60df6c6c8c7208dc29708677d24b2724deb (patch)
tree8b4cec720c1fe6464309b1de6ba441fc4e2191c3
parent4b1264cb26a481faf8448322ebb19b8993ae6aaf (diff)
Enforce the invariant that each socket is only ever expected to be read from or written to, never both
-rw-r--r--opentracker.c9
-rw-r--r--ot_http.c27
-rw-r--r--ot_http.h5
3 files changed, 16 insertions, 25 deletions
diff --git a/opentracker.c b/opentracker.c
index b54327a..27b2570 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -180,12 +180,11 @@ static void handle_write(const int64_t sock) {
180 180
181 /* In a chunked transfer, wait for the next piece once everything queued has gone out */ 181 /* In a chunked transfer, wait for the next piece once everything queued has gone out */
182 if (chunked) 182 if (chunked)
183 http_interest_drop(sock, cookie, EVENT_OUT); 183 http_interest_set(sock, cookie, 0);
184 else if (keep_alive) { 184 else if (keep_alive) {
185 /* The reply is out and the client asked to keep the connection, so stop 185 /* The reply is out and the client asked to keep the connection, so go
186 waiting to write and go back to waiting for the next request */ 186 back to waiting for the next request */
187 http_interest_drop(sock, cookie, EVENT_OUT); 187 http_interest_set(sock, cookie, EVENT_IN);
188 http_interest_add(sock, cookie, EVENT_IN);
189 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT)); 188 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT));
190 } else 189 } else
191 http_close(sock); 190 http_close(sock);
diff --git a/ot_http.c b/ot_http.c
index e8ba3da..66f0102 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -118,11 +118,9 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
118 batch_add(cookie->batch, outbuf, ws->reply_size - written_size); 118 batch_add(cookie->batch, outbuf, ws->reply_size - written_size);
119 119
120 /* writeable short data sockets just have a tcp timeout */ 120 /* writeable short data sockets just have a tcp timeout */
121 if (!ws->keep_alive) { 121 if (!ws->keep_alive)
122 fdstate_set_expiry(sock, 0); 122 fdstate_set_expiry(sock, 0);
123 http_interest_drop(sock, cookie, EVENT_IN); 123 http_interest_set(sock, cookie, EVENT_OUT);
124 }
125 http_interest_add(sock, cookie, EVENT_OUT);
126 } 124 }
127} 125}
128 126
@@ -135,21 +133,16 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
135#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP) 133#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP)
136#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) 134#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404)
137#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500) 135#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500)
138static void http_interest(const int64_t sock, struct http_data *cookie, int what) { 136/* A connection is either being read or being written, never both, so what it
137 waits for is set outright rather than added to and taken away again. The
138 event layer only hears about it when the answer changes. */
139void http_interest_set(const int64_t sock, struct http_data *cookie, int what) {
139 if (cookie->interest == what) 140 if (cookie->interest == what)
140 return; 141 return;
141 cookie->interest = what; 142 cookie->interest = what;
142 event_modify((int)sock, what, fdstate_generation((int)sock)); 143 event_modify((int)sock, what, fdstate_generation((int)sock));
143} 144}
144 145
145void http_interest_add(const int64_t sock, struct http_data *cookie, int what) {
146 http_interest(sock, cookie, cookie->interest | what);
147}
148
149void http_interest_drop(const int64_t sock, struct http_data *cookie, int what) {
150 http_interest(sock, cookie, cookie->interest & ~what);
151}
152
153ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) { 146ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) {
154 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required", 147 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required",
155 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"}; 148 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"};
@@ -194,7 +187,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
194 187
195 /* If we came here, wait for the answer is over */ 188 /* If we came here, wait for the answer is over */
196 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) { 189 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) {
197 http_interest_drop(sock, cookie, EVENT_IN); 190 http_interest_set(sock, cookie, 0);
198 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; 191 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK;
199 } 192 }
200 193
@@ -245,7 +238,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
245 } 238 }
246 239
247 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT_SEND)); 240 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT_SEND));
248 http_interest_add(sock, cookie, EVENT_OUT); 241 http_interest_set(sock, cookie, EVENT_OUT);
249 return 0; 242 return 0;
250} 243}
251 244
@@ -340,7 +333,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
340 /* Clients waiting for us should not easily timeout */ 333 /* Clients waiting for us should not easily timeout */
341 fdstate_set_expiry(sock, 0); 334 fdstate_set_expiry(sock, 0);
342 fullscrape_deliver(sock, format); 335 fullscrape_deliver(sock, format);
343 http_interest_drop(sock, cookie, EVENT_IN); 336 http_interest_set(sock, cookie, 0);
344 return ws->reply_size = -2; 337 return ws->reply_size = -2;
345 } 338 }
346#endif 339#endif
@@ -435,7 +428,7 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
435 /* Clients waiting for us should not easily timeout */ 428 /* Clients waiting for us should not easily timeout */
436 fdstate_set_expiry(sock, 0); 429 fdstate_set_expiry(sock, 0);
437 fullscrape_deliver(sock, format); 430 fullscrape_deliver(sock, format);
438 http_interest_drop(sock, cookie, EVENT_IN); 431 http_interest_set(sock, cookie, 0);
439 return ws->reply_size = -2; 432 return ws->reply_size = -2;
440} 433}
441#endif 434#endif
diff --git a/ot_http.h b/ot_http.h
index 0f351c1..ba16de4 100644
--- a/ot_http.h
+++ b/ot_http.h
@@ -33,9 +33,8 @@ struct http_data {
33 STRUCT_HTTP_FLAG flag; 33 STRUCT_HTTP_FLAG flag;
34}; 34};
35 35
36/* Add to or drop from what this connection is waiting to be told about */ 36/* What this connection is waiting for: EVENT_IN, EVENT_OUT, or nothing */
37void http_interest_add(const int64_t s, struct http_data *cookie, int what); 37void http_interest_set(const int64_t s, struct http_data *cookie, int what);
38void http_interest_drop(const int64_t s, struct http_data *cookie, int what);
39 38
40/* Close a connection and release everything that belongs to it */ 39/* Close a connection and release everything that belongs to it */
41void http_close(const int64_t s); 40void http_close(const int64_t s);