1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
//! Unix seqpacket sockets for [tokio](https://docs.rs/tokio). //! //! Seqpacket sockets combine a number of useful properties: //! * They are connection oriented. //! * They guarantee in-order message delivery. //! * They provide datagrams with well-defined semantics for passing along file descriptors. //! //! These properties make seqpacket sockets very well suited for local servers that need to pass file-descriptors around with their clients. //! //! You can create a [`UnixSeqpacketListener`] to start accepting connections, //! or create a [`UnixSeqpacket`] to connect to a listening socket. //! You can also create a pair of connected sockets with [`UnixSeqpacket::pair()`]. //! //! # Passing file descriptors and other ancillary data. //! //! You can use [`send_vectored_with_ancillary`][UnixSeqpacket::send_vectored_with_ancillary] and [`recv_vectored_with_ancillary`][UnixSeqpacket::recv_vectored_with_ancillary] //! to send and receive ancillary data. //! This can be used to pass file descriptors and unix credentials over sockets. //! //! # `&self` versus `&mut self` //! //! Seqpacket sockets have well-defined semantics when sending or receiving on the same socket from different threads. //! Although the order is not guaranteed in that scenario, each datagram will be delivered intact. //! Since tokio 0.3, it is also possible for multiple tasks to await the same file descriptor. //! As such, all I/O functions now take `&self` instead of `&mut self`, //! and the `split()` API has been deprecated. //! //! # Example //! ```no_run //! # async fn foo() -> Result<(), Box<dyn std::error::Error>> { //! use tokio_seqpacket::UnixSeqpacket; //! //! let mut socket = UnixSeqpacket::connect("/run/foo.sock").await?; //! socket.send(b"Hello!").await?; //! //! let mut buffer = [0u8; 128]; //! let len = socket.recv(&mut buffer).await?; //! println!("{}", String::from_utf8_lossy(&buffer[..len])); //! # Ok(()) //! # } //! ``` #![warn(missing_docs)] macro_rules! ready { ($e:expr) => { match $e { Poll::Pending => return Poll::Pending, Poll::Ready(x) => x, } }; } pub mod ancillary; mod listener; mod socket; mod ucred; pub use listener::UnixSeqpacketListener; pub use socket::UnixSeqpacket; pub use ucred::UCred; #[doc(hidden)] #[deprecated( since = "0.4.0", note = "all I/O functions now take a shared reference to self, so splitting is no longer necessary" )] pub type ReadHalf<'a> = &'a UnixSeqpacket; #[doc(hidden)] #[deprecated( since = "0.4.0", note = "all I/O functions now take a shared reference to self, so splitting is no longer necessary" )] pub type WriteHalf<'a> = &'a UnixSeqpacket; /// Get the socket type for a close-on-exec non-blocking seqpacket socket. fn socket_type() -> socket2::Type { socket2::Type::seqpacket().cloexec().non_blocking() } /// Get the Unix path of a socket address. /// /// An error is retuend if the address is not a Unix address, or if it is an unnamed or abstract. fn address_path(address: &socket2::SockAddr) -> std::io::Result<&std::path::Path> { use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; use std::path::Path; if address.family() != libc::AF_LOCAL as _ { Err(std::io::Error::new(std::io::ErrorKind::InvalidData, format!("address family is not AF_LOCAL/UNIX: {}", address.family()))) } else { let len = address.len() as usize; let address = address.as_ptr() as *const libc::sockaddr_un; let path_start = unsafe { &(*address).sun_path }.as_ptr().cast::<u8>(); let path_len = len - unsafe { path_start.offset_from(address.cast::<u8>()) } as usize; let path = unsafe { std::slice::from_raw_parts(path_start, path_len) }; // Some platforms include a trailing null byte in the path length. let path = if path.last() == Some(&0) { &path[..path.len() - 1] } else { path }; Ok(Path::new(OsStr::from_bytes(path))) } }