From 2c7659ec930277981b6333b5b3aff7840d11933c Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Sun, 25 Oct 2026 18:51:51 +0100 Subject: Decouple config parsing from binding and worker spawning * Options are parsed now into a listener description list before binding them at once and starting the workers later * UDP workers can now be configured per connection * socket reuse is now done more sensibly, mcast sockets always reused * Hold-off logic after spawning udp workers removed --- opentracker.c | 242 ++++++++++++++++++++++++++++++++++++------------ opentracker.conf.sample | 28 ++++-- ot_socket.c | 36 +++---- ot_socket.h | 9 +- ot_udp.c | 24 ++--- ot_udp.h | 4 +- tests/t_socket.c | 34 +++---- trackerlogic.c | 1 - 8 files changed, 253 insertions(+), 125 deletions(-) diff --git a/opentracker.c b/opentracker.c index 5b197d1..5f21ede 100644 --- a/opentracker.c +++ b/opentracker.c @@ -48,7 +48,22 @@ int g_self_pipe[2]; static char *g_serverdir; static char *g_serveruser; -static unsigned int g_udp_workers; + +typedef struct { + ot_ip6 ip; + uint16_t port; + PROTO_FLAG proto; + int shared; + int workers; + int64_t sock; +} ot_listen; +#define OT_LISTEN_INHERIT (-1) + +/* Config entries collected from command line and config files */ +static ot_listen *g_listen; +static size_t g_listen_count; +static int g_listen_shared; +static int g_listen_workers; static void panic(const char *routine) __attribute__((noreturn)); static void panic(const char *routine) { @@ -338,44 +353,156 @@ static void *server_mainloop(void *args) { return 0; } -static int64_t ot_try_bind(ot_ip6 ip, uint16_t port, PROTO_FLAG proto) { - int64_t sock; +static void listen_append(const ot_ip6 ip, uint16_t port, PROTO_FLAG proto, int shared, int workers) { + ot_listen *grown = realloc(g_listen, (g_listen_count + 1) * sizeof(ot_listen)); + ot_listen *entry; + + if (!grown) + panic("listen_append"); + g_listen = grown; + + entry = g_listen + g_listen_count++; + memcpy(entry->ip, ip, sizeof(ot_ip6)); + entry->port = port; + entry->proto = proto; + entry->shared = shared; + entry->workers = workers; + entry->sock = -1; +} + +typedef enum { LISTEN_OPTION_UNKNOWN, LISTEN_OPTION_SHARED, LISTEN_OPTION_WORKERS } listen_option_kind; + +typedef struct { + const char *name; + size_t len; + listen_option_kind kind; + int takes_value; +} listen_option_key; + +#define LISTEN_OPTION_KEY(s, k, v) {s, sizeof(s) - 1, k, v} + +static const listen_option_key listen_option_keys[] = { + LISTEN_OPTION_KEY("shared", LISTEN_OPTION_SHARED, 0), + LISTEN_OPTION_KEY("workers", LISTEN_OPTION_WORKERS, 1), +}; +static const size_t listen_option_count = sizeof(listen_option_keys) / sizeof(listen_option_keys[0]); + +static listen_option_kind parse_listen_option(char **p) { + size_t i; + + for (i = 0; i < listen_option_count; ++i) { + const listen_option_key *key = &listen_option_keys[i]; + char delimiter = (*p)[key->len]; + + if (strncmp(*p, key->name, key->len)) + continue; + if (key->takes_value ? delimiter != '=' : (delimiter && !isspace((unsigned char)delimiter))) + continue; + + *p += key->len + (key->takes_value ? 1 : 0); + return key->kind; + } + return LISTEN_OPTION_UNKNOWN; +} + +/* Options trailing an address in a listen statement, in any order */ +static int listen_scan_options(char *p, int *shared, int *workers) { + uint64_t value; + + for (;;) { + while (isspace((unsigned char)*p)) + ++p; + if (!*p) + return 1; + + switch (parse_listen_option(&p)) { + case LISTEN_OPTION_SHARED: + *shared = 1; + break; + case LISTEN_OPTION_WORKERS: { + size_t off = scan_udec(p, &value, UINT_MAX); + + if (!off) + return 0; + *workers = (int)value; + p += off; + break; + } + default: + return 0; + } + } +} + +static int listen_option(int value, int fallback) { return value == OT_LISTEN_INHERIT ? fallback : value; } + +static void listen_bind_one(ot_listen *entry) { + socket_sharing sharing = listen_option(entry->shared, g_listen_shared) ? SOCKET_SHARED : SOCKET_EXCLUSIVE; #ifdef _DEBUG { char *protos[] = {"TCP", "UDP", "UDP mcast"}; char _debug[512]; - int off = snprintf(_debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto]); - off += ip_format(_debug + off, ip); - snprintf(_debug + off, sizeof(_debug) - off, "]:%d...", port); + int off = snprintf(_debug, sizeof(_debug), "Binding socket type %s to address [", protos[entry->proto]); + off += ip_format(_debug + off, entry->ip); + snprintf(_debug + off, sizeof(_debug) - off, "]:%d...", entry->port); fputs(_debug, stderr); } #endif - if (proto == FLAG_TCP) { - if ((sock = socket_tcp_listen(ip, port)) == -1) +#ifdef WANT_SYNC_LIVE + if (entry->proto == FLAG_MCA) { + livesync_bind_mcast(entry->ip, entry->port); +#ifdef _DEBUG + fputs(" success.\n", stderr); +#endif + return; + } +#endif + + if (entry->proto == FLAG_TCP) { + if ((entry->sock = socket_tcp_listen(entry->ip, entry->port, sharing)) == -1) panic("socket_tcp_listen"); } else { - if ((sock = socket_udp_bind(ip, port)) == -1) + if ((entry->sock = socket_udp_bind(entry->ip, entry->port, sharing)) == -1) panic("socket_udp_bind"); } - if (!io_fd(sock)) + if (!io_fd(entry->sock)) panic("io_fd"); - io_setcookie(sock, (void *)proto); - - if ((proto == FLAG_UDP) && g_udp_workers) { - io_block(sock); - udp_init(sock, g_udp_workers); - } else - io_wantread(sock); + io_setcookie(entry->sock, (void *)entry->proto); + io_wantread(entry->sock); #ifdef _DEBUG fputs(" success.\n", stderr); #endif +} + +/* Bound in the order the entries were given. + Note: On macOS SO_REUSEPORT delivers everything to the socket that bound last. */ +static void listen_bind_all(void) { + size_t i; + + for (i = 0; i < g_listen_count; ++i) + listen_bind_one(g_listen + i); +} + +static void listen_start_udp_workers(void) { + size_t i; + + udp_init(); - return sock; + for (i = 0; i < g_listen_count; ++i) { + ot_listen *entry = g_listen + i; + int workers = listen_option(entry->workers, g_listen_workers); + + if (entry->proto != FLAG_UDP || workers <= 0) + continue; + + io_block(entry->sock); + udp_workers_install(entry->sock, (unsigned int)workers); + } } char *set_config_option(char **option, char *value) { @@ -452,7 +579,7 @@ typedef enum { CONFIG_LISTEN_TCP, CONFIG_LISTEN_UDP, CONFIG_LISTEN_UDP_WORKERS, - CONFIG_LISTEN_REUSEPORT, + CONFIG_LISTEN_SHARED, CONFIG_ACCESS_WHITELIST, CONFIG_ACCESS_BLACKLIST, CONFIG_ACCESS_FIFO_ADD, @@ -480,7 +607,7 @@ static const config_key config_keys[] = { CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP), CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP), CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS), - CONFIG_KEY("listen.reuseport", CONFIG_LISTEN_REUSEPORT), + CONFIG_KEY("listen.shared", CONFIG_LISTEN_SHARED), #ifdef WANT_ACCESSLIST_WHITE CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST), #elif defined(WANT_ACCESSLIST_BLACK) @@ -537,9 +664,10 @@ int parse_configfile(char *config_filename) { } while (fgets(inbuf, sizeof(inbuf), config_file_handle)) { - char *p = inbuf, *end; - uint64_t value; - uint16_t tmpport = 6969; + char *p = inbuf, *end; + uint64_t value; + uint16_t tmpport = 6969; + config_kind kind; /* Skip white spaces */ while (isspace((unsigned char)*p)) @@ -555,7 +683,8 @@ int parse_configfile(char *config_filename) { *--end = 0; /* Scan for commands */ - switch (parse_config_key(&p)) { + kind = parse_config_key(&p); + switch (kind) { case CONFIG_TRACKER_ROOTDIR: set_config_option(&g_serverdir, p); break; @@ -563,35 +692,29 @@ int parse_configfile(char *config_filename) { set_config_option(&g_serveruser, p); break; case CONFIG_LISTEN_TCP_UDP: - if (!scan_ip6_port(p, tmpip, &tmpport)) - goto parse_error; - ot_try_bind(tmpip, tmpport, FLAG_TCP); - ++bound; - ot_try_bind(tmpip, tmpport, FLAG_UDP); - ++bound; - break; case CONFIG_LISTEN_TCP: - if (!scan_ip6_port(p, tmpip, &tmpport)) - goto parse_error; - ot_try_bind(tmpip, tmpport, FLAG_TCP); - ++bound; - break; - case CONFIG_LISTEN_UDP: - if (!scan_ip6_port(p, tmpip, &tmpport)) + case CONFIG_LISTEN_UDP: { + int shared = OT_LISTEN_INHERIT + int workers = OT_LISTEN_INHERIT; + int off = scan_ip6_port(p, tmpip, &tmpport); + + if (!off || !listen_scan_options(p + off, &shared, &workers)) goto parse_error; - ot_try_bind(tmpip, tmpport, FLAG_UDP); - ++bound; + if (kind != CONFIG_LISTEN_UDP) + listen_append(tmpip, tmpport, FLAG_TCP, shared, OT_LISTEN_INHERIT), ++bound; + if (kind != CONFIG_LISTEN_TCP) + listen_append(tmpip, tmpport, FLAG_UDP, shared, workers), ++bound; break; + } case CONFIG_LISTEN_UDP_WORKERS: - if (scan_udec(p, &value, UINT_MAX)) - g_udp_workers = (unsigned int)value; + if (!scan_udec(p, &value, UINT_MAX)) + goto parse_error; + g_listen_workers = (int)value; break; - case CONFIG_LISTEN_REUSEPORT: - /* Like listen.udp.workers this is read when a socket is bound, so it - has to come before the listen lines it should apply to. */ + case CONFIG_LISTEN_SHARED: if (!scan_udec(p, &value, 1)) goto parse_error; - g_socket_reuseport = (int)value; + g_listen_shared = (int)value; break; #ifdef WANT_ACCESSLIST_WHITE case CONFIG_ACCESS_WHITELIST: @@ -638,9 +761,14 @@ int parse_configfile(char *config_filename) { break; case CONFIG_LIVESYNC_CLUSTER_LISTEN: tmpport = LIVESYNC_PORT; - if (!scan_ip6_port(p, tmpip, &tmpport)) - goto parse_error; - livesync_bind_mcast(tmpip, tmpport); + { + int shared = OT_LISTEN_INHERIT, dummy = OT_LISTEN_INHERIT; + int off = scan_ip6_port(p, tmpip, &tmpport); + + if (!off || !listen_scan_options(p + off, &shared, &dummy)) + goto parse_error; + listen_append(tmpip, tmpport, FLAG_MCA, shared, OT_LISTEN_INHERIT); + } break; #endif default: @@ -791,7 +919,7 @@ int main(int argc, char **argv) { usage(argv[0]); exit(1); } - ot_try_bind(serverip, (uint16_t)value, FLAG_TCP); + listen_append(serverip, (uint16_t)value, FLAG_TCP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); bound++; break; case 'P': @@ -799,7 +927,7 @@ int main(int argc, char **argv) { usage(argv[0]); exit(1); } - ot_try_bind(serverip, (uint16_t)value, FLAG_UDP); + listen_append(serverip, (uint16_t)value, FLAG_UDP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); bound++; break; #ifdef WANT_SYNC_LIVE @@ -808,7 +936,7 @@ int main(int argc, char **argv) { usage(argv[0]); exit(1); } - livesync_bind_mcast(serverip, (uint16_t)value); + listen_append(serverip, (uint16_t)value, FLAG_MCA, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); break; #endif case 'd': @@ -849,12 +977,13 @@ int main(int argc, char **argv) { } } - /* Bind to our default tcp/udp ports */ if (!bound) { - ot_try_bind(serverip, 6969, FLAG_TCP); - ot_try_bind(serverip, 6969, FLAG_UDP); + listen_append(serverip, 6969, FLAG_TCP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); + listen_append(serverip, 6969, FLAG_UDP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); } + listen_bind_all(); + defaul_signal_handlers(); #ifdef WANT_SYSLOGS @@ -893,8 +1022,7 @@ int main(int argc, char **argv) { install_signal_handlers(); - if (!g_udp_workers) - udp_init(-1, 0); + listen_start_udp_workers(); server_mainloop(0); diff --git a/opentracker.conf.sample b/opentracker.conf.sample index 054e405..4adb736 100644 --- a/opentracker.conf.sample +++ b/opentracker.conf.sample @@ -7,14 +7,8 @@ # If no listen option is given (here or on the command line), opentracker # listens on 0.0.0.0:6969 tcp and udp. # -# The next variable determines if udp sockets are handled in the event -# loop (set it to 0, the default) or are handled in blocking reads in -# dedicated worker threads. You have to set this value before the -# listen.tcp_udp or listen.udp statements before it takes effect, but you -# can re-set it for each listen statement. Normally you should keep it at -# the top of the config file. -# -# listen.udp.workers 4 +# Addresses are collected while this file is read and bound afterwards, +# so the order of the statements below does not matter. # # listen.tcp_udp 0.0.0.0 # listen.tcp_udp 192.168.0.1:80 @@ -25,6 +19,24 @@ # listen.tcp 0.0.0.0 # listen.udp 192.168.0.1:6969 # +# A listen statement takes options after the address: +# +# workers= handle this udp socket in blocking reads in that +# many dedicated worker threads instead of in the +# event loop. Ignored for tcp. +# shared allow another process to bind the same address and +# let the kernel share the traffic. Only useful if you +# deliberately run a second tracker there. +# +# listen.udp 10.0.0.5:6969 workers=4 shared +# +# The two statements below set defaults for every listen statement in +# this file that does not name the option itself. They may appear +# anywhere. +# +# listen.udp.workers 4 +# listen.shared 1 +# # Note, that using 0.0.0.0 for udp sockets may yield surprising results. # An answer packet sent on that socket will not necessarily have the # source address that the requesting client may expect, but any address diff --git a/ot_socket.c b/ot_socket.c index e26ad52..84020ca 100644 --- a/ot_socket.c +++ b/ot_socket.c @@ -15,8 +15,6 @@ #include "ot_ip.h" #include "ot_socket.h" -int g_socket_reuseport; - static void sockaddr_from_ip(struct sockaddr_in6 *sa, const ot_ip6 ip, uint16_t port) { memset(sa, 0, sizeof(*sa)); sa->sin6_family = AF_INET6; @@ -75,37 +73,43 @@ static int socket_v6(int type) { return s; } -static int socket_bind_v6(int s, const ot_ip6 ip, uint16_t port) { - struct sockaddr_in6 sa; - int one = 1; +/* The only place in the tree that needs to know what a kernel calls this */ +static void socket_set_sharing(int s, socket_sharing sharing) { + int one = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); #ifdef SO_REUSEPORT - if (g_socket_reuseport) + if (sharing == SOCKET_SHARED) setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); #endif +} + +static int socket_bind_v6(int s, const ot_ip6 ip, uint16_t port, socket_sharing sharing) { + struct sockaddr_in6 sa; + + socket_set_sharing(s, sharing); sockaddr_from_ip(&sa, ip, port); return bind(s, (struct sockaddr *)&sa, sizeof(sa)); } -int socket_tcp_listen(const ot_ip6 ip, uint16_t port) { +int socket_tcp_listen(const ot_ip6 ip, uint16_t port, socket_sharing sharing) { int s = socket_v6(SOCK_STREAM); if (s == -1) return -1; - if (socket_bind_v6(s, ip, port) == -1 || listen(s, SOMAXCONN) == -1) + if (socket_bind_v6(s, ip, port, sharing) == -1 || listen(s, SOMAXCONN) == -1) return close_and_fail(s); return s; } -int socket_udp_bind(const ot_ip6 ip, uint16_t port) { +int socket_udp_bind(const ot_ip6 ip, uint16_t port, socket_sharing sharing) { int s = socket_v6(SOCK_DGRAM); if (s == -1) return -1; - if (socket_bind_v6(s, ip, port) == -1) + if (socket_bind_v6(s, ip, port, sharing) == -1) return close_and_fail(s); return s; @@ -117,7 +121,7 @@ int socket_tcp_connect(const ot_ip6 srcip, uint16_t srcport, const ot_ip6 dstip, if (s == -1) return -1; - if (socket_bind_v6(s, srcip, srcport) == -1) + if (socket_bind_v6(s, srcip, srcport, SOCKET_EXCLUSIVE) == -1) return close_and_fail(s); sockaddr_from_ip(&sa, dstip, dstport); @@ -187,18 +191,16 @@ static void sockaddr4_from_ip(struct sockaddr_in *sa, const ot_ip6 ip, uint16_t memcpy(&sa->sin_addr, ip + sizeof(ip_v4mapped_prefix), 4); } +/* A multicast group is meant to have several listeners, so these are always + shared */ static int socket_v4_bind(const ot_ip6 ip, uint16_t port) { struct sockaddr_in sa; - int s, one = 1; + int s; if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) return -1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); -#ifdef SO_REUSEPORT - if (g_socket_reuseport) - setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); -#endif + socket_set_sharing(s, SOCKET_SHARED); sockaddr4_from_ip(&sa, ip, port); if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1) diff --git a/ot_socket.h b/ot_socket.h index 20fd839..21d04b1 100644 --- a/ot_socket.h +++ b/ot_socket.h @@ -15,13 +15,14 @@ cleared, so one descriptor serves both families and an IPv4 peer arrives as the v4 mapped address */ -/* Ask the kernel to let several processes bind the same address */ -extern int g_socket_reuseport; +/* How an address may be shared with other sockets. Which socket option says + so differs between kernels, which is socket_set_sharing's business */ +typedef enum { SOCKET_EXCLUSIVE, SOCKET_SHARED } socket_sharing; /* Create, bind and, for TCP, listen. The returned socket is non blocking Returns -1 on failure with errno set */ -int socket_tcp_listen(const ot_ip6 ip, uint16_t port); -int socket_udp_bind(const ot_ip6 ip, uint16_t port); +int socket_tcp_listen(const ot_ip6 ip, uint16_t port, socket_sharing sharing); +int socket_udp_bind(const ot_ip6 ip, uint16_t port, socket_sharing sharing); int socket_tcp_connect(const ot_ip6 srcip, uint16_t srcport, const ot_ip6 dstip, uint16_t dstport); int socket_is_connected(int s); diff --git a/ot_udp.c b/ot_udp.c index dc8267c..7f6517f 100644 --- a/ot_udp.c +++ b/ot_udp.c @@ -26,9 +26,6 @@ static uint32_t g_rijndael_round_key[44] = {0}; static volatile uint32_t g_key_of_the_hour[2] = {0}; static volatile ot_time g_hour_of_the_key; -static pthread_mutex_t udp_start_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t udp_start_cond = PTHREAD_COND_INITIALIZER; -static int g_opentracker_started = 0; static void udp_generate_rijndael_round_key(void) { uint32_t key[16]; @@ -211,11 +208,6 @@ static void *udp_worker(void *args) { ws.debugbuf = malloc(G_DEBUGBUF_SIZE); #endif - pthread_mutex_lock(&udp_start_mutex); - while(g_opentracker_running && !g_opentracker_started) - pthread_cond_wait(&udp_start_cond, &udp_start_mutex); - pthread_mutex_unlock(&udp_start_mutex); - while (g_opentracker_running) handle_udp6(sock, &ws); @@ -227,20 +219,18 @@ static void *udp_worker(void *args) { return NULL; } -void udp_init(int64_t sock, unsigned int worker_count) { - pthread_t thread_id; +void udp_init(void) { if (!g_rijndael_round_key[0]) udp_generate_rijndael_round_key(); +} + +void udp_workers_install(int64_t sock, unsigned int worker_count) { + pthread_t thread_id; + #ifdef _DEBUG - fprintf(stderr, " installing %d workers on udp socket %ld\n", worker_count, (unsigned long)sock); + fprintf(stderr, "Installing %d workers on udp socket %ld\n", worker_count, (unsigned long)sock); #endif while (worker_count--) pthread_create(&thread_id, NULL, udp_worker, (void *)sock); } -void udp_kickoff(void) { - pthread_mutex_lock(&udp_start_mutex); - g_opentracker_started = 1; - pthread_cond_broadcast(&udp_start_cond); - pthread_mutex_unlock(&udp_start_mutex); -} diff --git a/ot_udp.h b/ot_udp.h index 87d99a9..a8ab9fc 100644 --- a/ot_udp.h +++ b/ot_udp.h @@ -10,8 +10,8 @@ #include "trackerlogic.h" -void udp_init(int64_t sock, unsigned int worker_count); -void udp_kickoff(void); +void udp_init(void); +void udp_workers_install(int64_t sock, unsigned int worker_count); int handle_udp6(int64_t serversocket, struct ot_workstruct *ws); #endif diff --git a/tests/t_socket.c b/tests/t_socket.c index bbc9e5e..8eef7fd 100644 --- a/tests/t_socket.c +++ b/tests/t_socket.c @@ -91,14 +91,14 @@ static void case_socket_options(void) { int udp, tcp; test_case("a bound udp socket is non blocking and serves both families"); - udp = socket_udp_bind(ip_any, 0); + udp = socket_udp_bind(ip_any, 0, SOCKET_EXCLUSIVE); CHECK(udp != -1); CHECK_INT(is_nonblocking(udp), 1); CHECK_INT(sock_flag(udp, IPPROTO_IPV6, IPV6_V6ONLY), 0); close(udp); test_case("a listening tcp socket is non blocking and serves both families"); - tcp = socket_tcp_listen(ip_any, 0); + tcp = socket_tcp_listen(ip_any, 0, SOCKET_EXCLUSIVE); CHECK(tcp != -1); CHECK_INT(is_nonblocking(tcp), 1); CHECK_INT(sock_flag(tcp, IPPROTO_IPV6, IPV6_V6ONLY), 0); @@ -106,24 +106,20 @@ static void case_socket_options(void) { } #ifdef SO_REUSEPORT -static void case_reuseport_is_opt_in(void) { +static void case_sharing_is_opt_in(void) { int s; - test_case("reuseport stays off unless the operator asks for it"); - g_socket_reuseport = 0; - s = socket_udp_bind(ip_loopback, 0); + test_case("an address is exclusive unless sharing is asked for"); + s = socket_udp_bind(ip_loopback, 0, SOCKET_EXCLUSIVE); CHECK(s != -1); CHECK_INT(sock_flag(s, SOL_SOCKET, SO_REUSEPORT), 0); close(s); - test_case("reuseport reaches the socket when it is asked for"); - g_socket_reuseport = 1; - s = socket_udp_bind(ip_loopback, 0); + test_case("and shared when it is"); + s = socket_udp_bind(ip_loopback, 0, SOCKET_SHARED); CHECK(s != -1); CHECK_INT(sock_flag(s, SOL_SOCKET, SO_REUSEPORT), 1); close(s); - - g_socket_reuseport = 0; } #endif @@ -135,7 +131,7 @@ static void case_udp_roundtrip(void) { int s; test_case("a datagram comes back with the sender's address and port"); - s = socket_udp_bind(ip_loopback, 0); + s = socket_udp_bind(ip_loopback, 0, SOCKET_EXCLUSIVE); CHECK(s != -1); bound_address(s, own_ip, &own_port); CHECK(own_port != 0); @@ -158,9 +154,9 @@ static void case_udp_v4mapped(void) { int receiver, sender; test_case("an IPv4 sender is reported in its v4 mapped form"); - receiver = socket_udp_bind(ip_v4_loopback, 0); + receiver = socket_udp_bind(ip_v4_loopback, 0, SOCKET_EXCLUSIVE); CHECK(receiver != -1); - sender = socket_udp_bind(ip_v4_loopback, 0); + sender = socket_udp_bind(ip_v4_loopback, 0, SOCKET_EXCLUSIVE); CHECK(sender != -1); bound_address(receiver, receiver_ip, &receiver_port); bound_address(sender, sender_ip, &sender_port); @@ -184,7 +180,7 @@ static void case_tcp_roundtrip(void) { int listener, client, accepted; test_case("a connection is accepted and carries the caller's address"); - listener = socket_tcp_listen(ip_loopback, 0); + listener = socket_tcp_listen(ip_loopback, 0, SOCKET_EXCLUSIVE); CHECK(listener != -1); bound_address(listener, listener_ip, &listener_port); CHECK(listener_port != 0); @@ -216,7 +212,7 @@ static void case_connect_refused(void) { test_case("a refused connection is reported by socket_is_connected"); /* Take a port, then drop it, so nothing is listening on it any more */ - listener = socket_tcp_listen(ip_loopback, 0); + listener = socket_tcp_listen(ip_loopback, 0, SOCKET_EXCLUSIVE); CHECK(listener != -1); bound_address(listener, listener_ip, &port); close(listener); @@ -247,8 +243,8 @@ static void case_bind_failure(void) { test_case("binding an address no interface carries fails"); before = next_descriptor(); CHECK(before != -1); - CHECK_INT(socket_tcp_listen(ip_unassigned, 0), -1); - CHECK_INT(socket_udp_bind(ip_unassigned, 0), -1); + CHECK_INT(socket_tcp_listen(ip_unassigned, 0, SOCKET_EXCLUSIVE), -1); + CHECK_INT(socket_udp_bind(ip_unassigned, 0, SOCKET_EXCLUSIVE), -1); test_case("a failed bind leaves no socket behind"); CHECK_INT(next_descriptor(), before); @@ -294,7 +290,7 @@ static void case_mcast_sender(void) { void test_socket(void) { case_socket_options(); #ifdef SO_REUSEPORT - case_reuseport_is_opt_in(); + case_sharing_is_opt_in(); #endif case_udp_roundtrip(); case_udp_v4mapped(); diff --git a/trackerlogic.c b/trackerlogic.c index db1d787..52c8c18 100644 --- a/trackerlogic.c +++ b/trackerlogic.c @@ -569,7 +569,6 @@ void trackerlogic_init(void) { accesslist_init(); livesync_init(); stats_init(); - udp_kickoff(); } void trackerlogic_deinit(void) { -- cgit v1.3