]>
Commit | Line | Data |
---|---|---|
a7813a04 | 1 | #![stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
2 | |
3 | //! Unix-specific networking functionality | |
4 | ||
3b2f2976 XL |
5 | // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? |
6 | #[cfg(not(unix))] | |
f9f354fc | 7 | #[allow(non_camel_case_types)] |
3b2f2976 XL |
8 | mod libc { |
9 | pub use libc::c_int; | |
10 | pub type socklen_t = u32; | |
11 | pub struct sockaddr; | |
12 | #[derive(Clone)] | |
13 | pub struct sockaddr_un; | |
14 | } | |
15 | ||
532ac7d7 XL |
16 | use crate::ascii; |
17 | use crate::ffi::OsStr; | |
18 | use crate::fmt; | |
48663c56 | 19 | use crate::io::{self, Initializer, IoSlice, IoSliceMut}; |
532ac7d7 XL |
20 | use crate::mem; |
21 | use crate::net::{self, Shutdown}; | |
22 | use crate::os::unix::ffi::OsStrExt; | |
dfeec247 | 23 | use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; |
532ac7d7 | 24 | use crate::path::Path; |
532ac7d7 | 25 | use crate::sys::net::Socket; |
dfeec247 | 26 | use crate::sys::{self, cvt}; |
532ac7d7 | 27 | use crate::sys_common::{self, AsInner, FromInner, IntoInner}; |
dfeec247 | 28 | use crate::time::Duration; |
54a0048b | 29 | |
dfeec247 XL |
30 | #[cfg(any( |
31 | target_os = "linux", | |
32 | target_os = "android", | |
33 | target_os = "dragonfly", | |
34 | target_os = "freebsd", | |
35 | target_os = "openbsd", | |
36 | target_os = "netbsd", | |
37 | target_os = "haiku" | |
38 | ))] | |
c30ab7b3 | 39 | use libc::MSG_NOSIGNAL; |
dfeec247 XL |
40 | #[cfg(not(any( |
41 | target_os = "linux", | |
42 | target_os = "android", | |
43 | target_os = "dragonfly", | |
44 | target_os = "freebsd", | |
45 | target_os = "openbsd", | |
46 | target_os = "netbsd", | |
47 | target_os = "haiku" | |
48 | )))] | |
c30ab7b3 SL |
49 | const MSG_NOSIGNAL: libc::c_int = 0x0; |
50 | ||
dc9dc135 | 51 | fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { |
0531ce1d | 52 | // Work with an actual instance of the type since using a null pointer is UB |
dc9dc135 | 53 | let base = addr as *const _ as usize; |
0531ce1d XL |
54 | let path = &addr.sun_path as *const _ as usize; |
55 | path - base | |
54a0048b SL |
56 | } |
57 | ||
58 | unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { | |
59 | let mut addr: libc::sockaddr_un = mem::zeroed(); | |
60 | addr.sun_family = libc::AF_UNIX as libc::sa_family_t; | |
61 | ||
62 | let bytes = path.as_os_str().as_bytes(); | |
63 | ||
64 | if bytes.contains(&0) { | |
dfeec247 XL |
65 | return Err(io::Error::new( |
66 | io::ErrorKind::InvalidInput, | |
67 | "paths may not contain interior null bytes", | |
68 | )); | |
54a0048b SL |
69 | } |
70 | ||
71 | if bytes.len() >= addr.sun_path.len() { | |
dfeec247 XL |
72 | return Err(io::Error::new( |
73 | io::ErrorKind::InvalidInput, | |
74 | "path must be shorter than SUN_LEN", | |
75 | )); | |
54a0048b SL |
76 | } |
77 | for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { | |
78 | *dst = *src as libc::c_char; | |
79 | } | |
80 | // null byte for pathname addresses is already there because we zeroed the | |
81 | // struct | |
82 | ||
dc9dc135 | 83 | let mut len = sun_path_offset(&addr) + bytes.len(); |
54a0048b SL |
84 | match bytes.get(0) { |
85 | Some(&0) | None => {} | |
86 | Some(_) => len += 1, | |
87 | } | |
88 | Ok((addr, len as libc::socklen_t)) | |
89 | } | |
90 | ||
91 | enum AddressKind<'a> { | |
92 | Unnamed, | |
93 | Pathname(&'a Path), | |
94 | Abstract(&'a [u8]), | |
95 | } | |
96 | ||
97 | /// An address associated with a Unix socket. | |
32a655c1 SL |
98 | /// |
99 | /// # Examples | |
100 | /// | |
101 | /// ``` | |
102 | /// use std::os::unix::net::UnixListener; | |
103 | /// | |
104 | /// let socket = match UnixListener::bind("/tmp/sock") { | |
105 | /// Ok(sock) => sock, | |
106 | /// Err(e) => { | |
107 | /// println!("Couldn't bind: {:?}", e); | |
108 | /// return | |
109 | /// } | |
110 | /// }; | |
111 | /// let addr = socket.local_addr().expect("Couldn't get local address"); | |
112 | /// ``` | |
54a0048b | 113 | #[derive(Clone)] |
a7813a04 | 114 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
115 | pub struct SocketAddr { |
116 | addr: libc::sockaddr_un, | |
117 | len: libc::socklen_t, | |
118 | } | |
119 | ||
120 | impl SocketAddr { | |
121 | fn new<F>(f: F) -> io::Result<SocketAddr> | |
dfeec247 XL |
122 | where |
123 | F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int, | |
54a0048b SL |
124 | { |
125 | unsafe { | |
126 | let mut addr: libc::sockaddr_un = mem::zeroed(); | |
127 | let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t; | |
128 | cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; | |
129 | SocketAddr::from_parts(addr, len) | |
130 | } | |
131 | } | |
132 | ||
133 | fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<SocketAddr> { | |
134 | if len == 0 { | |
135 | // When there is a datagram from unnamed unix socket | |
136 | // linux returns zero bytes of address | |
dfeec247 | 137 | len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address |
54a0048b | 138 | } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { |
dfeec247 XL |
139 | return Err(io::Error::new( |
140 | io::ErrorKind::InvalidInput, | |
141 | "file descriptor did not correspond to a Unix socket", | |
142 | )); | |
54a0048b SL |
143 | } |
144 | ||
dfeec247 | 145 | Ok(SocketAddr { addr, len }) |
54a0048b SL |
146 | } |
147 | ||
9fa01778 | 148 | /// Returns `true` if the address is unnamed. |
32a655c1 SL |
149 | /// |
150 | /// # Examples | |
151 | /// | |
152 | /// A named address: | |
153 | /// | |
154 | /// ```no_run | |
155 | /// use std::os::unix::net::UnixListener; | |
156 | /// | |
60c5eb7d XL |
157 | /// fn main() -> std::io::Result<()> { |
158 | /// let socket = UnixListener::bind("/tmp/sock")?; | |
159 | /// let addr = socket.local_addr().expect("Couldn't get local address"); | |
160 | /// assert_eq!(addr.is_unnamed(), false); | |
161 | /// Ok(()) | |
162 | /// } | |
32a655c1 SL |
163 | /// ``` |
164 | /// | |
165 | /// An unnamed address: | |
166 | /// | |
167 | /// ``` | |
168 | /// use std::os::unix::net::UnixDatagram; | |
169 | /// | |
60c5eb7d XL |
170 | /// fn main() -> std::io::Result<()> { |
171 | /// let socket = UnixDatagram::unbound()?; | |
172 | /// let addr = socket.local_addr().expect("Couldn't get local address"); | |
173 | /// assert_eq!(addr.is_unnamed(), true); | |
174 | /// Ok(()) | |
175 | /// } | |
32a655c1 | 176 | /// ``` |
a7813a04 | 177 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b | 178 | pub fn is_unnamed(&self) -> bool { |
dfeec247 | 179 | if let AddressKind::Unnamed = self.address() { true } else { false } |
54a0048b SL |
180 | } |
181 | ||
182 | /// Returns the contents of this address if it is a `pathname` address. | |
32a655c1 SL |
183 | /// |
184 | /// # Examples | |
185 | /// | |
186 | /// With a pathname: | |
187 | /// | |
188 | /// ```no_run | |
189 | /// use std::os::unix::net::UnixListener; | |
190 | /// use std::path::Path; | |
191 | /// | |
60c5eb7d XL |
192 | /// fn main() -> std::io::Result<()> { |
193 | /// let socket = UnixListener::bind("/tmp/sock")?; | |
194 | /// let addr = socket.local_addr().expect("Couldn't get local address"); | |
195 | /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); | |
196 | /// Ok(()) | |
197 | /// } | |
32a655c1 SL |
198 | /// ``` |
199 | /// | |
200 | /// Without a pathname: | |
201 | /// | |
202 | /// ``` | |
203 | /// use std::os::unix::net::UnixDatagram; | |
204 | /// | |
60c5eb7d XL |
205 | /// fn main() -> std::io::Result<()> { |
206 | /// let socket = UnixDatagram::unbound()?; | |
207 | /// let addr = socket.local_addr().expect("Couldn't get local address"); | |
208 | /// assert_eq!(addr.as_pathname(), None); | |
209 | /// Ok(()) | |
210 | /// } | |
32a655c1 | 211 | /// ``` |
a7813a04 | 212 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b | 213 | pub fn as_pathname(&self) -> Option<&Path> { |
dfeec247 | 214 | if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } |
54a0048b SL |
215 | } |
216 | ||
416331ca | 217 | fn address(&self) -> AddressKind<'_> { |
dc9dc135 | 218 | let len = self.len as usize - sun_path_offset(&self.addr); |
54a0048b SL |
219 | let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; |
220 | ||
cc61c64b | 221 | // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses |
83c7162d XL |
222 | if len == 0 |
223 | || (cfg!(not(any(target_os = "linux", target_os = "android"))) | |
224 | && self.addr.sun_path[0] == 0) | |
225 | { | |
54a0048b SL |
226 | AddressKind::Unnamed |
227 | } else if self.addr.sun_path[0] == 0 { | |
228 | AddressKind::Abstract(&path[1..len]) | |
229 | } else { | |
230 | AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) | |
231 | } | |
232 | } | |
233 | } | |
234 | ||
a7813a04 | 235 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b | 236 | impl fmt::Debug for SocketAddr { |
532ac7d7 | 237 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
54a0048b SL |
238 | match self.address() { |
239 | AddressKind::Unnamed => write!(fmt, "(unnamed)"), | |
240 | AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), | |
241 | AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), | |
242 | } | |
243 | } | |
244 | } | |
245 | ||
246 | struct AsciiEscaped<'a>(&'a [u8]); | |
247 | ||
248 | impl<'a> fmt::Display for AsciiEscaped<'a> { | |
532ac7d7 | 249 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
54a0048b SL |
250 | write!(fmt, "\"")?; |
251 | for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { | |
252 | write!(fmt, "{}", byte as char)?; | |
253 | } | |
254 | write!(fmt, "\"") | |
255 | } | |
256 | } | |
257 | ||
258 | /// A Unix stream socket. | |
259 | /// | |
260 | /// # Examples | |
261 | /// | |
32a655c1 | 262 | /// ```no_run |
54a0048b SL |
263 | /// use std::os::unix::net::UnixStream; |
264 | /// use std::io::prelude::*; | |
265 | /// | |
60c5eb7d XL |
266 | /// fn main() -> std::io::Result<()> { |
267 | /// let mut stream = UnixStream::connect("/path/to/my/socket")?; | |
268 | /// stream.write_all(b"hello world")?; | |
269 | /// let mut response = String::new(); | |
270 | /// stream.read_to_string(&mut response)?; | |
271 | /// println!("{}", response); | |
272 | /// Ok(()) | |
273 | /// } | |
54a0048b | 274 | /// ``` |
a7813a04 | 275 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
276 | pub struct UnixStream(Socket); |
277 | ||
a7813a04 | 278 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b | 279 | impl fmt::Debug for UnixStream { |
532ac7d7 | 280 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
54a0048b SL |
281 | let mut builder = fmt.debug_struct("UnixStream"); |
282 | builder.field("fd", self.0.as_inner()); | |
283 | if let Ok(addr) = self.local_addr() { | |
284 | builder.field("local", &addr); | |
285 | } | |
286 | if let Ok(addr) = self.peer_addr() { | |
287 | builder.field("peer", &addr); | |
288 | } | |
289 | builder.finish() | |
290 | } | |
291 | } | |
292 | ||
293 | impl UnixStream { | |
294 | /// Connects to the socket named by `path`. | |
32a655c1 SL |
295 | /// |
296 | /// # Examples | |
297 | /// | |
298 | /// ```no_run | |
299 | /// use std::os::unix::net::UnixStream; | |
300 | /// | |
301 | /// let socket = match UnixStream::connect("/tmp/sock") { | |
302 | /// Ok(sock) => sock, | |
303 | /// Err(e) => { | |
304 | /// println!("Couldn't connect: {:?}", e); | |
305 | /// return | |
306 | /// } | |
307 | /// }; | |
308 | /// ``` | |
a7813a04 | 309 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
310 | pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> { |
311 | fn inner(path: &Path) -> io::Result<UnixStream> { | |
312 | unsafe { | |
313 | let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; | |
314 | let (addr, len) = sockaddr_un(path)?; | |
315 | ||
316 | cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?; | |
317 | Ok(UnixStream(inner)) | |
318 | } | |
319 | } | |
320 | inner(path.as_ref()) | |
321 | } | |
322 | ||
323 | /// Creates an unnamed pair of connected sockets. | |
324 | /// | |
325 | /// Returns two `UnixStream`s which are connected to each other. | |
32a655c1 SL |
326 | /// |
327 | /// # Examples | |
328 | /// | |
329 | /// ```no_run | |
330 | /// use std::os::unix::net::UnixStream; | |
331 | /// | |
332 | /// let (sock1, sock2) = match UnixStream::pair() { | |
333 | /// Ok((sock1, sock2)) => (sock1, sock2), | |
334 | /// Err(e) => { | |
335 | /// println!("Couldn't create a pair of sockets: {:?}", e); | |
336 | /// return | |
337 | /// } | |
338 | /// }; | |
339 | /// ``` | |
a7813a04 | 340 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
341 | pub fn pair() -> io::Result<(UnixStream, UnixStream)> { |
342 | let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; | |
343 | Ok((UnixStream(i1), UnixStream(i2))) | |
344 | } | |
345 | ||
346 | /// Creates a new independently owned handle to the underlying socket. | |
347 | /// | |
348 | /// The returned `UnixStream` is a reference to the same stream that this | |
349 | /// object references. Both handles will read and write the same stream of | |
3b2f2976 | 350 | /// data, and options set on one stream will be propagated to the other |
54a0048b | 351 | /// stream. |
32a655c1 SL |
352 | /// |
353 | /// # Examples | |
354 | /// | |
355 | /// ```no_run | |
356 | /// use std::os::unix::net::UnixStream; | |
357 | /// | |
60c5eb7d XL |
358 | /// fn main() -> std::io::Result<()> { |
359 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
360 | /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); | |
361 | /// Ok(()) | |
362 | /// } | |
32a655c1 | 363 | /// ``` |
a7813a04 | 364 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
365 | pub fn try_clone(&self) -> io::Result<UnixStream> { |
366 | self.0.duplicate().map(UnixStream) | |
367 | } | |
368 | ||
369 | /// Returns the socket address of the local half of this connection. | |
32a655c1 SL |
370 | /// |
371 | /// # Examples | |
372 | /// | |
373 | /// ```no_run | |
374 | /// use std::os::unix::net::UnixStream; | |
375 | /// | |
60c5eb7d XL |
376 | /// fn main() -> std::io::Result<()> { |
377 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
378 | /// let addr = socket.local_addr().expect("Couldn't get local address"); | |
379 | /// Ok(()) | |
380 | /// } | |
32a655c1 | 381 | /// ``` |
a7813a04 | 382 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
383 | pub fn local_addr(&self) -> io::Result<SocketAddr> { |
384 | SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) | |
385 | } | |
386 | ||
387 | /// Returns the socket address of the remote half of this connection. | |
32a655c1 SL |
388 | /// |
389 | /// # Examples | |
390 | /// | |
391 | /// ```no_run | |
392 | /// use std::os::unix::net::UnixStream; | |
393 | /// | |
60c5eb7d XL |
394 | /// fn main() -> std::io::Result<()> { |
395 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
396 | /// let addr = socket.peer_addr().expect("Couldn't get peer address"); | |
397 | /// Ok(()) | |
398 | /// } | |
32a655c1 | 399 | /// ``` |
a7813a04 | 400 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
401 | pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
402 | SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) | |
403 | } | |
404 | ||
405 | /// Sets the read timeout for the socket. | |
406 | /// | |
cc61c64b | 407 | /// If the provided value is [`None`], then [`read`] calls will block |
0531ce1d | 408 | /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this |
54a0048b | 409 | /// method. |
32a655c1 | 410 | /// |
3dfed10e | 411 | /// [`read`]: io::Read::read |
32a655c1 SL |
412 | /// |
413 | /// # Examples | |
414 | /// | |
415 | /// ```no_run | |
416 | /// use std::os::unix::net::UnixStream; | |
417 | /// use std::time::Duration; | |
418 | /// | |
60c5eb7d XL |
419 | /// fn main() -> std::io::Result<()> { |
420 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
421 | /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); | |
422 | /// Ok(()) | |
423 | /// } | |
32a655c1 | 424 | /// ``` |
0531ce1d XL |
425 | /// |
426 | /// An [`Err`] is returned if the zero [`Duration`] is passed to this | |
427 | /// method: | |
428 | /// | |
429 | /// ```no_run | |
430 | /// use std::io; | |
431 | /// use std::os::unix::net::UnixStream; | |
432 | /// use std::time::Duration; | |
433 | /// | |
60c5eb7d XL |
434 | /// fn main() -> std::io::Result<()> { |
435 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
436 | /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); | |
437 | /// let err = result.unwrap_err(); | |
438 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
439 | /// Ok(()) | |
440 | /// } | |
0531ce1d | 441 | /// ``` |
a7813a04 | 442 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
443 | pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { |
444 | self.0.set_timeout(timeout, libc::SO_RCVTIMEO) | |
445 | } | |
446 | ||
447 | /// Sets the write timeout for the socket. | |
448 | /// | |
cc61c64b | 449 | /// If the provided value is [`None`], then [`write`] calls will block |
0531ce1d XL |
450 | /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is |
451 | /// passed to this method. | |
32a655c1 | 452 | /// |
3dfed10e | 453 | /// [`read`]: io::Read::read |
32a655c1 SL |
454 | /// |
455 | /// # Examples | |
456 | /// | |
457 | /// ```no_run | |
458 | /// use std::os::unix::net::UnixStream; | |
459 | /// use std::time::Duration; | |
460 | /// | |
60c5eb7d XL |
461 | /// fn main() -> std::io::Result<()> { |
462 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
463 | /// socket.set_write_timeout(Some(Duration::new(1, 0))) | |
464 | /// .expect("Couldn't set write timeout"); | |
465 | /// Ok(()) | |
466 | /// } | |
32a655c1 | 467 | /// ``` |
0531ce1d XL |
468 | /// |
469 | /// An [`Err`] is returned if the zero [`Duration`] is passed to this | |
470 | /// method: | |
471 | /// | |
472 | /// ```no_run | |
473 | /// use std::io; | |
474 | /// use std::net::UdpSocket; | |
475 | /// use std::time::Duration; | |
476 | /// | |
60c5eb7d XL |
477 | /// fn main() -> std::io::Result<()> { |
478 | /// let socket = UdpSocket::bind("127.0.0.1:34254")?; | |
479 | /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); | |
480 | /// let err = result.unwrap_err(); | |
481 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
482 | /// Ok(()) | |
483 | /// } | |
0531ce1d | 484 | /// ``` |
a7813a04 | 485 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
486 | pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { |
487 | self.0.set_timeout(timeout, libc::SO_SNDTIMEO) | |
488 | } | |
489 | ||
490 | /// Returns the read timeout of this socket. | |
32a655c1 SL |
491 | /// |
492 | /// # Examples | |
493 | /// | |
494 | /// ```no_run | |
495 | /// use std::os::unix::net::UnixStream; | |
496 | /// use std::time::Duration; | |
497 | /// | |
60c5eb7d XL |
498 | /// fn main() -> std::io::Result<()> { |
499 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
500 | /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); | |
501 | /// assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0))); | |
502 | /// Ok(()) | |
503 | /// } | |
32a655c1 | 504 | /// ``` |
a7813a04 | 505 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
506 | pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
507 | self.0.timeout(libc::SO_RCVTIMEO) | |
508 | } | |
509 | ||
510 | /// Returns the write timeout of this socket. | |
32a655c1 SL |
511 | /// |
512 | /// # Examples | |
513 | /// | |
514 | /// ```no_run | |
515 | /// use std::os::unix::net::UnixStream; | |
516 | /// use std::time::Duration; | |
517 | /// | |
60c5eb7d XL |
518 | /// fn main() -> std::io::Result<()> { |
519 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
520 | /// socket.set_write_timeout(Some(Duration::new(1, 0))) | |
521 | /// .expect("Couldn't set write timeout"); | |
522 | /// assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0))); | |
523 | /// Ok(()) | |
524 | /// } | |
32a655c1 | 525 | /// ``` |
a7813a04 | 526 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
527 | pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
528 | self.0.timeout(libc::SO_SNDTIMEO) | |
529 | } | |
530 | ||
531 | /// Moves the socket into or out of nonblocking mode. | |
32a655c1 SL |
532 | /// |
533 | /// # Examples | |
534 | /// | |
535 | /// ```no_run | |
536 | /// use std::os::unix::net::UnixStream; | |
537 | /// | |
60c5eb7d XL |
538 | /// fn main() -> std::io::Result<()> { |
539 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
540 | /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); | |
541 | /// Ok(()) | |
542 | /// } | |
32a655c1 | 543 | /// ``` |
a7813a04 | 544 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
545 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
546 | self.0.set_nonblocking(nonblocking) | |
547 | } | |
548 | ||
549 | /// Returns the value of the `SO_ERROR` option. | |
32a655c1 SL |
550 | /// |
551 | /// # Examples | |
552 | /// | |
553 | /// ```no_run | |
554 | /// use std::os::unix::net::UnixStream; | |
555 | /// | |
60c5eb7d XL |
556 | /// fn main() -> std::io::Result<()> { |
557 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
558 | /// if let Ok(Some(err)) = socket.take_error() { | |
559 | /// println!("Got error: {:?}", err); | |
560 | /// } | |
561 | /// Ok(()) | |
32a655c1 SL |
562 | /// } |
563 | /// ``` | |
8faf50e0 XL |
564 | /// |
565 | /// # Platform specific | |
9fa01778 | 566 | /// On Redox this always returns `None`. |
a7813a04 | 567 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
568 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
569 | self.0.take_error() | |
570 | } | |
571 | ||
572 | /// Shuts down the read, write, or both halves of this connection. | |
573 | /// | |
574 | /// This function will cause all pending and future I/O calls on the | |
575 | /// specified portions to immediately return with an appropriate value | |
32a655c1 SL |
576 | /// (see the documentation of [`Shutdown`]). |
577 | /// | |
32a655c1 SL |
578 | /// # Examples |
579 | /// | |
580 | /// ```no_run | |
581 | /// use std::os::unix::net::UnixStream; | |
582 | /// use std::net::Shutdown; | |
583 | /// | |
60c5eb7d XL |
584 | /// fn main() -> std::io::Result<()> { |
585 | /// let socket = UnixStream::connect("/tmp/sock")?; | |
586 | /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); | |
587 | /// Ok(()) | |
588 | /// } | |
32a655c1 | 589 | /// ``` |
a7813a04 | 590 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
591 | pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { |
592 | self.0.shutdown(how) | |
593 | } | |
594 | } | |
595 | ||
a7813a04 | 596 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
597 | impl io::Read for UnixStream { |
598 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
599 | io::Read::read(&mut &*self, buf) | |
600 | } | |
601 | ||
48663c56 | 602 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
9fa01778 XL |
603 | io::Read::read_vectored(&mut &*self, bufs) |
604 | } | |
605 | ||
f9f354fc XL |
606 | #[inline] |
607 | fn is_read_vectored(&self) -> bool { | |
608 | io::Read::is_read_vectored(&&*self) | |
609 | } | |
610 | ||
041b39d2 XL |
611 | #[inline] |
612 | unsafe fn initializer(&self) -> Initializer { | |
613 | Initializer::nop() | |
54a0048b SL |
614 | } |
615 | } | |
616 | ||
a7813a04 | 617 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
618 | impl<'a> io::Read for &'a UnixStream { |
619 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
620 | self.0.read(buf) | |
621 | } | |
622 | ||
48663c56 | 623 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
9fa01778 XL |
624 | self.0.read_vectored(bufs) |
625 | } | |
626 | ||
f9f354fc XL |
627 | #[inline] |
628 | fn is_read_vectored(&self) -> bool { | |
629 | self.0.is_read_vectored() | |
630 | } | |
631 | ||
041b39d2 XL |
632 | #[inline] |
633 | unsafe fn initializer(&self) -> Initializer { | |
634 | Initializer::nop() | |
54a0048b SL |
635 | } |
636 | } | |
637 | ||
a7813a04 | 638 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
639 | impl io::Write for UnixStream { |
640 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
641 | io::Write::write(&mut &*self, buf) | |
642 | } | |
643 | ||
48663c56 | 644 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
9fa01778 XL |
645 | io::Write::write_vectored(&mut &*self, bufs) |
646 | } | |
647 | ||
f9f354fc XL |
648 | #[inline] |
649 | fn is_write_vectored(&self) -> bool { | |
650 | io::Write::is_write_vectored(&&*self) | |
651 | } | |
652 | ||
54a0048b SL |
653 | fn flush(&mut self) -> io::Result<()> { |
654 | io::Write::flush(&mut &*self) | |
655 | } | |
656 | } | |
657 | ||
a7813a04 | 658 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
659 | impl<'a> io::Write for &'a UnixStream { |
660 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
661 | self.0.write(buf) | |
662 | } | |
663 | ||
48663c56 | 664 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
9fa01778 XL |
665 | self.0.write_vectored(bufs) |
666 | } | |
667 | ||
f9f354fc XL |
668 | #[inline] |
669 | fn is_write_vectored(&self) -> bool { | |
670 | self.0.is_write_vectored() | |
671 | } | |
672 | ||
54a0048b SL |
673 | fn flush(&mut self) -> io::Result<()> { |
674 | Ok(()) | |
675 | } | |
676 | } | |
677 | ||
a7813a04 | 678 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
679 | impl AsRawFd for UnixStream { |
680 | fn as_raw_fd(&self) -> RawFd { | |
681 | *self.0.as_inner() | |
682 | } | |
683 | } | |
684 | ||
a7813a04 | 685 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
686 | impl FromRawFd for UnixStream { |
687 | unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { | |
688 | UnixStream(Socket::from_inner(fd)) | |
689 | } | |
690 | } | |
691 | ||
a7813a04 | 692 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
693 | impl IntoRawFd for UnixStream { |
694 | fn into_raw_fd(self) -> RawFd { | |
695 | self.0.into_inner() | |
696 | } | |
697 | } | |
698 | ||
3b2f2976 XL |
699 | #[stable(feature = "rust1", since = "1.0.0")] |
700 | impl AsRawFd for net::TcpStream { | |
dfeec247 XL |
701 | fn as_raw_fd(&self) -> RawFd { |
702 | *self.as_inner().socket().as_inner() | |
703 | } | |
3b2f2976 XL |
704 | } |
705 | ||
706 | #[stable(feature = "rust1", since = "1.0.0")] | |
707 | impl AsRawFd for net::TcpListener { | |
dfeec247 XL |
708 | fn as_raw_fd(&self) -> RawFd { |
709 | *self.as_inner().socket().as_inner() | |
710 | } | |
3b2f2976 XL |
711 | } |
712 | ||
713 | #[stable(feature = "rust1", since = "1.0.0")] | |
714 | impl AsRawFd for net::UdpSocket { | |
dfeec247 XL |
715 | fn as_raw_fd(&self) -> RawFd { |
716 | *self.as_inner().socket().as_inner() | |
717 | } | |
3b2f2976 XL |
718 | } |
719 | ||
720 | #[stable(feature = "from_raw_os", since = "1.1.0")] | |
721 | impl FromRawFd for net::TcpStream { | |
722 | unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { | |
723 | let socket = sys::net::Socket::from_inner(fd); | |
724 | net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) | |
725 | } | |
726 | } | |
727 | ||
728 | #[stable(feature = "from_raw_os", since = "1.1.0")] | |
729 | impl FromRawFd for net::TcpListener { | |
730 | unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { | |
731 | let socket = sys::net::Socket::from_inner(fd); | |
732 | net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) | |
733 | } | |
734 | } | |
735 | ||
736 | #[stable(feature = "from_raw_os", since = "1.1.0")] | |
737 | impl FromRawFd for net::UdpSocket { | |
738 | unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { | |
739 | let socket = sys::net::Socket::from_inner(fd); | |
740 | net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) | |
741 | } | |
742 | } | |
743 | ||
744 | #[stable(feature = "into_raw_os", since = "1.4.0")] | |
745 | impl IntoRawFd for net::TcpStream { | |
746 | fn into_raw_fd(self) -> RawFd { | |
747 | self.into_inner().into_socket().into_inner() | |
748 | } | |
749 | } | |
750 | #[stable(feature = "into_raw_os", since = "1.4.0")] | |
751 | impl IntoRawFd for net::TcpListener { | |
752 | fn into_raw_fd(self) -> RawFd { | |
753 | self.into_inner().into_socket().into_inner() | |
754 | } | |
755 | } | |
756 | #[stable(feature = "into_raw_os", since = "1.4.0")] | |
757 | impl IntoRawFd for net::UdpSocket { | |
758 | fn into_raw_fd(self) -> RawFd { | |
759 | self.into_inner().into_socket().into_inner() | |
760 | } | |
761 | } | |
762 | ||
54a0048b SL |
763 | /// A structure representing a Unix domain socket server. |
764 | /// | |
765 | /// # Examples | |
766 | /// | |
32a655c1 | 767 | /// ```no_run |
54a0048b SL |
768 | /// use std::thread; |
769 | /// use std::os::unix::net::{UnixStream, UnixListener}; | |
770 | /// | |
771 | /// fn handle_client(stream: UnixStream) { | |
772 | /// // ... | |
773 | /// } | |
774 | /// | |
60c5eb7d XL |
775 | /// fn main() -> std::io::Result<()> { |
776 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
54a0048b | 777 | /// |
60c5eb7d XL |
778 | /// // accept connections and process them, spawning a new thread for each one |
779 | /// for stream in listener.incoming() { | |
780 | /// match stream { | |
781 | /// Ok(stream) => { | |
782 | /// /* connection succeeded */ | |
783 | /// thread::spawn(|| handle_client(stream)); | |
784 | /// } | |
785 | /// Err(err) => { | |
786 | /// /* connection failed */ | |
787 | /// break; | |
788 | /// } | |
54a0048b SL |
789 | /// } |
790 | /// } | |
60c5eb7d | 791 | /// Ok(()) |
54a0048b | 792 | /// } |
54a0048b | 793 | /// ``` |
a7813a04 | 794 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
795 | pub struct UnixListener(Socket); |
796 | ||
a7813a04 | 797 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b | 798 | impl fmt::Debug for UnixListener { |
532ac7d7 | 799 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
54a0048b SL |
800 | let mut builder = fmt.debug_struct("UnixListener"); |
801 | builder.field("fd", self.0.as_inner()); | |
802 | if let Ok(addr) = self.local_addr() { | |
803 | builder.field("local", &addr); | |
804 | } | |
805 | builder.finish() | |
806 | } | |
807 | } | |
808 | ||
809 | impl UnixListener { | |
810 | /// Creates a new `UnixListener` bound to the specified socket. | |
32a655c1 SL |
811 | /// |
812 | /// # Examples | |
813 | /// | |
814 | /// ```no_run | |
815 | /// use std::os::unix::net::UnixListener; | |
816 | /// | |
817 | /// let listener = match UnixListener::bind("/path/to/the/socket") { | |
818 | /// Ok(sock) => sock, | |
819 | /// Err(e) => { | |
820 | /// println!("Couldn't connect: {:?}", e); | |
821 | /// return | |
822 | /// } | |
823 | /// }; | |
824 | /// ``` | |
a7813a04 | 825 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
826 | pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> { |
827 | fn inner(path: &Path) -> io::Result<UnixListener> { | |
828 | unsafe { | |
829 | let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; | |
830 | let (addr, len) = sockaddr_un(path)?; | |
831 | ||
cc61c64b | 832 | cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; |
54a0048b SL |
833 | cvt(libc::listen(*inner.as_inner(), 128))?; |
834 | ||
835 | Ok(UnixListener(inner)) | |
836 | } | |
837 | } | |
838 | inner(path.as_ref()) | |
839 | } | |
840 | ||
841 | /// Accepts a new incoming connection to this listener. | |
842 | /// | |
843 | /// This function will block the calling thread until a new Unix connection | |
3b2f2976 | 844 | /// is established. When established, the corresponding [`UnixStream`] and |
54a0048b | 845 | /// the remote peer's address will be returned. |
32a655c1 | 846 | /// |
3dfed10e | 847 | /// [`UnixStream`]: crate::os::unix::net::UnixStream |
32a655c1 SL |
848 | /// |
849 | /// # Examples | |
850 | /// | |
851 | /// ```no_run | |
852 | /// use std::os::unix::net::UnixListener; | |
853 | /// | |
60c5eb7d XL |
854 | /// fn main() -> std::io::Result<()> { |
855 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
32a655c1 | 856 | /// |
60c5eb7d XL |
857 | /// match listener.accept() { |
858 | /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), | |
859 | /// Err(e) => println!("accept function failed: {:?}", e), | |
860 | /// } | |
861 | /// Ok(()) | |
32a655c1 SL |
862 | /// } |
863 | /// ``` | |
a7813a04 | 864 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
865 | pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { |
866 | let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; | |
867 | let mut len = mem::size_of_val(&storage) as libc::socklen_t; | |
868 | let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; | |
869 | let addr = SocketAddr::from_parts(storage, len)?; | |
870 | Ok((UnixStream(sock), addr)) | |
871 | } | |
872 | ||
873 | /// Creates a new independently owned handle to the underlying socket. | |
874 | /// | |
875 | /// The returned `UnixListener` is a reference to the same socket that this | |
876 | /// object references. Both handles can be used to accept incoming | |
877 | /// connections and options set on one listener will affect the other. | |
32a655c1 SL |
878 | /// |
879 | /// # Examples | |
880 | /// | |
881 | /// ```no_run | |
882 | /// use std::os::unix::net::UnixListener; | |
883 | /// | |
60c5eb7d XL |
884 | /// fn main() -> std::io::Result<()> { |
885 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
886 | /// let listener_copy = listener.try_clone().expect("try_clone failed"); | |
887 | /// Ok(()) | |
888 | /// } | |
32a655c1 | 889 | /// ``` |
a7813a04 | 890 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
891 | pub fn try_clone(&self) -> io::Result<UnixListener> { |
892 | self.0.duplicate().map(UnixListener) | |
893 | } | |
894 | ||
895 | /// Returns the local socket address of this listener. | |
32a655c1 SL |
896 | /// |
897 | /// # Examples | |
898 | /// | |
899 | /// ```no_run | |
900 | /// use std::os::unix::net::UnixListener; | |
901 | /// | |
60c5eb7d XL |
902 | /// fn main() -> std::io::Result<()> { |
903 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
904 | /// let addr = listener.local_addr().expect("Couldn't get local address"); | |
905 | /// Ok(()) | |
906 | /// } | |
32a655c1 | 907 | /// ``` |
a7813a04 | 908 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
909 | pub fn local_addr(&self) -> io::Result<SocketAddr> { |
910 | SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) | |
911 | } | |
912 | ||
913 | /// Moves the socket into or out of nonblocking mode. | |
32a655c1 | 914 | /// |
dfeec247 XL |
915 | /// This will result in the `accept` operation becoming nonblocking, |
916 | /// i.e., immediately returning from their calls. If the IO operation is | |
917 | /// successful, `Ok` is returned and no further action is required. If the | |
918 | /// IO operation could not be completed and needs to be retried, an error | |
919 | /// with kind [`io::ErrorKind::WouldBlock`] is returned. | |
920 | /// | |
32a655c1 SL |
921 | /// # Examples |
922 | /// | |
923 | /// ```no_run | |
924 | /// use std::os::unix::net::UnixListener; | |
925 | /// | |
60c5eb7d XL |
926 | /// fn main() -> std::io::Result<()> { |
927 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
928 | /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); | |
929 | /// Ok(()) | |
930 | /// } | |
32a655c1 | 931 | /// ``` |
a7813a04 | 932 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
933 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
934 | self.0.set_nonblocking(nonblocking) | |
935 | } | |
936 | ||
937 | /// Returns the value of the `SO_ERROR` option. | |
32a655c1 SL |
938 | /// |
939 | /// # Examples | |
940 | /// | |
941 | /// ```no_run | |
942 | /// use std::os::unix::net::UnixListener; | |
943 | /// | |
60c5eb7d XL |
944 | /// fn main() -> std::io::Result<()> { |
945 | /// let listener = UnixListener::bind("/tmp/sock")?; | |
32a655c1 | 946 | /// |
60c5eb7d XL |
947 | /// if let Ok(Some(err)) = listener.take_error() { |
948 | /// println!("Got error: {:?}", err); | |
949 | /// } | |
950 | /// Ok(()) | |
32a655c1 SL |
951 | /// } |
952 | /// ``` | |
8faf50e0 XL |
953 | /// |
954 | /// # Platform specific | |
9fa01778 | 955 | /// On Redox this always returns `None`. |
a7813a04 | 956 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
957 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
958 | self.0.take_error() | |
959 | } | |
960 | ||
961 | /// Returns an iterator over incoming connections. | |
962 | /// | |
32a655c1 SL |
963 | /// The iterator will never return [`None`] and will also not yield the |
964 | /// peer's [`SocketAddr`] structure. | |
965 | /// | |
32a655c1 SL |
966 | /// # Examples |
967 | /// | |
968 | /// ```no_run | |
969 | /// use std::thread; | |
970 | /// use std::os::unix::net::{UnixStream, UnixListener}; | |
971 | /// | |
972 | /// fn handle_client(stream: UnixStream) { | |
973 | /// // ... | |
974 | /// } | |
975 | /// | |
60c5eb7d XL |
976 | /// fn main() -> std::io::Result<()> { |
977 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
978 | /// | |
979 | /// for stream in listener.incoming() { | |
980 | /// match stream { | |
981 | /// Ok(stream) => { | |
982 | /// thread::spawn(|| handle_client(stream)); | |
983 | /// } | |
984 | /// Err(err) => { | |
985 | /// break; | |
986 | /// } | |
32a655c1 SL |
987 | /// } |
988 | /// } | |
60c5eb7d | 989 | /// Ok(()) |
32a655c1 SL |
990 | /// } |
991 | /// ``` | |
a7813a04 | 992 | #[stable(feature = "unix_socket", since = "1.10.0")] |
416331ca | 993 | pub fn incoming(&self) -> Incoming<'_> { |
54a0048b SL |
994 | Incoming { listener: self } |
995 | } | |
996 | } | |
997 | ||
a7813a04 | 998 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
999 | impl AsRawFd for UnixListener { |
1000 | fn as_raw_fd(&self) -> RawFd { | |
1001 | *self.0.as_inner() | |
1002 | } | |
1003 | } | |
1004 | ||
a7813a04 | 1005 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1006 | impl FromRawFd for UnixListener { |
1007 | unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { | |
1008 | UnixListener(Socket::from_inner(fd)) | |
1009 | } | |
1010 | } | |
1011 | ||
a7813a04 | 1012 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1013 | impl IntoRawFd for UnixListener { |
1014 | fn into_raw_fd(self) -> RawFd { | |
1015 | self.0.into_inner() | |
1016 | } | |
1017 | } | |
1018 | ||
a7813a04 | 1019 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1020 | impl<'a> IntoIterator for &'a UnixListener { |
1021 | type Item = io::Result<UnixStream>; | |
1022 | type IntoIter = Incoming<'a>; | |
1023 | ||
1024 | fn into_iter(self) -> Incoming<'a> { | |
1025 | self.incoming() | |
1026 | } | |
1027 | } | |
1028 | ||
32a655c1 SL |
1029 | /// An iterator over incoming connections to a [`UnixListener`]. |
1030 | /// | |
1031 | /// It will never return [`None`]. | |
1032 | /// | |
32a655c1 | 1033 | /// # Examples |
54a0048b | 1034 | /// |
32a655c1 SL |
1035 | /// ```no_run |
1036 | /// use std::thread; | |
1037 | /// use std::os::unix::net::{UnixStream, UnixListener}; | |
1038 | /// | |
1039 | /// fn handle_client(stream: UnixStream) { | |
1040 | /// // ... | |
1041 | /// } | |
1042 | /// | |
60c5eb7d XL |
1043 | /// fn main() -> std::io::Result<()> { |
1044 | /// let listener = UnixListener::bind("/path/to/the/socket")?; | |
32a655c1 | 1045 | /// |
60c5eb7d XL |
1046 | /// for stream in listener.incoming() { |
1047 | /// match stream { | |
1048 | /// Ok(stream) => { | |
1049 | /// thread::spawn(|| handle_client(stream)); | |
1050 | /// } | |
1051 | /// Err(err) => { | |
1052 | /// break; | |
1053 | /// } | |
32a655c1 SL |
1054 | /// } |
1055 | /// } | |
60c5eb7d | 1056 | /// Ok(()) |
32a655c1 SL |
1057 | /// } |
1058 | /// ``` | |
54a0048b | 1059 | #[derive(Debug)] |
a7813a04 | 1060 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1061 | pub struct Incoming<'a> { |
1062 | listener: &'a UnixListener, | |
1063 | } | |
1064 | ||
a7813a04 | 1065 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1066 | impl<'a> Iterator for Incoming<'a> { |
1067 | type Item = io::Result<UnixStream>; | |
1068 | ||
1069 | fn next(&mut self) -> Option<io::Result<UnixStream>> { | |
1070 | Some(self.listener.accept().map(|s| s.0)) | |
1071 | } | |
1072 | ||
1073 | fn size_hint(&self) -> (usize, Option<usize>) { | |
f035d41b | 1074 | (usize::MAX, None) |
54a0048b SL |
1075 | } |
1076 | } | |
1077 | ||
1078 | /// A Unix datagram socket. | |
1079 | /// | |
1080 | /// # Examples | |
1081 | /// | |
32a655c1 | 1082 | /// ```no_run |
54a0048b SL |
1083 | /// use std::os::unix::net::UnixDatagram; |
1084 | /// | |
60c5eb7d XL |
1085 | /// fn main() -> std::io::Result<()> { |
1086 | /// let socket = UnixDatagram::bind("/path/to/my/socket")?; | |
1087 | /// socket.send_to(b"hello world", "/path/to/other/socket")?; | |
1088 | /// let mut buf = [0; 100]; | |
1089 | /// let (count, address) = socket.recv_from(&mut buf)?; | |
1090 | /// println!("socket {:?} sent {:?}", address, &buf[..count]); | |
1091 | /// Ok(()) | |
1092 | /// } | |
54a0048b | 1093 | /// ``` |
a7813a04 | 1094 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1095 | pub struct UnixDatagram(Socket); |
1096 | ||
a7813a04 | 1097 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b | 1098 | impl fmt::Debug for UnixDatagram { |
532ac7d7 | 1099 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
54a0048b SL |
1100 | let mut builder = fmt.debug_struct("UnixDatagram"); |
1101 | builder.field("fd", self.0.as_inner()); | |
1102 | if let Ok(addr) = self.local_addr() { | |
1103 | builder.field("local", &addr); | |
1104 | } | |
1105 | if let Ok(addr) = self.peer_addr() { | |
1106 | builder.field("peer", &addr); | |
1107 | } | |
1108 | builder.finish() | |
1109 | } | |
1110 | } | |
1111 | ||
1112 | impl UnixDatagram { | |
1113 | /// Creates a Unix datagram socket bound to the given path. | |
32a655c1 SL |
1114 | /// |
1115 | /// # Examples | |
1116 | /// | |
1117 | /// ```no_run | |
1118 | /// use std::os::unix::net::UnixDatagram; | |
1119 | /// | |
1120 | /// let sock = match UnixDatagram::bind("/path/to/the/socket") { | |
1121 | /// Ok(sock) => sock, | |
1122 | /// Err(e) => { | |
1123 | /// println!("Couldn't bind: {:?}", e); | |
1124 | /// return | |
1125 | /// } | |
1126 | /// }; | |
1127 | /// ``` | |
a7813a04 | 1128 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1129 | pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> { |
1130 | fn inner(path: &Path) -> io::Result<UnixDatagram> { | |
1131 | unsafe { | |
1132 | let socket = UnixDatagram::unbound()?; | |
1133 | let (addr, len) = sockaddr_un(path)?; | |
1134 | ||
cc61c64b | 1135 | cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?; |
54a0048b SL |
1136 | |
1137 | Ok(socket) | |
1138 | } | |
1139 | } | |
1140 | inner(path.as_ref()) | |
1141 | } | |
1142 | ||
1143 | /// Creates a Unix Datagram socket which is not bound to any address. | |
32a655c1 SL |
1144 | /// |
1145 | /// # Examples | |
1146 | /// | |
1147 | /// ```no_run | |
1148 | /// use std::os::unix::net::UnixDatagram; | |
1149 | /// | |
1150 | /// let sock = match UnixDatagram::unbound() { | |
1151 | /// Ok(sock) => sock, | |
1152 | /// Err(e) => { | |
1153 | /// println!("Couldn't unbound: {:?}", e); | |
1154 | /// return | |
1155 | /// } | |
1156 | /// }; | |
1157 | /// ``` | |
a7813a04 | 1158 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1159 | pub fn unbound() -> io::Result<UnixDatagram> { |
1160 | let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; | |
1161 | Ok(UnixDatagram(inner)) | |
1162 | } | |
1163 | ||
9fa01778 | 1164 | /// Creates an unnamed pair of connected sockets. |
54a0048b SL |
1165 | /// |
1166 | /// Returns two `UnixDatagrams`s which are connected to each other. | |
32a655c1 SL |
1167 | /// |
1168 | /// # Examples | |
1169 | /// | |
1170 | /// ```no_run | |
1171 | /// use std::os::unix::net::UnixDatagram; | |
1172 | /// | |
1173 | /// let (sock1, sock2) = match UnixDatagram::pair() { | |
1174 | /// Ok((sock1, sock2)) => (sock1, sock2), | |
1175 | /// Err(e) => { | |
1176 | /// println!("Couldn't unbound: {:?}", e); | |
1177 | /// return | |
1178 | /// } | |
1179 | /// }; | |
1180 | /// ``` | |
a7813a04 | 1181 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1182 | pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { |
1183 | let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; | |
1184 | Ok((UnixDatagram(i1), UnixDatagram(i2))) | |
1185 | } | |
1186 | ||
1187 | /// Connects the socket to the specified address. | |
1188 | /// | |
cc61c64b XL |
1189 | /// The [`send`] method may be used to send data to the specified address. |
1190 | /// [`recv`] and [`recv_from`] will only receive data from that address. | |
32a655c1 | 1191 | /// |
3dfed10e XL |
1192 | /// [`send`]: UnixDatagram::send |
1193 | /// [`recv`]: UnixDatagram::recv | |
1194 | /// [`recv_from`]: UnixDatagram::recv_from | |
32a655c1 SL |
1195 | /// |
1196 | /// # Examples | |
1197 | /// | |
1198 | /// ```no_run | |
1199 | /// use std::os::unix::net::UnixDatagram; | |
1200 | /// | |
60c5eb7d XL |
1201 | /// fn main() -> std::io::Result<()> { |
1202 | /// let sock = UnixDatagram::unbound()?; | |
1203 | /// match sock.connect("/path/to/the/socket") { | |
1204 | /// Ok(sock) => sock, | |
1205 | /// Err(e) => { | |
1206 | /// println!("Couldn't connect: {:?}", e); | |
1207 | /// return Err(e) | |
1208 | /// } | |
1209 | /// }; | |
1210 | /// Ok(()) | |
1211 | /// } | |
32a655c1 | 1212 | /// ``` |
a7813a04 | 1213 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1214 | pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { |
1215 | fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> { | |
1216 | unsafe { | |
1217 | let (addr, len) = sockaddr_un(path)?; | |
1218 | ||
1219 | cvt(libc::connect(*d.0.as_inner(), &addr as *const _ as *const _, len))?; | |
1220 | ||
1221 | Ok(()) | |
1222 | } | |
1223 | } | |
1224 | inner(self, path.as_ref()) | |
1225 | } | |
1226 | ||
1227 | /// Creates a new independently owned handle to the underlying socket. | |
1228 | /// | |
32a655c1 | 1229 | /// The returned `UnixDatagram` is a reference to the same socket that this |
54a0048b | 1230 | /// object references. Both handles can be used to accept incoming |
32a655c1 SL |
1231 | /// connections and options set on one side will affect the other. |
1232 | /// | |
1233 | /// # Examples | |
1234 | /// | |
1235 | /// ```no_run | |
1236 | /// use std::os::unix::net::UnixDatagram; | |
1237 | /// | |
60c5eb7d XL |
1238 | /// fn main() -> std::io::Result<()> { |
1239 | /// let sock = UnixDatagram::bind("/path/to/the/socket")?; | |
1240 | /// let sock_copy = sock.try_clone().expect("try_clone failed"); | |
1241 | /// Ok(()) | |
1242 | /// } | |
32a655c1 | 1243 | /// ``` |
a7813a04 | 1244 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1245 | pub fn try_clone(&self) -> io::Result<UnixDatagram> { |
1246 | self.0.duplicate().map(UnixDatagram) | |
1247 | } | |
1248 | ||
1249 | /// Returns the address of this socket. | |
32a655c1 SL |
1250 | /// |
1251 | /// # Examples | |
1252 | /// | |
1253 | /// ```no_run | |
1254 | /// use std::os::unix::net::UnixDatagram; | |
1255 | /// | |
60c5eb7d XL |
1256 | /// fn main() -> std::io::Result<()> { |
1257 | /// let sock = UnixDatagram::bind("/path/to/the/socket")?; | |
1258 | /// let addr = sock.local_addr().expect("Couldn't get local address"); | |
1259 | /// Ok(()) | |
1260 | /// } | |
32a655c1 | 1261 | /// ``` |
a7813a04 | 1262 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1263 | pub fn local_addr(&self) -> io::Result<SocketAddr> { |
1264 | SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) | |
1265 | } | |
1266 | ||
1267 | /// Returns the address of this socket's peer. | |
1268 | /// | |
cc61c64b | 1269 | /// The [`connect`] method will connect the socket to a peer. |
32a655c1 | 1270 | /// |
3dfed10e | 1271 | /// [`connect`]: UnixDatagram::connect |
32a655c1 SL |
1272 | /// |
1273 | /// # Examples | |
1274 | /// | |
1275 | /// ```no_run | |
1276 | /// use std::os::unix::net::UnixDatagram; | |
1277 | /// | |
60c5eb7d XL |
1278 | /// fn main() -> std::io::Result<()> { |
1279 | /// let sock = UnixDatagram::unbound()?; | |
1280 | /// sock.connect("/path/to/the/socket")?; | |
32a655c1 | 1281 | /// |
60c5eb7d XL |
1282 | /// let addr = sock.peer_addr().expect("Couldn't get peer address"); |
1283 | /// Ok(()) | |
1284 | /// } | |
32a655c1 | 1285 | /// ``` |
a7813a04 | 1286 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1287 | pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
1288 | SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) | |
1289 | } | |
1290 | ||
1291 | /// Receives data from the socket. | |
1292 | /// | |
1293 | /// On success, returns the number of bytes read and the address from | |
1294 | /// whence the data came. | |
32a655c1 SL |
1295 | /// |
1296 | /// # Examples | |
1297 | /// | |
1298 | /// ```no_run | |
1299 | /// use std::os::unix::net::UnixDatagram; | |
1300 | /// | |
60c5eb7d XL |
1301 | /// fn main() -> std::io::Result<()> { |
1302 | /// let sock = UnixDatagram::unbound()?; | |
1303 | /// let mut buf = vec![0; 10]; | |
1304 | /// let (size, sender) = sock.recv_from(buf.as_mut_slice())?; | |
1305 | /// println!("received {} bytes from {:?}", size, sender); | |
1306 | /// Ok(()) | |
32a655c1 SL |
1307 | /// } |
1308 | /// ``` | |
a7813a04 | 1309 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1310 | pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
1311 | let mut count = 0; | |
dfeec247 XL |
1312 | let addr = SocketAddr::new(|addr, len| unsafe { |
1313 | count = libc::recvfrom( | |
1314 | *self.0.as_inner(), | |
1315 | buf.as_mut_ptr() as *mut _, | |
1316 | buf.len(), | |
1317 | 0, | |
1318 | addr, | |
1319 | len, | |
1320 | ); | |
1321 | if count > 0 { | |
1322 | 1 | |
1323 | } else if count == 0 { | |
1324 | 0 | |
1325 | } else { | |
1326 | -1 | |
54a0048b SL |
1327 | } |
1328 | })?; | |
1329 | ||
1330 | Ok((count as usize, addr)) | |
1331 | } | |
1332 | ||
1333 | /// Receives data from the socket. | |
1334 | /// | |
1335 | /// On success, returns the number of bytes read. | |
32a655c1 SL |
1336 | /// |
1337 | /// # Examples | |
1338 | /// | |
1339 | /// ```no_run | |
1340 | /// use std::os::unix::net::UnixDatagram; | |
1341 | /// | |
60c5eb7d XL |
1342 | /// fn main() -> std::io::Result<()> { |
1343 | /// let sock = UnixDatagram::bind("/path/to/the/socket")?; | |
1344 | /// let mut buf = vec![0; 10]; | |
1345 | /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); | |
1346 | /// Ok(()) | |
1347 | /// } | |
32a655c1 | 1348 | /// ``` |
a7813a04 | 1349 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1350 | pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { |
1351 | self.0.read(buf) | |
1352 | } | |
1353 | ||
1354 | /// Sends data on the socket to the specified address. | |
1355 | /// | |
1356 | /// On success, returns the number of bytes written. | |
32a655c1 SL |
1357 | /// |
1358 | /// # Examples | |
1359 | /// | |
1360 | /// ```no_run | |
1361 | /// use std::os::unix::net::UnixDatagram; | |
1362 | /// | |
60c5eb7d XL |
1363 | /// fn main() -> std::io::Result<()> { |
1364 | /// let sock = UnixDatagram::unbound()?; | |
1365 | /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); | |
1366 | /// Ok(()) | |
1367 | /// } | |
32a655c1 | 1368 | /// ``` |
a7813a04 | 1369 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1370 | pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> { |
1371 | fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> { | |
1372 | unsafe { | |
1373 | let (addr, len) = sockaddr_un(path)?; | |
1374 | ||
dfeec247 XL |
1375 | let count = cvt(libc::sendto( |
1376 | *d.0.as_inner(), | |
1377 | buf.as_ptr() as *const _, | |
1378 | buf.len(), | |
1379 | MSG_NOSIGNAL, | |
1380 | &addr as *const _ as *const _, | |
1381 | len, | |
1382 | ))?; | |
54a0048b SL |
1383 | Ok(count as usize) |
1384 | } | |
1385 | } | |
1386 | inner(self, buf, path.as_ref()) | |
1387 | } | |
1388 | ||
1389 | /// Sends data on the socket to the socket's peer. | |
1390 | /// | |
1391 | /// The peer address may be set by the `connect` method, and this method | |
1392 | /// will return an error if the socket has not already been connected. | |
1393 | /// | |
1394 | /// On success, returns the number of bytes written. | |
32a655c1 SL |
1395 | /// |
1396 | /// # Examples | |
1397 | /// | |
1398 | /// ```no_run | |
1399 | /// use std::os::unix::net::UnixDatagram; | |
1400 | /// | |
60c5eb7d XL |
1401 | /// fn main() -> std::io::Result<()> { |
1402 | /// let sock = UnixDatagram::unbound()?; | |
1403 | /// sock.connect("/some/sock").expect("Couldn't connect"); | |
1404 | /// sock.send(b"omelette au fromage").expect("send_to function failed"); | |
1405 | /// Ok(()) | |
1406 | /// } | |
32a655c1 | 1407 | /// ``` |
a7813a04 | 1408 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1409 | pub fn send(&self, buf: &[u8]) -> io::Result<usize> { |
1410 | self.0.write(buf) | |
1411 | } | |
1412 | ||
1413 | /// Sets the read timeout for the socket. | |
1414 | /// | |
cc61c64b | 1415 | /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will |
0531ce1d XL |
1416 | /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] |
1417 | /// is passed to this method. | |
32a655c1 | 1418 | /// |
3dfed10e XL |
1419 | /// [`recv`]: UnixDatagram::recv |
1420 | /// [`recv_from`]: UnixDatagram::recv_from | |
32a655c1 SL |
1421 | /// |
1422 | /// # Examples | |
1423 | /// | |
1424 | /// ``` | |
1425 | /// use std::os::unix::net::UnixDatagram; | |
1426 | /// use std::time::Duration; | |
1427 | /// | |
60c5eb7d XL |
1428 | /// fn main() -> std::io::Result<()> { |
1429 | /// let sock = UnixDatagram::unbound()?; | |
1430 | /// sock.set_read_timeout(Some(Duration::new(1, 0))) | |
1431 | /// .expect("set_read_timeout function failed"); | |
1432 | /// Ok(()) | |
1433 | /// } | |
32a655c1 | 1434 | /// ``` |
0531ce1d XL |
1435 | /// |
1436 | /// An [`Err`] is returned if the zero [`Duration`] is passed to this | |
1437 | /// method: | |
1438 | /// | |
1439 | /// ```no_run | |
1440 | /// use std::io; | |
1441 | /// use std::os::unix::net::UnixDatagram; | |
1442 | /// use std::time::Duration; | |
1443 | /// | |
60c5eb7d XL |
1444 | /// fn main() -> std::io::Result<()> { |
1445 | /// let socket = UnixDatagram::unbound()?; | |
1446 | /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); | |
1447 | /// let err = result.unwrap_err(); | |
1448 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
1449 | /// Ok(()) | |
1450 | /// } | |
0531ce1d | 1451 | /// ``` |
a7813a04 | 1452 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1453 | pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { |
1454 | self.0.set_timeout(timeout, libc::SO_RCVTIMEO) | |
1455 | } | |
1456 | ||
1457 | /// Sets the write timeout for the socket. | |
1458 | /// | |
cc61c64b | 1459 | /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will |
0531ce1d | 1460 | /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this |
54a0048b | 1461 | /// method. |
32a655c1 | 1462 | /// |
3dfed10e XL |
1463 | /// [`send`]: UnixDatagram::send |
1464 | /// [`send_to`]: UnixDatagram::send_to | |
32a655c1 SL |
1465 | /// |
1466 | /// # Examples | |
1467 | /// | |
1468 | /// ``` | |
1469 | /// use std::os::unix::net::UnixDatagram; | |
1470 | /// use std::time::Duration; | |
1471 | /// | |
60c5eb7d XL |
1472 | /// fn main() -> std::io::Result<()> { |
1473 | /// let sock = UnixDatagram::unbound()?; | |
1474 | /// sock.set_write_timeout(Some(Duration::new(1, 0))) | |
1475 | /// .expect("set_write_timeout function failed"); | |
1476 | /// Ok(()) | |
1477 | /// } | |
32a655c1 | 1478 | /// ``` |
0531ce1d XL |
1479 | /// |
1480 | /// An [`Err`] is returned if the zero [`Duration`] is passed to this | |
1481 | /// method: | |
1482 | /// | |
1483 | /// ```no_run | |
1484 | /// use std::io; | |
1485 | /// use std::os::unix::net::UnixDatagram; | |
1486 | /// use std::time::Duration; | |
1487 | /// | |
60c5eb7d XL |
1488 | /// fn main() -> std::io::Result<()> { |
1489 | /// let socket = UnixDatagram::unbound()?; | |
1490 | /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); | |
1491 | /// let err = result.unwrap_err(); | |
1492 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
1493 | /// Ok(()) | |
1494 | /// } | |
0531ce1d | 1495 | /// ``` |
a7813a04 | 1496 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1497 | pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { |
1498 | self.0.set_timeout(timeout, libc::SO_SNDTIMEO) | |
1499 | } | |
1500 | ||
1501 | /// Returns the read timeout of this socket. | |
32a655c1 SL |
1502 | /// |
1503 | /// # Examples | |
1504 | /// | |
1505 | /// ``` | |
1506 | /// use std::os::unix::net::UnixDatagram; | |
1507 | /// use std::time::Duration; | |
1508 | /// | |
60c5eb7d XL |
1509 | /// fn main() -> std::io::Result<()> { |
1510 | /// let sock = UnixDatagram::unbound()?; | |
1511 | /// sock.set_read_timeout(Some(Duration::new(1, 0))) | |
1512 | /// .expect("set_read_timeout function failed"); | |
1513 | /// assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0))); | |
1514 | /// Ok(()) | |
1515 | /// } | |
32a655c1 | 1516 | /// ``` |
a7813a04 | 1517 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1518 | pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
1519 | self.0.timeout(libc::SO_RCVTIMEO) | |
1520 | } | |
1521 | ||
1522 | /// Returns the write timeout of this socket. | |
32a655c1 SL |
1523 | /// |
1524 | /// # Examples | |
1525 | /// | |
1526 | /// ``` | |
1527 | /// use std::os::unix::net::UnixDatagram; | |
1528 | /// use std::time::Duration; | |
1529 | /// | |
60c5eb7d XL |
1530 | /// fn main() -> std::io::Result<()> { |
1531 | /// let sock = UnixDatagram::unbound()?; | |
1532 | /// sock.set_write_timeout(Some(Duration::new(1, 0))) | |
1533 | /// .expect("set_write_timeout function failed"); | |
1534 | /// assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0))); | |
1535 | /// Ok(()) | |
1536 | /// } | |
32a655c1 | 1537 | /// ``` |
a7813a04 | 1538 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1539 | pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
1540 | self.0.timeout(libc::SO_SNDTIMEO) | |
1541 | } | |
1542 | ||
1543 | /// Moves the socket into or out of nonblocking mode. | |
32a655c1 SL |
1544 | /// |
1545 | /// # Examples | |
1546 | /// | |
1547 | /// ``` | |
1548 | /// use std::os::unix::net::UnixDatagram; | |
1549 | /// | |
60c5eb7d XL |
1550 | /// fn main() -> std::io::Result<()> { |
1551 | /// let sock = UnixDatagram::unbound()?; | |
1552 | /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); | |
1553 | /// Ok(()) | |
1554 | /// } | |
32a655c1 | 1555 | /// ``` |
a7813a04 | 1556 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1557 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
1558 | self.0.set_nonblocking(nonblocking) | |
1559 | } | |
1560 | ||
1561 | /// Returns the value of the `SO_ERROR` option. | |
32a655c1 SL |
1562 | /// |
1563 | /// # Examples | |
1564 | /// | |
1565 | /// ```no_run | |
1566 | /// use std::os::unix::net::UnixDatagram; | |
1567 | /// | |
60c5eb7d XL |
1568 | /// fn main() -> std::io::Result<()> { |
1569 | /// let sock = UnixDatagram::unbound()?; | |
1570 | /// if let Ok(Some(err)) = sock.take_error() { | |
1571 | /// println!("Got error: {:?}", err); | |
1572 | /// } | |
1573 | /// Ok(()) | |
32a655c1 SL |
1574 | /// } |
1575 | /// ``` | |
a7813a04 | 1576 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1577 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
1578 | self.0.take_error() | |
1579 | } | |
1580 | ||
1581 | /// Shut down the read, write, or both halves of this connection. | |
1582 | /// | |
1583 | /// This function will cause all pending and future I/O calls on the | |
1584 | /// specified portions to immediately return with an appropriate value | |
32a655c1 SL |
1585 | /// (see the documentation of [`Shutdown`]). |
1586 | /// | |
32a655c1 SL |
1587 | /// ```no_run |
1588 | /// use std::os::unix::net::UnixDatagram; | |
1589 | /// use std::net::Shutdown; | |
1590 | /// | |
60c5eb7d XL |
1591 | /// fn main() -> std::io::Result<()> { |
1592 | /// let sock = UnixDatagram::unbound()?; | |
1593 | /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); | |
1594 | /// Ok(()) | |
1595 | /// } | |
32a655c1 | 1596 | /// ``` |
a7813a04 | 1597 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1598 | pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { |
1599 | self.0.shutdown(how) | |
1600 | } | |
1601 | } | |
1602 | ||
a7813a04 | 1603 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1604 | impl AsRawFd for UnixDatagram { |
1605 | fn as_raw_fd(&self) -> RawFd { | |
1606 | *self.0.as_inner() | |
1607 | } | |
1608 | } | |
1609 | ||
a7813a04 | 1610 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1611 | impl FromRawFd for UnixDatagram { |
1612 | unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { | |
1613 | UnixDatagram(Socket::from_inner(fd)) | |
1614 | } | |
1615 | } | |
1616 | ||
a7813a04 | 1617 | #[stable(feature = "unix_socket", since = "1.10.0")] |
54a0048b SL |
1618 | impl IntoRawFd for UnixDatagram { |
1619 | fn into_raw_fd(self) -> RawFd { | |
1620 | self.0.into_inner() | |
1621 | } | |
1622 | } | |
1623 | ||
c30ab7b3 | 1624 | #[cfg(all(test, not(target_os = "emscripten")))] |
54a0048b | 1625 | mod test { |
532ac7d7 | 1626 | use crate::io::prelude::*; |
dfeec247 | 1627 | use crate::io::{self, ErrorKind}; |
532ac7d7 | 1628 | use crate::sys_common::io::test::tmpdir; |
dfeec247 XL |
1629 | use crate::thread; |
1630 | use crate::time::Duration; | |
54a0048b SL |
1631 | |
1632 | use super::*; | |
1633 | ||
1634 | macro_rules! or_panic { | |
1635 | ($e:expr) => { | |
1636 | match $e { | |
1637 | Ok(e) => e, | |
1638 | Err(e) => panic!("{}", e), | |
1639 | } | |
dfeec247 | 1640 | }; |
54a0048b SL |
1641 | } |
1642 | ||
1643 | #[test] | |
1644 | fn basic() { | |
1645 | let dir = tmpdir(); | |
1646 | let socket_path = dir.path().join("sock"); | |
1647 | let msg1 = b"hello"; | |
1648 | let msg2 = b"world!"; | |
1649 | ||
1650 | let listener = or_panic!(UnixListener::bind(&socket_path)); | |
1651 | let thread = thread::spawn(move || { | |
1652 | let mut stream = or_panic!(listener.accept()).0; | |
1653 | let mut buf = [0; 5]; | |
1654 | or_panic!(stream.read(&mut buf)); | |
1655 | assert_eq!(&msg1[..], &buf[..]); | |
1656 | or_panic!(stream.write_all(msg2)); | |
1657 | }); | |
1658 | ||
1659 | let mut stream = or_panic!(UnixStream::connect(&socket_path)); | |
dfeec247 | 1660 | assert_eq!(Some(&*socket_path), stream.peer_addr().unwrap().as_pathname()); |
54a0048b SL |
1661 | or_panic!(stream.write_all(msg1)); |
1662 | let mut buf = vec![]; | |
1663 | or_panic!(stream.read_to_end(&mut buf)); | |
1664 | assert_eq!(&msg2[..], &buf[..]); | |
1665 | drop(stream); | |
1666 | ||
1667 | thread.join().unwrap(); | |
1668 | } | |
1669 | ||
9fa01778 XL |
1670 | #[test] |
1671 | fn vectored() { | |
1672 | let (mut s1, mut s2) = or_panic!(UnixStream::pair()); | |
1673 | ||
dfeec247 XL |
1674 | let len = or_panic!(s1.write_vectored(&[ |
1675 | IoSlice::new(b"hello"), | |
1676 | IoSlice::new(b" "), | |
1677 | IoSlice::new(b"world!") | |
1678 | ],)); | |
9fa01778 XL |
1679 | assert_eq!(len, 12); |
1680 | ||
1681 | let mut buf1 = [0; 6]; | |
1682 | let mut buf2 = [0; 7]; | |
dfeec247 XL |
1683 | let len = or_panic!( |
1684 | s2.read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],) | |
1685 | ); | |
9fa01778 XL |
1686 | assert_eq!(len, 12); |
1687 | assert_eq!(&buf1, b"hello "); | |
1688 | assert_eq!(&buf2, b"world!\0"); | |
1689 | } | |
1690 | ||
54a0048b SL |
1691 | #[test] |
1692 | fn pair() { | |
1693 | let msg1 = b"hello"; | |
1694 | let msg2 = b"world!"; | |
1695 | ||
1696 | let (mut s1, mut s2) = or_panic!(UnixStream::pair()); | |
1697 | let thread = thread::spawn(move || { | |
1698 | // s1 must be moved in or the test will hang! | |
1699 | let mut buf = [0; 5]; | |
1700 | or_panic!(s1.read(&mut buf)); | |
1701 | assert_eq!(&msg1[..], &buf[..]); | |
1702 | or_panic!(s1.write_all(msg2)); | |
1703 | }); | |
1704 | ||
1705 | or_panic!(s2.write_all(msg1)); | |
1706 | let mut buf = vec![]; | |
1707 | or_panic!(s2.read_to_end(&mut buf)); | |
1708 | assert_eq!(&msg2[..], &buf[..]); | |
1709 | drop(s2); | |
1710 | ||
1711 | thread.join().unwrap(); | |
1712 | } | |
1713 | ||
1714 | #[test] | |
1715 | fn try_clone() { | |
1716 | let dir = tmpdir(); | |
1717 | let socket_path = dir.path().join("sock"); | |
1718 | let msg1 = b"hello"; | |
1719 | let msg2 = b"world"; | |
1720 | ||
1721 | let listener = or_panic!(UnixListener::bind(&socket_path)); | |
1722 | let thread = thread::spawn(move || { | |
1723 | let mut stream = or_panic!(listener.accept()).0; | |
1724 | or_panic!(stream.write_all(msg1)); | |
1725 | or_panic!(stream.write_all(msg2)); | |
1726 | }); | |
1727 | ||
1728 | let mut stream = or_panic!(UnixStream::connect(&socket_path)); | |
1729 | let mut stream2 = or_panic!(stream.try_clone()); | |
1730 | ||
1731 | let mut buf = [0; 5]; | |
1732 | or_panic!(stream.read(&mut buf)); | |
1733 | assert_eq!(&msg1[..], &buf[..]); | |
1734 | or_panic!(stream2.read(&mut buf)); | |
1735 | assert_eq!(&msg2[..], &buf[..]); | |
1736 | ||
1737 | thread.join().unwrap(); | |
1738 | } | |
1739 | ||
1740 | #[test] | |
1741 | fn iter() { | |
1742 | let dir = tmpdir(); | |
1743 | let socket_path = dir.path().join("sock"); | |
1744 | ||
1745 | let listener = or_panic!(UnixListener::bind(&socket_path)); | |
1746 | let thread = thread::spawn(move || { | |
1747 | for stream in listener.incoming().take(2) { | |
1748 | let mut stream = or_panic!(stream); | |
1749 | let mut buf = [0]; | |
1750 | or_panic!(stream.read(&mut buf)); | |
1751 | } | |
1752 | }); | |
1753 | ||
1754 | for _ in 0..2 { | |
1755 | let mut stream = or_panic!(UnixStream::connect(&socket_path)); | |
1756 | or_panic!(stream.write_all(&[0])); | |
1757 | } | |
1758 | ||
1759 | thread.join().unwrap(); | |
1760 | } | |
1761 | ||
1762 | #[test] | |
1763 | fn long_path() { | |
1764 | let dir = tmpdir(); | |
dfeec247 XL |
1765 | let socket_path = dir.path().join( |
1766 | "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa\ | |
1767 | sasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf", | |
1768 | ); | |
54a0048b SL |
1769 | match UnixStream::connect(&socket_path) { |
1770 | Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} | |
1771 | Err(e) => panic!("unexpected error {}", e), | |
1772 | Ok(_) => panic!("unexpected success"), | |
1773 | } | |
1774 | ||
1775 | match UnixListener::bind(&socket_path) { | |
1776 | Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} | |
1777 | Err(e) => panic!("unexpected error {}", e), | |
1778 | Ok(_) => panic!("unexpected success"), | |
1779 | } | |
1780 | ||
1781 | match UnixDatagram::bind(&socket_path) { | |
1782 | Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} | |
1783 | Err(e) => panic!("unexpected error {}", e), | |
1784 | Ok(_) => panic!("unexpected success"), | |
1785 | } | |
1786 | } | |
1787 | ||
1788 | #[test] | |
1789 | fn timeouts() { | |
1790 | let dir = tmpdir(); | |
1791 | let socket_path = dir.path().join("sock"); | |
1792 | ||
1793 | let _listener = or_panic!(UnixListener::bind(&socket_path)); | |
1794 | ||
1795 | let stream = or_panic!(UnixStream::connect(&socket_path)); | |
1796 | let dur = Duration::new(15410, 0); | |
1797 | ||
1798 | assert_eq!(None, or_panic!(stream.read_timeout())); | |
1799 | ||
1800 | or_panic!(stream.set_read_timeout(Some(dur))); | |
1801 | assert_eq!(Some(dur), or_panic!(stream.read_timeout())); | |
1802 | ||
1803 | assert_eq!(None, or_panic!(stream.write_timeout())); | |
1804 | ||
1805 | or_panic!(stream.set_write_timeout(Some(dur))); | |
1806 | assert_eq!(Some(dur), or_panic!(stream.write_timeout())); | |
1807 | ||
1808 | or_panic!(stream.set_read_timeout(None)); | |
1809 | assert_eq!(None, or_panic!(stream.read_timeout())); | |
1810 | ||
1811 | or_panic!(stream.set_write_timeout(None)); | |
1812 | assert_eq!(None, or_panic!(stream.write_timeout())); | |
1813 | } | |
1814 | ||
1815 | #[test] | |
1816 | fn test_read_timeout() { | |
1817 | let dir = tmpdir(); | |
1818 | let socket_path = dir.path().join("sock"); | |
1819 | ||
1820 | let _listener = or_panic!(UnixListener::bind(&socket_path)); | |
1821 | ||
1822 | let mut stream = or_panic!(UnixStream::connect(&socket_path)); | |
1823 | or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); | |
1824 | ||
1825 | let mut buf = [0; 10]; | |
a1dfa0c6 | 1826 | let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); |
dfeec247 XL |
1827 | assert!( |
1828 | kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, | |
1829 | "unexpected_error: {:?}", | |
1830 | kind | |
1831 | ); | |
54a0048b SL |
1832 | } |
1833 | ||
1834 | #[test] | |
1835 | fn test_read_with_timeout() { | |
1836 | let dir = tmpdir(); | |
1837 | let socket_path = dir.path().join("sock"); | |
1838 | ||
1839 | let listener = or_panic!(UnixListener::bind(&socket_path)); | |
1840 | ||
1841 | let mut stream = or_panic!(UnixStream::connect(&socket_path)); | |
1842 | or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); | |
1843 | ||
1844 | let mut other_end = or_panic!(listener.accept()).0; | |
1845 | or_panic!(other_end.write_all(b"hello world")); | |
1846 | ||
1847 | let mut buf = [0; 11]; | |
1848 | or_panic!(stream.read(&mut buf)); | |
1849 | assert_eq!(b"hello world", &buf[..]); | |
1850 | ||
a1dfa0c6 | 1851 | let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); |
dfeec247 XL |
1852 | assert!( |
1853 | kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, | |
1854 | "unexpected_error: {:?}", | |
1855 | kind | |
1856 | ); | |
54a0048b SL |
1857 | } |
1858 | ||
0531ce1d XL |
1859 | // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors |
1860 | // when passed zero Durations | |
1861 | #[test] | |
1862 | fn test_unix_stream_timeout_zero_duration() { | |
1863 | let dir = tmpdir(); | |
1864 | let socket_path = dir.path().join("sock"); | |
1865 | ||
1866 | let listener = or_panic!(UnixListener::bind(&socket_path)); | |
1867 | let stream = or_panic!(UnixStream::connect(&socket_path)); | |
1868 | ||
1869 | let result = stream.set_write_timeout(Some(Duration::new(0, 0))); | |
1870 | let err = result.unwrap_err(); | |
1871 | assert_eq!(err.kind(), ErrorKind::InvalidInput); | |
1872 | ||
1873 | let result = stream.set_read_timeout(Some(Duration::new(0, 0))); | |
1874 | let err = result.unwrap_err(); | |
1875 | assert_eq!(err.kind(), ErrorKind::InvalidInput); | |
1876 | ||
1877 | drop(listener); | |
1878 | } | |
1879 | ||
54a0048b SL |
1880 | #[test] |
1881 | fn test_unix_datagram() { | |
1882 | let dir = tmpdir(); | |
1883 | let path1 = dir.path().join("sock1"); | |
1884 | let path2 = dir.path().join("sock2"); | |
1885 | ||
1886 | let sock1 = or_panic!(UnixDatagram::bind(&path1)); | |
1887 | let sock2 = or_panic!(UnixDatagram::bind(&path2)); | |
1888 | ||
1889 | let msg = b"hello world"; | |
1890 | or_panic!(sock1.send_to(msg, &path2)); | |
1891 | let mut buf = [0; 11]; | |
1892 | or_panic!(sock2.recv_from(&mut buf)); | |
1893 | assert_eq!(msg, &buf[..]); | |
1894 | } | |
1895 | ||
1896 | #[test] | |
1897 | fn test_unnamed_unix_datagram() { | |
1898 | let dir = tmpdir(); | |
1899 | let path1 = dir.path().join("sock1"); | |
1900 | ||
1901 | let sock1 = or_panic!(UnixDatagram::bind(&path1)); | |
1902 | let sock2 = or_panic!(UnixDatagram::unbound()); | |
1903 | ||
1904 | let msg = b"hello world"; | |
1905 | or_panic!(sock2.send_to(msg, &path1)); | |
1906 | let mut buf = [0; 11]; | |
1907 | let (usize, addr) = or_panic!(sock1.recv_from(&mut buf)); | |
1908 | assert_eq!(usize, 11); | |
1909 | assert!(addr.is_unnamed()); | |
1910 | assert_eq!(msg, &buf[..]); | |
1911 | } | |
1912 | ||
1913 | #[test] | |
1914 | fn test_connect_unix_datagram() { | |
1915 | let dir = tmpdir(); | |
1916 | let path1 = dir.path().join("sock1"); | |
1917 | let path2 = dir.path().join("sock2"); | |
1918 | ||
1919 | let bsock1 = or_panic!(UnixDatagram::bind(&path1)); | |
1920 | let bsock2 = or_panic!(UnixDatagram::bind(&path2)); | |
1921 | let sock = or_panic!(UnixDatagram::unbound()); | |
1922 | or_panic!(sock.connect(&path1)); | |
1923 | ||
1924 | // Check send() | |
1925 | let msg = b"hello there"; | |
1926 | or_panic!(sock.send(msg)); | |
1927 | let mut buf = [0; 11]; | |
1928 | let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf)); | |
1929 | assert_eq!(usize, 11); | |
1930 | assert!(addr.is_unnamed()); | |
1931 | assert_eq!(msg, &buf[..]); | |
1932 | ||
1933 | // Changing default socket works too | |
1934 | or_panic!(sock.connect(&path2)); | |
1935 | or_panic!(sock.send(msg)); | |
1936 | or_panic!(bsock2.recv_from(&mut buf)); | |
1937 | } | |
1938 | ||
1939 | #[test] | |
1940 | fn test_unix_datagram_recv() { | |
1941 | let dir = tmpdir(); | |
1942 | let path1 = dir.path().join("sock1"); | |
1943 | ||
1944 | let sock1 = or_panic!(UnixDatagram::bind(&path1)); | |
1945 | let sock2 = or_panic!(UnixDatagram::unbound()); | |
1946 | or_panic!(sock2.connect(&path1)); | |
1947 | ||
1948 | let msg = b"hello world"; | |
1949 | or_panic!(sock2.send(msg)); | |
1950 | let mut buf = [0; 11]; | |
1951 | let size = or_panic!(sock1.recv(&mut buf)); | |
1952 | assert_eq!(size, 11); | |
1953 | assert_eq!(msg, &buf[..]); | |
1954 | } | |
1955 | ||
1956 | #[test] | |
1957 | fn datagram_pair() { | |
1958 | let msg1 = b"hello"; | |
1959 | let msg2 = b"world!"; | |
1960 | ||
1961 | let (s1, s2) = or_panic!(UnixDatagram::pair()); | |
1962 | let thread = thread::spawn(move || { | |
1963 | // s1 must be moved in or the test will hang! | |
1964 | let mut buf = [0; 5]; | |
1965 | or_panic!(s1.recv(&mut buf)); | |
1966 | assert_eq!(&msg1[..], &buf[..]); | |
1967 | or_panic!(s1.send(msg2)); | |
1968 | }); | |
1969 | ||
1970 | or_panic!(s2.send(msg1)); | |
1971 | let mut buf = [0; 6]; | |
1972 | or_panic!(s2.recv(&mut buf)); | |
1973 | assert_eq!(&msg2[..], &buf[..]); | |
1974 | drop(s2); | |
1975 | ||
1976 | thread.join().unwrap(); | |
1977 | } | |
1978 | ||
0531ce1d XL |
1979 | // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors |
1980 | // when passed zero Durations | |
1981 | #[test] | |
1982 | fn test_unix_datagram_timeout_zero_duration() { | |
1983 | let dir = tmpdir(); | |
1984 | let path = dir.path().join("sock"); | |
1985 | ||
1986 | let datagram = or_panic!(UnixDatagram::bind(&path)); | |
1987 | ||
1988 | let result = datagram.set_write_timeout(Some(Duration::new(0, 0))); | |
1989 | let err = result.unwrap_err(); | |
1990 | assert_eq!(err.kind(), ErrorKind::InvalidInput); | |
1991 | ||
1992 | let result = datagram.set_read_timeout(Some(Duration::new(0, 0))); | |
1993 | let err = result.unwrap_err(); | |
1994 | assert_eq!(err.kind(), ErrorKind::InvalidInput); | |
1995 | } | |
1996 | ||
54a0048b SL |
1997 | #[test] |
1998 | fn abstract_namespace_not_allowed() { | |
1999 | assert!(UnixStream::connect("\0asdf").is_err()); | |
2000 | } | |
2001 | } |