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