// SPDX-License-Identifier: MPL-2.0 use keyable_arc::KeyableArc; use super::ns::{self, AbstractHandle}; use crate::{ fs::{path::Dentry, utils::Inode}, net::socket::util::socket_addr::SocketAddr, prelude::*, }; #[derive(Clone, Debug, PartialEq, Eq)] pub enum UnixSocketAddr { Unnamed, Path(Arc), Abstract(Arc<[u8]>), } impl UnixSocketAddr { pub(super) fn bind(self) -> Result { let bound = match self { Self::Unnamed => UnixSocketAddrBound::Abstract(ns::alloc_ephemeral_abstract_name()?), Self::Path(path) => { let dentry = ns::create_socket_file(&path)?; UnixSocketAddrBound::Path(path, dentry) } Self::Abstract(name) => UnixSocketAddrBound::Abstract(ns::create_abstract_name(name)?), }; Ok(bound) } pub(super) fn connect(&self) -> Result { let bound = match self { Self::Unnamed => return_errno_with_message!( Errno::EINVAL, "the unnamed UNIX domain socket address is not valid for connecting" ), Self::Path(path) => UnixSocketAddrKey::Path(KeyableArc::from( ns::lookup_socket_file(path)?.inode().clone(), )), Self::Abstract(name) => { UnixSocketAddrKey::Abstract(KeyableArc::from(ns::lookup_abstract_name(name)?)) } }; Ok(bound) } } impl TryFrom for UnixSocketAddr { type Error = Error; fn try_from(value: SocketAddr) -> Result { match value { SocketAddr::Unix(unix_socket_addr) => Ok(unix_socket_addr), _ => return_errno_with_message!( Errno::EINVAL, "the socket address is not a valid UNIX domain socket address" ), } } } #[derive(Clone, Debug)] pub(super) enum UnixSocketAddrBound { Path(Arc, Arc), Abstract(Arc), } #[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] pub(super) enum UnixSocketAddrKey { Path(KeyableArc), Abstract(KeyableArc), } impl UnixSocketAddrBound { pub(super) fn to_key(&self) -> UnixSocketAddrKey { match self { Self::Path(_, dentry) => { UnixSocketAddrKey::Path(KeyableArc::from(dentry.inode().clone())) } Self::Abstract(handle) => UnixSocketAddrKey::Abstract(KeyableArc::from(handle.clone())), } } } impl From for UnixSocketAddr { fn from(value: UnixSocketAddrBound) -> Self { match value { UnixSocketAddrBound::Path(path, _) => Self::Path(path), UnixSocketAddrBound::Abstract(name) => Self::Abstract(name.name()), } } } impl From> for UnixSocketAddr { fn from(value: Option) -> Self { match value { Some(addr) => addr.into(), None => Self::Unnamed, } } } impl> From for SocketAddr { fn from(value: T) -> Self { SocketAddr::Unix(value.into()) } }