Signed-off-by: Loris Cro <kappaloris@gmail.com>
This commit is contained in:
Loris Cro
2020-06-16 22:38:51 +02:00
parent bd89bd6fdb
commit e85c89630e
3 changed files with 45 additions and 11 deletions

View File

@@ -720,6 +720,40 @@ pub const Loop = struct {
}
}
/// ------- I/0 APIs -------
pub fn accept(
self: *Loop,
/// 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: os.fd_t,
/// This argument is a pointer to a sockaddr structure. This structure is filled in with the
/// address of the peer socket, as known to the communications layer. The exact format of the
/// address returned addr is determined by the socket's address family (see `socket` and the
/// respective protocol man pages).
addr: *os.sockaddr,
/// This argument is a value-result argument: the caller must initialize it to contain the
/// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size
/// of the peer address.
///
/// 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: *os.socklen_t,
/// The following values can be bitwise ORed in flags to obtain different behavior:
/// * `SOCK_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the
/// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful.
flags: u32,
) os.AcceptError!os.fd_t {
while (true) {
return os.accept(sockfd, addr, addr_size, flags | os.SOCK_NONBLOCK) catch |err| switch (err) {
error.WouldBlock => {
self.waitUntilFdReadable(sockfd);
continue;
},
else => return err,
};
}
}
/// Performs an async `os.open` using a separate thread.
pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t {
var req_node = Request.Node{

View File

@@ -1661,18 +1661,23 @@ pub const StreamServer = struct {
/// If this function succeeds, the returned `Connection` is a caller-managed resource.
pub fn accept(self: *StreamServer) AcceptError!Connection {
const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
const accept_flags = nonblock | os.SOCK_CLOEXEC;
var accepted_addr: Address = undefined;
var adr_len: os.socklen_t = @sizeOf(Address);
if (os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
const accept_result = blk: {
if (std.io.is_async) {
const loop = std.event.Loop.instance orelse return error.UnexpectedError;
break :blk loop.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC);
} else {
break :blk os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC);
}
};
if (accept_result) |fd| {
return Connection{
.file = fs.File{ .handle = fd },
.address = accepted_addr,
};
} else |err| switch (err) {
// We only give SOCK_NONBLOCK when I/O mode is async, in which case this error
// is handled by os.accept4.
error.WouldBlock => unreachable,
else => |e| return e,
}

View File

@@ -2890,12 +2890,7 @@ pub fn accept(
return fd;
},
EINTR => continue,
EAGAIN => if (std.event.Loop.instance) |loop| {
loop.waitUntilFdReadable(sockfd);
continue;
} else {
return error.WouldBlock;
},
EAGAIN => return error.WouldBlock,
EBADF => unreachable, // always a race condition
ECONNABORTED => return error.ConnectionAborted,
EFAULT => unreachable,