| ... | @@ -10,6 +10,7 @@ const net = @This(); | ... | @@ -10,6 +10,7 @@ const net = @This(); |
| 10 | const mem = std.mem; | 10 | const mem = std.mem; |
| 11 | const os = std.os; | 11 | const os = std.os; |
| 12 | const fs = std.fs; | 12 | const fs = std.fs; |
| | 13 | const io = std.io; |
| 13 | | 14 | |
| 14 | pub const has_unix_sockets = @hasDecl(os, "sockaddr_un"); | 15 | pub const has_unix_sockets = @hasDecl(os, "sockaddr_un"); |
| 15 | | 16 | |
| ... | @@ -596,7 +597,7 @@ pub const Ip6Address = extern struct { | ... | @@ -596,7 +597,7 @@ pub const Ip6Address = extern struct { |
| 596 | } | 597 | } |
| 597 | }; | 598 | }; |
| 598 | | 599 | |
| 599 | pub fn connectUnixSocket(path: []const u8) !fs.File { | 600 | pub fn connectUnixSocket(path: []const u8) !Stream { |
| 600 | const opt_non_block = if (std.io.is_async) os.SOCK_NONBLOCK else 0; | 601 | const opt_non_block = if (std.io.is_async) os.SOCK_NONBLOCK else 0; |
| 601 | const sockfd = try os.socket( | 602 | const sockfd = try os.socket( |
| 602 | os.AF_UNIX, | 603 | os.AF_UNIX, |
| ... | @@ -614,7 +615,7 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { | ... | @@ -614,7 +615,7 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { |
| 614 | try os.connect(sockfd, &addr.any, addr.getOsSockLen()); | 615 | try os.connect(sockfd, &addr.any, addr.getOsSockLen()); |
| 615 | } | 616 | } |
| 616 | | 617 | |
| 617 | return fs.File{ | 618 | return Stream{ |
| 618 | .handle = sockfd, | 619 | .handle = sockfd, |
| 619 | }; | 620 | }; |
| 620 | } | 621 | } |
| ... | @@ -648,7 +649,7 @@ pub const AddressList = struct { | ... | @@ -648,7 +649,7 @@ pub const AddressList = struct { |
| 648 | }; | 649 | }; |
| 649 | | 650 | |
| 650 | /// All memory allocated with `allocator` will be freed before this function returns. | 651 | /// All memory allocated with `allocator` will be freed before this function returns. |
| 651 | pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16) !fs.File { | 652 | pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16) !Stream { |
| 652 | const list = try getAddressList(allocator, name, port); | 653 | const list = try getAddressList(allocator, name, port); |
| 653 | defer list.deinit(); | 654 | defer list.deinit(); |
| 654 | | 655 | |
| ... | @@ -665,7 +666,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16) | ... | @@ -665,7 +666,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16) |
| 665 | return std.os.ConnectError.ConnectionRefused; | 666 | return std.os.ConnectError.ConnectionRefused; |
| 666 | } | 667 | } |
| 667 | | 668 | |
| 668 | pub fn tcpConnectToAddress(address: Address) !fs.File { | 669 | pub fn tcpConnectToAddress(address: Address) !Stream { |
| 669 | const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; | 670 | const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; |
| 670 | const sock_flags = os.SOCK_STREAM | nonblock | | 671 | const sock_flags = os.SOCK_STREAM | nonblock | |
| 671 | (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC); | 672 | (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC); |
| ... | @@ -679,7 +680,7 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { | ... | @@ -679,7 +680,7 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { |
| 679 | try os.connect(sockfd, &address.any, address.getOsSockLen()); | 680 | try os.connect(sockfd, &address.any, address.getOsSockLen()); |
| 680 | } | 681 | } |
| 681 | | 682 | |
| 682 | return fs.File{ .handle = sockfd }; | 683 | return Stream{ .handle = sockfd }; |
| 683 | } | 684 | } |
| 684 | | 685 | |
| 685 | /// Call `AddressList.deinit` on the result. | 686 | /// Call `AddressList.deinit` on the result. |
| ... | @@ -1580,6 +1581,55 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) | ... | @@ -1580,6 +1581,55 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) |
| 1580 | } | 1581 | } |
| 1581 | } | 1582 | } |
| 1582 | | 1583 | |
| | 1584 | pub const Stream = struct { |
| | 1585 | // Underlying socket descriptor. |
| | 1586 | // Note that on some platforms this may not be interchangeable with a |
| | 1587 | // regular files descriptor. |
| | 1588 | handle: os.socket_t, |
| | 1589 | |
| | 1590 | pub fn close(self: Stream) void { |
| | 1591 | os.closeSocket(self.handle); |
| | 1592 | } |
| | 1593 | |
| | 1594 | pub const ReadError = os.ReadError; |
| | 1595 | pub const WriteError = os.WriteError; |
| | 1596 | |
| | 1597 | pub const Reader = io.Reader(Stream, ReadError, read); |
| | 1598 | pub const Writer = io.Writer(Stream, WriteError, write); |
| | 1599 | |
| | 1600 | pub fn reader(self: Stream) Reader { |
| | 1601 | return .{ .context = self }; |
| | 1602 | } |
| | 1603 | |
| | 1604 | pub fn writer(self: Stream) Writer { |
| | 1605 | return .{ .context = self }; |
| | 1606 | } |
| | 1607 | |
| | 1608 | pub fn read(self: Stream, buffer: []u8) ReadError!usize { |
| | 1609 | if (std.Target.current.os.tag == .windows) { |
| | 1610 | return os.windows.ReadFile(self.handle, buffer, null, io.default_mode); |
| | 1611 | } |
| | 1612 | |
| | 1613 | if (std.io.is_async) { |
| | 1614 | return std.event.Loop.instance.?.read(self.handle, buffer, false); |
| | 1615 | } else { |
| | 1616 | return os.read(self.handle, buffer); |
| | 1617 | } |
| | 1618 | } |
| | 1619 | |
| | 1620 | pub fn write(self: Stream, buffer: []const u8) WriteError!usize { |
| | 1621 | if (std.Target.current.os.tag == .windows) { |
| | 1622 | return os.windows.WriteFile(self.handle, buffer, null, io.default_mode); |
| | 1623 | } |
| | 1624 | |
| | 1625 | if (std.io.is_async) { |
| | 1626 | return std.event.Loop.instance.?.write(self.handle, buffer, false); |
| | 1627 | } else { |
| | 1628 | return os.write(self.handle, buffer); |
| | 1629 | } |
| | 1630 | } |
| | 1631 | }; |
| | 1632 | |
| 1583 | pub const StreamServer = struct { | 1633 | pub const StreamServer = struct { |
| 1584 | /// Copied from `Options` on `init`. | 1634 | /// Copied from `Options` on `init`. |
| 1585 | kernel_backlog: u31, | 1635 | kernel_backlog: u31, |
| ... | @@ -1686,7 +1736,7 @@ pub const StreamServer = struct { | ... | @@ -1686,7 +1736,7 @@ pub const StreamServer = struct { |
| 1686 | } || os.UnexpectedError; | 1736 | } || os.UnexpectedError; |
| 1687 | | 1737 | |
| 1688 | pub const Connection = struct { | 1738 | pub const Connection = struct { |
| 1689 | file: fs.File, | 1739 | stream: Stream, |
| 1690 | address: Address, | 1740 | address: Address, |
| 1691 | }; | 1741 | }; |
| 1692 | | 1742 | |
| ... | @@ -1705,7 +1755,7 @@ pub const StreamServer = struct { | ... | @@ -1705,7 +1755,7 @@ pub const StreamServer = struct { |
| 1705 | | 1755 | |
| 1706 | if (accept_result) |fd| { | 1756 | if (accept_result) |fd| { |
| 1707 | return Connection{ | 1757 | return Connection{ |
| 1708 | .file = fs.File{ .handle = fd }, | 1758 | .stream = Stream{ .handle = fd }, |
| 1709 | .address = accepted_addr, | 1759 | .address = accepted_addr, |
| 1710 | }; | 1760 | }; |
| 1711 | } else |err| switch (err) { | 1761 | } else |err| switch (err) { |