use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use std::os::unix::net::UnixStream as stdUnixStream;
use std::os::unix::net::UnixListener as stdUnixListener;
use std::io;
use tokio::net::{UnixStream, UnixListener, UnixDatagram};
use libc::SOCK_STREAM;
use crate::addr::UnixSocketAddr;
use crate::helpers::*;
use crate::credentials::*;
mod private {
use super::*;
pub trait Sealed {}
impl Sealed for UnixStream {}
impl Sealed for UnixListener {}
impl Sealed for UnixDatagram {}
}
pub trait UnixStreamExt: AsRawFd + private::Sealed {
fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> {
get_unix_addr(self.as_raw_fd(), GetAddr::LOCAL)
}
fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> {
get_unix_addr(self.as_raw_fd(), GetAddr::PEER)
}
fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> where Self: Sized;
fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr)
-> Result<Self, io::Error> where Self: Sized;
fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error> {
peer_credentials(self.as_raw_fd())
}
fn initial_peer_selinux_context(&self, buffer: &mut[u8]) -> Result<usize, io::Error> {
selinux_context(self.as_raw_fd(), buffer)
}
}
impl UnixStreamExt for UnixStream {
fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> {
let socket = Socket::new(SOCK_STREAM, true)?;
set_unix_addr(socket.as_raw_fd(), SetAddr::PEER, addr)?;
UnixStream::from_std(unsafe { stdUnixStream::from_raw_fd(socket.into_raw_fd()) })
}
fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr)
-> Result<Self, io::Error> {
let socket = Socket::new(SOCK_STREAM, true)?;
set_unix_addr(socket.as_raw_fd(), SetAddr::LOCAL, from)?;
set_unix_addr(socket.as_raw_fd(), SetAddr::PEER, to)?;
UnixStream::from_std(unsafe { stdUnixStream::from_raw_fd(socket.into_raw_fd()) })
}
}
pub trait UnixListenerExt: AsRawFd + private::Sealed {
type Conn;
fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error> where Self: Sized;
fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> {
get_unix_addr(self.as_raw_fd(), GetAddr::LOCAL)
}
}
impl UnixListenerExt for UnixListener {
type Conn = UnixStream;
fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error> {
let socket = Socket::new(SOCK_STREAM, true)?;
set_unix_addr(socket.as_raw_fd(), SetAddr::LOCAL, on)?;
socket.start_listening()?;
UnixListener::from_std(unsafe { stdUnixListener::from_raw_fd(socket.into_raw_fd()) })
}
}
pub trait UnixDatagramExt: AsRawFd + private::Sealed {
#[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
#[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> where Self: Sized;
fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> {
get_unix_addr(self.as_raw_fd(), GetAddr::LOCAL)
}
fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> {
get_unix_addr(self.as_raw_fd(), GetAddr::PEER)
}
fn bind_to_unix_addr(&self, addr: &UnixSocketAddr) -> Result<(), io::Error> {
set_unix_addr(self.as_raw_fd(), SetAddr::LOCAL, addr)
}
fn connect_to_unix_addr(&self, addr: &UnixSocketAddr) -> Result<(), io::Error> {
set_unix_addr(self.as_raw_fd(), SetAddr::PEER, addr)
}
fn initial_pair_credentials(&self) -> Result<ConnCredentials, io::Error> {
peer_credentials(self.as_raw_fd())
}
fn initial_pair_selinux_context(&self, buffer: &mut[u8]) -> Result<usize, io::Error> {
selinux_context(self.as_raw_fd(), buffer)
}
}
impl UnixDatagramExt for UnixDatagram {
fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> {
match UnixDatagram::unbound() {
Ok(socket) => match socket.bind_to_unix_addr(addr) {
Ok(()) => Ok(socket),
Err(e) => Err(e),
}
Err(e) => Err(e)
}
}
}