mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
std: add sendmsg
This commit is contained in:
parent
294ee1bbc9
commit
1f17221bc4
@ -4840,7 +4840,7 @@ pub const SendError = error{
|
||||
NetworkSubsystemFailed,
|
||||
} || UnexpectedError;
|
||||
|
||||
pub const SendToError = SendError || error{
|
||||
pub const SendMsgError = SendError || error{
|
||||
/// The passed address didn't have the correct address family in its sa_family field.
|
||||
AddressFamilyNotSupported,
|
||||
|
||||
@ -4859,6 +4859,79 @@ pub const SendToError = SendError || error{
|
||||
AddressNotAvailable,
|
||||
};
|
||||
|
||||
pub fn sendmsg(
|
||||
/// The file descriptor of the sending socket.
|
||||
sockfd: socket_t,
|
||||
/// Message header and iovecs
|
||||
msg: msghdr_const,
|
||||
flags: u32,
|
||||
) SendMsgError!usize {
|
||||
while (true) {
|
||||
const rc = system.sendmsg(sockfd, &msg, flags);
|
||||
if (builtin.os.tag == .windows) {
|
||||
if (rc == windows.ws2_32.SOCKET_ERROR) {
|
||||
switch (windows.ws2_32.WSAGetLastError()) {
|
||||
.WSAEACCES => return error.AccessDenied,
|
||||
.WSAEADDRNOTAVAIL => return error.AddressNotAvailable,
|
||||
.WSAECONNRESET => return error.ConnectionResetByPeer,
|
||||
.WSAEMSGSIZE => return error.MessageTooBig,
|
||||
.WSAENOBUFS => return error.SystemResources,
|
||||
.WSAENOTSOCK => return error.FileDescriptorNotASocket,
|
||||
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
|
||||
.WSAEDESTADDRREQ => unreachable, // A destination address is required.
|
||||
.WSAEFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small.
|
||||
.WSAEHOSTUNREACH => return error.NetworkUnreachable,
|
||||
// TODO: WSAEINPROGRESS, WSAEINTR
|
||||
.WSAEINVAL => unreachable,
|
||||
.WSAENETDOWN => return error.NetworkSubsystemFailed,
|
||||
.WSAENETRESET => return error.ConnectionResetByPeer,
|
||||
.WSAENETUNREACH => return error.NetworkUnreachable,
|
||||
.WSAENOTCONN => return error.SocketNotConnected,
|
||||
.WSAESHUTDOWN => 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.
|
||||
.WSAEWOULDBLOCK => return error.WouldBlock,
|
||||
.WSANOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function.
|
||||
else => |err| return windows.unexpectedWSAError(err),
|
||||
}
|
||||
} else {
|
||||
return @intCast(usize, rc);
|
||||
}
|
||||
} else {
|
||||
switch (errno(rc)) {
|
||||
0 => return @intCast(usize, rc),
|
||||
|
||||
EACCES => return error.AccessDenied,
|
||||
EAGAIN => return error.WouldBlock,
|
||||
EALREADY => return error.FastOpenAlreadyInProgress,
|
||||
EBADF => unreachable, // always a race condition
|
||||
ECONNRESET => return error.ConnectionResetByPeer,
|
||||
EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set.
|
||||
EFAULT => unreachable, // An invalid user space address was specified for an argument.
|
||||
EINTR => continue,
|
||||
EINVAL => unreachable, // Invalid argument passed.
|
||||
EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified
|
||||
EMSGSIZE => return error.MessageTooBig,
|
||||
ENOBUFS => return error.SystemResources,
|
||||
ENOMEM => return error.SystemResources,
|
||||
ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
|
||||
EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
|
||||
EPIPE => return error.BrokenPipe,
|
||||
EAFNOSUPPORT => return error.AddressFamilyNotSupported,
|
||||
ELOOP => return error.SymLinkLoop,
|
||||
ENAMETOOLONG => return error.NameTooLong,
|
||||
ENOENT => return error.FileNotFound,
|
||||
ENOTDIR => return error.NotDir,
|
||||
EHOSTUNREACH => return error.NetworkUnreachable,
|
||||
ENETUNREACH => return error.NetworkUnreachable,
|
||||
ENOTCONN => return error.SocketNotConnected,
|
||||
ENETDOWN => return error.NetworkSubsystemFailed,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const SendToError = SendMsgError;
|
||||
|
||||
/// 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
|
||||
|
||||
@ -400,10 +400,10 @@ pub const msghdr = extern struct {
|
||||
msg_namelen: socklen_t,
|
||||
msg_iov: [*]iovec,
|
||||
msg_iovlen: i32,
|
||||
__pad1: i32,
|
||||
__pad1: i32 = 0,
|
||||
msg_control: ?*c_void,
|
||||
msg_controllen: socklen_t,
|
||||
__pad2: socklen_t,
|
||||
__pad2: socklen_t = 0,
|
||||
msg_flags: i32,
|
||||
};
|
||||
|
||||
@ -412,10 +412,10 @@ pub const msghdr_const = extern struct {
|
||||
msg_namelen: socklen_t,
|
||||
msg_iov: [*]iovec_const,
|
||||
msg_iovlen: i32,
|
||||
__pad1: i32,
|
||||
__pad1: i32 = 0,
|
||||
msg_control: ?*c_void,
|
||||
msg_controllen: socklen_t,
|
||||
__pad2: socklen_t,
|
||||
__pad2: socklen_t = 0,
|
||||
msg_flags: i32,
|
||||
};
|
||||
|
||||
|
||||
@ -495,10 +495,10 @@ pub const msghdr = extern struct {
|
||||
msg_namelen: socklen_t,
|
||||
msg_iov: [*]iovec,
|
||||
msg_iovlen: i32,
|
||||
__pad1: i32,
|
||||
__pad1: i32 = 0,
|
||||
msg_control: ?*c_void,
|
||||
msg_controllen: socklen_t,
|
||||
__pad2: socklen_t,
|
||||
__pad2: socklen_t = 0,
|
||||
msg_flags: i32,
|
||||
};
|
||||
|
||||
@ -507,10 +507,10 @@ pub const msghdr_const = extern struct {
|
||||
msg_namelen: socklen_t,
|
||||
msg_iov: [*]iovec_const,
|
||||
msg_iovlen: i32,
|
||||
__pad1: i32,
|
||||
__pad1: i32 = 0,
|
||||
msg_control: ?*c_void,
|
||||
msg_controllen: socklen_t,
|
||||
__pad2: socklen_t,
|
||||
__pad2: socklen_t = 0,
|
||||
msg_flags: i32,
|
||||
};
|
||||
|
||||
|
||||
@ -977,7 +977,7 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal
|
||||
return syscall5(.getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
|
||||
}
|
||||
|
||||
pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
|
||||
pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize {
|
||||
if (builtin.arch == .i386) {
|
||||
return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags });
|
||||
}
|
||||
|
||||
@ -1291,6 +1291,19 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
|
||||
return ws2_32.getsockname(s, name, @ptrCast(*i32, namelen));
|
||||
}
|
||||
|
||||
pub fn sendmsg(
|
||||
s: ws2_32.SOCKET,
|
||||
msg: *const ws2_32.WSAMSG,
|
||||
flags: u32,
|
||||
) i32 {
|
||||
var bytes_send: DWORD = undefined;
|
||||
if (ws2_32.WSASendMsg(s, msg, flags, &bytes_send, null, null) == ws2_32.SOCKET_ERROR) {
|
||||
return ws2_32.SOCKET_ERROR;
|
||||
} else {
|
||||
return @as(i32, @intCast(u31, bytes_send));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
|
||||
var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) };
|
||||
var bytes_send: DWORD = undefined;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user