summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2022-11-24 04:20:06 +0100
committerDirk Engling <erdgeist@erdgeist.org>2022-11-24 04:20:06 +0100
commitbe825f57597b0e9dcf07d257e93f03e30935f7db (patch)
tree58059fe89c3e2faf8be5999b7cac010e03f1ae31
parent110868ec4ebe60521d5a4ced63feca6a1cf0aa2a (diff)
Add support for dynamic accesslists
-rw-r--r--Makefile1
-rw-r--r--opentracker.c12
-rw-r--r--opentracker.conf.sample37
-rw-r--r--ot_accesslist.c273
-rw-r--r--ot_accesslist.h8
-rw-r--r--ot_mutex.h6
-rw-r--r--ot_stats.h6
-rw-r--r--trackerlogic.h5
8 files changed, 298 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index 949e63e..e3301a5 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,7 @@ STRIP?=strip
24 24
25#FEATURES+=-DWANT_ACCESSLIST_BLACK 25#FEATURES+=-DWANT_ACCESSLIST_BLACK
26#FEATURES+=-DWANT_ACCESSLIST_WHITE 26#FEATURES+=-DWANT_ACCESSLIST_WHITE
27#FEATURES+=-DWANT_DYNAMIC_ACCESSLIST
27 28
28#FEATURES+=-DWANT_SYNC_LIVE 29#FEATURES+=-DWANT_SYNC_LIVE
29#FEATURES+=-DWANT_IP_FROM_QUERY_STRING 30#FEATURES+=-DWANT_IP_FROM_QUERY_STRING
diff --git a/opentracker.c b/opentracker.c
index a5ba7d3..b6d2bb9 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -135,8 +135,8 @@ static void help( char *name ) {
135} 135}
136#undef HELPLINE 136#undef HELPLINE
137 137
138static size_t header_complete( char * request, ssize_t byte_count ) { 138static ssize_t header_complete( char * request, ssize_t byte_count ) {
139 int i = 0, state = 0; 139 ssize_t i = 0, state = 0;
140 140
141 for( i=1; i < byte_count; i+=2 ) 141 for( i=1; i < byte_count; i+=2 )
142 if( request[i] <= 13 ) { 142 if( request[i] <= 13 ) {
@@ -184,7 +184,7 @@ static void handle_read( const int64 sock, struct ot_workstruct *ws ) {
184 ws->request_size = byte_count; 184 ws->request_size = byte_count;
185 http_handle_request( sock, ws ); 185 http_handle_request( sock, ws );
186 } else 186 } else
187 array_catb( &cookie->request, ws->inbuf, byte_count ); 187 array_catb( &cookie->request, ws->inbuf, (size_t)byte_count );
188 return; 188 return;
189 } 189 }
190 190
@@ -463,6 +463,12 @@ int parse_configfile( char * config_filename ) {
463 } else if(!byte_diff(p, 16, "access.blacklist" ) && isspace(p[16])) { 463 } else if(!byte_diff(p, 16, "access.blacklist" ) && isspace(p[16])) {
464 set_config_option( &g_accesslist_filename, p+17 ); 464 set_config_option( &g_accesslist_filename, p+17 );
465#endif 465#endif
466#ifdef WANT_DYNAMIC_ACCESSLIST
467 } else if(!byte_diff(p, 15, "access.fifo_add" ) && isspace(p[15])) {
468 set_config_option( &g_accesslist_pipe_add, p+16 );
469 } else if(!byte_diff(p, 18, "access.fifo_delete" ) && isspace(p[18])) {
470 set_config_option( &g_accesslist_pipe_delete, p+19 );
471#endif
466#ifdef WANT_RESTRICT_STATS 472#ifdef WANT_RESTRICT_STATS
467 } else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) { 473 } else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) {
468 if( !scan_ip6( p+13, tmpip )) goto parse_error; 474 if( !scan_ip6( p+13, tmpip )) goto parse_error;
diff --git a/opentracker.conf.sample b/opentracker.conf.sample
index db45122..55c2828 100644
--- a/opentracker.conf.sample
+++ b/opentracker.conf.sample
@@ -44,6 +44,43 @@
44# listing, so choose one of those options at compile time. File format 44# listing, so choose one of those options at compile time. File format
45# is straight forward: "<hex info hash>\n<hex info hash>\n..." 45# is straight forward: "<hex info hash>\n<hex info hash>\n..."
46# 46#
47# IIa) You can enable dynamic changesets to accesslists by enabling
48# WANT_DYNAMIC_ACCESSLIST.
49#
50# The suggested way to work with dynamic changeset lists is to keep a
51# main accesslist file that is loaded when opentracker (re)starts and
52# reloaded infrequently (hourly or daily).
53#
54# All changes to the accesslist (e.g. from a web frontend) should be
55# both appended to or removed from that file and sent to opentracker. By
56# keeping dynamic changeset lists, you can avoid reloading huge
57# accesslists whenever just a single entry is added or removed.
58#
59# Any info_hash (format see above) written to the fifo_add file will be
60# kept on a dynamic add-changeset, removed from the dynamic
61# delete-changeset and treated as if it was in the main accesslist file.
62# The semantic of the respective dynamic changeset depends on whether
63# WANT_ACCESSLIST_WHITE or WANT_ACCESSLIST_BLACK is enabled.
64#
65# access.fifo_add /var/run/opentracker/adder.fifo
66#
67# Any info_hash (format see above) written to the fifo_delete file will
68# be kept on a dynamic delete-changeset, removed from the dynamic
69# add-changeset and treated as if it was not in the main accesslist
70# file.
71#
72# access.fifo_delete /var/run/opentracker/deleter.fifo
73#
74# If you reload the accesslist by sending SIGHUP to the tracker process,
75# the dynamic lists are flushed, as opentracker assumes thoses lists are
76# merged into the main accesslist.
77#
78# NOTE: While you can have multiple writers sending lines to the fifos,
79# any writes larger than PIPE_BUF (see your limits.h, minimally 512
80# bytes but usually 4096) may be interleaved with data sent by other
81# writers. This can lead to unparsable lines of info_hashes.
82#
83# IIb)
47# If you do not want to grant anyone access to your stats, enable the 84# If you do not want to grant anyone access to your stats, enable the
48# WANT_RESTRICT_STATS option in Makefile and bless the ip addresses 85# WANT_RESTRICT_STATS option in Makefile and bless the ip addresses
49# allowed to fetch stats here. 86# allowed to fetch stats here.
diff --git a/ot_accesslist.c b/ot_accesslist.c
index a3a2049..078cebd 100644
--- a/ot_accesslist.c
+++ b/ot_accesslist.c
@@ -10,6 +10,11 @@
10#include <stdio.h> 10#include <stdio.h>
11#include <signal.h> 11#include <signal.h>
12#include <unistd.h> 12#include <unistd.h>
13#ifdef WANT_DYNAMIC_ACCESSLIST
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <errno.h>
17#endif
13 18
14/* Libowfat */ 19/* Libowfat */
15#include "byte.h" 20#include "byte.h"
@@ -24,23 +29,80 @@
24 29
25/* GLOBAL VARIABLES */ 30/* GLOBAL VARIABLES */
26#ifdef WANT_ACCESSLIST 31#ifdef WANT_ACCESSLIST
27 char *g_accesslist_filename; 32char *g_accesslist_filename = NULL;
33#ifdef WANT_DYNAMIC_ACCESSLIST
34char *g_accesslist_pipe_add = NULL;
35char *g_accesslist_pipe_delete = NULL;
36#endif
28static pthread_mutex_t g_accesslist_mutex; 37static pthread_mutex_t g_accesslist_mutex;
29 38
30typedef struct { 39/* Accesslists are lock free linked lists. We can not make them locking, because every announce
31 ot_hash *list; 40 would try to acquire the mutex, making it the most contested mutex in the whole of opentracker,
32 size_t size; 41 basically creating a central performance choke point.
33} ot_accesslist; 42
34ot_accesslist * g_accesslist = NULL; 43 The idea is that updating the list heads happens under the g_accesslist_mutex guard and is
35ot_accesslist * g_accesslist_old = NULL; 44 done atomically, while consumers might potentially still hold pointers deeper inside the list.
45
46 Consumers (for now only via accesslist_hashisvalid) will always fetch the list head pointer
47 that is guaranteed to live for at least five minutes. This should be many orders of magnitudes
48 more than how long it will be needed by the bsearch done on the list. */
49struct ot_accesslist;
50typedef struct ot_accesslist ot_accesslist;
51struct ot_accesslist {
52 ot_hash *list;
53 size_t size;
54 ot_time base;
55 ot_accesslist *next;
56};
57static ot_accesslist * g_accesslist = NULL;
58#ifdef WANT_DYNAMIC_ACCESSLIST
59static ot_accesslist * g_accesslist_add = NULL;
60static ot_accesslist * g_accesslist_delete = NULL;
61#endif
36 62
63/* Helpers to work on access lists */
37static int vector_compare_hash(const void *hash1, const void *hash2 ) { 64static int vector_compare_hash(const void *hash1, const void *hash2 ) {
38 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE ); 65 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE );
39} 66}
40 67
68static ot_accesslist * accesslist_free(ot_accesslist *accesslist) {
69 while (accesslist) {
70 ot_accesslist * this_accesslist = accesslist;
71 accesslist = this_accesslist->next;
72 free(this_accesslist->list);
73 free(this_accesslist);
74 }
75 return NULL;
76}
77
78static ot_accesslist * accesslist_make(ot_accesslist *next, size_t size) {
79 ot_accesslist * accesslist_new = malloc(sizeof(ot_accesslist));
80 if (accesslist_new) {
81 accesslist_new->list = size ? malloc(sizeof(ot_hash) * size) : NULL;
82 accesslist_new->size = size;
83 accesslist_new->base = g_now_minutes;
84 accesslist_new->next = next;
85 if (size && !accesslist_new->list) {
86 free(accesslist_new);
87 accesslist_new = NULL;
88 }
89 }
90 return accesslist_new;
91}
92
93/* This must be called with g_accesslist_mutex held.
94 This will never delete head, because that might still be in use. */
95static void accesslist_clean(ot_accesslist *accesslist) {
96 while (accesslist && accesslist->next) {
97 if (accesslist->next->base + 5 < g_now_minutes)
98 accesslist->next = accesslist_free(accesslist->next);
99 accesslist = accesslist->next;
100 }
101}
102
41/* Read initial access list */ 103/* Read initial access list */
42static void accesslist_readfile( void ) { 104static void accesslist_readfile( void ) {
43 ot_accesslist * accesslist_new = malloc(sizeof(ot_accesslist)); 105 ot_accesslist * accesslist_new;
44 ot_hash *info_hash; 106 ot_hash *info_hash;
45 const char *map, *map_end, *read_offs; 107 const char *map, *map_end, *read_offs;
46 size_t maplen; 108 size_t maplen;
@@ -54,14 +116,13 @@ static void accesslist_readfile( void ) {
54 116
55 /* You need at least 41 bytes to pass an info_hash, make enough room 117 /* You need at least 41 bytes to pass an info_hash, make enough room
56 for the maximum amount of them */ 118 for the maximum amount of them */
57 accesslist_new->size = 0; 119 accesslist_new = accesslist_make(g_accesslist, maplen / 41);
58 info_hash = accesslist_new->list = malloc( ( maplen / 41 ) * 20 ); 120 if( !accesslist_new ) {
59 if( !accesslist_new->list ) {
60 fprintf( stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", ( maplen / 41 ) * 20 ); 121 fprintf( stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", ( maplen / 41 ) * 20 );
61 mmap_unmap( map, maplen); 122 mmap_unmap( map, maplen);
62 free(accesslist_new);
63 return; 123 return;
64 } 124 }
125 info_hash = accesslist_new->list;
65 126
66 /* No use to scan if there's not enough room for another full info_hash */ 127 /* No use to scan if there's not enough room for another full info_hash */
67 map_end = map + maplen - 40; 128 map_end = map + maplen - 40;
@@ -71,18 +132,18 @@ static void accesslist_readfile( void ) {
71 while( read_offs <= map_end ) { 132 while( read_offs <= map_end ) {
72 int i; 133 int i;
73 for( i=0; i<(int)sizeof(ot_hash); ++i ) { 134 for( i=0; i<(int)sizeof(ot_hash); ++i ) {
74 int eger1 = scan_fromhex( read_offs[ 2*i ] ); 135 int eger1 = scan_fromhex( (unsigned char)read_offs[ 2*i ] );
75 int eger2 = scan_fromhex( read_offs[ 1 + 2*i ] ); 136 int eger2 = scan_fromhex( (unsigned char)read_offs[ 1 + 2*i ] );
76 if( eger1 < 0 || eger2 < 0 ) 137 if( eger1 < 0 || eger2 < 0 )
77 break; 138 break;
78 (*info_hash)[i] = eger1 * 16 + eger2; 139 (*info_hash)[i] = (uint8_t)(eger1 * 16 + eger2);
79 } 140 }
80 141
81 if( i == sizeof(ot_hash) ) { 142 if( i == sizeof(ot_hash) ) {
82 read_offs += 40; 143 read_offs += 40;
83 144
84 /* Append accesslist to accesslist vector */ 145 /* Append accesslist to accesslist vector */
85 if( read_offs == map_end || scan_fromhex( *read_offs ) < 0 ) 146 if( read_offs == map_end || scan_fromhex( (unsigned char)*read_offs ) < 0 )
86 ++info_hash; 147 ++info_hash;
87 } 148 }
88 149
@@ -100,14 +161,19 @@ static void accesslist_readfile( void ) {
100 161
101 /* Now exchange the accesslist vector in the least race condition prone way */ 162 /* Now exchange the accesslist vector in the least race condition prone way */
102 pthread_mutex_lock(&g_accesslist_mutex); 163 pthread_mutex_lock(&g_accesslist_mutex);
164 accesslist_new->next = g_accesslist;
165 g_accesslist = accesslist_new; /* Only now set a new list */
166
167#ifdef WANT_DYNAMIC_ACCESSLIST
168 /* If we have dynamic accesslists, reloading a new one will always void the add/delete lists.
169 Insert empty ones at the list head */
170 if (g_accesslist_add && (accesslist_new = accesslist_make(g_accesslist_add, 0)) != NULL)
171 g_accesslist_add = accesslist_new;
172 if (g_accesslist_delete && (accesslist_new = accesslist_make(g_accesslist_delete, 0)) != NULL)
173 g_accesslist_delete = accesslist_new;
174#endif
103 175
104 if (g_accesslist_old) { 176 accesslist_clean(g_accesslist);
105 free(g_accesslist_old->list);
106 free(g_accesslist_old);
107 }
108
109 g_accesslist_old = g_accesslist; /* Keep a copy for later free */
110 g_accesslist = accesslist_new; /* Only now set a new list */
111 177
112 pthread_mutex_unlock(&g_accesslist_mutex); 178 pthread_mutex_unlock(&g_accesslist_mutex);
113} 179}
@@ -115,11 +181,25 @@ static void accesslist_readfile( void ) {
115int accesslist_hashisvalid( ot_hash hash ) { 181int accesslist_hashisvalid( ot_hash hash ) {
116 /* Get working copy of current access list */ 182 /* Get working copy of current access list */
117 ot_accesslist * accesslist = g_accesslist; 183 ot_accesslist * accesslist = g_accesslist;
118 184#ifdef WANT_DYNAMIC_ACCESSLIST
185 ot_accesslist * accesslist_add, * accesslist_delete;
186#endif
119 void * exactmatch = NULL; 187 void * exactmatch = NULL;
120 188
121 if (accesslist) 189 if (accesslist)
122 exactmatch = bsearch( hash, accesslist->list, accesslist->size, OT_HASH_COMPARE_SIZE, vector_compare_hash ); 190 exactmatch = bsearch( hash, accesslist->list, accesslist->size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
191
192#ifdef WANT_DYNAMIC_ACCESSLIST
193 /* If we had no match on the main list, scan the list of dynamically added hashes */
194 accesslist_add = g_accesslist_add;
195 if ((exactmatch == NULL) && accesslist_add)
196 exactmatch = bsearch( hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
197
198 /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */
199 accesslist_delete = g_accesslist_delete;
200 if ((exactmatch != NULL) && accesslist_delete && bsearch( hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash ))
201 exactmatch = NULL;
202#endif
123 203
124#ifdef WANT_ACCESSLIST_BLACK 204#ifdef WANT_ACCESSLIST_BLACK
125 return exactmatch == NULL; 205 return exactmatch == NULL;
@@ -138,6 +218,8 @@ static void * accesslist_worker( void * args ) {
138 (void)args; 218 (void)args;
139 219
140 while( 1 ) { 220 while( 1 ) {
221 if (!g_opentracker_running)
222 return NULL;
141 223
142 /* Initial attempt to read accesslist */ 224 /* Initial attempt to read accesslist */
143 accesslist_readfile( ); 225 accesslist_readfile( );
@@ -148,27 +230,144 @@ static void * accesslist_worker( void * args ) {
148 return NULL; 230 return NULL;
149} 231}
150 232
233#ifdef WANT_DYNAMIC_ACCESSLIST
234static pthread_t thread_adder_id, thread_deleter_id;
235static void * accesslist_adddel_worker(char * fifoname, ot_accesslist ** adding_to, ot_accesslist ** removing_from) {
236 struct stat st;
237
238 if (!stat(fifoname, &st)) {
239 if (!S_ISFIFO(st.st_mode)) {
240 fprintf(stderr, "Error when starting dynamic accesslists: Found Non-FIFO file at %s.\nPlease remove it and restart opentracker.\n", fifoname);
241 return NULL;
242 }
243 } else {
244 int error = mkfifo(fifoname, 0755);
245 if (error && error != EEXIST) {
246 fprintf(stderr, "Error when starting dynamic accesslists: Couldn't create FIFO at %s, error: %s\n", fifoname, strerror(errno));
247 return NULL;
248 }
249 }
250
251 while (g_opentracker_running) {
252 FILE * fifo = fopen(fifoname, "r");
253 char *line = NULL;
254 size_t linecap = 0;
255 ssize_t linelen;
256
257 if (!fifo) {
258 fprintf(stderr, "Error when reading dynamic accesslists: Couldn't open FIFO at %s, error: %s\n", fifoname, strerror(errno));
259 return NULL;
260 }
261
262 while ((linelen = getline(&line, &linecap, fifo)) > 0) {
263 ot_hash info_hash;
264 int i;
265
266 printf("Got line %*s", (int)linelen, line);
267 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*"
268 If there's not enough characters for an info_hash in the line, skip it. */
269 if (linelen < 41)
270 continue;
271
272 for( i=0; i<(int)sizeof(ot_hash); ++i ) {
273 int eger1 = scan_fromhex( (unsigned char)line[ 2*i ] );
274 int eger2 = scan_fromhex( (unsigned char)line[ 1 + 2*i ] );
275 if( eger1 < 0 || eger2 < 0 )
276 break;
277 ((uint8_t*)info_hash)[i] = (uint8_t)(eger1 * 16 + eger2);
278 }
279printf("parsed info_hash %20s\n", info_hash);
280 if( i != sizeof(ot_hash) )
281 continue;
282
283 /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the
284 other worker threads from doing the same */
285 pthread_mutex_lock(&g_accesslist_mutex);
286
287 /* If the info hash is in the removing_from list, create a new head without that entry */
288 if (*removing_from && (*removing_from)->list) {
289 ot_hash * exactmatch = bsearch( info_hash, (*removing_from)->list, (*removing_from)->size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
290 if (exactmatch) {
291 ptrdiff_t off = exactmatch - (*removing_from)->list;
292 ot_accesslist * accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1);
293 if (accesslist_new) {
294 memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off);
295 memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, (*removing_from)->size - off - 1);
296 *removing_from = accesslist_new;
297 }
298 }
299 }
300 accesslist_clean(*removing_from);
301
302 /* Simple case: there's no adding_to list yet, create one with one member */
303 if (!*adding_to) {
304 *adding_to = accesslist_make(NULL, 1);
305 if (*adding_to)
306 memcpy((*adding_to)->list, info_hash, sizeof(ot_hash));
307 } else {
308 int exactmatch = 0;
309 ot_hash * insert_point = binary_search( info_hash, (*adding_to)->list, (*adding_to)->size, OT_HASH_COMPARE_SIZE, sizeof(ot_hash), &exactmatch );
310
311 /* Only if the info hash is not in the adding_to list, create a new head with that entry */
312 if (!exactmatch) {
313 ot_accesslist * accesslist_new = accesslist_make(*adding_to, (*adding_to)->size + 1);
314 ptrdiff_t off = insert_point - (*adding_to)->list;
315 if (accesslist_new) {
316 memcpy(accesslist_new->list, (*adding_to)->list, sizeof(ot_hash) * off);
317 memcpy(accesslist_new->list + off, info_hash, sizeof(info_hash));
318 memcpy(accesslist_new->list + off + 1, (*adding_to)->list + off, (*adding_to)->size - off);
319 *adding_to = accesslist_new;
320 }
321 }
322 }
323 accesslist_clean(*adding_to);
324
325 pthread_mutex_unlock(&g_accesslist_mutex);
326 }
327
328 fclose(fifo);
329 }
330 return NULL;
331}
332
333static void * accesslist_adder_worker( void * args ) {
334 (void)args;
335 return accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete);
336}
337static void * accesslist_deleter_worker( void * args ) {
338 (void)args;
339 return accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add);
340}
341#endif
342
151static pthread_t thread_id; 343static pthread_t thread_id;
152void accesslist_init( ) { 344void accesslist_init( ) {
153 pthread_mutex_init(&g_accesslist_mutex, NULL); 345 pthread_mutex_init(&g_accesslist_mutex, NULL);
154 pthread_create( &thread_id, NULL, accesslist_worker, NULL ); 346 pthread_create( &thread_id, NULL, accesslist_worker, NULL );
347#ifdef WANT_DYNAMIC_ACCESSLIST
348 if (g_accesslist_pipe_add)
349 pthread_create( &thread_adder_id, NULL, accesslist_adder_worker, NULL );
350 if (g_accesslist_pipe_delete)
351 pthread_create( &thread_deleter_id, NULL, accesslist_deleter_worker, NULL );
352#endif
155} 353}
156 354
157void accesslist_deinit( void ) { 355void accesslist_deinit( void ) {
158 pthread_cancel( thread_id ); 356 /* Wake up sleeping worker */
159 pthread_mutex_destroy(&g_accesslist_mutex); 357 pthread_kill(thread_id, SIGHUP);
160 358
161 if (g_accesslist_old) { 359 pthread_mutex_lock(&g_accesslist_mutex);
162 free(g_accesslist_old->list);
163 free(g_accesslist_old);
164 g_accesslist_old = 0;
165 }
166 360
167 if (g_accesslist) { 361 g_accesslist = accesslist_free(g_accesslist);
168 free(g_accesslist->list); 362
169 free(g_accesslist); 363#ifdef WANT_DYNAMIC_ACCESSLIST
170 g_accesslist = 0; 364 g_accesslist_add = accesslist_free(g_accesslist_add);
171 } 365 g_accesslist_delete = accesslist_free(g_accesslist_delete);
366#endif
367
368 pthread_mutex_unlock(&g_accesslist_mutex);
369 pthread_cancel( thread_id );
370 pthread_mutex_destroy(&g_accesslist_mutex);
172} 371}
173#endif 372#endif
174 373
diff --git a/ot_accesslist.h b/ot_accesslist.h
index b38b91a..e86969b 100644
--- a/ot_accesslist.h
+++ b/ot_accesslist.h
@@ -12,11 +12,15 @@
12 12
13#if defined ( WANT_ACCESSLIST_BLACK ) || defined (WANT_ACCESSLIST_WHITE ) 13#if defined ( WANT_ACCESSLIST_BLACK ) || defined (WANT_ACCESSLIST_WHITE )
14#define WANT_ACCESSLIST 14#define WANT_ACCESSLIST
15void accesslist_init( ); 15void accesslist_init( void );
16void accesslist_deinit( ); 16void accesslist_deinit( void );
17int accesslist_hashisvalid( ot_hash hash ); 17int accesslist_hashisvalid( ot_hash hash );
18 18
19extern char *g_accesslist_filename; 19extern char *g_accesslist_filename;
20#ifdef WANT_DYNAMIC_ACCESSLIST
21extern char *g_accesslist_pipe_add;
22extern char *g_accesslist_pipe_delete;
23#endif
20 24
21#else 25#else
22#define accesslist_init( accesslist_filename ) 26#define accesslist_init( accesslist_filename )
diff --git a/ot_mutex.h b/ot_mutex.h
index bd07009..93c1ecf 100644
--- a/ot_mutex.h
+++ b/ot_mutex.h
@@ -8,8 +8,8 @@
8 8
9#include <sys/uio.h> 9#include <sys/uio.h>
10 10
11void mutex_init( ); 11void mutex_init( void );
12void mutex_deinit( ); 12void mutex_deinit( void );
13 13
14ot_vector *mutex_bucket_lock( int bucket ); 14ot_vector *mutex_bucket_lock( int bucket );
15ot_vector *mutex_bucket_lock_by_hash( ot_hash hash ); 15ot_vector *mutex_bucket_lock_by_hash( ot_hash hash );
@@ -17,7 +17,7 @@ ot_vector *mutex_bucket_lock_by_hash( ot_hash hash );
17void mutex_bucket_unlock( int bucket, int delta_torrentcount ); 17void mutex_bucket_unlock( int bucket, int delta_torrentcount );
18void mutex_bucket_unlock_by_hash( ot_hash hash, int delta_torrentcount ); 18void mutex_bucket_unlock_by_hash( ot_hash hash, int delta_torrentcount );
19 19
20size_t mutex_get_torrent_count(); 20size_t mutex_get_torrent_count(void);
21 21
22typedef enum { 22typedef enum {
23 TASK_STATS_CONNS = 0x0001, 23 TASK_STATS_CONNS = 0x0001,
diff --git a/ot_stats.h b/ot_stats.h
index 6a2515b..ed60f68 100644
--- a/ot_stats.h
+++ b/ot_stats.h
@@ -40,11 +40,11 @@ enum {
40 40
41void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event_data ); 41void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event_data );
42void stats_deliver( int64 sock, int tasktype ); 42void stats_deliver( int64 sock, int tasktype );
43void stats_cleanup(); 43void stats_cleanup( void );
44size_t return_stats_for_tracker( char *reply, int mode, int format ); 44size_t return_stats_for_tracker( char *reply, int mode, int format );
45size_t stats_return_tracker_version( char *reply ); 45size_t stats_return_tracker_version( char *reply );
46void stats_init( ); 46void stats_init( void );
47void stats_deinit( ); 47void stats_deinit( void );
48 48
49extern const char *g_version_rijndael_c; 49extern const char *g_version_rijndael_c;
50extern const char *g_version_livesync_c; 50extern const char *g_version_livesync_c;
diff --git a/trackerlogic.h b/trackerlogic.h
index 87b9138..ef59179 100644
--- a/trackerlogic.h
+++ b/trackerlogic.h
@@ -133,7 +133,6 @@ struct ot_workstruct {
133 char *peer_id; 133 char *peer_id;
134 134
135 /* HTTP specific, non static */ 135 /* HTTP specific, non static */
136 int keep_alive;
137 char *request; 136 char *request;
138 ssize_t request_size; 137 ssize_t request_size;
139 ssize_t header_size; 138 ssize_t header_size;
@@ -143,6 +142,8 @@ struct ot_workstruct {
143 /* Entropy state for rand48 function so that threads don't need to acquire mutexes for 142 /* Entropy state for rand48 function so that threads don't need to acquire mutexes for
144 global random() or arc4random() state, which causes heavy load on linuxes */ 143 global random() or arc4random() state, which causes heavy load on linuxes */
145 uint16_t rand48_state[3]; 144 uint16_t rand48_state[3];
145
146 int keep_alive;
146}; 147};
147 148
148/* 149/*
@@ -163,7 +164,7 @@ struct ot_workstruct {
163#error Live logging networks disabled at the moment. 164#error Live logging networks disabled at the moment.
164#endif 165#endif
165 166
166void trackerlogic_init( ); 167void trackerlogic_init( void );
167void trackerlogic_deinit( void ); 168void trackerlogic_deinit( void );
168void exerr( char * message ); 169void exerr( char * message );
169 170