summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--opentracker.c4
-rw-r--r--ot_tcp.c66
-rw-r--r--ot_tcp.h2
-rw-r--r--ot_udp.c69
-rw-r--r--ot_udp.h2
-rw-r--r--ot_worker.c75
-rw-r--r--ot_worker.h39
8 files changed, 128 insertions, 133 deletions
diff --git a/Makefile b/Makefile
index dbc6166..c9aeafd 100644
--- a/Makefile
+++ b/Makefile
@@ -69,8 +69,8 @@ CFLAGS_libowfat=-I$(LIBOWFAT_HEADERS)
69LDFLAGS_libowfat=-L$(LIBOWFAT_LIBRARY) -lowfat 69LDFLAGS_libowfat=-L$(LIBOWFAT_LIBRARY) -lowfat
70 70
71BINARY =opentracker 71BINARY =opentracker
72HEADERS=trackerlogic.h ot_urlencoded.h ot_batch.h ot_buf.h ot_event.h ot_fdstate.h ot_fmt.h ot_hex.h ot_ip.h ot_config.h ot_scan.h ot_socket.h ot_tcp.h ot_workqueue.h ot_mutex.h ot_random.h ot_stats.h ot_vector.h ot_clean.h ot_udp.h ot_iovec.h ot_fullscrape.h ot_accesslist.h ot_http.h ot_livesync.h ot_rijndael.h 72HEADERS=trackerlogic.h ot_urlencoded.h ot_batch.h ot_buf.h ot_event.h ot_fdstate.h ot_fmt.h ot_hex.h ot_ip.h ot_config.h ot_scan.h ot_socket.h ot_tcp.h ot_worker.h ot_workqueue.h ot_mutex.h ot_random.h ot_stats.h ot_vector.h ot_clean.h ot_udp.h ot_iovec.h ot_fullscrape.h ot_accesslist.h ot_http.h ot_livesync.h ot_rijndael.h
73SOURCES=opentracker.c trackerlogic.c ot_urlencoded.c ot_batch.c ot_buf.c ot_event.c ot_fdstate.c ot_fmt.c ot_hex.c ot_ip.c ot_config.c ot_scan.c ot_socket.c ot_tcp.c ot_workqueue.c ot_mutex.c ot_random.c ot_stats.c ot_vector.c ot_clean.c ot_udp.c ot_iovec.c ot_fullscrape.c ot_accesslist.c ot_http.c ot_livesync.c ot_rijndael.c 73SOURCES=opentracker.c trackerlogic.c ot_urlencoded.c ot_batch.c ot_buf.c ot_event.c ot_fdstate.c ot_fmt.c ot_hex.c ot_ip.c ot_config.c ot_scan.c ot_socket.c ot_tcp.c ot_worker.c ot_workqueue.c ot_mutex.c ot_random.c ot_stats.c ot_vector.c ot_clean.c ot_udp.c ot_iovec.c ot_fullscrape.c ot_accesslist.c ot_http.c ot_livesync.c ot_rijndael.c
74SOURCES_proxy=proxy.c ot_batch.c ot_fdstate.c ot_vector.c ot_mutex.c ot_random.c ot_scan.c ot_ip.c ot_socket.c 74SOURCES_proxy=proxy.c ot_batch.c ot_fdstate.c ot_vector.c ot_mutex.c ot_random.c ot_scan.c ot_ip.c ot_socket.c
75 75
76all: $(BINARY) $(BINARY).debug 76all: $(BINARY) $(BINARY).debug
diff --git a/opentracker.c b/opentracker.c
index 2f2746d..644e99c 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -38,6 +38,7 @@
38#include "ot_stats.h" 38#include "ot_stats.h"
39#include "ot_tcp.h" 39#include "ot_tcp.h"
40#include "ot_udp.h" 40#include "ot_udp.h"
41#include "ot_worker.h"
41#include "trackerlogic.h" 42#include "trackerlogic.h"
42 43
43/* Globals */ 44/* Globals */
@@ -429,8 +430,7 @@ int main(int argc, char **argv) {
429 listen_start_udp_workers(); 430 listen_start_udp_workers();
430 431
431 server_mainloop(0); 432 server_mainloop(0);
432 tcp_workers_deinit(); 433 worker_stop_all();
433 udp_workers_deinit();
434 434
435 /* No thread is serving any more, so the teardown can run where a debugger 435 /* No thread is serving any more, so the teardown can run where a debugger
436 and the sanitizers can follow it */ 436 and the sanitizers can follow it */
diff --git a/ot_tcp.c b/ot_tcp.c
index 47697ca..4a5008b 100644
--- a/ot_tcp.c
+++ b/ot_tcp.c
@@ -20,6 +20,7 @@
20#include "ot_http.h" 20#include "ot_http.h"
21#include "ot_mutex.h" 21#include "ot_mutex.h"
22#include "ot_socket.h" 22#include "ot_socket.h"
23#include "ot_worker.h"
23#include "ot_stats.h" 24#include "ot_stats.h"
24#include "ot_tcp.h" 25#include "ot_tcp.h"
25#include "trackerlogic.h" 26#include "trackerlogic.h"
@@ -164,75 +165,18 @@ void tcp_accept(const int64_t serversocket, struct ot_workstruct *ws) {
164 } 165 }
165} 166}
166 167
167/* One of these per worker, each allocated on its own so that growing the
168 array below never moves the one a running worker holds. */
169struct tcp_worker {
170 pthread_t thread;
171 int64_t sock;
172 _Atomic int left;
173};
174
175static struct tcp_worker **g_workers;
176static size_t g_worker_count;
177
178/* A worker blocks in accept and nowhere else: the connection it is handed is 168/* A worker blocks in accept and nowhere else: the connection it is handed is
179 non blocking, so a client that stops talking is given to the event loop 169 non blocking, so a client that stops talking is given to the event loop
180 rather than keeping this thread. */ 170 rather than keeping this thread. */
181static void *tcp_worker(void *args) { 171static void tcp_run(struct ot_worker *me) {
182 struct tcp_worker *me = args;
183 struct ot_workstruct ws;
184
185 if (workstruct_init(&ws) == -1) {
186 fprintf(stderr, "Warning: a tcp worker could not get its buffers and will not run.\n");
187 atomic_store(&me->left, 1);
188 return NULL;
189 }
190
191 while (g_opentracker_running) 172 while (g_opentracker_running)
192 tcp_accept(me->sock, &ws); 173 tcp_accept(me->sock, &me->ws);
193
194 workstruct_deinit(&ws);
195 atomic_store(&me->left, 1);
196 return NULL;
197} 174}
198 175
199void tcp_worker_install(int64_t sock) { 176void tcp_worker_install(int64_t sock) {
200 struct tcp_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers));
201 struct tcp_worker *worker;
202
203 if (!grown || !(worker = calloc(1, sizeof(*worker)))) {
204 fprintf(stderr, "Warning: out of memory installing a tcp worker, this socket stays with the workers already running.\n");
205 g_workers = grown ? grown : g_workers;
206 return;
207 }
208 g_workers = grown;
209 worker->sock = sock;
210
211 socket_set_blocking((int)sock, 1); 177 socket_set_blocking((int)sock, 1);
212 socket_defer_accept((int)sock); 178 socket_defer_accept((int)sock);
213 179
214 if (pthread_create(&worker->thread, NULL, tcp_worker, worker)) 180 if (worker_start(tcp_run, sock) == -1)
215 free(worker); 181 fprintf(stderr, "Warning: could not install a tcp worker, this socket stays with the workers already running.\n");
216 else
217 g_workers[g_worker_count++] = worker;
218}
219
220void tcp_workers_deinit(void) {
221 size_t i;
222
223 for (i = 0; i < g_worker_count; ++i) {
224 struct tcp_worker *worker = g_workers[i];
225
226 /* Repeated because a signal only interrupts a call already under way */
227 while (!atomic_load(&worker->left)) {
228 pthread_kill(worker->thread, OT_SIGNAL_WAKE);
229 usleep(1000);
230 }
231 pthread_join(worker->thread, NULL);
232 free(worker);
233 }
234
235 free(g_workers);
236 g_workers = NULL;
237 g_worker_count = 0;
238} 182}
diff --git a/ot_tcp.h b/ot_tcp.h
index 96b6ec1..55a172c 100644
--- a/ot_tcp.h
+++ b/ot_tcp.h
@@ -22,7 +22,5 @@ void tcp_write(const int64_t sock);
22/* One thread accepting on one socket. Called once per worker. */ 22/* One thread accepting on one socket. Called once per worker. */
23void tcp_worker_install(int64_t sock); 23void tcp_worker_install(int64_t sock);
24 24
25/* Stop every worker installed above and wait for it to be gone */
26void tcp_workers_deinit(void);
27 25
28#endif 26#endif
diff --git a/ot_udp.c b/ot_udp.c
index 00ec566..309cbdb 100644
--- a/ot_udp.c
+++ b/ot_udp.c
@@ -16,21 +16,11 @@
16#include "ot_random.h" 16#include "ot_random.h"
17#include "ot_rijndael.h" 17#include "ot_rijndael.h"
18#include "ot_socket.h" 18#include "ot_socket.h"
19#include "ot_worker.h"
19#include "ot_stats.h" 20#include "ot_stats.h"
20#include "ot_udp.h" 21#include "ot_udp.h"
21#include "trackerlogic.h" 22#include "trackerlogic.h"
22 23
23/* One of these per worker, each allocated on its own so that growing the
24 array below never moves the one a running worker holds. */
25struct udp_worker {
26 pthread_t thread;
27 int64_t sock;
28 _Atomic int left;
29};
30
31static struct udp_worker **g_workers;
32static size_t g_worker_count;
33
34static uint32_t g_rijndael_round_key[44] = {0}; 24static uint32_t g_rijndael_round_key[44] = {0};
35static volatile uint32_t g_key_of_the_hour[2] = {0}; 25static volatile uint32_t g_key_of_the_hour[2] = {0};
36static volatile ot_time g_hour_of_the_key; 26static volatile ot_time g_hour_of_the_key;
@@ -217,22 +207,9 @@ int handle_udp6(int64_t serversocket, struct ot_workstruct *ws) {
217 return 1; 207 return 1;
218} 208}
219 209
220static void *udp_worker(void *args) { 210static void udp_run(struct ot_worker *me) {
221 struct udp_worker *me = args;
222 struct ot_workstruct ws;
223
224 if (workstruct_init(&ws) == -1) {
225 fprintf(stderr, "Warning: a udp worker could not get its buffers and will not run.\n");
226 atomic_store(&me->left, 1);
227 return NULL;
228 }
229
230 while (g_opentracker_running) 211 while (g_opentracker_running)
231 handle_udp6(me->sock, &ws); 212 handle_udp6(me->sock, &me->ws);
232
233 workstruct_deinit(&ws);
234 atomic_store(&me->left, 1);
235 return NULL;
236} 213}
237 214
238void udp_init(void) { 215void udp_init(void) {
@@ -241,47 +218,11 @@ void udp_init(void) {
241} 218}
242 219
243void udp_worker_install(int64_t sock) { 220void udp_worker_install(int64_t sock) {
244 struct udp_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers));
245 struct udp_worker *worker;
246
247 if (!grown || !(worker = calloc(1, sizeof(*worker)))) {
248 fprintf(stderr, "Warning: out of memory installing a udp worker, this socket stays with the workers already running.\n");
249 g_workers = grown ? grown : g_workers;
250 return;
251 }
252 g_workers = grown;
253 worker->sock = sock;
254
255#ifdef _DEBUG 221#ifdef _DEBUG
256 fprintf(stderr, "Installing a worker on udp socket %ld\n", (unsigned long)sock); 222 fprintf(stderr, "Installing a worker on udp socket %ld\n", (unsigned long)sock);
257#endif 223#endif
258 socket_set_blocking((int)sock, 1); 224 socket_set_blocking((int)sock, 1);
259 225
260 if (pthread_create(&worker->thread, NULL, udp_worker, worker)) 226 if (worker_start(udp_run, sock) == -1)
261 free(worker); 227 fprintf(stderr, "Warning: could not install a udp worker, this socket stays with the workers already running.\n");
262 else
263 g_workers[g_worker_count++] = worker;
264} 228}
265
266void udp_workers_deinit(void) {
267 size_t i;
268
269 for (i = 0; i < g_worker_count; ++i) {
270 struct udp_worker *worker = g_workers[i];
271
272 /* Repeated because a signal only interrupts a read already under way: a
273 worker that was between two reads when the first one arrived is inside
274 the next one by now. */
275 while (!atomic_load(&worker->left)) {
276 pthread_kill(worker->thread, OT_SIGNAL_WAKE);
277 usleep(1000);
278 }
279 pthread_join(worker->thread, NULL);
280 free(worker);
281 }
282
283 free(g_workers);
284 g_workers = NULL;
285 g_worker_count = 0;
286}
287
diff --git a/ot_udp.h b/ot_udp.h
index b731aca..1cd363a 100644
--- a/ot_udp.h
+++ b/ot_udp.h
@@ -14,8 +14,6 @@ void udp_init(void);
14/* One thread reading one socket. Called once per worker. */ 14/* One thread reading one socket. Called once per worker. */
15void udp_worker_install(int64_t sock); 15void udp_worker_install(int64_t sock);
16 16
17/* Stop every worker installed above and wait for it to be gone */
18void udp_workers_deinit(void);
19int handle_udp6(int64_t serversocket, struct ot_workstruct *ws); 17int handle_udp6(int64_t serversocket, struct ot_workstruct *ws);
20 18
21#endif 19#endif
diff --git a/ot_worker.c b/ot_worker.c
new file mode 100644
index 0000000..97eaeb2
--- /dev/null
+++ b/ot_worker.c
@@ -0,0 +1,75 @@
1/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
3
4 $id$ */
5
6/* System */
7#include <pthread.h>
8#include <stdatomic.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13/* Opentracker */
14#include "ot_worker.h"
15#include "trackerlogic.h"
16
17static struct ot_worker **g_workers;
18static size_t g_worker_count;
19
20/* Everything a worker needs doing around its own loop, in one place, so that
21 a new kind of worker cannot miss a piece of it. */
22static void *worker_trampoline(void *args) {
23 struct ot_worker *me = args;
24
25 if (workstruct_init(&me->ws) == -1)
26 fprintf(stderr, "Warning: a worker could not get its buffers and will not run.\n");
27 else {
28 me->run(me);
29 workstruct_deinit(&me->ws);
30 }
31
32 atomic_store(&me->left, 1);
33 return NULL;
34}
35
36int worker_start(ot_worker_run run, int64_t sock) {
37 struct ot_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers));
38 struct ot_worker *worker;
39
40 if (!grown)
41 return -1;
42 g_workers = grown;
43
44 if (!(worker = calloc(1, sizeof(*worker))))
45 return -1;
46 worker->sock = sock;
47 worker->run = run;
48
49 if (pthread_create(&worker->thread, NULL, worker_trampoline, worker)) {
50 free(worker);
51 return -1;
52 }
53 g_workers[g_worker_count++] = worker;
54 return 0;
55}
56
57void worker_stop_all(void) {
58 size_t i;
59
60 for (i = 0; i < g_worker_count; ++i) {
61 struct ot_worker *worker = g_workers[i];
62
63 /* Repeated because a signal only interrupts a call already under way */
64 while (!atomic_load(&worker->left)) {
65 pthread_kill(worker->thread, OT_SIGNAL_WAKE);
66 usleep(1000);
67 }
68 pthread_join(worker->thread, NULL);
69 free(worker);
70 }
71
72 free(g_workers);
73 g_workers = NULL;
74 g_worker_count = 0;
75}
diff --git a/ot_worker.h b/ot_worker.h
new file mode 100644
index 0000000..ea4f379
--- /dev/null
+++ b/ot_worker.h
@@ -0,0 +1,39 @@
1/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
3
4 $id$ */
5
6#ifndef OT_WORKER_H__
7#define OT_WORKER_H__
8
9#include <pthread.h>
10#include <stdatomic.h>
11#include <stdint.h>
12
13#include "trackerlogic.h"
14
15struct ot_worker;
16
17/* What a worker does between being started and being told to stop. It reads
18 worker->sock and works out of worker->ws; everything around it, from the
19 buffers to the counters to saying goodbye, is handled here. */
20typedef void (*ot_worker_run)(struct ot_worker *worker);
21
22/* A thread that serves requests on a socket of its own, with the buffers and
23 counters it needs. Each is allocated on its own, so taking on another one
24 never moves the record a running worker holds. */
25struct ot_worker {
26 pthread_t thread;
27 _Atomic int left;
28 int64_t sock;
29 ot_worker_run run;
30 struct ot_workstruct ws;
31};
32
33/* Start one. Returns -1 if it could not be started. */
34int worker_start(ot_worker_run run, int64_t sock);
35
36/* Wake every worker until it has left, then join it */
37void worker_stop_all(void);
38
39#endif