summaryrefslogtreecommitdiff
path: root/ot_socket.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-25 18:51:51 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-25 18:51:51 +0100
commit2c7659ec930277981b6333b5b3aff7840d11933c (patch)
tree1c363ce905ef1a62395f398335a94a47916af278 /ot_socket.c
parent632960a33eb8d23925b2bbef24d5065de7280aef (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.c36
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
18int g_socket_reuseport;
19
20static void sockaddr_from_ip(struct sockaddr_in6 *sa, const ot_ip6 ip, uint16_t port) { 18static 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
78static 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; 77static 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
87static 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
92int socket_tcp_listen(const ot_ip6 ip, uint16_t port) { 96int 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
103int socket_udp_bind(const ot_ip6 ip, uint16_t port) { 107int 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 */
190static int socket_v4_bind(const ot_ip6 ip, uint16_t port) { 196static 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)