getAddressList
Call AddressList.deinit on the result.
Function parameters
Parameters
Type definitions in this namespace
Types
Functions in this namespace
Functions
- tcpConnectToHost
- All memory allocated with `allocator` will be freed before this function returns.
- getAddressList
- Call `AddressList.deinit` on the result.
Error sets in this namespace
Error Sets
= switch (native_os) { .windows => builtin.os.version_range.windows.isAtLeast(.win10_rs4) orelse false, .wasi => false, else => true, }
Values
- has_unix_sockets
- = switch (native_os) { .windows => builtin.os.version_range.windows.isAtLeast(.win10_rs4) orelse false, .wasi => false, else => true, }
Source
Implementation
pub fn getAddressList(gpa: Allocator, name: []const u8, port: u16) GetAddressListError!*AddressList {
const result = blk: {
var arena = std.heap.ArenaAllocator.init(gpa);
errdefer arena.deinit();
const result = try arena.allocator().create(AddressList);
result.* = AddressList{
.arena = arena,
.addrs = undefined,
.canon_name = null,
};
break :blk result;
};
const arena = result.arena.allocator();
errdefer result.deinit();
if (native_os == .windows) {
const name_c = try gpa.dupeZ(u8, name);
defer gpa.free(name_c);
const port_c = try std.fmt.allocPrintSentinel(gpa, "{d}", .{port}, 0);
defer gpa.free(port_c);
const ws2_32 = windows.ws2_32;
const hints: posix.addrinfo = .{
.flags = .{ .NUMERICSERV = true },
.family = posix.AF.UNSPEC,
.socktype = posix.SOCK.STREAM,
.protocol = posix.IPPROTO.TCP,
.canonname = null,
.addr = null,
.addrlen = 0,
.next = null,
};
var res: ?*posix.addrinfo = null;
var first = true;
while (true) {
const rc = ws2_32.getaddrinfo(name_c.ptr, port_c.ptr, &hints, &res);
switch (@as(windows.ws2_32.WinsockError, @enumFromInt(@as(u16, @intCast(rc))))) {
@as(windows.ws2_32.WinsockError, @enumFromInt(0)) => break,
.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,
.WSANOTINITIALISED => {
if (!first) return error.Unexpected;
first = false;
try windows.callWSAStartup();
continue;
},
else => |err| return windows.unexpectedWSAError(err),
}
}
defer ws2_32.freeaddrinfo(res);
const addr_count = blk: {
var count: usize = 0;
var it = res;
while (it) |info| : (it = info.next) {
if (info.addr != null) {
count += 1;
}
}
break :blk count;
};
result.addrs = try arena.alloc(Address, addr_count);
var it = res;
var i: usize = 0;
while (it) |info| : (it = info.next) {
const addr = info.addr orelse continue;
result.addrs[i] = Address.initPosix(@alignCast(addr));
if (info.canonname) |n| {
if (result.canon_name == null) {
result.canon_name = try arena.dupe(u8, mem.sliceTo(n, 0));
}
}
i += 1;
}
return result;
}
if (builtin.link_libc) {
const name_c = try gpa.dupeZ(u8, name);
defer gpa.free(name_c);
const port_c = try std.fmt.allocPrintSentinel(gpa, "{d}", .{port}, 0);
defer gpa.free(port_c);
const hints: posix.addrinfo = .{
.flags = .{ .NUMERICSERV = true },
.family = posix.AF.UNSPEC,
.socktype = posix.SOCK.STREAM,
.protocol = posix.IPPROTO.TCP,
.canonname = null,
.addr = null,
.addrlen = 0,
.next = null,
};
var res: ?*posix.addrinfo = null;
switch (posix.system.getaddrinfo(name_c.ptr, port_c.ptr, &hints, &res)) {
@as(posix.system.EAI, @enumFromInt(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 (posix.errno(-1)) {
else => |e| return posix.unexpectedErrno(e),
},
else => unreachable,
}
defer if (res) |some| posix.system.freeaddrinfo(some);
const addr_count = blk: {
var count: usize = 0;
var it = res;
while (it) |info| : (it = info.next) {
if (info.addr != null) {
count += 1;
}
}
break :blk count;
};
result.addrs = try arena.alloc(Address, addr_count);
var it = res;
var i: usize = 0;
while (it) |info| : (it = info.next) {
const addr = info.addr orelse continue;
result.addrs[i] = Address.initPosix(@alignCast(addr));
if (info.canonname) |n| {
if (result.canon_name == null) {
result.canon_name = try arena.dupe(u8, mem.sliceTo(n, 0));
}
}
i += 1;
}
return result;
}
if (native_os == .linux) {
const family = posix.AF.UNSPEC;
var lookup_addrs: ArrayList(LookupAddr) = .empty;
defer lookup_addrs.deinit(gpa);
var canon: ArrayList(u8) = .empty;
defer canon.deinit(gpa);
try linuxLookupName(gpa, &lookup_addrs, &canon, name, family, .{ .NUMERICSERV = true }, port);
result.addrs = try arena.alloc(Address, lookup_addrs.items.len);
if (canon.items.len != 0) {
result.canon_name = try arena.dupe(u8, canon.items);
}
for (lookup_addrs.items, 0..) |lookup_addr, i| {
result.addrs[i] = lookup_addr.addr;
assert(result.addrs[i].getPort() == port);
}
return result;
}
@compileError("std.net.getAddressList unimplemented for this OS");
}