commit 7adc22ebe02c3afa146ae1792a41fe17d797ec1e
parent 95115695179fe1ad1f0c3d09c8cf400d77970d2d
Author: illiliti <illiliti@dimension.sh>
Date: Sun, 12 Mar 2023 10:55:46 +0300
net::udp: add reuseaddr/reuseport support
Signed-off-by: illiliti <illiliti@dimension.sh>
Diffstat:
3 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/net/udp/+freebsd.ha b/net/udp/+freebsd.ha
@@ -71,6 +71,16 @@ export fn listen(
yield fd;
};
+ for (let i = 0z; i < len(options); i += 1) {
+ match (options[i]) {
+ case reuseaddr =>
+ setsockopt(sockfd, rt::SO_REUSEADDR, true)?;
+ case reuseport =>
+ setsockopt(sockfd, rt::SO_REUSEPORT, true)?;
+ case => void;
+ };
+ };
+
const sockaddr = ip::to_native(addr, port);
const sz = ip::native_addrlen(addr);
match (rt::bind(sockfd, &sockaddr, sz)) {
@@ -172,3 +182,17 @@ export fn recvfrom(
return sz;
};
+
+fn setsockopt(
+ sockfd: int,
+ option: int,
+ value: bool,
+) (void | net::error) = {
+ let val: int = if (value) 1 else 0;
+ match (rt::setsockopt(sockfd, rt::SOL_SOCKET, option,
+ &val: *void, size(int): u32)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case int => void;
+ };
+};
diff --git a/net/udp/+linux.ha b/net/udp/+linux.ha
@@ -71,6 +71,16 @@ export fn listen(
yield fd;
};
+ for (let i = 0z; i < len(options); i += 1) {
+ match (options[i]) {
+ case reuseaddr =>
+ setsockopt(sockfd, rt::SO_REUSEADDR, true)?;
+ case reuseport =>
+ setsockopt(sockfd, rt::SO_REUSEPORT, true)?;
+ case => void;
+ };
+ };
+
const sockaddr = ip::to_native(addr, port);
const sz = size(rt::sockaddr): u32;
match (rt::bind(sockfd, &sockaddr, sz)) {
@@ -172,3 +182,17 @@ export fn recvfrom(
return sz;
};
+
+fn setsockopt(
+ sockfd: int,
+ option: int,
+ value: bool,
+) (void | net::error) = {
+ let val: int = if (value) 1 else 0;
+ match (rt::setsockopt(sockfd, rt::SOL_SOCKET, option,
+ &val: *void, size(int): u32)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case int => void;
+ };
+};
diff --git a/net/udp/options.ha b/net/udp/options.ha
@@ -2,6 +2,12 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
use net;
+// Enables port re-use for a UDP listener.
+export type reuseport = void;
+
+// Enables address re-use for a UDP listener.
+export type reuseaddr = void;
+
// To have the system select an arbitrary unused port for [[listen]], set port to
// zero. To retrieve the assigned port, provide this as one of the options and
// the addressed u16 will be filled in with the port.
@@ -11,6 +17,10 @@ export type portassignment = *u16;
export type connect_option = net::sockflags;
// Options available for [[listen]].
-export type listen_option = (portassignment | net::sockflags);
+export type listen_option = (
+ reuseport |
+ reuseaddr |
+ portassignment |
+ net::sockflags);
// TODO: Add send/recv flags