Commit 58fb5b29b6
Changed files (4)
lib
std
lib/std/os/bits/windows.zig
@@ -221,6 +221,15 @@ pub const SOCK_RAW = ws2_32.SOCK_RAW;
pub const SOCK_RDM = ws2_32.SOCK_RDM;
pub const SOCK_SEQPACKET = ws2_32.SOCK_SEQPACKET;
+/// WARNING: this flag is not supported by windows socket functions directly,
+/// it is only supported by std.os.socket. Be sure that this value does
+/// not share any bits with any of the SOCK_* values.
+pub const SOCK_CLOEXEC = 0x10000;
+/// WARNING: this flag is not supported by windows socket functions directly,
+/// it is only supported by std.os.socket. Be sure that this value does
+/// not share any bits with any of the SOCK_* values.
+pub const SOCK_NONBLOCK = 0x20000;
+
pub const IPPROTO_ICMP = ws2_32.IPPROTO_ICMP;
pub const IPPROTO_IGMP = ws2_32.IPPROTO_IGMP;
pub const BTHPROTO_RFCOMM = ws2_32.BTHPROTO_RFCOMM;
lib/std/os/windows/ws2_32.zig
@@ -174,6 +174,8 @@ pub const AI_SECURE = 0x08000;
pub const AI_RETURN_PREFERRED_NAMES = 0x10000;
pub const AI_DISABLE_IDN_ENCODING = 0x80000;
+pub const FIONBIO = -2147195266;
+
pub const sockaddr = extern struct {
family: ADDRESS_FAMILY,
data: [14]u8,
@@ -724,11 +726,6 @@ pub extern "ws2_32" fn WSAIoctl(
lpOverlapped: ?*WSAOVERLAPPED,
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
) callconv(.Stdcall) c_int;
-pub extern "ws2_32" fn socket(
- af: c_int,
- type: c_int,
- protocol: c_int,
-) callconv(.Stdcall) SOCKET;
pub extern "ws2_32" fn accept(
s: SOCKET,
addr: ?*sockaddr,
@@ -788,3 +785,8 @@ pub extern "ws2_32" fn getaddrinfo(
pub extern "ws2_32" fn freeaddrinfo(
pAddrInfo: *addrinfo,
) callconv(.Stdcall) void;
+pub extern "ws2_32" fn ioctlsocket(
+ s: SOCKET,
+ cmd: c_long,
+ argp: *c_ulong,
+) callconv(.Stdcall) c_int;
lib/std/net.zig
@@ -452,37 +452,33 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
};
var res: *os.addrinfo = undefined;
const rc = sys.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res);
- if (builtin.os.tag == .windows) {
- const ws2_32 = os.windows.ws2_32;
- if (rc != 0) switch (@intToEnum(os.windows.ws2_32.WinsockError, @intCast(u16, rc))) {
- .WSATRY_AGAIN => return error.TemporaryNameServerFailure,
- .WSANO_RECOVERY => return error.NameServerFailure,
- .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
- .WSA_NOT_ENOUGH_MEMORY => return error.OutOfMemory,
- .WSAHOST_NOT_FOUND => return error.UnknownHostName,
- .WSATYPE_NOT_FOUND => return error.ServiceUnavailable,
- .WSAEINVAL => unreachable,
- .WSAESOCKTNOSUPPORT => unreachable,
- else => |err| return os.windows.unexpectedWSAError(err),
- };
- } else {
- switch (rc) {
- @intToEnum(sys.EAI, 0) => {},
- .ADDRFAMILY => return error.HostLacksNetworkAddresses,
- .AGAIN => return error.TemporaryNameServerFailure,
- .BADFLAGS => unreachable, // Invalid hints
- .FAIL => return error.NameServerFailure,
- .FAMILY => return error.AddressFamilyNotSupported,
- .MEMORY => return error.OutOfMemory,
- .NODATA => return error.HostLacksNetworkAddresses,
- .NONAME => return error.UnknownHostName,
- .SERVICE => return error.ServiceUnavailable,
- .SOCKTYPE => unreachable, // Invalid socket type requested in hints
- .SYSTEM => switch (os.errno(-1)) {
- else => |e| return os.unexpectedErrno(e),
- },
- else => unreachable,
- }
+ if (builtin.os.tag == .windows) switch (@intToEnum(os.windows.ws2_32.WinsockError, @intCast(u16, rc))) {
+ @intToEnum(os.windows.ws2_32.WinsockError, 0) => {},
+ .WSATRY_AGAIN => return error.TemporaryNameServerFailure,
+ .WSANO_RECOVERY => return error.NameServerFailure,
+ .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
+ .WSA_NOT_ENOUGH_MEMORY => return error.OutOfMemory,
+ .WSAHOST_NOT_FOUND => return error.UnknownHostName,
+ .WSATYPE_NOT_FOUND => return error.ServiceUnavailable,
+ .WSAEINVAL => unreachable,
+ .WSAESOCKTNOSUPPORT => unreachable,
+ else => |err| return os.windows.unexpectedWSAError(err),
+ } else switch (rc) {
+ @intToEnum(sys.EAI, 0) => {},
+ .ADDRFAMILY => return error.HostLacksNetworkAddresses,
+ .AGAIN => return error.TemporaryNameServerFailure,
+ .BADFLAGS => unreachable, // Invalid hints
+ .FAIL => return error.NameServerFailure,
+ .FAMILY => return error.AddressFamilyNotSupported,
+ .MEMORY => return error.OutOfMemory,
+ .NODATA => return error.HostLacksNetworkAddresses,
+ .NONAME => return error.UnknownHostName,
+ .SERVICE => return error.ServiceUnavailable,
+ .SOCKTYPE => unreachable, // Invalid socket type requested in hints
+ .SYSTEM => switch (os.errno(-1)) {
+ else => |e| return os.unexpectedErrno(e),
+ },
+ else => unreachable,
}
defer sys.freeaddrinfo(res);
lib/std/os.zig
@@ -2447,17 +2447,29 @@ pub const SocketError = error{
pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t {
if (builtin.os.tag == .windows) {
- // NOTE: cannot remove SOCK_NONBLOCK and SOCK_CLOEXEC from socket_type because
- // windows does not define this flags yet
- const rc = windows.ws2_32.socket(@intCast(c_int, domain), @intCast(c_int, socket_type), @intCast(c_int, protocol));
- if (rc != windows.ws2_32.INVALID_SOCKET) return rc;
- switch (windows.ws2_32.WSAGetLastError()) {
+ // NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations
+ const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC);
+ const flags : u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0;
+ const rc = windows.ws2_32.WSASocketW(@intCast(c_int, domain), @intCast(c_int, filtered_sock_type),
+ @intCast(c_int, protocol), null, 0, flags);
+ if (rc == windows.ws2_32.INVALID_SOCKET) switch (windows.ws2_32.WSAGetLastError()) {
.WSAEMFILE => return error.ProcessFdQuotaExceeded,
.WSAENOBUFS => return error.SystemResources,
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
.WSAEPROTONOSUPPORT => return error.ProtocolNotSupported,
else => |err| return windows.unexpectedWSAError(err),
+ };
+ errdefer windows.closesocket(rc) catch unreachable;
+ if ((socket_type & SOCK_NONBLOCK) != 0) {
+ var mode : c_ulong = 1; // nonblocking
+ if (windows.ws2_32.SOCKET_ERROR == windows.ws2_32.ioctlsocket(rc, windows.ws2_32.FIONBIO, &mode)) {
+ switch (windows.ws2_32.WSAGetLastError()) {
+ // have not identified any error codes that should be handled yet
+ else => unreachable,
+ }
+ }
}
+ return rc;
}
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
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
else => |err| return windows.unexpectedWSAError(err),
}
+ return;
}
while (true) {