diff options
| author | Loris Cro <kappaloris@gmail.com> | 2020-06-16 22:38:51 +0200 |
|---|---|---|
| committer | Loris Cro <kappaloris@gmail.com> | 2020-09-24 21:56:27 +0200 |
| commit | e85c89630e78ccc0e4bab44064779a07a029cecd (patch) | |
| tree | ad8818dd35b5a9a0f781a69bb2c2a3fe6a681cb9 /lib | |
| parent | bd89bd6fdbcc0ce5ea7763a8043fd46099022b19 (diff) | |
| download | zig-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.zig | 34 | ||||
| -rw-r--r-- | lib/std/net.zig | 15 | ||||
| -rw-r--r-- | lib/std/os.zig | 7 |
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, |
