aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLoris Cro <kappaloris@gmail.com>2020-06-16 22:38:51 +0200
committerLoris Cro <kappaloris@gmail.com>2020-09-24 21:56:27 +0200
commite85c89630e78ccc0e4bab44064779a07a029cecd (patch)
treead8818dd35b5a9a0f781a69bb2c2a3fe6a681cb9 /lib
parentbd89bd6fdbcc0ce5ea7763a8043fd46099022b19 (diff)
downloadzig-e85c89630e78ccc0e4bab44064779a07a029cecd.tar.gz
zig-e85c89630e78ccc0e4bab44064779a07a029cecd.zip
accept
Signed-off-by: Loris Cro <kappaloris@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/std/event/loop.zig34
-rw-r--r--lib/std/net.zig15
-rw-r--r--lib/std/os.zig7
3 files changed, 45 insertions, 11 deletions
diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig
index c547f50365..f44b2f06e4 100644
--- a/lib/std/event/loop.zig
+++ b/lib/std/event/loop.zig
@@ -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{
diff --git a/lib/std/net.zig b/lib/std/net.zig
index 45d8f07f04..6b6d234843 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -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,
}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 0b09b1f82a..c5c34d4f40 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -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,