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 "" {...@@ -10,15 +10,18 @@ test "" {
10 _ = @import("net/test.zig");10 _ = @import("net/test.zig");
11}11}
1212
13pub const IpAddress = extern union {13const has_unix_sockets = @hasDecl(os, "sockaddr_un");
14
15pub const Address = extern union {
14 any: os.sockaddr,16 any: os.sockaddr,
15 in: os.sockaddr_in,17 in: os.sockaddr_in,
16 in6: os.sockaddr_in6,18 in6: os.sockaddr_in6,
19 un: if (has_unix_sockets) os.sockaddr_un else void,
1720
18 // TODO this crashed the compiler21 // TODO this crashed the compiler
19 //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0);22 //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 {
22 if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {25 if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {
23 error.Overflow,26 error.Overflow,
24 error.InvalidEnd,27 error.InvalidEnd,
...@@ -39,17 +42,17 @@ pub const IpAddress = extern union {...@@ -39,17 +42,17 @@ pub const IpAddress = extern union {
39 return error.InvalidIPAddressFormat;42 return error.InvalidIPAddressFormat;
40 }43 }
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 {
43 switch (family) {46 switch (family) {
44 os.AF_INET => return parseIp4(name, port),47 os.AF_INET => return parseIp4(name, port),
45 os.AF_INET6 => return parseIp6(name, port),48 os.AF_INET6 => return parseIp6(name, port),
46 os.AF_UNSPEC => return parse(name, port),49 os.AF_UNSPEC => return parseIp(name, port),
47 else => unreachable,50 else => unreachable,
48 }51 }
49 }52 }
5053
51 pub fn parseIp6(buf: []const u8, port: u16) !IpAddress {54 pub fn parseIp6(buf: []const u8, port: u16) !Address {
52 var result = IpAddress{55 var result = Address{
53 .in6 = os.sockaddr_in6{56 .in6 = os.sockaddr_in6{
54 .scope_id = 0,57 .scope_id = 0,
55 .port = mem.nativeToBig(u16, port),58 .port = mem.nativeToBig(u16, port),
...@@ -154,8 +157,8 @@ pub const IpAddress = extern union {...@@ -154,8 +157,8 @@ pub const IpAddress = extern union {
154 }157 }
155 }158 }
156159
157 pub fn parseIp4(buf: []const u8, port: u16) !IpAddress {160 pub fn parseIp4(buf: []const u8, port: u16) !Address {
158 var result = IpAddress{161 var result = Address{
159 .in = os.sockaddr_in{162 .in = os.sockaddr_in{
160 .port = mem.nativeToBig(u16, port),163 .port = mem.nativeToBig(u16, port),
161 .addr = undefined,164 .addr = undefined,
...@@ -194,8 +197,8 @@ pub const IpAddress = extern union {...@@ -194,8 +197,8 @@ pub const IpAddress = extern union {
194 return error.Incomplete;197 return error.Incomplete;
195 }198 }
196199
197 pub fn initIp4(addr: [4]u8, port: u16) IpAddress {200 pub fn initIp4(addr: [4]u8, port: u16) Address {
198 return IpAddress{201 return Address{
199 .in = os.sockaddr_in{202 .in = os.sockaddr_in{
200 .port = mem.nativeToBig(u16, port),203 .port = mem.nativeToBig(u16, port),
201 .addr = @ptrCast(*align(1) const u32, &addr).*,204 .addr = @ptrCast(*align(1) const u32, &addr).*,
...@@ -203,8 +206,8 @@ pub const IpAddress = extern union {...@@ -203,8 +206,8 @@ pub const IpAddress = extern union {
203 };206 };
204 }207 }
205208
206 pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) IpAddress {209 pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Address {
207 return IpAddress{210 return Address{
208 .in6 = os.sockaddr_in6{211 .in6 = os.sockaddr_in6{
209 .addr = addr,212 .addr = addr,
210 .port = mem.nativeToBig(u16, port),213 .port = mem.nativeToBig(u16, port),
...@@ -214,8 +217,24 @@ pub const IpAddress = extern union {...@@ -214,8 +217,24 @@ pub const IpAddress = extern union {
214 };217 };
215 }218 }
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
217 /// Returns the port in native endian.235 /// 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 {
219 const big_endian_port = switch (self.any.family) {238 const big_endian_port = switch (self.any.family) {
220 os.AF_INET => self.in.port,239 os.AF_INET => self.in.port,
221 os.AF_INET6 => self.in6.port,240 os.AF_INET6 => self.in6.port,
...@@ -225,7 +244,8 @@ pub const IpAddress = extern union {...@@ -225,7 +244,8 @@ pub const IpAddress = extern union {
225 }244 }
226245
227 /// `port` is native-endian.246 /// `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 {
229 const ptr = switch (self.any.family) {249 const ptr = switch (self.any.family) {
230 os.AF_INET => &self.in.port,250 os.AF_INET => &self.in.port,
231 os.AF_INET6 => &self.in6.port,251 os.AF_INET6 => &self.in6.port,
...@@ -237,16 +257,16 @@ pub const IpAddress = extern union {...@@ -237,16 +257,16 @@ pub const IpAddress = extern union {
237 /// Asserts that `addr` is an IP address.257 /// Asserts that `addr` is an IP address.
238 /// This function will read past the end of the pointer, with a size depending258 /// This function will read past the end of the pointer, with a size depending
239 /// on the address family.259 /// 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 {
241 switch (addr.family) {261 switch (addr.family) {
242 os.AF_INET => return IpAddress{ .in = @ptrCast(*const os.sockaddr_in, addr).* },262 os.AF_INET => return Address{ .in = @ptrCast(*const os.sockaddr_in, addr).* },
243 os.AF_INET6 => return IpAddress{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* },263 os.AF_INET6 => return Address{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* },
244 else => unreachable,264 else => unreachable,
245 }265 }
246 }266 }
247267
248 pub fn format(268 pub fn format(
249 self: IpAddress,269 self: Address,
250 comptime fmt: []const u8,270 comptime fmt: []const u8,
251 options: std.fmt.FormatOptions,271 options: std.fmt.FormatOptions,
252 context: var,272 context: var,
...@@ -314,20 +334,35 @@ pub const IpAddress = extern union {...@@ -314,20 +334,35 @@ pub const IpAddress = extern union {
314 }334 }
315 try std.fmt.format(context, Errors, output, "]:{}", port);335 try std.fmt.format(context, Errors, output, "]:{}", port);
316 },336 },
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 },
317 else => unreachable,344 else => unreachable,
318 }345 }
319 }346 }
320347
321 pub fn eql(a: IpAddress, b: IpAddress) bool {348 pub fn eql(a: Address, b: Address) bool {
322 const a_bytes = @ptrCast([*]const u8, &a.any)[0..a.getOsSockLen()];349 const a_bytes = @ptrCast([*]const u8, &a.any)[0..a.getOsSockLen()];
323 const b_bytes = @ptrCast([*]const u8, &b.any)[0..b.getOsSockLen()];350 const b_bytes = @ptrCast([*]const u8, &b.any)[0..b.getOsSockLen()];
324 return mem.eql(u8, a_bytes, b_bytes);351 return mem.eql(u8, a_bytes, b_bytes);
325 }352 }
326353
327 fn getOsSockLen(self: IpAddress) os.socklen_t {354 fn getOsSockLen(self: Address) os.socklen_t {
328 switch (self.any.family) {355 switch (self.any.family) {
329 os.AF_INET => return @sizeOf(os.sockaddr_in),356 os.AF_INET => return @sizeOf(os.sockaddr_in),
330 os.AF_INET6 => return @sizeOf(os.sockaddr_in6),357 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 },
331 else => unreachable,366 else => unreachable,
332 }367 }
333 }368 }
...@@ -342,23 +377,20 @@ pub fn connectUnixSocket(path: []const u8) !fs.File {...@@ -342,23 +377,20 @@ pub fn connectUnixSocket(path: []const u8) !fs.File {
342 );377 );
343 errdefer os.close(sockfd);378 errdefer os.close(sockfd);
344379
345 var sock_addr = os.sockaddr_un{380 var addr = try std.net.Address.initUnix(path);
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);
352381
353 const size = @intCast(u32, @sizeOf(os.sockaddr_un) - sock_addr.path.len + path.len);382 try os.connect(
354 try os.connect(sockfd, &sock_addr, size);383 sockfd,
384 &addr.any,
385 addr.getOsSockLen(),
386 );
355387
356 return fs.File.openHandle(sockfd);388 return fs.File.openHandle(sockfd);
357}389}
358390
359pub const AddressList = struct {391pub const AddressList = struct {
360 arena: std.heap.ArenaAllocator,392 arena: std.heap.ArenaAllocator,
361 addrs: []IpAddress,393 addrs: []Address,
362 canon_name: ?[]u8,394 canon_name: ?[]u8,
363395
364 fn deinit(self: *AddressList) void {396 fn deinit(self: *AddressList) void {
...@@ -381,7 +413,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16)...@@ -381,7 +413,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16)
381 return tcpConnectToAddress(addrs[0], port);413 return tcpConnectToAddress(addrs[0], port);
382}414}
383415
384pub fn tcpConnectToAddress(address: IpAddress) !fs.File {416pub fn tcpConnectToAddress(address: Address) !fs.File {
385 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;417 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
386 const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;418 const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;
387 const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP);419 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) !*...@@ -456,13 +488,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
456 }488 }
457 break :blk count;489 break :blk count;
458 };490 };
459 result.addrs = try arena.alloc(IpAddress, addr_count);491 result.addrs = try arena.alloc(Address, addr_count);
460492
461 var it: ?*os.addrinfo = res;493 var it: ?*os.addrinfo = res;
462 var i: usize = 0;494 var i: usize = 0;
463 while (it) |info| : (it = info.next) {495 while (it) |info| : (it = info.next) {
464 const addr = info.addr orelse continue;496 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
467 if (info.canonname) |n| {499 if (info.canonname) |n| {
468 if (result.canon_name == null) {500 if (result.canon_name == null) {
...@@ -485,7 +517,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -485,7 +517,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
485517
486 try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port);518 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);
489 if (!canon.isNull()) {521 if (!canon.isNull()) {
490 result.canon_name = canon.toOwnedSlice();522 result.canon_name = canon.toOwnedSlice();
491 }523 }
...@@ -501,7 +533,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -501,7 +533,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
501}533}
502534
503const LookupAddr = struct {535const LookupAddr = struct {
504 addr: IpAddress,536 addr: Address,
505 sortkey: i32 = 0,537 sortkey: i32 = 0,
506};538};
507539
...@@ -524,7 +556,7 @@ fn linuxLookupName(...@@ -524,7 +556,7 @@ fn linuxLookupName(
524 if (opt_name) |name| {556 if (opt_name) |name| {
525 // reject empty name and check len so it fits into temp bufs557 // reject empty name and check len so it fits into temp bufs
526 try canon.replaceContents(name);558 try canon.replaceContents(name);
527 if (IpAddress.parseExpectingFamily(name, family, port)) |addr| {559 if (Address.parseExpectingFamily(name, family, port)) |addr| {
528 try addrs.append(LookupAddr{ .addr = addr });560 try addrs.append(LookupAddr{ .addr = addr });
529 } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {561 } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {
530 return name_err;562 return name_err;
...@@ -751,23 +783,23 @@ fn linuxLookupNameFromNull(...@@ -751,23 +783,23 @@ fn linuxLookupNameFromNull(
751 if ((flags & std.c.AI_PASSIVE) != 0) {783 if ((flags & std.c.AI_PASSIVE) != 0) {
752 if (family != os.AF_INET6) {784 if (family != os.AF_INET6) {
753 (try addrs.addOne()).* = LookupAddr{785 (try addrs.addOne()).* = LookupAddr{
754 .addr = IpAddress.initIp4([1]u8{0} ** 4, port),786 .addr = Address.initIp4([1]u8{0} ** 4, port),
755 };787 };
756 }788 }
757 if (family != os.AF_INET) {789 if (family != os.AF_INET) {
758 (try addrs.addOne()).* = LookupAddr{790 (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),
760 };792 };
761 }793 }
762 } else {794 } else {
763 if (family != os.AF_INET6) {795 if (family != os.AF_INET6) {
764 (try addrs.addOne()).* = LookupAddr{796 (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),
766 };798 };
767 }799 }
768 if (family != os.AF_INET) {800 if (family != os.AF_INET) {
769 (try addrs.addOne()).* = LookupAddr{801 (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),
771 };803 };
772 }804 }
773 }805 }
...@@ -812,7 +844,7 @@ fn linuxLookupNameFromHosts(...@@ -812,7 +844,7 @@ fn linuxLookupNameFromHosts(
812 }844 }
813 } else continue;845 } 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) {
816 error.Overflow,848 error.Overflow,
817 error.InvalidEnd,849 error.InvalidEnd,
818 error.InvalidCharacter,850 error.InvalidCharacter,
...@@ -1033,7 +1065,7 @@ fn linuxLookupNameFromNumericUnspec(...@@ -1033,7 +1065,7 @@ fn linuxLookupNameFromNumericUnspec(
1033 name: []const u8,1065 name: []const u8,
1034 port: u16,1066 port: u16,
1035) !void {1067) !void {
1036 const addr = try IpAddress.parse(name, port);1068 const addr = try Address.parseIp(name, port);
1037 (try addrs.addOne()).* = LookupAddr{ .addr = addr };1069 (try addrs.addOne()).* = LookupAddr{ .addr = addr };
1038}1070}
10391071
...@@ -1049,7 +1081,7 @@ fn resMSendRc(...@@ -1049,7 +1081,7 @@ fn resMSendRc(
1049 var sl: os.socklen_t = @sizeOf(os.sockaddr_in);1081 var sl: os.socklen_t = @sizeOf(os.sockaddr_in);
1050 var family: os.sa_family_t = os.AF_INET;1082 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);
1053 defer ns_list.deinit();1085 defer ns_list.deinit();
10541086
1055 try ns_list.resize(rc.ns.len);1087 try ns_list.resize(rc.ns.len);
...@@ -1065,8 +1097,8 @@ fn resMSendRc(...@@ -1065,8 +1097,8 @@ fn resMSendRc(
1065 }1097 }
10661098
1067 // Get local address and open/bind a socket1099 // Get local address and open/bind a socket
1068 var sa: IpAddress = undefined;1100 var sa: Address = undefined;
1069 @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(IpAddress));1101 @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
1070 sa.any.family = family;1102 sa.any.family = family;
1071 const flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK;1103 const flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK;
1072 const fd = os.socket(family, flags, 0) catch |err| switch (err) {1104 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)...@@ -1224,7 +1256,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
1224 const new_addr = try ctx.addrs.addOne();1256 const new_addr = try ctx.addrs.addOne();
1225 new_addr.* = LookupAddr{1257 new_addr.* = LookupAddr{
1226 // TODO slice [0..4] to make this *[4]u8 without @ptrCast1258 // 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),
1228 };1260 };
1229 },1261 },
1230 os.RR_AAAA => {1262 os.RR_AAAA => {
...@@ -1232,7 +1264,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)...@@ -1232,7 +1264,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
1232 const new_addr = try ctx.addrs.addOne();1264 const new_addr = try ctx.addrs.addOne();
1233 new_addr.* = LookupAddr{1265 new_addr.* = LookupAddr{
1234 // TODO slice [0..16] to make this *[16]u8 without @ptrCast1266 // 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),
1236 };1268 };
1237 },1269 },
1238 os.RR_CNAME => {1270 os.RR_CNAME => {
...@@ -1248,12 +1280,12 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)...@@ -1248,12 +1280,12 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
1248 }1280 }
1249}1281}
12501282
1251pub const TcpServer = struct {1283pub const StreamServer = struct {
1252 /// Copied from `Options` on `init`.1284 /// Copied from `Options` on `init`.
1253 kernel_backlog: u32,1285 kernel_backlog: u32,
12541286
1255 /// `undefined` until `listen` returns successfully.1287 /// `undefined` until `listen` returns successfully.
1256 listen_address: IpAddress,1288 listen_address: Address,
12571289
1258 sockfd: ?os.fd_t,1290 sockfd: ?os.fd_t,
12591291
...@@ -1266,24 +1298,26 @@ pub const TcpServer = struct {...@@ -1266,24 +1298,26 @@ pub const TcpServer = struct {
12661298
1267 /// After this call succeeds, resources have been acquired and must1299 /// After this call succeeds, resources have been acquired and must
1268 /// be released with `deinit`.1300 /// be released with `deinit`.
1269 pub fn init(options: Options) TcpServer {1301 pub fn init(options: Options) StreamServer {
1270 return TcpServer{1302 return StreamServer{
1271 .sockfd = null,1303 .sockfd = null,
1272 .kernel_backlog = options.kernel_backlog,1304 .kernel_backlog = options.kernel_backlog,
1273 .listen_address = undefined,1305 .listen_address = undefined,
1274 };1306 };
1275 }1307 }
12761308
1277 /// Release all resources. The `TcpServer` memory becomes `undefined`.1309 /// Release all resources. The `StreamServer` memory becomes `undefined`.
1278 pub fn deinit(self: *TcpServer) void {1310 pub fn deinit(self: *StreamServer) void {
1279 self.close();1311 self.close();
1280 self.* = undefined;1312 self.* = undefined;
1281 }1313 }
12821314
1283 pub fn listen(self: *TcpServer, address: IpAddress) !void {1315 pub fn listen(self: *StreamServer, address: Address) !void {
1284 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;1316 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
1285 const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock;1317 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);
1287 self.sockfd = sockfd;1321 self.sockfd = sockfd;
1288 errdefer {1322 errdefer {
1289 os.close(sockfd);1323 os.close(sockfd);
...@@ -1299,7 +1333,7 @@ pub const TcpServer = struct {...@@ -1299,7 +1333,7 @@ pub const TcpServer = struct {
1299 /// Stop listening. It is still necessary to call `deinit` after stopping listening.1333 /// Stop listening. It is still necessary to call `deinit` after stopping listening.
1300 /// Calling `deinit` will automatically call `close`. It is safe to call `close` when1334 /// Calling `deinit` will automatically call `close`. It is safe to call `close` when
1301 /// not listening.1335 /// not listening.
1302 pub fn close(self: *TcpServer) void {1336 pub fn close(self: *StreamServer) void {
1303 if (self.sockfd) |fd| {1337 if (self.sockfd) |fd| {
1304 os.close(fd);1338 os.close(fd);
1305 self.sockfd = null;1339 self.sockfd = null;
...@@ -1327,11 +1361,11 @@ pub const TcpServer = struct {...@@ -1327,11 +1361,11 @@ pub const TcpServer = struct {
1327 } || os.UnexpectedError;1361 } || os.UnexpectedError;
13281362
1329 /// If this function succeeds, the returned `fs.File` is a caller-managed resource.1363 /// 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 {
1331 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;1365 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
1332 const accept_flags = nonblock | os.SOCK_CLOEXEC;1366 const accept_flags = nonblock | os.SOCK_CLOEXEC;
1333 var accepted_addr: IpAddress = undefined;1367 var accepted_addr: Address = undefined;
1334 var adr_len: os.socklen_t = @sizeOf(IpAddress);1368 var adr_len: os.socklen_t = @sizeOf(Address);
1335 if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {1369 if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
1336 return fs.File.openHandle(fd);1370 return fs.File.openHandle(fd);
1337 } else |err| switch (err) {1371 } else |err| switch (err) {
lib/std/net/test.zig+17-17
...@@ -28,17 +28,17 @@ test "parse and render IPv6 addresses" {...@@ -28,17 +28,17 @@ test "parse and render IPv6 addresses" {
28 "::ffff:123.5.123.5",28 "::ffff:123.5.123.5",
29 };29 };
30 for (ips) |ip, i| {30 for (ips) |ip, i| {
31 var addr = net.IpAddress.parseIp6(ip, 0) catch unreachable;31 var addr = net.Address.parseIp6(ip, 0) catch unreachable;
32 var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;32 var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;
33 std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));33 std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
34 }34 }
3535
36 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6(":::", 0));36 testing.expectError(error.InvalidCharacter, net.Address.parseIp6(":::", 0));
37 testing.expectError(error.Overflow, net.IpAddress.parseIp6("FF001::FB", 0));37 testing.expectError(error.Overflow, net.Address.parseIp6("FF001::FB", 0));
38 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0));38 testing.expectError(error.InvalidCharacter, net.Address.parseIp6("FF01::Fb:zig", 0));
39 testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));39 testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
40 testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0));40 testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
41 testing.expectError(error.InvalidIpv4Mapping, net.IpAddress.parseIp6("::123.123.123.123", 0));41 testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
42}42}
4343
44test "parse and render IPv4 addresses" {44test "parse and render IPv4 addresses" {
...@@ -50,16 +50,16 @@ test "parse and render IPv4 addresses" {...@@ -50,16 +50,16 @@ test "parse and render IPv4 addresses" {
50 "123.255.0.91",50 "123.255.0.91",
51 "127.0.0.1",51 "127.0.0.1",
52 }) |ip| {52 }) |ip| {
53 var addr = net.IpAddress.parseIp4(ip, 0) catch unreachable;53 var addr = net.Address.parseIp4(ip, 0) catch unreachable;
54 var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;54 var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable;
55 std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));55 std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
56 }56 }
5757
58 testing.expectError(error.Overflow, net.IpAddress.parseIp4("256.0.0.1", 0));58 testing.expectError(error.Overflow, net.Address.parseIp4("256.0.0.1", 0));
59 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("x.0.0.1", 0));59 testing.expectError(error.InvalidCharacter, net.Address.parseIp4("x.0.0.1", 0));
60 testing.expectError(error.InvalidEnd, net.IpAddress.parseIp4("127.0.0.1.1", 0));60 testing.expectError(error.InvalidEnd, net.Address.parseIp4("127.0.0.1.1", 0));
61 testing.expectError(error.Incomplete, net.IpAddress.parseIp4("127.0.0.", 0));61 testing.expectError(error.Incomplete, net.Address.parseIp4("127.0.0.", 0));
62 testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("100..0.1", 0));62 testing.expectError(error.InvalidCharacter, net.Address.parseIp4("100..0.1", 0));
63}63}
6464
65test "resolve DNS" {65test "resolve DNS" {
...@@ -91,9 +91,9 @@ test "listen on a port, send bytes, receive bytes" {...@@ -91,9 +91,9 @@ test "listen on a port, send bytes, receive bytes" {
91 }91 }
9292
93 // TODO doing this at comptime crashed the compiler93 // 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{});
97 defer server.deinit();97 defer server.deinit();
98 try server.listen(localhost);98 try server.listen(localhost);
9999
...@@ -104,7 +104,7 @@ test "listen on a port, send bytes, receive bytes" {...@@ -104,7 +104,7 @@ test "listen on a port, send bytes, receive bytes" {
104 try await client_frame;104 try await client_frame;
105}105}
106106
107fn testClient(addr: net.IpAddress) anyerror!void {107fn testClient(addr: net.Address) anyerror!void {
108 const socket_file = try net.tcpConnectToAddress(addr);108 const socket_file = try net.tcpConnectToAddress(addr);
109 defer socket_file.close();109 defer socket_file.close();
110110
...@@ -114,7 +114,7 @@ fn testClient(addr: net.IpAddress) anyerror!void {...@@ -114,7 +114,7 @@ fn testClient(addr: net.IpAddress) anyerror!void {
114 testing.expect(mem.eql(u8, msg, "hello from server\n"));114 testing.expect(mem.eql(u8, msg, "hello from server\n"));
115}115}
116116
117fn testServer(server: *net.TcpServer) anyerror!void {117fn testServer(server: *net.StreamServer) anyerror!void {
118 var client_file = try server.accept();118 var client_file = try server.accept();
119119
120 const stream = &client_file.outStream().stream;120 const stream = &client_file.outStream().stream;
lib/std/os/bits/windows.zig+5
...@@ -186,6 +186,11 @@ pub const sockaddr_in6 = extern struct {...@@ -186,6 +186,11 @@ pub const sockaddr_in6 = extern struct {
186pub const in6_addr = [16]u8;186pub const in6_addr = [16]u8;
187pub const in_addr = u32;187pub const in_addr = u32;
188188
189pub const sockaddr_un = extern struct {
190 family: sa_family_t = AF_UNIX,
191 path: [108]u8,
192};
193
189pub const AF_UNSPEC = 0;194pub const AF_UNSPEC = 0;
190pub const AF_UNIX = 1;195pub const AF_UNIX = 1;
191pub const AF_INET = 2;196pub const AF_INET = 2;