From d96d7353387e10a2306f05d98955ac22db6e89e7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 7 Jan 2026 15:06:04 -0800 Subject: [PATCH] posix: remove send, sendto, sendmsg see #6600 --- lib/std/os/linux/IoUring/test.zig | 10 +- lib/std/posix.zig | 283 ------------------------------ 2 files changed, 9 insertions(+), 284 deletions(-) diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig index fb0013b9d1..c924fb3d2a 100644 --- a/lib/std/os/linux/IoUring/test.zig +++ b/lib/std/os/linux/IoUring/test.zig @@ -1874,7 +1874,7 @@ test "accept_direct" { try testing.expect(cqe_accept.user_data == accept_userdata); // send data - _ = try posix.send(client, buffer_send, 0); + _ = try send(client, buffer_send, 0); // Example of how to use registered fd: // 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 else => return error.GetSockNameFailure, } } + +fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize { + const rc = posix.system.sendto(sockfd, buf.ptr, buf.len, flags, null, 0); + switch (posix.errno(rc)) { + .SUCCESS => return @intCast(rc), + else => return error.SendFailed, + } +} diff --git a/lib/std/posix.zig b/lib/std/posix.zig index f3976f6909..986f3de9da 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -1545,289 +1545,6 @@ pub fn uname() utsname { } } -pub const SendError = error{ - /// (For UNIX domain sockets, which are identified by pathname) Write permission is denied - /// on the destination socket file, or search permission is denied for one of the - /// directories the path prefix. (See path_resolution(7).) - /// (For UDP sockets) An attempt was made to send to a network/broadcast address as though - /// it was a unicast address. - AccessDenied, - - /// The socket is marked nonblocking and the requested operation would block, and - /// there is no global event loop configured. - /// It's also possible to get this error under the following condition: - /// (Internet domain datagram sockets) The socket referred to by sockfd had not previously - /// been bound to an address and, upon attempting to bind it to an ephemeral port, it was - /// determined that all port numbers in the ephemeral port range are currently in use. See - /// the discussion of /proc/sys/net/ipv4/ip_local_port_range in ip(7). - WouldBlock, - - /// Another Fast Open is already in progress. - FastOpenAlreadyInProgress, - - /// Connection reset by peer. - ConnectionResetByPeer, - - /// The socket type requires that message be sent atomically, and the size of the message - /// to be sent made this impossible. The message is not transmitted. - MessageOversize, - - /// The output queue for a network interface was full. This generally indicates that the - /// interface has stopped sending, but may be caused by transient congestion. (Normally, - /// this does not occur in Linux. Packets are just silently dropped when a device queue - /// overflows.) - /// This is also caused when there is not enough kernel memory available. - SystemResources, - - /// The local end has been shut down on a connection oriented socket. In this case, the - /// process will also receive a SIGPIPE unless MSG.NOSIGNAL is set. - BrokenPipe, - - FileDescriptorNotASocket, - - /// Network is unreachable. - NetworkUnreachable, - - /// The local network interface used to reach the destination is down. - NetworkDown, - - /// The destination address is not listening. - ConnectionRefused, -} || UnexpectedError; - -pub const SendMsgError = SendError || error{ - /// The passed address didn't have the correct address family in its sa_family field. - AddressFamilyUnsupported, - - /// Returned when socket is AF.UNIX and the given path has a symlink loop. - SymLinkLoop, - - /// Returned when socket is AF.UNIX and the given path length exceeds `max_path_bytes` bytes. - NameTooLong, - - /// Returned when socket is AF.UNIX and the given path does not point to an existing file. - FileNotFound, - NotDir, - - /// The socket is not connected (connection-oriented sockets only). - SocketUnconnected, - AddressUnavailable, -}; - -pub fn sendmsg( - /// The file descriptor of the sending socket. - sockfd: socket_t, - /// Message header and iovecs - msg: *const msghdr_const, - flags: u32, -) SendMsgError!usize { - while (true) { - const rc = system.sendmsg(sockfd, msg, flags); - if (native_os == .windows) { - if (rc == windows.ws2_32.SOCKET_ERROR) { - switch (windows.ws2_32.WSAGetLastError()) { - .EACCES => return error.AccessDenied, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ECONNRESET => return error.ConnectionResetByPeer, - .EMSGSIZE => return error.MessageOversize, - .ENOBUFS => return error.SystemResources, - .ENOTSOCK => return error.FileDescriptorNotASocket, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .EDESTADDRREQ => unreachable, // A destination address is required. - .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. - .EHOSTUNREACH => return error.NetworkUnreachable, - // TODO: EINPROGRESS, EINTR - .EINVAL => unreachable, - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENETUNREACH => return error.NetworkUnreachable, - .ENOTCONN => return error.SocketUnconnected, - .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. - .EWOULDBLOCK => return error.WouldBlock, - .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. - else => |err| return windows.unexpectedWSAError(err), - } - } else { - return @intCast(rc); - } - } else { - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - - .ACCES => return error.AccessDenied, - .AGAIN => return error.WouldBlock, - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => unreachable, // always a race condition - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. - .FAULT => unreachable, // An invalid user space address was specified for an argument. - .INTR => continue, - .INVAL => unreachable, // Invalid argument passed. - .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageOversize, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. - .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .HOSTUNREACH => return error.NetworkUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return unexpectedErrno(err), - } - } - } -} - -pub const SendToError = SendMsgError || error{ - /// The destination address is not reachable by the bound address. - UnreachableAddress, - /// The destination address is not listening. - ConnectionRefused, -}; - -/// Transmit a message to another socket. -/// -/// The `sendto` call may be used only when the socket is in a connected state (so that the intended -/// recipient is known). The following call -/// -/// send(sockfd, buf, len, flags); -/// -/// is equivalent to -/// -/// sendto(sockfd, buf, len, flags, NULL, 0); -/// -/// If sendto() is used on a connection-mode (`SOCK.STREAM`, `SOCK.SEQPACKET`) socket, the arguments -/// `dest_addr` and `addrlen` are asserted to be `null` and `0` respectively, and asserted -/// that the socket was actually connected. -/// Otherwise, the address of the target is given by `dest_addr` with `addrlen` specifying its size. -/// -/// If the message is too long to pass atomically through the underlying protocol, -/// `SendError.MessageOversize` is returned, and the message is not transmitted. -/// -/// There is no indication of failure to deliver. -/// -/// When the message does not fit into the send buffer of the socket, `sendto` normally blocks, -/// unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail -/// with `SendError.WouldBlock`. The `select` call may be used to determine when it is -/// possible to send more data. -pub fn sendto( - /// The file descriptor of the sending socket. - sockfd: socket_t, - /// Message to send. - buf: []const u8, - flags: u32, - dest_addr: ?*const sockaddr, - addrlen: socklen_t, -) SendToError!usize { - if (native_os == .windows) { - switch (windows.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen)) { - windows.ws2_32.SOCKET_ERROR => switch (windows.ws2_32.WSAGetLastError()) { - .EACCES => return error.AccessDenied, - .EADDRNOTAVAIL => return error.AddressUnavailable, - .ECONNRESET => return error.ConnectionResetByPeer, - .EMSGSIZE => return error.MessageOversize, - .ENOBUFS => return error.SystemResources, - .ENOTSOCK => return error.FileDescriptorNotASocket, - .EAFNOSUPPORT => return error.AddressFamilyUnsupported, - .EDESTADDRREQ => unreachable, // A destination address is required. - .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. - .EHOSTUNREACH => return error.NetworkUnreachable, - // TODO: EINPROGRESS, EINTR - .EINVAL => unreachable, - .ENETDOWN => return error.NetworkDown, - .ENETRESET => return error.ConnectionResetByPeer, - .ENETUNREACH => return error.NetworkUnreachable, - .ENOTCONN => return error.SocketUnconnected, - .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. - .EWOULDBLOCK => return error.WouldBlock, - .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. - else => |err| return windows.unexpectedWSAError(err), - }, - else => |rc| return @intCast(rc), - } - } - while (true) { - const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - - .ACCES => return error.AccessDenied, - .AGAIN => return error.WouldBlock, - .ALREADY => return error.FastOpenAlreadyInProgress, - .BADF => unreachable, // always a race condition - .CONNREFUSED => return error.ConnectionRefused, - .CONNRESET => return error.ConnectionResetByPeer, - .DESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. - .FAULT => unreachable, // An invalid user space address was specified for an argument. - .INTR => continue, - .INVAL => return error.UnreachableAddress, - .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageOversize, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. - .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyUnsupported, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .HOSTUNREACH => return error.NetworkUnreachable, - .NETUNREACH => return error.NetworkUnreachable, - .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkDown, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Transmit a message to another socket. -/// -/// The `send` call may be used only when the socket is in a connected state (so that the intended -/// recipient is known). The only difference between `send` and `write` is the presence of -/// flags. With a zero flags argument, `send` is equivalent to `write`. Also, the following -/// call -/// -/// send(sockfd, buf, len, flags); -/// -/// is equivalent to -/// -/// sendto(sockfd, buf, len, flags, NULL, 0); -/// -/// There is no indication of failure to deliver. -/// -/// When the message does not fit into the send buffer of the socket, `send` normally blocks, -/// unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail -/// with `SendError.WouldBlock`. The `select` call may be used to determine when it is -/// possible to send more data. -pub fn send( - /// The file descriptor of the sending socket. - sockfd: socket_t, - buf: []const u8, - flags: u32, -) SendError!usize { - return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) { - error.AddressFamilyUnsupported => unreachable, - error.SymLinkLoop => unreachable, - error.NameTooLong => unreachable, - error.FileNotFound => unreachable, - error.NotDir => unreachable, - error.NetworkUnreachable => unreachable, - error.AddressUnavailable => unreachable, - error.SocketUnconnected => unreachable, - error.UnreachableAddress => unreachable, - else => |e| return e, - }; -} - pub const PollError = error{ /// The network subsystem has failed. NetworkDown,