use std::
{
borrow::Cow,
fmt,
io::{self, ErrorKind},
mem::{self, MaybeUninit},
net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
path::{Path, PathBuf},
ptr
};
use crate::
{
AF_INET, AF_INET6, AF_UNIX, LocalFrom, So9SockDomain, in_addr, in6_addr, msghdr, sa_family_t,
sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, sockaddr_un, socklen_t, UnixSocketAddr
};
pub enum RawAddressHolder
{
Owned(sockaddr_storage, socklen_t),
Pointer(*const sockaddr, socklen_t)
}
#[cfg(unix)]
impl fmt::Debug for RawAddressHolder
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Owned(arg0, arg1) =>
f.debug_tuple("Owned").field(arg0).field(arg1).finish(),
Self::Pointer(arg0, arg1) =>
f.debug_tuple("Pointer").field(arg0).field(arg1).finish(),
}
}
}
#[cfg(windows)]
impl fmt::Debug for RawAddressHolder
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Owned(_arg0, arg1) =>
f.debug_tuple("Owned").field(arg1).finish(),
Self::Pointer(arg0, arg1) =>
f.debug_tuple("Pointer").field(arg0).field(arg1).finish(),
}
}
}
impl RawAddressHolder
{
pub(crate)
fn get_sockaddr_ptr(&self) -> (*const sockaddr, socklen_t)
{
match *self
{
Self::Owned(ref sockaddr, len) =>
(sockaddr as *const sockaddr_storage as *const sockaddr, len),
Self::Pointer(sockaddr, len) =>
(sockaddr, len),
}
}
}
pub trait IntoSockAddrSpec<SAT: Clone>
{
fn from_type(&self) -> io::Result<Cow<'_, SAT>>;
}
pub trait So9AddrIntoRaw
{
fn into_raw_addr(&self) -> RawAddressHolder;
}
pub trait So9AddrDomain
{
fn get_addr_domain(&self) -> So9SockDomain;
}
#[derive(Debug)]
pub struct So9SocketAddr(pub(crate) MaybeUninit<sockaddr_storage>, socklen_t);
impl Default for So9SocketAddr
{
fn default() -> Self
{
return Self(MaybeUninit::zeroed(), So9SocketAddr::SO9SOCK_LEN)
}
}
impl So9SocketAddr
{
pub(crate) const SO9SOCK_LEN: socklen_t = size_of::<sockaddr_storage>() as socklen_t;
#[cfg(unix)]
pub(crate)
fn set_length(&mut self, msg: &msghdr)
{
self.1 = msg.msg_namelen;
}
#[cfg(windows)]
pub(crate)
fn set_length(&mut self, msg: &msghdr)
{
self.1 = msg.cmsg_len as i32;
}
pub(crate)
fn get_sockaddr_ptr(&mut self) -> *mut sockaddr
{
return self.0.as_mut_ptr() as *mut sockaddr;
}
pub(crate)
fn get_capacity_mut(&mut self) -> &mut socklen_t
{
return &mut self.1;
}
pub(crate)
fn get_sockaddr_storage_ptr(&mut self) -> *mut sockaddr_storage
{
return self.0.as_mut_ptr();
}
pub
fn get_sa_fam(&self) -> sa_family_t
{
return unsafe{ self.0.assume_init_ref() }.ss_family;
}
pub
fn get_len(&self) -> socklen_t
{
return self.1;
}
}
impl From<UnixSocketAddr> for So9SocketAddr
{
fn from(un: UnixSocketAddr) -> Self
{
un.into()
}
}
impl From<&UnixSocketAddr> for So9SocketAddr
{
fn from(un: &UnixSocketAddr) -> Self
{
let raw_un = un.into_raw();
let mut raw_sa = MaybeUninit::<sockaddr_storage>::zeroed();
let sockaddr_vin = unsafe{ &mut *raw_sa.as_mut_ptr().cast::<sockaddr_un>()};
sockaddr_vin.sun_family = AF_UNIX as sa_family_t;
sockaddr_vin.sun_path.copy_from_slice(&raw_un.0.sun_path);
return Self(raw_sa, raw_un.1);
}
}
impl From<SocketAddrV4> for So9SocketAddr
{
fn from(inp_sa: SocketAddrV4) -> Self
{
So9SocketAddr::from(&inp_sa)
}
}
impl From<SocketAddrV6> for So9SocketAddr
{
fn from(inp_sa: SocketAddrV6) -> Self
{
So9SocketAddr::from(&inp_sa)
}
}
impl From<SocketAddr> for So9SocketAddr
{
fn from(inp_sa: SocketAddr) -> Self
{
So9SocketAddr::from(&inp_sa)
}
}
impl From<&SocketAddr> for So9SocketAddr
{
fn from(inp_sa: &SocketAddr) -> Self
{
let res: So9SocketAddr =
match inp_sa
{
SocketAddr::V4(socket_addr_v4) =>
{
socket_addr_v4.into()
},
SocketAddr::V6(socket_addr_v6) =>
{
socket_addr_v6.into()
},
};
return res;
}
}
impl From<&SocketAddrV4> for So9SocketAddr
{
fn from(socket_addr_v4: &SocketAddrV4) -> Self
{
let mut raw_sa = MaybeUninit::<sockaddr_storage>::zeroed();
let sockaddr_vin = unsafe{ &mut *raw_sa.as_mut_ptr().cast::<sockaddr_in>()};
sockaddr_vin.sin_family = AF_INET as sa_family_t;
sockaddr_vin.sin_port = socket_addr_v4.port().to_be();
sockaddr_vin.sin_addr = <in_addr as LocalFrom<&Ipv4Addr>>::from(socket_addr_v4.ip());
let ss_len = mem::size_of::<sockaddr_in>() as socklen_t;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos",
))]
{
raw_sa.ss_len = len as u8;
}
return Self(raw_sa, ss_len);
}
}
impl From<&SocketAddrV6> for So9SocketAddr
{
fn from(socket_addr_v6: &SocketAddrV6) -> Self
{
let mut raw_sa = MaybeUninit::<sockaddr_storage>::zeroed();
let sockaddr_vin = unsafe{ &mut *raw_sa.as_mut_ptr().cast::<sockaddr_in6>()};
sockaddr_vin.sin6_family = AF_INET6 as sa_family_t;
sockaddr_vin.sin6_port = socket_addr_v6.port().to_be();
sockaddr_vin.sin6_addr = <in6_addr as LocalFrom<&Ipv6Addr>>::from(socket_addr_v6.ip());
sockaddr_vin.sin6_flowinfo = socket_addr_v6.flowinfo();
#[cfg(unix)]
{
sockaddr_vin.sin6_scope_id = socket_addr_v6.scope_id();
}
#[cfg(windows)]
{
use windows_sys::Win32::Networking::WinSock::SOCKADDR_IN6_0;
sockaddr_vin.Anonymous =
SOCKADDR_IN6_0
{
sin6_scope_id: socket_addr_v6.scope_id(),
};
}
let ss_len = mem::size_of::<sockaddr_in6>() as socklen_t;
return Self(raw_sa, ss_len);
}
}
impl TryFrom<So9SocketAddr> for UnixSocketAddr
{
type Error = io::Error;
fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error>
{
unsafe
{
UnixSocketAddr::from_sockaddr_storage(so9_sa.0.assume_init_ref(), so9_sa.1)
}
}
}
impl TryFrom<So9SocketAddr> for SocketAddrV4
{
type Error = io::Error;
fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error>
{
let sa = unsafe{ so9_sa.0.assume_init() };
if sa.ss_family == AF_INET as sa_family_t
{
let addr = unsafe{ &*(ptr::addr_of!(sa).cast::<sockaddr_in>()) };
let ip = <Ipv4Addr as LocalFrom<in_addr>>::from(addr.sin_addr);
let port = u16::from_be(addr.sin_port);
return Ok(SocketAddrV4::new(ip, port));
}
return Err(
io::Error::new(ErrorKind::InvalidData,
format!("ss_family: {} is not of type SocketAddr", sa.ss_family))
);
}
}
impl TryFrom<So9SocketAddr> for SocketAddrV6
{
type Error = io::Error;
fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error>
{
let sa = unsafe{ so9_sa.0.assume_init() };
if sa.ss_family == AF_INET6 as sa_family_t
{
let addr = unsafe{ &*(ptr::addr_of!(sa).cast::<sockaddr_in6>()) };
let ip = <Ipv6Addr as LocalFrom<in6_addr>>::from(addr.sin6_addr);
let port = u16::from_be(addr.sin6_port);
let res =
SocketAddrV6::new(
ip,
port,
addr.sin6_flowinfo,
#[cfg(unix)]
addr.sin6_scope_id,
#[cfg(windows)]
unsafe
{
addr.Anonymous.sin6_scope_id
},
);
return Ok(res);
}
return Err(
io::Error::new(ErrorKind::InvalidData,
format!("ss_family: {} is not of type SocketAddr", sa.ss_family))
);
}
}
impl TryFrom<So9SocketAddr> for SocketAddr
{
type Error = io::Error;
fn try_from(so9_sa: So9SocketAddr) -> Result<Self, Self::Error>
{
let sa = unsafe{ so9_sa.0.assume_init_ref() };
if sa.ss_family == AF_INET as sa_family_t
{
return SocketAddrV4::try_from(so9_sa).map(|v| SocketAddr::V4(v));
}
else if sa.ss_family == AF_INET6 as sa_family_t
{
return SocketAddrV6::try_from(so9_sa).map(|v| SocketAddr::V6(v));
}
else
{
return Err(
io::Error::new(ErrorKind::InvalidData,
format!("ss_family: {} is not of type SocketAddr", sa.ss_family))
);
}
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for UnixSocketAddr
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
Ok(Cow::Borrowed(self))
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for &UnixSocketAddr
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
Ok(Cow::Borrowed(self))
}
}
impl IntoSockAddrSpec<SocketAddr> for SocketAddr
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
Ok(Cow::Borrowed(self))
}
}
impl IntoSockAddrSpec<SocketAddr> for &SocketAddr
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
Ok(Cow::Borrowed(self))
}
}
impl IntoSockAddrSpec<SocketAddr> for SocketAddrV6
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
Ok(Cow::Owned(SocketAddr::from((*self).clone())))
}
}
impl IntoSockAddrSpec<SocketAddr> for &SocketAddrV6
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
Ok(Cow::Owned(SocketAddr::from((*self).clone())))
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for &str
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
UnixSocketAddr::new(self).map(|v| Cow::Owned(v))
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for &Path
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for Path
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for &PathBuf
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
}
}
impl IntoSockAddrSpec<UnixSocketAddr> for PathBuf
{
fn from_type(&self) -> io::Result<Cow<'_, UnixSocketAddr>>
{
UnixSocketAddr::from_path(&self).map(|v| Cow::Owned(v))
}
}
impl IntoSockAddrSpec<SocketAddr> for &str
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
return
self
.parse::<SocketAddr>()
.map_err(|e|
io::Error::new(ErrorKind::InvalidInput, e.to_string())
)
.map(|v| Cow::Owned(v));
}
}
impl IntoSockAddrSpec<SocketAddr> for &SocketAddrV4
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
Ok(Cow::Owned(SocketAddr::from((*self).clone())))
}
}
impl IntoSockAddrSpec<SocketAddrV4> for SocketAddrV4
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddrV4>>
{
Ok(Cow::Borrowed(self))
}
}
impl IntoSockAddrSpec<SocketAddr> for SocketAddrV4
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddr>>
{
Ok(Cow::Owned(SocketAddr::from((*self).clone())))
}
}
impl IntoSockAddrSpec<SocketAddrV4> for &str
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddrV4>>
{
return
self
.parse::<SocketAddrV4>()
.map_err(|e|
io::Error::new(ErrorKind::InvalidInput, e.to_string())
)
.map(|v| Cow::Owned(v));
}
}
impl IntoSockAddrSpec<SocketAddrV6> for &str
{
fn from_type(&self) -> io::Result<Cow<'_, SocketAddrV6>>
{
return
self
.parse::<SocketAddrV6>()
.map_err(|e|
io::Error::new(ErrorKind::InvalidInput, e.to_string())
)
.map(|v| Cow::Owned(v));
}
}
impl So9AddrIntoRaw for UnixSocketAddr
{
fn into_raw_addr(&self) -> RawAddressHolder
{
let raw = unsafe { self.as_raw_ptr_general() };
return RawAddressHolder::Pointer(raw.0, raw.1);
}
}
impl So9AddrIntoRaw for SocketAddr
{
fn into_raw_addr(&self) -> RawAddressHolder
{
let sa: So9SocketAddr = self.into();
return RawAddressHolder::Owned( unsafe{ sa.0.assume_init() }, sa.1);
}
}
impl So9AddrIntoRaw for SocketAddrV4
{
fn into_raw_addr(&self) -> RawAddressHolder
{
let sa: So9SocketAddr = self.into();
return RawAddressHolder::Owned( unsafe{ sa.0.assume_init() }, sa.1);
}
}
impl So9AddrIntoRaw for SocketAddrV6
{
fn into_raw_addr(&self) -> RawAddressHolder
{
let sa: So9SocketAddr = self.into();
return RawAddressHolder::Owned( unsafe{ sa.0.assume_init() }, sa.1);
}
}
impl So9AddrDomain for So9SockDomain
{
fn get_addr_domain(&self) -> So9SockDomain
{
return *self;
}
}
impl So9AddrDomain for UnixSocketAddr
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain::UNIX;
}
}
impl So9AddrDomain for SocketAddr
{
fn get_addr_domain(&self) -> So9SockDomain
{
if self.is_ipv4() == true
{
return So9SockDomain::IPV4;
}
else
{
return So9SockDomain::IPV6;
}
}
}
impl So9AddrDomain for SocketAddrV4
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain::IPV4;
}
}
impl So9AddrDomain for SocketAddrV6
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain::IPV6;
}
}
#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum So9DomainInets
{
Inet = So9SockDomain::IPV4.0 as i32,
Inet6 = So9SockDomain::IPV6.0 as i32,
}
#[cfg(target_family = "unix")]
impl So9AddrDomain for So9DomainInets
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain(*self as i32);
}
}
#[cfg(target_family = "windows")]
impl So9AddrDomain for So9DomainInets
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain(*self as u16);
}
}
#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum So9DomainUnix
{
Unix = So9SockDomain::UNIX.0 as i32,
}
#[cfg(target_family = "unix")]
impl So9AddrDomain for So9DomainUnix
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain(*self as i32);
}
}
#[cfg(target_family = "windows")]
impl So9AddrDomain for So9DomainUnix
{
fn get_addr_domain(&self) -> So9SockDomain
{
return So9SockDomain(*self as u16);
}
}
#[cfg(test)]
mod test_addr_int
{
use super::*;
#[test]
fn test_addr_1()
{
let ipv4: SocketAddrV4 = "127.0.0.1:80".parse().unwrap();
let RawAddressHolder::Owned(s9_raw, s9_sz) = ipv4.into_raw_addr()
else { panic!("expected RawAddressHolder::Owned") };
let mut sa9 = So9SocketAddr::from(&ipv4);
assert_eq!(sa9.get_sa_fam(), s9_raw.ss_family);
assert_eq!(*sa9.get_capacity_mut(), s9_sz);
let s9_raw_ptr = &s9_raw as *const sockaddr_storage as *const u8;
let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
for _ in 0..s9_sz
{
unsafe
{
if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
{
panic!("does not match");
}
}
}
let ipv4_back: SocketAddrV4 = sa9.try_into().unwrap();
assert_eq!(ipv4_back, ipv4);
}
#[test]
fn test_addr_2()
{
let ipv6: SocketAddrV6 = "[a20c:828f:aae4:ee01:0983:3506:2f58:5a64]:80".parse().unwrap();
let RawAddressHolder::Owned(s9_raw, s9_sz) = ipv6.into_raw_addr()
else { panic!("expected RawAddressHolder::Owned") };
let mut sa9 = So9SocketAddr::from(&ipv6);
assert_eq!(sa9.get_sa_fam(), s9_raw.ss_family);
assert_eq!(*sa9.get_capacity_mut(), s9_sz);
let s9_raw_ptr = &s9_raw as *const sockaddr_storage as *const u8;
let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
for _ in 0..s9_sz
{
unsafe
{
if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
{
panic!("does not match");
}
}
}
let ipv6_back: SocketAddrV6 = sa9.try_into().unwrap();
assert_eq!(ipv6_back, ipv6);
}
#[test]
fn test_addr_4()
{
let ipv4: SocketAddr = "127.0.0.1:80".parse().unwrap();
let RawAddressHolder::Owned(s9_raw, s9_sz) = ipv4.into_raw_addr()
else { panic!("expected RawAddressHolder::Owned") };
let mut sa9 = So9SocketAddr::from(&ipv4);
assert_eq!(sa9.get_sa_fam(), s9_raw.ss_family);
assert_eq!(*sa9.get_capacity_mut(), s9_sz);
let s9_raw_ptr = &s9_raw as *const sockaddr_storage as *const u8;
let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
for _ in 0..s9_sz
{
unsafe
{
if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
{
panic!("does not match");
}
}
}
}
#[test]
fn test_addr_5()
{
let unix_addr: UnixSocketAddr = UnixSocketAddr::from_path("/tmp/sock.sock").unwrap();
let RawAddressHolder::Pointer(s9_raw, s9_sz) = unix_addr.into_raw_addr()
else { panic!("expected RawAddressHolder::Owned") };
let mut sa9 = So9SocketAddr::from(&unix_addr);
assert_eq!(sa9.get_sa_fam(), unsafe { s9_raw.as_ref().unwrap() }.sa_family);
assert_eq!(*sa9.get_capacity_mut(), s9_sz);
let s9_raw_ptr = s9_raw as *const u8;
let sa9_ptr = sa9.get_sockaddr_storage_ptr() as *const u8;
for _ in 0..s9_sz
{
unsafe
{
if s9_raw_ptr.as_ref().unwrap() != sa9_ptr.as_ref().unwrap()
{
panic!("does not match");
}
}
}
}
}