mod split;
pub use split::{BoxedSplit, Split};
mod tcp;
mod unix;
mod vsock;
#[cfg(not(feature = "tokio"))]
use async_io::Async;
use std::io;
#[cfg(not(feature = "tokio"))]
use std::sync::Arc;
use crate::fdo::ConnectionCredentials;
#[cfg(unix)]
use std::os::fd::{BorrowedFd, OwnedFd};
#[cfg(unix)]
type RecvmsgResult = io::Result<(usize, Vec<OwnedFd>)>;
#[cfg(not(unix))]
type RecvmsgResult = io::Result<usize>;
pub trait Socket {
type ReadHalf: ReadHalf;
type WriteHalf: WriteHalf;
fn split(self) -> Split<Self::ReadHalf, Self::WriteHalf>
where
Self: Sized;
}
#[async_trait::async_trait]
pub trait ReadHalf: std::fmt::Debug + Send + Sync + 'static {
async fn recvmsg(&mut self, buf: &mut [u8]) -> RecvmsgResult;
fn can_pass_unix_fd(&self) -> bool {
false
}
async fn peer_credentials(&mut self) -> io::Result<ConnectionCredentials> {
Ok(ConnectionCredentials::default())
}
}
#[async_trait::async_trait]
pub trait WriteHalf: std::fmt::Debug + Send + Sync + 'static {
async fn sendmsg(
&mut self,
buffer: &[u8],
#[cfg(unix)] fds: &[BorrowedFd<'_>],
) -> io::Result<usize>;
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
async fn send_zero_byte(&mut self) -> io::Result<Option<usize>> {
Ok(None)
}
async fn close(&mut self) -> io::Result<()>;
fn can_pass_unix_fd(&self) -> bool {
false
}
async fn peer_credentials(&mut self) -> io::Result<ConnectionCredentials> {
Ok(ConnectionCredentials::default())
}
}
#[async_trait::async_trait]
impl ReadHalf for Box<dyn ReadHalf> {
fn can_pass_unix_fd(&self) -> bool {
(**self).can_pass_unix_fd()
}
async fn recvmsg(&mut self, buf: &mut [u8]) -> RecvmsgResult {
(**self).recvmsg(buf).await
}
async fn peer_credentials(&mut self) -> io::Result<ConnectionCredentials> {
(**self).peer_credentials().await
}
}
#[async_trait::async_trait]
impl WriteHalf for Box<dyn WriteHalf> {
async fn sendmsg(
&mut self,
buffer: &[u8],
#[cfg(unix)] fds: &[BorrowedFd<'_>],
) -> io::Result<usize> {
(**self)
.sendmsg(
buffer,
#[cfg(unix)]
fds,
)
.await
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
async fn send_zero_byte(&mut self) -> io::Result<Option<usize>> {
(**self).send_zero_byte().await
}
async fn close(&mut self) -> io::Result<()> {
(**self).close().await
}
fn can_pass_unix_fd(&self) -> bool {
(**self).can_pass_unix_fd()
}
async fn peer_credentials(&mut self) -> io::Result<ConnectionCredentials> {
(**self).peer_credentials().await
}
}
#[cfg(not(feature = "tokio"))]
impl<T> Socket for Async<T>
where
T: std::fmt::Debug + Send + Sync,
Arc<Async<T>>: ReadHalf + WriteHalf,
{
type ReadHalf = Arc<Async<T>>;
type WriteHalf = Arc<Async<T>>;
fn split(self) -> Split<Self::ReadHalf, Self::WriteHalf> {
let arc = Arc::new(self);
Split {
read: arc.clone(),
write: arc,
}
}
}