feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.netReceivePosix
fn netReceivePosix(
socket_handle: net.Socket.Handle,
message: *net.IncomingMessage,
data_buffer: []u8,
flags: net.ReceiveFlags,
nonblocking: bool,
) (net.Socket.ReceiveError || error
File
Code
fn netReceivePosix(
socket_handle: net.Socket.Handle,
message: *net.IncomingMessage,
data_buffer: []u8,
flags: net.ReceiveFlags,
nonblocking: bool,
) (net.Socket.ReceiveError || error{WouldBlock})!void {
// * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371)
// * it wants iovecs for each message but we have a better API: one data
// buffer to handle all the messages. The better API cannot be lowered to
// the split vectors though because reducing the buffer size might make
// some messages unreceivable.
const posix_flags: u32 =
@as(u32, if (flags.oob) posix.MSG.OOB else 0) |
@as(u32, if (flags.peek) posix.MSG.PEEK else 0) |
@as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) |
posix.MSG.NOSIGNAL |
@as(u32, if (nonblocking) posix.MSG.DONTWAIT else 0);
var storage: PosixAddress = undefined;
var iov: posix.iovec = .{ .base = data_buffer.ptr, .len = data_buffer.len };
var msg: posix.msghdr = .{
.name = &storage.any,
.namelen = @sizeOf(PosixAddress),
.iov = (&iov)[0..1],
.iovlen = 1,
.control = message.control.ptr,
.controllen = @intCast(message.control.len),
.flags = undefined,
};
const syscall = try Syscall.start();
while (true) {
const rc = posix.system.recvmsg(socket_handle, &msg, posix_flags);
switch (posix.errno(rc)) {
.SUCCESS => {
syscall.finish();
const data = data_buffer[0..@intCast(rc)];
message.* = .{
.from = addressFromPosix(&storage),
.data = data,
.control = if (msg.control) |ptr| @as([*]u8, @ptrCast(ptr))[0..msg.controllen] else message.control,
.flags = .{
.eor = (msg.flags & posix.MSG.EOR) != 0,
.trunc = (msg.flags & posix.MSG.TRUNC) != 0,
.ctrunc = (msg.flags & posix.MSG.CTRUNC) != 0,
.oob = (msg.flags & posix.MSG.OOB) != 0,
.errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false,
},
};
return;
},
.INTR => {
try syscall.checkCancel();
continue;
},
.NFILE => return syscall.fail(error.SystemFdQuotaExceeded),
.MFILE => return syscall.fail(error.ProcessFdQuotaExceeded),
.NOBUFS => return syscall.fail(error.SystemResources),
.NOMEM => return syscall.fail(error.SystemResources),
.NOTCONN => return syscall.fail(error.SocketUnconnected),
.MSGSIZE => return syscall.fail(error.MessageOversize),
.PIPE => return syscall.fail(error.SocketUnconnected),
.CONNRESET => return syscall.fail(error.ConnectionResetByPeer),
.NETDOWN => return syscall.fail(error.NetworkDown),
.AGAIN => return syscall.fail(error.WouldBlock),
.BADF => |err| return syscall.errnoBug(err),
.FAULT => |err| return syscall.errnoBug(err),
.INVAL => |err| return syscall.errnoBug(err),
.NOTSOCK => |err| return syscall.errnoBug(err),
.OPNOTSUPP => |err| return syscall.errnoBug(err),
else => |err| return syscall.unexpectedErrno(err),
}
}
}