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