use core::{
mem,
mem::MaybeUninit,
ptr,
};
use super::abi::*;
use crate::{
result_from_value,
AsRawFd,
Error,
OwnedFd,
SockAddr,
EINVAL,
ENOMEM,
};
#[inline]
pub unsafe fn accept4_raw(
fd: &impl AsRawFd,
addr: *mut u8,
addr_len: *mut isize,
flags: i32,
) -> crate::Result<OwnedFd> {
let ret = syscall_4(
288,
fd.as_raw_fd() as usize,
addr as usize,
addr_len as usize,
flags as usize,
) as i32;
result_from_value(ret).map(OwnedFd::new)
}
#[inline]
pub fn accept4(fd: &impl AsRawFd, flags: i32) -> crate::Result<OwnedFd> {
unsafe { accept4_raw(fd, ptr::null_mut(), ptr::null_mut(), flags) }
}
#[inline]
pub fn accept4_with_peer_addr<T: SockAddr>(
fd: &impl AsRawFd,
flags: i32,
) -> crate::Result<(OwnedFd, T)> {
let addr_len = isize::try_from(mem::size_of::<T>()).unwrap();
let mut addr: MaybeUninit<T> = MaybeUninit::uninit();
let mut out_len = addr_len;
let fd = unsafe {
accept4_raw(
fd,
addr.as_mut_ptr() as *mut u8,
&mut out_len as *mut isize,
flags,
)
}?;
if out_len != addr_len {
return Err(Error::from_code(ENOMEM));
}
let addr = unsafe { addr.assume_init() };
let family = unsafe { mem::transmute::<&T, &u16>(&addr) };
if *family != T::family().into() {
return Err(Error::from_code(EINVAL));
}
Ok((fd, addr))
}