| ... | ... | @@ -1697,34 +1697,10 @@ fn netListenIpPosix( |
| 1697 | 1697 | ) Io.net.IpAddress.ListenError!Io.net.Server { |
| 1698 | 1698 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1699 | 1699 | const family = posixAddressFamily(&address); |
| 1700 | | const protocol: u32 = posix.IPPROTO.TCP; |
| 1701 | | const socket_fd = while (true) { |
| 1702 | | try pool.checkCancel(); |
| 1703 | | const flags: u32 = posix.SOCK.STREAM | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; |
| 1704 | | const socket_rc = posix.system.socket(family, flags, protocol); |
| 1705 | | switch (posix.errno(socket_rc)) { |
| 1706 | | .SUCCESS => { |
| 1707 | | const fd: posix.fd_t = @intCast(socket_rc); |
| 1708 | | errdefer posix.close(fd); |
| 1709 | | if (socket_flags_unsupported) while (true) { |
| 1710 | | try pool.checkCancel(); |
| 1711 | | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { |
| 1712 | | .SUCCESS => break, |
| 1713 | | .INTR => continue, |
| 1714 | | else => |err| return posix.unexpectedErrno(err), |
| 1715 | | } |
| 1716 | | }; |
| 1717 | | break fd; |
| 1718 | | }, |
| 1719 | | .INTR => continue, |
| 1720 | | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1721 | | .MFILE => return error.ProcessFdQuotaExceeded, |
| 1722 | | .NFILE => return error.SystemFdQuotaExceeded, |
| 1723 | | .NOBUFS => return error.SystemResources, |
| 1724 | | .NOMEM => return error.SystemResources, |
| 1725 | | else => |err| return posix.unexpectedErrno(err), |
| 1726 | | } |
| 1727 | | }; |
| 1700 | const socket_fd = try openSocketPosix(pool, family, .{ |
| 1701 | .mode = options.mode, |
| 1702 | .protocol = options.protocol, |
| 1703 | }); |
| 1728 | 1704 | errdefer posix.close(socket_fd); |
| 1729 | 1705 | |
| 1730 | 1706 | if (options.reuse_address) { |
| ... | ... | @@ -1763,53 +1739,49 @@ fn netListenUnix( |
| 1763 | 1739 | ) Io.net.UnixAddress.ListenError!Io.net.Socket.Handle { |
| 1764 | 1740 | if (!Io.net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 1765 | 1741 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1766 | | const protocol: u32 = 0; |
| 1767 | | const socket_fd = while (true) { |
| 1768 | | try pool.checkCancel(); |
| 1769 | | const flags: u32 = posix.SOCK.STREAM | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; |
| 1770 | | const socket_rc = posix.system.socket(posix.AF.UNIX, flags, protocol); |
| 1771 | | switch (posix.errno(socket_rc)) { |
| 1772 | | .SUCCESS => { |
| 1773 | | const fd: posix.fd_t = @intCast(socket_rc); |
| 1774 | | errdefer posix.close(fd); |
| 1775 | | if (socket_flags_unsupported) while (true) { |
| 1776 | | try pool.checkCancel(); |
| 1777 | | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { |
| 1778 | | .SUCCESS => break, |
| 1779 | | .INTR => continue, |
| 1780 | | else => |err| return posix.unexpectedErrno(err), |
| 1781 | | } |
| 1782 | | }; |
| 1783 | | break fd; |
| 1784 | | }, |
| 1785 | | .INTR => continue, |
| 1786 | | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1787 | | .MFILE => return error.ProcessFdQuotaExceeded, |
| 1788 | | .NFILE => return error.SystemFdQuotaExceeded, |
| 1789 | | .NOBUFS => return error.SystemResources, |
| 1790 | | .NOMEM => return error.SystemResources, |
| 1791 | | else => |err| return posix.unexpectedErrno(err), |
| 1792 | | } |
| 1742 | const socket_fd = openSocketPosix(pool, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { |
| 1743 | error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported, |
| 1744 | error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, |
| 1745 | error.SocketModeUnsupported => return error.AddressFamilyUnsupported, |
| 1746 | else => |e| return e, |
| 1793 | 1747 | }; |
| 1794 | 1748 | errdefer posix.close(socket_fd); |
| 1795 | 1749 | |
| 1796 | 1750 | var storage: UnixAddress = undefined; |
| 1797 | 1751 | const addr_len = addressUnixToPosix(address, &storage); |
| 1752 | try posixBindUnix(pool, socket_fd, &storage.any, addr_len); |
| 1753 | |
| 1798 | 1754 | while (true) { |
| 1799 | 1755 | try pool.checkCancel(); |
| 1800 | | switch (posix.errno(posix.system.bind(socket_fd, &storage.any, addr_len))) { |
| 1756 | switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { |
| 1757 | .SUCCESS => break, |
| 1758 | .ADDRINUSE => return error.AddressInUse, |
| 1759 | .BADF => |err| return errnoBug(err), |
| 1760 | else => |err| return posix.unexpectedErrno(err), |
| 1761 | } |
| 1762 | } |
| 1763 | |
| 1764 | return socket_fd; |
| 1765 | } |
| 1766 | |
| 1767 | fn posixBindUnix(pool: *Pool, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1768 | while (true) { |
| 1769 | try pool.checkCancel(); |
| 1770 | switch (posix.errno(posix.system.bind(fd, addr, addr_len))) { |
| 1801 | 1771 | .SUCCESS => break, |
| 1802 | 1772 | .INTR => continue, |
| 1803 | 1773 | .ACCES => return error.AccessDenied, |
| 1804 | | .PERM => return error.PermissionDenied, |
| 1805 | 1774 | .ADDRINUSE => return error.AddressInUse, |
| 1806 | 1775 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1807 | 1776 | .ADDRNOTAVAIL => return error.AddressUnavailable, |
| 1808 | 1777 | .NOMEM => return error.SystemResources, |
| 1778 | |
| 1809 | 1779 | .LOOP => return error.SymLinkLoop, |
| 1810 | 1780 | .NOENT => return error.FileNotFound, |
| 1811 | 1781 | .NOTDIR => return error.NotDir, |
| 1812 | 1782 | .ROFS => return error.ReadOnlyFileSystem, |
| 1783 | .PERM => return error.PermissionDenied, |
| 1784 | |
| 1813 | 1785 | .BADF => |err| return errnoBug(err), // always a race condition if this error is returned |
| 1814 | 1786 | .INVAL => |err| return errnoBug(err), // invalid parameters |
| 1815 | 1787 | .NOTSOCK => |err| return errnoBug(err), // invalid `sockfd` |
| ... | ... | @@ -1818,18 +1790,6 @@ fn netListenUnix( |
| 1818 | 1790 | else => |err| return posix.unexpectedErrno(err), |
| 1819 | 1791 | } |
| 1820 | 1792 | } |
| 1821 | | |
| 1822 | | while (true) { |
| 1823 | | try pool.checkCancel(); |
| 1824 | | switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { |
| 1825 | | .SUCCESS => break, |
| 1826 | | .ADDRINUSE => return error.AddressInUse, |
| 1827 | | .BADF => |err| return errnoBug(err), |
| 1828 | | else => |err| return posix.unexpectedErrno(err), |
| 1829 | | } |
| 1830 | | } |
| 1831 | | |
| 1832 | | return socket_fd; |
| 1833 | 1793 | } |
| 1834 | 1794 | |
| 1835 | 1795 | fn posixBind(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| ... | ... | @@ -1857,7 +1817,6 @@ fn posixConnect(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.socka |
| 1857 | 1817 | switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) { |
| 1858 | 1818 | .SUCCESS => return, |
| 1859 | 1819 | .INTR => continue, |
| 1860 | | .ADDRINUSE => return error.AddressInUse, |
| 1861 | 1820 | .ADDRNOTAVAIL => return error.AddressUnavailable, |
| 1862 | 1821 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1863 | 1822 | .AGAIN, .INPROGRESS => return error.WouldBlock, |
| ... | ... | @@ -1866,7 +1825,7 @@ fn posixConnect(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.socka |
| 1866 | 1825 | .CONNREFUSED => return error.ConnectionRefused, |
| 1867 | 1826 | .CONNRESET => return error.ConnectionResetByPeer, |
| 1868 | 1827 | .FAULT => |err| return errnoBug(err), |
| 1869 | | .ISCONN => return error.AlreadyConnected, |
| 1828 | .ISCONN => |err| return errnoBug(err), |
| 1870 | 1829 | .HOSTUNREACH => return error.HostUnreachable, |
| 1871 | 1830 | .NETUNREACH => return error.NetworkUnreachable, |
| 1872 | 1831 | .NOTSOCK => |err| return errnoBug(err), |
| ... | ... | @@ -1874,7 +1833,6 @@ fn posixConnect(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.socka |
| 1874 | 1833 | .TIMEDOUT => return error.ConnectionTimedOut, |
| 1875 | 1834 | .CONNABORTED => |err| return errnoBug(err), |
| 1876 | 1835 | .ACCES => return error.AccessDenied, |
| 1877 | | // UNIX socket error codes: |
| 1878 | 1836 | .PERM => |err| return errnoBug(err), |
| 1879 | 1837 | .NOENT => |err| return errnoBug(err), |
| 1880 | 1838 | else => |err| return posix.unexpectedErrno(err), |
| ... | ... | @@ -1882,6 +1840,35 @@ fn posixConnect(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.socka |
| 1882 | 1840 | } |
| 1883 | 1841 | } |
| 1884 | 1842 | |
| 1843 | fn posixConnectUnix(pool: *Pool, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1844 | while (true) { |
| 1845 | try pool.checkCancel(); |
| 1846 | switch (posix.errno(posix.system.connect(fd, addr, addr_len))) { |
| 1847 | .SUCCESS => return, |
| 1848 | .INTR => continue, |
| 1849 | |
| 1850 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1851 | .AGAIN => return error.WouldBlock, |
| 1852 | .INPROGRESS => return error.WouldBlock, |
| 1853 | .ACCES => return error.AccessDenied, |
| 1854 | |
| 1855 | .LOOP => return error.SymLinkLoop, |
| 1856 | .NOENT => return error.FileNotFound, |
| 1857 | .NOTDIR => return error.NotDir, |
| 1858 | .ROFS => return error.ReadOnlyFileSystem, |
| 1859 | .PERM => return error.PermissionDenied, |
| 1860 | |
| 1861 | .BADF => |err| return errnoBug(err), |
| 1862 | .CONNABORTED => |err| return errnoBug(err), |
| 1863 | .FAULT => |err| return errnoBug(err), |
| 1864 | .ISCONN => |err| return errnoBug(err), |
| 1865 | .NOTSOCK => |err| return errnoBug(err), |
| 1866 | .PROTOTYPE => |err| return errnoBug(err), |
| 1867 | else => |err| return posix.unexpectedErrno(err), |
| 1868 | } |
| 1869 | } |
| 1870 | } |
| 1871 | |
| 1885 | 1872 | fn posixGetSockName(pool: *Pool, socket_fd: posix.fd_t, addr: *posix.sockaddr, addr_len: *posix.socklen_t) !void { |
| 1886 | 1873 | while (true) { |
| 1887 | 1874 | try pool.checkCancel(); |
| ... | ... | @@ -1926,6 +1913,7 @@ fn netConnectIpPosix( |
| 1926 | 1913 | .mode = options.mode, |
| 1927 | 1914 | .protocol = options.protocol, |
| 1928 | 1915 | }); |
| 1916 | errdefer posix.close(socket_fd); |
| 1929 | 1917 | var storage: PosixAddress = undefined; |
| 1930 | 1918 | var addr_len = addressToPosix(address, &storage); |
| 1931 | 1919 | try posixConnect(pool, socket_fd, &storage.any, addr_len); |
| ... | ... | @@ -1940,10 +1928,14 @@ fn netConnectUnix( |
| 1940 | 1928 | userdata: ?*anyopaque, |
| 1941 | 1929 | address: *const Io.net.UnixAddress, |
| 1942 | 1930 | ) Io.net.UnixAddress.ConnectError!Io.net.Socket.Handle { |
| 1931 | if (!Io.net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 1943 | 1932 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1944 | | _ = pool; |
| 1945 | | _ = address; |
| 1946 | | @panic("TODO"); |
| 1933 | const socket_fd = try openSocketPosix(pool, posix.AF.UNIX, .{ .mode = .stream }); |
| 1934 | errdefer posix.close(socket_fd); |
| 1935 | var storage: UnixAddress = undefined; |
| 1936 | const addr_len = addressUnixToPosix(address, &storage); |
| 1937 | try posixConnectUnix(pool, socket_fd, &storage.any, addr_len); |
| 1938 | return socket_fd; |
| 1947 | 1939 | } |
| 1948 | 1940 | |
| 1949 | 1941 | fn netBindIpPosix( |
| ... | ... | @@ -2497,18 +2489,16 @@ fn netInterfaceNameResolve( |
| 2497 | 2489 | name: *const Io.net.Interface.Name, |
| 2498 | 2490 | ) Io.net.Interface.Name.ResolveError!Io.net.Interface { |
| 2499 | 2491 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2500 | | try pool.checkCancel(); |
| 2501 | 2492 | |
| 2502 | 2493 | if (native_os == .linux) { |
| 2503 | | const rc = posix.system.socket(posix.AF.UNIX, posix.SOCK.DGRAM | posix.SOCK.CLOEXEC, 0); |
| 2504 | | const sock_fd: posix.fd_t = switch (posix.errno(rc)) { |
| 2505 | | .SUCCESS => @intCast(rc), |
| 2506 | | .ACCES => return error.AccessDenied, |
| 2507 | | .MFILE => return error.SystemResources, |
| 2508 | | .NFILE => return error.SystemResources, |
| 2509 | | .NOBUFS => return error.SystemResources, |
| 2510 | | .NOMEM => return error.SystemResources, |
| 2511 | | else => |err| return posix.unexpectedErrno(err), |
| 2494 | const sock_fd = openSocketPosix(pool, posix.AF.UNIX, .{ .mode = .dgram }) catch |err| switch (err) { |
| 2495 | error.ProcessFdQuotaExceeded => return error.SystemResources, |
| 2496 | error.SystemFdQuotaExceeded => return error.SystemResources, |
| 2497 | error.AddressFamilyUnsupported => return error.Unexpected, |
| 2498 | error.ProtocolUnsupportedBySystem => return error.Unexpected, |
| 2499 | error.ProtocolUnsupportedByAddressFamily => return error.Unexpected, |
| 2500 | error.SocketModeUnsupported => return error.Unexpected, |
| 2501 | else => |e| return e, |
| 2512 | 2502 | }; |
| 2513 | 2503 | defer posix.close(sock_fd); |
| 2514 | 2504 | |
| ... | ... | @@ -2521,12 +2511,12 @@ fn netInterfaceNameResolve( |
| 2521 | 2511 | try pool.checkCancel(); |
| 2522 | 2512 | switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { |
| 2523 | 2513 | .SUCCESS => return .{ .index = @bitCast(ifr.ifru.ivalue) }, |
| 2514 | .INTR => continue, |
| 2524 | 2515 | .INVAL => |err| return errnoBug(err), // Bad parameters. |
| 2525 | 2516 | .NOTTY => |err| return errnoBug(err), |
| 2526 | 2517 | .NXIO => |err| return errnoBug(err), |
| 2527 | 2518 | .BADF => |err| return errnoBug(err), // Always a race condition. |
| 2528 | 2519 | .FAULT => |err| return errnoBug(err), // Bad pointer parameter. |
| 2529 | | .INTR => continue, |
| 2530 | 2520 | .IO => |err| return errnoBug(err), // sock_fd is not a file descriptor |
| 2531 | 2521 | .NODEV => return error.InterfaceNotFound, |
| 2532 | 2522 | else => |err| return posix.unexpectedErrno(err), |
| ... | ... | @@ -2535,12 +2525,14 @@ fn netInterfaceNameResolve( |
| 2535 | 2525 | } |
| 2536 | 2526 | |
| 2537 | 2527 | if (native_os == .windows) { |
| 2528 | try pool.checkCancel(); |
| 2538 | 2529 | const index = std.os.windows.ws2_32.if_nametoindex(&name.bytes); |
| 2539 | 2530 | if (index == 0) return error.InterfaceNotFound; |
| 2540 | 2531 | return .{ .index = index }; |
| 2541 | 2532 | } |
| 2542 | 2533 | |
| 2543 | 2534 | if (builtin.link_libc) { |
| 2535 | try pool.checkCancel(); |
| 2544 | 2536 | const index = std.c.if_nametoindex(&name.bytes); |
| 2545 | 2537 | if (index == 0) return error.InterfaceNotFound; |
| 2546 | 2538 | return .{ .index = @bitCast(index) }; |
| ... | ... | @@ -2591,7 +2583,7 @@ fn addressFromPosix(posix_address: *PosixAddress) Io.net.IpAddress { |
| 2591 | 2583 | return switch (posix_address.any.family) { |
| 2592 | 2584 | posix.AF.INET => .{ .ip4 = address4FromPosix(&posix_address.in) }, |
| 2593 | 2585 | posix.AF.INET6 => .{ .ip6 = address6FromPosix(&posix_address.in6) }, |
| 2594 | | else => unreachable, |
| 2586 | else => .{ .ip4 = .loopback(0) }, |
| 2595 | 2587 | }; |
| 2596 | 2588 | } |
| 2597 | 2589 | |