std.net.StreamServer.Options: add reuse_port
This commit is contained in:
@@ -1867,6 +1867,7 @@ pub const StreamServer = struct {
|
||||
/// Copied from `Options` on `init`.
|
||||
kernel_backlog: u31,
|
||||
reuse_address: bool,
|
||||
reuse_port: bool,
|
||||
|
||||
/// `undefined` until `listen` returns successfully.
|
||||
listen_address: Address,
|
||||
@@ -1881,6 +1882,9 @@ pub const StreamServer = struct {
|
||||
|
||||
/// Enable SO.REUSEADDR on the socket.
|
||||
reuse_address: bool = false,
|
||||
|
||||
/// Enable SO.REUSEPORT on the socket.
|
||||
reuse_port: bool = false,
|
||||
};
|
||||
|
||||
/// After this call succeeds, resources have been acquired and must
|
||||
@@ -1890,6 +1894,7 @@ pub const StreamServer = struct {
|
||||
.sockfd = null,
|
||||
.kernel_backlog = options.kernel_backlog,
|
||||
.reuse_address = options.reuse_address,
|
||||
.reuse_port = options.reuse_port,
|
||||
.listen_address = undefined,
|
||||
};
|
||||
}
|
||||
@@ -1920,6 +1925,14 @@ pub const StreamServer = struct {
|
||||
&mem.toBytes(@as(c_int, 1)),
|
||||
);
|
||||
}
|
||||
if (@hasDecl(os.SO, "REUSEPORT") and self.reuse_port) {
|
||||
try os.setsockopt(
|
||||
sockfd,
|
||||
os.SOL.SOCKET,
|
||||
os.SO.REUSEPORT,
|
||||
&mem.toBytes(@as(c_int, 1)),
|
||||
);
|
||||
}
|
||||
|
||||
var socklen = address.getOsSockLen();
|
||||
try os.bind(sockfd, &address.any, socklen);
|
||||
|
||||
@@ -230,6 +230,27 @@ test "listen on ipv4 try connect on ipv6 then ipv4" {
|
||||
try await client_frame;
|
||||
}
|
||||
|
||||
test "listen on an in use port" {
|
||||
if (builtin.os.tag != .linux and comptime !builtin.os.tag.isDarwin()) {
|
||||
// TODO build abstractions for other operating systems
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
|
||||
const localhost = try net.Address.parseIp("127.0.0.1", 0);
|
||||
|
||||
var server1 = net.StreamServer.init(net.StreamServer.Options{
|
||||
.reuse_port = true,
|
||||
});
|
||||
defer server1.deinit();
|
||||
try server1.listen(localhost);
|
||||
|
||||
var server2 = net.StreamServer.init(net.StreamServer.Options{
|
||||
.reuse_port = true,
|
||||
});
|
||||
defer server2.deinit();
|
||||
try server2.listen(server1.listen_address);
|
||||
}
|
||||
|
||||
fn testClientToHost(allocator: mem.Allocator, name: []const u8, port: u16) anyerror!void {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user