| ... | @@ -1545,289 +1545,6 @@ pub fn uname() utsname { | ... | @@ -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 | pub const PollError = error{ | 1548 | pub const PollError = error{ |
| 1832 | /// The network subsystem has failed. | 1549 | /// The network subsystem has failed. |
| 1833 | NetworkDown, | 1550 | NetworkDown, |