posix_socket/address/
unix.rs1use crate::{AsSocketAddress, SpecificSocketAddress};
2use std::path::Path;
3
4#[derive(Clone)]
9#[repr(C)]
10pub struct UnixSocketAddress {
11 inner: libc::sockaddr_un,
13
14 len: libc::socklen_t,
16}
17
18impl UnixSocketAddress {
19 pub fn new<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
21 use std::os::unix::ffi::OsStrExt;
22 let path = path.as_ref().as_os_str().as_bytes();
23
24 unsafe {
25 let mut output = Self {
26 inner: libc::sockaddr_un {
27 sun_family: Self::static_family(),
28 sun_path: std::mem::zeroed(),
29 },
30 len: 0,
31 };
32 let path_offset = output.path_offset();
33 if path.len() >= Self::max_len() as usize - path_offset - 1 {
34 Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "path is too large for a socket address"))
35 } else if path.is_empty() {
36 Ok(output)
37 } else {
38 std::ptr::copy(
39 path.as_ptr(),
40 output.inner.sun_path.as_mut_ptr() as *mut u8,
41 path.len(),
42 );
43 output.len = (path_offset + path.len() + 1) as libc::socklen_t;
44 Ok(output)
45 }
46 }
47 }
48
49 pub fn new_unnamed() -> Self {
51 unsafe {
52 let mut address = Self {
53 inner: libc::sockaddr_un {
54 sun_family: Self::static_family(),
55 sun_path: std::mem::zeroed(),
56 },
57 len: 0,
58 };
59 address.len = address.path_offset() as libc::socklen_t;
60 address
61 }
62 }
63
64 pub fn from_raw(inner: libc::sockaddr_un, len: libc::socklen_t) -> Self {
66 Self { inner, len }
67 }
68
69 pub fn into_raw(self) -> (libc::sockaddr_un, libc::socklen_t) {
71 (self.inner, self.len)
72 }
73
74 pub fn as_path(&self) -> Option<&Path> {
78 unsafe {
79 use std::os::unix::ffi::OsStrExt;
80 let path_len = self.path_len();
81 if path_len == 0 {
82 None
83 } else if self.inner.sun_path[0] == 0 {
84 None
85 } else {
86 let path: &[u8] = std::mem::transmute(&self.inner.sun_path[..path_len - 1]);
87 let path = std::ffi::OsStr::from_bytes(path);
88 Some(Path::new(path))
89 }
90 }
91 }
92
93 pub fn is_unnamed(&self) -> bool {
95 self.path_len() == 0
96 }
97
98 pub fn as_abstract(&self) -> Option<&std::ffi::CStr> {
104 unsafe {
105 let path_len = self.path_len();
106 if path_len > 0 && self.inner.sun_path[0] == 0 {
107 Some(std::mem::transmute(&self.inner.sun_path[1..path_len]))
108 } else {
109 None
110 }
111 }
112 }
113
114 fn path_offset(&self) -> usize {
116 let start = &self.inner as *const _ as usize;
117 let sun_path = &self.inner.sun_path as *const _ as usize;
118 sun_path - start
119 }
120
121 fn path_len(&self) -> usize {
123 self.len() as usize - self.path_offset()
124 }
125}
126
127impl SpecificSocketAddress for UnixSocketAddress {
128 fn static_family() -> libc::sa_family_t {
129 libc::AF_LOCAL as libc::sa_family_t
130 }
131}
132
133unsafe impl AsSocketAddress for UnixSocketAddress {
134 fn as_sockaddr(&self) -> *const libc::sockaddr {
135 &self.inner as *const _ as *const _
136 }
137
138 fn as_sockaddr_mut(address: &mut std::mem::MaybeUninit<Self>) -> *mut libc::sockaddr {
139 unsafe { &mut address.as_mut_ptr().as_mut().unwrap().inner as *mut _ as *mut _ }
140 }
141
142 fn len(&self) -> libc::socklen_t {
143 self.len
144 }
145
146 fn finalize(address: std::mem::MaybeUninit<Self>, len: libc::socklen_t) -> std::io::Result<Self> {
147 unsafe {
148 let mut address = address.assume_init();
149 if address.family() != Self::static_family() {
150 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "wrong address family, expeced AF_LOCAL"));
151 }
152 if len > Self::max_len() {
153 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "address too large"));
154 }
155 address.len = len;
156 Ok(address)
157 }
158 }
159
160 fn max_len() -> libc::socklen_t {
161 std::mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
162 }
163}
164
165impl From<UnixSocketAddress> for crate::SocketAddress {
166 fn from(other: UnixSocketAddress) -> Self {
167 Self::from(&other)
168 }
169}
170
171impl From<&UnixSocketAddress> for crate::SocketAddress {
172 fn from(other: &UnixSocketAddress) -> Self {
173 Self::from_other(other)
174 }
175}
176
177impl From<std::os::unix::net::SocketAddr> for UnixSocketAddress {
178 fn from(other: std::os::unix::net::SocketAddr) -> Self {
179 Self::from(&other)
180 }
181}
182
183impl From<&std::os::unix::net::SocketAddr> for UnixSocketAddress {
184 fn from(other: &std::os::unix::net::SocketAddr) -> Self {
185 if let Some(path) = other.as_pathname() {
186 Self::new(path).unwrap()
187 } else if other.is_unnamed() {
188 Self::new_unnamed()
189 } else {
190 panic!("attempted to convert an std::unix::net::SocketAddr that is not a path and not unnamed");
191 }
192 }
193}