| author | |
| committer | |
| log | 71f6780c98c0f84668385a901bb591d19aa3944d |
| tree | 713f57dd6759464f9235e8b1c6ff5e3aba6b54cd |
| parent | f46b6501a2626dae6b6419e904972ab702fab27e |
6 files changed, 78 insertions(+), 72 deletions(-)
lib/std/Io.zig+31-2| ... | ... | @@ -229,7 +229,6 @@ pub const VTable = struct { |
| 229 | 229 | randomSecure: *const fn (?*anyopaque, buffer: []u8) RandomSecureError!void, |
| 230 | 230 | |
| 231 | 231 | netListenIp: *const fn (?*anyopaque, address: *const net.IpAddress, net.IpAddress.ListenOptions) net.IpAddress.ListenError!net.Socket, |
| 232 | netAccept: *const fn (?*anyopaque, server: net.Socket.Handle, options: net.Server.AcceptOptions) net.Server.AcceptError!net.Socket, | |
| 233 | 232 | netBindIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.BindOptions) net.IpAddress.BindError!net.Socket, |
| 234 | 233 | netConnectIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Socket, |
| 235 | 234 | netListenUnix: *const fn (?*anyopaque, *const net.UnixAddress, net.UnixAddress.ListenOptions) net.UnixAddress.ListenError!net.Socket.Handle, |
| ... | ... | @@ -251,6 +250,7 @@ pub const Operation = union(enum) { |
| 251 | 250 | device_io_control: DeviceIoControl, |
| 252 | 251 | net_receive: NetReceive, |
| 253 | 252 | net_send: NetSend, |
| 253 | net_accept: NetAccept, | |
| 254 | 254 | net_read: NetRead, |
| 255 | 255 | net_write: NetWrite, |
| 256 | 256 | |
| ... | ... | @@ -342,6 +342,35 @@ pub const Operation = union(enum) { |
| 342 | 342 | }, |
| 343 | 343 | }; |
| 344 | 344 | |
| 345 | pub const NetAccept = struct { | |
| 346 | socket_handle: net.Socket.Handle, | |
| 347 | options: net.Server.AcceptOptions, | |
| 348 | ||
| 349 | pub const Error = error{ | |
| 350 | /// The per-process limit on the number of open file descriptors has been reached. | |
| 351 | ProcessFdQuotaExceeded, | |
| 352 | /// The system-wide limit on the total number of open files has been reached. | |
| 353 | SystemFdQuotaExceeded, | |
| 354 | /// Not enough free memory. This often means that the memory allocation is limited | |
| 355 | /// by the socket buffer limits, not by the system memory. | |
| 356 | SystemResources, | |
| 357 | /// Either `listen` was never called, or `shutdown` was called (possibly while | |
| 358 | /// this call was blocking). This allows `shutdown` to be used as a concurrent | |
| 359 | /// cancellation mechanism. | |
| 360 | SocketNotListening, | |
| 361 | /// The network subsystem has failed. | |
| 362 | NetworkDown, | |
| 363 | /// An incoming connection was indicated, but was subsequently terminated by the | |
| 364 | /// remote peer prior to accepting the call. | |
| 365 | ConnectionAborted, | |
| 366 | /// Firewall rules forbid connection. | |
| 367 | BlockedByFirewall, | |
| 368 | ProtocolFailure, | |
| 369 | } || Io.UnexpectedError; | |
| 370 | ||
| 371 | pub const Result = Error!net.Socket; | |
| 372 | }; | |
| 373 | ||
| 345 | 374 | pub const NetReceive = struct { |
| 346 | 375 | socket_handle: net.Socket.Handle, |
| 347 | 376 | message_buffer: []net.IncomingMessage, |
| ... | ... | @@ -2819,7 +2848,6 @@ pub const failing: std.Io = .{ |
| 2819 | 2848 | .sleep = noSleep, |
| 2820 | 2849 | |
| 2821 | 2850 | .netListenIp = failingNetListenIp, |
| 2822 | .netAccept = failingNetAccept, | |
| 2823 | 2851 | .netBindIp = failingNetBindIp, |
| 2824 | 2852 | .netConnectIp = failingNetConnectIp, |
| 2825 | 2853 | .netListenUnix = failingNetListenUnix, |
| ... | ... | @@ -2972,6 +3000,7 @@ pub fn failingOperate(userdata: ?*anyopaque, operation: Operation) Cancelable!Op |
| 2972 | 3000 | .device_io_control => unreachable, |
| 2973 | 3001 | .net_receive => .{ .net_receive = .{ error.NetworkDown, 0 } }, |
| 2974 | 3002 | .net_send => .{ .net_send = .{ error.NetworkDown, 0 } }, |
| 3003 | .net_accept => .{ .net_accept = error.NetworkDown }, | |
| 2975 | 3004 | .net_read => .{ .net_read = error.NetworkDown }, |
| 2976 | 3005 | .net_write => .{ .net_write = error.NetworkDown }, |
| 2977 | 3006 | }; |
lib/std/Io/Dispatch.zig+1-13| ... | ... | @@ -452,7 +452,6 @@ pub fn io(ev: *Evented) Io { |
| 452 | 452 | .randomSecure = randomSecure, |
| 453 | 453 | |
| 454 | 454 | .netListenIp = netListenIpUnavailable, |
| 455 | .netAccept = netAcceptUnavailable, | |
| 456 | 455 | .netBindIp = netBindIpUnavailable, |
| 457 | 456 | .netConnectIp = netConnectIpUnavailable, |
| 458 | 457 | .netListenUnix = netListenUnixUnavailable, |
| ... | ... | @@ -1712,6 +1711,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 1712 | 1711 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, |
| 1713 | 1712 | .net_receive => @panic("TODO implement net_receive operation"), |
| 1714 | 1713 | .net_send => @panic("TODO implement net_send operation"), |
| 1714 | .net_accept => @panic("TODO implement net_accept operation"), | |
| 1715 | 1715 | .net_read => @panic("TODO implement net_read operation"), |
| 1716 | 1716 | .net_write => @panic("TODO implement net_write operation"), |
| 1717 | 1717 | } |
| ... | ... | @@ -4803,18 +4803,6 @@ fn netListenIpUnavailable( |
| 4803 | 4803 | return error.NetworkDown; |
| 4804 | 4804 | } |
| 4805 | 4805 | |
| 4806 | fn netAcceptUnavailable( | |
| 4807 | userdata: ?*anyopaque, | |
| 4808 | listen_handle: net.Socket.Handle, | |
| 4809 | options: net.Server.AcceptOptions, | |
| 4810 | ) net.Server.AcceptError!net.Socket { | |
| 4811 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | |
| 4812 | _ = ev; | |
| 4813 | _ = listen_handle; | |
| 4814 | _ = options; | |
| 4815 | return error.NetworkDown; | |
| 4816 | } | |
| 4817 | ||
| 4818 | 4806 | fn netBindIpUnavailable( |
| 4819 | 4807 | userdata: ?*anyopaque, |
| 4820 | 4808 | address: *const net.IpAddress, |
lib/std/Io/Kqueue.zig-8| ... | ... | @@ -646,7 +646,6 @@ pub fn io(k: *Kqueue) Io { |
| 646 | 646 | |
| 647 | 647 | .netListenIp = netListenIp, |
| 648 | 648 | .netListenUnix = netListenUnix, |
| 649 | .netAccept = netAccept, | |
| 650 | 649 | .netBindIp = netBindIp, |
| 651 | 650 | .netConnectIp = netConnectIp, |
| 652 | 651 | .netConnectUnix = netConnectUnix, |
| ... | ... | @@ -1008,13 +1007,6 @@ fn netListenIp( |
| 1008 | 1007 | _ = options; |
| 1009 | 1008 | @panic("TODO"); |
| 1010 | 1009 | } |
| 1011 | fn netAccept(userdata: ?*anyopaque, server: net.Socket.Handle, options: net.Server.AcceptOptions) net.Server.AcceptError!net.Socket { | |
| 1012 | const k: *Kqueue = @ptrCast(@alignCast(userdata)); | |
| 1013 | _ = k; | |
| 1014 | _ = server; | |
| 1015 | _ = options; | |
| 1016 | @panic("TODO"); | |
| 1017 | } | |
| 1018 | 1010 | fn netBindIp( |
| 1019 | 1011 | userdata: ?*anyopaque, |
| 1020 | 1012 | address: *const net.IpAddress, |
lib/std/Io/Threaded.zig+35-11| ... | ... | @@ -1969,10 +1969,6 @@ pub fn io(t: *Threaded) Io { |
| 1969 | 1969 | .windows => netListenUnixWindows, |
| 1970 | 1970 | else => netListenUnixPosix, |
| 1971 | 1971 | }, |
| 1972 | .netAccept = switch (native_os) { | |
| 1973 | .windows => netAcceptWindows, | |
| 1974 | else => netAcceptPosix, | |
| 1975 | }, | |
| 1976 | 1972 | .netBindIp = switch (native_os) { |
| 1977 | 1973 | .windows => netBindIpWindows, |
| 1978 | 1974 | else => netBindIpPosix, |
| ... | ... | @@ -2625,6 +2621,12 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2625 | 2621 | break :o .{ null, sent }; |
| 2626 | 2622 | }, |
| 2627 | 2623 | }, |
| 2624 | .net_accept => |o| return .{ | |
| 2625 | .net_accept = netAccept(t, o.socket_handle, o.options) catch |err| switch (err) { | |
| 2626 | error.Canceled => |e| return e, | |
| 2627 | else => |e| e, | |
| 2628 | }, | |
| 2629 | }, | |
| 2628 | 2630 | .net_read => |o| return .{ |
| 2629 | 2631 | .net_read = netRead(o.socket_handle, o.data, o.control) catch |err| switch (err) { |
| 2630 | 2632 | error.Canceled => |e| return e, |
| ... | ... | @@ -2698,6 +2700,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2698 | 2700 | }; |
| 2699 | 2701 | poll_len += 1; |
| 2700 | 2702 | }, |
| 2703 | .net_accept => |o| { | |
| 2704 | poll_buffer[poll_len] = .{ | |
| 2705 | .fd = o.socket_handle, | |
| 2706 | .events = posix.POLL.IN | posix.POLL.ERR, | |
| 2707 | .revents = 0, | |
| 2708 | }; | |
| 2709 | poll_len += 1; | |
| 2710 | }, | |
| 2701 | 2711 | .net_read => |o| { |
| 2702 | 2712 | poll_buffer[poll_len] = .{ |
| 2703 | 2713 | .fd = o.socket_handle, |
| ... | ... | @@ -2917,6 +2927,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2917 | 2927 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| 2918 | 2928 | b.completed.tail = index; |
| 2919 | 2929 | }, |
| 2930 | .net_accept => |o| try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR), | |
| 2920 | 2931 | .net_read => |o| try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR), |
| 2921 | 2932 | .net_write => |o| try poll_storage.add(o.socket_handle, posix.POLL.OUT | posix.POLL.ERR), |
| 2922 | 2933 | } |
| ... | ... | @@ -3115,6 +3126,7 @@ fn batchApc( |
| 3115 | 3126 | .device_io_control => .{ .device_io_control = iosb.* }, |
| 3116 | 3127 | .net_receive => unreachable, |
| 3117 | 3128 | .net_send => unreachable, |
| 3129 | .net_accept => unreachable, | |
| 3118 | 3130 | .net_read => unreachable, |
| 3119 | 3131 | .net_write => unreachable, |
| 3120 | 3132 | }; |
| ... | ... | @@ -3332,6 +3344,16 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io |
| 3332 | 3344 | .net_send = netSendWindows(t, o.socket_handle, o.messages, o.flags), |
| 3333 | 3345 | }); |
| 3334 | 3346 | }, |
| 3347 | .net_accept => |o| { | |
| 3348 | // TODO integrate with overlapped I/O or equivalent to avoid this error | |
| 3349 | if (concurrency) return error.ConcurrencyUnavailable; | |
| 3350 | batchCompleteBlockingWindows(b, operation_userdata, .{ | |
| 3351 | .net_accept = netAccept(t, o.socket_handle, o.options) catch |err| switch (err) { | |
| 3352 | error.Canceled => |e| return e, | |
| 3353 | else => |e| e, | |
| 3354 | }, | |
| 3355 | }); | |
| 3356 | }, | |
| 3335 | 3357 | .net_read => |*o| { |
| 3336 | 3358 | // TODO integrate with overlapped I/O or equivalent to avoid this error |
| 3337 | 3359 | if (concurrency) return error.ConcurrencyUnavailable; |
| ... | ... | @@ -12813,11 +12835,15 @@ fn bindSocketUnixAfd(socket_handle: net.Socket.Handle, address: *const net.UnixA |
| 12813 | 12835 | } |
| 12814 | 12836 | } |
| 12815 | 12837 | |
| 12816 | fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle, options: net.Server.AcceptOptions) net.Server.AcceptError!net.Socket { | |
| 12838 | fn netAccept(t: *Threaded, listen_fd: net.Socket.Handle, options: net.Server.AcceptOptions) net.Server.AcceptError!net.Socket { | |
| 12817 | 12839 | if (!have_networking) return error.NetworkDown; |
| 12818 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 12819 | _ = t; | |
| 12820 | options; | |
| 12840 | return if (is_windows) | |
| 12841 | netAcceptWindows(t, listen_fd, options) | |
| 12842 | else | |
| 12843 | netAcceptPosix(listen_fd); | |
| 12844 | } | |
| 12845 | ||
| 12846 | fn netAcceptPosix(listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Socket { | |
| 12821 | 12847 | var storage: PosixAddress = undefined; |
| 12822 | 12848 | var addr_len: posix.socklen_t = @sizeOf(PosixAddress); |
| 12823 | 12849 | const syscall: Syscall = try .start(); |
| ... | ... | @@ -12862,9 +12888,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle, options: |
| 12862 | 12888 | return .{ .handle = fd, .address = addressFromPosix(&storage) }; |
| 12863 | 12889 | } |
| 12864 | 12890 | |
| 12865 | fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle, options: net.Server.AcceptOptions) net.Server.AcceptError!net.Socket { | |
| 12866 | if (!have_networking) return error.NetworkDown; | |
| 12867 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 12891 | fn netAcceptWindows(t: *Threaded, listen_handle: net.Socket.Handle, options: net.Server.AcceptOptions) net.Server.AcceptError!net.Socket { | |
| 12868 | 12892 | const Storage = extern struct { |
| 12869 | 12893 | Info: windows.AFD.LISTEN_RESPONSE_INFO, |
| 12870 | 12894 | RemoteAddress: extern union { posix: PosixAddress, unix: UnixAddress }, |
lib/std/Io/Uring.zig+6-13| ... | ... | @@ -772,7 +772,6 @@ pub fn io(ev: *Evented) Io { |
| 772 | 772 | .randomSecure = randomSecure, |
| 773 | 773 | |
| 774 | 774 | .netListenIp = netListenIpUnavailable, |
| 775 | .netAccept = netAcceptUnavailable, | |
| 776 | 775 | .netBindIp = netBindIp, |
| 777 | 776 | .netConnectIp = netConnectIpUnavailable, |
| 778 | 777 | .netListenUnix = netListenUnixUnavailable, |
| ... | ... | @@ -2111,6 +2110,12 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2111 | 2110 | break :r .{ error.NetworkDown, 0 }; // TODO |
| 2112 | 2111 | }, |
| 2113 | 2112 | }, |
| 2113 | .net_accept => |o| .{ | |
| 2114 | .net_accept = r: { | |
| 2115 | _ = o; | |
| 2116 | break :r error.NetworkDown; // TODO | |
| 2117 | }, | |
| 2118 | }, | |
| 2114 | 2119 | .net_read => |o| .{ |
| 2115 | 2120 | .net_read = r: { |
| 2116 | 2121 | _ = o; |
| ... | ... | @@ -4995,18 +5000,6 @@ fn netListenIpUnavailable( |
| 4995 | 5000 | return error.NetworkDown; |
| 4996 | 5001 | } |
| 4997 | 5002 | |
| 4998 | fn netAcceptUnavailable( | |
| 4999 | userdata: ?*anyopaque, | |
| 5000 | listen_handle: net.Socket.Handle, | |
| 5001 | options: net.Server.AcceptOptions, | |
| 5002 | ) net.Server.AcceptError!net.Socket { | |
| 5003 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | |
| 5004 | _ = ev; | |
| 5005 | _ = listen_handle; | |
| 5006 | _ = options; | |
| 5007 | return error.NetworkDown; | |
| 5008 | } | |
| 5009 | ||
| 5010 | 5003 | fn netBindIp( |
| 5011 | 5004 | userdata: ?*anyopaque, |
| 5012 | 5005 | address: *const net.IpAddress, |
lib/std/Io/net.zig+5-25| ... | ... | @@ -1556,30 +1556,7 @@ pub const Server = struct { |
| 1556 | 1556 | s.* = undefined; |
| 1557 | 1557 | } |
| 1558 | 1558 | |
| 1559 | pub const AcceptError = error{ | |
| 1560 | /// The per-process limit on the number of open file descriptors has been reached. | |
| 1561 | ProcessFdQuotaExceeded, | |
| 1562 | /// The system-wide limit on the total number of open files has been reached. | |
| 1563 | SystemFdQuotaExceeded, | |
| 1564 | /// Not enough free memory. This often means that the memory allocation is limited | |
| 1565 | /// by the socket buffer limits, not by the system memory. | |
| 1566 | SystemResources, | |
| 1567 | /// Either `listen` was never called, or `shutdown` was called (possibly while | |
| 1568 | /// this call was blocking). This allows `shutdown` to be used as a concurrent | |
| 1569 | /// cancellation mechanism. | |
| 1570 | SocketNotListening, | |
| 1571 | /// The network subsystem has failed. | |
| 1572 | NetworkDown, | |
| 1573 | /// No connection is already queued and ready to be accepted, and | |
| 1574 | /// the socket is configured as non-blocking. | |
| 1575 | WouldBlock, | |
| 1576 | /// An incoming connection was indicated, but was subsequently terminated by the | |
| 1577 | /// remote peer prior to accepting the call. | |
| 1578 | ConnectionAborted, | |
| 1579 | /// Firewall rules forbid connection. | |
| 1580 | BlockedByFirewall, | |
| 1581 | ProtocolFailure, | |
| 1582 | } || Io.UnexpectedError || Io.Cancelable; | |
| 1559 | pub const AcceptError = Io.Operation.NetAccept.Error || Io.Cancelable; | |
| 1583 | 1560 | |
| 1584 | 1561 | pub const AcceptOptions = switch (native_os) { |
| 1585 | 1562 | .windows => struct { mode: Socket.Mode, protocol: ?Protocol }, |
| ... | ... | @@ -1588,7 +1565,10 @@ pub const Server = struct { |
| 1588 | 1565 | |
| 1589 | 1566 | /// Blocks until a client connects to the server. |
| 1590 | 1567 | pub fn accept(s: *Server, io: Io) AcceptError!Stream { |
| 1591 | return .{ .socket = try io.vtable.netAccept(io.userdata, s.socket.handle, s.options) }; | |
| 1568 | return .{ .socket = try (try io.operate(.{ .net_accept = .{ | |
| 1569 | .socket_handle = s.socket.handle, | |
| 1570 | .options = s.options, | |
| 1571 | } })).net_accept }; | |
| 1592 | 1572 | } |
| 1593 | 1573 | }; |
| 1594 | 1574 |