std/os/unix/net/datagram.rs
1#[cfg(any(
2 target_os = "linux",
3 target_os = "android",
4 target_os = "dragonfly",
5 target_os = "freebsd",
6 target_os = "openbsd",
7 target_os = "netbsd",
8 target_os = "solaris",
9 target_os = "illumos",
10 target_os = "haiku",
11 target_os = "nto",
12 target_os = "qnx",
13 target_os = "cygwin"
14))]
15use libc::MSG_NOSIGNAL;
16
17use super::{SocketAddr, sockaddr_un};
18#[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "cygwin"))]
19use super::{SocketAncillary, recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to};
20#[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "cygwin"))]
21use crate::io::{IoSlice, IoSliceMut};
22use crate::macros::rustdoc_skip_body;
23use crate::net::Shutdown;
24use crate::os::unix::io::{
25 AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd, unsafe_impl_fd_asrefs,
26};
27use crate::path::Path;
28use crate::sys::net::Socket;
29use crate::sys::{AsInner, FromInner, IntoInner, cvt};
30use crate::time::Duration;
31use crate::{fmt, io};
32#[cfg(not(any(
33 target_os = "linux",
34 target_os = "android",
35 target_os = "dragonfly",
36 target_os = "freebsd",
37 target_os = "openbsd",
38 target_os = "netbsd",
39 target_os = "solaris",
40 target_os = "illumos",
41 target_os = "haiku",
42 target_os = "nto",
43 target_os = "qnx",
44 target_os = "cygwin"
45)))]
46const MSG_NOSIGNAL: core::ffi::c_int = 0x0;
47
48/// A Unix datagram socket.
49///
50/// # Examples
51///
52#[cfg_attr(target_family = "unix", doc = "```no_run")]
53#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
54/// use std::os::unix::net::UnixDatagram;
55///
56/// fn main() -> std::io::Result<()> {
57/// let socket = UnixDatagram::bind("/path/to/my/socket")?;
58/// socket.send_to(b"hello world", "/path/to/other/socket")?;
59/// let mut buf = [0; 100];
60/// let (count, address) = socket.recv_from(&mut buf)?;
61/// println!("socket {:?} sent {:?}", address, &buf[..count]);
62/// Ok(())
63/// }
64/// ```
65#[stable(feature = "unix_socket", since = "1.10.0")]
66pub struct UnixDatagram(Socket);
67
68#[stable(feature = "unix_socket", since = "1.10.0")]
69impl fmt::Debug for UnixDatagram {
70 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
71 let mut builder = fmt.debug_struct("UnixDatagram");
72 builder.field("fd", self.0.as_inner());
73 if let Ok(addr) = self.local_addr() {
74 builder.field("local", &addr);
75 }
76 if let Ok(addr) = self.peer_addr() {
77 builder.field("peer", &addr);
78 }
79 builder.finish()
80 }
81}
82
83impl UnixDatagram {
84 /// Creates a Unix datagram socket bound to the given path.
85 ///
86 /// # Examples
87 ///
88 #[cfg_attr(target_family = "unix", doc = "```no_run")]
89 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
90 /// use std::os::unix::net::UnixDatagram;
91 ///
92 /// let sock = match UnixDatagram::bind("/path/to/the/socket") {
93 /// Ok(sock) => sock,
94 /// Err(e) => {
95 /// println!("Couldn't bind: {e:?}");
96 /// return
97 /// }
98 /// };
99 /// ```
100 #[stable(feature = "unix_socket", since = "1.10.0")]
101 pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
102 unsafe {
103 let socket = UnixDatagram::unbound()?;
104 let (addr, len) = sockaddr_un(path.as_ref())?;
105
106 cvt(libc::bind(socket.as_raw_fd(), (&raw const addr) as *const _, len as _))?;
107
108 Ok(socket)
109 }
110 }
111
112 /// Creates a Unix datagram socket bound to an address.
113 ///
114 /// # Examples
115 ///
116 #[cfg_attr(target_family = "unix", doc = "```no_run")]
117 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
118 /// use std::os::unix::net::{SocketAddr, UnixDatagram};
119 ///
120 /// fn main() -> std::io::Result<()> {
121 /// let addr = SocketAddr::from_pathname("path/to/socket")?;
122 ///
123 /// let sock = match UnixDatagram::bind_addr(&addr) {
124 /// Ok(sock) => sock,
125 /// Err(err) => {
126 /// println!("Couldn't bind: {err:?}");
127 /// return Err(err);
128 /// }
129 /// };
130 /// Ok(())
131 /// }
132 /// ```
133 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
134 pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixDatagram> {
135 unsafe {
136 let socket = UnixDatagram::unbound()?;
137 cvt(libc::bind(
138 socket.as_raw_fd(),
139 (&raw const socket_addr.addr) as *const _,
140 socket_addr.len as _,
141 ))?;
142 Ok(socket)
143 }
144 }
145
146 /// Creates a Unix Datagram socket which is not bound to any address.
147 ///
148 /// # Examples
149 ///
150 #[cfg_attr(target_family = "unix", doc = "```no_run")]
151 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
152 /// use std::os::unix::net::UnixDatagram;
153 ///
154 /// let sock = match UnixDatagram::unbound() {
155 /// Ok(sock) => sock,
156 /// Err(e) => {
157 /// println!("Couldn't unbound: {e:?}");
158 /// return
159 /// }
160 /// };
161 /// ```
162 #[stable(feature = "unix_socket", since = "1.10.0")]
163 pub fn unbound() -> io::Result<UnixDatagram> {
164 let inner = Socket::new(libc::AF_UNIX, libc::SOCK_DGRAM)?;
165 Ok(UnixDatagram(inner))
166 }
167
168 /// Creates an unnamed pair of connected sockets.
169 ///
170 /// Returns two `UnixDatagrams`s which are connected to each other.
171 ///
172 /// # Examples
173 ///
174 #[cfg_attr(target_family = "unix", doc = "```no_run")]
175 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
176 /// use std::os::unix::net::UnixDatagram;
177 ///
178 /// let (sock1, sock2) = match UnixDatagram::pair() {
179 /// Ok((sock1, sock2)) => (sock1, sock2),
180 /// Err(e) => {
181 /// println!("Couldn't unbound: {e:?}");
182 /// return
183 /// }
184 /// };
185 /// ```
186 #[stable(feature = "unix_socket", since = "1.10.0")]
187 pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
188 let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
189 Ok((UnixDatagram(i1), UnixDatagram(i2)))
190 }
191
192 /// Connects the socket to the specified path address.
193 ///
194 /// The [`send`] method may be used to send data to the specified address.
195 /// [`recv`] and [`recv_from`] will only receive data from that address.
196 ///
197 /// [`send`]: UnixDatagram::send
198 /// [`recv`]: UnixDatagram::recv
199 /// [`recv_from`]: UnixDatagram::recv_from
200 ///
201 /// # Examples
202 ///
203 #[cfg_attr(target_family = "unix", doc = "```no_run")]
204 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
205 /// use std::os::unix::net::UnixDatagram;
206 ///
207 /// fn main() -> std::io::Result<()> {
208 /// let sock = UnixDatagram::unbound()?;
209 /// match sock.connect("/path/to/the/socket") {
210 /// Ok(sock) => sock,
211 /// Err(e) => {
212 /// println!("Couldn't connect: {e:?}");
213 /// return Err(e)
214 /// }
215 /// };
216 /// Ok(())
217 /// }
218 /// ```
219 #[stable(feature = "unix_socket", since = "1.10.0")]
220 pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
221 unsafe {
222 let (addr, len) = sockaddr_un(path.as_ref())?;
223
224 cvt(libc::connect(self.as_raw_fd(), (&raw const addr) as *const _, len))?;
225 }
226 Ok(())
227 }
228
229 /// Connects the socket to an address.
230 ///
231 /// # Examples
232 ///
233 #[cfg_attr(target_family = "unix", doc = "```no_run")]
234 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
235 /// use std::os::unix::net::{UnixDatagram};
236 ///
237 /// fn main() -> std::io::Result<()> {
238 /// let bound = UnixDatagram::bind("/path/to/socket")?;
239 /// let addr = bound.local_addr()?;
240 ///
241 /// let sock = UnixDatagram::unbound()?;
242 /// match sock.connect_addr(&addr) {
243 /// Ok(sock) => sock,
244 /// Err(e) => {
245 /// println!("Couldn't connect: {e:?}");
246 /// return Err(e)
247 /// }
248 /// };
249 /// Ok(())
250 /// }
251 /// ```
252 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
253 pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> {
254 unsafe {
255 cvt(libc::connect(
256 self.as_raw_fd(),
257 (&raw const socket_addr.addr) as *const _,
258 socket_addr.len,
259 ))?;
260 }
261 Ok(())
262 }
263
264 /// Creates a new independently owned handle to the underlying socket.
265 ///
266 /// The returned `UnixDatagram` is a reference to the same socket that this
267 /// object references. Both handles can be used to accept incoming
268 /// connections and options set on one side will affect the other.
269 ///
270 /// # Examples
271 ///
272 #[cfg_attr(target_family = "unix", doc = "```no_run")]
273 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
274 /// use std::os::unix::net::UnixDatagram;
275 ///
276 /// fn main() -> std::io::Result<()> {
277 /// let sock = UnixDatagram::bind("/path/to/the/socket")?;
278 /// let sock_copy = sock.try_clone().expect("`UnixDatagram::try_clone` should not fail");
279 /// Ok(())
280 /// }
281 /// ```
282 #[stable(feature = "unix_socket", since = "1.10.0")]
283 pub fn try_clone(&self) -> io::Result<UnixDatagram> {
284 self.0.duplicate().map(UnixDatagram)
285 }
286
287 /// Returns the address of this socket.
288 ///
289 /// # Examples
290 ///
291 #[cfg_attr(target_family = "unix", doc = "```no_run")]
292 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
293 /// use std::os::unix::net::UnixDatagram;
294 ///
295 /// fn main() -> std::io::Result<()> {
296 /// let sock = UnixDatagram::bind("/path/to/the/socket")?;
297 /// let addr = sock.local_addr().expect("`UnixDatagram::local_addr` should not fail");
298 /// Ok(())
299 /// }
300 /// ```
301 #[stable(feature = "unix_socket", since = "1.10.0")]
302 #[rustdoc_skip_body]
303 pub fn local_addr(&self) -> io::Result<SocketAddr> {
304 SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.as_raw_fd(), addr, len) })
305 }
306
307 /// Returns the address of this socket's peer.
308 ///
309 /// The [`connect`] method will connect the socket to a peer.
310 ///
311 /// [`connect`]: UnixDatagram::connect
312 ///
313 /// # Examples
314 ///
315 #[cfg_attr(target_family = "unix", doc = "```no_run")]
316 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
317 /// use std::os::unix::net::UnixDatagram;
318 ///
319 /// fn main() -> std::io::Result<()> {
320 /// let sock = UnixDatagram::unbound()?;
321 /// sock.connect("/path/to/the/socket")?;
322 ///
323 /// let addr = sock.peer_addr().expect("`UnixDatagram::peer_addr` should not fail");
324 /// Ok(())
325 /// }
326 /// ```
327 #[stable(feature = "unix_socket", since = "1.10.0")]
328 #[rustdoc_skip_body]
329 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
330 SocketAddr::new(|addr, len| unsafe { libc::getpeername(self.as_raw_fd(), addr, len) })
331 }
332
333 fn recv_from_flags(
334 &self,
335 buf: &mut [u8],
336 flags: core::ffi::c_int,
337 ) -> io::Result<(usize, SocketAddr)> {
338 let mut count = 0;
339 let addr = SocketAddr::new(|addr, len| unsafe {
340 count = libc::recvfrom(
341 self.as_raw_fd(),
342 buf.as_mut_ptr() as *mut _,
343 buf.len(),
344 flags,
345 addr,
346 len,
347 );
348 if count > 0 {
349 1
350 } else if count == 0 {
351 0
352 } else {
353 -1
354 }
355 })?;
356
357 Ok((count as usize, addr))
358 }
359
360 /// Receives data from the socket.
361 ///
362 /// On success, returns the number of bytes read and the address from
363 /// whence the data came.
364 ///
365 /// # Examples
366 ///
367 #[cfg_attr(target_family = "unix", doc = "```no_run")]
368 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
369 /// use std::os::unix::net::UnixDatagram;
370 ///
371 /// fn main() -> std::io::Result<()> {
372 /// let sock = UnixDatagram::unbound()?;
373 /// let mut buf = vec![0; 10];
374 /// let (size, sender) = sock.recv_from(buf.as_mut_slice())?;
375 /// println!("received {size} bytes from {sender:?}");
376 /// Ok(())
377 /// }
378 /// ```
379 #[stable(feature = "unix_socket", since = "1.10.0")]
380 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
381 self.recv_from_flags(buf, 0)
382 }
383
384 /// Receives data from the socket.
385 ///
386 /// On success, returns the number of bytes read.
387 ///
388 /// # Examples
389 ///
390 #[cfg_attr(target_family = "unix", doc = "```no_run")]
391 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
392 /// use std::os::unix::net::UnixDatagram;
393 ///
394 /// fn main() -> std::io::Result<()> {
395 /// let sock = UnixDatagram::bind("/path/to/the/socket")?;
396 /// let mut buf = vec![0; 10];
397 /// sock.recv(buf.as_mut_slice()).expect("`UnixDatagram::recv` should not fail");
398 /// Ok(())
399 /// }
400 /// ```
401 #[stable(feature = "unix_socket", since = "1.10.0")]
402 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
403 self.0.read(buf)
404 }
405
406 /// Receives data and ancillary data from socket.
407 ///
408 /// On success, returns the number of bytes read, if the data was truncated and the address from whence the msg came.
409 ///
410 /// # Examples
411 ///
412 #[cfg_attr(
413 any(target_os = "android", target_os = "linux", target_os = "cygwin"),
414 doc = "```no_run"
415 )]
416 #[cfg_attr(
417 not(any(target_os = "android", target_os = "linux", target_os = "cygwin")),
418 doc = "```ignore"
419 )]
420 /// #![feature(unix_socket_ancillary_data)]
421 /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
422 /// use std::io::IoSliceMut;
423 ///
424 /// fn main() -> std::io::Result<()> {
425 /// let sock = UnixDatagram::unbound()?;
426 /// let mut buf1 = [1; 8];
427 /// let mut buf2 = [2; 16];
428 /// let mut buf3 = [3; 8];
429 /// let mut bufs = &mut [
430 /// IoSliceMut::new(&mut buf1),
431 /// IoSliceMut::new(&mut buf2),
432 /// IoSliceMut::new(&mut buf3),
433 /// ][..];
434 /// let mut fds = [0; 8];
435 /// let mut ancillary_buffer = [0; 128];
436 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
437 /// let (size, _truncated, sender) = sock.recv_vectored_with_ancillary_from(bufs, &mut ancillary)?;
438 /// println!("received {size}");
439 /// for ancillary_result in ancillary.messages() {
440 /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
441 /// for fd in scm_rights {
442 /// println!("receive file descriptor: {fd}");
443 /// }
444 /// }
445 /// }
446 /// Ok(())
447 /// }
448 /// ```
449 #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "cygwin"))]
450 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
451 pub fn recv_vectored_with_ancillary_from(
452 &self,
453 bufs: &mut [IoSliceMut<'_>],
454 ancillary: &mut SocketAncillary<'_>,
455 ) -> io::Result<(usize, bool, SocketAddr)> {
456 let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?;
457 let addr = addr?;
458
459 Ok((count, truncated, addr))
460 }
461
462 /// Receives data and ancillary data from socket.
463 ///
464 /// On success, returns the number of bytes read and if the data was truncated.
465 ///
466 /// # Examples
467 ///
468 #[cfg_attr(
469 any(target_os = "android", target_os = "linux", target_os = "cygwin"),
470 doc = "```no_run"
471 )]
472 #[cfg_attr(
473 not(any(target_os = "android", target_os = "linux", target_os = "cygwin")),
474 doc = "```ignore"
475 )]
476 /// #![feature(unix_socket_ancillary_data)]
477 /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
478 /// use std::io::IoSliceMut;
479 ///
480 /// fn main() -> std::io::Result<()> {
481 /// let sock = UnixDatagram::unbound()?;
482 /// let mut buf1 = [1; 8];
483 /// let mut buf2 = [2; 16];
484 /// let mut buf3 = [3; 8];
485 /// let mut bufs = &mut [
486 /// IoSliceMut::new(&mut buf1),
487 /// IoSliceMut::new(&mut buf2),
488 /// IoSliceMut::new(&mut buf3),
489 /// ][..];
490 /// let mut fds = [0; 8];
491 /// let mut ancillary_buffer = [0; 128];
492 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
493 /// let (size, _truncated) = sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
494 /// println!("received {size}");
495 /// for ancillary_result in ancillary.messages() {
496 /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
497 /// for fd in scm_rights {
498 /// println!("receive file descriptor: {fd}");
499 /// }
500 /// }
501 /// }
502 /// Ok(())
503 /// }
504 /// ```
505 #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "cygwin"))]
506 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
507 pub fn recv_vectored_with_ancillary(
508 &self,
509 bufs: &mut [IoSliceMut<'_>],
510 ancillary: &mut SocketAncillary<'_>,
511 ) -> io::Result<(usize, bool)> {
512 let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?;
513 addr?;
514
515 Ok((count, truncated))
516 }
517
518 /// Sends data on the socket to the specified address.
519 ///
520 /// On success, returns the number of bytes written.
521 ///
522 /// # Examples
523 ///
524 #[cfg_attr(target_family = "unix", doc = "```no_run")]
525 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
526 /// use std::os::unix::net::UnixDatagram;
527 ///
528 /// fn main() -> std::io::Result<()> {
529 /// let sock = UnixDatagram::unbound()?;
530 /// sock.send_to(b"omelette au fromage", "/some/sock").expect("`UnixDatagram::send_to` should not fail");
531 /// Ok(())
532 /// }
533 /// ```
534 #[stable(feature = "unix_socket", since = "1.10.0")]
535 pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
536 unsafe {
537 let (addr, len) = sockaddr_un(path.as_ref())?;
538
539 let count = cvt(libc::sendto(
540 self.as_raw_fd(),
541 buf.as_ptr() as *const _,
542 buf.len(),
543 MSG_NOSIGNAL,
544 (&raw const addr) as *const _,
545 len,
546 ))?;
547 Ok(count as usize)
548 }
549 }
550
551 /// Sends data on the socket to the specified [SocketAddr].
552 ///
553 /// On success, returns the number of bytes written.
554 ///
555 /// [SocketAddr]: crate::os::unix::net::SocketAddr
556 ///
557 /// # Examples
558 ///
559 #[cfg_attr(target_family = "unix", doc = "```no_run")]
560 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
561 /// use std::os::unix::net::{UnixDatagram};
562 ///
563 /// fn main() -> std::io::Result<()> {
564 /// let bound = UnixDatagram::bind("/path/to/socket")?;
565 /// let addr = bound.local_addr()?;
566 ///
567 /// let sock = UnixDatagram::unbound()?;
568 /// sock.send_to_addr(b"bacon egg and cheese", &addr).expect("`UnixDatagram::send_to_addr` should not fail");
569 /// Ok(())
570 /// }
571 /// ```
572 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
573 pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result<usize> {
574 unsafe {
575 let count = cvt(libc::sendto(
576 self.as_raw_fd(),
577 buf.as_ptr() as *const _,
578 buf.len(),
579 MSG_NOSIGNAL,
580 (&raw const socket_addr.addr) as *const _,
581 socket_addr.len,
582 ))?;
583 Ok(count as usize)
584 }
585 }
586
587 /// Sends data on the socket to the socket's peer.
588 ///
589 /// The peer address may be set by the `connect` method, and this method
590 /// will return an error if the socket has not already been connected.
591 ///
592 /// On success, returns the number of bytes written.
593 ///
594 /// # Examples
595 ///
596 #[cfg_attr(target_family = "unix", doc = "```no_run")]
597 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
598 /// use std::os::unix::net::UnixDatagram;
599 ///
600 /// fn main() -> std::io::Result<()> {
601 /// let sock = UnixDatagram::unbound()?;
602 /// sock.connect("/some/sock").expect("`UnixDatagram::connect` should not fail");
603 /// sock.send(b"omelette au fromage").expect("`UnixDatagram` is not connected");
604 /// Ok(())
605 /// }
606 /// ```
607 #[stable(feature = "unix_socket", since = "1.10.0")]
608 #[rustdoc_skip_body]
609 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
610 self.0.write(buf)
611 }
612
613 /// Sends data and ancillary data on the socket to the specified address.
614 ///
615 /// On success, returns the number of bytes written.
616 ///
617 /// # Examples
618 ///
619 #[cfg_attr(
620 any(target_os = "android", target_os = "linux", target_os = "cygwin"),
621 doc = "```no_run"
622 )]
623 #[cfg_attr(
624 not(any(target_os = "android", target_os = "linux", target_os = "cygwin")),
625 doc = "```ignore"
626 )]
627 /// #![feature(unix_socket_ancillary_data)]
628 /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
629 /// use std::io::IoSlice;
630 ///
631 /// fn main() -> std::io::Result<()> {
632 /// let sock = UnixDatagram::unbound()?;
633 /// let buf1 = [1; 8];
634 /// let buf2 = [2; 16];
635 /// let buf3 = [3; 8];
636 /// let bufs = &[
637 /// IoSlice::new(&buf1),
638 /// IoSlice::new(&buf2),
639 /// IoSlice::new(&buf3),
640 /// ][..];
641 /// let fds = [0, 1, 2];
642 /// let mut ancillary_buffer = [0; 128];
643 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
644 /// ancillary.add_fds(&fds[..]);
645 /// sock.send_vectored_with_ancillary_to(bufs, &mut ancillary, "/some/sock")
646 /// .expect("`UnixDatagram::send_vectored_with_ancillary_to` should not fail");
647 /// Ok(())
648 /// }
649 /// ```
650 #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "cygwin"))]
651 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
652 pub fn send_vectored_with_ancillary_to<P: AsRef<Path>>(
653 &self,
654 bufs: &[IoSlice<'_>],
655 ancillary: &mut SocketAncillary<'_>,
656 path: P,
657 ) -> io::Result<usize> {
658 send_vectored_with_ancillary_to(&self.0, Some(path.as_ref()), bufs, ancillary)
659 }
660
661 /// Sends data and ancillary data on the socket.
662 ///
663 /// On success, returns the number of bytes written.
664 ///
665 /// # Examples
666 ///
667 #[cfg_attr(
668 any(target_os = "android", target_os = "linux", target_os = "cygwin"),
669 doc = "```no_run"
670 )]
671 #[cfg_attr(
672 not(any(target_os = "android", target_os = "linux", target_os = "cygwin")),
673 doc = "```ignore"
674 )]
675 /// #![feature(unix_socket_ancillary_data)]
676 /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
677 /// use std::io::IoSlice;
678 ///
679 /// fn main() -> std::io::Result<()> {
680 /// let sock = UnixDatagram::unbound()?;
681 /// let buf1 = [1; 8];
682 /// let buf2 = [2; 16];
683 /// let buf3 = [3; 8];
684 /// let bufs = &[
685 /// IoSlice::new(&buf1),
686 /// IoSlice::new(&buf2),
687 /// IoSlice::new(&buf3),
688 /// ][..];
689 /// let fds = [0, 1, 2];
690 /// let mut ancillary_buffer = [0; 128];
691 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
692 /// ancillary.add_fds(&fds[..]);
693 /// sock.send_vectored_with_ancillary(bufs, &mut ancillary)
694 /// .expect("`UnixDatagram::send_vectored_with_ancillary` should not fail");
695 /// Ok(())
696 /// }
697 /// ```
698 #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "cygwin"))]
699 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
700 pub fn send_vectored_with_ancillary(
701 &self,
702 bufs: &[IoSlice<'_>],
703 ancillary: &mut SocketAncillary<'_>,
704 ) -> io::Result<usize> {
705 send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary)
706 }
707
708 /// Sets the read timeout for the socket.
709 ///
710 /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
711 /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
712 /// is passed to this method.
713 ///
714 /// [`recv`]: UnixDatagram::recv
715 /// [`recv_from`]: UnixDatagram::recv_from
716 ///
717 /// # Examples
718 ///
719 #[cfg_attr(target_family = "unix", doc = "```")]
720 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
721 /// use std::os::unix::net::UnixDatagram;
722 /// use std::time::Duration;
723 ///
724 /// fn main() -> std::io::Result<()> {
725 /// let sock = UnixDatagram::unbound()?;
726 /// sock.set_read_timeout(Some(Duration::new(1, 0)))
727 /// .expect("`UnixDatagram::set_read_timeout` should not fail");
728 /// Ok(())
729 /// }
730 /// ```
731 ///
732 /// An [`Err`] is returned if the zero [`Duration`] is passed to this
733 /// method:
734 ///
735 #[cfg_attr(target_family = "unix", doc = "```no_run")]
736 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
737 /// use std::io;
738 /// use std::os::unix::net::UnixDatagram;
739 /// use std::time::Duration;
740 ///
741 /// fn main() -> std::io::Result<()> {
742 /// let socket = UnixDatagram::unbound()?;
743 /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
744 /// let err = result.unwrap_err();
745 /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
746 /// Ok(())
747 /// }
748 /// ```
749 #[stable(feature = "unix_socket", since = "1.10.0")]
750 #[rustdoc_skip_body]
751 pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
752 self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
753 }
754
755 /// Sets the write timeout for the socket.
756 ///
757 /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
758 /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
759 /// method.
760 ///
761 /// [`send`]: UnixDatagram::send
762 /// [`send_to`]: UnixDatagram::send_to
763 ///
764 /// # Examples
765 ///
766 #[cfg_attr(target_family = "unix", doc = "```")]
767 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
768 /// use std::os::unix::net::UnixDatagram;
769 /// use std::time::Duration;
770 ///
771 /// fn main() -> std::io::Result<()> {
772 /// let sock = UnixDatagram::unbound()?;
773 /// sock.set_write_timeout(Some(Duration::new(1, 0)))
774 /// .expect("`UnixDatagram::set_write_timeout` should not fail");
775 /// Ok(())
776 /// }
777 /// ```
778 ///
779 /// An [`Err`] is returned if the zero [`Duration`] is passed to this
780 /// method:
781 ///
782 #[cfg_attr(target_family = "unix", doc = "```no_run")]
783 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
784 /// use std::io;
785 /// use std::os::unix::net::UnixDatagram;
786 /// use std::time::Duration;
787 ///
788 /// fn main() -> std::io::Result<()> {
789 /// let socket = UnixDatagram::unbound()?;
790 /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
791 /// let err = result.unwrap_err();
792 /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
793 /// Ok(())
794 /// }
795 /// ```
796 #[stable(feature = "unix_socket", since = "1.10.0")]
797 #[rustdoc_skip_body]
798 pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
799 self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
800 }
801
802 /// Returns the read timeout of this socket.
803 ///
804 /// # Examples
805 ///
806 #[cfg_attr(target_family = "unix", doc = "```")]
807 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
808 /// use std::os::unix::net::UnixDatagram;
809 /// use std::time::Duration;
810 ///
811 /// fn main() -> std::io::Result<()> {
812 /// let sock = UnixDatagram::unbound()?;
813 /// sock.set_read_timeout(Some(Duration::new(1, 0)))
814 /// .expect("`UnixDatagram::set_read_timeout` should not fail");
815 /// assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0)));
816 /// Ok(())
817 /// }
818 /// ```
819 #[stable(feature = "unix_socket", since = "1.10.0")]
820 #[rustdoc_skip_body]
821 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
822 self.0.timeout(libc::SO_RCVTIMEO)
823 }
824
825 /// Returns the write timeout of this socket.
826 ///
827 /// # Examples
828 ///
829 #[cfg_attr(target_family = "unix", doc = "```")]
830 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
831 /// use std::os::unix::net::UnixDatagram;
832 /// use std::time::Duration;
833 ///
834 /// fn main() -> std::io::Result<()> {
835 /// let sock = UnixDatagram::unbound()?;
836 /// sock.set_write_timeout(Some(Duration::new(1, 0)))
837 /// .expect("`UnixDatagram::set_write_timeout` should not fail");
838 /// assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0)));
839 /// Ok(())
840 /// }
841 /// ```
842 #[stable(feature = "unix_socket", since = "1.10.0")]
843 #[rustdoc_skip_body]
844 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
845 self.0.timeout(libc::SO_SNDTIMEO)
846 }
847
848 /// Moves the socket into or out of nonblocking mode.
849 ///
850 /// # Examples
851 ///
852 #[cfg_attr(target_family = "unix", doc = "```")]
853 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
854 /// use std::os::unix::net::UnixDatagram;
855 ///
856 /// fn main() -> std::io::Result<()> {
857 /// let sock = UnixDatagram::unbound()?;
858 /// sock.set_nonblocking(true).expect("`UnixDatagram::set_nonblocking` should not fail");
859 /// Ok(())
860 /// }
861 /// ```
862 #[stable(feature = "unix_socket", since = "1.10.0")]
863 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
864 self.0.set_nonblocking(nonblocking)
865 }
866
867 /// Set the id of the socket for network filtering purpose
868 ///
869 #[cfg_attr(
870 any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"),
871 doc = "```no_run"
872 )]
873 #[cfg_attr(
874 not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")),
875 doc = "```ignore"
876 )]
877 /// #![feature(unix_set_mark)]
878 /// use std::os::unix::net::UnixDatagram;
879 ///
880 /// fn main() -> std::io::Result<()> {
881 /// let sock = UnixDatagram::unbound()?;
882 /// sock.set_mark(32)?;
883 /// Ok(())
884 /// }
885 /// ```
886 #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))]
887 #[unstable(feature = "unix_set_mark", issue = "96467")]
888 #[rustdoc_skip_body]
889 pub fn set_mark(&self, mark: u32) -> io::Result<()> {
890 self.0.set_mark(mark)
891 }
892
893 /// Returns the value of the `SO_ERROR` option.
894 ///
895 /// # Examples
896 ///
897 #[cfg_attr(target_family = "unix", doc = "```no_run")]
898 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
899 /// use std::os::unix::net::UnixDatagram;
900 ///
901 /// fn main() -> std::io::Result<()> {
902 /// let sock = UnixDatagram::unbound()?;
903 /// if let Ok(Some(err)) = sock.take_error() {
904 /// println!("Got error: {err:?}");
905 /// }
906 /// Ok(())
907 /// }
908 /// ```
909 #[stable(feature = "unix_socket", since = "1.10.0")]
910 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
911 self.0.take_error()
912 }
913
914 /// Shut down the read, write, or both halves of this connection.
915 ///
916 /// This function will cause all pending and future I/O calls on the
917 /// specified portions to immediately return with an appropriate value
918 /// (see the documentation of [`Shutdown`]).
919 ///
920 #[cfg_attr(target_family = "unix", doc = "```no_run")]
921 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
922 /// use std::os::unix::net::UnixDatagram;
923 /// use std::net::Shutdown;
924 ///
925 /// fn main() -> std::io::Result<()> {
926 /// let sock = UnixDatagram::unbound()?;
927 /// sock.shutdown(Shutdown::Both).expect("`UnixDatagram::shutdown` should not fail");
928 /// Ok(())
929 /// }
930 /// ```
931 #[stable(feature = "unix_socket", since = "1.10.0")]
932 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
933 self.0.shutdown(how)
934 }
935
936 /// Receives data on the socket from the remote address to which it is
937 /// connected, without removing that data from the queue. On success,
938 /// returns the number of bytes peeked.
939 ///
940 /// Successive calls return the same data. This is accomplished by passing
941 /// `MSG_PEEK` as a flag to the underlying `recv` system call.
942 ///
943 /// # Examples
944 ///
945 #[cfg_attr(target_family = "unix", doc = "```no_run")]
946 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
947 /// #![feature(unix_socket_peek)]
948 ///
949 /// use std::os::unix::net::UnixDatagram;
950 ///
951 /// fn main() -> std::io::Result<()> {
952 /// let socket = UnixDatagram::bind("/tmp/sock")?;
953 /// let mut buf = [0; 10];
954 /// let len = socket.peek(&mut buf).expect("`UnixDatagram::peek` should not fail");
955 /// Ok(())
956 /// }
957 /// ```
958 #[unstable(feature = "unix_socket_peek", issue = "76923")]
959 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
960 self.0.peek(buf)
961 }
962
963 /// Receives a single datagram message on the socket, without removing it from the
964 /// queue. On success, returns the number of bytes read and the origin.
965 ///
966 /// The function must be called with valid byte array `buf` of sufficient size to
967 /// hold the message bytes. If a message is too long to fit in the supplied buffer,
968 /// excess bytes may be discarded.
969 ///
970 /// Successive calls return the same data. This is accomplished by passing
971 /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
972 ///
973 /// Do not use this function to implement busy waiting, instead use `libc::poll` to
974 /// synchronize IO events on one or more sockets.
975 ///
976 /// # Examples
977 ///
978 #[cfg_attr(target_family = "unix", doc = "```no_run")]
979 #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")]
980 /// #![feature(unix_socket_peek)]
981 ///
982 /// use std::os::unix::net::UnixDatagram;
983 ///
984 /// fn main() -> std::io::Result<()> {
985 /// let socket = UnixDatagram::bind("/tmp/sock")?;
986 /// let mut buf = [0; 10];
987 /// let (len, addr) = socket.peek_from(&mut buf).expect("peek failed");
988 /// Ok(())
989 /// }
990 /// ```
991 #[unstable(feature = "unix_socket_peek", issue = "76923")]
992 #[rustdoc_skip_body]
993 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
994 self.recv_from_flags(buf, libc::MSG_PEEK)
995 }
996}
997
998#[stable(feature = "unix_socket", since = "1.10.0")]
999impl AsRawFd for UnixDatagram {
1000 #[inline]
1001 #[rustdoc_skip_body]
1002 fn as_raw_fd(&self) -> RawFd {
1003 self.0.as_inner().as_raw_fd()
1004 }
1005}
1006
1007#[stable(feature = "unix_socket", since = "1.10.0")]
1008impl FromRawFd for UnixDatagram {
1009 #[inline]
1010 #[rustdoc_skip_body]
1011 unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
1012 UnixDatagram(Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))))
1013 }
1014}
1015
1016#[stable(feature = "unix_socket", since = "1.10.0")]
1017impl IntoRawFd for UnixDatagram {
1018 #[inline]
1019 #[rustdoc_skip_body]
1020 fn into_raw_fd(self) -> RawFd {
1021 self.0.into_inner().into_inner().into_raw_fd()
1022 }
1023}
1024
1025#[stable(feature = "io_safety", since = "1.63.0")]
1026impl AsFd for UnixDatagram {
1027 #[inline]
1028 #[rustdoc_skip_body]
1029 fn as_fd(&self) -> BorrowedFd<'_> {
1030 self.0.as_inner().as_fd()
1031 }
1032}
1033
1034// SAFETY: It's a tower of 1-field wrappers around OwnedFd.
1035// No methods to close the socket, no methods with safety preconditions,
1036// other than the fd being valid.
1037unsafe_impl_fd_asrefs!(UnixDatagram);
1038
1039#[stable(feature = "io_safety", since = "1.63.0")]
1040impl From<UnixDatagram> for OwnedFd {
1041 /// Takes ownership of a [`UnixDatagram`]'s socket file descriptor.
1042 #[inline]
1043 fn from(unix_datagram: UnixDatagram) -> OwnedFd {
1044 unsafe { OwnedFd::from_raw_fd(unix_datagram.into_raw_fd()) }
1045 }
1046}
1047
1048#[stable(feature = "io_safety", since = "1.63.0")]
1049impl From<OwnedFd> for UnixDatagram {
1050 #[inline]
1051 fn from(owned: OwnedFd) -> Self {
1052 unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
1053 }
1054}
1055
1056impl AsInner<Socket> for UnixDatagram {
1057 #[inline]
1058 fn as_inner(&self) -> &Socket {
1059 &self.0
1060 }
1061}