Merge pull request #3635 from lun-4/unify-unix-sockets
std.net: add unix socket support to Address and StreamServermaster
commit
891e2149b0
152
lib/std/net.zig
152
lib/std/net.zig
|
@ -10,15 +10,18 @@ test "" {
|
|||
_ = @import("net/test.zig");
|
||||
}
|
||||
|
||||
pub const IpAddress = extern union {
|
||||
const has_unix_sockets = @hasDecl(os, "sockaddr_un");
|
||||
|
||||
pub const Address = extern union {
|
||||
any: os.sockaddr,
|
||||
in: os.sockaddr_in,
|
||||
in6: os.sockaddr_in6,
|
||||
un: if (has_unix_sockets) os.sockaddr_un else void,
|
||||
|
||||
// TODO this crashed the compiler
|
||||
//pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0);
|
||||
|
||||
pub fn parse(name: []const u8, port: u16) !IpAddress {
|
||||
pub fn parseIp(name: []const u8, port: u16) !Address {
|
||||
if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {
|
||||
error.Overflow,
|
||||
error.InvalidEnd,
|
||||
|
@ -39,17 +42,17 @@ pub const IpAddress = extern union {
|
|||
return error.InvalidIPAddressFormat;
|
||||
}
|
||||
|
||||
pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !IpAddress {
|
||||
pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !Address {
|
||||
switch (family) {
|
||||
os.AF_INET => return parseIp4(name, port),
|
||||
os.AF_INET6 => return parseIp6(name, port),
|
||||
os.AF_UNSPEC => return parse(name, port),
|
||||
os.AF_UNSPEC => return parseIp(name, port),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parseIp6(buf: []const u8, port: u16) !IpAddress {
|
||||
var result = IpAddress{
|
||||
pub fn parseIp6(buf: []const u8, port: u16) !Address {
|
||||
var result = Address{
|
||||
.in6 = os.sockaddr_in6{
|
||||
.scope_id = 0,
|
||||
.port = mem.nativeToBig(u16, port),
|
||||
|
@ -154,8 +157,8 @@ pub const IpAddress = extern union {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parseIp4(buf: []const u8, port: u16) !IpAddress {
|
||||
var result = IpAddress{
|
||||
pub fn parseIp4(buf: []const u8, port: u16) !Address {
|
||||
var result = Address{
|
||||
.in = os.sockaddr_in{
|
||||
.port = mem.nativeToBig(u16, port),
|
||||
.addr = undefined,
|
||||
|
@ -194,8 +197,8 @@ pub const IpAddress = extern union {
|
|||
return error.Incomplete;
|
||||
}
|
||||
|
||||
pub fn initIp4(addr: [4]u8, port: u16) IpAddress {
|
||||
return IpAddress{
|
||||
pub fn initIp4(addr: [4]u8, port: u16) Address {
|
||||
return Address{
|
||||
.in = os.sockaddr_in{
|
||||
.port = mem.nativeToBig(u16, port),
|
||||
.addr = @ptrCast(*align(1) const u32, &addr).*,
|
||||
|
@ -203,8 +206,8 @@ pub const IpAddress = extern union {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) IpAddress {
|
||||
return IpAddress{
|
||||
pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Address {
|
||||
return Address{
|
||||
.in6 = os.sockaddr_in6{
|
||||
.addr = addr,
|
||||
.port = mem.nativeToBig(u16, port),
|
||||
|
@ -214,8 +217,24 @@ pub const IpAddress = extern union {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn initUnix(path: []const u8) !Address {
|
||||
var sock_addr = os.sockaddr_un{
|
||||
.family = os.AF_UNIX,
|
||||
.path = undefined,
|
||||
};
|
||||
|
||||
// this enables us to have the proper length of the socket in getOsSockLen
|
||||
mem.set(u8, &sock_addr.path, 0);
|
||||
|
||||
if (path.len > sock_addr.path.len) return error.NameTooLong;
|
||||
mem.copy(u8, &sock_addr.path, path);
|
||||
|
||||
return Address{ .un = sock_addr };
|
||||
}
|
||||
|
||||
/// Returns the port in native endian.
|
||||
pub fn getPort(self: IpAddress) u16 {
|
||||
/// Asserts that the address is ip4 or ip6.
|
||||
pub fn getPort(self: Address) u16 {
|
||||
const big_endian_port = switch (self.any.family) {
|
||||
os.AF_INET => self.in.port,
|
||||
os.AF_INET6 => self.in6.port,
|
||||
|
@ -225,7 +244,8 @@ pub const IpAddress = extern union {
|
|||
}
|
||||
|
||||
/// `port` is native-endian.
|
||||
pub fn setPort(self: *IpAddress, port: u16) void {
|
||||
/// Asserts that the address is ip4 or ip6.
|
||||
pub fn setPort(self: *Address, port: u16) void {
|
||||
const ptr = switch (self.any.family) {
|
||||
os.AF_INET => &self.in.port,
|
||||
os.AF_INET6 => &self.in6.port,
|
||||
|
@ -237,16 +257,16 @@ pub const IpAddress = extern union {
|
|||
/// Asserts that `addr` is an IP address.
|
||||
/// This function will read past the end of the pointer, with a size depending
|
||||
/// on the address family.
|
||||
pub fn initPosix(addr: *align(4) const os.sockaddr) IpAddress {
|
||||
pub fn initPosix(addr: *align(4) const os.sockaddr) Address {
|
||||
switch (addr.family) {
|
||||
os.AF_INET => return IpAddress{ .in = @ptrCast(*const os.sockaddr_in, addr).* },
|
||||
os.AF_INET6 => return IpAddress{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* },
|
||||
os.AF_INET => return Address{ .in = @ptrCast(*const os.sockaddr_in, addr).* },
|
||||
os.AF_INET6 => return Address{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* },
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: IpAddress,
|
||||
self: Address,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
context: var,
|
||||
|
@ -314,20 +334,35 @@ pub const IpAddress = extern union {
|
|||
}
|
||||
try std.fmt.format(context, Errors, output, "]:{}", port);
|
||||
},
|
||||
os.AF_UNIX => {
|
||||
if (!has_unix_sockets) {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
try std.fmt.format(context, Errors, output, "{}", self.un.path);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eql(a: IpAddress, b: IpAddress) bool {
|
||||
pub fn eql(a: Address, b: Address) bool {
|
||||
const a_bytes = @ptrCast([*]const u8, &a.any)[0..a.getOsSockLen()];
|
||||
const b_bytes = @ptrCast([*]const u8, &b.any)[0..b.getOsSockLen()];
|
||||
return mem.eql(u8, a_bytes, b_bytes);
|
||||
}
|
||||
|
||||
fn getOsSockLen(self: IpAddress) os.socklen_t {
|
||||
fn getOsSockLen(self: Address) os.socklen_t {
|
||||
switch (self.any.family) {
|
||||
os.AF_INET => return @sizeOf(os.sockaddr_in),
|
||||
os.AF_INET6 => return @sizeOf(os.sockaddr_in6),
|
||||
os.AF_UNIX => {
|
||||
if (!has_unix_sockets) {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
const path_len = std.mem.len(u8, &self.un.path);
|
||||
return @intCast(os.socklen_t, @sizeOf(os.sockaddr_un) - self.un.path.len + path_len);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
@ -342,23 +377,20 @@ pub fn connectUnixSocket(path: []const u8) !fs.File {
|
|||
);
|
||||
errdefer os.close(sockfd);
|
||||
|
||||
var sock_addr = os.sockaddr_un{
|
||||
.family = os.AF_UNIX,
|
||||
.path = undefined,
|
||||
};
|
||||
var addr = try std.net.Address.initUnix(path);
|
||||
|
||||
if (path.len > sock_addr.path.len) return error.NameTooLong;
|
||||
mem.copy(u8, &sock_addr.path, path);
|
||||
|
||||
const size = @intCast(u32, @sizeOf(os.sockaddr_un) - sock_addr.path.len + path.len);
|
||||
try os.connect(sockfd, &sock_addr, size);
|
||||
try os.connect(
|
||||
sockfd,
|
||||
&addr.any,
|
||||
addr.getOsSockLen(),
|
||||
);
|
||||
|
||||
return fs.File.openHandle(sockfd);
|
||||
}
|
||||
|
||||
pub const AddressList = struct {
|
||||
arena: std.heap.ArenaAllocator,
|
||||
addrs: []IpAddress,
|
||||
addrs: []Address,
|
||||
canon_name: ?[]u8,
|
||||
|
||||
fn deinit(self: *AddressList) void {
|
||||
|
@ -381,7 +413,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16)
|
|||
return tcpConnectToAddress(addrs[0], port);
|
||||
}
|
||||
|
||||
pub fn tcpConnectToAddress(address: IpAddress) !fs.File {
|
||||
pub fn tcpConnectToAddress(address: Address) !fs.File {
|
||||
const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
|
||||
const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;
|
||||
const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP);
|
||||
|
@ -456,13 +488,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
|
|||
}
|
||||
break :blk count;
|
||||
};
|
||||
result.addrs = try arena.alloc(IpAddress, addr_count);
|
||||
result.addrs = try arena.alloc(Address, addr_count);
|
||||
|
||||
var it: ?*os.addrinfo = res;
|
||||
var i: usize = 0;
|
||||
while (it) |info| : (it = info.next) {
|
||||
const addr = info.addr orelse continue;
|
||||
result.addrs[i] = IpAddress.initPosix(@alignCast(4, addr));
|
||||
result.addrs[i] = Address.initPosix(@alignCast(4, addr));
|
||||
|
||||
if (info.canonname) |n| {
|
||||
if (result.canon_name == null) {
|
||||
|
@ -485,7 +517,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
|
|||
|
||||
try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port);
|
||||
|
||||
result.addrs = try arena.alloc(IpAddress, lookup_addrs.len);
|
||||
result.addrs = try arena.alloc(Address, lookup_addrs.len);
|
||||
if (!canon.isNull()) {
|
||||
result.canon_name = canon.toOwnedSlice();
|
||||
}
|
||||
|
@ -501,7 +533,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
|
|||
}
|
||||
|
||||
const LookupAddr = struct {
|
||||
addr: IpAddress,
|
||||
addr: Address,
|
||||
sortkey: i32 = 0,
|
||||
};
|
||||
|
||||
|
@ -524,7 +556,7 @@ fn linuxLookupName(
|
|||
if (opt_name) |name| {
|
||||
// reject empty name and check len so it fits into temp bufs
|
||||
try canon.replaceContents(name);
|
||||
if (IpAddress.parseExpectingFamily(name, family, port)) |addr| {
|
||||
if (Address.parseExpectingFamily(name, family, port)) |addr| {
|
||||
try addrs.append(LookupAddr{ .addr = addr });
|
||||
} else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {
|
||||
return name_err;
|
||||
|
@ -751,23 +783,23 @@ fn linuxLookupNameFromNull(
|
|||
if ((flags & std.c.AI_PASSIVE) != 0) {
|
||||
if (family != os.AF_INET6) {
|
||||
(try addrs.addOne()).* = LookupAddr{
|
||||
.addr = IpAddress.initIp4([1]u8{0} ** 4, port),
|
||||
.addr = Address.initIp4([1]u8{0} ** 4, port),
|
||||
};
|
||||
}
|
||||
if (family != os.AF_INET) {
|
||||
(try addrs.addOne()).* = LookupAddr{
|
||||
.addr = IpAddress.initIp6([1]u8{0} ** 16, port, 0, 0),
|
||||
.addr = Address.initIp6([1]u8{0} ** 16, port, 0, 0),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (family != os.AF_INET6) {
|
||||
(try addrs.addOne()).* = LookupAddr{
|
||||
.addr = IpAddress.initIp4([4]u8{ 127, 0, 0, 1 }, port),
|
||||
.addr = Address.initIp4([4]u8{ 127, 0, 0, 1 }, port),
|
||||
};
|
||||
}
|
||||
if (family != os.AF_INET) {
|
||||
(try addrs.addOne()).* = LookupAddr{
|
||||
.addr = IpAddress.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0),
|
||||
.addr = Address.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -812,7 +844,7 @@ fn linuxLookupNameFromHosts(
|
|||
}
|
||||
} else continue;
|
||||
|
||||
const addr = IpAddress.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) {
|
||||
const addr = Address.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) {
|
||||
error.Overflow,
|
||||
error.InvalidEnd,
|
||||
error.InvalidCharacter,
|
||||
|
@ -1033,7 +1065,7 @@ fn linuxLookupNameFromNumericUnspec(
|
|||
name: []const u8,
|
||||
port: u16,
|
||||
) !void {
|
||||
const addr = try IpAddress.parse(name, port);
|
||||
const addr = try Address.parseIp(name, port);
|
||||
(try addrs.addOne()).* = LookupAddr{ .addr = addr };
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1081,7 @@ fn resMSendRc(
|
|||
var sl: os.socklen_t = @sizeOf(os.sockaddr_in);
|
||||
var family: os.sa_family_t = os.AF_INET;
|
||||
|
||||
var ns_list = std.ArrayList(IpAddress).init(rc.ns.allocator);
|
||||
var ns_list = std.ArrayList(Address).init(rc.ns.allocator);
|
||||
defer ns_list.deinit();
|
||||
|
||||
try ns_list.resize(rc.ns.len);
|
||||
|
@ -1065,8 +1097,8 @@ fn resMSendRc(
|
|||
}
|
||||
|
||||
// Get local address and open/bind a socket
|
||||
var sa: IpAddress = undefined;
|
||||
@memset(@ptrCast([*]u8, &sa), 0, @sizeOf(IpAddress));
|
||||
var sa: Address = undefined;
|
||||
@memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
|
||||
sa.any.family = family;
|
||||
const flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK;
|
||||
const fd = os.socket(family, flags, 0) catch |err| switch (err) {
|
||||
|
@ -1224,7 +1256,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
|
|||
const new_addr = try ctx.addrs.addOne();
|
||||
new_addr.* = LookupAddr{
|
||||
// TODO slice [0..4] to make this *[4]u8 without @ptrCast
|
||||
.addr = IpAddress.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port),
|
||||
.addr = Address.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port),
|
||||
};
|
||||
},
|
||||
os.RR_AAAA => {
|
||||
|
@ -1232,7 +1264,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
|
|||
const new_addr = try ctx.addrs.addOne();
|
||||
new_addr.* = LookupAddr{
|
||||
// TODO slice [0..16] to make this *[16]u8 without @ptrCast
|
||||
.addr = IpAddress.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0),
|
||||
.addr = Address.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0),
|
||||
};
|
||||
},
|
||||
os.RR_CNAME => {
|
||||
|
@ -1248,12 +1280,12 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
|
|||
}
|
||||
}
|
||||
|
||||
pub const TcpServer = struct {
|
||||
pub const StreamServer = struct {
|
||||
/// Copied from `Options` on `init`.
|
||||
kernel_backlog: u32,
|
||||
|
||||
/// `undefined` until `listen` returns successfully.
|
||||
listen_address: IpAddress,
|
||||
listen_address: Address,
|
||||
|
||||
sockfd: ?os.fd_t,
|
||||
|
||||
|
@ -1266,24 +1298,26 @@ pub const TcpServer = struct {
|
|||
|
||||
/// After this call succeeds, resources have been acquired and must
|
||||
/// be released with `deinit`.
|
||||
pub fn init(options: Options) TcpServer {
|
||||
return TcpServer{
|
||||
pub fn init(options: Options) StreamServer {
|
||||
return StreamServer{
|
||||
.sockfd = null,
|
||||
.kernel_backlog = options.kernel_backlog,
|
||||
.listen_address = undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/// Release all resources. The `TcpServer` memory becomes `undefined`.
|
||||
pub fn deinit(self: *TcpServer) void {
|
||||
/// Release all resources. The `StreamServer` memory becomes `undefined`.
|
||||
pub fn deinit(self: *StreamServer) void {
|
||||
self.close();
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn listen(self: *TcpServer, address: IpAddress) !void {
|
||||
pub fn listen(self: *StreamServer, address: Address) !void {
|
||||
const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
|
||||
const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;
|
||||
const sockfd = try os.socket(os.AF_INET, sock_flags, os.IPPROTO_TCP);
|
||||
const proto = if (address.any.family == os.AF_UNIX) @as(u32, 0) else os.IPPROTO_TCP;
|
||||
|
||||
const sockfd = try os.socket(address.any.family, sock_flags, proto);
|
||||
self.sockfd = sockfd;
|
||||
errdefer {
|
||||
os.close(sockfd);
|
||||
|
@ -1299,7 +1333,7 @@ pub const TcpServer = struct {
|
|||
/// Stop listening. It is still necessary to call `deinit` after stopping listening.
|
||||
/// Calling `deinit` will automatically call `close`. It is safe to call `close` when
|
||||
/// not listening.
|
||||
pub fn close(self: *TcpServer) void {
|
||||
pub fn close(self: *StreamServer) void {
|
||||
if (self.sockfd) |fd| {
|
||||
os.close(fd);
|
||||
self.sockfd = null;
|
||||
|
@ -1327,11 +1361,11 @@ pub const TcpServer = struct {
|
|||
} || os.UnexpectedError;
|
||||
|
||||
/// If this function succeeds, the returned `fs.File` is a caller-managed resource.
|
||||
pub fn accept(self: *TcpServer) AcceptError!fs.File {
|
||||
pub fn accept(self: *StreamServer) AcceptError!fs.File {
|
||||
const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
|
||||
const accept_flags = nonblock | os.SOCK_CLOEXEC;
|
||||
var accepted_addr: IpAddress = undefined;
|
||||
var adr_len: os.socklen_t = @sizeOf(IpAddress);
|
||||
var accepted_addr: Address = undefined;
|
||||
var adr_len: os.socklen_t = @sizeOf(Address);
|
||||
if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
|
||||
return fs.File.openHandle(fd);
|
||||
} else |err| switch (err) {
|
||||
|
|
|
@ -28,17 +28,17 @@ test "parse and render IPv6 addresses" {
|
|||
"::ffff:123.5.123.5",
|
||||
};
|
||||
for (ips) |ip, i| {
|
||||
var addr = net.IpAddress.parseIp6(ip, 0) catch unreachable;
|
||||
var addr = net.Address.parseIp6(ip, 0) catch unreachable;
|
||||
var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;
|
||||
std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
|
||||
}
|
||||
|
||||
testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6(":::", 0));
|
||||
testing.expectError(error.Overflow, net.IpAddress.parseIp6("FF001::FB", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0));
|
||||
testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
|
||||
testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0));
|
||||
testing.expectError(error.InvalidIpv4Mapping, net.IpAddress.parseIp6("::123.123.123.123", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.Address.parseIp6(":::", 0));
|
||||
testing.expectError(error.Overflow, net.Address.parseIp6("FF001::FB", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.Address.parseIp6("FF01::Fb:zig", 0));
|
||||
testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
|
||||
testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
|
||||
testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
|
||||
}
|
||||
|
||||
test "parse and render IPv4 addresses" {
|
||||
|
@ -50,16 +50,16 @@ test "parse and render IPv4 addresses" {
|
|||
"123.255.0.91",
|
||||
"127.0.0.1",
|
||||
}) |ip| {
|
||||
var addr = net.IpAddress.parseIp4(ip, 0) catch unreachable;
|
||||
var addr = net.Address.parseIp4(ip, 0) catch unreachable;
|
||||
var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;
|
||||
std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
|
||||
}
|
||||
|
||||
testing.expectError(error.Overflow, net.IpAddress.parseIp4("256.0.0.1", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("x.0.0.1", 0));
|
||||
testing.expectError(error.InvalidEnd, net.IpAddress.parseIp4("127.0.0.1.1", 0));
|
||||
testing.expectError(error.Incomplete, net.IpAddress.parseIp4("127.0.0.", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("100..0.1", 0));
|
||||
testing.expectError(error.Overflow, net.Address.parseIp4("256.0.0.1", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.Address.parseIp4("x.0.0.1", 0));
|
||||
testing.expectError(error.InvalidEnd, net.Address.parseIp4("127.0.0.1.1", 0));
|
||||
testing.expectError(error.Incomplete, net.Address.parseIp4("127.0.0.", 0));
|
||||
testing.expectError(error.InvalidCharacter, net.Address.parseIp4("100..0.1", 0));
|
||||
}
|
||||
|
||||
test "resolve DNS" {
|
||||
|
@ -91,9 +91,9 @@ test "listen on a port, send bytes, receive bytes" {
|
|||
}
|
||||
|
||||
// TODO doing this at comptime crashed the compiler
|
||||
const localhost = net.IpAddress.parse("127.0.0.1", 0);
|
||||
const localhost = net.Address.parseIp("127.0.0.1", 0);
|
||||
|
||||
var server = net.TcpServer.init(net.TcpServer.Options{});
|
||||
var server = net.StreamServer.init(net.StreamServer.Options{});
|
||||
defer server.deinit();
|
||||
try server.listen(localhost);
|
||||
|
||||
|
@ -104,7 +104,7 @@ test "listen on a port, send bytes, receive bytes" {
|
|||
try await client_frame;
|
||||
}
|
||||
|
||||
fn testClient(addr: net.IpAddress) anyerror!void {
|
||||
fn testClient(addr: net.Address) anyerror!void {
|
||||
const socket_file = try net.tcpConnectToAddress(addr);
|
||||
defer socket_file.close();
|
||||
|
||||
|
@ -114,7 +114,7 @@ fn testClient(addr: net.IpAddress) anyerror!void {
|
|||
testing.expect(mem.eql(u8, msg, "hello from server\n"));
|
||||
}
|
||||
|
||||
fn testServer(server: *net.TcpServer) anyerror!void {
|
||||
fn testServer(server: *net.StreamServer) anyerror!void {
|
||||
var client_file = try server.accept();
|
||||
|
||||
const stream = &client_file.outStream().stream;
|
||||
|
|
|
@ -186,6 +186,11 @@ pub const sockaddr_in6 = extern struct {
|
|||
pub const in6_addr = [16]u8;
|
||||
pub const in_addr = u32;
|
||||
|
||||
pub const sockaddr_un = extern struct {
|
||||
family: sa_family_t = AF_UNIX,
|
||||
path: [108]u8,
|
||||
};
|
||||
|
||||
pub const AF_UNSPEC = 0;
|
||||
pub const AF_UNIX = 1;
|
||||
pub const AF_INET = 2;
|
||||
|
|
Loading…
Reference in New Issue