Skip to main content

dope_core/io/socket/
addr.rs

1use 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}