mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user