| ... | ... | @@ -1545,289 +1545,6 @@ pub fn uname() utsname { |
| 1545 | 1545 | } |
| 1546 | 1546 | } |
| 1547 | 1547 | |
| 1548 | | pub const SendError = error{ |
| 1549 | | /// (For UNIX domain sockets, which are identified by pathname) Write permission is denied |
| 1550 | | /// on the destination socket file, or search permission is denied for one of the |
| 1551 | | /// directories the path prefix. (See path_resolution(7).) |
| 1552 | | /// (For UDP sockets) An attempt was made to send to a network/broadcast address as though |
| 1553 | | /// it was a unicast address. |
| 1554 | | AccessDenied, |
| 1555 | | |
| 1556 | | /// The socket is marked nonblocking and the requested operation would block, and |
| 1557 | | /// there is no global event loop configured. |
| 1558 | | /// It's also possible to get this error under the following condition: |
| 1559 | | /// (Internet domain datagram sockets) The socket referred to by sockfd had not previously |
| 1560 | | /// been bound to an address and, upon attempting to bind it to an ephemeral port, it was |
| 1561 | | /// determined that all port numbers in the ephemeral port range are currently in use. See |
| 1562 | | /// the discussion of /proc/sys/net/ipv4/ip_local_port_range in ip(7). |
| 1563 | | WouldBlock, |
| 1564 | | |
| 1565 | | /// Another Fast Open is already in progress. |
| 1566 | | FastOpenAlreadyInProgress, |
| 1567 | | |
| 1568 | | /// Connection reset by peer. |
| 1569 | | ConnectionResetByPeer, |
| 1570 | | |
| 1571 | | /// The socket type requires that message be sent atomically, and the size of the message |
| 1572 | | /// to be sent made this impossible. The message is not transmitted. |
| 1573 | | MessageOversize, |
| 1574 | | |
| 1575 | | /// The output queue for a network interface was full. This generally indicates that the |
| 1576 | | /// interface has stopped sending, but may be caused by transient congestion. (Normally, |
| 1577 | | /// this does not occur in Linux. Packets are just silently dropped when a device queue |
| 1578 | | /// overflows.) |
| 1579 | | /// This is also caused when there is not enough kernel memory available. |
| 1580 | | SystemResources, |
| 1581 | | |
| 1582 | | /// The local end has been shut down on a connection oriented socket. In this case, the |
| 1583 | | /// process will also receive a SIGPIPE unless MSG.NOSIGNAL is set. |
| 1584 | | BrokenPipe, |
| 1585 | | |
| 1586 | | FileDescriptorNotASocket, |
| 1587 | | |
| 1588 | | /// Network is unreachable. |
| 1589 | | NetworkUnreachable, |
| 1590 | | |
| 1591 | | /// The local network interface used to reach the destination is down. |
| 1592 | | NetworkDown, |
| 1593 | | |
| 1594 | | /// The destination address is not listening. |
| 1595 | | ConnectionRefused, |
| 1596 | | } || UnexpectedError; |
| 1597 | | |
| 1598 | | pub const SendMsgError = SendError || error{ |
| 1599 | | /// The passed address didn't have the correct address family in its sa_family field. |
| 1600 | | AddressFamilyUnsupported, |
| 1601 | | |
| 1602 | | /// Returned when socket is AF.UNIX and the given path has a symlink loop. |
| 1603 | | SymLinkLoop, |
| 1604 | | |
| 1605 | | /// Returned when socket is AF.UNIX and the given path length exceeds `max_path_bytes` bytes. |
| 1606 | | NameTooLong, |
| 1607 | | |
| 1608 | | /// Returned when socket is AF.UNIX and the given path does not point to an existing file. |
| 1609 | | FileNotFound, |
| 1610 | | NotDir, |
| 1611 | | |
| 1612 | | /// The socket is not connected (connection-oriented sockets only). |
| 1613 | | SocketUnconnected, |
| 1614 | | AddressUnavailable, |
| 1615 | | }; |
| 1616 | | |
| 1617 | | pub fn sendmsg( |
| 1618 | | /// The file descriptor of the sending socket. |
| 1619 | | sockfd: socket_t, |
| 1620 | | /// Message header and iovecs |
| 1621 | | msg: *const msghdr_const, |
| 1622 | | flags: u32, |
| 1623 | | ) SendMsgError!usize { |
| 1624 | | while (true) { |
| 1625 | | const rc = system.sendmsg(sockfd, msg, flags); |
| 1626 | | if (native_os == .windows) { |
| 1627 | | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| 1628 | | switch (windows.ws2_32.WSAGetLastError()) { |
| 1629 | | .EACCES => return error.AccessDenied, |
| 1630 | | .EADDRNOTAVAIL => return error.AddressUnavailable, |
| 1631 | | .ECONNRESET => return error.ConnectionResetByPeer, |
| 1632 | | .EMSGSIZE => return error.MessageOversize, |
| 1633 | | .ENOBUFS => return error.SystemResources, |
| 1634 | | .ENOTSOCK => return error.FileDescriptorNotASocket, |
| 1635 | | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1636 | | .EDESTADDRREQ => unreachable, // A destination address is required. |
| 1637 | | .EFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. |
| 1638 | | .EHOSTUNREACH => return error.NetworkUnreachable, |
| 1639 | | // TODO: EINPROGRESS, EINTR |
| 1640 | | .EINVAL => unreachable, |
| 1641 | | .ENETDOWN => return error.NetworkDown, |
| 1642 | | .ENETRESET => return error.ConnectionResetByPeer, |
| 1643 | | .ENETUNREACH => return error.NetworkUnreachable, |
| 1644 | | .ENOTCONN => return error.SocketUnconnected, |
| 1645 | | .ESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. |
| 1646 | | .EWOULDBLOCK => return error.WouldBlock, |
| 1647 | | .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. |
| 1648 | | else => |err| return windows.unexpectedWSAError(err), |
| 1649 | | } |
| 1650 | | } else { |
| 1651 | | return @intCast(rc); |
| 1652 | | } |
| 1653 | | } else { |
| 1654 | | switch (errno(rc)) { |
| 1655 | | .SUCCESS => return @intCast(rc), |
| 1656 | | |
| 1657 | | .ACCES => return error.AccessDenied, |
| 1658 | | .AGAIN => return error.WouldBlock, |
| 1659 | | .ALREADY => return error.FastOpenAlreadyInProgress, |
| 1660 | | .BADF => unreachable, // always a race condition |
| 1661 | | .CONNRESET => return error.ConnectionResetByPeer, |
| 1662 | | .DESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. |
| 1663 | | .FAULT => unreachable, // An invalid user space address was specified for an argument. |
| 1664 | | .INTR => continue, |
| 1665 | | .INVAL => unreachable, // Invalid argument passed. |
| 1666 | | .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified |
| 1667 | | .MSGSIZE => return error.MessageOversize, |
| 1668 | | .NOBUFS => return error.SystemResources, |
| 1669 | | .NOMEM => return error.SystemResources, |
| 1670 | | .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. |
| 1671 | | .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. |
| 1672 | | .PIPE => return error.BrokenPipe, |
| 1673 | | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1674 | | .LOOP => return error.SymLinkLoop, |
| 1675 | | .NAMETOOLONG => return error.NameTooLong, |
| 1676 | | .NOENT => return error.FileNotFound, |
| 1677 | | .NOTDIR => return error.NotDir, |
| 1678 | | .HOSTUNREACH => return error.NetworkUnreachable, |
| 1679 | | .NETUNREACH => return error.NetworkUnreachable, |
| 1680 | | .NOTCONN => return error.SocketUnconnected, |
| 1681 | | .NETDOWN => return error.NetworkDown, |
| 1682 | | else => |err| return unexpectedErrno(err), |
| 1683 | | } |
| 1684 | | } |
| 1685 | | } |
| 1686 | | } |
| 1687 | | |
| 1688 | | pub const SendToError = SendMsgError || error{ |
| 1689 | | /// The destination address is not reachable by the bound address. |
| 1690 | | UnreachableAddress, |
| 1691 | | /// The destination address is not listening. |
| 1692 | | ConnectionRefused, |
| 1693 | | }; |
| 1694 | | |
| 1695 | | /// Transmit a message to another socket. |
| 1696 | | /// |
| 1697 | | /// The `sendto` call may be used only when the socket is in a connected state (so that the intended |
| 1698 | | /// recipient is known). The following call |
| 1699 | | /// |
| 1700 | | /// send(sockfd, buf, len, flags); |
| 1701 | | /// |
| 1702 | | /// is equivalent to |
| 1703 | | /// |
| 1704 | | /// sendto(sockfd, buf, len, flags, NULL, 0); |
| 1705 | | /// |
| 1706 | | /// If sendto() is used on a connection-mode (`SOCK.STREAM`, `SOCK.SEQPACKET`) socket, the arguments |
| 1707 | | /// `dest_addr` and `addrlen` are asserted to be `null` and `0` respectively, and asserted |
| 1708 | | /// that the socket was actually connected. |
| 1709 | | /// Otherwise, the address of the target is given by `dest_addr` with `addrlen` specifying its size. |
| 1710 | | /// |
| 1711 | | /// If the message is too long to pass atomically through the underlying protocol, |
| 1712 | | /// `SendError.MessageOversize` is returned, and the message is not transmitted. |
| 1713 | | /// |
| 1714 | | /// There is no indication of failure to deliver. |
| 1715 | | /// |
| 1716 | | /// When the message does not fit into the send buffer of the socket, `sendto` normally blocks, |
| 1717 | | /// unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail |
| 1718 | | /// with `SendError.WouldBlock`. The `select` call may be used to determine when it is |
| 1719 | | /// possible to send more data. |
| 1720 | | pub fn sendto( |
| 1721 | | /// The file descriptor of the sending socket. |
| 1722 | | sockfd: socket_t, |
| 1723 | | /// Message to send. |
| 1724 | | buf: []const u8, |
| 1725 | | flags: u32, |
| 1726 | | dest_addr: ?*const sockaddr, |
| 1727 | | addrlen: socklen_t, |
| 1728 | | ) SendToError!usize { |
| 1729 | | if (native_os == .windows) { |
| 1730 | | switch (windows.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen)) { |
| 1731 | | windows.ws2_32.SOCKET_ERROR => switch (windows.ws2_32.WSAGetLastError()) { |
| 1732 | | .EACCES => return error.AccessDenied, |
| 1733 | | .EADDRNOTAVAIL => return error.AddressUnavailable, |
| 1734 | | .ECONNRESET => return error.ConnectionResetByPeer, |
| 1735 | | .EMSGSIZE => return error.MessageOversize, |
| 1736 | | .ENOBUFS => return error.SystemResources, |
| 1737 | | .ENOTSOCK => return error.FileDescriptorNotASocket, |
| 1738 | | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1739 | | .EDESTADDRREQ => unreachable, // A destination address is required. |
| 1740 | | .EFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. |
| 1741 | | .EHOSTUNREACH => return error.NetworkUnreachable, |
| 1742 | | // TODO: EINPROGRESS, EINTR |
| 1743 | | .EINVAL => unreachable, |
| 1744 | | .ENETDOWN => return error.NetworkDown, |
| 1745 | | .ENETRESET => return error.ConnectionResetByPeer, |
| 1746 | | .ENETUNREACH => return error.NetworkUnreachable, |
| 1747 | | .ENOTCONN => return error.SocketUnconnected, |
| 1748 | | .ESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. |
| 1749 | | .EWOULDBLOCK => return error.WouldBlock, |
| 1750 | | .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. |
| 1751 | | else => |err| return windows.unexpectedWSAError(err), |
| 1752 | | }, |
| 1753 | | else => |rc| return @intCast(rc), |
| 1754 | | } |
| 1755 | | } |
| 1756 | | while (true) { |
| 1757 | | const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen); |
| 1758 | | switch (errno(rc)) { |
| 1759 | | .SUCCESS => return @intCast(rc), |
| 1760 | | |
| 1761 | | .ACCES => return error.AccessDenied, |
| 1762 | | .AGAIN => return error.WouldBlock, |
| 1763 | | .ALREADY => return error.FastOpenAlreadyInProgress, |
| 1764 | | .BADF => unreachable, // always a race condition |
| 1765 | | .CONNREFUSED => return error.ConnectionRefused, |
| 1766 | | .CONNRESET => return error.ConnectionResetByPeer, |
| 1767 | | .DESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. |
| 1768 | | .FAULT => unreachable, // An invalid user space address was specified for an argument. |
| 1769 | | .INTR => continue, |
| 1770 | | .INVAL => return error.UnreachableAddress, |
| 1771 | | .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified |
| 1772 | | .MSGSIZE => return error.MessageOversize, |
| 1773 | | .NOBUFS => return error.SystemResources, |
| 1774 | | .NOMEM => return error.SystemResources, |
| 1775 | | .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. |
| 1776 | | .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. |
| 1777 | | .PIPE => return error.BrokenPipe, |
| 1778 | | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 1779 | | .LOOP => return error.SymLinkLoop, |
| 1780 | | .NAMETOOLONG => return error.NameTooLong, |
| 1781 | | .NOENT => return error.FileNotFound, |
| 1782 | | .NOTDIR => return error.NotDir, |
| 1783 | | .HOSTUNREACH => return error.NetworkUnreachable, |
| 1784 | | .NETUNREACH => return error.NetworkUnreachable, |
| 1785 | | .NOTCONN => return error.SocketUnconnected, |
| 1786 | | .NETDOWN => return error.NetworkDown, |
| 1787 | | else => |err| return unexpectedErrno(err), |
| 1788 | | } |
| 1789 | | } |
| 1790 | | } |
| 1791 | | |
| 1792 | | /// Transmit a message to another socket. |
| 1793 | | /// |
| 1794 | | /// The `send` call may be used only when the socket is in a connected state (so that the intended |
| 1795 | | /// recipient is known). The only difference between `send` and `write` is the presence of |
| 1796 | | /// flags. With a zero flags argument, `send` is equivalent to `write`. Also, the following |
| 1797 | | /// call |
| 1798 | | /// |
| 1799 | | /// send(sockfd, buf, len, flags); |
| 1800 | | /// |
| 1801 | | /// is equivalent to |
| 1802 | | /// |
| 1803 | | /// sendto(sockfd, buf, len, flags, NULL, 0); |
| 1804 | | /// |
| 1805 | | /// There is no indication of failure to deliver. |
| 1806 | | /// |
| 1807 | | /// When the message does not fit into the send buffer of the socket, `send` normally blocks, |
| 1808 | | /// unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail |
| 1809 | | /// with `SendError.WouldBlock`. The `select` call may be used to determine when it is |
| 1810 | | /// possible to send more data. |
| 1811 | | pub fn send( |
| 1812 | | /// The file descriptor of the sending socket. |
| 1813 | | sockfd: socket_t, |
| 1814 | | buf: []const u8, |
| 1815 | | flags: u32, |
| 1816 | | ) SendError!usize { |
| 1817 | | return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) { |
| 1818 | | error.AddressFamilyUnsupported => unreachable, |
| 1819 | | error.SymLinkLoop => unreachable, |
| 1820 | | error.NameTooLong => unreachable, |
| 1821 | | error.FileNotFound => unreachable, |
| 1822 | | error.NotDir => unreachable, |
| 1823 | | error.NetworkUnreachable => unreachable, |
| 1824 | | error.AddressUnavailable => unreachable, |
| 1825 | | error.SocketUnconnected => unreachable, |
| 1826 | | error.UnreachableAddress => unreachable, |
| 1827 | | else => |e| return e, |
| 1828 | | }; |
| 1829 | | } |
| 1830 | | |
| 1831 | 1548 | pub const PollError = error{ |
| 1832 | 1549 | /// The network subsystem has failed. |
| 1833 | 1550 | NetworkDown, |