Skip to content

Commit 86ba8c0

Browse files
committed
Merge branch 'lun-4-net-reuseaddr-opt'
Closes #3820
2 parents 73e535e + 99f6f8e commit 86ba8c0

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

lib/std/c.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
120120
pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
121121
pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
122122
pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int;
123-
pub extern "c" fn getsockopt(sockfd: fd_t, level: c_int, optname: c_int, optval: *c_void, optlen: *socklen_t) c_int;
123+
pub extern "c" fn getsockopt(sockfd: fd_t, level: u32, optname: u32, optval: *c_void, optlen: *socklen_t) c_int;
124+
pub extern "c" fn setsockopt(sockfd: fd_t, level: u32, optname: u32, optval: *c_void, optlen: socklen_t) c_int;
124125
pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize;
125126
pub extern "c" fn sendto(
126127
sockfd: fd_t,

lib/std/net.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
12791279
pub const StreamServer = struct {
12801280
/// Copied from `Options` on `init`.
12811281
kernel_backlog: u32,
1282+
reuse_address: bool,
12821283

12831284
/// `undefined` until `listen` returns successfully.
12841285
listen_address: Address,
@@ -1290,6 +1291,9 @@ pub const StreamServer = struct {
12901291
/// If more than this many connections pool in the kernel, clients will start
12911292
/// seeing "Connection refused".
12921293
kernel_backlog: u32 = 128,
1294+
1295+
/// Enable SO_REUSEADDR on the socket.
1296+
reuse_address: bool = false,
12931297
};
12941298

12951299
/// After this call succeeds, resources have been acquired and must
@@ -1298,6 +1302,7 @@ pub const StreamServer = struct {
12981302
return StreamServer{
12991303
.sockfd = null,
13001304
.kernel_backlog = options.kernel_backlog,
1305+
.reuse_address = options.reuse_address,
13011306
.listen_address = undefined,
13021307
};
13031308
}
@@ -1320,6 +1325,15 @@ pub const StreamServer = struct {
13201325
self.sockfd = null;
13211326
}
13221327

1328+
if (self.reuse_address) {
1329+
try os.setsockopt(
1330+
self.sockfd.?,
1331+
os.SOL_SOCKET,
1332+
os.SO_REUSEADDR,
1333+
&mem.toBytes(@as(c_int, 1)),
1334+
);
1335+
}
1336+
13231337
var socklen = address.getOsSockLen();
13241338
try os.bind(sockfd, &address.any, socklen);
13251339
try os.listen(sockfd, self.kernel_backlog);

lib/std/os.zig

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3250,3 +3250,34 @@ pub fn sched_yield() SchedYieldError!void {
32503250
else => return error.SystemCannotYield,
32513251
}
32523252
}
3253+
3254+
pub const SetSockOptError = error{
3255+
/// The socket is already connected, and a specified option cannot be set while the socket is connected.
3256+
AlreadyConnected,
3257+
3258+
/// The option is not supported by the protocol.
3259+
InvalidProtocolOption,
3260+
3261+
/// The send and receive timeout values are too big to fit into the timeout fields in the socket structure.
3262+
TimeoutTooBig,
3263+
3264+
/// Insufficient resources are available in the system to complete the call.
3265+
SystemResources,
3266+
} || UnexpectedError;
3267+
3268+
/// Set a socket's options.
3269+
pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void {
3270+
switch (errno(system.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)))) {
3271+
0 => {},
3272+
EBADF => unreachable, // always a race condition
3273+
ENOTSOCK => unreachable, // always a race condition
3274+
EINVAL => unreachable,
3275+
EFAULT => unreachable,
3276+
EDOM => return error.TimeoutTooBig,
3277+
EISCONN => return error.AlreadyConnected,
3278+
ENOPROTOOPT => return error.InvalidProtocolOption,
3279+
ENOMEM => return error.SystemResources,
3280+
ENOBUFS => return error.SystemResources,
3281+
else => |err| return unexpectedErrno(err),
3282+
}
3283+
}

0 commit comments

Comments
 (0)