mod addr;
mod close;
pub(crate) mod opt;
mod released;
pub(crate) mod send_file;
mod socket;
mod sockopt;
mod split;
mod stream;
mod tcp;
mod tcp_options;
mod udp;
mod udp_socket;
#[cfg(unix)]
pub mod unix;
#[cfg(unix)]
mod unix_socket;
pub use self::addr::{ToSocketAddrs, lookup_host};
pub use self::released::Released;
pub use self::socket::TcpSocket;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::sockopt::DeviceName;
pub use self::split::{OwnedReadHalf, OwnedWriteHalf, ReadHalf, ReuniteError, WriteHalf};
pub use self::tcp::TcpStreamGenerator;
pub use self::tcp_options::TcpKeepalive;
pub use self::udp_socket::UdpSocketBuilder;
#[cfg(unix)]
pub use self::unix_socket::UnixSocket;
use std::io;
use crate::io::Handle;
pub type TcpListener = Handle<std::net::TcpListener>;
pub type TcpStream = Handle<std::net::TcpStream>;
pub type UdpSocket = Handle<std::net::UdpSocket>;
#[cfg(unix)]
pub type UnixListener = Handle<std::os::unix::net::UnixListener>;
#[cfg(unix)]
pub type UnixStream = Handle<std::os::unix::net::UnixStream>;
#[cfg(unix)]
pub type UnixDatagram = Handle<std::os::unix::net::UnixDatagram>;
#[cfg(test)]
pub(crate) fn refused_addr() -> (Option<TcpSocket>, std::net::SocketAddr) {
if cfg!(any(target_os = "linux", target_os = "android")) {
let socket = TcpSocket::new_v4().unwrap();
socket.bind("127.0.0.1:0".parse().unwrap()).unwrap();
let addr = socket.local_addr().unwrap();
return (Some(socket), addr);
}
let freed = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
(None, freed.local_addr().unwrap())
}
fn at_once<T>(
poll: impl FnOnce(&mut core::task::Context<'_>) -> core::task::Poll<io::Result<T>>,
) -> io::Result<T> {
crate::coop::outside(|| {
let mut cx = core::task::Context::from_waker(core::task::Waker::noop());
match poll(&mut cx) {
core::task::Poll::Ready(result) => result,
core::task::Poll::Pending => Err(io::ErrorKind::WouldBlock.into()),
}
})
}
fn poll_ready(
source: &std::sync::Arc<crate::io::Source>,
cx: &mut core::task::Context<'_>,
interest: crate::io::Interest,
) -> core::task::Poll<io::Result<crate::io::Ready>> {
use crate::io::Ready;
use core::task::Poll;
let mut ready = Ready::EMPTY;
if interest.is_readable()
&& let Poll::Ready(closed) = source.poll_read_ready(cx)
{
ready = ready | Ready::READABLE;
if closed? {
ready = ready | Ready::READ_CLOSED;
}
}
if interest.is_writable()
&& let Poll::Ready(closed) = source.poll_write_ready(cx)
{
ready = ready | Ready::WRITABLE;
if closed? {
ready = ready | Ready::WRITE_CLOSED;
}
}
if ready.is_empty() {
Poll::Pending
} else {
Poll::Ready(Ok(ready))
}
}
macro_rules! caller_io {
($($ty:ty),* $(,)?) => {$(
#[cfg(unix)]
impl Handle<$ty> {
pub fn try_io<R>(
&self,
interest: crate::io::Interest,
f: impl FnOnce() -> io::Result<R>,
) -> io::Result<R> {
crate::io::caller::try_io(self.source(), crate::io::caller::sides(interest), f)
}
pub async fn async_io<R>(
&self,
interest: crate::io::Interest,
f: impl FnMut() -> io::Result<R>,
) -> io::Result<R> {
crate::io::caller::async_io(self.source(), crate::io::caller::sides(interest), f)
.await
}
}
)*};
}
caller_io!(std::net::TcpStream, std::net::UdpSocket);
#[cfg(unix)]
caller_io!(
std::os::unix::net::UnixStream,
std::os::unix::net::UnixDatagram
);
fn none_worked(last: Option<io::Error>) -> io::Error {
last.unwrap_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "no address was given"))
}
#[cfg(test)]
mod tests;