commit
1b201f460f
|
@ -131,6 +131,7 @@ pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint
|
|||
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 connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
|
||||
pub extern "c" fn accept(sockfd: fd_t, addr: *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 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: ?*const c_void, optlen: socklen_t) c_int;
|
||||
|
|
|
@ -1379,7 +1379,7 @@ pub const StreamServer = struct {
|
|||
const accept_flags = nonblock | os.SOCK_CLOEXEC;
|
||||
var accepted_addr: Address = undefined;
|
||||
var adr_len: os.socklen_t = @sizeOf(Address);
|
||||
if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
|
||||
if (os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
|
||||
return Connection{
|
||||
.file = fs.File{ .handle = fd },
|
||||
.address = accepted_addr,
|
||||
|
|
|
@ -2159,9 +2159,20 @@ pub const SocketError = error{
|
|||
} || UnexpectedError;
|
||||
|
||||
pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t {
|
||||
const have_sock_flags = comptime !std.Target.current.isDarwin();
|
||||
const filtered_sock_type = if (!have_sock_flags)
|
||||
socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC)
|
||||
else
|
||||
socket_type;
|
||||
const rc = system.socket(domain, socket_type, protocol);
|
||||
switch (errno(rc)) {
|
||||
0 => return @intCast(fd_t, rc),
|
||||
0 => {
|
||||
const fd = @intCast(fd_t, rc);
|
||||
if (!have_sock_flags and filtered_sock_type != socket_type) {
|
||||
try setSockFlags(fd, socket_type);
|
||||
}
|
||||
return fd;
|
||||
},
|
||||
EACCES => return error.PermissionDenied,
|
||||
EAFNOSUPPORT => return error.AddressFamilyNotSupported,
|
||||
EINVAL => return error.ProtocolFamilyNotAvailable,
|
||||
|
@ -2284,7 +2295,7 @@ pub const AcceptError = error{
|
|||
/// Accept a connection on a socket.
|
||||
/// If the application has a global event loop enabled, EAGAIN is handled
|
||||
/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.
|
||||
pub fn accept4(
|
||||
pub fn accept(
|
||||
/// This argument is a socket that has been created with `socket`, bound to a local address
|
||||
/// with `bind`, and is listening for connections after a `listen`.
|
||||
sockfd: fd_t,
|
||||
|
@ -2300,8 +2311,7 @@ pub fn accept4(
|
|||
/// The returned address is truncated if the buffer provided is too small; in this case, `addr_size`
|
||||
/// will return a value greater than was supplied to the call.
|
||||
addr_size: *socklen_t,
|
||||
/// If flags is 0, then `accept4` is the same as `accept`. The following values can be bitwise
|
||||
/// ORed in flags to obtain different behavior:
|
||||
/// The following values can be bitwise ORed in flags to obtain different behavior:
|
||||
/// * `SOCK_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the open file description (see `open`)
|
||||
/// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve
|
||||
/// the same result.
|
||||
|
@ -2309,12 +2319,24 @@ pub fn accept4(
|
|||
/// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful.
|
||||
flags: u32,
|
||||
) AcceptError!fd_t {
|
||||
while (true) {
|
||||
const rc = system.accept4(sockfd, addr, addr_size, flags);
|
||||
switch (errno(rc)) {
|
||||
0 => return @intCast(fd_t, rc),
|
||||
EINTR => continue,
|
||||
const have_accept4 = comptime !std.Target.current.isDarwin();
|
||||
assert(0 == (flags & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC))); // Unsupported flag(s)
|
||||
|
||||
while (true) {
|
||||
const rc = if (have_accept4)
|
||||
system.accept4(sockfd, addr, addr_size, flags)
|
||||
else
|
||||
system.accept(sockfd, addr, addr_size);
|
||||
|
||||
switch (errno(rc)) {
|
||||
0 => {
|
||||
const fd = @intCast(fd_t, rc);
|
||||
if (!have_accept4 and flags != 0) {
|
||||
try setSockFlags(fd, flags);
|
||||
}
|
||||
return fd;
|
||||
},
|
||||
EINTR => continue,
|
||||
EAGAIN => if (std.event.Loop.instance) |loop| {
|
||||
loop.waitUntilFdReadable(sockfd);
|
||||
continue;
|
||||
|
@ -2333,7 +2355,6 @@ pub fn accept4(
|
|||
EOPNOTSUPP => unreachable,
|
||||
EPROTO => return error.ProtocolFailure,
|
||||
EPERM => return error.BlockedByFirewall,
|
||||
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
|
@ -3245,6 +3266,35 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize {
|
|||
}
|
||||
}
|
||||
|
||||
fn setSockFlags(fd: fd_t, flags: u32) !void {
|
||||
{
|
||||
var fd_flags = fcntl(fd, F_GETFD, 0) catch |err| switch (err) {
|
||||
error.FileBusy => unreachable,
|
||||
error.Locked => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
if ((flags & SOCK_NONBLOCK) != 0) fd_flags |= FD_CLOEXEC;
|
||||
_ = fcntl(fd, F_SETFD, fd_flags) catch |err| switch (err) {
|
||||
error.FileBusy => unreachable,
|
||||
error.Locked => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
{
|
||||
var fl_flags = fcntl(fd, F_GETFL, 0) catch |err| switch (err) {
|
||||
error.FileBusy => unreachable,
|
||||
error.Locked => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
if ((flags & SOCK_CLOEXEC) != 0) fl_flags |= O_NONBLOCK;
|
||||
_ = fcntl(fd, F_SETFL, fl_flags) catch |err| switch (err) {
|
||||
error.FileBusy => unreachable,
|
||||
error.Locked => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub const FlockError = error{
|
||||
WouldBlock,
|
||||
|
||||
|
|
|
@ -764,6 +764,15 @@ pub const SOCK_RDM = 4;
|
|||
pub const SOCK_SEQPACKET = 5;
|
||||
pub const SOCK_MAXADDRLEN = 255;
|
||||
|
||||
/// Not actually supported by Darwin, but Zig supplies a shim.
|
||||
/// This numerical value is not ABI-stable. It need only not conflict
|
||||
/// with any other "SOCK_" bits.
|
||||
pub const SOCK_CLOEXEC = 1 << 15;
|
||||
/// Not actually supported by Darwin, but Zig supplies a shim.
|
||||
/// This numerical value is not ABI-stable. It need only not conflict
|
||||
/// with any other "SOCK_" bits.
|
||||
pub const SOCK_NONBLOCK = 1 << 16;
|
||||
|
||||
pub const IPPROTO_ICMP = 1;
|
||||
pub const IPPROTO_ICMPV6 = 58;
|
||||
pub const IPPROTO_TCP = 6;
|
||||
|
|
Loading…
Reference in New Issue