| author | |
| committer | |
| log | 2b48f559f424d8bf790bf54f4bb83d631461a681 |
| tree | 63afbec73718161bf16640d9a26427fbc0454789 |
| parent | bea4ea5ff89ca1e9c517b3c4b00934931d280c57 |
6 files changed, 77 insertions(+), 62 deletions(-)
lib/std/Io.zig+19-10| ... | ... | @@ -243,8 +243,6 @@ pub const VTable = struct { |
| 243 | 243 | netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle, |
| 244 | 244 | netSocketCreatePair: *const fn (?*anyopaque, net.Socket.CreatePairOptions) net.Socket.CreatePairError![2]net.Socket, |
| 245 | 245 | netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, |
| 246 | /// Returns 0 on end of stream. | |
| 247 | netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize, | |
| 248 | 246 | netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, |
| 249 | 247 | netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize, |
| 250 | 248 | netClose: *const fn (?*anyopaque, handle: []const net.Socket.Handle) void, |
| ... | ... | @@ -261,6 +259,7 @@ pub const Operation = union(enum) { |
| 261 | 259 | /// other systems this tag is unreachable. |
| 262 | 260 | device_io_control: DeviceIoControl, |
| 263 | 261 | net_receive: NetReceive, |
| 262 | net_read: NetRead, | |
| 264 | 263 | |
| 265 | 264 | pub const Tag = @typeInfo(Operation).@"union".tag_type.?; |
| 266 | 265 | |
| ... | ... | @@ -386,6 +385,23 @@ pub const Operation = union(enum) { |
| 386 | 385 | pub const Result = struct { ?net.Socket.ReceiveError, usize }; |
| 387 | 386 | }; |
| 388 | 387 | |
| 388 | pub const NetRead = struct { | |
| 389 | socket_handle: net.Socket.Handle, | |
| 390 | data: [][]u8, | |
| 391 | ||
| 392 | pub const Error = error{ | |
| 393 | SystemResources, | |
| 394 | ConnectionResetByPeer, | |
| 395 | SocketUnconnected, | |
| 396 | /// The file descriptor does not hold the required rights to read | |
| 397 | /// from it. | |
| 398 | AccessDenied, | |
| 399 | NetworkDown, | |
| 400 | } || Io.UnexpectedError; | |
| 401 | ||
| 402 | pub const Result = Error!usize; | |
| 403 | }; | |
| 404 | ||
| 389 | 405 | pub const Result = Result: { |
| 390 | 406 | const operation_fields = @typeInfo(Operation).@"union".fields; |
| 391 | 407 | var field_names: [operation_fields.len][]const u8 = undefined; |
| ... | ... | @@ -2626,7 +2642,6 @@ pub const failing: std.Io = .{ |
| 2626 | 2642 | .netConnectUnix = failingNetConnectUnix, |
| 2627 | 2643 | .netSocketCreatePair = failingNetSocketCreatePair, |
| 2628 | 2644 | .netSend = failingNetSend, |
| 2629 | .netRead = failingNetRead, | |
| 2630 | 2645 | .netWrite = failingNetWrite, |
| 2631 | 2646 | .netWriteFile = failingNetWriteFile, |
| 2632 | 2647 | .netClose = unreachableNetClose, |
| ... | ... | @@ -2774,6 +2789,7 @@ pub fn failingOperate(userdata: ?*anyopaque, operation: Operation) Cancelable!Op |
| 2774 | 2789 | .file_write_streaming => .{ .file_write_streaming = error.InputOutput }, |
| 2775 | 2790 | .device_io_control => unreachable, |
| 2776 | 2791 | .net_receive => .{ .net_receive = .{ error.NetworkDown, 0 } }, |
| 2792 | .net_read => .{ .net_read = error.NetworkDown }, | |
| 2777 | 2793 | }; |
| 2778 | 2794 | } |
| 2779 | 2795 | |
| ... | ... | @@ -3377,13 +3393,6 @@ pub fn failingNetSend(userdata: ?*anyopaque, handle: net.Socket.Handle, messages |
| 3377 | 3393 | return .{ error.NetworkDown, 0 }; |
| 3378 | 3394 | } |
| 3379 | 3395 | |
| 3380 | pub fn failingNetRead(userdata: ?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | |
| 3381 | _ = userdata; | |
| 3382 | _ = src; | |
| 3383 | _ = data; | |
| 3384 | return error.NetworkDown; | |
| 3385 | } | |
| 3386 | ||
| 3387 | 3396 | pub fn failingNetWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize { |
| 3388 | 3397 | _ = userdata; |
| 3389 | 3398 | _ = dest; |
lib/std/Io/Dispatch.zig+3-13| ... | ... | @@ -459,7 +459,6 @@ pub fn io(ev: *Evented) Io { |
| 459 | 459 | .netConnectUnix = netConnectUnixUnavailable, |
| 460 | 460 | .netSocketCreatePair = netSocketCreatePairUnavailable, |
| 461 | 461 | .netSend = netSendUnavailable, |
| 462 | .netRead = netReadUnavailable, | |
| 463 | 462 | .netWrite = netWriteUnavailable, |
| 464 | 463 | .netWriteFile = netWriteFileUnavailable, |
| 465 | 464 | .netClose = netClose, |
| ... | ... | @@ -1713,6 +1712,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 1713 | 1712 | }, |
| 1714 | 1713 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, |
| 1715 | 1714 | .net_receive => @panic("TODO implement net_receive operation"), |
| 1715 | .net_read => @panic("TODO implement net_read operation"), | |
| 1716 | 1716 | } |
| 1717 | 1717 | } |
| 1718 | 1718 | |
| ... | ... | @@ -2134,6 +2134,7 @@ fn batchDrainSubmitted( |
| 2134 | 2134 | }, |
| 2135 | 2135 | .device_io_control => {}, |
| 2136 | 2136 | .net_receive => @panic("TODO implement batched net_receive"), |
| 2137 | .net_read => @panic("TODO implement batched net_read"), | |
| 2137 | 2138 | }; |
| 2138 | 2139 | if (concurrency) return error.ConcurrencyUnavailable; |
| 2139 | 2140 | break :result try operate(ev, storage.submission.operation); |
| ... | ... | @@ -2193,6 +2194,7 @@ fn batchSourceEvent(context: ?*anyopaque) callconv(.c) void { |
| 2193 | 2194 | }, |
| 2194 | 2195 | .device_io_control => unreachable, |
| 2195 | 2196 | .net_receive => @panic("TODO implement batched net_receive"), |
| 2197 | .net_read => @panic("TODO implement batched net_read"), | |
| 2196 | 2198 | }; |
| 2197 | 2199 | |
| 2198 | 2200 | switch (pending.node.prev) { |
| ... | ... | @@ -4877,18 +4879,6 @@ fn netSendUnavailable( |
| 4877 | 4879 | return .{ error.NetworkDown, 0 }; |
| 4878 | 4880 | } |
| 4879 | 4881 | |
| 4880 | fn netReadUnavailable( | |
| 4881 | userdata: ?*anyopaque, | |
| 4882 | fd: net.Socket.Handle, | |
| 4883 | data: [][]u8, | |
| 4884 | ) net.Stream.Reader.Error!usize { | |
| 4885 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | |
| 4886 | _ = ev; | |
| 4887 | _ = fd; | |
| 4888 | _ = data; | |
| 4889 | return error.NetworkDown; | |
| 4890 | } | |
| 4891 | ||
| 4892 | 4882 | fn netWriteUnavailable( |
| 4893 | 4883 | userdata: ?*anyopaque, |
| 4894 | 4884 | handle: net.Socket.Handle, |
lib/std/Io/Threaded.zig+33-14| ... | ... | @@ -1943,10 +1943,6 @@ pub fn io(t: *Threaded) Io { |
| 1943 | 1943 | .windows => netShutdownWindows, |
| 1944 | 1944 | else => netShutdownPosix, |
| 1945 | 1945 | }, |
| 1946 | .netRead = switch (native_os) { | |
| 1947 | .windows => netReadWindows, | |
| 1948 | else => netReadPosix, | |
| 1949 | }, | |
| 1950 | 1946 | .netWrite = switch (native_os) { |
| 1951 | 1947 | .windows => netWriteWindows, |
| 1952 | 1948 | else => netWritePosix, |
| ... | ... | @@ -2566,6 +2562,12 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2566 | 2562 | }; |
| 2567 | 2563 | break :o .{ null, 1 }; |
| 2568 | 2564 | } }, |
| 2565 | .net_read => |o| return .{ | |
| 2566 | .net_read = netRead(o.socket_handle, o.data) catch |err| switch (err) { | |
| 2567 | error.Canceled => |e| return e, | |
| 2568 | else => |e| e, | |
| 2569 | }, | |
| 2570 | }, | |
| 2569 | 2571 | } |
| 2570 | 2572 | } |
| 2571 | 2573 | |
| ... | ... | @@ -2621,6 +2623,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2621 | 2623 | }; |
| 2622 | 2624 | poll_len += 1; |
| 2623 | 2625 | }, |
| 2626 | .net_read => |o| { | |
| 2627 | poll_buffer[poll_len] = .{ | |
| 2628 | .fd = o.socket_handle, | |
| 2629 | .events = posix.POLL.IN | posix.POLL.ERR, | |
| 2630 | .revents = 0, | |
| 2631 | }; | |
| 2632 | poll_len += 1; | |
| 2633 | }, | |
| 2624 | 2634 | } |
| 2625 | 2635 | index = submission.node.next; |
| 2626 | 2636 | } |
| ... | ... | @@ -2798,6 +2808,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2798 | 2808 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| 2799 | 2809 | b.completed.tail = index; |
| 2800 | 2810 | }, |
| 2811 | .net_read => |o| try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR), | |
| 2801 | 2812 | } |
| 2802 | 2813 | index = submission.node.next; |
| 2803 | 2814 | } |
| ... | ... | @@ -2993,6 +3004,7 @@ fn batchApc( |
| 2993 | 3004 | .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) }, |
| 2994 | 3005 | .device_io_control => .{ .device_io_control = iosb.* }, |
| 2995 | 3006 | .net_receive => unreachable, |
| 3007 | .net_read => unreachable, | |
| 2996 | 3008 | }; |
| 2997 | 3009 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| 2998 | 3010 | }, |
| ... | ... | @@ -3201,6 +3213,16 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io |
| 3201 | 3213 | .net_receive = netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags), |
| 3202 | 3214 | }); |
| 3203 | 3215 | }, |
| 3216 | .net_read => |*o| { | |
| 3217 | // TODO integrate with overlapped I/O or equivalent to avoid this error | |
| 3218 | if (concurrency) return error.ConcurrencyUnavailable; | |
| 3219 | batchCompleteBlockingWindows(b, operation_userdata, .{ | |
| 3220 | .net_read = netRead(o.socket_handle, o.data) catch |err| switch (err) { | |
| 3221 | error.Canceled => |e| return e, | |
| 3222 | else => |e| e, | |
| 3223 | }, | |
| 3224 | }); | |
| 3225 | }, | |
| 3204 | 3226 | } |
| 3205 | 3227 | index = submission.node.next; |
| 3206 | 3228 | } |
| ... | ... | @@ -12549,11 +12571,14 @@ fn deferAcceptAfd(t: *Threaded, listen_handle: net.Socket.Handle, info: windows. |
| 12549 | 12571 | } |
| 12550 | 12572 | } |
| 12551 | 12573 | |
| 12552 | fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | |
| 12574 | fn netRead(socket_handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | |
| 12553 | 12575 | if (!have_networking) return error.NetworkDown; |
| 12554 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 12555 | _ = t; | |
| 12556 | 12576 | |
| 12577 | if (is_windows) return netReadWindows(socket_handle, data); | |
| 12578 | return netReadPosix(socket_handle, data); | |
| 12579 | } | |
| 12580 | ||
| 12581 | fn netReadPosix(fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | |
| 12557 | 12582 | var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; |
| 12558 | 12583 | var i: usize = 0; |
| 12559 | 12584 | for (data) |buf| { |
| ... | ... | @@ -12590,7 +12615,6 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. |
| 12590 | 12615 | .NOMEM => return error.SystemResources, |
| 12591 | 12616 | .NOTCONN => return error.SocketUnconnected, |
| 12592 | 12617 | .CONNRESET => return error.ConnectionResetByPeer, |
| 12593 | .TIMEDOUT => return error.Timeout, | |
| 12594 | 12618 | .NOTCAPABLE => return error.AccessDenied, |
| 12595 | 12619 | else => |err| return posix.unexpectedErrno(err), |
| 12596 | 12620 | } |
| ... | ... | @@ -12622,7 +12646,6 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. |
| 12622 | 12646 | .NOMEM => return error.SystemResources, |
| 12623 | 12647 | .NOTCONN => return error.SocketUnconnected, |
| 12624 | 12648 | .CONNRESET => return error.ConnectionResetByPeer, |
| 12625 | .TIMEDOUT => return error.Timeout, | |
| 12626 | 12649 | .PIPE => return error.SocketUnconnected, |
| 12627 | 12650 | .NETDOWN => return error.NetworkDown, |
| 12628 | 12651 | else => |err| return posix.unexpectedErrno(err), |
| ... | ... | @@ -12632,11 +12655,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. |
| 12632 | 12655 | } |
| 12633 | 12656 | } |
| 12634 | 12657 | |
| 12635 | fn netReadWindows(userdata: ?*anyopaque, socket_handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | |
| 12636 | if (!have_networking) return error.NetworkDown; | |
| 12637 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 12638 | _ = t; | |
| 12639 | ||
| 12658 | fn netReadWindows(socket_handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | |
| 12640 | 12659 | var iovecs: [max_iovecs_len]windows.AFD.WSABUF(.@"var") = undefined; |
| 12641 | 12660 | var len: u32 = 0; |
| 12642 | 12661 | for (data) |buf| { |
lib/std/Io/Uring.zig+11-13| ... | ... | @@ -779,7 +779,6 @@ pub fn io(ev: *Evented) Io { |
| 779 | 779 | .netConnectUnix = netConnectUnixUnavailable, |
| 780 | 780 | .netSocketCreatePair = netSocketCreatePairUnavailable, |
| 781 | 781 | .netSend = netSendUnavailable, |
| 782 | .netRead = netReadUnavailable, | |
| 783 | 782 | .netWrite = netWriteUnavailable, |
| 784 | 783 | .netWriteFile = netWriteFileUnavailable, |
| 785 | 784 | .netClose = netClose, |
| ... | ... | @@ -2105,6 +2104,12 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2105 | 2104 | }; |
| 2106 | 2105 | }, |
| 2107 | 2106 | }, |
| 2107 | .net_read => |o| .{ | |
| 2108 | .net_read = r: { | |
| 2109 | _ = o; | |
| 2110 | break :r error.NetworkDown; // TODO | |
| 2111 | }, | |
| 2112 | }, | |
| 2108 | 2113 | }; |
| 2109 | 2114 | } |
| 2110 | 2115 | |
| ... | ... | @@ -2392,6 +2397,10 @@ fn batchDrainSubmitted( |
| 2392 | 2397 | _ = o; |
| 2393 | 2398 | @panic("TODO implement batchDrainSubmitted for net_receive"); |
| 2394 | 2399 | }, |
| 2400 | .net_read => |o| { | |
| 2401 | _ = o; | |
| 2402 | @panic("TODO implement batchDrainSubmitted for net_read"); | |
| 2403 | }, | |
| 2395 | 2404 | })) |result| { |
| 2396 | 2405 | switch (batch.completed.tail) { |
| 2397 | 2406 | .none => batch.completed.head = index, |
| ... | ... | @@ -2493,6 +2502,7 @@ fn batchDrainReady(batch: *Io.Batch) Io.Timeout.Error!void { |
| 2493 | 2502 | }, |
| 2494 | 2503 | .device_io_control => unreachable, |
| 2495 | 2504 | .net_receive => @panic("TODO"), |
| 2505 | .net_read => @panic("TODO"), | |
| 2496 | 2506 | })) |result| { |
| 2497 | 2507 | switch (batch.completed.tail) { |
| 2498 | 2508 | .none => batch.completed.head = index, |
| ... | ... | @@ -5142,18 +5152,6 @@ fn netReceive( |
| 5142 | 5152 | } |
| 5143 | 5153 | } |
| 5144 | 5154 | |
| 5145 | fn netReadUnavailable( | |
| 5146 | userdata: ?*anyopaque, | |
| 5147 | fd: net.Socket.Handle, | |
| 5148 | data: [][]u8, | |
| 5149 | ) net.Stream.Reader.Error!usize { | |
| 5150 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | |
| 5151 | _ = ev; | |
| 5152 | _ = fd; | |
| 5153 | _ = data; | |
| 5154 | return error.NetworkDown; | |
| 5155 | } | |
| 5156 | ||
| 5157 | 5155 | fn netWriteUnavailable( |
| 5158 | 5156 | userdata: ?*anyopaque, |
| 5159 | 5157 | handle: net.Socket.Handle, |
lib/std/Io/net.zig+11-11| ... | ... | @@ -1245,6 +1245,15 @@ pub const Stream = struct { |
| 1245 | 1245 | |
| 1246 | 1246 | const max_iovecs_len = 8; |
| 1247 | 1247 | |
| 1248 | /// This is a low-level API that calls the `Io` interface function directly. | |
| 1249 | /// For a higher level API, see `reader`. | |
| 1250 | pub fn read(s: *const Stream, io: Io, data: [][]u8) Reader.Error!usize { | |
| 1251 | return (try io.operate(.{ .net_read = .{ | |
| 1252 | .socket_handle = s.socket.handle, | |
| 1253 | .data = data, | |
| 1254 | } })).net_read; | |
| 1255 | } | |
| 1256 | ||
| 1248 | 1257 | pub fn close(s: *const Stream, io: Io) void { |
| 1249 | 1258 | io.vtable.netClose(io.userdata, (&s.socket.handle)[0..1]); |
| 1250 | 1259 | } |
| ... | ... | @@ -1259,16 +1268,7 @@ pub const Stream = struct { |
| 1259 | 1268 | stream: Stream, |
| 1260 | 1269 | err: ?Error, |
| 1261 | 1270 | |
| 1262 | pub const Error = error{ | |
| 1263 | SystemResources, | |
| 1264 | ConnectionResetByPeer, | |
| 1265 | Timeout, | |
| 1266 | SocketUnconnected, | |
| 1267 | /// The file descriptor does not hold the required rights to read | |
| 1268 | /// from it. | |
| 1269 | AccessDenied, | |
| 1270 | NetworkDown, | |
| 1271 | } || Io.Cancelable || Io.UnexpectedError; | |
| 1271 | pub const Error = Io.Operation.NetRead.Error || Io.Cancelable; | |
| 1272 | 1272 | |
| 1273 | 1273 | pub fn init(stream: Stream, io: Io, buffer: []u8) Reader { |
| 1274 | 1274 | return .{ |
| ... | ... | @@ -1302,7 +1302,7 @@ pub const Stream = struct { |
| 1302 | 1302 | const dest_n, const data_size = try io_r.writableVector(&iovecs_buffer, data); |
| 1303 | 1303 | const dest = iovecs_buffer[0..dest_n]; |
| 1304 | 1304 | assert(dest[0].len > 0); |
| 1305 | const n = io.vtable.netRead(io.userdata, r.stream.socket.handle, dest) catch |err| { | |
| 1305 | const n = r.stream.read(io, dest) catch |err| { | |
| 1306 | 1306 | r.err = err; |
| 1307 | 1307 | return error.ReadFailed; |
| 1308 | 1308 | }; |
src/IncrementalDebugServer.zig-1| ... | ... | @@ -86,7 +86,6 @@ fn runServer(ids: *IncrementalDebugServer) void { |
| 86 | 86 | error.OutOfMemory, |
| 87 | 87 | error.Unexpected, |
| 88 | 88 | error.SystemResources, |
| 89 | error.Timeout, | |
| 90 | 89 | error.NetworkDown, |
| 91 | 90 | error.NetworkUnreachable, |
| 92 | 91 | error.HostUnreachable, |