authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-07 15:06:04-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-07 17:33:07-08:00
logd96d7353387e10a2306f05d98955ac22db6e89e7
tree33ecf55831086c346db1f09b061713f94063f118
parent791baefff2c0130dadbce7fd5abc69ec7df8cc53

posix: remove send, sendto, sendmsg

see #6600

2 files changed, 9 insertions(+), 284 deletions(-)

lib/std/os/linux/IoUring/test.zig+9-1
...@@ -1874,7 +1874,7 @@ test "accept_direct" {...@@ -1874,7 +1874,7 @@ test "accept_direct" {
1874 try testing.expect(cqe_accept.user_data == accept_userdata);1874 try testing.expect(cqe_accept.user_data == accept_userdata);
18751875
1876 // send data1876 // send data
1877 _ = try posix.send(client, buffer_send, 0);1877 _ = try send(client, buffer_send, 0);
18781878
1879 // Example of how to use registered fd:1879 // Example of how to use registered fd:
1880 // Submit receive to fixed file returned by accept (fd_index).1880 // Submit receive to fixed file returned by accept (fd_index).
...@@ -2724,3 +2724,11 @@ fn getsockname(sock: posix.socket_t, addr: *posix.sockaddr, addrlen: *posix.sock...@@ -2724,3 +2724,11 @@ fn getsockname(sock: posix.socket_t, addr: *posix.sockaddr, addrlen: *posix.sock
2724 else => return error.GetSockNameFailure,2724 else => return error.GetSockNameFailure,
2725 }2725 }
2726}2726}
2727
2728fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize {
2729 const rc = posix.system.sendto(sockfd, buf.ptr, buf.len, flags, null, 0);
2730 switch (posix.errno(rc)) {
2731 .SUCCESS => return @intCast(rc),
2732 else => return error.SendFailed,
2733 }
2734}
lib/std/posix.zig-283
...@@ -1545,289 +1545,6 @@ pub fn uname() utsname {...@@ -1545,289 +1545,6 @@ pub fn uname() utsname {
1545 }1545 }
1546}1546}
15471547
1548pub 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
1598pub 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
1617pub 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
1688pub 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.
1720pub 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.
1811pub 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
1831pub const PollError = error{1548pub const PollError = error{
1832 /// The network subsystem has failed.1549 /// The network subsystem has failed.
1833 NetworkDown,1550 NetworkDown,