use crate::backend::c;
use crate::io::{self, IoSlice, IoSliceMut};
use crate::net::addr::SocketAddrArg;
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrBuf};
use core::mem::zeroed;
#[cfg(all(
not(any(windows, target_os = "espidf", target_os = "wasi")),
any(
target_os = "android",
target_os = "redox",
all(
target_os = "linux",
not(target_env = "musl"),
not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
)
)
))]
#[inline]
fn msg_iov_len(len: usize) -> c::size_t {
len
}
#[cfg(all(
not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")),
not(any(
target_os = "android",
target_os = "redox",
all(
target_os = "linux",
not(target_env = "musl"),
not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
)
))
))]
#[inline]
fn msg_iov_len(len: usize) -> c::c_int {
len.try_into().unwrap_or(c::c_int::MAX)
}
#[cfg(any(
bsd,
solarish,
target_env = "musl",
target_os = "aix",
target_os = "cygwin",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "hurd",
target_os = "nto",
))]
#[inline]
fn msg_control_len(len: usize) -> c::socklen_t {
len.try_into().unwrap_or(c::socklen_t::MAX)
}
#[cfg(not(any(
bsd,
solarish,
windows,
target_env = "musl",
target_os = "aix",
target_os = "cygwin",
target_os = "emscripten",
target_os = "espidf",
target_os = "fuchsia",
target_os = "haiku",
target_os = "hurd",
target_os = "nto",
target_os = "vita",
target_os = "wasi",
)))]
#[inline]
fn msg_control_len(len: usize) -> c::size_t {
len
}
pub(crate) unsafe fn with_recv_msghdr<R>(
name: &mut SocketAddrBuf,
iov: &mut [IoSliceMut<'_>],
control: &mut RecvAncillaryBuffer<'_>,
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
) -> io::Result<R> {
control.clear();
let mut msghdr = zero_msghdr();
msghdr.msg_name = name.storage.as_mut_ptr().cast();
msghdr.msg_namelen = name.len;
msghdr.msg_iov = iov.as_mut_ptr().cast();
msghdr.msg_iovlen = msg_iov_len(iov.len());
msghdr.msg_control = control.as_control_ptr().cast();
msghdr.msg_controllen = msg_control_len(control.control_len());
let res = f(&mut msghdr);
if res.is_ok() {
control.set_control_len(msghdr.msg_controllen as usize);
}
name.len = msghdr.msg_namelen;
res
}
pub(crate) fn noaddr_msghdr(
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
) -> c::msghdr {
let mut h = zero_msghdr();
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
h
}
pub(crate) unsafe fn with_msghdr<R>(
addr: &impl SocketAddrArg,
iov: &[IoSlice<'_>],
control: &mut SendAncillaryBuffer<'_, '_, '_>,
f: impl FnOnce(&c::msghdr) -> R,
) -> R {
addr.with_sockaddr(|addr_ptr, addr_len| {
let mut h = zero_msghdr();
h.msg_name = addr_ptr as *mut _;
h.msg_namelen = bitcast!(addr_len);
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
h.msg_control = control.as_control_ptr().cast();
h.msg_controllen = msg_control_len(control.control_len());
f(&h)
})
}
#[cfg(unix)]
pub(crate) fn zero_msghdr() -> c::msghdr {
unsafe { zeroed() }
}