| ... | @@ -1871,6 +1871,7 @@ pub const StreamServer = struct { | ... | @@ -1871,6 +1871,7 @@ pub const StreamServer = struct { |
| 1871 | kernel_backlog: u31, | 1871 | kernel_backlog: u31, |
| 1872 | reuse_address: bool, | 1872 | reuse_address: bool, |
| 1873 | reuse_port: bool, | 1873 | reuse_port: bool, |
| | 1874 | force_nonblocking: bool, |
| 1874 | | 1875 | |
| 1875 | /// `undefined` until `listen` returns successfully. | 1876 | /// `undefined` until `listen` returns successfully. |
| 1876 | listen_address: Address, | 1877 | listen_address: Address, |
| ... | @@ -1888,6 +1889,9 @@ pub const StreamServer = struct { | ... | @@ -1888,6 +1889,9 @@ pub const StreamServer = struct { |
| 1888 | | 1889 | |
| 1889 | /// Enable SO.REUSEPORT on the socket. | 1890 | /// Enable SO.REUSEPORT on the socket. |
| 1890 | reuse_port: bool = false, | 1891 | reuse_port: bool = false, |
| | 1892 | |
| | 1893 | /// Force non-blocking mode. |
| | 1894 | force_nonblocking: bool = false, |
| 1891 | }; | 1895 | }; |
| 1892 | | 1896 | |
| 1893 | /// After this call succeeds, resources have been acquired and must | 1897 | /// After this call succeeds, resources have been acquired and must |
| ... | @@ -1898,6 +1902,7 @@ pub const StreamServer = struct { | ... | @@ -1898,6 +1902,7 @@ pub const StreamServer = struct { |
| 1898 | .kernel_backlog = options.kernel_backlog, | 1902 | .kernel_backlog = options.kernel_backlog, |
| 1899 | .reuse_address = options.reuse_address, | 1903 | .reuse_address = options.reuse_address, |
| 1900 | .reuse_port = options.reuse_port, | 1904 | .reuse_port = options.reuse_port, |
| | 1905 | .force_nonblocking = options.force_nonblocking, |
| 1901 | .listen_address = undefined, | 1906 | .listen_address = undefined, |
| 1902 | }; | 1907 | }; |
| 1903 | } | 1908 | } |
| ... | @@ -1911,9 +1916,11 @@ pub const StreamServer = struct { | ... | @@ -1911,9 +1916,11 @@ pub const StreamServer = struct { |
| 1911 | pub fn listen(self: *StreamServer, address: Address) !void { | 1916 | pub fn listen(self: *StreamServer, address: Address) !void { |
| 1912 | const nonblock = if (std.io.is_async) os.SOCK.NONBLOCK else 0; | 1917 | const nonblock = if (std.io.is_async) os.SOCK.NONBLOCK else 0; |
| 1913 | const sock_flags = os.SOCK.STREAM | os.SOCK.CLOEXEC | nonblock; | 1918 | const sock_flags = os.SOCK.STREAM | os.SOCK.CLOEXEC | nonblock; |
| | 1919 | var use_sock_flags: u32 = sock_flags; |
| | 1920 | if (self.force_nonblocking) use_sock_flags |= os.SOCK.NONBLOCK; |
| 1914 | const proto = if (address.any.family == os.AF.UNIX) @as(u32, 0) else os.IPPROTO.TCP; | 1921 | const proto = if (address.any.family == os.AF.UNIX) @as(u32, 0) else os.IPPROTO.TCP; |
| 1915 | | 1922 | |
| 1916 | const sockfd = try os.socket(address.any.family, sock_flags, proto); | 1923 | const sockfd = try os.socket(address.any.family, use_sock_flags, proto); |
| 1917 | self.sockfd = sockfd; | 1924 | self.sockfd = sockfd; |
| 1918 | errdefer { | 1925 | errdefer { |
| 1919 | os.closeSocket(sockfd); | 1926 | os.closeSocket(sockfd); |
| ... | @@ -1963,8 +1970,8 @@ pub const StreamServer = struct { | ... | @@ -1963,8 +1970,8 @@ pub const StreamServer = struct { |
| 1963 | /// The system-wide limit on the total number of open files has been reached. | 1970 | /// The system-wide limit on the total number of open files has been reached. |
| 1964 | SystemFdQuotaExceeded, | 1971 | SystemFdQuotaExceeded, |
| 1965 | | 1972 | |
| 1966 | /// Not enough free memory. This often means that the memory allocation is limited | 1973 | /// Not enough free memory. This often means that the memory allocation |
| 1967 | /// by the socket buffer limits, not by the system memory. | 1974 | /// is limited by the socket buffer limits, not by the system memory. |
| 1968 | SystemResources, | 1975 | SystemResources, |
| 1969 | | 1976 | |
| 1970 | /// Socket is not listening for new connections. | 1977 | /// Socket is not listening for new connections. |
| ... | @@ -1972,6 +1979,9 @@ pub const StreamServer = struct { | ... | @@ -1972,6 +1979,9 @@ pub const StreamServer = struct { |
| 1972 | | 1979 | |
| 1973 | ProtocolFailure, | 1980 | ProtocolFailure, |
| 1974 | | 1981 | |
| | 1982 | /// Socket is in non-blocking mode and there is no connection to accept. |
| | 1983 | WouldBlock, |
| | 1984 | |
| 1975 | /// Firewall rules forbid connection. | 1985 | /// Firewall rules forbid connection. |
| 1976 | BlockedByFirewall, | 1986 | BlockedByFirewall, |
| 1977 | | 1987 | |
| ... | @@ -2007,9 +2017,8 @@ pub const StreamServer = struct { | ... | @@ -2007,9 +2017,8 @@ pub const StreamServer = struct { |
| 2007 | .stream = Stream{ .handle = fd }, | 2017 | .stream = Stream{ .handle = fd }, |
| 2008 | .address = accepted_addr, | 2018 | .address = accepted_addr, |
| 2009 | }; | 2019 | }; |
| 2010 | } else |err| switch (err) { | 2020 | } else |err| { |
| 2011 | error.WouldBlock => unreachable, | 2021 | return err; |
| 2012 | else => |e| return e, | | |
| 2013 | } | 2022 | } |
| 2014 | } | 2023 | } |
| 2015 | }; | 2024 | }; |