diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 38a94f352d..63242810c3 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -3172,10 +3172,62 @@ fn netListenUnixWindows( ) net.UnixAddress.ListenError!net.Socket.Handle { if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); - _ = address; - _ = options; - @panic("TODO implement netListenUnixWindows"); + + const socket_handle = openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { + error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, + else => |e| return e, + }; + errdefer closeSocketWindows(socket_handle); + + var storage: WsaAddress = undefined; + const addr_len = addressUnixToWsa(address, &storage); + + while (true) { + try t.checkCancel(); + const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) break; + switch (ws2_32.WSAGetLastError()) { + .EINTR => continue, + .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, + .NOTINITIALISED => { + try initializeWsa(t); + continue; + }, + .EADDRINUSE => return error.AddressInUse, + .EADDRNOTAVAIL => return error.AddressUnavailable, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .ENOBUFS => return error.SystemResources, + .ENETDOWN => return error.NetworkDown, + else => |err| return windows.unexpectedWSAError(err), + } + } + + while (true) { + try t.checkCancel(); + const rc = ws2_32.listen(socket_handle, options.kernel_backlog); + if (rc != ws2_32.SOCKET_ERROR) break; + switch (ws2_32.WSAGetLastError()) { + .EINTR => continue, + .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, + .NOTINITIALISED => { + try initializeWsa(t); + continue; + }, + .ENETDOWN => return error.NetworkDown, + .EADDRINUSE => return error.AddressInUse, + .EISCONN => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EMFILE, .ENOBUFS => return error.SystemResources, + .ENOTSOCK => |err| return wsaErrorBug(err), + .EOPNOTSUPP => |err| return wsaErrorBug(err), + .EINPROGRESS => |err| return wsaErrorBug(err), + else => |err| return windows.unexpectedWSAError(err), + } + } + + return socket_handle; } fn netListenUnixUnavailable( @@ -3493,9 +3545,37 @@ fn netConnectUnixWindows( ) net.UnixAddress.ConnectError!net.Socket.Handle { if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; const t: *Threaded = @ptrCast(@alignCast(userdata)); - try t.checkCancel(); - _ = address; - @panic("TODO implement netConnectUnixWindows"); + + const socket_handle = try openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }); + errdefer closeSocketWindows(socket_handle); + var storage: WsaAddress = undefined; + const addr_len = addressUnixToWsa(address, &storage); + + while (true) { + const rc = ws2_32.connect(socket_handle, &storage.any, addr_len); + if (rc != ws2_32.SOCKET_ERROR) break; + switch (ws2_32.WSAGetLastError()) { + .EINTR => continue, + .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, + .NOTINITIALISED => { + try initializeWsa(t); + continue; + }, + + .ECONNREFUSED => return error.FileNotFound, + .EFAULT => |err| return wsaErrorBug(err), + .EINVAL => |err| return wsaErrorBug(err), + .EISCONN => |err| return wsaErrorBug(err), + .ENOTSOCK => |err| return wsaErrorBug(err), + .EWOULDBLOCK => return error.WouldBlock, + .EACCES => return error.AccessDenied, + .ENOBUFS => return error.SystemResources, + .EAFNOSUPPORT => return error.AddressFamilyUnsupported, + else => |err| return windows.unexpectedWSAError(err), + } + } + + return socket_handle; } fn netConnectUnixUnavailable( @@ -4935,6 +5015,13 @@ fn addressUnixToPosix(a: *const net.UnixAddress, storage: *UnixAddress) posix.so return @sizeOf(posix.sockaddr.un); } +fn addressUnixToWsa(a: *const net.UnixAddress, storage: *WsaAddress) i32 { + @memcpy(storage.un.path[0..a.path.len], a.path); + storage.un.family = posix.AF.UNIX; + storage.un.path[a.path.len] = 0; + return @sizeOf(posix.sockaddr.un); +} + fn address4FromPosix(in: *const posix.sockaddr.in) net.Ip4Address { return .{ .port = std.mem.bigToNative(u16, in.port), diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index 362ff424a8..b691b1501e 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -879,6 +879,7 @@ pub const UnixAddress = struct { NotDir, ReadOnlyFileSystem, WouldBlock, + NetworkDown, } || Io.Cancelable || Io.UnexpectedError; pub fn connect(ua: *const UnixAddress, io: Io) ConnectError!Stream {