diff options
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | opentracker.c | 32 | ||||
| -rw-r--r-- | ot_accesslist.c | 34 | ||||
| -rw-r--r-- | ot_accesslist.h | 6 | ||||
| -rw-r--r-- | ot_config.c | 2 | ||||
| -rw-r--r-- | ot_fdstate.c | 188 | ||||
| -rw-r--r-- | ot_fdstate.h | 57 | ||||
| -rw-r--r-- | ot_fullscrape.c | 14 | ||||
| -rw-r--r-- | ot_hex.c | 4 | ||||
| -rw-r--r-- | ot_hex.h | 4 | ||||
| -rw-r--r-- | ot_http.c | 75 | ||||
| -rw-r--r-- | ot_iovec.c | 10 | ||||
| -rw-r--r-- | ot_iovec.h | 6 | ||||
| -rw-r--r-- | ot_stats.c | 22 | ||||
| -rw-r--r-- | ot_sync.c | 6 | ||||
| -rw-r--r-- | ot_urlencoded.c (renamed from scan_urlencoded_query.c) | 16 | ||||
| -rw-r--r-- | ot_urlencoded.h (renamed from scan_urlencoded_query.h) | 8 | ||||
| -rw-r--r-- | ot_vector.c | 10 | ||||
| -rw-r--r-- | ot_vector.h | 2 | ||||
| -rw-r--r-- | proxy.c | 17 | ||||
| -rw-r--r-- | tests/runner.c | 3 | ||||
| -rw-r--r-- | tests/t_fdstate.c | 224 | ||||
| -rw-r--r-- | tests/t_hex.c | 28 | ||||
| -rw-r--r-- | tests/t_iovec.c | 20 | ||||
| -rw-r--r-- | tests/t_urlencoded.c (renamed from tests/t_scan_urlencoded_query.c) | 66 | ||||
| -rw-r--r-- | tests/t_vector.c | 16 | ||||
| -rw-r--r-- | tests/test.h | 3 | ||||
| -rw-r--r-- | trackerlogic.c | 6 |
28 files changed, 677 insertions, 212 deletions
| @@ -68,9 +68,9 @@ CFLAGS+=-I$(LIBOWFAT_HEADERS) -DGIT_VERSION=$(GIT_VERSION) -Wall -pipe -pthread | |||
| 68 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread | 68 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread |
| 69 | 69 | ||
| 70 | BINARY =opentracker | 70 | BINARY =opentracker |
| 71 | HEADERS=trackerlogic.h scan_urlencoded_query.h ot_batch.h ot_buf.h ot_hex.h ot_ip.h ot_config.h ot_scan.h ot_socket.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 | 71 | HEADERS=trackerlogic.h ot_urlencoded.h ot_batch.h ot_buf.h ot_fdstate.h ot_hex.h ot_ip.h ot_config.h ot_scan.h ot_socket.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 |
| 72 | SOURCES=opentracker.c trackerlogic.c scan_urlencoded_query.c ot_batch.c ot_buf.c ot_hex.c ot_ip.c ot_config.c ot_scan.c ot_socket.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 | 72 | SOURCES=opentracker.c trackerlogic.c ot_urlencoded.c ot_batch.c ot_buf.c ot_fdstate.c ot_hex.c ot_ip.c ot_config.c ot_scan.c ot_socket.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 |
| 73 | SOURCES_proxy=proxy.c ot_batch.c ot_vector.c ot_mutex.c ot_random.c ot_scan.c ot_ip.c ot_socket.c | 73 | SOURCES_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 |
| 74 | 74 | ||
| 75 | OBJECTS = $(SOURCES:%.c=%.o) | 75 | OBJECTS = $(SOURCES:%.c=%.o) |
| 76 | OBJECTS_debug = $(SOURCES:%.c=%.debug.o) | 76 | OBJECTS_debug = $(SOURCES:%.c=%.debug.o) |
| @@ -119,8 +119,8 @@ $(OBJECTS_proxy_debug): $(HEADERS) | |||
| 119 | # has to. tests/stubs.c supplies the few symbols those modules reference but | 119 | # has to. tests/stubs.c supplies the few symbols those modules reference but |
| 120 | # the tests never reach. | 120 | # the tests never reach. |
| 121 | TESTBIN=tests/runner | 121 | TESTBIN=tests/runner |
| 122 | TEST_SOURCES=tests/runner.c tests/test.c tests/stubs.c tests/t_scan_urlencoded_query.c tests/t_iovec.c tests/t_vector.c tests/t_random.c tests/t_hex.c tests/t_accesslist.c tests/t_scan.c tests/t_buf.c tests/t_ip.c tests/t_socket.c tests/t_mutex.c tests/t_batch.c | 122 | TEST_SOURCES=tests/runner.c tests/test.c tests/stubs.c tests/t_urlencoded.c tests/t_iovec.c tests/t_vector.c tests/t_random.c tests/t_hex.c tests/t_accesslist.c tests/t_scan.c tests/t_buf.c tests/t_ip.c tests/t_socket.c tests/t_mutex.c tests/t_batch.c tests/t_fdstate.c |
| 123 | TEST_UNITS=scan_urlencoded_query.c ot_batch.c ot_buf.c ot_ip.c ot_socket.c ot_iovec.c ot_vector.c ot_random.c ot_hex.c ot_scan.c ot_accesslist.c ot_mutex.c | 123 | TEST_UNITS=ot_urlencoded.c ot_batch.c ot_fdstate.c ot_buf.c ot_ip.c ot_socket.c ot_iovec.c ot_vector.c ot_random.c ot_hex.c ot_scan.c ot_accesslist.c ot_mutex.c |
| 124 | TEST_HEADERS=tests/test.h $(HEADERS) | 124 | TEST_HEADERS=tests/test.h $(HEADERS) |
| 125 | # Tests reach code that sits behind feature flags, so the units under test are | 125 | # Tests reach code that sits behind feature flags, so the units under test are |
| 126 | # built with those features enabled. A test binary is not a production binary. | 126 | # built with those features enabled. A test binary is not a production binary. |
diff --git a/opentracker.c b/opentracker.c index 50fff29..f0f6404 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "ot_mutex.h" | 34 | #include "ot_mutex.h" |
| 35 | #include "ot_random.h" | 35 | #include "ot_random.h" |
| 36 | #include "ot_scan.h" | 36 | #include "ot_scan.h" |
| 37 | #include "ot_fdstate.h" | ||
| 37 | #include "ot_socket.h" | 38 | #include "ot_socket.h" |
| 38 | #include "ot_stats.h" | 39 | #include "ot_stats.h" |
| 39 | #include "ot_udp.h" | 40 | #include "ot_udp.h" |
| @@ -117,7 +118,7 @@ static ssize_t header_complete(char *request, ssize_t byte_count) { | |||
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | static void handle_dead(const int64_t sock) { | 120 | static void handle_dead(const int64_t sock) { |
| 120 | struct http_data *cookie = io_getcookie(sock); | 121 | struct http_data *cookie = fdstate_cookie(sock); |
| 121 | if (cookie) { | 122 | if (cookie) { |
| 122 | if (cookie->batch) | 123 | if (cookie->batch) |
| 123 | batch_reset(cookie->batch); | 124 | batch_reset(cookie->batch); |
| @@ -127,11 +128,13 @@ static void handle_dead(const int64_t sock) { | |||
| 127 | mutex_workqueue_canceltask(sock); | 128 | mutex_workqueue_canceltask(sock); |
| 128 | free(cookie); | 129 | free(cookie); |
| 129 | } | 130 | } |
| 131 | /* The generation has to move before the kernel can reissue the number */ | ||
| 132 | fdstate_close(sock); | ||
| 130 | io_close(sock); | 133 | io_close(sock); |
| 131 | } | 134 | } |
| 132 | 135 | ||
| 133 | static void handle_read(const int64_t sock, struct ot_workstruct *ws) { | 136 | static void handle_read(const int64_t sock, struct ot_workstruct *ws) { |
| 134 | struct http_data *cookie = io_getcookie(sock); | 137 | struct http_data *cookie = fdstate_cookie(sock); |
| 135 | ssize_t byte_count = io_tryread(sock, ws->inbuf, G_INBUF_SIZE); | 138 | ssize_t byte_count = io_tryread(sock, ws->inbuf, G_INBUF_SIZE); |
| 136 | 139 | ||
| 137 | if (byte_count == 0 || byte_count == -3) { | 140 | if (byte_count == 0 || byte_count == -3) { |
| @@ -175,7 +178,7 @@ static void handle_read(const int64_t sock, struct ot_workstruct *ws) { | |||
| 175 | } | 178 | } |
| 176 | 179 | ||
| 177 | static void handle_write(const int64_t sock) { | 180 | static void handle_write(const int64_t sock) { |
| 178 | struct http_data *cookie = io_getcookie(sock); | 181 | struct http_data *cookie = fdstate_cookie(sock); |
| 179 | int chunked = 0; | 182 | int chunked = 0; |
| 180 | 183 | ||
| 181 | if (cookie) { | 184 | if (cookie) { |
| @@ -204,7 +207,6 @@ static void handle_accept(const int64_t serversocket) { | |||
| 204 | int64_t sock; | 207 | int64_t sock; |
| 205 | ot_ip6 ip; | 208 | ot_ip6 ip; |
| 206 | uint16_t port; | 209 | uint16_t port; |
| 207 | tai6464 t; | ||
| 208 | 210 | ||
| 209 | while ((sock = socket_accept(serversocket, ip, &port)) != -1) { | 211 | while ((sock = socket_accept(serversocket, ip, &port)) != -1) { |
| 210 | 212 | ||
| @@ -218,16 +220,11 @@ static void handle_accept(const int64_t serversocket) { | |||
| 218 | memset(cookie, 0, sizeof(struct http_data)); | 220 | memset(cookie, 0, sizeof(struct http_data)); |
| 219 | memcpy(cookie->ip, ip, sizeof(ot_ip6)); | 221 | memcpy(cookie->ip, ip, sizeof(ot_ip6)); |
| 220 | 222 | ||
| 221 | io_setcookie(sock, cookie); | 223 | fdstate_open(sock, cookie, g_now_seconds + OT_CLIENT_TIMEOUT); |
| 222 | io_wantread(sock); | 224 | io_wantread(sock); |
| 223 | 225 | ||
| 224 | stats_issue_event(EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip); | 226 | stats_issue_event(EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip); |
| 225 | 227 | ||
| 226 | /* That breaks taia encapsulation. But there is no way to take system | ||
| 227 | time this often in FreeBSD and libowfat does not allow to set unix time */ | ||
| 228 | taia_uint(&t, 0); /* Clear t */ | ||
| 229 | tai_unix(&(t.sec), (g_now_seconds + OT_CLIENT_TIMEOUT)); | ||
| 230 | io_timeout(sock, t); | ||
| 231 | } | 228 | } |
| 232 | io_eagain(serversocket); | 229 | io_eagain(serversocket); |
| 233 | } | 230 | } |
| @@ -259,7 +256,7 @@ static void *server_mainloop(void *args) { | |||
| 259 | io_wait(); | 256 | io_wait(); |
| 260 | 257 | ||
| 261 | while ((sock = io_canread()) != -1) { | 258 | while ((sock = io_canread()) != -1) { |
| 262 | const void *cookie = io_getcookie(sock); | 259 | const void *cookie = fdstate_cookie(sock); |
| 263 | if ((intptr_t)cookie == FLAG_TCP) | 260 | if ((intptr_t)cookie == FLAG_TCP) |
| 264 | handle_accept(sock); | 261 | handle_accept(sock); |
| 265 | else if ((intptr_t)cookie == FLAG_UDP) | 262 | else if ((intptr_t)cookie == FLAG_UDP) |
| @@ -277,7 +274,9 @@ static void *server_mainloop(void *args) { | |||
| 277 | handle_write(sock); | 274 | handle_write(sock); |
| 278 | 275 | ||
| 279 | if (g_now_seconds > next_timeout_check) { | 276 | if (g_now_seconds > next_timeout_check) { |
| 280 | while ((sock = io_timeouted()) != -1) | 277 | int cursor = 0; |
| 278 | |||
| 279 | while ((sock = fdstate_next_expired(g_now_seconds, &cursor)) != -1) | ||
| 281 | handle_dead(sock); | 280 | handle_dead(sock); |
| 282 | next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; | 281 | next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; |
| 283 | } | 282 | } |
| @@ -323,7 +322,7 @@ static void listen_bind_one(ot_listen *entry) { | |||
| 323 | if (!io_fd(entry->sock)) | 322 | if (!io_fd(entry->sock)) |
| 324 | panic("io_fd"); | 323 | panic("io_fd"); |
| 325 | 324 | ||
| 326 | io_setcookie(entry->sock, (void *)entry->proto); | 325 | fdstate_open(entry->sock, (void *)entry->proto, 0); |
| 327 | io_wantread(entry->sock); | 326 | io_wantread(entry->sock); |
| 328 | 327 | ||
| 329 | #ifdef _DEBUG | 328 | #ifdef _DEBUG |
| @@ -376,7 +375,7 @@ void load_state(const char *const state_filename) { | |||
| 376 | while (fgets(inbuf, sizeof(inbuf), state_filehandle)) { | 375 | while (fgets(inbuf, sizeof(inbuf), state_filehandle)) { |
| 377 | size_t i; | 376 | size_t i; |
| 378 | 377 | ||
| 379 | if (!hex_tohash(infohash, inbuf)) | 378 | if (!hex_to_hash(infohash, inbuf)) |
| 380 | continue; | 379 | continue; |
| 381 | i = 2 * sizeof(ot_hash); | 380 | i = 2 * sizeof(ot_hash); |
| 382 | 381 | ||
| @@ -452,6 +451,8 @@ int main(int argc, char **argv) { | |||
| 452 | pthread_t thread_id; /* time cacher */ | 451 | pthread_t thread_id; /* time cacher */ |
| 453 | 452 | ||
| 454 | random_init(); | 453 | random_init(); |
| 454 | if (fdstate_init() == -1) | ||
| 455 | panic("fdstate_init"); | ||
| 455 | config_parse(argc, argv); | 456 | config_parse(argc, argv); |
| 456 | 457 | ||
| 457 | listen_bind_all(); | 458 | listen_bind_all(); |
| @@ -477,7 +478,7 @@ int main(int argc, char **argv) { | |||
| 477 | panic("selfpipe io_fd failed: "); | 478 | panic("selfpipe io_fd failed: "); |
| 478 | if (!io_fd(g_self_pipe[1])) | 479 | if (!io_fd(g_self_pipe[1])) |
| 479 | panic("selfpipe io_fd failed: "); | 480 | panic("selfpipe io_fd failed: "); |
| 480 | io_setcookie(g_self_pipe[0], (void *)FLAG_SELFPIPE); | 481 | fdstate_open(g_self_pipe[0], (void *)FLAG_SELFPIPE, 0); |
| 481 | io_wantread(g_self_pipe[0]); | 482 | io_wantread(g_self_pipe[0]); |
| 482 | 483 | ||
| 483 | /* Init all sub systems. This call may fail with an exit() */ | 484 | /* Init all sub systems. This call may fail with an exit() */ |
| @@ -498,5 +499,6 @@ int main(int argc, char **argv) { | |||
| 498 | 499 | ||
| 499 | server_mainloop(0); | 500 | server_mainloop(0); |
| 500 | 501 | ||
| 502 | fdstate_deinit(); | ||
| 501 | return 0; | 503 | return 0; |
| 502 | } | 504 | } |
diff --git a/ot_accesslist.c b/ot_accesslist.c index d7e88ee..79a11a5 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c | |||
| @@ -110,7 +110,7 @@ size_t accesslist_parse_hashes(ot_hash *dest, size_t capacity, const char *buf, | |||
| 110 | size_t count = 0; | 110 | size_t count = 0; |
| 111 | 111 | ||
| 112 | while (count < capacity && end - offs >= 40) { | 112 | while (count < capacity && end - offs >= 40) { |
| 113 | if (hex_tohash(dest[count], offs)) { | 113 | if (hex_to_hash(dest[count], offs)) { |
| 114 | offs += 40; | 114 | offs += 40; |
| 115 | 115 | ||
| 116 | if (offs == end || !hex_isdigit((unsigned char)*offs)) | 116 | if (offs == end || !hex_isdigit((unsigned char)*offs)) |
| @@ -308,7 +308,7 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 308 | if (linelen < 41) | 308 | if (linelen < 41) |
| 309 | continue; | 309 | continue; |
| 310 | 310 | ||
| 311 | if (!hex_tohash(info_hash, line)) | 311 | if (!hex_to_hash(info_hash, line)) |
| 312 | continue; | 312 | continue; |
| 313 | 313 | ||
| 314 | /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the | 314 | /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the |
| @@ -339,7 +339,7 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 339 | } | 339 | } |
| 340 | } else { | 340 | } else { |
| 341 | int exactmatch = 0; | 341 | int exactmatch = 0; |
| 342 | ot_hash *insert_point = binary_search(info_hash, (*adding_to)->list, (*adding_to)->size, sizeof(ot_hash), OT_HASH_COMPARE_SIZE, &exactmatch); | 342 | ot_hash *insert_point = vector_binary_search(info_hash, (*adding_to)->list, (*adding_to)->size, sizeof(ot_hash), OT_HASH_COMPARE_SIZE, &exactmatch); |
| 343 | 343 | ||
| 344 | /* Only if the info hash is not in the adding_to list, create a new head with that entry */ | 344 | /* Only if the info hash is not in the adding_to list, create a new head with that entry */ |
| 345 | if (!exactmatch) { | 345 | if (!exactmatch) { |
| @@ -416,7 +416,7 @@ void accesslist_cleanup(void) { | |||
| 416 | } | 416 | } |
| 417 | #endif | 417 | #endif |
| 418 | 418 | ||
| 419 | int address_in_net(const ot_ip6 address, const ot_net *net) { | 419 | int accesslist_address_in_net(const ot_ip6 address, const ot_net *net) { |
| 420 | int bits = net->bits, checkbits = (0x7f00 >> (bits & 7)); | 420 | int bits = net->bits, checkbits = (0x7f00 >> (bits & 7)); |
| 421 | int result = memcmp(address, &net->address, bits >> 3); | 421 | int result = memcmp(address, &net->address, bits >> 3); |
| 422 | if (!result && (bits & 7)) | 422 | if (!result && (bits & 7)) |
| @@ -424,7 +424,7 @@ int address_in_net(const ot_ip6 address, const ot_net *net) { | |||
| 424 | return result == 0; | 424 | return result == 0; |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | void *set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, const size_t member_size) { | 427 | void *accesslist_set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, const size_t member_size) { |
| 428 | size_t i; | 428 | size_t i; |
| 429 | int exactmatch; | 429 | int exactmatch; |
| 430 | 430 | ||
| @@ -435,7 +435,7 @@ void *set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, | |||
| 435 | /* Check each net in vector for overlap */ | 435 | /* Check each net in vector for overlap */ |
| 436 | uint8_t *member = ((uint8_t *)vector->data); | 436 | uint8_t *member = ((uint8_t *)vector->data); |
| 437 | for (i = 0; i < vector->size; ++i) { | 437 | for (i = 0; i < vector->size; ++i) { |
| 438 | if (address_in_net(*(ot_ip6 *)member, net) || address_in_net(net->address, (ot_net *)member)) | 438 | if (accesslist_address_in_net(*(ot_ip6 *)member, net) || accesslist_address_in_net(net->address, (ot_net *)member)) |
| 439 | return 0; | 439 | return 0; |
| 440 | member += member_size; | 440 | member += member_size; |
| 441 | } | 441 | } |
| @@ -451,16 +451,16 @@ void *set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, | |||
| 451 | 451 | ||
| 452 | /* Takes a vector filled with { ot_net net, uint8_t[x] value }; | 452 | /* Takes a vector filled with { ot_net net, uint8_t[x] value }; |
| 453 | Returns value associated with the net, or NULL if not found */ | 453 | Returns value associated with the net, or NULL if not found */ |
| 454 | void *get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size) { | 454 | void *accesslist_get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size) { |
| 455 | int exactmatch; | 455 | int exactmatch; |
| 456 | /* This binary search will return a pointer to the first non-containing network... */ | 456 | /* This binary search will return a pointer to the first non-containing network... */ |
| 457 | ot_net *net = binary_search(address, vector->data, vector->size, member_size, sizeof(ot_ip6), &exactmatch); | 457 | ot_net *net = vector_binary_search(address, vector->data, vector->size, member_size, sizeof(ot_ip6), &exactmatch); |
| 458 | if (!net) | 458 | if (!net) |
| 459 | return NULL; | 459 | return NULL; |
| 460 | /* ... so we'll need to move back one step unless we've exactly hit the first address in network */ | 460 | /* ... so we'll need to move back one step unless we've exactly hit the first address in network */ |
| 461 | if (!exactmatch && ((void *)net > vector->data)) | 461 | if (!exactmatch && ((void *)net > vector->data)) |
| 462 | --net; | 462 | --net; |
| 463 | if (!address_in_net(address, net)) | 463 | if (!accesslist_address_in_net(address, net)) |
| 464 | return NULL; | 464 | return NULL; |
| 465 | return (void *)net; | 465 | return (void *)net; |
| 466 | } | 466 | } |
| @@ -472,7 +472,7 @@ static pthread_mutex_t g_lognets_list_mutex = PTHREAD_MUTEX_INITIALIZER; | |||
| 472 | 472 | ||
| 473 | void loglist_add_network(const ot_net *net) { | 473 | void loglist_add_network(const ot_net *net) { |
| 474 | pthread_mutex_lock(&g_lognets_list_mutex); | 474 | pthread_mutex_lock(&g_lognets_list_mutex); |
| 475 | set_value_for_net(net, &g_lognets_list, NULL, sizeof(ot_net)); | 475 | accesslist_set_value_for_net(net, &g_lognets_list, NULL, sizeof(ot_net)); |
| 476 | pthread_mutex_unlock(&g_lognets_list_mutex); | 476 | pthread_mutex_unlock(&g_lognets_list_mutex); |
| 477 | } | 477 | } |
| 478 | 478 | ||
| @@ -487,7 +487,7 @@ void loglist_reset(void) { | |||
| 487 | int loglist_check_address(const ot_ip6 address) { | 487 | int loglist_check_address(const ot_ip6 address) { |
| 488 | int result; | 488 | int result; |
| 489 | pthread_mutex_lock(&g_lognets_list_mutex); | 489 | pthread_mutex_lock(&g_lognets_list_mutex); |
| 490 | result = (NULL != get_value_for_net(address, &g_lognets_list, sizeof(ot_net))); | 490 | result = (NULL != accesslist_get_value_for_net(address, &g_lognets_list, sizeof(ot_net))); |
| 491 | pthread_mutex_unlock(&g_lognets_list_mutex); | 491 | pthread_mutex_unlock(&g_lognets_list_mutex); |
| 492 | return result; | 492 | return result; |
| 493 | } | 493 | } |
| @@ -508,17 +508,17 @@ int proxylist_add_network(const ot_net *proxy, const ot_net *net) { | |||
| 508 | pthread_mutex_lock(&g_proxies_list_mutex); | 508 | pthread_mutex_lock(&g_proxies_list_mutex); |
| 509 | 509 | ||
| 510 | /* If we have a direct hit, use and extend the vector there */ | 510 | /* If we have a direct hit, use and extend the vector there */ |
| 511 | map = binary_search(proxy, g_proxies_list.data, g_proxies_list.size, sizeof(ot_proxymap), sizeof(ot_net), &exactmatch); | 511 | map = vector_binary_search(proxy, g_proxies_list.data, g_proxies_list.size, sizeof(ot_proxymap), sizeof(ot_net), &exactmatch); |
| 512 | 512 | ||
| 513 | if (!map || !exactmatch) { | 513 | if (!map || !exactmatch) { |
| 514 | /* else see, if we've got overlapping networks | 514 | /* else see, if we've got overlapping networks |
| 515 | and get a new empty vector if not */ | 515 | and get a new empty vector if not */ |
| 516 | ot_vector empty; | 516 | ot_vector empty; |
| 517 | memset(&empty, 0, sizeof(ot_vector)); | 517 | memset(&empty, 0, sizeof(ot_vector)); |
| 518 | map = set_value_for_net(proxy, &g_proxies_list, &empty, sizeof(ot_proxymap)); | 518 | map = accesslist_set_value_for_net(proxy, &g_proxies_list, &empty, sizeof(ot_proxymap)); |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | if (map && set_value_for_net(net, &map->networks, NULL, sizeof(ot_net))) | 521 | if (map && accesslist_set_value_for_net(net, &map->networks, NULL, sizeof(ot_net))) |
| 522 | result = 1; | 522 | result = 1; |
| 523 | 523 | ||
| 524 | pthread_mutex_unlock(&g_proxies_list_mutex); | 524 | pthread_mutex_unlock(&g_proxies_list_mutex); |
| @@ -531,8 +531,8 @@ int proxylist_check_proxy(const ot_ip6 proxy, const ot_ip6 address) { | |||
| 531 | 531 | ||
| 532 | pthread_mutex_lock(&g_proxies_list_mutex); | 532 | pthread_mutex_lock(&g_proxies_list_mutex); |
| 533 | 533 | ||
| 534 | if ((map = get_value_for_net(proxy, &g_proxies_list, sizeof(ot_proxymap)))) | 534 | if ((map = accesslist_get_value_for_net(proxy, &g_proxies_list, sizeof(ot_proxymap)))) |
| 535 | if (!address || get_value_for_net(address, &map->networks, sizeof(ot_net))) | 535 | if (!address || accesslist_get_value_for_net(address, &map->networks, sizeof(ot_net))) |
| 536 | result = 1; | 536 | result = 1; |
| 537 | 537 | ||
| 538 | pthread_mutex_unlock(&g_proxies_list_mutex); | 538 | pthread_mutex_unlock(&g_proxies_list_mutex); |
| @@ -587,7 +587,7 @@ int accesslist_bless_net(ot_net *net, ot_permissions permissions) { | |||
| 587 | int accesslist_is_blessed(ot_ip6 ip, ot_permissions permissions) { | 587 | int accesslist_is_blessed(ot_ip6 ip, ot_permissions permissions) { |
| 588 | size_t i; | 588 | size_t i; |
| 589 | for (i = 0; i < g_admin_nets_count; ++i) | 589 | for (i = 0; i < g_admin_nets_count; ++i) |
| 590 | if (address_in_net(ip, g_admin_nets + i) && (g_admin_nets_permissions[i] & permissions)) | 590 | if (accesslist_address_in_net(ip, g_admin_nets + i) && (g_admin_nets_permissions[i] & permissions)) |
| 591 | return 1; | 591 | return 1; |
| 592 | return 0; | 592 | return 0; |
| 593 | } | 593 | } |
diff --git a/ot_accesslist.h b/ot_accesslist.h index 9dfdd95..0a8bf4c 100644 --- a/ot_accesslist.h +++ b/ot_accesslist.h | |||
| @@ -40,7 +40,7 @@ extern const char *g_accesslist_pipe_delete; | |||
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | /* Test if an address is subset of an ot_net, return value is considered a bool */ | 42 | /* Test if an address is subset of an ot_net, return value is considered a bool */ |
| 43 | int address_in_net(const ot_ip6 address, const ot_net *net); | 43 | int accesslist_address_in_net(const ot_ip6 address, const ot_net *net); |
| 44 | 44 | ||
| 45 | /* Store a value into a vector of struct { ot_net net, uint8_t[x] value } member; | 45 | /* Store a value into a vector of struct { ot_net net, uint8_t[x] value } member; |
| 46 | returns NULL | 46 | returns NULL |
| @@ -51,13 +51,13 @@ int address_in_net(const ot_ip6 address, const ot_net *net); | |||
| 51 | returns pointer to new member in vector for success | 51 | returns pointer to new member in vector for success |
| 52 | member_size can be sizeof(ot_net) to reduce the lookup to a boolean mapping | 52 | member_size can be sizeof(ot_net) to reduce the lookup to a boolean mapping |
| 53 | */ | 53 | */ |
| 54 | void *set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, const size_t member_size); | 54 | void *accesslist_set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, const size_t member_size); |
| 55 | 55 | ||
| 56 | /* Takes a vector filled with struct { ot_net net, uint8_t[x] value } member; | 56 | /* Takes a vector filled with struct { ot_net net, uint8_t[x] value } member; |
| 57 | Returns pointer to _member_ associated with the net, or NULL if not found | 57 | Returns pointer to _member_ associated with the net, or NULL if not found |
| 58 | member_size can be sizeof(ot_net) to reduce the lookup to a boolean mapping | 58 | member_size can be sizeof(ot_net) to reduce the lookup to a boolean mapping |
| 59 | */ | 59 | */ |
| 60 | void *get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size); | 60 | void *accesslist_get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size); |
| 61 | 61 | ||
| 62 | #ifdef WANT_IP_FROM_PROXY | 62 | #ifdef WANT_IP_FROM_PROXY |
| 63 | int proxylist_add_network(const ot_net *proxy, const ot_net *net); | 63 | int proxylist_add_network(const ot_net *proxy, const ot_net *net); |
diff --git a/ot_config.c b/ot_config.c index e9666f9..a5fc06e 100644 --- a/ot_config.c +++ b/ot_config.c | |||
| @@ -264,7 +264,7 @@ static config_kind parse_config_key(char **p) { | |||
| 264 | return CONFIG_UNKNOWN; | 264 | return CONFIG_UNKNOWN; |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | int parse_configfile(char *config_filename) { | 267 | static int parse_configfile(char *config_filename) { |
| 268 | FILE *config_file_handle; | 268 | FILE *config_file_handle; |
| 269 | char inbuf[512]; | 269 | char inbuf[512]; |
| 270 | ot_ip6 tmpip; | 270 | ot_ip6 tmpip; |
diff --git a/ot_fdstate.c b/ot_fdstate.c new file mode 100644 index 0000000..7f73d3d --- /dev/null +++ b/ot_fdstate.c | |||
| @@ -0,0 +1,188 @@ | |||
| 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 <stdatomic.h> | ||
| 8 | #include <stdint.h> | ||
| 9 | #include <stdlib.h> | ||
| 10 | #include <sys/mman.h> | ||
| 11 | #include <sys/resource.h> | ||
| 12 | #include <sys/types.h> | ||
| 13 | |||
| 14 | /* Opentracker */ | ||
| 15 | #include "ot_fdstate.h" | ||
| 16 | |||
| 17 | enum { FD_FREE, FD_IDLE, FD_BUSY, FD_CLOSING }; | ||
| 18 | |||
| 19 | /* Generation and state share one word so that taking the state is also a | ||
| 20 | check that the generation has not moved */ | ||
| 21 | #define FD_GEN(w) ((uint32_t)((w) >> 32)) | ||
| 22 | #define FD_ST(w) ((uint32_t)(((w) >> 24) & 0xff)) | ||
| 23 | #define FD_WORD(g, s) (((uint64_t)(g) << 32) | ((uint64_t)(s) << 24)) | ||
| 24 | #define FD_SET_ST(w, s) (((w) & ~(uint64_t)0xff000000) | ((uint64_t)(s) << 24)) | ||
| 25 | |||
| 26 | typedef struct { | ||
| 27 | _Atomic uint64_t state; | ||
| 28 | _Atomic(void *) cookie; | ||
| 29 | _Atomic ot_time expiry; | ||
| 30 | } ot_fdslot; | ||
| 31 | |||
| 32 | /* A descriptor the kernel can hand out is below the limit it was handed out | ||
| 33 | under, but the limit can be raised after we sized the table, so an out of | ||
| 34 | range descriptor is rejected */ | ||
| 35 | #define FD_SLOTS_MAX (1u << 20) | ||
| 36 | |||
| 37 | static ot_fdslot *g_slots; | ||
| 38 | static size_t g_slot_count; | ||
| 39 | /* Descriptors are handed out lowest first, so a sweep only has to walk as | ||
| 40 | far as the highest one ever seen rather than the whole table. */ | ||
| 41 | static _Atomic size_t g_slot_highest; | ||
| 42 | |||
| 43 | int fdstate_init(void) { | ||
| 44 | struct rlimit limit; | ||
| 45 | size_t count = FD_SLOTS_MAX; | ||
| 46 | |||
| 47 | if (getrlimit(RLIMIT_NOFILE, &limit) == 0 && limit.rlim_cur != RLIM_INFINITY && limit.rlim_cur < FD_SLOTS_MAX) | ||
| 48 | count = (size_t)limit.rlim_cur; | ||
| 49 | |||
| 50 | g_slots = mmap(NULL, count * sizeof(ot_fdslot), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
| 51 | if (g_slots == MAP_FAILED) { | ||
| 52 | g_slots = NULL; | ||
| 53 | return -1; | ||
| 54 | } | ||
| 55 | |||
| 56 | g_slot_count = count; | ||
| 57 | atomic_store(&g_slot_highest, 0); | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | void fdstate_deinit(void) { | ||
| 62 | if (g_slots) | ||
| 63 | munmap(g_slots, g_slot_count * sizeof(ot_fdslot)); | ||
| 64 | g_slots = NULL; | ||
| 65 | g_slot_count = 0; | ||
| 66 | atomic_store(&g_slot_highest, 0); | ||
| 67 | } | ||
| 68 | |||
| 69 | size_t fdstate_slots(void) { return g_slot_count; } | ||
| 70 | |||
| 71 | static ot_fdslot *fdstate_slot(int fd) { | ||
| 72 | if (fd < 0 || (size_t)fd >= g_slot_count) | ||
| 73 | return NULL; | ||
| 74 | return g_slots + fd; | ||
| 75 | } | ||
| 76 | |||
| 77 | uint32_t fdstate_open(int fd, void *cookie, ot_time expiry) { | ||
| 78 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 79 | uint64_t word; | ||
| 80 | |||
| 81 | if (!slot) | ||
| 82 | return 0; | ||
| 83 | |||
| 84 | { | ||
| 85 | size_t highest = atomic_load_explicit(&g_slot_highest, memory_order_relaxed); | ||
| 86 | |||
| 87 | while ((size_t)fd > highest && | ||
| 88 | !atomic_compare_exchange_weak_explicit(&g_slot_highest, &highest, (size_t)fd, memory_order_relaxed, | ||
| 89 | memory_order_relaxed)) | ||
| 90 | ; | ||
| 91 | } | ||
| 92 | |||
| 93 | word = atomic_load_explicit(&slot->state, memory_order_relaxed); | ||
| 94 | atomic_store_explicit(&slot->cookie, cookie, memory_order_relaxed); | ||
| 95 | atomic_store_explicit(&slot->expiry, expiry, memory_order_relaxed); | ||
| 96 | /* Publishes the two above to whoever claims the slot next */ | ||
| 97 | atomic_store_explicit(&slot->state, FD_WORD(FD_GEN(word), FD_IDLE), memory_order_release); | ||
| 98 | |||
| 99 | return FD_GEN(word); | ||
| 100 | } | ||
| 101 | |||
| 102 | int fdstate_claim(int fd, uint32_t generation) { | ||
| 103 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 104 | uint64_t word; | ||
| 105 | |||
| 106 | if (!slot) | ||
| 107 | return 0; | ||
| 108 | |||
| 109 | word = atomic_load_explicit(&slot->state, memory_order_acquire); | ||
| 110 | for (;;) { | ||
| 111 | if (FD_GEN(word) != generation || FD_ST(word) != FD_IDLE) | ||
| 112 | return 0; | ||
| 113 | if (atomic_compare_exchange_weak_explicit(&slot->state, &word, FD_SET_ST(word, FD_BUSY), memory_order_acquire, | ||
| 114 | memory_order_relaxed)) | ||
| 115 | return 1; | ||
| 116 | /* word now holds what was really there, so the test above runs again */ | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | void fdstate_release(int fd) { | ||
| 121 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 122 | uint64_t word; | ||
| 123 | |||
| 124 | if (!slot) | ||
| 125 | return; | ||
| 126 | |||
| 127 | word = atomic_load_explicit(&slot->state, memory_order_relaxed); | ||
| 128 | atomic_store_explicit(&slot->state, FD_SET_ST(word, FD_IDLE), memory_order_release); | ||
| 129 | } | ||
| 130 | |||
| 131 | int fdstate_claim_expired(int fd, ot_time now) { | ||
| 132 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 133 | uint64_t word; | ||
| 134 | ot_time expiry; | ||
| 135 | |||
| 136 | if (!slot) | ||
| 137 | return 0; | ||
| 138 | |||
| 139 | /* Reading before asking for the slot keeps the common case, a descriptor | ||
| 140 | that has not expired, off the bus entirely */ | ||
| 141 | word = atomic_load_explicit(&slot->state, memory_order_relaxed); | ||
| 142 | if (FD_ST(word) != FD_IDLE) | ||
| 143 | return 0; | ||
| 144 | expiry = atomic_load_explicit(&slot->expiry, memory_order_relaxed); | ||
| 145 | if (!expiry || expiry > now) | ||
| 146 | return 0; | ||
| 147 | |||
| 148 | /* Nothing can move the expiry while the slot sits at FD_IDLE, so winning | ||
| 149 | the slot is the last word */ | ||
| 150 | return atomic_compare_exchange_strong_explicit(&slot->state, &word, FD_SET_ST(word, FD_CLOSING), memory_order_acquire, | ||
| 151 | memory_order_relaxed); | ||
| 152 | } | ||
| 153 | |||
| 154 | void fdstate_close(int fd) { | ||
| 155 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 156 | uint64_t word; | ||
| 157 | |||
| 158 | if (!slot) | ||
| 159 | return; | ||
| 160 | |||
| 161 | word = atomic_load_explicit(&slot->state, memory_order_relaxed); | ||
| 162 | atomic_store_explicit(&slot->cookie, NULL, memory_order_relaxed); | ||
| 163 | atomic_store_explicit(&slot->expiry, 0, memory_order_relaxed); | ||
| 164 | atomic_store_explicit(&slot->state, FD_WORD(FD_GEN(word) + 1, FD_FREE), memory_order_release); | ||
| 165 | } | ||
| 166 | |||
| 167 | int fdstate_next_expired(ot_time now, int *cursor) { | ||
| 168 | size_t highest = atomic_load_explicit(&g_slot_highest, memory_order_relaxed); | ||
| 169 | |||
| 170 | for (; (size_t)*cursor <= highest; ++*cursor) | ||
| 171 | if (fdstate_claim_expired(*cursor, now)) | ||
| 172 | return (*cursor)++; | ||
| 173 | |||
| 174 | return -1; | ||
| 175 | } | ||
| 176 | |||
| 177 | void *fdstate_cookie(int fd) { | ||
| 178 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 179 | |||
| 180 | return slot ? atomic_load_explicit(&slot->cookie, memory_order_relaxed) : NULL; | ||
| 181 | } | ||
| 182 | |||
| 183 | void fdstate_set_expiry(int fd, ot_time expiry) { | ||
| 184 | ot_fdslot *slot = fdstate_slot(fd); | ||
| 185 | |||
| 186 | if (slot) | ||
| 187 | atomic_store_explicit(&slot->expiry, expiry, memory_order_relaxed); | ||
| 188 | } | ||
diff --git a/ot_fdstate.h b/ot_fdstate.h new file mode 100644 index 0000000..88f685d --- /dev/null +++ b/ot_fdstate.h | |||
| @@ -0,0 +1,57 @@ | |||
| 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_FDSTATE_H__ | ||
| 7 | #define OT_FDSTATE_H__ | ||
| 8 | |||
| 9 | #include <stdint.h> | ||
| 10 | |||
| 11 | #include "trackerlogic.h" | ||
| 12 | |||
| 13 | /* What the tracker knows about a file descriptor: who owns it, when it | ||
| 14 | should be given up on, and whether anyone is working on it right now. | ||
| 15 | |||
| 16 | A descriptor number says nothing about identity, since the kernel hands | ||
| 17 | the same number out again as soon as it is closed. Every slot therefore | ||
| 18 | carries a generation that is bumped when the descriptor is given up, and | ||
| 19 | every caller that was told about a descriptor has to say which generation | ||
| 20 | it was told about. A caller holding a stale generation is turned away | ||
| 21 | instead of being handed somebody else's connection. | ||
| 22 | |||
| 23 | The table is sized once from RLIMIT_NOFILE and never moves, so looking a | ||
| 24 | descriptor up needs no synchronisation at all. */ | ||
| 25 | |||
| 26 | int fdstate_init(void); | ||
| 27 | void fdstate_deinit(void); | ||
| 28 | size_t fdstate_slots(void); | ||
| 29 | |||
| 30 | /* Take a freshly accepted descriptor into the table and return the | ||
| 31 | generation to quote when asking for it back. expiry of 0 never expires. */ | ||
| 32 | uint32_t fdstate_open(int fd, void *cookie, ot_time expiry); | ||
| 33 | |||
| 34 | /* Ask for exclusive use. Returns 0 if the descriptor has been recycled since | ||
| 35 | generation was handed out, or if somebody else is using it. */ | ||
| 36 | int fdstate_claim(int fd, uint32_t generation); | ||
| 37 | void fdstate_release(int fd); | ||
| 38 | |||
| 39 | /* The cleaner's side of the same thing: takes the descriptor only if nobody | ||
| 40 | is working on it and it really has expired. Never waits. */ | ||
| 41 | int fdstate_claim_expired(int fd, ot_time now); | ||
| 42 | |||
| 43 | /* Give the descriptor up. The generation is bumped here, which has to happen | ||
| 44 | before close(2) so that the kernel cannot reissue the number while events | ||
| 45 | quoting the old generation are still in flight. */ | ||
| 46 | void fdstate_close(int fd); | ||
| 47 | |||
| 48 | /* Walks the table for descriptors that have expired, handing back one at a | ||
| 49 | time until it returns -1. The cursor belongs to the caller, so several | ||
| 50 | sweepers can run without sharing anything. */ | ||
| 51 | int fdstate_next_expired(ot_time now, int *cursor); | ||
| 52 | |||
| 53 | /* Both only valid while the caller holds the descriptor. */ | ||
| 54 | void *fdstate_cookie(int fd); | ||
| 55 | void fdstate_set_expiry(int fd, ot_time expiry); | ||
| 56 | |||
| 57 | #endif | ||
diff --git a/ot_fullscrape.c b/ot_fullscrape.c index eade79d..0dee5c2 100644 --- a/ot_fullscrape.c +++ b/ot_fullscrape.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include "ot_fullscrape.h" | 25 | #include "ot_fullscrape.h" |
| 26 | #include "ot_iovec.h" | 26 | #include "ot_iovec.h" |
| 27 | #include "ot_mutex.h" | 27 | #include "ot_mutex.h" |
| 28 | #include "scan_urlencoded_query.h" | 28 | #include "ot_urlencoded.h" |
| 29 | #include "trackerlogic.h" | 29 | #include "trackerlogic.h" |
| 30 | 30 | ||
| 31 | /* Fetch full scrape info for all torrents | 31 | /* Fetch full scrape info for all torrents |
| @@ -105,12 +105,12 @@ static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_torrent *torre | |||
| 105 | 105 | ||
| 106 | break; | 106 | break; |
| 107 | case TASK_FULLSCRAPE_TPB_ASCII: | 107 | case TASK_FULLSCRAPE_TPB_ASCII: |
| 108 | hex_fromhash(r, *hash); | 108 | hex_from_hash(r, *hash); |
| 109 | r += 2 * sizeof(ot_hash); | 109 | r += 2 * sizeof(ot_hash); |
| 110 | r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count); | 110 | r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count); |
| 111 | break; | 111 | break; |
| 112 | case TASK_FULLSCRAPE_TPB_ASCII_PLUS: | 112 | case TASK_FULLSCRAPE_TPB_ASCII_PLUS: |
| 113 | hex_fromhash(r, *hash); | 113 | hex_from_hash(r, *hash); |
| 114 | r += 2 * sizeof(ot_hash); | 114 | r += 2 * sizeof(ot_hash); |
| 115 | r += sprintf(r, ":%zd:%zd:%zd\n", seed_count, peer_count - seed_count, down_count); | 115 | r += sprintf(r, ":%zd:%zd:%zd\n", seed_count, peer_count - seed_count, down_count); |
| 116 | break; | 116 | break; |
| @@ -122,11 +122,11 @@ static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_torrent *torre | |||
| 122 | r += 8; | 122 | r += 8; |
| 123 | break; | 123 | break; |
| 124 | case TASK_FULLSCRAPE_TPB_URLENCODED: | 124 | case TASK_FULLSCRAPE_TPB_URLENCODED: |
| 125 | r += fmt_urlencoded(r, *hash, sizeof(ot_hash)); | 125 | r += urlencoded_format(r, *hash, sizeof(ot_hash)); |
| 126 | r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count); | 126 | r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count); |
| 127 | break; | 127 | break; |
| 128 | case TASK_FULLSCRAPE_TRACKERSTATE: | 128 | case TASK_FULLSCRAPE_TRACKERSTATE: |
| 129 | hex_fromhash(r, *hash); | 129 | hex_from_hash(r, *hash); |
| 130 | r += 2 * sizeof(ot_hash); | 130 | r += 2 * sizeof(ot_hash); |
| 131 | r += sprintf(r, ":%zd:%zd\n", torrent->peer_list6->base, down_count); | 131 | r += sprintf(r, ":%zd:%zd\n", torrent->peer_list6->base, down_count); |
| 132 | break; | 132 | break; |
| @@ -296,7 +296,7 @@ static void fullscrape_make_gzip(int taskid, ot_tasktype mode) { | |||
| 296 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); | 296 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); |
| 297 | 297 | ||
| 298 | if (!iovector.iov_base) { | 298 | if (!iovector.iov_base) { |
| 299 | fprintf(stderr, "Problem with iovec_fix_increase_or_free\n"); | 299 | fprintf(stderr, "Problem with iovec_next_chunk\n"); |
| 300 | deflateEnd(&strm); | 300 | deflateEnd(&strm); |
| 301 | return; | 301 | return; |
| 302 | } | 302 | } |
| @@ -422,7 +422,7 @@ static void fullscrape_make_zstd(int taskid, ot_tasktype mode) { | |||
| 422 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); | 422 | iovector.iov_base = malloc(OT_SCRAPE_CHUNK_SIZE); |
| 423 | 423 | ||
| 424 | if (!iovector.iov_base) { | 424 | if (!iovector.iov_base) { |
| 425 | fprintf(stderr, "Problem with iovec_fix_increase_or_free\n"); | 425 | fprintf(stderr, "Problem with iovec_next_chunk\n"); |
| 426 | ZSTD_freeCCtx(zstream); | 426 | ZSTD_freeCCtx(zstream); |
| 427 | return; | 427 | return; |
| 428 | } | 428 | } |
| @@ -23,7 +23,7 @@ int hex_value(int c) { | |||
| 23 | 23 | ||
| 24 | int hex_isdigit(int c) { return hex_value(c) >= 0; } | 24 | int hex_isdigit(int c) { return hex_value(c) >= 0; } |
| 25 | 25 | ||
| 26 | char *hex_fromhash(char *dest, const uint8_t *hash) { | 26 | char *hex_from_hash(char *dest, const uint8_t *hash) { |
| 27 | static const char digits[] = "0123456789ABCDEF"; | 27 | static const char digits[] = "0123456789ABCDEF"; |
| 28 | char *d = dest; | 28 | char *d = dest; |
| 29 | size_t i; | 29 | size_t i; |
| @@ -36,7 +36,7 @@ char *hex_fromhash(char *dest, const uint8_t *hash) { | |||
| 36 | return dest; | 36 | return dest; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | int hex_tohash(ot_hash hash, const char *src) { | 39 | int hex_to_hash(ot_hash hash, const char *src) { |
| 40 | uint8_t decoded[sizeof(ot_hash)]; | 40 | uint8_t decoded[sizeof(ot_hash)]; |
| 41 | size_t i; | 41 | size_t i; |
| 42 | 42 | ||
| @@ -12,12 +12,12 @@ | |||
| 12 | 12 | ||
| 13 | /* Write hash as forty upper case hex digits followed by a terminating zero. | 13 | /* Write hash as forty upper case hex digits followed by a terminating zero. |
| 14 | dest must have room for forty one bytes. Returns dest. */ | 14 | dest must have room for forty one bytes. Returns dest. */ |
| 15 | char *hex_fromhash(char *dest, const uint8_t *hash); | 15 | char *hex_from_hash(char *dest, const uint8_t *hash); |
| 16 | 16 | ||
| 17 | /* Read forty hex digits from src into hash. Returns non-zero on success. | 17 | /* Read forty hex digits from src into hash. Returns non-zero on success. |
| 18 | On failure hash is left untouched and no byte of src beyond the offending | 18 | On failure hash is left untouched and no byte of src beyond the offending |
| 19 | character is read, so src need not be forty characters long. */ | 19 | character is read, so src need not be forty characters long. */ |
| 20 | int hex_tohash(ot_hash hash, const char *src); | 20 | int hex_to_hash(ot_hash hash, const char *src); |
| 21 | 21 | ||
| 22 | /* Non-zero if c is a hexadecimal digit, in either case. */ | 22 | /* Non-zero if c is a hexadecimal digit, in either case. */ |
| 23 | int hex_isdigit(int c); | 23 | int hex_isdigit(int c); |
| @@ -25,8 +25,9 @@ | |||
| 25 | #include "ot_ip.h" | 25 | #include "ot_ip.h" |
| 26 | #include "ot_mutex.h" | 26 | #include "ot_mutex.h" |
| 27 | #include "ot_scan.h" | 27 | #include "ot_scan.h" |
| 28 | #include "ot_fdstate.h" | ||
| 28 | #include "ot_stats.h" | 29 | #include "ot_stats.h" |
| 29 | #include "scan_urlencoded_query.h" | 30 | #include "ot_urlencoded.h" |
| 30 | #include "trackerlogic.h" | 31 | #include "trackerlogic.h" |
| 31 | 32 | ||
| 32 | #define OT_MAXMULTISCRAPE_COUNT 64 | 33 | #define OT_MAXMULTISCRAPE_COUNT 64 |
| @@ -38,7 +39,7 @@ ssize_t g_stats_path_len; | |||
| 38 | enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; | 39 | enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; |
| 39 | 40 | ||
| 40 | static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | 41 | static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { |
| 41 | struct http_data *cookie = io_getcookie(sock); | 42 | struct http_data *cookie = fdstate_cookie(sock); |
| 42 | ssize_t written_size; | 43 | ssize_t written_size; |
| 43 | 44 | ||
| 44 | if (!cookie) { | 45 | if (!cookie) { |
| @@ -72,7 +73,6 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | |||
| 72 | 73 | ||
| 73 | if (written_size < ws->reply_size) { | 74 | if (written_size < ws->reply_size) { |
| 74 | char *outbuf; | 75 | char *outbuf; |
| 75 | tai6464 t; | ||
| 76 | 76 | ||
| 77 | if (!(outbuf = malloc(ws->reply_size - written_size))) { | 77 | if (!(outbuf = malloc(ws->reply_size - written_size))) { |
| 78 | buf_reset(&cookie->request); | 78 | buf_reset(&cookie->request); |
| @@ -97,8 +97,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | |||
| 97 | 97 | ||
| 98 | /* writeable short data sockets just have a tcp timeout */ | 98 | /* writeable short data sockets just have a tcp timeout */ |
| 99 | if (!ws->keep_alive) { | 99 | if (!ws->keep_alive) { |
| 100 | taia_uint(&t, 0); | 100 | fdstate_set_expiry(sock, 0); |
| 101 | io_timeout(sock, t); | ||
| 102 | io_dontwantread(sock); | 101 | io_dontwantread(sock); |
| 103 | } | 102 | } |
| 104 | io_wantwrite(sock); | 103 | io_wantwrite(sock); |
| @@ -135,11 +134,10 @@ ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) | |||
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { | 136 | ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { |
| 138 | struct http_data *cookie = io_getcookie(sock); | 137 | struct http_data *cookie = fdstate_cookie(sock); |
| 139 | char *header; | 138 | char *header; |
| 140 | const char *encoding = ""; | 139 | const char *encoding = ""; |
| 141 | size_t header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector); | 140 | size_t header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector); |
| 142 | tai6464 t; | ||
| 143 | 141 | ||
| 144 | /* No cookie? Bad socket. Leave. */ | 142 | /* No cookie? Bad socket. Leave. */ |
| 145 | if (!cookie) { | 143 | if (!cookie) { |
| @@ -209,10 +207,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t | |||
| 209 | cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; | 207 | cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; |
| 210 | } | 208 | } |
| 211 | 209 | ||
| 212 | /* writeable sockets timeout after 10 minutes */ | 210 | fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT_SEND); |
| 213 | taia_now(&t); | ||
| 214 | taia_addsec(&t, &t, OT_CLIENT_TIMEOUT_SEND); | ||
| 215 | io_timeout(sock, t); | ||
| 216 | io_wantwrite(sock); | 211 | io_wantwrite(sock); |
| 217 | return 0; | 212 | return 0; |
| 218 | } | 213 | } |
| @@ -248,7 +243,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c | |||
| 248 | {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII}, | 243 | {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII}, |
| 249 | {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}}; | 244 | {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}}; |
| 250 | 245 | ||
| 251 | struct http_data *cookie = io_getcookie(sock); | 246 | struct http_data *cookie = fdstate_cookie(sock); |
| 252 | int mode = TASK_STATS_PEERS, scanon = 1, format = 0; | 247 | int mode = TASK_STATS_PEERS, scanon = 1, format = 0; |
| 253 | 248 | ||
| 254 | /* A socket without one is a dead socket, which is what http_sendiovecdata | 249 | /* A socket without one is a dead socket, which is what http_sendiovecdata |
| @@ -262,21 +257,21 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c | |||
| 262 | #endif | 257 | #endif |
| 263 | 258 | ||
| 264 | while (scanon) { | 259 | while (scanon) { |
| 265 | switch (scan_find_keywords(keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM)) { | 260 | switch (urlencoded_match_keyword(keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM)) { |
| 266 | case -2: | 261 | case -2: |
| 267 | scanon = 0; | 262 | scanon = 0; |
| 268 | break; /* TERMINATOR */ | 263 | break; /* TERMINATOR */ |
| 269 | case -1: | 264 | case -1: |
| 270 | HTTPERROR_400_PARAM; /* PARSE ERROR */ | 265 | HTTPERROR_400_PARAM; /* PARSE ERROR */ |
| 271 | case -3: | 266 | case -3: |
| 272 | scan_urlencoded_skipvalue(&read_ptr); | 267 | urlencoded_skip_value(&read_ptr); |
| 273 | break; | 268 | break; |
| 274 | case 1: /* matched "mode" */ | 269 | case 1: /* matched "mode" */ |
| 275 | if ((mode = scan_find_keywords(keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) | 270 | if ((mode = urlencoded_match_keyword(keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) |
| 276 | HTTPERROR_400_PARAM; | 271 | HTTPERROR_400_PARAM; |
| 277 | break; | 272 | break; |
| 278 | case 2: /* matched "format" */ | 273 | case 2: /* matched "format" */ |
| 279 | if ((format = scan_find_keywords(keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) | 274 | if ((format = urlencoded_match_keyword(keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) |
| 280 | HTTPERROR_400_PARAM; | 275 | HTTPERROR_400_PARAM; |
| 281 | break; | 276 | break; |
| 282 | case 3: | 277 | case 3: |
| @@ -291,7 +286,6 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c | |||
| 291 | } | 286 | } |
| 292 | 287 | ||
| 293 | if (mode == TASK_STATS_TPB) { | 288 | if (mode == TASK_STATS_TPB) { |
| 294 | tai6464 t; | ||
| 295 | #ifdef WANT_COMPRESSION_GZIP | 289 | #ifdef WANT_COMPRESSION_GZIP |
| 296 | ws->request[ws->request_size - 1] = 0; | 290 | ws->request[ws->request_size - 1] = 0; |
| 297 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS | 291 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS |
| @@ -307,8 +301,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c | |||
| 307 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; | 301 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; |
| 308 | 302 | ||
| 309 | /* Clients waiting for us should not easily timeout */ | 303 | /* Clients waiting for us should not easily timeout */ |
| 310 | taia_uint(&t, 0); | 304 | fdstate_set_expiry(sock, 0); |
| 311 | io_timeout(sock, t); | ||
| 312 | fullscrape_deliver(sock, format); | 305 | fullscrape_deliver(sock, format); |
| 313 | io_dontwantread(sock); | 306 | io_dontwantread(sock); |
| 314 | return ws->reply_size = -2; | 307 | return ws->reply_size = -2; |
| @@ -317,13 +310,11 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c | |||
| 317 | 310 | ||
| 318 | /* default format for now */ | 311 | /* default format for now */ |
| 319 | if ((mode & TASK_CLASS_MASK) == TASK_STATS) { | 312 | if ((mode & TASK_CLASS_MASK) == TASK_STATS) { |
| 320 | tai6464 t; | ||
| 321 | 313 | ||
| 322 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | 314 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; |
| 323 | 315 | ||
| 324 | /* Complex stats also include expensive memory debugging tools */ | 316 | /* Complex stats also include expensive memory debugging tools */ |
| 325 | taia_uint(&t, 0); | 317 | fdstate_set_expiry(sock, 0); |
| 326 | io_timeout(sock, t); | ||
| 327 | stats_deliver(sock, mode); | 318 | stats_deliver(sock, mode); |
| 328 | return ws->reply_size = -2; | 319 | return ws->reply_size = -2; |
| 329 | } | 320 | } |
| @@ -343,9 +334,8 @@ typedef struct { | |||
| 343 | 334 | ||
| 344 | #ifdef WANT_FULLSCRAPE | 335 | #ifdef WANT_FULLSCRAPE |
| 345 | static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) { | 336 | static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) { |
| 346 | struct http_data *cookie = io_getcookie(sock); | 337 | struct http_data *cookie = fdstate_cookie(sock); |
| 347 | int format = 0; | 338 | int format = 0; |
| 348 | tai6464 t; | ||
| 349 | 339 | ||
| 350 | #ifdef WANT_MODEST_FULLSCRAPES | 340 | #ifdef WANT_MODEST_FULLSCRAPES |
| 351 | { | 341 | { |
| @@ -404,8 +394,7 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct * | |||
| 404 | /* Pass this task to the worker thread */ | 394 | /* Pass this task to the worker thread */ |
| 405 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; | 395 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; |
| 406 | /* Clients waiting for us should not easily timeout */ | 396 | /* Clients waiting for us should not easily timeout */ |
| 407 | taia_uint(&t, 0); | 397 | fdstate_set_expiry(sock, 0); |
| 408 | io_timeout(sock, t); | ||
| 409 | fullscrape_deliver(sock, format); | 398 | fullscrape_deliver(sock, format); |
| 410 | io_dontwantread(sock); | 399 | io_dontwantread(sock); |
| 411 | return ws->reply_size = -2; | 400 | return ws->reply_size = -2; |
| @@ -429,18 +418,18 @@ static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, | |||
| 429 | } | 418 | } |
| 430 | 419 | ||
| 431 | while (scanon) { | 420 | while (scanon) { |
| 432 | switch (scan_find_keywords(keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM)) { | 421 | switch (urlencoded_match_keyword(keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM)) { |
| 433 | case -2: | 422 | case -2: |
| 434 | scanon = 0; | 423 | scanon = 0; |
| 435 | break; /* TERMINATOR */ | 424 | break; /* TERMINATOR */ |
| 436 | default: | 425 | default: |
| 437 | HTTPERROR_400_PARAM; /* PARSE ERROR */ | 426 | HTTPERROR_400_PARAM; /* PARSE ERROR */ |
| 438 | case -3: | 427 | case -3: |
| 439 | scan_urlencoded_skipvalue(&read_ptr); | 428 | urlencoded_skip_value(&read_ptr); |
| 440 | break; | 429 | break; |
| 441 | case 1: /* matched "info_hash" */ | 430 | case 1: /* matched "info_hash" */ |
| 442 | /* ignore this, when we have less than 20 bytes */ | 431 | /* ignore this, when we have less than 20 bytes */ |
| 443 | if (scan_urlencoded_query(&read_ptr, (char *)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE) != (ssize_t)sizeof(ot_hash)) | 432 | if (urlencoded_parse(&read_ptr, (char *)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE) != (ssize_t)sizeof(ot_hash)) |
| 444 | HTTPERROR_400_PARAM; | 433 | HTTPERROR_400_PARAM; |
| 445 | break; | 434 | break; |
| 446 | } | 435 | } |
| @@ -497,7 +486,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 497 | unsigned short port = 0; | 486 | unsigned short port = 0; |
| 498 | char *write_ptr; | 487 | char *write_ptr; |
| 499 | ssize_t len; | 488 | ssize_t len; |
| 500 | struct http_data *cookie = io_getcookie(sock); | 489 | struct http_data *cookie = fdstate_cookie(sock); |
| 501 | 490 | ||
| 502 | /* This is to hack around stupid clients that send "announce ?info_hash" */ | 491 | /* This is to hack around stupid clients that send "announce ?info_hash" */ |
| 503 | if (read_ptr[-1] != '?') { | 492 | if (read_ptr[-1] != '?') { |
| @@ -529,24 +518,24 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 529 | scanon = 1; | 518 | scanon = 1; |
| 530 | 519 | ||
| 531 | while (scanon) { | 520 | while (scanon) { |
| 532 | switch (scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM)) { | 521 | switch (urlencoded_match_keyword(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM)) { |
| 533 | case -2: | 522 | case -2: |
| 534 | scanon = 0; | 523 | scanon = 0; |
| 535 | break; /* TERMINATOR */ | 524 | break; /* TERMINATOR */ |
| 536 | case -1: | 525 | case -1: |
| 537 | HTTPERROR_400_PARAM; /* PARSE ERROR */ | 526 | HTTPERROR_400_PARAM; /* PARSE ERROR */ |
| 538 | case -3: | 527 | case -3: |
| 539 | scan_urlencoded_skipvalue(&read_ptr); | 528 | urlencoded_skip_value(&read_ptr); |
| 540 | break; | 529 | break; |
| 541 | case 1: /* matched "port" */ | 530 | case 1: /* matched "port" */ |
| 542 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); | 531 | len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); |
| 543 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp) || (tmp > 0xffff)) | 532 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp) || (tmp > 0xffff)) |
| 544 | HTTPERROR_400_PARAM; | 533 | HTTPERROR_400_PARAM; |
| 545 | port = htons(tmp); | 534 | port = htons(tmp); |
| 546 | OT_SETPORT(&ws->peer, &port); | 535 | OT_SETPORT(&ws->peer, &port); |
| 547 | break; | 536 | break; |
| 548 | case 2: /* matched "left" */ | 537 | case 2: /* matched "left" */ |
| 549 | if ((len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) | 538 | if ((len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) |
| 550 | HTTPERROR_400_PARAM; | 539 | HTTPERROR_400_PARAM; |
| 551 | if (scan_fixed_int(write_ptr, len, &tmp)) | 540 | if (scan_fixed_int(write_ptr, len, &tmp)) |
| 552 | tmp = 0; | 541 | tmp = 0; |
| @@ -554,7 +543,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 554 | OT_PEERFLAG(&ws->peer) |= PEER_FLAG_SEEDING; | 543 | OT_PEERFLAG(&ws->peer) |= PEER_FLAG_SEEDING; |
| 555 | break; | 544 | break; |
| 556 | case 3: /* matched "event" */ | 545 | case 3: /* matched "event" */ |
| 557 | switch (scan_find_keywords(keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE)) { | 546 | switch (urlencoded_match_keyword(keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE)) { |
| 558 | case -1: | 547 | case -1: |
| 559 | HTTPERROR_400_PARAM; | 548 | HTTPERROR_400_PARAM; |
| 560 | case 1: /* matched "completed" */ | 549 | case 1: /* matched "completed" */ |
| @@ -568,7 +557,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 568 | } | 557 | } |
| 569 | break; | 558 | break; |
| 570 | case 4: /* matched "numwant" */ | 559 | case 4: /* matched "numwant" */ |
| 571 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); | 560 | len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); |
| 572 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) | 561 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) |
| 573 | HTTPERROR_400_PARAM; | 562 | HTTPERROR_400_PARAM; |
| 574 | if (tmp < 0) | 563 | if (tmp < 0) |
| @@ -578,7 +567,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 578 | numwant = tmp; | 567 | numwant = tmp; |
| 579 | break; | 568 | break; |
| 580 | case 5: /* matched "compact" */ | 569 | case 5: /* matched "compact" */ |
| 581 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); | 570 | len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); |
| 582 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) | 571 | if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) |
| 583 | HTTPERROR_400_PARAM; | 572 | HTTPERROR_400_PARAM; |
| 584 | if (!tmp) | 573 | if (!tmp) |
| @@ -588,7 +577,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 588 | if (ws->hash) | 577 | if (ws->hash) |
| 589 | HTTPERROR_400_DOUBLEHASH; | 578 | HTTPERROR_400_DOUBLEHASH; |
| 590 | /* ignore this, when we have less than 20 bytes */ | 579 | /* ignore this, when we have less than 20 bytes */ |
| 591 | if (scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20) | 580 | if (urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20) |
| 592 | HTTPERROR_400_PARAM; | 581 | HTTPERROR_400_PARAM; |
| 593 | ws->hash = (ot_hash *)write_ptr; | 582 | ws->hash = (ot_hash *)write_ptr; |
| 594 | break; | 583 | break; |
| @@ -596,7 +585,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 596 | case 7: /* matched "ip" */ | 585 | case 7: /* matched "ip" */ |
| 597 | { | 586 | { |
| 598 | char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply + 16; | 587 | char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply + 16; |
| 599 | len = scan_urlencoded_query(&read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE); | 588 | len = urlencoded_parse(&read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE); |
| 600 | tmp_buf2[len] = 0; | 589 | tmp_buf2[len] = 0; |
| 601 | if ((len <= 0) || !ip_scan(tmp_buf2, tmp_buf1)) | 590 | if ((len <= 0) || !ip_scan(tmp_buf2, tmp_buf1)) |
| 602 | HTTPERROR_400_PARAM; | 591 | HTTPERROR_400_PARAM; |
| @@ -612,7 +601,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 612 | uint64_t value; | 601 | uint64_t value; |
| 613 | signed short parsed, bits; | 602 | signed short parsed, bits; |
| 614 | 603 | ||
| 615 | len = scan_urlencoded_query(&read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE); | 604 | len = urlencoded_parse(&read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE); |
| 616 | tmp_buf[len] = 0; | 605 | tmp_buf[len] = 0; |
| 617 | if (len <= 0) | 606 | if (len <= 0) |
| 618 | HTTPERROR_400_PARAM; | 607 | HTTPERROR_400_PARAM; |
| @@ -641,7 +630,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct | |||
| 641 | #endif | 630 | #endif |
| 642 | case 9: /* matched "peer_id" */ | 631 | case 9: /* matched "peer_id" */ |
| 643 | /* ignore this, when we have less than 20 bytes */ | 632 | /* ignore this, when we have less than 20 bytes */ |
| 644 | if (scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20) | 633 | if (urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20) |
| 645 | HTTPERROR_400_PARAM; | 634 | HTTPERROR_400_PARAM; |
| 646 | ws->peer_id = write_ptr; | 635 | ws->peer_id = write_ptr; |
| 647 | break; | 636 | break; |
| @@ -674,7 +663,7 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { | |||
| 674 | char *read_ptr = ws->request, *write_ptr; | 663 | char *read_ptr = ws->request, *write_ptr; |
| 675 | 664 | ||
| 676 | #ifdef WANT_FULLLOG_NETWORKS | 665 | #ifdef WANT_FULLLOG_NETWORKS |
| 677 | struct http_data *cookie = io_getcookie(sock); | 666 | struct http_data *cookie = fdstate_cookie(sock); |
| 678 | if (loglist_check_address(cookie->ip)) { | 667 | if (loglist_check_address(cookie->ip)) { |
| 679 | ot_log *log = malloc(sizeof(ot_log)); | 668 | ot_log *log = malloc(sizeof(ot_log)); |
| 680 | if (log) { | 669 | if (log) { |
| @@ -720,7 +709,7 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { | |||
| 720 | In reality we abandoned requiring the url to be correct. This now | 709 | In reality we abandoned requiring the url to be correct. This now |
| 721 | only decodes url encoded characters, we check for announces and | 710 | only decodes url encoded characters, we check for announces and |
| 722 | scrapes by looking for "a*" or "sc" */ | 711 | scrapes by looking for "a*" or "sc" */ |
| 723 | len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_PATH); | 712 | len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_PATH); |
| 724 | 713 | ||
| 725 | /* If parsing returned an error, leave with not found */ | 714 | /* If parsing returned an error, leave with not found */ |
| 726 | if (g_redirecturl && (len == -2)) | 715 | if (g_redirecturl && (len == -2)) |
| @@ -12,7 +12,7 @@ | |||
| 12 | /* Opentracker */ | 12 | /* Opentracker */ |
| 13 | #include "ot_iovec.h" | 13 | #include "ot_iovec.h" |
| 14 | 14 | ||
| 15 | void *iovec_increase(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc) { | 15 | void *iovec_new_chunk(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc) { |
| 16 | void *new_data; | 16 | void *new_data; |
| 17 | size_t new_entries = 1 + *iovec_entries; | 17 | size_t new_entries = 1 + *iovec_entries; |
| 18 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); | 18 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); |
| @@ -62,7 +62,7 @@ void iovec_free(size_t *iovec_entries, struct iovec **iovector) { | |||
| 62 | *iovec_entries = 0; | 62 | *iovec_entries = 0; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void iovec_fixlast(size_t *iovec_entries, struct iovec **iovector, void *last_ptr) { | 65 | void iovec_trim_last(size_t *iovec_entries, struct iovec **iovector, void *last_ptr) { |
| 66 | if (*iovec_entries) { | 66 | if (*iovec_entries) { |
| 67 | char *base = (char *)((*iovector)[*iovec_entries - 1]).iov_base; | 67 | char *base = (char *)((*iovector)[*iovec_entries - 1]).iov_base; |
| 68 | size_t new_alloc = ((char *)last_ptr) - base; | 68 | size_t new_alloc = ((char *)last_ptr) - base; |
| @@ -72,12 +72,12 @@ void iovec_fixlast(size_t *iovec_entries, struct iovec **iovector, void *last_pt | |||
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | void *iovec_fix_increase_or_free(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc) { | 75 | void *iovec_next_chunk(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc) { |
| 76 | void *new_data; | 76 | void *new_data; |
| 77 | 77 | ||
| 78 | iovec_fixlast(iovec_entries, iovector, last_ptr); | 78 | iovec_trim_last(iovec_entries, iovector, last_ptr); |
| 79 | 79 | ||
| 80 | if (!(new_data = iovec_increase(iovec_entries, iovector, new_alloc))) | 80 | if (!(new_data = iovec_new_chunk(iovec_entries, iovector, new_alloc))) |
| 81 | iovec_free(iovec_entries, iovector); | 81 | iovec_free(iovec_entries, iovector); |
| 82 | 82 | ||
| 83 | return new_data; | 83 | return new_data; |
| @@ -8,13 +8,13 @@ | |||
| 8 | 8 | ||
| 9 | #include <sys/uio.h> | 9 | #include <sys/uio.h> |
| 10 | 10 | ||
| 11 | void *iovec_increase(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc); | 11 | void *iovec_new_chunk(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc); |
| 12 | void *iovec_append(size_t *iovec_entries, struct iovec **iovector, struct iovec *append_iovector); | 12 | void *iovec_append(size_t *iovec_entries, struct iovec **iovector, struct iovec *append_iovector); |
| 13 | void iovec_fixlast(size_t *iovec_entries, struct iovec **iovector, void *last_ptr); | 13 | void iovec_trim_last(size_t *iovec_entries, struct iovec **iovector, void *last_ptr); |
| 14 | void iovec_free(size_t *iovec_entries, struct iovec **iovector); | 14 | void iovec_free(size_t *iovec_entries, struct iovec **iovector); |
| 15 | 15 | ||
| 16 | size_t iovec_length(const size_t *iovec_entries, const struct iovec **iovector); | 16 | size_t iovec_length(const size_t *iovec_entries, const struct iovec **iovector); |
| 17 | 17 | ||
| 18 | void *iovec_fix_increase_or_free(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc); | 18 | void *iovec_next_chunk(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc); |
| 19 | 19 | ||
| 20 | #endif | 20 | #endif |
| @@ -345,15 +345,15 @@ size_t stats_top_txt(char *reply, size_t amount) { | |||
| 345 | r += sprintf(r, "Top %zd torrents by peers:\n", amount); | 345 | r += sprintf(r, "Top %zd torrents by peers:\n", amount); |
| 346 | for (idx = 0; idx < amount; ++idx) | 346 | for (idx = 0; idx < amount; ++idx) |
| 347 | if (top100c[idx].val) | 347 | if (top100c[idx].val) |
| 348 | r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, hex_fromhash(hex_out, top100c[idx].hash)); | 348 | r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, hex_from_hash(hex_out, top100c[idx].hash)); |
| 349 | r += sprintf(r, "Top %zd torrents by seeds:\n", amount); | 349 | r += sprintf(r, "Top %zd torrents by seeds:\n", amount); |
| 350 | for (idx = 0; idx < amount; ++idx) | 350 | for (idx = 0; idx < amount; ++idx) |
| 351 | if (top100s[idx].val) | 351 | if (top100s[idx].val) |
| 352 | r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, hex_fromhash(hex_out, top100s[idx].hash)); | 352 | r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, hex_from_hash(hex_out, top100s[idx].hash)); |
| 353 | r += sprintf(r, "Top %zd torrents by leechers:\n", amount); | 353 | r += sprintf(r, "Top %zd torrents by leechers:\n", amount); |
| 354 | for (idx = 0; idx < amount; ++idx) | 354 | for (idx = 0; idx < amount; ++idx) |
| 355 | if (top100l[idx].val) | 355 | if (top100l[idx].val) |
| 356 | r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, hex_fromhash(hex_out, top100l[idx].hash)); | 356 | r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, hex_from_hash(hex_out, top100l[idx].hash)); |
| 357 | 357 | ||
| 358 | return r - reply; | 358 | return r - reply; |
| 359 | } | 359 | } |
| @@ -459,7 +459,7 @@ static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector, | |||
| 459 | 459 | ||
| 460 | while (loglist) { | 460 | while (loglist) { |
| 461 | if (r + (loglist->size + 64) >= re) { | 461 | if (r + (loglist->size + 64) >= re) { |
| 462 | r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 32 * OT_STATS_TMPSIZE); | 462 | r = iovec_next_chunk(iovec_entries, iovector, r, 32 * OT_STATS_TMPSIZE); |
| 463 | if (!r) | 463 | if (!r) |
| 464 | return; | 464 | return; |
| 465 | re = r + 32 * OT_STATS_TMPSIZE; | 465 | re = r + 32 * OT_STATS_TMPSIZE; |
| @@ -479,7 +479,7 @@ static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector, | |||
| 479 | free(loglist); | 479 | free(loglist); |
| 480 | loglist = llnext; | 480 | loglist = llnext; |
| 481 | } | 481 | } |
| 482 | iovec_fixlast(iovec_entries, iovector, r); | 482 | iovec_trim_last(iovec_entries, iovector, r); |
| 483 | } | 483 | } |
| 484 | #endif | 484 | #endif |
| 485 | 485 | ||
| @@ -570,7 +570,7 @@ static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_taskty | |||
| 570 | 570 | ||
| 571 | *iovec_entries = 0; | 571 | *iovec_entries = 0; |
| 572 | *iovector = NULL; | 572 | *iovector = NULL; |
| 573 | if (!(r = iovec_increase(iovec_entries, iovector, OT_STATS_TMPSIZE))) | 573 | if (!(r = iovec_new_chunk(iovec_entries, iovector, OT_STATS_TMPSIZE))) |
| 574 | return; | 574 | return; |
| 575 | 575 | ||
| 576 | switch (mode & TASK_TASK_MASK) { | 576 | switch (mode & TASK_TASK_MASK) { |
| @@ -587,13 +587,13 @@ static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_taskty | |||
| 587 | r += stats_top_txt(r, 10); | 587 | r += stats_top_txt(r, 10); |
| 588 | break; | 588 | break; |
| 589 | case TASK_STATS_TOP100: | 589 | case TASK_STATS_TOP100: |
| 590 | r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE); | 590 | r = iovec_next_chunk(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE); |
| 591 | if (!r) | 591 | if (!r) |
| 592 | return; | 592 | return; |
| 593 | r += stats_top_txt(r, 100); | 593 | r += stats_top_txt(r, 100); |
| 594 | break; | 594 | break; |
| 595 | case TASK_STATS_EVERYTHING: | 595 | case TASK_STATS_EVERYTHING: |
| 596 | r = iovec_fix_increase_or_free(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT); | 596 | r = iovec_next_chunk(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT); |
| 597 | if (!r) | 597 | if (!r) |
| 598 | return; | 598 | return; |
| 599 | r += stats_return_everything(r); | 599 | r += stats_return_everything(r); |
| @@ -612,7 +612,7 @@ static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_taskty | |||
| 612 | iovec_free(iovec_entries, iovector); | 612 | iovec_free(iovec_entries, iovector); |
| 613 | return; | 613 | return; |
| 614 | } | 614 | } |
| 615 | iovec_fixlast(iovec_entries, iovector, r); | 615 | iovec_trim_last(iovec_entries, iovector, r); |
| 616 | } | 616 | } |
| 617 | 617 | ||
| 618 | void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_data) { | 618 | void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_data) { |
| @@ -651,9 +651,9 @@ void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_ | |||
| 651 | localtime_r(&ttt, &time_now); | 651 | localtime_r(&ttt, &time_now); |
| 652 | strftime(timestring, sizeof(timestring), "%FT%T%z", &time_now); | 652 | strftime(timestring, sizeof(timestring), "%FT%T%z", &time_now); |
| 653 | 653 | ||
| 654 | hex_fromhash(hash_hex, *ws->hash); | 654 | hex_from_hash(hash_hex, *ws->hash); |
| 655 | if (ws->peer_id) | 655 | if (ws->peer_id) |
| 656 | hex_fromhash(peerid_hex, (uint8_t *)ws->peer_id); | 656 | hex_from_hash(peerid_hex, (uint8_t *)ws->peer_id); |
| 657 | else { | 657 | else { |
| 658 | *peerid_hex = 0; | 658 | *peerid_hex = 0; |
| 659 | } | 659 | } |
| @@ -77,7 +77,7 @@ static void sync_make(size_t *iovec_entries, struct iovec **iovector) { | |||
| 77 | /* Setup return vector... */ | 77 | /* Setup return vector... */ |
| 78 | *iovec_entries = 0; | 78 | *iovec_entries = 0; |
| 79 | *iovector = NULL; | 79 | *iovector = NULL; |
| 80 | if (!(r = iovec_increase(iovec_entries, iovector, OT_SYNC_CHUNK_SIZE))) | 80 | if (!(r = iovec_new_chunk(iovec_entries, iovector, OT_SYNC_CHUNK_SIZE))) |
| 81 | return; | 81 | return; |
| 82 | 82 | ||
| 83 | /* ... and pointer to end of current output buffer. | 83 | /* ... and pointer to end of current output buffer. |
| @@ -105,7 +105,7 @@ static void sync_make(size_t *iovec_entries, struct iovec **iovector) { | |||
| 105 | 105 | ||
| 106 | /* Allocate a fresh output buffer at the end of our buffers list | 106 | /* Allocate a fresh output buffer at the end of our buffers list |
| 107 | release bucket and return, if that fails */ | 107 | release bucket and return, if that fails */ |
| 108 | if (!(r = iovec_fix_increase_or_free(iovec_entries, iovector, r, OT_SYNC_CHUNK_SIZE))) | 108 | if (!(r = iovec_next_chunk(iovec_entries, iovector, r, OT_SYNC_CHUNK_SIZE))) |
| 109 | return mutex_bucket_unlock(bucket); | 109 | return mutex_bucket_unlock(bucket); |
| 110 | 110 | ||
| 111 | /* Adjust new end of output buffer */ | 111 | /* Adjust new end of output buffer */ |
| @@ -131,7 +131,7 @@ static void sync_make(size_t *iovec_entries, struct iovec **iovector) { | |||
| 131 | *r++ = 'e'; | 131 | *r++ = 'e'; |
| 132 | 132 | ||
| 133 | /* Release unused memory in current output buffer */ | 133 | /* Release unused memory in current output buffer */ |
| 134 | iovec_fixlast(iovec_entries, iovector, r); | 134 | iovec_trim_last(iovec_entries, iovector, r); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | /* This is the entry point into this worker thread | 137 | /* This is the entry point into this worker thread |
diff --git a/scan_urlencoded_query.c b/ot_urlencoded.c index 4825a4a..1ca6e81 100644 --- a/scan_urlencoded_query.c +++ b/ot_urlencoded.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | $id$ */ | 4 | $id$ */ |
| 5 | 5 | ||
| 6 | /* Opentracker */ | 6 | /* Opentracker */ |
| 7 | #include "scan_urlencoded_query.h" | 7 | #include "ot_urlencoded.h" |
| 8 | 8 | ||
| 9 | /* System */ | 9 | /* System */ |
| 10 | #include <string.h> | 10 | #include <string.h> |
| @@ -53,7 +53,7 @@ static unsigned char fromhex(unsigned char x) { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | /* Skip the value of a param=value pair */ | 55 | /* Skip the value of a param=value pair */ |
| 56 | void scan_urlencoded_skipvalue(char **string) { | 56 | void urlencoded_skip_value(char **string) { |
| 57 | const unsigned char *s = *(const unsigned char **)string; | 57 | const unsigned char *s = *(const unsigned char **)string; |
| 58 | unsigned char f; | 58 | unsigned char f; |
| 59 | 59 | ||
| @@ -63,16 +63,16 @@ void scan_urlencoded_skipvalue(char **string) { | |||
| 63 | ; | 63 | ; |
| 64 | 64 | ||
| 65 | /* If we stopped at a hard terminator like \0 or \n, make the | 65 | /* If we stopped at a hard terminator like \0 or \n, make the |
| 66 | next scan_urlencoded_query encounter it again */ | 66 | next urlencoded_parse encounter it again */ |
| 67 | if (f & SCAN_SEARCHPATH_TERMINATOR) | 67 | if (f & SCAN_SEARCHPATH_TERMINATOR) |
| 68 | --s; | 68 | --s; |
| 69 | 69 | ||
| 70 | *string = (char *)s; | 70 | *string = (char *)s; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | int scan_find_keywords(const ot_keywords *keywords, char **string, SCAN_SEARCHPATH_FLAG flags) { | 73 | int urlencoded_match_keyword(const ot_keywords *keywords, char **string, SCAN_SEARCHPATH_FLAG flags) { |
| 74 | char *deststring = *string; | 74 | char *deststring = *string; |
| 75 | ssize_t match_length = scan_urlencoded_query(string, deststring, flags); | 75 | ssize_t match_length = urlencoded_parse(string, deststring, flags); |
| 76 | 76 | ||
| 77 | if (match_length < 0) | 77 | if (match_length < 0) |
| 78 | return match_length; | 78 | return match_length; |
| @@ -88,7 +88,7 @@ int scan_find_keywords(const ot_keywords *keywords, char **string, SCAN_SEARCHPA | |||
| 88 | return -3; | 88 | return -3; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) { | 91 | ssize_t urlencoded_parse(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) { |
| 92 | const unsigned char *s = *(const unsigned char **)string; | 92 | const unsigned char *s = *(const unsigned char **)string; |
| 93 | unsigned char *d = (unsigned char *)deststring; | 93 | unsigned char *d = (unsigned char *)deststring; |
| 94 | unsigned char b, c; | 94 | unsigned char b, c; |
| @@ -121,7 +121,7 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F | |||
| 121 | if (d == (unsigned char *)deststring) | 121 | if (d == (unsigned char *)deststring) |
| 122 | return -2; | 122 | return -2; |
| 123 | 123 | ||
| 124 | /* Else make the next call to scan_urlencoded_param encounter it again */ | 124 | /* Else make the next call to urlencoded_parse encounter it again */ |
| 125 | --s; | 125 | --s; |
| 126 | break; | 126 | break; |
| 127 | case '?': | 127 | case '?': |
| @@ -160,7 +160,7 @@ ssize_t scan_fixed_int(char *data, size_t len, int *tmp) { | |||
| 160 | return len; | 160 | return len; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | size_t fmt_urlencoded(char *dest, const uint8_t *src, size_t len) { | 163 | size_t urlencoded_format(char *dest, const uint8_t *src, size_t len) { |
| 164 | static const char safe[] = "$/.=~-_"; | 164 | static const char safe[] = "$/.=~-_"; |
| 165 | static const char hexdigit[] = "0123456789abcdef"; | 165 | static const char hexdigit[] = "0123456789abcdef"; |
| 166 | size_t written = 0, i; | 166 | size_t written = 0, i; |
diff --git a/scan_urlencoded_query.h b/ot_urlencoded.h index f71752d..8147370 100644 --- a/scan_urlencoded_query.h +++ b/ot_urlencoded.h | |||
| @@ -30,7 +30,7 @@ typedef enum { | |||
| 30 | or -1 for parse error | 30 | or -1 for parse error |
| 31 | or -2 for terminator found | 31 | or -2 for terminator found |
| 32 | */ | 32 | */ |
| 33 | ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags); | 33 | ssize_t urlencoded_parse(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags); |
| 34 | 34 | ||
| 35 | /* string in: pointer to source | 35 | /* string in: pointer to source |
| 36 | out: pointer to next scan position | 36 | out: pointer to next scan position |
| @@ -40,12 +40,12 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F | |||
| 40 | or -2 for terminator found | 40 | or -2 for terminator found |
| 41 | or -3 for no keyword matched | 41 | or -3 for no keyword matched |
| 42 | */ | 42 | */ |
| 43 | int scan_find_keywords(const ot_keywords *keywords, char **string, SCAN_SEARCHPATH_FLAG flags); | 43 | int urlencoded_match_keyword(const ot_keywords *keywords, char **string, SCAN_SEARCHPATH_FLAG flags); |
| 44 | 44 | ||
| 45 | /* string in: pointer to value of a param=value pair to skip | 45 | /* string in: pointer to value of a param=value pair to skip |
| 46 | out: pointer to next scan position on return | 46 | out: pointer to next scan position on return |
| 47 | */ | 47 | */ |
| 48 | void scan_urlencoded_skipvalue(char **string); | 48 | void urlencoded_skip_value(char **string); |
| 49 | 49 | ||
| 50 | /* data pointer to len chars of string | 50 | /* data pointer to len chars of string |
| 51 | len length of chars in data to parse | 51 | len length of chars in data to parse |
| @@ -56,6 +56,6 @@ ssize_t scan_fixed_int(char *data, size_t len, int *number); | |||
| 56 | 56 | ||
| 57 | /* The other direction: percent encode len bytes from src into dest and return | 57 | /* The other direction: percent encode len bytes from src into dest and return |
| 58 | how many characters were written. dest needs room for three times len. */ | 58 | how many characters were written. dest needs room for three times len. */ |
| 59 | size_t fmt_urlencoded(char *dest, const uint8_t *src, size_t len); | 59 | size_t urlencoded_format(char *dest, const uint8_t *src, size_t len); |
| 60 | 60 | ||
| 61 | #endif | 61 | #endif |
diff --git a/ot_vector.c b/ot_vector.c index 7f18246..924d468 100644 --- a/ot_vector.c +++ b/ot_vector.c | |||
| @@ -19,7 +19,7 @@ static int vector_compare_peer4(const void *peer1, const void *peer2) { return m | |||
| 19 | no exact match is found. In that case it sets exactmatch 0 and gives | 19 | no exact match is found. In that case it sets exactmatch 0 and gives |
| 20 | calling functions the chance to insert data | 20 | calling functions the chance to insert data |
| 21 | */ | 21 | */ |
| 22 | void *binary_search(const void *const key, const void *base, const size_t member_count, const size_t member_size, size_t compare_size, int *exactmatch) { | 22 | void *vector_binary_search(const void *const key, const void *base, const size_t member_count, const size_t member_size, size_t compare_size, int *exactmatch) { |
| 23 | size_t interval = member_count; | 23 | size_t interval = member_count; |
| 24 | 24 | ||
| 25 | while (interval) { | 25 | while (interval) { |
| @@ -50,13 +50,13 @@ static uint8_t vector_hash_peer(ot_peer const *peer, size_t compare_size, size_t | |||
| 50 | 50 | ||
| 51 | /* This is the generic insert operation for our vector type. | 51 | /* This is the generic insert operation for our vector type. |
| 52 | It tries to locate the object at "key" with size "member_size" by comparing its first "compare_size" bytes with | 52 | It tries to locate the object at "key" with size "member_size" by comparing its first "compare_size" bytes with |
| 53 | those of objects in vector. Our special "binary_search" function does that and either returns the match or a | 53 | those of objects in vector. Our special "vector_binary_search" function does that and either returns the match or a |
| 54 | pointer to where the object is to be inserted. vector_find_or_insert makes space for the object and copies it, | 54 | pointer to where the object is to be inserted. vector_find_or_insert makes space for the object and copies it, |
| 55 | if it wasn't found in vector. Caller needs to check the passed "exactmatch" variable to see, whether an insert | 55 | if it wasn't found in vector. Caller needs to check the passed "exactmatch" variable to see, whether an insert |
| 56 | took place. If resizing the vector failed, NULL is returned, else the pointer to the object in vector. | 56 | took place. If resizing the vector failed, NULL is returned, else the pointer to the object in vector. |
| 57 | */ | 57 | */ |
| 58 | void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch) { | 58 | void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch) { |
| 59 | uint8_t *match = binary_search(key, vector->data, vector->size, member_size, compare_size, exactmatch); | 59 | uint8_t *match = vector_binary_search(key, vector->data, vector->size, member_size, compare_size, exactmatch); |
| 60 | 60 | ||
| 61 | if (*exactmatch) | 61 | if (*exactmatch) |
| 62 | return match; | 62 | return match; |
| @@ -89,7 +89,7 @@ ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size | |||
| 89 | /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ | 89 | /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ |
| 90 | if (vector->space < vector->size) | 90 | if (vector->space < vector->size) |
| 91 | vector = ((ot_vector *)vector->data) + vector_hash_peer(peer, compare_size, vector->size); | 91 | vector = ((ot_vector *)vector->data) + vector_hash_peer(peer, compare_size, vector->size); |
| 92 | match = binary_search(peer, vector->data, vector->size, peer_size, compare_size, exactmatch); | 92 | match = vector_binary_search(peer, vector->data, vector->size, peer_size, compare_size, exactmatch); |
| 93 | 93 | ||
| 94 | if (*exactmatch) | 94 | if (*exactmatch) |
| 95 | return match; | 95 | return match; |
| @@ -137,7 +137,7 @@ int vector_remove_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size) | |||
| 137 | vector = ((ot_vector *)vector->data) + vector_hash_peer(peer, compare_size, vector->size); | 137 | vector = ((ot_vector *)vector->data) + vector_hash_peer(peer, compare_size, vector->size); |
| 138 | 138 | ||
| 139 | end = ((ot_peer *)vector->data) + peer_size * vector->size; | 139 | end = ((ot_peer *)vector->data) + peer_size * vector->size; |
| 140 | match = (ot_peer *)binary_search(peer, vector->data, vector->size, peer_size, compare_size, &exactmatch); | 140 | match = (ot_peer *)vector_binary_search(peer, vector->data, vector->size, peer_size, compare_size, &exactmatch); |
| 141 | if (!exactmatch) | 141 | if (!exactmatch) |
| 142 | return 0; | 142 | return 0; |
| 143 | 143 | ||
diff --git a/ot_vector.h b/ot_vector.h index fbc75f4..d553956 100644 --- a/ot_vector.h +++ b/ot_vector.h | |||
| @@ -26,7 +26,7 @@ typedef struct { | |||
| 26 | /* trackerlogic.h needs ot_vector, break circular dependency here */ | 26 | /* trackerlogic.h needs ot_vector, break circular dependency here */ |
| 27 | #include "trackerlogic.h" | 27 | #include "trackerlogic.h" |
| 28 | 28 | ||
| 29 | void *binary_search(const void *const key, const void *base, const size_t member_count, const size_t member_size, size_t compare_size, int *exactmatch); | 29 | void *vector_binary_search(const void *const key, const void *base, const size_t member_count, const size_t member_size, size_t compare_size, int *exactmatch); |
| 30 | void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch); | 30 | void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch); |
| 31 | ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch); | 31 | ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch); |
| 32 | 32 | ||
| @@ -19,6 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | /* Opentracker */ | 20 | /* Opentracker */ |
| 21 | #include "ot_batch.h" | 21 | #include "ot_batch.h" |
| 22 | #include "ot_fdstate.h" | ||
| 22 | #include "ot_ip.h" | 23 | #include "ot_ip.h" |
| 23 | #include "ot_mutex.h" | 24 | #include "ot_mutex.h" |
| 24 | #include "ot_random.h" | 25 | #include "ot_random.h" |
| @@ -148,7 +149,7 @@ size_t add_peer_to_torrent_proxy(ot_hash hash, ot_peer *peer, size_t peer_size) | |||
| 148 | size_t remove_peer_from_torrent_proxy(ot_hash hash, ot_peer *peer, size_t peer_size) { | 149 | size_t remove_peer_from_torrent_proxy(ot_hash hash, ot_peer *peer, size_t peer_size) { |
| 149 | int exactmatch; | 150 | int exactmatch; |
| 150 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); | 151 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); |
| 151 | ot_torrent *torrent = binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); | 152 | ot_torrent *torrent = vector_binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
| 152 | 153 | ||
| 153 | if (exactmatch) { | 154 | if (exactmatch) { |
| 154 | ot_peerlist *peer_list = peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; | 155 | ot_peerlist *peer_list = peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; |
| @@ -267,7 +268,7 @@ static void handle_reconnects(void) { | |||
| 267 | continue; /* No socket for you */ | 268 | continue; /* No socket for you */ |
| 268 | io_fd(newfd); | 269 | io_fd(newfd); |
| 269 | io_wantwrite(newfd); /* So we will be informed when it is connected */ | 270 | io_wantwrite(newfd); /* So we will be informed when it is connected */ |
| 270 | io_setcookie(newfd, g_connections + i); | 271 | fdstate_open(newfd, g_connections + i, 0); |
| 271 | 272 | ||
| 272 | /* Prepare connection info block */ | 273 | /* Prepare connection info block */ |
| 273 | reset_info_block(g_connections + i); | 274 | reset_info_block(g_connections + i); |
| @@ -310,7 +311,7 @@ static void handle_accept(int64_t serversocket) { | |||
| 310 | g_connections[i].port = port; | 311 | g_connections[i].port = port; |
| 311 | g_connections[i].fd = newfd; | 312 | g_connections[i].fd = newfd; |
| 312 | 313 | ||
| 313 | io_setcookie(newfd, g_connections + i); | 314 | fdstate_open(newfd, g_connections + i, 0); |
| 314 | 315 | ||
| 315 | /* We expect the connecting side to begin with its tracker_id */ | 316 | /* We expect the connecting side to begin with its tracker_id */ |
| 316 | io_wantread(newfd); | 317 | io_wantread(newfd); |
| @@ -325,7 +326,7 @@ static void handle_read(int64_t peersocket) { | |||
| 325 | int i; | 326 | int i; |
| 326 | int64_t datalen; | 327 | int64_t datalen; |
| 327 | uint32_t tracker_id; | 328 | uint32_t tracker_id; |
| 328 | proxy_peer *peer = io_getcookie(peersocket); | 329 | proxy_peer *peer = fdstate_cookie(peersocket); |
| 329 | 330 | ||
| 330 | if (!peer) { | 331 | if (!peer) { |
| 331 | /* Can't happen ;) */ | 332 | /* Can't happen ;) */ |
| @@ -391,7 +392,7 @@ static void handle_read(int64_t peersocket) { | |||
| 391 | 392 | ||
| 392 | /* Can write new sync data to the stream */ | 393 | /* Can write new sync data to the stream */ |
| 393 | static void handle_write(int64_t peersocket) { | 394 | static void handle_write(int64_t peersocket) { |
| 394 | proxy_peer *peer = io_getcookie(peersocket); | 395 | proxy_peer *peer = fdstate_cookie(peersocket); |
| 395 | 396 | ||
| 396 | if (!peer) { | 397 | if (!peer) { |
| 397 | /* Can't happen ;) */ | 398 | /* Can't happen ;) */ |
| @@ -464,7 +465,7 @@ static void server_mainloop() { | |||
| 464 | 465 | ||
| 465 | /* Loop over readable sockets */ | 466 | /* Loop over readable sockets */ |
| 466 | while ((sock = io_canread()) != -1) { | 467 | while ((sock = io_canread()) != -1) { |
| 467 | const void *cookie = io_getcookie(sock); | 468 | const void *cookie = fdstate_cookie(sock); |
| 468 | if ((uintptr_t)cookie == FLAG_SERVERSOCKET) | 469 | if ((uintptr_t)cookie == FLAG_SERVERSOCKET) |
| 469 | handle_accept(sock); | 470 | handle_accept(sock); |
| 470 | else | 471 | else |
| @@ -493,7 +494,7 @@ static int64_t ot_try_bind(ot_ip6 ip, uint16_t port) { | |||
| 493 | if (!io_fd(sock)) | 494 | if (!io_fd(sock)) |
| 494 | panic("io_fd"); | 495 | panic("io_fd"); |
| 495 | 496 | ||
| 496 | io_setcookie(sock, (void *)FLAG_SERVERSOCKET); | 497 | fdstate_open(sock, (void *)FLAG_SERVERSOCKET, 0); |
| 497 | io_wantread(sock); | 498 | io_wantread(sock); |
| 498 | return sock; | 499 | return sock; |
| 499 | } | 500 | } |
| @@ -535,6 +536,8 @@ int main(int argc, char **argv) { | |||
| 535 | int scanon = 1, lbound = 0, sbound = 0; | 536 | int scanon = 1, lbound = 0, sbound = 0; |
| 536 | 537 | ||
| 537 | random_init(); | 538 | random_init(); |
| 539 | if (fdstate_init() == -1) | ||
| 540 | panic("fdstate_init"); | ||
| 538 | g_tracker_id = random_uint32(); | 541 | g_tracker_id = random_uint32(); |
| 539 | 542 | ||
| 540 | while (scanon) { | 543 | while (scanon) { |
diff --git a/tests/runner.c b/tests/runner.c index 148b928..9e5c99f 100644 --- a/tests/runner.c +++ b/tests/runner.c | |||
| @@ -14,7 +14,7 @@ struct module { | |||
| 14 | void (*run)(void); | 14 | void (*run)(void); |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | static const struct module modules[] = {{"scan_urlencoded_query", test_scan_urlencoded_query}, | 17 | static const struct module modules[] = {{"ot_urlencoded", test_urlencoded}, |
| 18 | {"ot_iovec", test_iovec}, | 18 | {"ot_iovec", test_iovec}, |
| 19 | {"ot_vector", test_vector}, | 19 | {"ot_vector", test_vector}, |
| 20 | {"ot_random", test_random}, | 20 | {"ot_random", test_random}, |
| @@ -25,6 +25,7 @@ static const struct module modules[] = {{"scan_urlencoded_query", test_scan_urle | |||
| 25 | {"ot_socket", test_socket}, | 25 | {"ot_socket", test_socket}, |
| 26 | {"ot_mutex", test_mutex}, | 26 | {"ot_mutex", test_mutex}, |
| 27 | {"ot_batch", test_batch}, | 27 | {"ot_batch", test_batch}, |
| 28 | {"ot_fdstate", test_fdstate}, | ||
| 28 | {"ot_accesslist", test_accesslist}, | 29 | {"ot_accesslist", test_accesslist}, |
| 29 | {NULL, NULL}}; | 30 | {NULL, NULL}}; |
| 30 | 31 | ||
diff --git a/tests/t_fdstate.c b/tests/t_fdstate.c new file mode 100644 index 0000000..bf8724a --- /dev/null +++ b/tests/t_fdstate.c | |||
| @@ -0,0 +1,224 @@ | |||
| 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 <stdint.h> | ||
| 10 | #include <stdlib.h> | ||
| 11 | #include <string.h> | ||
| 12 | |||
| 13 | /* Opentracker */ | ||
| 14 | #include "ot_fdstate.h" | ||
| 15 | #include "test.h" | ||
| 16 | |||
| 17 | /* ------------------------------------------------------- one thread first */ | ||
| 18 | |||
| 19 | static void case_open_claim_release(void) { | ||
| 20 | char cookie[4]; | ||
| 21 | uint32_t generation; | ||
| 22 | |||
| 23 | test_case("a descriptor taken into the table can be claimed and gives back its cookie"); | ||
| 24 | generation = fdstate_open(7, cookie, 0); | ||
| 25 | CHECK_INT(fdstate_claim(7, generation), 1); | ||
| 26 | CHECK_PTR(fdstate_cookie(7), cookie); | ||
| 27 | fdstate_release(7); | ||
| 28 | |||
| 29 | test_case("and can be claimed again once released"); | ||
| 30 | CHECK_INT(fdstate_claim(7, generation), 1); | ||
| 31 | fdstate_release(7); | ||
| 32 | fdstate_close(7); | ||
| 33 | } | ||
| 34 | |||
| 35 | static void case_one_holder_at_a_time(void) { | ||
| 36 | uint32_t generation = fdstate_open(8, NULL, 0); | ||
| 37 | |||
| 38 | test_case("a descriptor somebody holds cannot be claimed again"); | ||
| 39 | CHECK_INT(fdstate_claim(8, generation), 1); | ||
| 40 | CHECK_INT(fdstate_claim(8, generation), 0); | ||
| 41 | fdstate_release(8); | ||
| 42 | CHECK_INT(fdstate_claim(8, generation), 1); | ||
| 43 | fdstate_release(8); | ||
| 44 | fdstate_close(8); | ||
| 45 | } | ||
| 46 | |||
| 47 | static void case_stale_generation_is_refused(void) { | ||
| 48 | char first[4], second[4]; | ||
| 49 | uint32_t old, new; | ||
| 50 | |||
| 51 | test_case("a caller quoting the generation of a closed descriptor is turned away"); | ||
| 52 | old = fdstate_open(9, first, 0); | ||
| 53 | fdstate_close(9); | ||
| 54 | new = fdstate_open(9, second, 0); | ||
| 55 | CHECK(old != new); | ||
| 56 | CHECK_INT(fdstate_claim(9, old), 0); | ||
| 57 | |||
| 58 | test_case("while the one quoting the new generation gets the new cookie"); | ||
| 59 | CHECK_INT(fdstate_claim(9, new), 1); | ||
| 60 | CHECK_PTR(fdstate_cookie(9), second); | ||
| 61 | fdstate_release(9); | ||
| 62 | fdstate_close(9); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void case_expiry(void) { | ||
| 66 | uint32_t generation = fdstate_open(10, NULL, 100); | ||
| 67 | |||
| 68 | test_case("a descriptor past its expiry is collected"); | ||
| 69 | CHECK_INT(fdstate_claim_expired(10, 99), 0); | ||
| 70 | CHECK_INT(fdstate_claim_expired(10, 100), 1); | ||
| 71 | fdstate_close(10); | ||
| 72 | |||
| 73 | test_case("one that never expires is never collected"); | ||
| 74 | generation = fdstate_open(10, NULL, 0); | ||
| 75 | CHECK_INT(fdstate_claim_expired(10, 1 << 30), 0); | ||
| 76 | |||
| 77 | test_case("and one somebody is working on is left alone"); | ||
| 78 | fdstate_set_expiry(10, 1); | ||
| 79 | CHECK_INT(fdstate_claim(10, generation), 1); | ||
| 80 | CHECK_INT(fdstate_claim_expired(10, 1 << 30), 0); | ||
| 81 | fdstate_release(10); | ||
| 82 | CHECK_INT(fdstate_claim_expired(10, 1 << 30), 1); | ||
| 83 | fdstate_close(10); | ||
| 84 | } | ||
| 85 | |||
| 86 | static void case_out_of_range(void) { | ||
| 87 | test_case("a descriptor outside the table is refused rather than trusted"); | ||
| 88 | CHECK_INT(fdstate_claim(-1, 0), 0); | ||
| 89 | CHECK_INT(fdstate_claim((int)fdstate_slots(), 0), 0); | ||
| 90 | CHECK_INT(fdstate_claim_expired(-1, 0), 0); | ||
| 91 | CHECK_PTR(fdstate_cookie(-1), NULL); | ||
| 92 | } | ||
| 93 | |||
| 94 | /* --------------------------------------------------------- then in anger */ | ||
| 95 | |||
| 96 | /* The race this is about only exists while a descriptor is being recycled, | ||
| 97 | so recycling is driven by work done rather than by a clock: every slot is | ||
| 98 | given up after RECYCLE_AFTER claims, whatever the machine's speed. */ | ||
| 99 | |||
| 100 | #define STRESS_SLOTS 64 | ||
| 101 | #define RECYCLE_AFTER 32 | ||
| 102 | #define STRESS_CLAIMS 200000 | ||
| 103 | #define STRESS_GIVEUP (STRESS_CLAIMS * 100) | ||
| 104 | |||
| 105 | static _Atomic long stress_claims, stress_recycles, stress_violations, stress_attempts; | ||
| 106 | static _Atomic int stress_lives[STRESS_SLOTS]; | ||
| 107 | static _Atomic int stress_live[STRESS_SLOTS]; | ||
| 108 | |||
| 109 | /* Generation and cookie are published in one word so a worker can never read | ||
| 110 | a cookie that belongs to a different generation than the one it claimed | ||
| 111 | with. Each connection gets a cookie nobody else ever gets. */ | ||
| 112 | static _Atomic uint64_t stress_conn[STRESS_SLOTS]; | ||
| 113 | static _Atomic uint64_t stress_next_cookie; | ||
| 114 | |||
| 115 | #define STRESS_CONN(cookie, gen) (((uint64_t)(cookie) << 32) | (uint32_t)(gen)) | ||
| 116 | #define STRESS_CONN_COOKIE(w) ((void *)(uintptr_t)((w) >> 32)) | ||
| 117 | #define STRESS_CONN_GEN(w) ((uint32_t)(w)) | ||
| 118 | |||
| 119 | static int stress_running(void) { | ||
| 120 | return atomic_load(&stress_claims) < STRESS_CLAIMS && atomic_load(&stress_attempts) < STRESS_GIVEUP; | ||
| 121 | } | ||
| 122 | |||
| 123 | static void *stress_worker(void *arg) { | ||
| 124 | unsigned seed = (unsigned)(uintptr_t)arg; | ||
| 125 | |||
| 126 | while (stress_running()) { | ||
| 127 | int fd = (int)(rand_r(&seed) % STRESS_SLOTS); | ||
| 128 | uint64_t conn = atomic_load(&stress_conn[fd]); | ||
| 129 | |||
| 130 | atomic_fetch_add(&stress_attempts, 1); | ||
| 131 | if (!fdstate_claim(fd, STRESS_CONN_GEN(conn))) | ||
| 132 | continue; | ||
| 133 | |||
| 134 | if (fdstate_cookie(fd) != STRESS_CONN_COOKIE(conn)) | ||
| 135 | atomic_fetch_add(&stress_violations, 1); | ||
| 136 | if (atomic_fetch_sub(&stress_lives[fd], 1) <= 1) | ||
| 137 | fdstate_set_expiry(fd, 1); /* retired by its holder, as a handler would */ | ||
| 138 | if (fdstate_cookie(fd) != STRESS_CONN_COOKIE(conn)) | ||
| 139 | atomic_fetch_add(&stress_violations, 1); | ||
| 140 | |||
| 141 | fdstate_release(fd); | ||
| 142 | atomic_fetch_add(&stress_claims, 1); | ||
| 143 | } | ||
| 144 | return NULL; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void *stress_keeper(void *arg) { | ||
| 148 | (void)arg; | ||
| 149 | while (stress_running()) { | ||
| 150 | int fd; | ||
| 151 | |||
| 152 | for (fd = 0; fd < STRESS_SLOTS; ++fd) { | ||
| 153 | if (atomic_load(&stress_live[fd])) { | ||
| 154 | if (!fdstate_claim_expired(fd, 1)) | ||
| 155 | continue; /* a worker has it, come back */ | ||
| 156 | fdstate_close(fd); | ||
| 157 | atomic_store(&stress_live[fd], 0); | ||
| 158 | atomic_fetch_add(&stress_recycles, 1); | ||
| 159 | } | ||
| 160 | { | ||
| 161 | void *cookie = (void *)(uintptr_t)(atomic_fetch_add(&stress_next_cookie, 1) + 1); | ||
| 162 | uint32_t gen = fdstate_open(fd, cookie, 0); | ||
| 163 | |||
| 164 | atomic_store(&stress_lives[fd], RECYCLE_AFTER); | ||
| 165 | atomic_store(&stress_conn[fd], STRESS_CONN((uintptr_t)cookie, gen)); | ||
| 166 | atomic_store(&stress_live[fd], 1); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 170 | return NULL; | ||
| 171 | } | ||
| 172 | |||
| 173 | static void case_recycling_under_load(void) { | ||
| 174 | pthread_t worker[4], keeper; | ||
| 175 | size_t i; | ||
| 176 | |||
| 177 | test_case("no worker is ever handed a connection from another generation"); | ||
| 178 | atomic_store(&stress_claims, 0); | ||
| 179 | atomic_store(&stress_recycles, 0); | ||
| 180 | atomic_store(&stress_violations, 0); | ||
| 181 | atomic_store(&stress_attempts, 0); | ||
| 182 | atomic_store(&stress_next_cookie, 0); | ||
| 183 | /* Every slot is opened and published before any worker runs: a worker only | ||
| 184 | ever learns of a descriptor from whoever registered it, and never | ||
| 185 | invents a generation of its own. */ | ||
| 186 | for (i = 0; i < STRESS_SLOTS; ++i) { | ||
| 187 | void *cookie = (void *)(uintptr_t)(atomic_fetch_add(&stress_next_cookie, 1) + 1); | ||
| 188 | uint32_t gen = fdstate_open((int)i, cookie, 0); | ||
| 189 | |||
| 190 | atomic_store(&stress_lives[i], RECYCLE_AFTER); | ||
| 191 | atomic_store(&stress_conn[i], STRESS_CONN((uintptr_t)cookie, gen)); | ||
| 192 | atomic_store(&stress_live[i], 1); | ||
| 193 | } | ||
| 194 | |||
| 195 | pthread_create(&keeper, NULL, stress_keeper, NULL); | ||
| 196 | for (i = 0; i < sizeof(worker) / sizeof(worker[0]); ++i) | ||
| 197 | pthread_create(&worker[i], NULL, stress_worker, (void *)(uintptr_t)(i + 1)); | ||
| 198 | for (i = 0; i < sizeof(worker) / sizeof(worker[0]); ++i) | ||
| 199 | pthread_join(worker[i], NULL); | ||
| 200 | pthread_join(keeper, NULL); | ||
| 201 | |||
| 202 | CHECK_INT(atomic_load(&stress_violations), 0); | ||
| 203 | |||
| 204 | test_case("and the run actually recycled descriptors, or it proved nothing"); | ||
| 205 | CHECK(atomic_load(&stress_claims) >= STRESS_CLAIMS); | ||
| 206 | CHECK(atomic_load(&stress_recycles) > STRESS_CLAIMS / (RECYCLE_AFTER * 4)); | ||
| 207 | |||
| 208 | for (i = 0; i < STRESS_SLOTS; ++i) | ||
| 209 | fdstate_close((int)i); | ||
| 210 | } | ||
| 211 | |||
| 212 | void test_fdstate(void) { | ||
| 213 | CHECK_INT(fdstate_init(), 0); | ||
| 214 | CHECK(fdstate_slots() > STRESS_SLOTS); | ||
| 215 | |||
| 216 | case_open_claim_release(); | ||
| 217 | case_one_holder_at_a_time(); | ||
| 218 | case_stale_generation_is_refused(); | ||
| 219 | case_expiry(); | ||
| 220 | case_out_of_range(); | ||
| 221 | case_recycling_under_load(); | ||
| 222 | |||
| 223 | fdstate_deinit(); | ||
| 224 | } | ||
diff --git a/tests/t_hex.c b/tests/t_hex.c index 7cce8ac..a761737 100644 --- a/tests/t_hex.c +++ b/tests/t_hex.c | |||
| @@ -18,7 +18,7 @@ static void case_encode(void) { | |||
| 18 | 18 | ||
| 19 | test_case("a hash encodes to forty upper case digits and a terminator"); | 19 | test_case("a hash encodes to forty upper case digits and a terminator"); |
| 20 | memset(dest, 0x7f, sizeof(dest)); | 20 | memset(dest, 0x7f, sizeof(dest)); |
| 21 | CHECK_PTR(hex_fromhash(dest, sample), dest); | 21 | CHECK_PTR(hex_from_hash(dest, sample), dest); |
| 22 | CHECK_STR(dest, "000123456789ABCDEFFF10203040506070809" "0A0"); | 22 | CHECK_STR(dest, "000123456789ABCDEFFF10203040506070809" "0A0"); |
| 23 | CHECK_INT(strlen(dest), 40); | 23 | CHECK_INT(strlen(dest), 40); |
| 24 | CHECK_INT((unsigned char)dest[41], 0x7f); | 24 | CHECK_INT((unsigned char)dest[41], 0x7f); |
| @@ -28,7 +28,7 @@ static void case_decode(void) { | |||
| 28 | ot_hash hash; | 28 | ot_hash hash; |
| 29 | 29 | ||
| 30 | test_case("forty digits decode back to the hash"); | 30 | test_case("forty digits decode back to the hash"); |
| 31 | CHECK(hex_tohash(hash, "000123456789ABCDEFFF10203040506070809" "0A0")); | 31 | CHECK(hex_to_hash(hash, "000123456789ABCDEFFF10203040506070809" "0A0")); |
| 32 | CHECK_MEM(hash, sample, sizeof(sample)); | 32 | CHECK_MEM(hash, sample, sizeof(sample)); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| @@ -41,8 +41,8 @@ static void case_round_trip(void) { | |||
| 41 | for (i = 0; i < 256; ++i) { | 41 | for (i = 0; i < 256; ++i) { |
| 42 | uint8_t probe[20]; | 42 | uint8_t probe[20]; |
| 43 | memset(probe, (uint8_t)i, sizeof(probe)); | 43 | memset(probe, (uint8_t)i, sizeof(probe)); |
| 44 | hex_fromhash(text, probe); | 44 | hex_from_hash(text, probe); |
| 45 | if (!hex_tohash(hash, text) || memcmp(hash, probe, sizeof(probe))) { | 45 | if (!hex_to_hash(hash, text) || memcmp(hash, probe, sizeof(probe))) { |
| 46 | test_failf(__FILE__, __LINE__, "round trip failed for byte value %zu", i); | 46 | test_failf(__FILE__, __LINE__, "round trip failed for byte value %zu", i); |
| 47 | return; | 47 | return; |
| 48 | } | 48 | } |
| @@ -54,8 +54,8 @@ static void case_decode_is_case_insensitive(void) { | |||
| 54 | ot_hash upper, lower; | 54 | ot_hash upper, lower; |
| 55 | 55 | ||
| 56 | test_case("lower case digits decode the same as upper case"); | 56 | test_case("lower case digits decode the same as upper case"); |
| 57 | CHECK(hex_tohash(upper, "ABCDEF0123456789ABCDEF0123456789ABCDEF01")); | 57 | CHECK(hex_to_hash(upper, "ABCDEF0123456789ABCDEF0123456789ABCDEF01")); |
| 58 | CHECK(hex_tohash(lower, "abcdef0123456789abcdef0123456789abcdef01")); | 58 | CHECK(hex_to_hash(lower, "abcdef0123456789abcdef0123456789abcdef01")); |
| 59 | CHECK_MEM(lower, upper, sizeof(ot_hash)); | 59 | CHECK_MEM(lower, upper, sizeof(ot_hash)); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| @@ -63,18 +63,18 @@ static void case_rejects_non_digits(void) { | |||
| 63 | ot_hash hash; | 63 | ot_hash hash; |
| 64 | 64 | ||
| 65 | test_case("a non hex character anywhere rejects the whole string"); | 65 | test_case("a non hex character anywhere rejects the whole string"); |
| 66 | CHECK_INT(hex_tohash(hash, "g00123456789ABCDEFFF102030405060708090A0"), 0); | 66 | CHECK_INT(hex_to_hash(hash, "g00123456789ABCDEFFF102030405060708090A0"), 0); |
| 67 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEFFF102030405060708090Ag"), 0); | 67 | CHECK_INT(hex_to_hash(hash, "000123456789ABCDEFFF102030405060708090Ag"), 0); |
| 68 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEF:F102030405060708090A"), 0); | 68 | CHECK_INT(hex_to_hash(hash, "000123456789ABCDEF:F102030405060708090A"), 0); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void case_rejects_short_input(void) { | 71 | static void case_rejects_short_input(void) { |
| 72 | ot_hash hash; | 72 | ot_hash hash; |
| 73 | 73 | ||
| 74 | test_case("a string shorter than forty digits is rejected"); | 74 | test_case("a string shorter than forty digits is rejected"); |
| 75 | CHECK_INT(hex_tohash(hash, ""), 0); | 75 | CHECK_INT(hex_to_hash(hash, ""), 0); |
| 76 | CHECK_INT(hex_tohash(hash, "00"), 0); | 76 | CHECK_INT(hex_to_hash(hash, "00"), 0); |
| 77 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEFFF102030405060708090A"), 0); | 77 | CHECK_INT(hex_to_hash(hash, "000123456789ABCDEFFF102030405060708090A"), 0); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static void case_leaves_hash_untouched_on_failure(void) { | 80 | static void case_leaves_hash_untouched_on_failure(void) { |
| @@ -82,7 +82,7 @@ static void case_leaves_hash_untouched_on_failure(void) { | |||
| 82 | 82 | ||
| 83 | test_case("a rejected string leaves the destination untouched"); | 83 | test_case("a rejected string leaves the destination untouched"); |
| 84 | memset(hash, 0x5a, sizeof(hash)); | 84 | memset(hash, 0x5a, sizeof(hash)); |
| 85 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEFFF10203040506070809XX0"), 0); | 85 | CHECK_INT(hex_to_hash(hash, "000123456789ABCDEFFF10203040506070809XX0"), 0); |
| 86 | CHECK_MEM(hash, "\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a", sizeof(hash)); | 86 | CHECK_MEM(hash, "\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a", sizeof(hash)); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| @@ -96,7 +96,7 @@ static void case_stops_at_the_terminator(void) { | |||
| 96 | memcpy(guarded, "0012", 4); | 96 | memcpy(guarded, "0012", 4); |
| 97 | guarded[4] = 0; | 97 | guarded[4] = 0; |
| 98 | memset(guarded + 5, 'f', 3); | 98 | memset(guarded + 5, 'f', 3); |
| 99 | CHECK_INT(hex_tohash(hash, guarded), 0); | 99 | CHECK_INT(hex_to_hash(hash, guarded), 0); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static void case_isdigit(void) { | 102 | static void case_isdigit(void) { |
diff --git a/tests/t_iovec.c b/tests/t_iovec.c index 89f3fda..2553141 100644 --- a/tests/t_iovec.c +++ b/tests/t_iovec.c | |||
| @@ -18,13 +18,13 @@ static void case_increase_and_length(void) { | |||
| 18 | void *first, *second; | 18 | void *first, *second; |
| 19 | 19 | ||
| 20 | test_case("increase appends an entry and length is their sum"); | 20 | test_case("increase appends an entry and length is their sum"); |
| 21 | first = iovec_increase(&entries, &vector, 100); | 21 | first = iovec_new_chunk(&entries, &vector, 100); |
| 22 | CHECK(first != NULL); | 22 | CHECK(first != NULL); |
| 23 | CHECK_INT(entries, 1); | 23 | CHECK_INT(entries, 1); |
| 24 | CHECK_INT(vector[0].iov_len, 100); | 24 | CHECK_INT(vector[0].iov_len, 100); |
| 25 | CHECK_PTR(vector[0].iov_base, first); | 25 | CHECK_PTR(vector[0].iov_base, first); |
| 26 | 26 | ||
| 27 | second = iovec_increase(&entries, &vector, 50); | 27 | second = iovec_new_chunk(&entries, &vector, 50); |
| 28 | CHECK(second != NULL); | 28 | CHECK(second != NULL); |
| 29 | CHECK_INT(entries, 2); | 29 | CHECK_INT(entries, 2); |
| 30 | CHECK_INT(vector[1].iov_len, 50); | 30 | CHECK_INT(vector[1].iov_len, 50); |
| @@ -38,8 +38,8 @@ static void case_free_resets(void) { | |||
| 38 | struct iovec *vector = NULL; | 38 | struct iovec *vector = NULL; |
| 39 | 39 | ||
| 40 | test_case("free releases the entries and resets the vector"); | 40 | test_case("free releases the entries and resets the vector"); |
| 41 | CHECK(iovec_increase(&entries, &vector, 10) != NULL); | 41 | CHECK(iovec_new_chunk(&entries, &vector, 10) != NULL); |
| 42 | CHECK(iovec_increase(&entries, &vector, 10) != NULL); | 42 | CHECK(iovec_new_chunk(&entries, &vector, 10) != NULL); |
| 43 | iovec_free(&entries, &vector); | 43 | iovec_free(&entries, &vector); |
| 44 | CHECK_INT(entries, 0); | 44 | CHECK_INT(entries, 0); |
| 45 | CHECK_PTR(vector, NULL); | 45 | CHECK_PTR(vector, NULL); |
| @@ -52,12 +52,12 @@ static void case_fixlast_shrinks(void) { | |||
| 52 | char *block; | 52 | char *block; |
| 53 | 53 | ||
| 54 | test_case("fixlast trims the last entry to the bytes actually used"); | 54 | test_case("fixlast trims the last entry to the bytes actually used"); |
| 55 | CHECK(iovec_increase(&entries, &vector, 64) != NULL); | 55 | CHECK(iovec_new_chunk(&entries, &vector, 64) != NULL); |
| 56 | block = iovec_increase(&entries, &vector, 1000); | 56 | block = iovec_new_chunk(&entries, &vector, 1000); |
| 57 | CHECK(block != NULL); | 57 | CHECK(block != NULL); |
| 58 | memset(block, 'x', 20); | 58 | memset(block, 'x', 20); |
| 59 | 59 | ||
| 60 | iovec_fixlast(&entries, &vector, block + 20); | 60 | iovec_trim_last(&entries, &vector, block + 20); |
| 61 | CHECK_INT(entries, 2); | 61 | CHECK_INT(entries, 2); |
| 62 | CHECK_INT(vector[1].iov_len, 20); | 62 | CHECK_INT(vector[1].iov_len, 20); |
| 63 | CHECK_INT(iovec_length(&entries, (const struct iovec **)&vector), 84); | 63 | CHECK_INT(iovec_length(&entries, (const struct iovec **)&vector), 84); |
| @@ -71,7 +71,7 @@ static void case_fixlast_on_empty(void) { | |||
| 71 | struct iovec *vector = NULL; | 71 | struct iovec *vector = NULL; |
| 72 | 72 | ||
| 73 | test_case("fixlast on an empty vector does nothing"); | 73 | test_case("fixlast on an empty vector does nothing"); |
| 74 | iovec_fixlast(&entries, &vector, NULL); | 74 | iovec_trim_last(&entries, &vector, NULL); |
| 75 | CHECK_INT(entries, 0); | 75 | CHECK_INT(entries, 0); |
| 76 | CHECK_PTR(vector, NULL); | 76 | CHECK_PTR(vector, NULL); |
| 77 | } | 77 | } |
| @@ -103,9 +103,9 @@ static void case_fix_increase(void) { | |||
| 103 | char *block; | 103 | char *block; |
| 104 | 104 | ||
| 105 | test_case("fix_increase trims the previous entry and adds a new one"); | 105 | test_case("fix_increase trims the previous entry and adds a new one"); |
| 106 | block = iovec_increase(&entries, &vector, 500); | 106 | block = iovec_new_chunk(&entries, &vector, 500); |
| 107 | CHECK(block != NULL); | 107 | CHECK(block != NULL); |
| 108 | block = iovec_fix_increase_or_free(&entries, &vector, block + 30, 200); | 108 | block = iovec_next_chunk(&entries, &vector, block + 30, 200); |
| 109 | CHECK(block != NULL); | 109 | CHECK(block != NULL); |
| 110 | CHECK_INT(entries, 2); | 110 | CHECK_INT(entries, 2); |
| 111 | CHECK_INT(vector[0].iov_len, 30); | 111 | CHECK_INT(vector[0].iov_len, 30); |
diff --git a/tests/t_scan_urlencoded_query.c b/tests/t_urlencoded.c index f660ea3..1239e6b 100644 --- a/tests/t_scan_urlencoded_query.c +++ b/tests/t_urlencoded.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <string.h> | 7 | #include <string.h> |
| 8 | 8 | ||
| 9 | /* Opentracker */ | 9 | /* Opentracker */ |
| 10 | #include "scan_urlencoded_query.h" | 10 | #include "ot_urlencoded.h" |
| 11 | #include "test.h" | 11 | #include "test.h" |
| 12 | 12 | ||
| 13 | /* The scanner returns the number of bytes written to the destination, or | 13 | /* The scanner returns the number of bytes written to the destination, or |
| @@ -23,7 +23,7 @@ static void case_path(void) { | |||
| 23 | ssize_t n; | 23 | ssize_t n; |
| 24 | 24 | ||
| 25 | test_case("path stops at the question mark"); | 25 | test_case("path stops at the question mark"); |
| 26 | n = scan_urlencoded_query(&p, dest, SCAN_PATH); | 26 | n = urlencoded_parse(&p, dest, SCAN_PATH); |
| 27 | CHECK_INT(n, 9); | 27 | CHECK_INT(n, 9); |
| 28 | dest[n] = 0; | 28 | dest[n] = 0; |
| 29 | CHECK_STR(dest, "/announce"); | 29 | CHECK_STR(dest, "/announce"); |
| @@ -37,22 +37,22 @@ static void case_param_and_value(void) { | |||
| 37 | ssize_t n; | 37 | ssize_t n; |
| 38 | 38 | ||
| 39 | test_case("parameter stops at '=', value stops at '&'"); | 39 | test_case("parameter stops at '=', value stops at '&'"); |
| 40 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_PARAM); | 40 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); |
| 41 | CHECK_INT(n, 9); | 41 | CHECK_INT(n, 9); |
| 42 | dest[n] = 0; | 42 | dest[n] = 0; |
| 43 | CHECK_STR(dest, "info_hash"); | 43 | CHECK_STR(dest, "info_hash"); |
| 44 | 44 | ||
| 45 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 45 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 46 | CHECK_INT(n, 3); | 46 | CHECK_INT(n, 3); |
| 47 | dest[n] = 0; | 47 | dest[n] = 0; |
| 48 | CHECK_STR(dest, "abc"); | 48 | CHECK_STR(dest, "abc"); |
| 49 | 49 | ||
| 50 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_PARAM); | 50 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); |
| 51 | CHECK_INT(n, 4); | 51 | CHECK_INT(n, 4); |
| 52 | dest[n] = 0; | 52 | dest[n] = 0; |
| 53 | CHECK_STR(dest, "port"); | 53 | CHECK_STR(dest, "port"); |
| 54 | 54 | ||
| 55 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 55 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 56 | CHECK_INT(n, 2); | 56 | CHECK_INT(n, 2); |
| 57 | dest[n] = 0; | 57 | dest[n] = 0; |
| 58 | CHECK_STR(dest, "80"); | 58 | CHECK_STR(dest, "80"); |
| @@ -65,7 +65,7 @@ static void case_percent_decoding(void) { | |||
| 65 | ssize_t n; | 65 | ssize_t n; |
| 66 | 66 | ||
| 67 | test_case("percent escapes decode"); | 67 | test_case("percent escapes decode"); |
| 68 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 68 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 69 | CHECK_INT(n, 3); | 69 | CHECK_INT(n, 3); |
| 70 | CHECK_MEM(dest, "ABC", 3); | 70 | CHECK_MEM(dest, "ABC", 3); |
| 71 | } | 71 | } |
| @@ -79,7 +79,7 @@ static void case_binary_info_hash(void) { | |||
| 79 | ssize_t n; | 79 | ssize_t n; |
| 80 | 80 | ||
| 81 | test_case("twenty byte binary value survives decoding"); | 81 | test_case("twenty byte binary value survives decoding"); |
| 82 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 82 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 83 | CHECK_INT(n, 20); | 83 | CHECK_INT(n, 20); |
| 84 | CHECK_MEM(dest, want, 20); | 84 | CHECK_MEM(dest, want, 20); |
| 85 | } | 85 | } |
| @@ -90,7 +90,7 @@ static void case_in_place(void) { | |||
| 90 | ssize_t n; | 90 | ssize_t n; |
| 91 | 91 | ||
| 92 | test_case("decoding in place over the source is safe"); | 92 | test_case("decoding in place over the source is safe"); |
| 93 | n = scan_urlencoded_query(&p, query, SCAN_SEARCHPATH_VALUE); | 93 | n = urlencoded_parse(&p, query, SCAN_SEARCHPATH_VALUE); |
| 94 | CHECK_INT(n, 2); | 94 | CHECK_INT(n, 2); |
| 95 | CHECK_MEM(query, "AB", 2); | 95 | CHECK_MEM(query, "AB", 2); |
| 96 | } | 96 | } |
| @@ -102,7 +102,7 @@ static void case_bad_escape(void) { | |||
| 102 | ssize_t n; | 102 | ssize_t n; |
| 103 | 103 | ||
| 104 | test_case("a non hexadecimal escape is a parse error"); | 104 | test_case("a non hexadecimal escape is a parse error"); |
| 105 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 105 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 106 | CHECK_INT(n, -1); | 106 | CHECK_INT(n, -1); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| @@ -113,7 +113,7 @@ static void case_truncated_escape(void) { | |||
| 113 | ssize_t n; | 113 | ssize_t n; |
| 114 | 114 | ||
| 115 | test_case("an escape cut short by the terminator is a parse error"); | 115 | test_case("an escape cut short by the terminator is a parse error"); |
| 116 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 116 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 117 | CHECK_INT(n, -1); | 117 | CHECK_INT(n, -1); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| @@ -125,11 +125,11 @@ static void case_terminator(void) { | |||
| 125 | ssize_t n; | 125 | ssize_t n; |
| 126 | 126 | ||
| 127 | test_case("a hard terminator before any output reports end of input"); | 127 | test_case("a hard terminator before any output reports end of input"); |
| 128 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_PARAM); | 128 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); |
| 129 | CHECK_INT(n, -2); | 129 | CHECK_INT(n, -2); |
| 130 | 130 | ||
| 131 | p = space; | 131 | p = space; |
| 132 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_PARAM); | 132 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); |
| 133 | CHECK_INT(n, -2); | 133 | CHECK_INT(n, -2); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| @@ -140,10 +140,10 @@ static void case_terminator_after_output(void) { | |||
| 140 | ssize_t n; | 140 | ssize_t n; |
| 141 | 141 | ||
| 142 | test_case("a hard terminator after output is left for the next call"); | 142 | test_case("a hard terminator after output is left for the next call"); |
| 143 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 143 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 144 | CHECK_INT(n, 3); | 144 | CHECK_INT(n, 3); |
| 145 | CHECK_INT(*p, 0); | 145 | CHECK_INT(*p, 0); |
| 146 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 146 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 147 | CHECK_INT(n, -2); | 147 | CHECK_INT(n, -2); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| @@ -159,14 +159,14 @@ static void case_separators_are_contextual(void) { | |||
| 159 | ssize_t n; | 159 | ssize_t n; |
| 160 | 160 | ||
| 161 | test_case("a question mark is literal inside a value"); | 161 | test_case("a question mark is literal inside a value"); |
| 162 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 162 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 163 | CHECK_INT(n, 3); | 163 | CHECK_INT(n, 3); |
| 164 | dest[n] = 0; | 164 | dest[n] = 0; |
| 165 | CHECK_STR(dest, "a?b"); | 165 | CHECK_STR(dest, "a?b"); |
| 166 | 166 | ||
| 167 | test_case("an equals sign is literal inside a value"); | 167 | test_case("an equals sign is literal inside a value"); |
| 168 | p = equals; | 168 | p = equals; |
| 169 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 169 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 170 | CHECK_INT(n, 3); | 170 | CHECK_INT(n, 3); |
| 171 | dest[n] = 0; | 171 | dest[n] = 0; |
| 172 | CHECK_STR(dest, "a=b"); | 172 | CHECK_STR(dest, "a=b"); |
| @@ -179,7 +179,7 @@ static void case_ampersand_in_path(void) { | |||
| 179 | ssize_t n; | 179 | ssize_t n; |
| 180 | 180 | ||
| 181 | test_case("an ampersand in a path is a parse error"); | 181 | test_case("an ampersand in a path is a parse error"); |
| 182 | n = scan_urlencoded_query(&p, dest, SCAN_PATH); | 182 | n = urlencoded_parse(&p, dest, SCAN_PATH); |
| 183 | CHECK_INT(n, -1); | 183 | CHECK_INT(n, -1); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| @@ -190,7 +190,7 @@ static void case_raw_high_byte(void) { | |||
| 190 | ssize_t n; | 190 | ssize_t n; |
| 191 | 191 | ||
| 192 | test_case("an undecoded byte above ASCII is a parse error"); | 192 | test_case("an undecoded byte above ASCII is a parse error"); |
| 193 | n = scan_urlencoded_query(&p, dest, SCAN_SEARCHPATH_VALUE); | 193 | n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); |
| 194 | CHECK_INT(n, -1); | 194 | CHECK_INT(n, -1); |
| 195 | } | 195 | } |
| 196 | 196 | ||
| @@ -200,12 +200,12 @@ static void case_skipvalue(void) { | |||
| 200 | char *p = query; | 200 | char *p = query; |
| 201 | 201 | ||
| 202 | test_case("skipvalue steps over the value and its separator"); | 202 | test_case("skipvalue steps over the value and its separator"); |
| 203 | scan_urlencoded_skipvalue(&p); | 203 | urlencoded_skip_value(&p); |
| 204 | CHECK_STR(p, "next=1"); | 204 | CHECK_STR(p, "next=1"); |
| 205 | 205 | ||
| 206 | test_case("skipvalue leaves a hard terminator in place"); | 206 | test_case("skipvalue leaves a hard terminator in place"); |
| 207 | p = bare; | 207 | p = bare; |
| 208 | scan_urlencoded_skipvalue(&p); | 208 | urlencoded_skip_value(&p); |
| 209 | CHECK_INT(*p, 0); | 209 | CHECK_INT(*p, 0); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| @@ -217,15 +217,15 @@ static void case_find_keywords(void) { | |||
| 217 | char *p = match; | 217 | char *p = match; |
| 218 | 218 | ||
| 219 | test_case("a known keyword returns its value"); | 219 | test_case("a known keyword returns its value"); |
| 220 | CHECK_INT(scan_find_keywords(keywords, &p, SCAN_SEARCHPATH_PARAM), 2); | 220 | CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), 2); |
| 221 | 221 | ||
| 222 | test_case("an unknown keyword returns -3"); | 222 | test_case("an unknown keyword returns -3"); |
| 223 | p = nomatch; | 223 | p = nomatch; |
| 224 | CHECK_INT(scan_find_keywords(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); | 224 | CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); |
| 225 | 225 | ||
| 226 | test_case("a prefix of a keyword does not match it"); | 226 | test_case("a prefix of a keyword does not match it"); |
| 227 | p = prefix; | 227 | p = prefix; |
| 228 | CHECK_INT(scan_find_keywords(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); | 228 | CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static void case_fixed_int(void) { | 231 | static void case_fixed_int(void) { |
| @@ -265,7 +265,7 @@ static void case_fmt_passes_safe_bytes(void) { | |||
| 265 | size_t n; | 265 | size_t n; |
| 266 | 266 | ||
| 267 | test_case("alphanumerics and the safe punctuation pass through"); | 267 | test_case("alphanumerics and the safe punctuation pass through"); |
| 268 | n = fmt_urlencoded(dest, src, 11); | 268 | n = urlencoded_format(dest, src, 11); |
| 269 | dest[n] = 0; | 269 | dest[n] = 0; |
| 270 | CHECK_INT(n, 11); | 270 | CHECK_INT(n, 11); |
| 271 | CHECK_STR(dest, "aZ09$-./=_~"); | 271 | CHECK_STR(dest, "aZ09$-./=_~"); |
| @@ -277,7 +277,7 @@ static void case_fmt_escapes_the_rest(void) { | |||
| 277 | size_t n; | 277 | size_t n; |
| 278 | 278 | ||
| 279 | test_case("everything else becomes a percent escape"); | 279 | test_case("everything else becomes a percent escape"); |
| 280 | n = fmt_urlencoded(dest, src, sizeof(src)); | 280 | n = urlencoded_format(dest, src, sizeof(src)); |
| 281 | dest[n] = 0; | 281 | dest[n] = 0; |
| 282 | CHECK_INT(n, 18); | 282 | CHECK_INT(n, 18); |
| 283 | CHECK_STR(dest, "%20%25%26%2b%3a%3f"); | 283 | CHECK_STR(dest, "%20%25%26%2b%3a%3f"); |
| @@ -289,7 +289,7 @@ static void case_fmt_hex_is_lower_case(void) { | |||
| 289 | size_t n; | 289 | size_t n; |
| 290 | 290 | ||
| 291 | test_case("escapes use lower case hex digits"); | 291 | test_case("escapes use lower case hex digits"); |
| 292 | n = fmt_urlencoded(dest, src, sizeof(src)); | 292 | n = urlencoded_format(dest, src, sizeof(src)); |
| 293 | dest[n] = 0; | 293 | dest[n] = 0; |
| 294 | CHECK_INT(n, 9); | 294 | CHECK_INT(n, 9); |
| 295 | CHECK_STR(dest, "%00%ab%ff"); | 295 | CHECK_STR(dest, "%00%ab%ff"); |
| @@ -300,7 +300,7 @@ static void case_fmt_zero_length(void) { | |||
| 300 | 300 | ||
| 301 | test_case("a zero length input writes nothing"); | 301 | test_case("a zero length input writes nothing"); |
| 302 | memset(dest, 0x5a, sizeof(dest)); | 302 | memset(dest, 0x5a, sizeof(dest)); |
| 303 | CHECK_INT(fmt_urlencoded(dest, (const uint8_t *)"abc", 0), 0); | 303 | CHECK_INT(urlencoded_format(dest, (const uint8_t *)"abc", 0), 0); |
| 304 | CHECK_MEM(dest, "\x5a\x5a\x5a\x5a", 4); | 304 | CHECK_MEM(dest, "\x5a\x5a\x5a\x5a", 4); |
| 305 | } | 305 | } |
| 306 | 306 | ||
| @@ -312,7 +312,7 @@ static void case_fmt_worst_case_fits(void) { | |||
| 312 | test_case("a hash of entirely unsafe bytes needs three times its length"); | 312 | test_case("a hash of entirely unsafe bytes needs three times its length"); |
| 313 | for (i = 0; i < sizeof(src); ++i) | 313 | for (i = 0; i < sizeof(src); ++i) |
| 314 | src[i] = 0xff; | 314 | src[i] = 0xff; |
| 315 | n = fmt_urlencoded(dest, src, sizeof(src)); | 315 | n = urlencoded_format(dest, src, sizeof(src)); |
| 316 | dest[n] = 0; | 316 | dest[n] = 0; |
| 317 | CHECK_INT(n, 60); | 317 | CHECK_INT(n, 60); |
| 318 | for (i = 0; i < 20; ++i) | 318 | for (i = 0; i < 20; ++i) |
| @@ -328,7 +328,7 @@ static void case_fmt_decoder_disagrees_on_dollar(void) { | |||
| 328 | encoder passes through unescaped, '$' is the only one the decoder then | 328 | encoder passes through unescaped, '$' is the only one the decoder then |
| 329 | refuses, and it refuses the whole string rather than stopping short. | 329 | refuses, and it refuses the whole string rather than stopping short. |
| 330 | Output of the urlencoded full scrape therefore does not round trip | 330 | Output of the urlencoded full scrape therefore does not round trip |
| 331 | through scan_urlencoded_query when a hash contains 0x24. Harmless today | 331 | through urlencoded_parse when a hash contains 0x24. Harmless today |
| 332 | because only third party tooling reads that output. */ | 332 | because only third party tooling reads that output. */ |
| 333 | const uint8_t src[] = {'a', '$', 'b'}; | 333 | const uint8_t src[] = {'a', '$', 'b'}; |
| 334 | char dest[16]; | 334 | char dest[16]; |
| @@ -338,15 +338,15 @@ static void case_fmt_decoder_disagrees_on_dollar(void) { | |||
| 338 | ssize_t got; | 338 | ssize_t got; |
| 339 | 339 | ||
| 340 | test_case("the encoder passes '$' but the decoder rejects it"); | 340 | test_case("the encoder passes '$' but the decoder rejects it"); |
| 341 | n = fmt_urlencoded(dest, src, sizeof(src)); | 341 | n = urlencoded_format(dest, src, sizeof(src)); |
| 342 | dest[n] = 0; | 342 | dest[n] = 0; |
| 343 | CHECK_STR(dest, "a$b"); | 343 | CHECK_STR(dest, "a$b"); |
| 344 | 344 | ||
| 345 | got = scan_urlencoded_query(&p, scanned, SCAN_SEARCHPATH_VALUE); | 345 | got = urlencoded_parse(&p, scanned, SCAN_SEARCHPATH_VALUE); |
| 346 | CHECK_INT(got, -1); | 346 | CHECK_INT(got, -1); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | void test_scan_urlencoded_query(void) { | 349 | void test_urlencoded(void) { |
| 350 | case_path(); | 350 | case_path(); |
| 351 | case_param_and_value(); | 351 | case_param_and_value(); |
| 352 | case_percent_decoding(); | 352 | case_percent_decoding(); |
diff --git a/tests/t_vector.c b/tests/t_vector.c index a8186b2..541a6da 100644 --- a/tests/t_vector.c +++ b/tests/t_vector.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "trackerlogic.h" | 13 | #include "trackerlogic.h" |
| 14 | #include "test.h" | 14 | #include "test.h" |
| 15 | 15 | ||
| 16 | /* binary_search returns the matching member when there is one, and otherwise | 16 | /* vector_binary_search returns the matching member when there is one, and otherwise |
| 17 | the position at which the key would have to be inserted to keep the vector | 17 | the position at which the key would have to be inserted to keep the vector |
| 18 | sorted. exactmatch distinguishes the two. */ | 18 | sorted. exactmatch distinguishes the two. */ |
| 19 | 19 | ||
| @@ -25,7 +25,7 @@ static void case_search_finds_member(void) { | |||
| 25 | void *found; | 25 | void *found; |
| 26 | 26 | ||
| 27 | test_case("an existing key is found"); | 27 | test_case("an existing key is found"); |
| 28 | found = binary_search(key, sorted, 5, 4, 4, &exactmatch); | 28 | found = vector_binary_search(key, sorted, 5, 4, 4, &exactmatch); |
| 29 | CHECK(exactmatch != 0); | 29 | CHECK(exactmatch != 0); |
| 30 | CHECK_PTR(found, sorted[2]); | 30 | CHECK_PTR(found, sorted[2]); |
| 31 | } | 31 | } |
| @@ -36,9 +36,9 @@ static void case_search_finds_first_and_last(void) { | |||
| 36 | int exactmatch; | 36 | int exactmatch; |
| 37 | 37 | ||
| 38 | test_case("the first and last members are found"); | 38 | test_case("the first and last members are found"); |
| 39 | CHECK_PTR(binary_search(first, sorted, 5, 4, 4, &exactmatch), sorted[0]); | 39 | CHECK_PTR(vector_binary_search(first, sorted, 5, 4, 4, &exactmatch), sorted[0]); |
| 40 | CHECK(exactmatch != 0); | 40 | CHECK(exactmatch != 0); |
| 41 | CHECK_PTR(binary_search(last, sorted, 5, 4, 4, &exactmatch), sorted[4]); | 41 | CHECK_PTR(vector_binary_search(last, sorted, 5, 4, 4, &exactmatch), sorted[4]); |
| 42 | CHECK(exactmatch != 0); | 42 | CHECK(exactmatch != 0); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| @@ -49,11 +49,11 @@ static void case_search_insert_position(void) { | |||
| 49 | void *slot; | 49 | void *slot; |
| 50 | 50 | ||
| 51 | test_case("a missing key yields its insert position"); | 51 | test_case("a missing key yields its insert position"); |
| 52 | slot = binary_search(middle, sorted, 5, 4, 4, &exactmatch); | 52 | slot = vector_binary_search(middle, sorted, 5, 4, 4, &exactmatch); |
| 53 | CHECK_INT(exactmatch, 0); | 53 | CHECK_INT(exactmatch, 0); |
| 54 | CHECK_PTR(slot, sorted[2]); | 54 | CHECK_PTR(slot, sorted[2]); |
| 55 | 55 | ||
| 56 | slot = binary_search(before, sorted, 5, 4, 4, &exactmatch); | 56 | slot = vector_binary_search(before, sorted, 5, 4, 4, &exactmatch); |
| 57 | CHECK_INT(exactmatch, 0); | 57 | CHECK_INT(exactmatch, 0); |
| 58 | CHECK_PTR(slot, sorted[0]); | 58 | CHECK_PTR(slot, sorted[0]); |
| 59 | } | 59 | } |
| @@ -64,7 +64,7 @@ static void case_search_past_the_end(void) { | |||
| 64 | void *slot; | 64 | void *slot; |
| 65 | 65 | ||
| 66 | test_case("a key above every member yields the position past the end"); | 66 | test_case("a key above every member yields the position past the end"); |
| 67 | slot = binary_search(beyond, sorted, 5, 4, 4, &exactmatch); | 67 | slot = vector_binary_search(beyond, sorted, 5, 4, 4, &exactmatch); |
| 68 | CHECK_INT(exactmatch, 0); | 68 | CHECK_INT(exactmatch, 0); |
| 69 | CHECK_PTR(slot, sorted[5]); | 69 | CHECK_PTR(slot, sorted[5]); |
| 70 | } | 70 | } |
| @@ -74,7 +74,7 @@ static void case_search_empty(void) { | |||
| 74 | void *base = (void *)sorted; | 74 | void *base = (void *)sorted; |
| 75 | 75 | ||
| 76 | test_case("searching an empty vector reports no match at the base"); | 76 | test_case("searching an empty vector reports no match at the base"); |
| 77 | CHECK_PTR(binary_search(sorted[0], base, 0, 4, 4, &exactmatch), base); | 77 | CHECK_PTR(vector_binary_search(sorted[0], base, 0, 4, 4, &exactmatch), base); |
| 78 | CHECK_INT(exactmatch, 0); | 78 | CHECK_INT(exactmatch, 0); |
| 79 | } | 79 | } |
| 80 | 80 | ||
diff --git a/tests/test.h b/tests/test.h index fd574c2..cebd08a 100644 --- a/tests/test.h +++ b/tests/test.h | |||
| @@ -76,7 +76,7 @@ extern unsigned long test_failures; | |||
| 76 | } while (0) | 76 | } while (0) |
| 77 | 77 | ||
| 78 | /* One entry point per module under test */ | 78 | /* One entry point per module under test */ |
| 79 | void test_scan_urlencoded_query(void); | 79 | void test_urlencoded(void); |
| 80 | void test_iovec(void); | 80 | void test_iovec(void); |
| 81 | void test_vector(void); | 81 | void test_vector(void); |
| 82 | void test_random(void); | 82 | void test_random(void); |
| @@ -88,5 +88,6 @@ void test_ip(void); | |||
| 88 | void test_socket(void); | 88 | void test_socket(void); |
| 89 | void test_mutex(void); | 89 | void test_mutex(void); |
| 90 | void test_batch(void); | 90 | void test_batch(void); |
| 91 | void test_fdstate(void); | ||
| 91 | 92 | ||
| 92 | #endif | 93 | #endif |
diff --git a/trackerlogic.c b/trackerlogic.c index 74fea6d..9705bd6 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -381,7 +381,7 @@ size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, s | |||
| 381 | size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply) { | 381 | size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply) { |
| 382 | int exactmatch, delta_torrentcount = 0; | 382 | int exactmatch, delta_torrentcount = 0; |
| 383 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); | 383 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); |
| 384 | ot_torrent *torrent = binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); | 384 | ot_torrent *torrent = vector_binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
| 385 | 385 | ||
| 386 | if (!exactmatch) { | 386 | if (!exactmatch) { |
| 387 | memset(reply, 0, 12); | 387 | memset(reply, 0, 12); |
| @@ -414,7 +414,7 @@ size_t return_tcp_scrape_for_torrent(ot_hash const *hash_list, size_t amount, ch | |||
| 414 | int delta_torrentcount = 0; | 414 | int delta_torrentcount = 0; |
| 415 | ot_hash const *hash = hash_list + i; | 415 | ot_hash const *hash = hash_list + i; |
| 416 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*hash); | 416 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*hash); |
| 417 | ot_torrent *torrent = binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); | 417 | ot_torrent *torrent = vector_binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
| 418 | 418 | ||
| 419 | if (exactmatch) { | 419 | if (exactmatch) { |
| 420 | if (clean_single_torrent(torrent)) { | 420 | if (clean_single_torrent(torrent)) { |
| @@ -443,7 +443,7 @@ static ot_peerlist dummy_list; | |||
| 443 | size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws) { | 443 | size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws) { |
| 444 | int exactmatch; | 444 | int exactmatch; |
| 445 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*ws->hash); | 445 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*ws->hash); |
| 446 | ot_torrent *torrent = binary_search(ws->hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); | 446 | ot_torrent *torrent = vector_binary_search(ws->hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
| 447 | ot_peerlist *peer_list = &dummy_list; | 447 | ot_peerlist *peer_list = &dummy_list; |
| 448 | size_t peer_size; /* initialized in next line */ | 448 | size_t peer_size; /* initialized in next line */ |
| 449 | ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); | 449 | ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); |
