summaryrefslogtreecommitdiff
path: root/ot_udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_udp.c')
-rw-r--r--ot_udp.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/ot_udp.c b/ot_udp.c
index 87741da..1ec5148 100644
--- a/ot_udp.c
+++ b/ot_udp.c
@@ -9,6 +9,7 @@
9#include <stdio.h> 9#include <stdio.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12#include <unistd.h>
12 13
13/* Opentracker */ 14/* Opentracker */
14#include "ot_ip.h" 15#include "ot_ip.h"
@@ -19,6 +20,17 @@
19#include "ot_udp.h" 20#include "ot_udp.h"
20#include "trackerlogic.h" 21#include "trackerlogic.h"
21 22
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
22static uint32_t g_rijndael_round_key[44] = {0}; 34static uint32_t g_rijndael_round_key[44] = {0};
23static volatile uint32_t g_key_of_the_hour[2] = {0}; 35static volatile uint32_t g_key_of_the_hour[2] = {0};
24static volatile ot_time g_hour_of_the_key; 36static volatile ot_time g_hour_of_the_key;
@@ -206,7 +218,7 @@ int handle_udp6(int64_t serversocket, struct ot_workstruct *ws) {
206} 218}
207 219
208static void *udp_worker(void *args) { 220static void *udp_worker(void *args) {
209 int64_t sock = (int64_t)args; 221 struct udp_worker *me = args;
210 struct ot_workstruct ws; 222 struct ot_workstruct ws;
211 memset(&ws, 0, sizeof(ws)); 223 memset(&ws, 0, sizeof(ws));
212 224
@@ -218,7 +230,7 @@ static void *udp_worker(void *args) {
218#endif 230#endif
219 231
220 while (g_opentracker_running) 232 while (g_opentracker_running)
221 handle_udp6(sock, &ws); 233 handle_udp6(me->sock, &ws);
222 234
223 stats_counters_retire(&ws); 235 stats_counters_retire(&ws);
224 236
@@ -227,6 +239,8 @@ static void *udp_worker(void *args) {
227#ifdef _DEBUG_HTTPERROR 239#ifdef _DEBUG_HTTPERROR
228 free(ws.debugbuf); 240 free(ws.debugbuf);
229#endif 241#endif
242
243 atomic_store(&me->left, 1);
230 return NULL; 244 return NULL;
231} 245}
232 246
@@ -236,11 +250,47 @@ void udp_init(void) {
236} 250}
237 251
238void udp_worker_install(int64_t sock) { 252void udp_worker_install(int64_t sock) {
239 pthread_t thread_id; 253 struct udp_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers));
254 struct udp_worker *worker;
255
256 if (!grown || !(worker = calloc(1, sizeof(*worker)))) {
257 fprintf(stderr, "Warning: out of memory installing a udp worker, this socket stays with the workers already running.\n");
258 g_workers = grown ? grown : g_workers;
259 return;
260 }
261 g_workers = grown;
262 worker->sock = sock;
240 263
241#ifdef _DEBUG 264#ifdef _DEBUG
242 fprintf(stderr, "Installing a worker on udp socket %ld\n", (unsigned long)sock); 265 fprintf(stderr, "Installing a worker on udp socket %ld\n", (unsigned long)sock);
243#endif 266#endif
244 pthread_create(&thread_id, NULL, udp_worker, (void *)sock); 267 socket_set_blocking((int)sock, 1);
268
269 if (pthread_create(&worker->thread, NULL, udp_worker, worker))
270 free(worker);
271 else
272 g_workers[g_worker_count++] = worker;
273}
274
275void udp_workers_deinit(void) {
276 size_t i;
277
278 for (i = 0; i < g_worker_count; ++i) {
279 struct udp_worker *worker = g_workers[i];
280
281 /* Repeated because a signal only interrupts a read already under way: a
282 worker that was between two reads when the first one arrived is inside
283 the next one by now. */
284 while (!atomic_load(&worker->left)) {
285 pthread_kill(worker->thread, OT_SIGNAL_WAKE);
286 usleep(1000);
287 }
288 pthread_join(worker->thread, NULL);
289 free(worker);
290 }
291
292 free(g_workers);
293 g_workers = NULL;
294 g_worker_count = 0;
245} 295}
246 296