authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-08 16:12:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-08 19:20:06-07:00
log85ed81bb94ca59da49a128cb6ee5065b130ba06c
treed7bcce74b2c5b85424efe79f6e3b22c3ed3e101c
parentdd8de03720588eaaa165da70295e29dd23fe1886

std.Io.Threaded: implement netReceive for Windows


2 files changed, 78 insertions(+), 12 deletions(-)

lib/std/Io/Threaded.zig+70-5
......@@ -13072,11 +13072,76 @@ fn netSendWindows(
1307213072) struct { ?net.Socket.SendError, usize } {
1307313073 if (!have_networking) return .{ error.NetworkDown, 0 };
1307413074 const t: *Threaded = @ptrCast(@alignCast(userdata));
13075 _ = t;
13076 _ = handle;
13077 _ = messages;
13078 _ = flags;
13079 @panic("TODO netSendWindows");
13075
13076 // Ignored flags: confirm, eor, fastopen
13077 const windows_flags: u32 =
13078 @as(u32, if (flags.oob) ws2_32.MSG.OOB else 0) |
13079 @as(u32, if (flags.dont_route) ws2_32.MSG.DONTROUTE else 0);
13080
13081 for (messages, 0..) |*m, i| {
13082 netSendWindowsOne(t, handle, m, windows_flags) catch |err| return .{ err, i };
13083 }
13084 return .{ null, messages.len };
13085}
13086
13087fn netSendWindowsOne(
13088 t: *Threaded,
13089 handle: net.Socket.Handle,
13090 message: *net.OutgoingMessage,
13091 flags: u32,
13092) net.Socket.SendError!void {
13093 var buf: ws2_32.WSABUF = .{
13094 .buf = @constCast(message.data_ptr),
13095 .len = std.math.cast(u32, message.data_len) orelse return error.MessageOversize,
13096 };
13097 var n: u32 = undefined;
13098 var address: WsaAddress = undefined;
13099 const address_size = addressToWsa(message.address, &address);
13100 var syscall: Syscall = try .start();
13101 while (true) {
13102 const rc = ws2_32.WSASendTo(
13103 handle,
13104 (&buf)[0..1],
13105 1,
13106 &n,
13107 flags,
13108 &address.any,
13109 address_size,
13110 null,
13111 null,
13112 );
13113 if (rc != ws2_32.SOCKET_ERROR) {
13114 syscall.finish();
13115 return;
13116 }
13117 switch (ws2_32.WSAGetLastError()) {
13118 .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => {
13119 try syscall.checkCancel();
13120 continue;
13121 },
13122 .NOTINITIALISED => {
13123 syscall.finish();
13124 try initializeWsa(t);
13125 syscall = try .start();
13126 continue;
13127 },
13128
13129 .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer),
13130 .ENETDOWN => return syscall.fail(error.NetworkDown),
13131 .ENETRESET => return syscall.fail(error.ConnectionResetByPeer),
13132 .ENOTCONN => return syscall.fail(error.SocketUnconnected),
13133 .EFAULT => unreachable, // a pointer is not completely contained in user address space.
13134
13135 else => |err| {
13136 syscall.finish();
13137 switch (err) {
13138 .EINVAL => return wsaErrorBug(err),
13139 .EMSGSIZE => return wsaErrorBug(err),
13140 else => return windows.unexpectedWSAError(err),
13141 }
13142 },
13143 }
13144 }
1308013145}
1308113146
1308213147fn netSendUnavailable(
lib/std/Io/net.zig+8-7
......@@ -1117,12 +1117,13 @@ pub const Socket = struct {
11171117 /// * `receiveTimeout`
11181118 pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage {
11191119 var message: IncomingMessage = .init;
1120 const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, .none);
1121 if (maybe_err) |err| switch (err) {
1122 // No timeout is passed to `netReceieve`, so it must not return timeout related errors.
1123 error.Timeout => unreachable,
1124 else => |e| return e,
1125 };
1120 const maybe_err, const count = (try io.operate(.{ .net_receive = .{
1121 .socket_handle = s.handle,
1122 .message_buffer = (&message)[0..1],
1123 .data_buffer = buffer,
1124 .flags = .{},
1125 } })).net_receive;
1126 if (maybe_err) |err| return err;
11261127 assert(1 == count);
11271128 return message;
11281129 }
......@@ -1144,7 +1145,7 @@ pub const Socket = struct {
11441145 ) ReceiveTimeoutError!IncomingMessage {
11451146 var message: IncomingMessage = .init;
11461147 const maybe_err, const count = (try io.operateTimeout(.{ .net_receive = .{
1147 .socket = s.handle,
1148 .socket_handle = s.handle,
11481149 .message_buffer = (&message)[0..1],
11491150 .data_buffer = buffer,
11501151 .flags = .{},