use crate::{RuntimeError, modules::int_check::IntCheck};
use std::mem;
const MAX_DATAGRAM: usize = 64 * 1024;
pub(crate) fn send_datagram(
fd: libc::c_int,
data: &[u8],
to: *const libc::sockaddr,
len: libc::socklen_t,
) -> Result<Option<usize>, RuntimeError> {
loop {
let sent = unsafe {
libc::sendto(
fd,
data.as_ptr().cast::<libc::c_void>(),
data.len(),
0,
to,
len,
)
}
.check();
match sent {
Ok(sent) => return Ok(Some(sent as usize)),
Err(RuntimeError::CheckError(Some(libc::EINTR))) => {}
Err(RuntimeError::CheckError(Some(libc::EAGAIN))) => return Ok(None),
Err(error) => return Err(error),
}
}
}
pub(crate) fn recv_datagram(
fd: libc::c_int,
peek: bool,
) -> Result<Option<(Vec<u8>, libc::sockaddr_storage, libc::socklen_t)>, RuntimeError> {
let mut data: Vec<u8> = Vec::with_capacity(MAX_DATAGRAM);
loop {
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
let got = unsafe {
libc::recvfrom(
fd,
data.spare_capacity_mut()
.as_mut_ptr()
.cast::<libc::c_void>(),
MAX_DATAGRAM,
if peek { libc::MSG_PEEK } else { 0 },
(&mut storage as *mut libc::sockaddr_storage).cast::<libc::sockaddr>(),
&mut len,
)
}
.check();
match got {
Ok(read) => {
unsafe { data.set_len(read as usize) };
data.shrink_to_fit();
return Ok(Some((data, storage, len)));
}
Err(RuntimeError::CheckError(Some(libc::EINTR))) => {}
Err(RuntimeError::CheckError(Some(libc::EAGAIN))) => return Ok(None),
Err(error) => return Err(error),
}
}
}