dope_sys/io/socket/addr/
internet.rs1use std::{mem, net, ptr};
2
3use crate::io::socket::{
4 Domain,
5 addr::{Addr, CAPACITY, Error, FAMILY_BYTES, Socklen, Source},
6};
7
8#[derive(Clone, Copy)]
10#[repr(transparent)]
11pub(super) struct Inet(libc::sockaddr_in);
12
13impl Inet {
14 pub(super) const BYTES: usize = mem::size_of::<libc::sockaddr_in>();
16
17 fn from_std<S: Source>(addr: net::SocketAddrV4) -> Self {
18 let mut raw: libc::sockaddr_in = unsafe { mem::zeroed() };
20 raw.sin_port = addr.port().to_be();
21 raw.sin_addr = libc::in_addr {
22 s_addr: u32::from_ne_bytes(addr.ip().octets()),
23 };
24 unsafe {
26 ptr::from_mut(&mut raw)
27 .cast::<[u8; 2]>()
28 .write(S::header(Domain::Inet4, Socklen::of::<Self>()))
29 };
30
31 Self(raw)
32 }
33
34 #[must_use]
35 fn to_std(self) -> net::SocketAddrV4 {
36 let ip = net::Ipv4Addr::from(u32::from_be(self.0.sin_addr.s_addr));
37 net::SocketAddrV4::new(ip, u16::from_be(self.0.sin_port))
38 }
39}
40
41#[derive(Clone, Copy)]
43#[repr(transparent)]
44pub(super) struct Inet6(libc::sockaddr_in6);
45
46impl Inet6 {
47 fn from_std<S: Source>(addr: net::SocketAddrV6) -> Self {
48 let mut raw: libc::sockaddr_in6 = unsafe { mem::zeroed() };
50 raw.sin6_port = addr.port().to_be();
51 raw.sin6_flowinfo = addr.flowinfo();
52 raw.sin6_addr = libc::in6_addr {
53 s6_addr: addr.ip().octets(),
54 };
55 raw.sin6_scope_id = addr.scope_id();
56 unsafe {
58 ptr::from_mut(&mut raw)
59 .cast::<[u8; 2]>()
60 .write(S::header(Domain::Inet6, Socklen::of::<Self>()))
61 };
62
63 Self(raw)
64 }
65
66 #[must_use]
67 fn to_std(self) -> net::SocketAddrV6 {
68 net::SocketAddrV6::new(
69 net::Ipv6Addr::from(self.0.sin6_addr.s6_addr),
70 u16::from_be(self.0.sin6_port),
71 self.0.sin6_flowinfo,
72 self.0.sin6_scope_id,
73 )
74 }
75}
76
77#[derive(Clone, Copy)]
79pub struct Internet {
80 storage: Storage,
81 len: Socklen,
82}
83
84#[derive(Clone, Copy)]
85#[repr(C)]
86union Storage {
87 v4: Inet,
88 v6: Inet6,
89}
90
91impl Internet {
92 pub fn try_parse(bytes: &[u8]) -> Result<net::SocketAddr, Error> {
94 let actual = bytes.len();
95 if actual > CAPACITY {
96 return Err(Error::Storage {
97 actual,
98 capacity: CAPACITY,
99 });
100 }
101 unsafe { Self::decode(bytes.as_ptr(), actual) }
103 }
104
105 pub(super) unsafe fn decode(bytes: *const u8, actual: usize) -> Result<net::SocketAddr, Error> {
109 if actual < FAMILY_BYTES {
110 return Err(Error::Header {
111 actual,
112 required: FAMILY_BYTES,
113 });
114 }
115 let family = unsafe {
118 bytes
119 .add(mem::offset_of!(libc::sockaddr_storage, ss_family))
120 .cast::<libc::sa_family_t>()
121 .read_unaligned()
122 } as libc::c_int;
123
124 Ok(unsafe {
127 match family {
128 libc::AF_INET => read::<Inet>(bytes, actual, family)?.to_std().into(),
129 libc::AF_INET6 => read::<Inet6>(bytes, actual, family)?.to_std().into(),
130 other => {
131 return Err(Error::Unsupported {
132 family: other,
133 actual,
134 });
135 }
136 }
137 })
138 }
139
140 pub fn from_std<S: Source>(address: net::SocketAddr) -> Self {
141 match address {
142 net::SocketAddr::V4(address) => Self {
143 storage: Storage {
144 v4: Inet::from_std::<S>(address),
145 },
146 len: Socklen::of::<Inet>(),
147 },
148 net::SocketAddr::V6(address) => Self {
149 storage: Storage {
150 v6: Inet6::from_std::<S>(address),
151 },
152 len: Socklen::of::<Inet6>(),
153 },
154 }
155 }
156
157 pub fn as_addr(&self) -> Addr<'_> {
158 Addr::new(&self.storage, self.len)
159 }
160
161 pub fn domain(&self) -> Domain {
162 if self.len.get() == Inet::BYTES {
163 Domain::Inet4
164 } else {
165 Domain::Inet6
166 }
167 }
168}
169
170unsafe fn read<T: Copy>(bytes: *const u8, actual: usize, family: i32) -> Result<T, Error> {
174 let required = mem::size_of::<T>();
175 if actual < required {
176 return Err(Error::Address {
177 family,
178 actual,
179 required,
180 });
181 }
182 Ok(unsafe { bytes.cast::<T>().read_unaligned() })
184}
185
186const _: () = assert!(mem::size_of::<Internet>() <= 32);