resolve
Function parameters
Parameters
- buf:[]const u8
- port:u16
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 resolve(buf: []const u8, port: u16) IPv6ResolveError!Ip6Address {
// TODO: Unify the implementations of resolveIp6 and parseIp6.
var result = Ip6Address{
.sa = posix.sockaddr.in6{
.scope_id = 0,
.port = mem.nativeToBig(u16, port),
.flowinfo = 0,
.addr = undefined,
},
};
var ip_slice: *[16]u8 = result.sa.addr[0..];
var tail: [16]u8 = undefined;
var x: u16 = 0;
var saw_any_digits = false;
var index: u8 = 0;
var abbrv = false;
var scope_id = false;
var scope_id_value: [posix.IFNAMESIZE - 1]u8 = undefined;
var scope_id_index: usize = 0;
for (buf, 0..) |c, i| {
if (scope_id) {
// Handling of percent-encoding should be for an URI library.
if ((c >= '0' and c <= '9') or
(c >= 'A' and c <= 'Z') or
(c >= 'a' and c <= 'z') or
(c == '-') or (c == '.') or (c == '_') or (c == '~'))
{
if (scope_id_index >= scope_id_value.len) {
return error.Overflow;
}
scope_id_value[scope_id_index] = c;
scope_id_index += 1;
} else {
return error.InvalidCharacter;
}
} else if (c == ':') {
if (!saw_any_digits) {
if (abbrv) return error.InvalidCharacter; // ':::'
if (i != 0) abbrv = true;
@memset(ip_slice[index..], 0);
ip_slice = tail[0..];
index = 0;
continue;
}
if (index == 14) {
return error.InvalidEnd;
}
ip_slice[index] = @as(u8, @truncate(x >> 8));
index += 1;
ip_slice[index] = @as(u8, @truncate(x));
index += 1;
x = 0;
saw_any_digits = false;
} else if (c == '%') {
if (!saw_any_digits) {
return error.InvalidCharacter;
}
scope_id = true;
saw_any_digits = false;
} else if (c == '.') {
if (!abbrv or ip_slice[0] != 0xff or ip_slice[1] != 0xff) {
// must start with '::ffff:'
return error.InvalidIpv4Mapping;
}
const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1;
const addr = (Ip4Address.parse(buf[start_index..], 0) catch {
return error.InvalidIpv4Mapping;
}).sa.addr;
ip_slice = result.sa.addr[0..];
ip_slice[10] = 0xff;
ip_slice[11] = 0xff;
const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]);
ip_slice[12] = ptr[0];
ip_slice[13] = ptr[1];
ip_slice[14] = ptr[2];
ip_slice[15] = ptr[3];
return result;
} else {
const digit = try std.fmt.charToDigit(c, 16);
{
const ov = @mulWithOverflow(x, 16);
if (ov[1] != 0) return error.Overflow;
x = ov[0];
}
{
const ov = @addWithOverflow(x, digit);
if (ov[1] != 0) return error.Overflow;
x = ov[0];
}
saw_any_digits = true;
}
}
if (!saw_any_digits and !abbrv) {
return error.Incomplete;
}
if (scope_id and scope_id_index == 0) {
return error.Incomplete;
}
var resolved_scope_id: u32 = 0;
if (scope_id_index > 0) {
const scope_id_str = scope_id_value[0..scope_id_index];
resolved_scope_id = std.fmt.parseInt(u32, scope_id_str, 10) catch |err| blk: {
if (err != error.InvalidCharacter) return err;
break :blk try if_nametoindex(scope_id_str);
};
}
result.sa.scope_id = resolved_scope_id;
if (index == 14) {
ip_slice[14] = @as(u8, @truncate(x >> 8));
ip_slice[15] = @as(u8, @truncate(x));
return result;
} else {
ip_slice[index] = @as(u8, @truncate(x >> 8));
index += 1;
ip_slice[index] = @as(u8, @truncate(x));
index += 1;
@memcpy(result.sa.addr[16 - index ..][0..index], ip_slice[0..index]);
return result;
}
}