Function sendmmsg [src]

Prototype

pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize

Parameters

fd: i32msgvec: [*]mmsghdr_constvlen: u32flags: u32

Source

pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize { if (@typeInfo(usize).int.bits > @typeInfo(@typeInfo(mmsghdr).@"struct".fields[1].type).int.bits) { // workaround kernel brokenness: // if adding up all iov_len overflows a i32 then split into multiple calls // see https://www.openwall.com/lists/musl/2014/06/07/5 const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel var next_unsent: usize = 0; for (msgvec[0..kvlen], 0..) |*msg, i| { var size: i32 = 0; const msg_iovlen = @as(usize, @intCast(msg.hdr.iovlen)); // kernel side this is treated as unsigned for (msg.hdr.iov[0..msg_iovlen]) |iov| { if (iov.len > std.math.maxInt(i32) or @addWithOverflow(size, @as(i32, @intCast(iov.len)))[1] != 0) { // batch-send all messages up to the current message if (next_unsent < i) { const batch_size = i - next_unsent; const r = syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(&msgvec[next_unsent]), batch_size, flags); if (E.init(r) != .SUCCESS) return next_unsent; if (r < batch_size) return next_unsent + r; } // send current message as own packet const r = sendmsg(fd, &msg.hdr, flags); if (E.init(r) != .SUCCESS) return r; // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe. msg.len = @as(u32, @intCast(r)); next_unsent = i + 1; break; } size += @intCast(iov.len); } } if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG.EOR) const batch_size = kvlen - next_unsent; const r = syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(&msgvec[next_unsent]), batch_size, flags); if (E.init(r) != .SUCCESS) return r; return next_unsent + r; } return kvlen; } return syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(msgvec), vlen, flags); }