use std::{
io,
os::unix::prelude::{AsRawFd, RawFd},
path::Path,
};
use super::{
socket_addr::{local_addr, pair, peer_addr, socket_addr},
SocketAddr,
};
use crate::{
buf::{IoBuf, IoBufMut},
driver::{op::Op, shared_fd::SharedFd},
net::new_socket,
};
mod listener;
pub use listener::UnixSeqpacketListener;
pub struct UnixSeqpacket {
fd: SharedFd,
}
impl UnixSeqpacket {
pub(crate) fn from_shared_fd(fd: SharedFd) -> Self {
Self { fd }
}
pub fn pair() -> io::Result<(Self, Self)> {
let (a, b) = pair(libc::SOCK_SEQPACKET)?;
Ok((
Self::from_shared_fd(SharedFd::new::<false>(a)?),
Self::from_shared_fd(SharedFd::new::<false>(b)?),
))
}
pub async fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self> {
let (addr, addr_len) = socket_addr(path.as_ref())?;
Self::inner_connect(addr, addr_len).await
}
pub async fn connect_addr(addr: SocketAddr) -> io::Result<Self> {
let (addr, addr_len) = addr.into_parts();
Self::inner_connect(addr, addr_len).await
}
#[inline(always)]
async fn inner_connect(
sockaddr: libc::sockaddr_un,
socklen: libc::socklen_t,
) -> io::Result<Self> {
let socket = new_socket(libc::AF_UNIX, libc::SOCK_SEQPACKET)?;
let op = Op::connect_unix(SharedFd::new::<false>(socket)?, sockaddr, socklen)?;
let completion = op.await;
completion.meta.result?;
Ok(Self::from_shared_fd(completion.data.fd))
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
local_addr(self.as_raw_fd())
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
peer_addr(self.as_raw_fd())
}
pub async fn readable(&self, relaxed: bool) -> io::Result<()> {
let op = Op::poll_read(&self.fd, relaxed).unwrap();
op.wait().await
}
pub async fn writable(&self, relaxed: bool) -> io::Result<()> {
let op = Op::poll_write(&self.fd, relaxed).unwrap();
op.wait().await
}
pub async fn send_to<T: IoBuf, P: AsRef<Path>>(
&self,
buf: T,
path: P,
) -> crate::BufResult<usize, T> {
let addr = match crate::net::unix::socket_addr::socket_addr(path.as_ref()) {
Ok(addr) => addr,
Err(e) => return (Err(e), buf),
};
let op = Op::send_msg_unix(
self.fd.clone(),
buf,
Some(SocketAddr::from_parts(addr.0, addr.1)),
)
.unwrap();
op.wait().await
}
pub async fn recv_from<T: IoBufMut>(&self, buf: T) -> crate::BufResult<(usize, SocketAddr), T> {
let op = Op::recv_msg_unix(self.fd.clone(), buf).unwrap();
op.wait().await
}
pub async fn send<T: IoBuf>(&self, buf: T) -> crate::BufResult<usize, T> {
let op = Op::send_msg_unix(self.fd.clone(), buf, None).unwrap();
op.wait().await
}
pub async fn recv<T: IoBufMut>(&self, buf: T) -> crate::BufResult<usize, T> {
let op = Op::recv(self.fd.clone(), buf).unwrap();
op.read().await
}
}
impl AsRawFd for UnixSeqpacket {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.fd.raw_fd()
}
}
impl std::fmt::Debug for UnixSeqpacket {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("UnixSeqpacket")
.field("fd", &self.fd)
.finish()
}
}