| ... | ... | @@ -7,6 +7,8 @@ |
| 7 | 7 | const std = @import("../../std.zig"); |
| 8 | 8 | |
| 9 | 9 | const os = std.os; |
| 10 | const ip = std.x.net.ip; |
| 11 | |
| 10 | 12 | const fmt = std.fmt; |
| 11 | 13 | const mem = std.mem; |
| 12 | 14 | const builtin = std.builtin; |
| ... | ... | @@ -19,61 +21,16 @@ const Socket = std.x.os.Socket; |
| 19 | 21 | /// A generic TCP socket abstraction. |
| 20 | 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 | 24 | /// A TCP client-address pair. |
| 68 | 25 | pub const Connection = struct { |
| 69 | 26 | client: tcp.Client, |
| 70 | | address: tcp.Address, |
| 27 | address: ip.Address, |
| 71 | 28 | |
| 72 | 29 | /// Enclose a TCP client and address into a client-address pair. |
| 73 | 30 | pub fn from(conn: Socket.Connection) tcp.Connection { |
| 74 | 31 | return .{ |
| 75 | 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 | 85 | } |
| 129 | 86 | |
| 130 | 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 | 89 | return self.socket.connect(address.into()); |
| 133 | 90 | } |
| 134 | 91 | |
| ... | ... | @@ -185,8 +142,8 @@ pub const Client = struct { |
| 185 | 142 | } |
| 186 | 143 | |
| 187 | 144 | /// Query the address that the client's socket is locally bounded to. |
| 188 | | pub fn getLocalAddress(self: Client) !tcp.Address { |
| 189 | | return tcp.Address.from(try self.socket.getLocalAddress()); |
| 145 | pub fn getLocalAddress(self: Client) !ip.Address { |
| 146 | return ip.Address.from(try self.socket.getLocalAddress()); |
| 190 | 147 | } |
| 191 | 148 | |
| 192 | 149 | /// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if |
| ... | ... | @@ -253,7 +210,7 @@ pub const Listener = struct { |
| 253 | 210 | } |
| 254 | 211 | |
| 255 | 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 | 214 | return self.socket.bind(address.into()); |
| 258 | 215 | } |
| 259 | 216 | |
| ... | ... | @@ -274,8 +231,8 @@ pub const Listener = struct { |
| 274 | 231 | } |
| 275 | 232 | |
| 276 | 233 | /// Query the address that the listener's socket is locally bounded to. |
| 277 | | pub fn getLocalAddress(self: Listener) !tcp.Address { |
| 278 | | return tcp.Address.from(try self.socket.getLocalAddress()); |
| 234 | pub fn getLocalAddress(self: Listener) !ip.Address { |
| 235 | return ip.Address.from(try self.socket.getLocalAddress()); |
| 279 | 236 | } |
| 280 | 237 | |
| 281 | 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 | 279 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); |
| 323 | 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 | 283 | try listener.listen(128); |
| 327 | 284 | |
| 328 | 285 | const binded_address = try listener.getLocalAddress(); |
| ... | ... | @@ -342,7 +299,7 @@ test "tcp/client: set read timeout of 1 millisecond on blocking client" { |
| 342 | 299 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); |
| 343 | 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 | 303 | try listener.listen(128); |
| 347 | 304 | |
| 348 | 305 | const binded_address = try listener.getLocalAddress(); |
| ... | ... | @@ -366,7 +323,7 @@ test "tcp/listener: bind to unspecified ipv4 address" { |
| 366 | 323 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); |
| 367 | 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 | 327 | try listener.listen(128); |
| 371 | 328 | |
| 372 | 329 | const address = try listener.getLocalAddress(); |
| ... | ... | @@ -379,7 +336,7 @@ test "tcp/listener: bind to unspecified ipv6 address" { |
| 379 | 336 | const listener = try tcp.Listener.init(.ipv6, os.SOCK_CLOEXEC); |
| 380 | 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 | 340 | try listener.listen(128); |
| 384 | 341 | |
| 385 | 342 | const address = try listener.getLocalAddress(); |