Skip to main content

dope_core/io/socket/
addr.rs

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