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