hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mnet/udp/+freebsd.ha | 24++++++++++++++++++++++++
Mnet/udp/+linux.ha | 24++++++++++++++++++++++++
Mnet/udp/options.ha | 12+++++++++++-
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