use std::{ffi::c_int, fmt, io::{self, ErrorKind}, net::{IpAddr, Ipv6Addr, SocketAddr}};
use crate::{AF_INET6, IP6T_SO_ORIGINAL_DST, LocalFrom, OptRMarker, SOL_IPV6, SockOptMarker, sa_family_t, sockaddr_in6, in6_addr};
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct SoIp6OriginalDst(sockaddr_in6);
#[cfg(unix)]
impl fmt::Debug for SoIp6OriginalDst
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.debug_tuple("SoIp6OriginalDst").field(&self.0).finish()
}
}
#[cfg(windows)]
impl fmt::Debug for SoIp6OriginalDst
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.debug_tuple("SoIp6OriginalDst").finish()
}
}
impl SockOptMarker for SoIp6OriginalDst
{
const SO_LEVEL: c_int = SOL_IPV6 as i32;
const SO_OPTNAME: c_int = IP6T_SO_ORIGINAL_DST as i32;
type DataType = io::Result<SocketAddr>;
type InputType = sockaddr_in6;
#[inline]
fn from(value: Self::InputType) -> Self
{
return Self(value);
}
#[inline]
fn get(self) -> Self::DataType
{
if self.0.sin6_family != AF_INET6 as sa_family_t
{
return Err(
io::Error::new(ErrorKind::Other,
format!("expected IPv6, received sin_family: {}", self.0.sin6_family))
);
}
let ipv6 = <Ipv6Addr as LocalFrom<in6_addr>>::from(self.0.sin6_addr);
return Ok(SocketAddr::new(IpAddr::V6(ipv6), self.0.sin6_port));
}
#[inline]
fn from_user(_: Self::DataType) -> Self where Self: Sized
{
panic!("SoIp6OriginalDst cannot write!");
}
}
impl OptRMarker for SoIp6OriginalDst {}