dope_core/io/socket/
addr.rs1use std::io;
2use std::io::{Error, ErrorKind};
3use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
4use std::os::fd::RawFd;
5use std::os::unix::ffi::OsStrExt;
6use std::path::Path;
7use std::slice::{from_raw_parts, from_raw_parts_mut};
8
9use libc::{
10 AF_INET, AF_INET6, AF_UNIX, c_char, getsockname, sa_family_t, sockaddr, sockaddr_in,
11 sockaddr_in6, sockaddr_storage, socklen_t,
12};
13
14use crate::driver::Driver;
15use crate::io::socket::Pod;
16use crate::platform::raw::abi::PlatformAbi;
17
18#[derive(Clone, Copy, Debug)]
19pub struct Addr {
20 storage: sockaddr_storage,
21 len: socklen_t,
22}
23
24#[derive(Clone, Copy)]
25#[repr(C)]
26union InetStorage {
27 v4: sockaddr_in,
28 v6: sockaddr_in6,
29}
30
31#[derive(Clone, Copy)]
32pub struct InetAddr {
33 storage: InetStorage,
34 len: socklen_t,
35}
36
37impl InetAddr {
38 pub fn from_std(addr: SocketAddr) -> Self {
39 match addr {
40 SocketAddr::V4(v4) => Self {
41 storage: InetStorage {
42 v4: Driver::encode_v4(v4),
43 },
44 len: size_of::<sockaddr_in>() as socklen_t,
45 },
46 SocketAddr::V6(v6) => Self {
47 storage: InetStorage {
48 v6: Driver::encode_v6(v6),
49 },
50 len: size_of::<sockaddr_in6>() as socklen_t,
51 },
52 }
53 }
54
55 pub fn mut_ptr(&mut self) -> *mut sockaddr {
56 &raw mut self.storage as *mut sockaddr
57 }
58
59 pub fn socklen(&self) -> socklen_t {
60 self.len
61 }
62}
63
64impl Addr {
65 pub fn empty() -> Self {
66 Self {
67 storage: Pod::zeroed(),
68 len: size_of::<sockaddr_storage>() as socklen_t,
69 }
70 }
71
72 fn from_payload<T: Copy>(payload: T, len: socklen_t) -> Self {
73 const {
74 assert!(
75 size_of::<T>() <= size_of::<libc::sockaddr_storage>(),
76 "payload does not fit in sockaddr_storage",
77 );
78 assert!(
79 align_of::<T>() <= align_of::<libc::sockaddr_storage>(),
80 "payload over-aligned for sockaddr_storage",
81 );
82 }
83 let mut out = Self::empty();
84 let bytes = unsafe { from_raw_parts(&payload as *const T as *const u8, size_of::<T>()) };
85 out.storage_bytes()[..bytes.len()].copy_from_slice(bytes);
86 out.len = len;
87 out
88 }
89
90 fn storage_bytes(&mut self) -> &mut [u8] {
91 unsafe {
92 from_raw_parts_mut(
93 &raw mut self.storage as *mut u8,
94 size_of::<sockaddr_storage>(),
95 )
96 }
97 }
98
99 pub fn ptr(&self) -> *const sockaddr {
100 &raw const self.storage as *const sockaddr
101 }
102
103 pub fn mut_ptr(&mut self) -> *mut sockaddr {
104 &raw mut self.storage as *mut sockaddr
105 }
106
107 pub fn socklen(&self) -> socklen_t {
108 self.len
109 }
110
111 pub fn len_ptr(&mut self) -> *mut socklen_t {
112 &mut self.len as *mut socklen_t
113 }
114
115 pub fn from_std(addr: SocketAddr) -> Self {
116 match addr {
117 SocketAddr::V4(v4) => {
118 Self::from_payload(Driver::encode_v4(v4), size_of::<sockaddr_in>() as socklen_t)
119 }
120 SocketAddr::V6(v6) => Self::from_payload(
121 Driver::encode_v6(v6),
122 size_of::<sockaddr_in6>() as socklen_t,
123 ),
124 }
125 }
126
127 pub fn from_unix_path(path: &Path) -> io::Result<Self> {
128 let bytes = path.as_os_str().as_bytes();
129 if bytes.is_empty() {
130 return Err(Error::new(ErrorKind::InvalidInput, "empty path"));
131 }
132 let mut encoded = Driver::sockaddr_un();
133 encoded.sun_family = AF_UNIX as _;
134 let max = encoded.sun_path.len().saturating_sub(1);
135 if bytes.len() > max {
136 return Err(Error::new(ErrorKind::InvalidInput, "path too long"));
137 }
138 for (index, byte) in bytes.iter().enumerate() {
139 encoded.sun_path[index] = *byte as c_char;
140 }
141 let len = (size_of::<sa_family_t>() + bytes.len() + 1) as socklen_t;
142 Driver::finish_unix(&mut encoded, len);
143 Ok(Self::from_payload(encoded, len))
144 }
145
146 pub fn from_getsockname(fd: RawFd) -> io::Result<Self> {
147 let mut addr = Self::empty();
148 let rc = unsafe { getsockname(fd, addr.mut_ptr(), addr.len_ptr()) };
149 if rc < 0 {
150 return Err(Error::last_os_error());
151 }
152 Ok(addr)
153 }
154
155 pub fn parse_msg_name(name: &[u8]) -> Option<SocketAddr> {
156 if name.len() > size_of::<sockaddr_storage>() {
157 return None;
158 }
159 let mut addr = Self::empty();
160 addr.storage_bytes()[..name.len()].copy_from_slice(name);
161 addr.into_std_len(name.len() as socklen_t).ok()
162 }
163
164 pub fn into_std(self) -> io::Result<SocketAddr> {
165 self.into_std_len(self.socklen())
166 }
167
168 fn into_std_len(self, len: socklen_t) -> io::Result<SocketAddr> {
169 if (len as usize) < size_of::<sa_family_t>() {
170 return Err(Error::new(ErrorKind::InvalidData, "short sockaddr"));
171 }
172
173 let family = self.storage.ss_family as i32;
174 match family {
175 AF_INET => {
176 if (len as usize) < size_of::<sockaddr_in>() {
177 return Err(Error::new(ErrorKind::InvalidData, "short sockaddr_in"));
178 }
179 let sa = unsafe { &*self.ptr().cast::<sockaddr_in>() };
180 let ip = Ipv4Addr::from(u32::from_be(sa.sin_addr.s_addr));
181 let port = u16::from_be(sa.sin_port);
182 Ok(SocketAddr::new(ip.into(), port))
183 }
184 AF_INET6 => {
185 if (len as usize) < size_of::<sockaddr_in6>() {
186 return Err(Error::new(ErrorKind::InvalidData, "short sockaddr_in6"));
187 }
188 let sa = unsafe { &*self.ptr().cast::<sockaddr_in6>() };
189 let ip = Ipv6Addr::from(sa.sin6_addr.s6_addr);
190 let port = u16::from_be(sa.sin6_port);
191 Ok(SocketAddr::new(ip.into(), port))
192 }
193 _ => Err(Error::new(
194 ErrorKind::InvalidData,
195 "unknown sockaddr family",
196 )),
197 }
198 }
199}