| author | |
| committer | |
| log | 58fb5b29b690dd868c7f69631fe59eae48fc9f4b |
| tree | e489cbd1096b9d1d08e26067abfc6dcfad594cdf |
| parent | 2bae91e7697dfcaee7e250c813715fc4051ac51a |
* support posix SOCK_NONBLOCK and SOCK_CLOEXEC flags on windows
* fix bugs in os.socket and os.connect to return at the correct place4 files changed, 61 insertions(+), 41 deletions(-)
lib/std/net.zig+27-31| ... | @@ -452,37 +452,33 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* | ... | @@ -452,37 +452,33 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* |
| 452 | }; | 452 | }; |
| 453 | var res: *os.addrinfo = undefined; | 453 | var res: *os.addrinfo = undefined; |
| 454 | const rc = sys.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res); | 454 | const rc = sys.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res); |
| 455 | if (builtin.os.tag == .windows) { | 455 | if (builtin.os.tag == .windows) switch (@intToEnum(os.windows.ws2_32.WinsockError, @intCast(u16, rc))) { |
| 456 | const ws2_32 = os.windows.ws2_32; | 456 | @intToEnum(os.windows.ws2_32.WinsockError, 0) => {}, |
| 457 | if (rc != 0) switch (@intToEnum(os.windows.ws2_32.WinsockError, @intCast(u16, rc))) { | 457 | .WSATRY_AGAIN => return error.TemporaryNameServerFailure, |
| 458 | .WSATRY_AGAIN => return error.TemporaryNameServerFailure, | 458 | .WSANO_RECOVERY => return error.NameServerFailure, |
| 459 | .WSANO_RECOVERY => return error.NameServerFailure, | 459 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, |
| 460 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, | 460 | .WSA_NOT_ENOUGH_MEMORY => return error.OutOfMemory, |
| 461 | .WSA_NOT_ENOUGH_MEMORY => return error.OutOfMemory, | 461 | .WSAHOST_NOT_FOUND => return error.UnknownHostName, |
| 462 | .WSAHOST_NOT_FOUND => return error.UnknownHostName, | 462 | .WSATYPE_NOT_FOUND => return error.ServiceUnavailable, |
| 463 | .WSATYPE_NOT_FOUND => return error.ServiceUnavailable, | 463 | .WSAEINVAL => unreachable, |
| 464 | .WSAEINVAL => unreachable, | 464 | .WSAESOCKTNOSUPPORT => unreachable, |
| 465 | .WSAESOCKTNOSUPPORT => unreachable, | 465 | else => |err| return os.windows.unexpectedWSAError(err), |
| 466 | else => |err| return os.windows.unexpectedWSAError(err), | 466 | } else switch (rc) { |
| 467 | }; | 467 | @intToEnum(sys.EAI, 0) => {}, |
| 468 | } else { | 468 | .ADDRFAMILY => return error.HostLacksNetworkAddresses, |
| 469 | switch (rc) { | 469 | .AGAIN => return error.TemporaryNameServerFailure, |
| 470 | @intToEnum(sys.EAI, 0) => {}, | 470 | .BADFLAGS => unreachable, // Invalid hints |
| 471 | .ADDRFAMILY => return error.HostLacksNetworkAddresses, | 471 | .FAIL => return error.NameServerFailure, |
| 472 | .AGAIN => return error.TemporaryNameServerFailure, | 472 | .FAMILY => return error.AddressFamilyNotSupported, |
| 473 | .BADFLAGS => unreachable, // Invalid hints | 473 | .MEMORY => return error.OutOfMemory, |
| 474 | .FAIL => return error.NameServerFailure, | 474 | .NODATA => return error.HostLacksNetworkAddresses, |
| 475 | .FAMILY => return error.AddressFamilyNotSupported, | 475 | .NONAME => return error.UnknownHostName, |
| 476 | .MEMORY => return error.OutOfMemory, | 476 | .SERVICE => return error.ServiceUnavailable, |
| 477 | .NODATA => return error.HostLacksNetworkAddresses, | 477 | .SOCKTYPE => unreachable, // Invalid socket type requested in hints |
| 478 | .NONAME => return error.UnknownHostName, | 478 | .SYSTEM => switch (os.errno(-1)) { |
| 479 | .SERVICE => return error.ServiceUnavailable, | 479 | else => |e| return os.unexpectedErrno(e), |
| 480 | .SOCKTYPE => unreachable, // Invalid socket type requested in hints | 480 | }, |
| 481 | .SYSTEM => switch (os.errno(-1)) { | 481 | else => unreachable, |
| 482 | else => |e| return os.unexpectedErrno(e), | ||
| 483 | }, | ||
| 484 | else => unreachable, | ||
| 485 | } | ||
| 486 | } | 482 | } |
| 487 | defer sys.freeaddrinfo(res); | 483 | defer sys.freeaddrinfo(res); |
| 488 | 484 |
lib/std/os.zig+18-5| ... | @@ -2447,17 +2447,29 @@ pub const SocketError = error{ | ... | @@ -2447,17 +2447,29 @@ pub const SocketError = error{ |
| 2447 | 2447 | ||
| 2448 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { | 2448 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { |
| 2449 | if (builtin.os.tag == .windows) { | 2449 | if (builtin.os.tag == .windows) { |
| 2450 | // NOTE: cannot remove SOCK_NONBLOCK and SOCK_CLOEXEC from socket_type because | 2450 | // NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations |
| 2451 | // windows does not define this flags yet | 2451 | const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC); |
| 2452 | const rc = windows.ws2_32.socket(@intCast(c_int, domain), @intCast(c_int, socket_type), @intCast(c_int, protocol)); | 2452 | const flags : u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0; |
| 2453 | if (rc != windows.ws2_32.INVALID_SOCKET) return rc; | 2453 | const rc = windows.ws2_32.WSASocketW(@intCast(c_int, domain), @intCast(c_int, filtered_sock_type), |
| 2454 | switch (windows.ws2_32.WSAGetLastError()) { | 2454 | @intCast(c_int, protocol), null, 0, flags); |
| 2455 | if (rc == windows.ws2_32.INVALID_SOCKET) switch (windows.ws2_32.WSAGetLastError()) { | ||
| 2455 | .WSAEMFILE => return error.ProcessFdQuotaExceeded, | 2456 | .WSAEMFILE => return error.ProcessFdQuotaExceeded, |
| 2456 | .WSAENOBUFS => return error.SystemResources, | 2457 | .WSAENOBUFS => return error.SystemResources, |
| 2457 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, | 2458 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, |
| 2458 | .WSAEPROTONOSUPPORT => return error.ProtocolNotSupported, | 2459 | .WSAEPROTONOSUPPORT => return error.ProtocolNotSupported, |
| 2459 | else => |err| return windows.unexpectedWSAError(err), | 2460 | else => |err| return windows.unexpectedWSAError(err), |
| 2461 | }; | ||
| 2462 | errdefer windows.closesocket(rc) catch unreachable; | ||
| 2463 | if ((socket_type & SOCK_NONBLOCK) != 0) { | ||
| 2464 | var mode : c_ulong = 1; // nonblocking | ||
| 2465 | if (windows.ws2_32.SOCKET_ERROR == windows.ws2_32.ioctlsocket(rc, windows.ws2_32.FIONBIO, &mode)) { | ||
| 2466 | switch (windows.ws2_32.WSAGetLastError()) { | ||
| 2467 | // have not identified any error codes that should be handled yet | ||
| 2468 | else => unreachable, | ||
| 2469 | } | ||
| 2470 | } | ||
| 2460 | } | 2471 | } |
| 2472 | return rc; | ||
| 2461 | } | 2473 | } |
| 2462 | 2474 | ||
| 2463 | const have_sock_flags = comptime !std.Target.current.isDarwin(); | 2475 | const have_sock_flags = comptime !std.Target.current.isDarwin(); |
| ... | @@ -2855,6 +2867,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con | ... | @@ -2855,6 +2867,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con |
| 2855 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, | 2867 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, |
| 2856 | else => |err| return windows.unexpectedWSAError(err), | 2868 | else => |err| return windows.unexpectedWSAError(err), |
| 2857 | } | 2869 | } |
| 2870 | return; | ||
| 2858 | } | 2871 | } |
| 2859 | 2872 | ||
| 2860 | while (true) { | 2873 | while (true) { |
lib/std/os/bits/windows.zig+9| ... | @@ -221,6 +221,15 @@ pub const SOCK_RAW = ws2_32.SOCK_RAW; | ... | @@ -221,6 +221,15 @@ pub const SOCK_RAW = ws2_32.SOCK_RAW; |
| 221 | pub const SOCK_RDM = ws2_32.SOCK_RDM; | 221 | pub const SOCK_RDM = ws2_32.SOCK_RDM; |
| 222 | pub const SOCK_SEQPACKET = ws2_32.SOCK_SEQPACKET; | 222 | pub const SOCK_SEQPACKET = ws2_32.SOCK_SEQPACKET; |
| 223 | 223 | ||
| 224 | /// WARNING: this flag is not supported by windows socket functions directly, | ||
| 225 | /// it is only supported by std.os.socket. Be sure that this value does | ||
| 226 | /// not share any bits with any of the SOCK_* values. | ||
| 227 | pub const SOCK_CLOEXEC = 0x10000; | ||
| 228 | /// WARNING: this flag is not supported by windows socket functions directly, | ||
| 229 | /// it is only supported by std.os.socket. Be sure that this value does | ||
| 230 | /// not share any bits with any of the SOCK_* values. | ||
| 231 | pub const SOCK_NONBLOCK = 0x20000; | ||
| 232 | |||
| 224 | pub const IPPROTO_ICMP = ws2_32.IPPROTO_ICMP; | 233 | pub const IPPROTO_ICMP = ws2_32.IPPROTO_ICMP; |
| 225 | pub const IPPROTO_IGMP = ws2_32.IPPROTO_IGMP; | 234 | pub const IPPROTO_IGMP = ws2_32.IPPROTO_IGMP; |
| 226 | pub const BTHPROTO_RFCOMM = ws2_32.BTHPROTO_RFCOMM; | 235 | pub const BTHPROTO_RFCOMM = ws2_32.BTHPROTO_RFCOMM; |
lib/std/os/windows/ws2_32.zig+7-5| ... | @@ -174,6 +174,8 @@ pub const AI_SECURE = 0x08000; | ... | @@ -174,6 +174,8 @@ pub const AI_SECURE = 0x08000; |
| 174 | pub const AI_RETURN_PREFERRED_NAMES = 0x10000; | 174 | pub const AI_RETURN_PREFERRED_NAMES = 0x10000; |
| 175 | pub const AI_DISABLE_IDN_ENCODING = 0x80000; | 175 | pub const AI_DISABLE_IDN_ENCODING = 0x80000; |
| 176 | 176 | ||
| 177 | pub const FIONBIO = -2147195266; | ||
| 178 | |||
| 177 | pub const sockaddr = extern struct { | 179 | pub const sockaddr = extern struct { |
| 178 | family: ADDRESS_FAMILY, | 180 | family: ADDRESS_FAMILY, |
| 179 | data: [14]u8, | 181 | data: [14]u8, |
| ... | @@ -724,11 +726,6 @@ pub extern "ws2_32" fn WSAIoctl( | ... | @@ -724,11 +726,6 @@ pub extern "ws2_32" fn WSAIoctl( |
| 724 | lpOverlapped: ?*WSAOVERLAPPED, | 726 | lpOverlapped: ?*WSAOVERLAPPED, |
| 725 | lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE, | 727 | lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE, |
| 726 | ) callconv(.Stdcall) c_int; | 728 | ) callconv(.Stdcall) c_int; |
| 727 | pub extern "ws2_32" fn socket( | ||
| 728 | af: c_int, | ||
| 729 | type: c_int, | ||
| 730 | protocol: c_int, | ||
| 731 | ) callconv(.Stdcall) SOCKET; | ||
| 732 | pub extern "ws2_32" fn accept( | 729 | pub extern "ws2_32" fn accept( |
| 733 | s: SOCKET, | 730 | s: SOCKET, |
| 734 | addr: ?*sockaddr, | 731 | addr: ?*sockaddr, |
| ... | @@ -788,3 +785,8 @@ pub extern "ws2_32" fn getaddrinfo( | ... | @@ -788,3 +785,8 @@ pub extern "ws2_32" fn getaddrinfo( |
| 788 | pub extern "ws2_32" fn freeaddrinfo( | 785 | pub extern "ws2_32" fn freeaddrinfo( |
| 789 | pAddrInfo: *addrinfo, | 786 | pAddrInfo: *addrinfo, |
| 790 | ) callconv(.Stdcall) void; | 787 | ) callconv(.Stdcall) void; |
| 788 | pub extern "ws2_32" fn ioctlsocket( | ||
| 789 | s: SOCKET, | ||
| 790 | cmd: c_long, | ||
| 791 | argp: *c_ulong, | ||
| 792 | ) callconv(.Stdcall) c_int; |