Skip to content

Commit dd67672

Browse files
committed
std.Io.Threaded: implement netLookup for Windows
1 parent c1d6ca3 commit dd67672

File tree

2 files changed

+108
-31
lines changed

2 files changed

+108
-31
lines changed

lib/std/Io/Threaded.zig

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4058,8 +4058,81 @@ fn netLookupFallible(
40584058
assert(name.len <= HostName.max_len);
40594059

40604060
if (is_windows) {
4061-
// TODO use GetAddrInfoExW / GetAddrInfoExCancel
4062-
@compileError("TODO");
4061+
var name_buffer: [HostName.max_len + 1]u16 = undefined;
4062+
const name_len = std.unicode.wtf8ToWtf16Le(&name_buffer, host_name.bytes) catch
4063+
unreachable; // HostName is prevalidated.
4064+
name_buffer[name_len] = 0;
4065+
const name_w = name_buffer[0..name_len :0];
4066+
4067+
var port_buffer: [8]u8 = undefined;
4068+
var port_buffer_wide: [8]u16 = undefined;
4069+
const port = std.fmt.bufPrint(&port_buffer, "{d}", .{options.port}) catch
4070+
unreachable; // `port_buffer` is big enough for decimal u16.
4071+
for (port, port_buffer[0..port.len]) |byte, *wide| wide.* = byte;
4072+
port_buffer_wide[port.len] = 0;
4073+
const port_w = port_buffer_wide[0..port.len :0];
4074+
4075+
const hints: ws2_32.ADDRINFOEXW = .{
4076+
.flags = .{ .NUMERICSERV = true },
4077+
.family = posix.AF.UNSPEC,
4078+
.socktype = posix.SOCK.STREAM,
4079+
.protocol = posix.IPPROTO.TCP,
4080+
.canonname = null,
4081+
.addr = null,
4082+
.addrlen = 0,
4083+
.blob = null,
4084+
.bloblen = 0,
4085+
.provider = null,
4086+
.next = null,
4087+
};
4088+
var res: *ws2_32.ADDRINFOEXW = undefined;
4089+
const timeout: ?*ws2_32.timeval = null;
4090+
while (true) {
4091+
try t.checkCancel(); // TODO make requestCancel call GetAddrInfoExCancel
4092+
// TODO make this append to the queue eagerly rather than blocking until
4093+
// the whole thing finishes
4094+
const rc: ws2_32.WinsockError = @enumFromInt(ws2_32.GetAddrInfoExW(name_w, port_w, .DNS, null, &hints, &res, timeout, null, null));
4095+
switch (rc) {
4096+
@as(ws2_32.WinsockError, @enumFromInt(0)) => break,
4097+
.EINTR => continue,
4098+
.ECANCELLED, .E_CANCELLED => return error.Canceled,
4099+
.NOTINITIALISED => {
4100+
try initializeWsa(t);
4101+
continue;
4102+
},
4103+
.TRY_AGAIN => return error.NameServerFailure,
4104+
.EINVAL => |err| return wsaErrorBug(err),
4105+
.NO_RECOVERY => return error.NameServerFailure,
4106+
.EAFNOSUPPORT => return error.AddressFamilyUnsupported,
4107+
.NOT_ENOUGH_MEMORY => return error.SystemResources,
4108+
.HOST_NOT_FOUND => return error.UnknownHostName,
4109+
.TYPE_NOT_FOUND => return error.ProtocolUnsupportedByAddressFamily,
4110+
.ESOCKTNOSUPPORT => return error.ProtocolUnsupportedBySystem,
4111+
else => |err| return windows.unexpectedWSAError(err),
4112+
}
4113+
}
4114+
defer ws2_32.FreeAddrInfoExW(res);
4115+
4116+
var it: ?*ws2_32.ADDRINFOEXW = res;
4117+
var canon_name: ?[*:0]const u16 = null;
4118+
while (it) |info| : (it = info.next) {
4119+
const addr = info.addr orelse continue;
4120+
const storage: WsaAddress = .{ .any = addr.* };
4121+
try resolved.putOne(t_io, .{ .address = addressFromWsa(&storage) });
4122+
4123+
if (info.canonname) |n| {
4124+
if (canon_name == null) {
4125+
canon_name = n;
4126+
}
4127+
}
4128+
}
4129+
if (canon_name) |n| {
4130+
const len = std.unicode.wtf16LeToWtf8(options.canonical_name_buffer, std.mem.sliceTo(n, 0));
4131+
try resolved.putOne(t_io, .{ .canonical_name = .{
4132+
.bytes = options.canonical_name_buffer[0..len],
4133+
} });
4134+
}
4135+
return;
40634136
}
40644137

40654138
// On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.

lib/std/os/windows/ws2_32.zig

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -702,28 +702,32 @@ pub const FIONBIO = -2147195266;
702702
pub const ADDRINFOEX_VERSION_2 = 2;
703703
pub const ADDRINFOEX_VERSION_3 = 3;
704704
pub const ADDRINFOEX_VERSION_4 = 4;
705-
pub const NS_ALL = 0;
706-
pub const NS_SAP = 1;
707-
pub const NS_NDS = 2;
708-
pub const NS_PEER_BROWSE = 3;
709-
pub const NS_SLP = 5;
710-
pub const NS_DHCP = 6;
711-
pub const NS_TCPIP_LOCAL = 10;
712-
pub const NS_TCPIP_HOSTS = 11;
713-
pub const NS_DNS = 12;
714-
pub const NS_NETBT = 13;
715-
pub const NS_WINS = 14;
716-
pub const NS_NLA = 15;
717-
pub const NS_NBP = 20;
718-
pub const NS_MS = 30;
719-
pub const NS_STDA = 31;
720-
pub const NS_NTDS = 32;
721-
pub const NS_EMAIL = 37;
722-
pub const NS_X500 = 40;
723-
pub const NS_NIS = 41;
724-
pub const NS_NISPLUS = 42;
725-
pub const NS_WRQ = 50;
726-
pub const NS_NETDES = 60;
705+
706+
pub const NS = enum(u32) {
707+
ALL = 0,
708+
SAP = 1,
709+
NDS = 2,
710+
PEER_BROWSE = 3,
711+
SLP = 5,
712+
DHCP = 6,
713+
TCPIP_LOCAL = 10,
714+
TCPIP_HOSTS = 11,
715+
DNS = 12,
716+
NETBT = 13,
717+
WINS = 14,
718+
NLA = 15,
719+
NBP = 20,
720+
MS = 30,
721+
STDA = 31,
722+
NTDS = 32,
723+
EMAIL = 37,
724+
X500 = 40,
725+
NIS = 41,
726+
NISPLUS = 42,
727+
WRQ = 50,
728+
NETDES = 60,
729+
};
730+
727731
pub const NI_NOFQDN = 1;
728732
pub const NI_NUMERICHOST = 2;
729733
pub const NI_NAMEREQD = 4;
@@ -1086,12 +1090,12 @@ pub const ADDRINFOEXW = extern struct {
10861090
socktype: i32,
10871091
protocol: i32,
10881092
addrlen: usize,
1089-
canonname: [*:0]u16,
1090-
addr: *sockaddr,
1091-
blob: *anyopaque,
1093+
canonname: ?[*:0]u16,
1094+
addr: ?*sockaddr,
1095+
blob: ?*anyopaque,
10921096
bloblen: usize,
1093-
provider: *GUID,
1094-
next: *ADDRINFOEXW,
1097+
provider: ?*GUID,
1098+
next: ?*ADDRINFOEXW,
10951099
};
10961100

10971101
pub const sockaddr = extern struct {
@@ -2101,7 +2105,7 @@ pub extern "mswsock" fn EnumProtocolsW(
21012105
) callconv(.winapi) i32;
21022106

21032107
pub extern "mswsock" fn GetAddressByNameW(
2104-
dwNameSpace: u32,
2108+
dwNameSpace: NS,
21052109
lpServiceType: *GUID,
21062110
lpServiceName: ?[*:0]u16,
21072111
lpiProtocols: ?*i32,
@@ -2127,7 +2131,7 @@ pub extern "mswsock" fn GetNameByTypeW(
21272131
pub extern "ws2_32" fn GetAddrInfoExW(
21282132
pName: ?[*:0]const u16,
21292133
pServiceName: ?[*:0]const u16,
2130-
dwNameSpace: DWORD,
2134+
dwNameSpace: NS,
21312135
lpNspId: ?*GUID,
21322136
hints: ?*const ADDRINFOEXW,
21332137
ppResult: **ADDRINFOEXW,

0 commit comments

Comments
 (0)