#![allow(unsafe_code)]
use std::net::TcpStream;
use std::os::fd::AsRawFd;
use std::time::Duration;
pub(crate) fn wait(
write: Option<&TcpStream>,
read: Option<&TcpStream>,
timeout: Duration,
) -> std::io::Result<bool> {
let fd = |s: Option<&TcpStream>| s.map_or(-1, AsRawFd::as_raw_fd);
let mut fds = [
libc::pollfd {
fd: fd(write),
events: libc::POLLOUT,
revents: 0,
},
libc::pollfd {
fd: fd(read),
events: libc::POLLIN,
revents: 0,
},
];
let ms = libc::c_int::try_from(timeout.as_millis()).unwrap_or(libc::c_int::MAX);
loop {
let ready = unsafe { libc::poll(fds.as_mut_ptr(), 2, ms) };
match ready {
0 => return Ok(false),
1.. => return Ok(true),
_ => {
let e = std::io::Error::last_os_error();
if e.kind() != std::io::ErrorKind::Interrupted {
return Err(e);
}
}
}
}
}
pub(crate) fn peek(s: &TcpStream) -> std::io::Result<usize> {
let mut b = 0u8;
let n = unsafe {
libc::recv(
s.as_raw_fd(),
(&raw mut b).cast(),
1,
libc::MSG_PEEK | libc::MSG_DONTWAIT,
)
};
usize::try_from(n).map_err(|_| std::io::Error::last_os_error())
}