mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
recvmsg: posix wrapper, void on windows
Also, added EPIPE to recvfrom() error set (it's a documented error for unix and tcp sockets, at least), which recvmsg() largely shares. Windows has an odd, callback-based form of recvmsg() that doesn't fit the normal interface here.
This commit is contained in:
parent
79313d844f
commit
c4c6c01cc5
2 changed files with 63 additions and 1 deletions
|
|
@ -10779,7 +10779,15 @@ pub extern "c" fn recvfrom(
|
|||
noalias src_addr: ?*sockaddr,
|
||||
noalias addrlen: ?*socklen_t,
|
||||
) if (native_os == .windows) c_int else isize;
|
||||
pub extern "c" fn recvmsg(sockfd: fd_t, msg: *msghdr, flags: u32) isize;
|
||||
|
||||
pub const recvmsg = switch (native_os) {
|
||||
// Windows: Technically, a form of recvmsg() exists for Windows, but the
|
||||
// user has to install some kind of callback for it. I'm not sure if/how
|
||||
// we can map this to normal recvmsg() interface use.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_wsarecvmsg
|
||||
.windows => void,
|
||||
else => private.recvmsg,
|
||||
};
|
||||
|
||||
pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;
|
||||
|
||||
|
|
@ -11424,6 +11432,7 @@ const private = struct {
|
|||
extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int;
|
||||
extern "c" fn readdir(dir: *DIR) ?*dirent;
|
||||
extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;
|
||||
extern "c" fn recvmsg(sockfd: fd_t, msg: *msghdr, flags: u32) isize;
|
||||
extern "c" fn sched_yield() c_int;
|
||||
extern "c" fn sendfile(out_fd: fd_t, in_fd: fd_t, offset: ?*off_t, count: usize) isize;
|
||||
extern "c" fn sigaction(sig: c_int, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) c_int;
|
||||
|
|
|
|||
|
|
@ -6644,6 +6644,9 @@ pub const RecvFromError = error{
|
|||
|
||||
/// The socket is not connected (connection-oriented sockets only).
|
||||
SocketNotConnected,
|
||||
|
||||
/// The other end closed the socket unexpectedly or a read is executed on a shut down socket
|
||||
BrokenPipe,
|
||||
} || UnexpectedError;
|
||||
|
||||
pub fn recv(sock: socket_t, buf: []u8, flags: u32) RecvFromError!usize {
|
||||
|
|
@ -6692,12 +6695,62 @@ pub fn recvfrom(
|
|||
.CONNREFUSED => return error.ConnectionRefused,
|
||||
.CONNRESET => return error.ConnectionResetByPeer,
|
||||
.TIMEDOUT => return error.ConnectionTimedOut,
|
||||
.PIPE => return error.BrokenPipe,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const RecvMsgError = RecvFromError || error{
|
||||
/// Reception of SCM_RIGHTS fds via ancillary data in msg.control would
|
||||
/// exceed some system limit (generally this is retryable by trying to
|
||||
/// receive fewer fds or closing some existing fds)
|
||||
SystemFdQuotaExceeded,
|
||||
|
||||
/// Reception of SCM_RIGHTS fds via ancillary data in msg.control would
|
||||
/// exceed some process limit (generally this is retryable by trying to
|
||||
/// receive fewer fds, closing some existing fds, or changing the ulimit)
|
||||
ProcessFdQuotaExceeded,
|
||||
};
|
||||
|
||||
/// If `sockfd` is opened in non blocking mode, the function will
|
||||
/// return error.WouldBlock when EAGAIN is received.
|
||||
pub fn recvmsg(
|
||||
/// The file descriptor of the sending socket.
|
||||
sockfd: socket_t,
|
||||
/// Message header and iovecs
|
||||
msg: *msghdr,
|
||||
flags: u32,
|
||||
) RecvMsgError!usize {
|
||||
if (@TypeOf(system.recvmsg) == void)
|
||||
@compileError("recvmsg() not supported on this OS");
|
||||
while (true) {
|
||||
const rc = system.recvmsg(sockfd, msg, flags);
|
||||
switch (errno(rc)) {
|
||||
.SUCCESS => return @intCast(rc),
|
||||
.AGAIN => return error.WouldBlock,
|
||||
.BADF => unreachable, // always a race condition
|
||||
.NFILE => return error.SystemFdQuotaExceeded,
|
||||
.MFILE => return error.ProcessFdQuotaExceeded,
|
||||
.INTR => continue,
|
||||
.FAULT => unreachable, // An invalid user space address was specified for an argument.
|
||||
.INVAL => unreachable, // Invalid argument passed.
|
||||
.ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified
|
||||
.NOBUFS => return error.SystemResources,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NOTCONN => return error.SocketNotConnected,
|
||||
.NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
|
||||
.MSGSIZE => return error.MessageTooBig,
|
||||
.PIPE => return error.BrokenPipe,
|
||||
.OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
|
||||
.CONNRESET => return error.ConnectionResetByPeer,
|
||||
.NETDOWN => return error.NetworkSubsystemFailed,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const DnExpandError = error{InvalidDnsPacket};
|
||||
|
||||
pub fn dn_expand(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue