use std::ffi::{c_int, c_void};
use std::io::{self, IoSlice};
use std::os::fd::RawFd;
use super::Sock;
pub(crate) const WAKE_KEY: u64 = u64::MAX;
const MSG_DONTWAIT: c_int = if cfg!(target_os = "linux") {
0x40
} else {
0x80
};
unsafe extern "C" {
fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize;
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct PollEvent {
pub(crate) key: u64,
pub(crate) readable: bool,
pub(crate) writable: bool,
pub(crate) hangup: bool,
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct Registered(RawFd);
impl Registered {
pub(crate) fn new(raw: RawFd) -> Registered {
Registered(raw)
}
pub(crate) fn raw(self) -> RawFd {
self.0
}
fn sock(self) -> Sock<'static> {
unsafe { std::os::fd::BorrowedFd::borrow_raw(self.0) }
}
pub(crate) fn set_abortive(self) {
let _ = super::set_linger(self.sock(), Some(std::time::Duration::ZERO));
}
pub(crate) fn recv(self, buf: &mut [u8]) -> io::Result<usize> {
super::retry_interrupted(|| {
#[cfg(any(test, net_io_shim))]
let room = match super::shim::io(super::shim::Op::Recv, buf.len())? {
Some(n) => n,
None => buf.len(),
};
#[cfg(not(any(test, net_io_shim)))]
let room = buf.len();
let n = unsafe {
recv(
self.0,
buf.as_mut_ptr().cast::<c_void>(),
room,
MSG_DONTWAIT,
)
};
if n < 0 {
Err(io::Error::last_os_error())
} else {
Ok(n.unsigned_abs())
}
})
}
pub(crate) fn send_vectored(self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
super::retry_interrupted(|| super::send_vectored_sock(self.sock(), bufs))
}
pub(crate) fn connect_start(self, addr: std::net::SocketAddr) -> io::Result<bool> {
super::connect_start(self.sock(), addr)
}
pub(crate) fn take_error(self) -> io::Result<Option<io::Error>> {
super::take_error(self.sock())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_flags_match_libc() {
assert_eq!(MSG_DONTWAIT, libc::MSG_DONTWAIT);
}
}