| author | |
| committer | |
| log | e85c89630e78ccc0e4bab44064779a07a029cecd |
| tree | ad8818dd35b5a9a0f781a69bb2c2a3fe6a681cb9 |
| parent | bd89bd6fdbcc0ce5ea7763a8043fd46099022b19 |
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 | } |
| 722 | 722 | ||
| 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 { |
| 1661 | 1661 | ||
| 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 condition | 2894 | EBADF => unreachable, // always a race condition |
| 2900 | ECONNABORTED => return error.ConnectionAborted, | 2895 | ECONNABORTED => return error.ConnectionAborted, |
| 2901 | EFAULT => unreachable, | 2896 | EFAULT => unreachable, |