summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-26 20:03:22 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-26 20:03:22 +0100
commit2d6b6d4da1d9732b2b02989a4374d356ff840d1b (patch)
tree50ff9d2fba93934d1572706f10593aec0ea57e07 /ot_http.c
parentf2f5b0450d4b7269bafdfb1bd1788303f6d8ce7b (diff)
Replace libowfat's event waiter with our own abstraction
It's with a heavy heart that I remove libowfat as my event library from opentracker. libowfat is what taught opentracker to walk and then fly. The tracker was literally standing on the shoulder of giants when I started writing it in 2006. For its time, the event abstraction was unparalleled and it has held up for many years, and it served the bittorrent community greatly. https://erdgeist.org/gitweb/opentracker/commit/?id=ad472597c569568bad0526d116b601dfcb36638c Unfortunately, it is very likely that libowfat will not be maintained anymore for the foreseeable future, it is already not easy to get its source from upstream and opentracker started receiving bug reports that I can not reasonably answer or patch. Before the project gets more dependent on the limitations of libowfat's current state, I need to teach opentracker to stand on its own feet and fly by itself. I've learned a great deal in the process and have even more respect now for what libowfat pioneered. The path for opentracker is cleared now. Ground work has already been laid in the migration process to support multi threaded http processing while keeping the aggressive reduction of syscalls alive that made the libowfat+opentracker combo so scalable. Here be some dragons, though: Even though there is a unit test suite now, the event loop's rewrite has not been battle tested yet. So you might want to hold up for a bit before jumping on the solo band wagon. What awaits at the end will be a long overdue v1.0, which will be named in honour of Felix.
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/ot_http.c b/ot_http.c
index 3c135cb..5e10d59 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -14,9 +14,6 @@
14#include <sys/types.h> 14#include <sys/types.h>
15#include <unistd.h> 15#include <unistd.h>
16 16
17/* Libowfat */
18#include "io.h"
19
20/* Opentracker */ 17/* Opentracker */
21#include "ot_accesslist.h" 18#include "ot_accesslist.h"
22#include "ot_fullscrape.h" 19#include "ot_fullscrape.h"
@@ -25,6 +22,7 @@
25#include "ot_ip.h" 22#include "ot_ip.h"
26#include "ot_mutex.h" 23#include "ot_mutex.h"
27#include "ot_scan.h" 24#include "ot_scan.h"
25#include "ot_event.h"
28#include "ot_fdstate.h" 26#include "ot_fdstate.h"
29#include "ot_stats.h" 27#include "ot_stats.h"
30#include "ot_urlencoded.h" 28#include "ot_urlencoded.h"
@@ -43,7 +41,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
43 ssize_t written_size; 41 ssize_t written_size;
44 42
45 if (!cookie) { 43 if (!cookie) {
46 io_close(sock); 44 event_del((int)sock), close((int)sock);
47 return; 45 return;
48 } 46 }
49 47
@@ -67,7 +65,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
67 if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { 65 if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) {
68 buf_reset(&cookie->request); 66 buf_reset(&cookie->request);
69 free(cookie); 67 free(cookie);
70 io_close(sock); 68 event_del((int)sock), close((int)sock);
71 return; 69 return;
72 } 70 }
73 71
@@ -77,7 +75,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
77 if (!(outbuf = malloc(ws->reply_size - written_size))) { 75 if (!(outbuf = malloc(ws->reply_size - written_size))) {
78 buf_reset(&cookie->request); 76 buf_reset(&cookie->request);
79 free(cookie); 77 free(cookie);
80 io_close(sock); 78 event_del((int)sock), close((int)sock);
81 return; 79 return;
82 } 80 }
83 81
@@ -88,7 +86,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
88 free(outbuf); 86 free(outbuf);
89 buf_reset(&cookie->request); 87 buf_reset(&cookie->request);
90 free(cookie); 88 free(cookie);
91 io_close(sock); 89 event_del((int)sock), close((int)sock);
92 return; 90 return;
93 } 91 }
94 } 92 }
@@ -98,9 +96,9 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
98 /* writeable short data sockets just have a tcp timeout */ 96 /* writeable short data sockets just have a tcp timeout */
99 if (!ws->keep_alive) { 97 if (!ws->keep_alive) {
100 fdstate_set_expiry(sock, 0); 98 fdstate_set_expiry(sock, 0);
101 io_dontwantread(sock); 99 http_interest_drop(sock, cookie, EVENT_IN);
102 } 100 }
103 io_wantwrite(sock); 101 http_interest_add(sock, cookie, EVENT_OUT);
104 } 102 }
105} 103}
106 104
@@ -113,6 +111,21 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
113#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP) 111#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP)
114#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) 112#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404)
115#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500) 113#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500)
114static void http_interest(const int64_t sock, struct http_data *cookie, int what) {
115 if (cookie->interest == what)
116 return;
117 cookie->interest = what;
118 event_modify((int)sock, what, fdstate_generation((int)sock));
119}
120
121void http_interest_add(const int64_t sock, struct http_data *cookie, int what) {
122 http_interest(sock, cookie, cookie->interest | what);
123}
124
125void http_interest_drop(const int64_t sock, struct http_data *cookie, int what) {
126 http_interest(sock, cookie, cookie->interest & ~what);
127}
128
116ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) { 129ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) {
117 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required", 130 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required",
118 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"}; 131 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"};
@@ -157,7 +170,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
157 170
158 /* If we came here, wait for the answer is over */ 171 /* If we came here, wait for the answer is over */
159 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) { 172 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) {
160 io_dontwantread(sock); 173 http_interest_drop(sock, cookie, EVENT_IN);
161 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; 174 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK;
162 } 175 }
163 176
@@ -208,7 +221,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
208 } 221 }
209 222
210 fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT_SEND); 223 fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT_SEND);
211 io_wantwrite(sock); 224 http_interest_add(sock, cookie, EVENT_OUT);
212 return 0; 225 return 0;
213} 226}
214 227
@@ -303,7 +316,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
303 /* Clients waiting for us should not easily timeout */ 316 /* Clients waiting for us should not easily timeout */
304 fdstate_set_expiry(sock, 0); 317 fdstate_set_expiry(sock, 0);
305 fullscrape_deliver(sock, format); 318 fullscrape_deliver(sock, format);
306 io_dontwantread(sock); 319 http_interest_drop(sock, cookie, EVENT_IN);
307 return ws->reply_size = -2; 320 return ws->reply_size = -2;
308 } 321 }
309#endif 322#endif
@@ -396,7 +409,7 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
396 /* Clients waiting for us should not easily timeout */ 409 /* Clients waiting for us should not easily timeout */
397 fdstate_set_expiry(sock, 0); 410 fdstate_set_expiry(sock, 0);
398 fullscrape_deliver(sock, format); 411 fullscrape_deliver(sock, format);
399 io_dontwantread(sock); 412 http_interest_drop(sock, cookie, EVENT_IN);
400 return ws->reply_size = -2; 413 return ws->reply_size = -2;
401} 414}
402#endif 415#endif