| ... | @@ -14,6 +14,19 @@ pub const has_unix_sockets = @hasDecl(os.sockaddr, "un") and | ... | @@ -14,6 +14,19 @@ pub const has_unix_sockets = @hasDecl(os.sockaddr, "un") and |
| 14 | (builtin.target.os.tag != .windows or | 14 | (builtin.target.os.tag != .windows or |
| 15 | builtin.os.version_range.windows.isAtLeast(.win10_rs4) orelse false); | 15 | builtin.os.version_range.windows.isAtLeast(.win10_rs4) orelse false); |
| 16 | | 16 | |
| | 17 | pub const IPParseError = error{ |
| | 18 | Overflow, |
| | 19 | InvalidEnd, |
| | 20 | InvalidCharacter, |
| | 21 | Incomplete, |
| | 22 | }; |
| | 23 | |
| | 24 | pub const IPv4ParseError = IPParseError || error{NonCanonical}; |
| | 25 | |
| | 26 | pub const IPv6ParseError = IPParseError || error{InvalidIpv4Mapping}; |
| | 27 | pub const IPv6InterfaceError = os.SocketError || os.IoCtl_SIOCGIFINDEX_Error || error{NameTooLong}; |
| | 28 | pub const IPv6ResolveError = IPv6ParseError || IPv6InterfaceError; |
| | 29 | |
| 17 | pub const Address = extern union { | 30 | pub const Address = extern union { |
| 18 | any: os.sockaddr, | 31 | any: os.sockaddr, |
| 19 | in: Ip4Address, | 32 | in: Ip4Address, |
| ... | @@ -77,15 +90,15 @@ pub const Address = extern union { | ... | @@ -77,15 +90,15 @@ pub const Address = extern union { |
| 77 | } | 90 | } |
| 78 | } | 91 | } |
| 79 | | 92 | |
| 80 | pub fn parseIp6(buf: []const u8, port: u16) !Address { | 93 | pub fn parseIp6(buf: []const u8, port: u16) IPv6ParseError!Address { |
| 81 | return Address{ .in6 = try Ip6Address.parse(buf, port) }; | 94 | return Address{ .in6 = try Ip6Address.parse(buf, port) }; |
| 82 | } | 95 | } |
| 83 | | 96 | |
| 84 | pub fn resolveIp6(buf: []const u8, port: u16) !Address { | 97 | pub fn resolveIp6(buf: []const u8, port: u16) IPv6ResolveError!Address { |
| 85 | return Address{ .in6 = try Ip6Address.resolve(buf, port) }; | 98 | return Address{ .in6 = try Ip6Address.resolve(buf, port) }; |
| 86 | } | 99 | } |
| 87 | | 100 | |
| 88 | pub fn parseIp4(buf: []const u8, port: u16) !Address { | 101 | pub fn parseIp4(buf: []const u8, port: u16) IPv4ParseError!Address { |
| 89 | return Address{ .in = try Ip4Address.parse(buf, port) }; | 102 | return Address{ .in = try Ip4Address.parse(buf, port) }; |
| 90 | } | 103 | } |
| 91 | | 104 | |
| ... | @@ -198,7 +211,7 @@ pub const Address = extern union { | ... | @@ -198,7 +211,7 @@ pub const Address = extern union { |
| 198 | pub const Ip4Address = extern struct { | 211 | pub const Ip4Address = extern struct { |
| 199 | sa: os.sockaddr.in, | 212 | sa: os.sockaddr.in, |
| 200 | | 213 | |
| 201 | pub fn parse(buf: []const u8, port: u16) !Ip4Address { | 214 | pub fn parse(buf: []const u8, port: u16) IPv4ParseError!Ip4Address { |
| 202 | var result = Ip4Address{ | 215 | var result = Ip4Address{ |
| 203 | .sa = .{ | 216 | .sa = .{ |
| 204 | .port = mem.nativeToBig(u16, port), | 217 | .port = mem.nativeToBig(u16, port), |
| ... | @@ -307,7 +320,7 @@ pub const Ip6Address = extern struct { | ... | @@ -307,7 +320,7 @@ pub const Ip6Address = extern struct { |
| 307 | /// Parse a given IPv6 address string into an Address. | 320 | /// Parse a given IPv6 address string into an Address. |
| 308 | /// Assumes the Scope ID of the address is fully numeric. | 321 | /// Assumes the Scope ID of the address is fully numeric. |
| 309 | /// For non-numeric addresses, see `resolveIp6`. | 322 | /// For non-numeric addresses, see `resolveIp6`. |
| 310 | pub fn parse(buf: []const u8, port: u16) !Ip6Address { | 323 | pub fn parse(buf: []const u8, port: u16) IPv6ParseError!Ip6Address { |
| 311 | var result = Ip6Address{ | 324 | var result = Ip6Address{ |
| 312 | .sa = os.sockaddr.in6{ | 325 | .sa = os.sockaddr.in6{ |
| 313 | .scope_id = 0, | 326 | .scope_id = 0, |
| ... | @@ -424,7 +437,7 @@ pub const Ip6Address = extern struct { | ... | @@ -424,7 +437,7 @@ pub const Ip6Address = extern struct { |
| 424 | } | 437 | } |
| 425 | } | 438 | } |
| 426 | | 439 | |
| 427 | pub fn resolve(buf: []const u8, port: u16) !Ip6Address { | 440 | pub fn resolve(buf: []const u8, port: u16) IPv6ResolveError!Ip6Address { |
| 428 | // TODO: Unify the implementations of resolveIp6 and parseIp6. | 441 | // TODO: Unify the implementations of resolveIp6 and parseIp6. |
| 429 | var result = Ip6Address{ | 442 | var result = Ip6Address{ |
| 430 | .sa = os.sockaddr.in6{ | 443 | .sa = os.sockaddr.in6{ |
| ... | @@ -659,7 +672,7 @@ pub fn connectUnixSocket(path: []const u8) !Stream { | ... | @@ -659,7 +672,7 @@ pub fn connectUnixSocket(path: []const u8) !Stream { |
| 659 | }; | 672 | }; |
| 660 | } | 673 | } |
| 661 | | 674 | |
| 662 | fn if_nametoindex(name: []const u8) !u32 { | 675 | fn if_nametoindex(name: []const u8) IPv6InterfaceError!u32 { |
| 663 | if (builtin.target.os.tag == .linux) { | 676 | if (builtin.target.os.tag == .linux) { |
| 664 | var ifr: os.ifreq = undefined; | 677 | var ifr: os.ifreq = undefined; |
| 665 | const sockfd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM | os.SOCK.CLOEXEC, 0); | 678 | const sockfd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM | os.SOCK.CLOEXEC, 0); |