authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2020-06-16 22:38:51+02:00
committergravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2020-09-24 21:56:27+02:00
loge85c89630e78ccc0e4bab44064779a07a029cecd
treead8818dd35b5a9a0f781a69bb2c2a3fe6a681cb9
parentbd89bd6fdbcc0ce5ea7763a8043fd46099022b19

accept

Signed-off-by: Loris Cro <kappaloris@gmail.com>

3 files changed, 45 insertions(+), 11 deletions(-)

lib/std/event/loop.zig+34
...@@ -720,6 +720,40 @@ pub const Loop = struct {...@@ -720,6 +720,40 @@ pub const Loop = struct {
720 }720 }
721 }721 }
722722
723 /// ------- I/0 APIs -------
724 pub fn accept(
725 self: *Loop,
726 /// This argument is a socket that has been created with `socket`, bound to a local address
727 /// with `bind`, and is listening for connections after a `listen`.
728 sockfd: os.fd_t,
729 /// This argument is a pointer to a sockaddr structure. This structure is filled in with the
730 /// address of the peer socket, as known to the communications layer. The exact format of the
731 /// address returned addr is determined by the socket's address family (see `socket` and the
732 /// respective protocol man pages).
733 addr: *os.sockaddr,
734 /// This argument is a value-result argument: the caller must initialize it to contain the
735 /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size
736 /// of the peer address.
737 ///
738 /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size`
739 /// will return a value greater than was supplied to the call.
740 addr_size: *os.socklen_t,
741 /// The following values can be bitwise ORed in flags to obtain different behavior:
742 /// * `SOCK_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the
743 /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful.
744 flags: u32,
745 ) os.AcceptError!os.fd_t {
746 while (true) {
747 return os.accept(sockfd, addr, addr_size, flags | os.SOCK_NONBLOCK) catch |err| switch (err) {
748 error.WouldBlock => {
749 self.waitUntilFdReadable(sockfd);
750 continue;
751 },
752 else => return err,
753 };
754 }
755 }
756
723 /// Performs an async `os.open` using a separate thread.757 /// Performs an async `os.open` using a separate thread.
724 pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t {758 pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t {
725 var req_node = Request.Node{759 var req_node = Request.Node{
lib/std/net.zig+10-5
...@@ -1661,18 +1661,23 @@ pub const StreamServer = struct {...@@ -1661,18 +1661,23 @@ pub const StreamServer = struct {
16611661
1662 /// If this function succeeds, the returned `Connection` is a caller-managed resource.1662 /// If this function succeeds, the returned `Connection` is a caller-managed resource.
1663 pub fn accept(self: *StreamServer) AcceptError!Connection {1663 pub fn accept(self: *StreamServer) AcceptError!Connection {
1664 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
1665 const accept_flags = nonblock | os.SOCK_CLOEXEC;
1666 var accepted_addr: Address = undefined;1664 var accepted_addr: Address = undefined;
1667 var adr_len: os.socklen_t = @sizeOf(Address);1665 var adr_len: os.socklen_t = @sizeOf(Address);
1668 if (os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {1666 const accept_result = blk: {
1667 if (std.io.is_async) {
1668 const loop = std.event.Loop.instance orelse return error.UnexpectedError;
1669 break :blk loop.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC);
1670 } else {
1671 break :blk os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC);
1672 }
1673 };
1674
1675 if (accept_result) |fd| {
1669 return Connection{1676 return Connection{
1670 .file = fs.File{ .handle = fd },1677 .file = fs.File{ .handle = fd },
1671 .address = accepted_addr,1678 .address = accepted_addr,
1672 };1679 };
1673 } else |err| switch (err) {1680 } else |err| switch (err) {
1674 // We only give SOCK_NONBLOCK when I/O mode is async, in which case this error
1675 // is handled by os.accept4.
1676 error.WouldBlock => unreachable,1681 error.WouldBlock => unreachable,
1677 else => |e| return e,1682 else => |e| return e,
1678 }1683 }
lib/std/os.zig+1-6
...@@ -2890,12 +2890,7 @@ pub fn accept(...@@ -2890,12 +2890,7 @@ pub fn accept(
2890 return fd;2890 return fd;
2891 },2891 },
2892 EINTR => continue,2892 EINTR => continue,
2893 EAGAIN => if (std.event.Loop.instance) |loop| {2893 EAGAIN => return error.WouldBlock,
2894 loop.waitUntilFdReadable(sockfd);
2895 continue;
2896 } else {
2897 return error.WouldBlock;
2898 },
2899 EBADF => unreachable, // always a race condition2894 EBADF => unreachable, // always a race condition
2900 ECONNABORTED => return error.ConnectionAborted,2895 ECONNABORTED => return error.ConnectionAborted,
2901 EFAULT => unreachable,2896 EFAULT => unreachable,