commit
86ba8c06bf
|
@ -120,7 +120,8 @@ pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
|
||||||
pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
|
pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
|
||||||
pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
|
pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
|
||||||
pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int;
|
pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int;
|
||||||
pub extern "c" fn getsockopt(sockfd: fd_t, level: c_int, optname: c_int, optval: *c_void, optlen: *socklen_t) c_int;
|
pub extern "c" fn getsockopt(sockfd: fd_t, level: u32, optname: u32, optval: *c_void, optlen: *socklen_t) c_int;
|
||||||
|
pub extern "c" fn setsockopt(sockfd: fd_t, level: u32, optname: u32, optval: *c_void, optlen: socklen_t) c_int;
|
||||||
pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize;
|
pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize;
|
||||||
pub extern "c" fn sendto(
|
pub extern "c" fn sendto(
|
||||||
sockfd: fd_t,
|
sockfd: fd_t,
|
||||||
|
|
|
@ -1279,6 +1279,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
|
||||||
pub const StreamServer = struct {
|
pub const StreamServer = struct {
|
||||||
/// Copied from `Options` on `init`.
|
/// Copied from `Options` on `init`.
|
||||||
kernel_backlog: u32,
|
kernel_backlog: u32,
|
||||||
|
reuse_address: bool,
|
||||||
|
|
||||||
/// `undefined` until `listen` returns successfully.
|
/// `undefined` until `listen` returns successfully.
|
||||||
listen_address: Address,
|
listen_address: Address,
|
||||||
|
@ -1290,6 +1291,9 @@ pub const StreamServer = struct {
|
||||||
/// If more than this many connections pool in the kernel, clients will start
|
/// If more than this many connections pool in the kernel, clients will start
|
||||||
/// seeing "Connection refused".
|
/// seeing "Connection refused".
|
||||||
kernel_backlog: u32 = 128,
|
kernel_backlog: u32 = 128,
|
||||||
|
|
||||||
|
/// Enable SO_REUSEADDR on the socket.
|
||||||
|
reuse_address: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// After this call succeeds, resources have been acquired and must
|
/// After this call succeeds, resources have been acquired and must
|
||||||
|
@ -1298,6 +1302,7 @@ pub const StreamServer = struct {
|
||||||
return StreamServer{
|
return StreamServer{
|
||||||
.sockfd = null,
|
.sockfd = null,
|
||||||
.kernel_backlog = options.kernel_backlog,
|
.kernel_backlog = options.kernel_backlog,
|
||||||
|
.reuse_address = options.reuse_address,
|
||||||
.listen_address = undefined,
|
.listen_address = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1320,6 +1325,15 @@ pub const StreamServer = struct {
|
||||||
self.sockfd = null;
|
self.sockfd = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.reuse_address) {
|
||||||
|
try os.setsockopt(
|
||||||
|
self.sockfd.?,
|
||||||
|
os.SOL_SOCKET,
|
||||||
|
os.SO_REUSEADDR,
|
||||||
|
&mem.toBytes(@as(c_int, 1)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var socklen = address.getOsSockLen();
|
var socklen = address.getOsSockLen();
|
||||||
try os.bind(sockfd, &address.any, socklen);
|
try os.bind(sockfd, &address.any, socklen);
|
||||||
try os.listen(sockfd, self.kernel_backlog);
|
try os.listen(sockfd, self.kernel_backlog);
|
||||||
|
|
|
@ -3250,3 +3250,34 @@ pub fn sched_yield() SchedYieldError!void {
|
||||||
else => return error.SystemCannotYield,
|
else => return error.SystemCannotYield,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const SetSockOptError = error{
|
||||||
|
/// The socket is already connected, and a specified option cannot be set while the socket is connected.
|
||||||
|
AlreadyConnected,
|
||||||
|
|
||||||
|
/// The option is not supported by the protocol.
|
||||||
|
InvalidProtocolOption,
|
||||||
|
|
||||||
|
/// The send and receive timeout values are too big to fit into the timeout fields in the socket structure.
|
||||||
|
TimeoutTooBig,
|
||||||
|
|
||||||
|
/// Insufficient resources are available in the system to complete the call.
|
||||||
|
SystemResources,
|
||||||
|
} || UnexpectedError;
|
||||||
|
|
||||||
|
/// Set a socket's options.
|
||||||
|
pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void {
|
||||||
|
switch (errno(system.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)))) {
|
||||||
|
0 => {},
|
||||||
|
EBADF => unreachable, // always a race condition
|
||||||
|
ENOTSOCK => unreachable, // always a race condition
|
||||||
|
EINVAL => unreachable,
|
||||||
|
EFAULT => unreachable,
|
||||||
|
EDOM => return error.TimeoutTooBig,
|
||||||
|
EISCONN => return error.AlreadyConnected,
|
||||||
|
ENOPROTOOPT => return error.InvalidProtocolOption,
|
||||||
|
ENOMEM => return error.SystemResources,
|
||||||
|
ENOBUFS => return error.SystemResources,
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue