| ... | @@ -7,6 +7,8 @@ | ... | @@ -7,6 +7,8 @@ |
| 7 | const std = @import("../../std.zig"); | 7 | const std = @import("../../std.zig"); |
| 8 | | 8 | |
| 9 | const os = std.os; | 9 | const os = std.os; |
| | 10 | const ip = std.x.net.ip; |
| | 11 | |
| 10 | const fmt = std.fmt; | 12 | const fmt = std.fmt; |
| 11 | const mem = std.mem; | 13 | const mem = std.mem; |
| 12 | const builtin = std.builtin; | 14 | const builtin = std.builtin; |
| ... | @@ -19,61 +21,16 @@ const Socket = std.x.os.Socket; | ... | @@ -19,61 +21,16 @@ const Socket = std.x.os.Socket; |
| 19 | /// A generic TCP socket abstraction. | 21 | /// A generic TCP socket abstraction. |
| 20 | const tcp = @This(); | 22 | const tcp = @This(); |
| 21 | | 23 | |
| 22 | /// A union of all eligible types of socket addresses over TCP. | | |
| 23 | pub const Address = union(enum) { | | |
| 24 | ipv4: IPv4.Address, | | |
| 25 | ipv6: IPv6.Address, | | |
| 26 | | | |
| 27 | /// Instantiate a new address with a IPv4 host and port. | | |
| 28 | pub fn initIPv4(host: IPv4, port: u16) Address { | | |
| 29 | return .{ .ipv4 = .{ .host = host, .port = port } }; | | |
| 30 | } | | |
| 31 | | | |
| 32 | /// Instantiate a new address with a IPv6 host and port. | | |
| 33 | pub fn initIPv6(host: IPv6, port: u16) Address { | | |
| 34 | return .{ .ipv6 = .{ .host = host, .port = port } }; | | |
| 35 | } | | |
| 36 | | | |
| 37 | /// Re-interpret a generic socket address into a TCP socket address. | | |
| 38 | pub fn from(address: Socket.Address) tcp.Address { | | |
| 39 | return switch (address) { | | |
| 40 | .ipv4 => |ipv4_address| .{ .ipv4 = ipv4_address }, | | |
| 41 | .ipv6 => |ipv6_address| .{ .ipv6 = ipv6_address }, | | |
| 42 | }; | | |
| 43 | } | | |
| 44 | | | |
| 45 | /// Re-interpret a TCP socket address into a generic socket address. | | |
| 46 | pub fn into(self: tcp.Address) Socket.Address { | | |
| 47 | return switch (self) { | | |
| 48 | .ipv4 => |ipv4_address| .{ .ipv4 = ipv4_address }, | | |
| 49 | .ipv6 => |ipv6_address| .{ .ipv6 = ipv6_address }, | | |
| 50 | }; | | |
| 51 | } | | |
| 52 | | | |
| 53 | /// Implements the `std.fmt.format` API. | | |
| 54 | pub fn format( | | |
| 55 | self: tcp.Address, | | |
| 56 | comptime layout: []const u8, | | |
| 57 | opts: fmt.FormatOptions, | | |
| 58 | writer: anytype, | | |
| 59 | ) !void { | | |
| 60 | switch (self) { | | |
| 61 | .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), | | |
| 62 | .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), | | |
| 63 | } | | |
| 64 | } | | |
| 65 | }; | | |
| 66 | | | |
| 67 | /// A TCP client-address pair. | 24 | /// A TCP client-address pair. |
| 68 | pub const Connection = struct { | 25 | pub const Connection = struct { |
| 69 | client: tcp.Client, | 26 | client: tcp.Client, |
| 70 | address: tcp.Address, | 27 | address: ip.Address, |
| 71 | | 28 | |
| 72 | /// Enclose a TCP client and address into a client-address pair. | 29 | /// Enclose a TCP client and address into a client-address pair. |
| 73 | pub fn from(conn: Socket.Connection) tcp.Connection { | 30 | pub fn from(conn: Socket.Connection) tcp.Connection { |
| 74 | return .{ | 31 | return .{ |
| 75 | .client = tcp.Client.from(conn.socket), | 32 | .client = tcp.Client.from(conn.socket), |
| 76 | .address = tcp.Address.from(conn.address), | 33 | .address = ip.Address.from(conn.address), |
| 77 | }; | 34 | }; |
| 78 | } | 35 | } |
| 79 | | 36 | |
| ... | @@ -128,7 +85,7 @@ pub const Client = struct { | ... | @@ -128,7 +85,7 @@ pub const Client = struct { |
| 128 | } | 85 | } |
| 129 | | 86 | |
| 130 | /// Have the client attempt to the connect to an address. | 87 | /// Have the client attempt to the connect to an address. |
| 131 | pub fn connect(self: Client, address: tcp.Address) !void { | 88 | pub fn connect(self: Client, address: ip.Address) !void { |
| 132 | return self.socket.connect(address.into()); | 89 | return self.socket.connect(address.into()); |
| 133 | } | 90 | } |
| 134 | | 91 | |
| ... | @@ -185,8 +142,8 @@ pub const Client = struct { | ... | @@ -185,8 +142,8 @@ pub const Client = struct { |
| 185 | } | 142 | } |
| 186 | | 143 | |
| 187 | /// Query the address that the client's socket is locally bounded to. | 144 | /// Query the address that the client's socket is locally bounded to. |
| 188 | pub fn getLocalAddress(self: Client) !tcp.Address { | 145 | pub fn getLocalAddress(self: Client) !ip.Address { |
| 189 | return tcp.Address.from(try self.socket.getLocalAddress()); | 146 | return ip.Address.from(try self.socket.getLocalAddress()); |
| 190 | } | 147 | } |
| 191 | | 148 | |
| 192 | /// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if | 149 | /// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if |
| ... | @@ -253,7 +210,7 @@ pub const Listener = struct { | ... | @@ -253,7 +210,7 @@ pub const Listener = struct { |
| 253 | } | 210 | } |
| 254 | | 211 | |
| 255 | /// Binds the listener's socket to an address. | 212 | /// Binds the listener's socket to an address. |
| 256 | pub fn bind(self: Listener, address: tcp.Address) !void { | 213 | pub fn bind(self: Listener, address: ip.Address) !void { |
| 257 | return self.socket.bind(address.into()); | 214 | return self.socket.bind(address.into()); |
| 258 | } | 215 | } |
| 259 | | 216 | |
| ... | @@ -274,8 +231,8 @@ pub const Listener = struct { | ... | @@ -274,8 +231,8 @@ pub const Listener = struct { |
| 274 | } | 231 | } |
| 275 | | 232 | |
| 276 | /// Query the address that the listener's socket is locally bounded to. | 233 | /// Query the address that the listener's socket is locally bounded to. |
| 277 | pub fn getLocalAddress(self: Listener) !tcp.Address { | 234 | pub fn getLocalAddress(self: Listener) !ip.Address { |
| 278 | return tcp.Address.from(try self.socket.getLocalAddress()); | 235 | return ip.Address.from(try self.socket.getLocalAddress()); |
| 279 | } | 236 | } |
| 280 | | 237 | |
| 281 | /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if | 238 | /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if |
| ... | @@ -322,7 +279,7 @@ test "tcp: create client/listener pair" { | ... | @@ -322,7 +279,7 @@ test "tcp: create client/listener pair" { |
| 322 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); | 279 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); |
| 323 | defer listener.deinit(); | 280 | defer listener.deinit(); |
| 324 | | 281 | |
| 325 | try listener.bind(tcp.Address.initIPv4(IPv4.unspecified, 0)); | 282 | try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); |
| 326 | try listener.listen(128); | 283 | try listener.listen(128); |
| 327 | | 284 | |
| 328 | const binded_address = try listener.getLocalAddress(); | 285 | const binded_address = try listener.getLocalAddress(); |
| ... | @@ -342,7 +299,7 @@ test "tcp/client: set read timeout of 1 millisecond on blocking client" { | ... | @@ -342,7 +299,7 @@ test "tcp/client: set read timeout of 1 millisecond on blocking client" { |
| 342 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); | 299 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); |
| 343 | defer listener.deinit(); | 300 | defer listener.deinit(); |
| 344 | | 301 | |
| 345 | try listener.bind(tcp.Address.initIPv4(IPv4.unspecified, 0)); | 302 | try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); |
| 346 | try listener.listen(128); | 303 | try listener.listen(128); |
| 347 | | 304 | |
| 348 | const binded_address = try listener.getLocalAddress(); | 305 | const binded_address = try listener.getLocalAddress(); |
| ... | @@ -366,7 +323,7 @@ test "tcp/listener: bind to unspecified ipv4 address" { | ... | @@ -366,7 +323,7 @@ test "tcp/listener: bind to unspecified ipv4 address" { |
| 366 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); | 323 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); |
| 367 | defer listener.deinit(); | 324 | defer listener.deinit(); |
| 368 | | 325 | |
| 369 | try listener.bind(tcp.Address.initIPv4(IPv4.unspecified, 0)); | 326 | try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); |
| 370 | try listener.listen(128); | 327 | try listener.listen(128); |
| 371 | | 328 | |
| 372 | const address = try listener.getLocalAddress(); | 329 | const address = try listener.getLocalAddress(); |
| ... | @@ -379,7 +336,7 @@ test "tcp/listener: bind to unspecified ipv6 address" { | ... | @@ -379,7 +336,7 @@ test "tcp/listener: bind to unspecified ipv6 address" { |
| 379 | const listener = try tcp.Listener.init(.ipv6, os.SOCK_CLOEXEC); | 336 | const listener = try tcp.Listener.init(.ipv6, os.SOCK_CLOEXEC); |
| 380 | defer listener.deinit(); | 337 | defer listener.deinit(); |
| 381 | | 338 | |
| 382 | try listener.bind(tcp.Address.initIPv6(IPv6.unspecified, 0)); | 339 | try listener.bind(ip.Address.initIPv6(IPv6.unspecified, 0)); |
| 383 | try listener.listen(128); | 340 | try listener.listen(128); |
| 384 | | 341 | |
| 385 | const address = try listener.getLocalAddress(); | 342 | const address = try listener.getLocalAddress(); |