Skip to main content

dope_core/io/socket/
addr.rs

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