use ::std::{
io,
net::{TcpListener, TcpStream, ToSocketAddrs, UdpSocket},
os::{
fd::AsFd,
unix::net::{UnixDatagram, UnixListener},
},
path::Path,
};
use nix::sys::socket::{listen, AddressFamily, Backlog, SockFlag, SockType};
use super::CapNetAgent;
pub trait TcpListenerExt {
fn cap_bind<A>(
agent: &mut CapNetAgent,
addrs: A,
) -> io::Result<TcpListener>
where
A: ToSocketAddrs;
}
impl TcpListenerExt for TcpListener {
fn cap_bind<A>(agent: &mut CapNetAgent, addrs: A) -> io::Result<TcpListener>
where
A: ToSocketAddrs,
{
let s: TcpListener = agent.bind_std_to_addrs(addrs)?;
listen(&s, Backlog::MAXALLOWABLE)?;
Ok(s)
}
}
pub trait TcpStreamExt {
fn cap_connect<A: ToSocketAddrs>(
agent: &mut CapNetAgent,
addrs: A,
) -> io::Result<TcpStream>;
}
impl TcpStreamExt for TcpStream {
fn cap_connect<A: ToSocketAddrs>(
agent: &mut CapNetAgent,
addrs: A,
) -> io::Result<TcpStream> {
let mut last_err = None;
for addr in addrs.to_socket_addrs()? {
let family = if addr.is_ipv4() {
AddressFamily::Inet
} else {
AddressFamily::Inet6
};
let sock = nix::sys::socket::socket(
family,
SockType::Stream,
SockFlag::empty(),
None,
)
.map_err(io::Error::from)?;
match agent.connect_std_fd(sock.as_fd(), addr) {
Ok(()) => return Ok(TcpStream::from(sock)),
Err(e) => {
last_err = Some(e);
}
}
}
Err(last_err.unwrap_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any addresses",
)
}))
}
}
pub trait UdpSocketExt {
fn cap_bind<A>(agent: &mut CapNetAgent, addr: A) -> io::Result<UdpSocket>
where
A: ToSocketAddrs;
fn cap_connect<A>(
&self,
agent: &mut CapNetAgent,
addrs: A,
) -> io::Result<()>
where
A: ToSocketAddrs;
}
impl UdpSocketExt for UdpSocket {
fn cap_bind<A>(agent: &mut CapNetAgent, addrs: A) -> io::Result<UdpSocket>
where
A: ToSocketAddrs,
{
agent.bind_std_to_addrs(addrs)
}
fn cap_connect<A>(
&self,
agent: &mut CapNetAgent,
addrs: A,
) -> io::Result<()>
where
A: ToSocketAddrs,
{
agent.connect_std_to_addrs(self.as_fd(), addrs)
}
}
pub trait UnixDatagramExt {
fn cap_bind<P>(
agent: &mut CapNetAgent,
path: P,
) -> io::Result<UnixDatagram>
where
P: AsRef<Path>;
}
impl UnixDatagramExt for UnixDatagram {
fn cap_bind<P>(agent: &mut CapNetAgent, path: P) -> io::Result<UnixDatagram>
where
P: AsRef<Path>,
{
let s = agent.bind_std_unix(SockType::Datagram, path)?;
Ok(UnixDatagram::from(s))
}
}
pub trait UnixListenerExt {
fn cap_bind<P>(
agent: &mut CapNetAgent,
path: P,
) -> io::Result<UnixListener>
where
P: AsRef<Path>;
}
impl UnixListenerExt for UnixListener {
fn cap_bind<P>(agent: &mut CapNetAgent, path: P) -> io::Result<UnixListener>
where
P: AsRef<Path>,
{
let s = agent.bind_std_unix(SockType::Stream, path)?;
listen(&s, Backlog::MAXALLOWABLE)?;
Ok(UnixListener::from(s))
}
}