diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-25 18:51:51 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-25 18:51:51 +0100 |
| commit | 2c7659ec930277981b6333b5b3aff7840d11933c (patch) | |
| tree | 1c363ce905ef1a62395f398335a94a47916af278 /ot_socket.c | |
| parent | 632960a33eb8d23925b2bbef24d5065de7280aef (diff) | |
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
Diffstat (limited to 'ot_socket.c')
| -rw-r--r-- | ot_socket.c | 36 |
1 files changed, 19 insertions, 17 deletions
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 @@ | |||
| 15 | #include "ot_ip.h" | 15 | #include "ot_ip.h" |
| 16 | #include "ot_socket.h" | 16 | #include "ot_socket.h" |
| 17 | 17 | ||
| 18 | int g_socket_reuseport; | ||
| 19 | |||
| 20 | static void sockaddr_from_ip(struct sockaddr_in6 *sa, const ot_ip6 ip, uint16_t port) { | 18 | static void sockaddr_from_ip(struct sockaddr_in6 *sa, const ot_ip6 ip, uint16_t port) { |
| 21 | memset(sa, 0, sizeof(*sa)); | 19 | memset(sa, 0, sizeof(*sa)); |
| 22 | sa->sin6_family = AF_INET6; | 20 | sa->sin6_family = AF_INET6; |
| @@ -75,37 +73,43 @@ static int socket_v6(int type) { | |||
| 75 | return s; | 73 | return s; |
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | static int socket_bind_v6(int s, const ot_ip6 ip, uint16_t port) { | 76 | /* The only place in the tree that needs to know what a kernel calls this */ |
| 79 | struct sockaddr_in6 sa; | 77 | static void socket_set_sharing(int s, socket_sharing sharing) { |
| 80 | int one = 1; | 78 | int one = 1; |
| 81 | 79 | ||
| 82 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); | 80 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); |
| 83 | #ifdef SO_REUSEPORT | 81 | #ifdef SO_REUSEPORT |
| 84 | if (g_socket_reuseport) | 82 | if (sharing == SOCKET_SHARED) |
| 85 | setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); | 83 | setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); |
| 86 | #endif | 84 | #endif |
| 85 | } | ||
| 86 | |||
| 87 | static int socket_bind_v6(int s, const ot_ip6 ip, uint16_t port, socket_sharing sharing) { | ||
| 88 | struct sockaddr_in6 sa; | ||
| 89 | |||
| 90 | socket_set_sharing(s, sharing); | ||
| 87 | 91 | ||
| 88 | sockaddr_from_ip(&sa, ip, port); | 92 | sockaddr_from_ip(&sa, ip, port); |
| 89 | return bind(s, (struct sockaddr *)&sa, sizeof(sa)); | 93 | return bind(s, (struct sockaddr *)&sa, sizeof(sa)); |
| 90 | } | 94 | } |
| 91 | 95 | ||
| 92 | int socket_tcp_listen(const ot_ip6 ip, uint16_t port) { | 96 | int socket_tcp_listen(const ot_ip6 ip, uint16_t port, socket_sharing sharing) { |
| 93 | int s = socket_v6(SOCK_STREAM); | 97 | int s = socket_v6(SOCK_STREAM); |
| 94 | 98 | ||
| 95 | if (s == -1) | 99 | if (s == -1) |
| 96 | return -1; | 100 | return -1; |
| 97 | if (socket_bind_v6(s, ip, port) == -1 || listen(s, SOMAXCONN) == -1) | 101 | if (socket_bind_v6(s, ip, port, sharing) == -1 || listen(s, SOMAXCONN) == -1) |
| 98 | return close_and_fail(s); | 102 | return close_and_fail(s); |
| 99 | 103 | ||
| 100 | return s; | 104 | return s; |
| 101 | } | 105 | } |
| 102 | 106 | ||
| 103 | int socket_udp_bind(const ot_ip6 ip, uint16_t port) { | 107 | int socket_udp_bind(const ot_ip6 ip, uint16_t port, socket_sharing sharing) { |
| 104 | int s = socket_v6(SOCK_DGRAM); | 108 | int s = socket_v6(SOCK_DGRAM); |
| 105 | 109 | ||
| 106 | if (s == -1) | 110 | if (s == -1) |
| 107 | return -1; | 111 | return -1; |
| 108 | if (socket_bind_v6(s, ip, port) == -1) | 112 | if (socket_bind_v6(s, ip, port, sharing) == -1) |
| 109 | return close_and_fail(s); | 113 | return close_and_fail(s); |
| 110 | 114 | ||
| 111 | return s; | 115 | return s; |
| @@ -117,7 +121,7 @@ int socket_tcp_connect(const ot_ip6 srcip, uint16_t srcport, const ot_ip6 dstip, | |||
| 117 | 121 | ||
| 118 | if (s == -1) | 122 | if (s == -1) |
| 119 | return -1; | 123 | return -1; |
| 120 | if (socket_bind_v6(s, srcip, srcport) == -1) | 124 | if (socket_bind_v6(s, srcip, srcport, SOCKET_EXCLUSIVE) == -1) |
| 121 | return close_and_fail(s); | 125 | return close_and_fail(s); |
| 122 | 126 | ||
| 123 | sockaddr_from_ip(&sa, dstip, dstport); | 127 | 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 | |||
| 187 | memcpy(&sa->sin_addr, ip + sizeof(ip_v4mapped_prefix), 4); | 191 | memcpy(&sa->sin_addr, ip + sizeof(ip_v4mapped_prefix), 4); |
| 188 | } | 192 | } |
| 189 | 193 | ||
| 194 | /* A multicast group is meant to have several listeners, so these are always | ||
| 195 | shared */ | ||
| 190 | static int socket_v4_bind(const ot_ip6 ip, uint16_t port) { | 196 | static int socket_v4_bind(const ot_ip6 ip, uint16_t port) { |
| 191 | struct sockaddr_in sa; | 197 | struct sockaddr_in sa; |
| 192 | int s, one = 1; | 198 | int s; |
| 193 | 199 | ||
| 194 | if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) | 200 | if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) |
| 195 | return -1; | 201 | return -1; |
| 196 | 202 | ||
| 197 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); | 203 | socket_set_sharing(s, SOCKET_SHARED); |
| 198 | #ifdef SO_REUSEPORT | ||
| 199 | if (g_socket_reuseport) | ||
| 200 | setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); | ||
| 201 | #endif | ||
| 202 | 204 | ||
| 203 | sockaddr4_from_ip(&sa, ip, port); | 205 | sockaddr4_from_ip(&sa, ip, port); |
| 204 | if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1) | 206 | if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1) |
