authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-10 20:40:19+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-11-10 20:40:19+00:00
log891e2149b0d72a511e58a994c3f66dff500e6615
treedadd50bf962f4e58a7a8b3613fcc9b69dc2687ba
parent98e37537d1fc290e3df35b03b41b036490ffdaee
parentc8a8da28049d2e9aece857359725b2a8f6d3732b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3635 from lun-4/unify-unix-sockets

std.net: add unix socket support to Address and StreamServer

3 files changed, 115 insertions(+), 76 deletions(-)

lib/std/net.zig+93-59
......@@ -10,15 +10,18 @@ test "" {
1010 _ = @import("net/test.zig");
1111}
1212
13pub const IpAddress = extern union {
13const has_unix_sockets = @hasDecl(os, "sockaddr_un");
14
15pub const Address = extern union {
1416 any: os.sockaddr,
1517 in: os.sockaddr_in,
1618 in6: os.sockaddr_in6,
19 un: if (has_unix_sockets) os.sockaddr_un else void,
1720
1821 // TODO this crashed the compiler
1922 //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0);
2023
21 pub fn parse(name: []const u8, port: u16) !IpAddress {
24 pub fn parseIp(name: []const u8, port: u16) !Address {
2225 if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {
2326 error.Overflow,
2427 error.InvalidEnd,
......@@ -39,17 +42,17 @@ pub const IpAddress = extern union {
3942 return error.InvalidIPAddressFormat;
4043 }
4144
42 pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !IpAddress {
45 pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !Address {
4346 switch (family) {
4447 os.AF_INET => return parseIp4(name, port),
4548 os.AF_INET6 => return parseIp6(name, port),
46 os.AF_UNSPEC => return parse(name, port),
49 os.AF_UNSPEC => return parseIp(name, port),
4750 else => unreachable,
4851 }
4952 }
5053
51 pub fn parseIp6(buf: []const u8, port: u16) !IpAddress {
52 var result = IpAddress{
54 pub fn parseIp6(buf: []const u8, port: u16) !Address {
55 var result = Address{
5356 .in6 = os.sockaddr_in6{
5457 .scope_id = 0,
5558 .port = mem.nativeToBig(u16, port),
......@@ -154,8 +157,8 @@ pub const IpAddress = extern union {
154157 }
155158 }
156159
157 pub fn parseIp4(buf: []const u8, port: u16) !IpAddress {
158 var result = IpAddress{
160 pub fn parseIp4(buf: []const u8, port: u16) !Address {
161 var result = Address{
159162 .in = os.sockaddr_in{
160163 .port = mem.nativeToBig(u16, port),
161164 .addr = undefined,
......@@ -194,8 +197,8 @@ pub const IpAddress = extern union {
194197 return error.Incomplete;
195198 }
196199
197 pub fn initIp4(addr: [4]u8, port: u16) IpAddress {
198 return IpAddress{
200 pub fn initIp4(addr: [4]u8, port: u16) Address {
201 return Address{
199202 .in = os.sockaddr_in{
200203 .port = mem.nativeToBig(u16, port),
201204 .addr = @ptrCast(*align(1) const u32, &addr).*,
......@@ -203,8 +206,8 @@ pub const IpAddress = extern union {
203206 };
204207 }
205208
206 pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) IpAddress {
207 return IpAddress{
209 pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Address {
210 return Address{
208211 .in6 = os.sockaddr_in6{
209212 .addr = addr,
210213 .port = mem.nativeToBig(u16, port),
......@@ -214,8 +217,24 @@ pub const IpAddress = extern union {
214217 };
215218 }
216219
220 pub fn initUnix(path: []const u8) !Address {
221 var sock_addr = os.sockaddr_un{
222 .family = os.AF_UNIX,
223 .path = undefined,
224 };
225
226 // this enables us to have the proper length of the socket in getOsSockLen
227 mem.set(u8, &sock_addr.path, 0);
228
229 if (path.len > sock_addr.path.len) return error.NameTooLong;
230 mem.copy(u8, &sock_addr.path, path);
231
232 return Address{ .un = sock_addr };
233 }
234
217235 /// Returns the port in native endian.
218 pub fn getPort(self: IpAddress) u16 {
236 /// Asserts that the address is ip4 or ip6.
237 pub fn getPort(self: Address) u16 {
219238 const big_endian_port = switch (self.any.family) {
220239 os.AF_INET => self.in.port,
221240 os.AF_INET6 => self.in6.port,
......@@ -225,7 +244,8 @@ pub const IpAddress = extern union {
225244 }
226245
227246 /// `port` is native-endian.
228 pub fn setPort(self: *IpAddress, port: u16) void {
247 /// Asserts that the address is ip4 or ip6.
248 pub fn setPort(self: *Address, port: u16) void {
229249 const ptr = switch (self.any.family) {
230250 os.AF_INET => &self.in.port,
231251 os.AF_INET6 => &self.in6.port,
......@@ -237,16 +257,16 @@ pub const IpAddress = extern union {
237257 /// Asserts that `addr` is an IP address.
238258 /// This function will read past the end of the pointer, with a size depending
239259 /// on the address family.
240 pub fn initPosix(addr: *align(4) const os.sockaddr) IpAddress {
260 pub fn initPosix(addr: *align(4) const os.sockaddr) Address {
241261 switch (addr.family) {
242 os.AF_INET => return IpAddress{ .in = @ptrCast(*const os.sockaddr_in, addr).* },
243 os.AF_INET6 => return IpAddress{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* },
262 os.AF_INET => return Address{ .in = @ptrCast(*const os.sockaddr_in, addr).* },
263 os.AF_INET6 => return Address{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* },
244264 else => unreachable,
245265 }
246266 }
247267
248268 pub fn format(
249 self: IpAddress,
269 self: Address,
250270 comptime fmt: []const u8,
251271 options: std.fmt.FormatOptions,
252272 context: var,
......@@ -314,20 +334,35 @@ pub const IpAddress = extern union {
314334 }
315335 try std.fmt.format(context, Errors, output, "]:{}", port);
316336 },
337 os.AF_UNIX => {
338 if (!has_unix_sockets) {
339 unreachable;
340 }
341
342 try std.fmt.format(context, Errors, output, "{}", self.un.path);
343 },
317344 else => unreachable,
318345 }
319346 }
320347
321 pub fn eql(a: IpAddress, b: IpAddress) bool {
348 pub fn eql(a: Address, b: Address) bool {
322349 const a_bytes = @ptrCast([*]const u8, &a.any)[0..a.getOsSockLen()];
323350 const b_bytes = @ptrCast([*]const u8, &b.any)[0..b.getOsSockLen()];
324351 return mem.eql(u8, a_bytes, b_bytes);
325352 }
326353
327 fn getOsSockLen(self: IpAddress) os.socklen_t {
354 fn getOsSockLen(self: Address) os.socklen_t {
328355 switch (self.any.family) {
329356 os.AF_INET => return @sizeOf(os.sockaddr_in),
330357 os.AF_INET6 => return @sizeOf(os.sockaddr_in6),
358 os.AF_UNIX => {
359 if (!has_unix_sockets) {
360 unreachable;
361 }
362
363 const path_len = std.mem.len(u8, &self.un.path);
364 return @intCast(os.socklen_t, @sizeOf(os.sockaddr_un) - self.un.path.len + path_len);
365 },
331366 else => unreachable,
332367 }
333368 }
......@@ -342,23 +377,20 @@ pub fn connectUnixSocket(path: []const u8) !fs.File {
342377 );
343378 errdefer os.close(sockfd);
344379
345 var sock_addr = os.sockaddr_un{
346 .family = os.AF_UNIX,
347 .path = undefined,
348 };
349
350 if (path.len > sock_addr.path.len) return error.NameTooLong;
351 mem.copy(u8, &sock_addr.path, path);
380 var addr = try std.net.Address.initUnix(path);
352381
353 const size = @intCast(u32, @sizeOf(os.sockaddr_un) - sock_addr.path.len + path.len);
354 try os.connect(sockfd, &sock_addr, size);
382 try os.connect(
383 sockfd,
384 &addr.any,
385 addr.getOsSockLen(),
386 );
355387
356388 return fs.File.openHandle(sockfd);
357389}
358390
359391pub const AddressList = struct {
360392 arena: std.heap.ArenaAllocator,
361 addrs: []IpAddress,
393 addrs: []Address,
362394 canon_name: ?[]u8,
363395
364396 fn deinit(self: *AddressList) void {
......@@ -381,7 +413,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16)
381413 return tcpConnectToAddress(addrs[0], port);
382414}
383415
384pub fn tcpConnectToAddress(address: IpAddress) !fs.File {
416pub fn tcpConnectToAddress(address: Address) !fs.File {
385417 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
386418 const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;
387419 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) !*
456488 }
457489 break :blk count;
458490 };
459 result.addrs = try arena.alloc(IpAddress, addr_count);
491 result.addrs = try arena.alloc(Address, addr_count);
460492
461493 var it: ?*os.addrinfo = res;
462494 var i: usize = 0;
463495 while (it) |info| : (it = info.next) {
464496 const addr = info.addr orelse continue;
465 result.addrs[i] = IpAddress.initPosix(@alignCast(4, addr));
497 result.addrs[i] = Address.initPosix(@alignCast(4, addr));
466498
467499 if (info.canonname) |n| {
468500 if (result.canon_name == null) {
......@@ -485,7 +517,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
485517
486518 try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port);
487519
488 result.addrs = try arena.alloc(IpAddress, lookup_addrs.len);
520 result.addrs = try arena.alloc(Address, lookup_addrs.len);
489521 if (!canon.isNull()) {
490522 result.canon_name = canon.toOwnedSlice();
491523 }
......@@ -501,7 +533,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
501533}
502534
503535const LookupAddr = struct {
504 addr: IpAddress,
536 addr: Address,
505537 sortkey: i32 = 0,
506538};
507539
......@@ -524,7 +556,7 @@ fn linuxLookupName(
524556 if (opt_name) |name| {
525557 // reject empty name and check len so it fits into temp bufs
526558 try canon.replaceContents(name);
527 if (IpAddress.parseExpectingFamily(name, family, port)) |addr| {
559 if (Address.parseExpectingFamily(name, family, port)) |addr| {
528560 try addrs.append(LookupAddr{ .addr = addr });
529561 } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {
530562 return name_err;
......@@ -751,23 +783,23 @@ fn linuxLookupNameFromNull(
751783 if ((flags & std.c.AI_PASSIVE) != 0) {
752784 if (family != os.AF_INET6) {
753785 (try addrs.addOne()).* = LookupAddr{
754 .addr = IpAddress.initIp4([1]u8{0} ** 4, port),
786 .addr = Address.initIp4([1]u8{0} ** 4, port),
755787 };
756788 }
757789 if (family != os.AF_INET) {
758790 (try addrs.addOne()).* = LookupAddr{
759 .addr = IpAddress.initIp6([1]u8{0} ** 16, port, 0, 0),
791 .addr = Address.initIp6([1]u8{0} ** 16, port, 0, 0),
760792 };
761793 }
762794 } else {
763795 if (family != os.AF_INET6) {
764796 (try addrs.addOne()).* = LookupAddr{
765 .addr = IpAddress.initIp4([4]u8{ 127, 0, 0, 1 }, port),
797 .addr = Address.initIp4([4]u8{ 127, 0, 0, 1 }, port),
766798 };
767799 }
768800 if (family != os.AF_INET) {
769801 (try addrs.addOne()).* = LookupAddr{
770 .addr = IpAddress.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0),
802 .addr = Address.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0),
771803 };
772804 }
773805 }
......@@ -812,7 +844,7 @@ fn linuxLookupNameFromHosts(
812844 }
813845 } else continue;
814846
815 const addr = IpAddress.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) {
847 const addr = Address.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) {
816848 error.Overflow,
817849 error.InvalidEnd,
818850 error.InvalidCharacter,
......@@ -1033,7 +1065,7 @@ fn linuxLookupNameFromNumericUnspec(
10331065 name: []const u8,
10341066 port: u16,
10351067) !void {
1036 const addr = try IpAddress.parse(name, port);
1068 const addr = try Address.parseIp(name, port);
10371069 (try addrs.addOne()).* = LookupAddr{ .addr = addr };
10381070}
10391071
......@@ -1049,7 +1081,7 @@ fn resMSendRc(
10491081 var sl: os.socklen_t = @sizeOf(os.sockaddr_in);
10501082 var family: os.sa_family_t = os.AF_INET;
10511083
1052 var ns_list = std.ArrayList(IpAddress).init(rc.ns.allocator);
1084 var ns_list = std.ArrayList(Address).init(rc.ns.allocator);
10531085 defer ns_list.deinit();
10541086
10551087 try ns_list.resize(rc.ns.len);
......@@ -1065,8 +1097,8 @@ fn resMSendRc(
10651097 }
10661098
10671099 // Get local address and open/bind a socket
1068 var sa: IpAddress = undefined;
1069 @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(IpAddress));
1100 var sa: Address = undefined;
1101 @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
10701102 sa.any.family = family;
10711103 const flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK;
10721104 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)
12241256 const new_addr = try ctx.addrs.addOne();
12251257 new_addr.* = LookupAddr{
12261258 // TODO slice [0..4] to make this *[4]u8 without @ptrCast
1227 .addr = IpAddress.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port),
1259 .addr = Address.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port),
12281260 };
12291261 },
12301262 os.RR_AAAA => {
......@@ -1232,7 +1264,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
12321264 const new_addr = try ctx.addrs.addOne();
12331265 new_addr.* = LookupAddr{
12341266 // TODO slice [0..16] to make this *[16]u8 without @ptrCast
1235 .addr = IpAddress.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0),
1267 .addr = Address.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0),
12361268 };
12371269 },
12381270 os.RR_CNAME => {
......@@ -1248,12 +1280,12 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
12481280 }
12491281}
12501282
1251pub const TcpServer = struct {
1283pub const StreamServer = struct {
12521284 /// Copied from `Options` on `init`.
12531285 kernel_backlog: u32,
12541286
12551287 /// `undefined` until `listen` returns successfully.
1256 listen_address: IpAddress,
1288 listen_address: Address,
12571289
12581290 sockfd: ?os.fd_t,
12591291
......@@ -1266,24 +1298,26 @@ pub const TcpServer = struct {
12661298
12671299 /// After this call succeeds, resources have been acquired and must
12681300 /// be released with `deinit`.
1269 pub fn init(options: Options) TcpServer {
1270 return TcpServer{
1301 pub fn init(options: Options) StreamServer {
1302 return StreamServer{
12711303 .sockfd = null,
12721304 .kernel_backlog = options.kernel_backlog,
12731305 .listen_address = undefined,
12741306 };
12751307 }
12761308
1277 /// Release all resources. The `TcpServer` memory becomes `undefined`.
1278 pub fn deinit(self: *TcpServer) void {
1309 /// Release all resources. The `StreamServer` memory becomes `undefined`.
1310 pub fn deinit(self: *StreamServer) void {
12791311 self.close();
12801312 self.* = undefined;
12811313 }
12821314
1283 pub fn listen(self: *TcpServer, address: IpAddress) !void {
1315 pub fn listen(self: *StreamServer, address: Address) !void {
12841316 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
12851317 const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;
1286 const sockfd = try os.socket(os.AF_INET, sock_flags, os.IPPROTO_TCP);
1318 const proto = if (address.any.family == os.AF_UNIX) @as(u32, 0) else os.IPPROTO_TCP;
1319
1320 const sockfd = try os.socket(address.any.family, sock_flags, proto);
12871321 self.sockfd = sockfd;
12881322 errdefer {
12891323 os.close(sockfd);
......@@ -1299,7 +1333,7 @@ pub const TcpServer = struct {
12991333 /// Stop listening. It is still necessary to call `deinit` after stopping listening.
13001334 /// Calling `deinit` will automatically call `close`. It is safe to call `close` when
13011335 /// not listening.
1302 pub fn close(self: *TcpServer) void {
1336 pub fn close(self: *StreamServer) void {
13031337 if (self.sockfd) |fd| {
13041338 os.close(fd);
13051339 self.sockfd = null;
......@@ -1327,11 +1361,11 @@ pub const TcpServer = struct {
13271361 } || os.UnexpectedError;
13281362
13291363 /// If this function succeeds, the returned `fs.File` is a caller-managed resource.
1330 pub fn accept(self: *TcpServer) AcceptError!fs.File {
1364 pub fn accept(self: *StreamServer) AcceptError!fs.File {
13311365 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
13321366 const accept_flags = nonblock | os.SOCK_CLOEXEC;
1333 var accepted_addr: IpAddress = undefined;
1334 var adr_len: os.socklen_t = @sizeOf(IpAddress);
1367 var accepted_addr: Address = undefined;
1368 var adr_len: os.socklen_t = @sizeOf(Address);
13351369 if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
13361370 return fs.File.openHandle(fd);
13371371 } else |err| switch (err) {
lib/std/net/test.zig+17-17
......@@ -28,17 +28,17 @@ test "parse and render IPv6 addresses" {
2828 "::ffff:123.5.123.5",
2929 };
3030 for (ips) |ip, i| {
31 var addr = net.IpAddress.parseIp6(ip, 0) catch unreachable;
31 var addr = net.Address.parseIp6(ip, 0) catch unreachable;
3232 var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;
3333 std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
3434 }
3535
36 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6(":::", 0));
37 testing.expectError(error.Overflow, net.IpAddress.parseIp6("FF001::FB", 0));
38 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0));
39 testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
40 testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0));
41 testing.expectError(error.InvalidIpv4Mapping, net.IpAddress.parseIp6("::123.123.123.123", 0));
36 testing.expectError(error.InvalidCharacter, net.Address.parseIp6(":::", 0));
37 testing.expectError(error.Overflow, net.Address.parseIp6("FF001::FB", 0));
38 testing.expectError(error.InvalidCharacter, net.Address.parseIp6("FF01::Fb:zig", 0));
39 testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
40 testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
41 testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
4242}
4343
4444test "parse and render IPv4 addresses" {
......@@ -50,16 +50,16 @@ test "parse and render IPv4 addresses" {
5050 "123.255.0.91",
5151 "127.0.0.1",
5252 }) |ip| {
53 var addr = net.IpAddress.parseIp4(ip, 0) catch unreachable;
53 var addr = net.Address.parseIp4(ip, 0) catch unreachable;
5454 var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;
5555 std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
5656 }
5757
58 testing.expectError(error.Overflow, net.IpAddress.parseIp4("256.0.0.1", 0));
59 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("x.0.0.1", 0));
60 testing.expectError(error.InvalidEnd, net.IpAddress.parseIp4("127.0.0.1.1", 0));
61 testing.expectError(error.Incomplete, net.IpAddress.parseIp4("127.0.0.", 0));
62 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("100..0.1", 0));
58 testing.expectError(error.Overflow, net.Address.parseIp4("256.0.0.1", 0));
59 testing.expectError(error.InvalidCharacter, net.Address.parseIp4("x.0.0.1", 0));
60 testing.expectError(error.InvalidEnd, net.Address.parseIp4("127.0.0.1.1", 0));
61 testing.expectError(error.Incomplete, net.Address.parseIp4("127.0.0.", 0));
62 testing.expectError(error.InvalidCharacter, net.Address.parseIp4("100..0.1", 0));
6363}
6464
6565test "resolve DNS" {
......@@ -91,9 +91,9 @@ test "listen on a port, send bytes, receive bytes" {
9191 }
9292
9393 // TODO doing this at comptime crashed the compiler
94 const localhost = net.IpAddress.parse("127.0.0.1", 0);
94 const localhost = net.Address.parseIp("127.0.0.1", 0);
9595
96 var server = net.TcpServer.init(net.TcpServer.Options{});
96 var server = net.StreamServer.init(net.StreamServer.Options{});
9797 defer server.deinit();
9898 try server.listen(localhost);
9999
......@@ -104,7 +104,7 @@ test "listen on a port, send bytes, receive bytes" {
104104 try await client_frame;
105105}
106106
107fn testClient(addr: net.IpAddress) anyerror!void {
107fn testClient(addr: net.Address) anyerror!void {
108108 const socket_file = try net.tcpConnectToAddress(addr);
109109 defer socket_file.close();
110110
......@@ -114,7 +114,7 @@ fn testClient(addr: net.IpAddress) anyerror!void {
114114 testing.expect(mem.eql(u8, msg, "hello from server\n"));
115115}
116116
117fn testServer(server: *net.TcpServer) anyerror!void {
117fn testServer(server: *net.StreamServer) anyerror!void {
118118 var client_file = try server.accept();
119119
120120 const stream = &client_file.outStream().stream;
lib/std/os/bits/windows.zig+5
......@@ -186,6 +186,11 @@ pub const sockaddr_in6 = extern struct {
186186pub const in6_addr = [16]u8;
187187pub const in_addr = u32;
188188
189pub const sockaddr_un = extern struct {
190 family: sa_family_t = AF_UNIX,
191 path: [108]u8,
192};
193
189194pub const AF_UNSPEC = 0;
190195pub const AF_UNIX = 1;
191196pub const AF_INET = 2;