| ... | ... | @@ -10,15 +10,16 @@ test "" { |
| 10 | 10 | _ = @import("net/test.zig"); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | | pub const IpAddress = extern union { |
| 13 | pub const Address = extern union { |
| 14 | 14 | any: os.sockaddr, |
| 15 | 15 | in: os.sockaddr_in, |
| 16 | 16 | in6: os.sockaddr_in6, |
| 17 | unix: os.sockaddr_un, |
| 17 | 18 | |
| 18 | 19 | // TODO this crashed the compiler |
| 19 | 20 | //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0); |
| 20 | 21 | |
| 21 | | pub fn parse(name: []const u8, port: u16) !IpAddress { |
| 22 | pub fn parseIp(name: []const u8, port: u16) !Address { |
| 22 | 23 | if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) { |
| 23 | 24 | error.Overflow, |
| 24 | 25 | error.InvalidEnd, |
| ... | ... | @@ -39,7 +40,7 @@ pub const IpAddress = extern union { |
| 39 | 40 | return error.InvalidIPAddressFormat; |
| 40 | 41 | } |
| 41 | 42 | |
| 42 | | pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !IpAddress { |
| 43 | pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !Address { |
| 43 | 44 | switch (family) { |
| 44 | 45 | os.AF_INET => return parseIp4(name, port), |
| 45 | 46 | os.AF_INET6 => return parseIp6(name, port), |
| ... | ... | @@ -48,8 +49,8 @@ pub const IpAddress = extern union { |
| 48 | 49 | } |
| 49 | 50 | } |
| 50 | 51 | |
| 51 | | pub fn parseIp6(buf: []const u8, port: u16) !IpAddress { |
| 52 | | var result = IpAddress{ |
| 52 | pub fn parseIp6(buf: []const u8, port: u16) !Address { |
| 53 | var result = Address{ |
| 53 | 54 | .in6 = os.sockaddr_in6{ |
| 54 | 55 | .scope_id = 0, |
| 55 | 56 | .port = mem.nativeToBig(u16, port), |
| ... | ... | @@ -154,8 +155,8 @@ pub const IpAddress = extern union { |
| 154 | 155 | } |
| 155 | 156 | } |
| 156 | 157 | |
| 157 | | pub fn parseIp4(buf: []const u8, port: u16) !IpAddress { |
| 158 | | var result = IpAddress{ |
| 158 | pub fn parseIp4(buf: []const u8, port: u16) !Address { |
| 159 | var result = Address{ |
| 159 | 160 | .in = os.sockaddr_in{ |
| 160 | 161 | .port = mem.nativeToBig(u16, port), |
| 161 | 162 | .addr = undefined, |
| ... | ... | @@ -194,8 +195,8 @@ pub const IpAddress = extern union { |
| 194 | 195 | return error.Incomplete; |
| 195 | 196 | } |
| 196 | 197 | |
| 197 | | pub fn initIp4(addr: [4]u8, port: u16) IpAddress { |
| 198 | | return IpAddress{ |
| 198 | pub fn initIp4(addr: [4]u8, port: u16) Address { |
| 199 | return Address{ |
| 199 | 200 | .in = os.sockaddr_in{ |
| 200 | 201 | .port = mem.nativeToBig(u16, port), |
| 201 | 202 | .addr = @ptrCast(*align(1) const u32, &addr).*, |
| ... | ... | @@ -203,8 +204,8 @@ pub const IpAddress = extern union { |
| 203 | 204 | }; |
| 204 | 205 | } |
| 205 | 206 | |
| 206 | | pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) IpAddress { |
| 207 | | return IpAddress{ |
| 207 | pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Address { |
| 208 | return Address{ |
| 208 | 209 | .in6 = os.sockaddr_in6{ |
| 209 | 210 | .addr = addr, |
| 210 | 211 | .port = mem.nativeToBig(u16, port), |
| ... | ... | @@ -215,7 +216,7 @@ pub const IpAddress = extern union { |
| 215 | 216 | } |
| 216 | 217 | |
| 217 | 218 | /// Returns the port in native endian. |
| 218 | | pub fn getPort(self: IpAddress) u16 { |
| 219 | pub fn getPort(self: Address) u16 { |
| 219 | 220 | const big_endian_port = switch (self.any.family) { |
| 220 | 221 | os.AF_INET => self.in.port, |
| 221 | 222 | os.AF_INET6 => self.in6.port, |
| ... | ... | @@ -225,7 +226,7 @@ pub const IpAddress = extern union { |
| 225 | 226 | } |
| 226 | 227 | |
| 227 | 228 | /// `port` is native-endian. |
| 228 | | pub fn setPort(self: *IpAddress, port: u16) void { |
| 229 | pub fn setPort(self: *Address, port: u16) void { |
| 229 | 230 | const ptr = switch (self.any.family) { |
| 230 | 231 | os.AF_INET => &self.in.port, |
| 231 | 232 | os.AF_INET6 => &self.in6.port, |
| ... | ... | @@ -237,16 +238,16 @@ pub const IpAddress = extern union { |
| 237 | 238 | /// Asserts that `addr` is an IP address. |
| 238 | 239 | /// This function will read past the end of the pointer, with a size depending |
| 239 | 240 | /// on the address family. |
| 240 | | pub fn initPosix(addr: *align(4) const os.sockaddr) IpAddress { |
| 241 | pub fn initPosix(addr: *align(4) const os.sockaddr) Address { |
| 241 | 242 | 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).* }, |
| 243 | os.AF_INET => return Address{ .in = @ptrCast(*const os.sockaddr_in, addr).* }, |
| 244 | os.AF_INET6 => return Address{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* }, |
| 244 | 245 | else => unreachable, |
| 245 | 246 | } |
| 246 | 247 | } |
| 247 | 248 | |
| 248 | 249 | pub fn format( |
| 249 | | self: IpAddress, |
| 250 | self: Address, |
| 250 | 251 | comptime fmt: []const u8, |
| 251 | 252 | options: std.fmt.FormatOptions, |
| 252 | 253 | context: var, |
| ... | ... | @@ -271,7 +272,7 @@ pub const IpAddress = extern union { |
| 271 | 272 | }, |
| 272 | 273 | os.AF_INET6 => { |
| 273 | 274 | const port = mem.bigToNative(u16, self.in6.port); |
| 274 | | if (mem.eql(u8, self.in6.addr[0..12], [_]u8{0,0,0,0,0,0,0,0,0,0,0xff,0xff})) { |
| 275 | if (mem.eql(u8, self.in6.addr[0..12], [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) { |
| 275 | 276 | try std.fmt.format( |
| 276 | 277 | context, |
| 277 | 278 | Errors, |
| ... | ... | @@ -318,13 +319,13 @@ pub const IpAddress = extern union { |
| 318 | 319 | } |
| 319 | 320 | } |
| 320 | 321 | |
| 321 | | pub fn eql(a: IpAddress, b: IpAddress) bool { |
| 322 | pub fn eql(a: Address, b: Address) bool { |
| 322 | 323 | const a_bytes = @ptrCast([*]const u8, &a.any)[0..a.getOsSockLen()]; |
| 323 | 324 | const b_bytes = @ptrCast([*]const u8, &b.any)[0..b.getOsSockLen()]; |
| 324 | 325 | return mem.eql(u8, a_bytes, b_bytes); |
| 325 | 326 | } |
| 326 | 327 | |
| 327 | | fn getOsSockLen(self: IpAddress) os.socklen_t { |
| 328 | fn getOsSockLen(self: Address) os.socklen_t { |
| 328 | 329 | switch (self.any.family) { |
| 329 | 330 | os.AF_INET => return @sizeOf(os.sockaddr_in), |
| 330 | 331 | os.AF_INET6 => return @sizeOf(os.sockaddr_in6), |
| ... | ... | @@ -358,7 +359,7 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { |
| 358 | 359 | |
| 359 | 360 | pub const AddressList = struct { |
| 360 | 361 | arena: std.heap.ArenaAllocator, |
| 361 | | addrs: []IpAddress, |
| 362 | addrs: []Address, |
| 362 | 363 | canon_name: ?[]u8, |
| 363 | 364 | |
| 364 | 365 | fn deinit(self: *AddressList) void { |
| ... | ... | @@ -381,7 +382,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16) |
| 381 | 382 | return tcpConnectToAddress(addrs[0], port); |
| 382 | 383 | } |
| 383 | 384 | |
| 384 | | pub fn tcpConnectToAddress(address: IpAddress) !fs.File { |
| 385 | pub fn tcpConnectToAddress(address: Address) !fs.File { |
| 385 | 386 | const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; |
| 386 | 387 | const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock; |
| 387 | 388 | const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP); |
| ... | ... | @@ -456,13 +457,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* |
| 456 | 457 | } |
| 457 | 458 | break :blk count; |
| 458 | 459 | }; |
| 459 | | result.addrs = try arena.alloc(IpAddress, addr_count); |
| 460 | result.addrs = try arena.alloc(Address, addr_count); |
| 460 | 461 | |
| 461 | 462 | var it: ?*os.addrinfo = res; |
| 462 | 463 | var i: usize = 0; |
| 463 | 464 | while (it) |info| : (it = info.next) { |
| 464 | 465 | const addr = info.addr orelse continue; |
| 465 | | result.addrs[i] = IpAddress.initPosix(@alignCast(4, addr)); |
| 466 | result.addrs[i] = Address.initPosix(@alignCast(4, addr)); |
| 466 | 467 | |
| 467 | 468 | if (info.canonname) |n| { |
| 468 | 469 | if (result.canon_name == null) { |
| ... | ... | @@ -485,7 +486,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* |
| 485 | 486 | |
| 486 | 487 | try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port); |
| 487 | 488 | |
| 488 | | result.addrs = try arena.alloc(IpAddress, lookup_addrs.len); |
| 489 | result.addrs = try arena.alloc(Address, lookup_addrs.len); |
| 489 | 490 | if (!canon.isNull()) { |
| 490 | 491 | result.canon_name = canon.toOwnedSlice(); |
| 491 | 492 | } |
| ... | ... | @@ -501,7 +502,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* |
| 501 | 502 | } |
| 502 | 503 | |
| 503 | 504 | const LookupAddr = struct { |
| 504 | | addr: IpAddress, |
| 505 | addr: Address, |
| 505 | 506 | sortkey: i32 = 0, |
| 506 | 507 | }; |
| 507 | 508 | |
| ... | ... | @@ -524,7 +525,7 @@ fn linuxLookupName( |
| 524 | 525 | if (opt_name) |name| { |
| 525 | 526 | // reject empty name and check len so it fits into temp bufs |
| 526 | 527 | try canon.replaceContents(name); |
| 527 | | if (IpAddress.parseExpectingFamily(name, family, port)) |addr| { |
| 528 | if (Address.parseExpectingFamily(name, family, port)) |addr| { |
| 528 | 529 | try addrs.append(LookupAddr{ .addr = addr }); |
| 529 | 530 | } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) { |
| 530 | 531 | return name_err; |
| ... | ... | @@ -751,23 +752,23 @@ fn linuxLookupNameFromNull( |
| 751 | 752 | if ((flags & std.c.AI_PASSIVE) != 0) { |
| 752 | 753 | if (family != os.AF_INET6) { |
| 753 | 754 | (try addrs.addOne()).* = LookupAddr{ |
| 754 | | .addr = IpAddress.initIp4([1]u8{0} ** 4, port), |
| 755 | .addr = Address.initIp4([1]u8{0} ** 4, port), |
| 755 | 756 | }; |
| 756 | 757 | } |
| 757 | 758 | if (family != os.AF_INET) { |
| 758 | 759 | (try addrs.addOne()).* = LookupAddr{ |
| 759 | | .addr = IpAddress.initIp6([1]u8{0} ** 16, port, 0, 0), |
| 760 | .addr = Address.initIp6([1]u8{0} ** 16, port, 0, 0), |
| 760 | 761 | }; |
| 761 | 762 | } |
| 762 | 763 | } else { |
| 763 | 764 | if (family != os.AF_INET6) { |
| 764 | 765 | (try addrs.addOne()).* = LookupAddr{ |
| 765 | | .addr = IpAddress.initIp4([4]u8{ 127, 0, 0, 1 }, port), |
| 766 | .addr = Address.initIp4([4]u8{ 127, 0, 0, 1 }, port), |
| 766 | 767 | }; |
| 767 | 768 | } |
| 768 | 769 | if (family != os.AF_INET) { |
| 769 | 770 | (try addrs.addOne()).* = LookupAddr{ |
| 770 | | .addr = IpAddress.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0), |
| 771 | .addr = Address.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0), |
| 771 | 772 | }; |
| 772 | 773 | } |
| 773 | 774 | } |
| ... | ... | @@ -812,7 +813,7 @@ fn linuxLookupNameFromHosts( |
| 812 | 813 | } |
| 813 | 814 | } else continue; |
| 814 | 815 | |
| 815 | | const addr = IpAddress.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) { |
| 816 | const addr = Address.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) { |
| 816 | 817 | error.Overflow, |
| 817 | 818 | error.InvalidEnd, |
| 818 | 819 | error.InvalidCharacter, |
| ... | ... | @@ -1033,7 +1034,7 @@ fn linuxLookupNameFromNumericUnspec( |
| 1033 | 1034 | name: []const u8, |
| 1034 | 1035 | port: u16, |
| 1035 | 1036 | ) !void { |
| 1036 | | const addr = try IpAddress.parse(name, port); |
| 1037 | const addr = try Address.parse(name, port); |
| 1037 | 1038 | (try addrs.addOne()).* = LookupAddr{ .addr = addr }; |
| 1038 | 1039 | } |
| 1039 | 1040 | |
| ... | ... | @@ -1049,7 +1050,7 @@ fn resMSendRc( |
| 1049 | 1050 | var sl: os.socklen_t = @sizeOf(os.sockaddr_in); |
| 1050 | 1051 | var family: os.sa_family_t = os.AF_INET; |
| 1051 | 1052 | |
| 1052 | | var ns_list = std.ArrayList(IpAddress).init(rc.ns.allocator); |
| 1053 | var ns_list = std.ArrayList(Address).init(rc.ns.allocator); |
| 1053 | 1054 | defer ns_list.deinit(); |
| 1054 | 1055 | |
| 1055 | 1056 | try ns_list.resize(rc.ns.len); |
| ... | ... | @@ -1065,8 +1066,8 @@ fn resMSendRc( |
| 1065 | 1066 | } |
| 1066 | 1067 | |
| 1067 | 1068 | // Get local address and open/bind a socket |
| 1068 | | var sa: IpAddress = undefined; |
| 1069 | | @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(IpAddress)); |
| 1069 | var sa: Address = undefined; |
| 1070 | @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address)); |
| 1070 | 1071 | sa.any.family = family; |
| 1071 | 1072 | const flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK; |
| 1072 | 1073 | const fd = os.socket(family, flags, 0) catch |err| switch (err) { |
| ... | ... | @@ -1224,7 +1225,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) |
| 1224 | 1225 | const new_addr = try ctx.addrs.addOne(); |
| 1225 | 1226 | new_addr.* = LookupAddr{ |
| 1226 | 1227 | // TODO slice [0..4] to make this *[4]u8 without @ptrCast |
| 1227 | | .addr = IpAddress.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port), |
| 1228 | .addr = Address.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port), |
| 1228 | 1229 | }; |
| 1229 | 1230 | }, |
| 1230 | 1231 | os.RR_AAAA => { |
| ... | ... | @@ -1232,7 +1233,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) |
| 1232 | 1233 | const new_addr = try ctx.addrs.addOne(); |
| 1233 | 1234 | new_addr.* = LookupAddr{ |
| 1234 | 1235 | // 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), |
| 1236 | .addr = Address.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0), |
| 1236 | 1237 | }; |
| 1237 | 1238 | }, |
| 1238 | 1239 | os.RR_CNAME => { |
| ... | ... | @@ -1253,7 +1254,7 @@ pub const TcpServer = struct { |
| 1253 | 1254 | kernel_backlog: u32, |
| 1254 | 1255 | |
| 1255 | 1256 | /// `undefined` until `listen` returns successfully. |
| 1256 | | listen_address: IpAddress, |
| 1257 | listen_address: Address, |
| 1257 | 1258 | |
| 1258 | 1259 | sockfd: ?os.fd_t, |
| 1259 | 1260 | |
| ... | ... | @@ -1280,7 +1281,7 @@ pub const TcpServer = struct { |
| 1280 | 1281 | self.* = undefined; |
| 1281 | 1282 | } |
| 1282 | 1283 | |
| 1283 | | pub fn listen(self: *TcpServer, address: IpAddress) !void { |
| 1284 | pub fn listen(self: *TcpServer, address: Address) !void { |
| 1284 | 1285 | const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; |
| 1285 | 1286 | const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock; |
| 1286 | 1287 | const sockfd = try os.socket(os.AF_INET, sock_flags, os.IPPROTO_TCP); |
| ... | ... | @@ -1330,8 +1331,8 @@ pub const TcpServer = struct { |
| 1330 | 1331 | pub fn accept(self: *TcpServer) AcceptError!fs.File { |
| 1331 | 1332 | const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; |
| 1332 | 1333 | const accept_flags = nonblock | os.SOCK_CLOEXEC; |
| 1333 | | var accepted_addr: IpAddress = undefined; |
| 1334 | | var adr_len: os.socklen_t = @sizeOf(IpAddress); |
| 1334 | var accepted_addr: Address = undefined; |
| 1335 | var adr_len: os.socklen_t = @sizeOf(Address); |
| 1335 | 1336 | if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| { |
| 1336 | 1337 | return fs.File.openHandle(fd); |
| 1337 | 1338 | } else |err| switch (err) { |