use crate::{
RuntimeError,
futures::{
net::stream::{FinishTask, Pipe, RecvTask, SendTask, Source},
unix::{
path::Bound,
unix_task::{UnixAcceptTask, UnixRecvFromTask, UnixSendToTask},
},
},
modules::{fd::Fd, int_check::IntCheck},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Credentials {
uid: u32,
gid: u32,
}
impl Credentials {
pub fn uid(&self) -> u32 {
self.uid
}
pub fn gid(&self) -> u32 {
self.gid
}
}
use std::{
fmt,
path::{Path, PathBuf},
sync::Arc,
};
struct UnixStream {
pipe: Pipe,
path: PathBuf,
}
#[derive(Clone)]
pub struct UnixConnection {
stream: Arc<UnixStream>,
}
impl UnixConnection {
pub(crate) fn new(fd: Fd, path: PathBuf) -> Self {
Self {
stream: Arc::new(UnixStream {
pipe: Pipe::new(fd),
path,
}),
}
}
#[inline(always)]
pub(crate) fn pipe(&self) -> &Pipe {
&self.stream.pipe
}
#[inline(always)]
fn source(&self) -> Source {
Source::Unix(self.clone())
}
pub fn send(&self, data: impl Into<Arc<[u8]>>) -> SendTask {
SendTask::new(self.source(), data.into())
}
pub fn recv(&self, max: usize) -> RecvTask {
RecvTask::some(self.source(), max)
}
pub fn recv_exact(&self, len: usize) -> RecvTask {
RecvTask::exact(self.source(), len)
}
pub fn recv_until(&self, delimiter: &[u8], max: usize) -> RecvTask {
RecvTask::until(self.source(), Arc::from(delimiter), max)
}
pub fn recv_to_end(&self) -> RecvTask {
RecvTask::to_end(self.source())
}
#[inline(always)]
pub fn path(&self) -> &Path {
&self.stream.path
}
pub fn peer_credentials(&self) -> Result<Credentials, RuntimeError> {
let (mut uid, mut gid) = (0, 0);
unsafe { libc::getpeereid(self.pipe().fd(), &mut uid, &mut gid) }.check()?;
Ok(Credentials { uid, gid })
}
pub fn finish(&self) -> FinishTask {
FinishTask::new(self.source())
}
pub fn close(self) {
drop(self);
}
}
impl fmt::Debug for UnixConnection {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("UnixConnection")
.field("path", &self.stream.path)
.finish()
}
}
struct UnixListening {
fd: Fd,
bound: Bound,
}
#[derive(Clone)]
pub struct UnixListener {
socket: Arc<UnixListening>,
}
impl UnixListener {
pub(crate) fn new(fd: Fd, bound: Bound) -> Self {
Self {
socket: Arc::new(UnixListening { fd, bound }),
}
}
#[inline(always)]
pub(crate) fn fd(&self) -> libc::c_int {
self.socket.fd.raw()
}
pub fn accept(&self) -> UnixAcceptTask {
UnixAcceptTask::new(self.clone())
}
#[inline(always)]
pub fn path(&self) -> &Path {
self.socket.bound.path()
}
pub fn close(self) {
drop(self);
}
}
impl fmt::Debug for UnixListener {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("UnixListener")
.field("path", &self.path())
.finish()
}
}
struct UnixDatagrams {
fd: Fd,
bound: Bound,
}
#[derive(Clone)]
pub struct UnixDatagram {
socket: Arc<UnixDatagrams>,
}
impl UnixDatagram {
pub(crate) fn new(fd: Fd, bound: Bound) -> Self {
Self {
socket: Arc::new(UnixDatagrams { fd, bound }),
}
}
#[inline(always)]
pub(crate) fn fd(&self) -> libc::c_int {
self.socket.fd.raw()
}
pub fn send_to(&self, path: impl AsRef<Path>, data: impl Into<Arc<[u8]>>) -> UnixSendToTask {
UnixSendToTask::new(self.clone(), path.as_ref().to_path_buf(), data.into())
}
pub fn recv_from(&self) -> UnixRecvFromTask {
UnixRecvFromTask::new(self.clone())
}
#[inline(always)]
pub fn path(&self) -> &Path {
self.socket.bound.path()
}
pub fn close(self) {
drop(self);
}
}
impl fmt::Debug for UnixDatagram {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("UnixDatagram")
.field("path", &self.path())
.finish()
}
}