mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-29 06:06:14 -08:00
Add examples and docstring improvements for mio/uds_recv_fd (#551)
This commit is contained in:
@@ -22,7 +22,7 @@ pub mod io;
|
||||
pub mod length_prefix_encoding;
|
||||
/// Memory manipulation and allocation utilities.
|
||||
pub mod mem;
|
||||
/// MIO integration utilities.
|
||||
/// [MIO (Metal I/O)](https://docs.rs/crate/mio/) integration utilities.
|
||||
pub mod mio;
|
||||
/// Extended Option type functionality.
|
||||
pub mod option;
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
result::OkExt,
|
||||
};
|
||||
|
||||
/// Module containing I/O interest flags for Unix operations
|
||||
/// Module containing I/O interest flags for Unix operations (see also: [mio::Interest])
|
||||
pub mod interest {
|
||||
use mio::Interest;
|
||||
|
||||
@@ -20,9 +20,48 @@ pub mod interest {
|
||||
pub const RW: Interest = R.add(W);
|
||||
}
|
||||
|
||||
/// Extension trait providing additional functionality for Unix listener
|
||||
/// Extension trait providing additional functionality for a Unix listener
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use mio::net::{UnixListener, UnixStream};
|
||||
/// use rosenpass_util::mio::{UnixListenerExt, UnixStreamExt};
|
||||
///
|
||||
/// use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// // This would be the UDS created by an external source
|
||||
/// let socket_path = "/tmp/rp_mio_uds_test_socket";
|
||||
/// if Path::new(socket_path).exists() {
|
||||
/// std::fs::remove_file(socket_path).expect("Failed to remove existing socket");
|
||||
/// }
|
||||
///
|
||||
/// // An extended MIO listener can then be created by claiming the existing socket
|
||||
/// // Note that the original descriptor is not reused, but copied before claiming it here
|
||||
/// let listener = UnixListener::bind(socket_path).unwrap();
|
||||
/// let listener_fd: RawFd = listener.as_raw_fd();
|
||||
/// let ext_listener = <UnixListener as UnixListenerExt>
|
||||
/// ::claim_fd(listener_fd).expect("Failed to claim_fd for ext_listener socket");
|
||||
///
|
||||
/// // Similarly, "client" connections can be established by claiming existing sockets
|
||||
/// // Note that in this case, the file descriptor will be reused (safety implications!)
|
||||
/// let stream = UnixStream::connect(socket_path).unwrap();
|
||||
/// let stream_fd = stream.into_raw_fd();
|
||||
/// let ext_stream = <UnixStream as UnixStreamExt>
|
||||
/// ::claim_fd_inplace(stream_fd).expect("Failed to claim_fd_inplace for ext_stream socket");
|
||||
///
|
||||
/// // Handle accepted connections...
|
||||
/// ext_listener.accept().expect("Failed to accept incoming connection");
|
||||
///
|
||||
/// // Send or receive messages ...
|
||||
///
|
||||
/// // Cleanup, shutdown etc. goes here ...
|
||||
/// std::fs::remove_file(socket_path).unwrap();
|
||||
/// ```
|
||||
pub trait UnixListenerExt: Sized {
|
||||
/// Creates a new Unix listener by claiming ownership of a raw file descriptor
|
||||
/// (see [fd::claim_fd](crate::fd::claim_fd))
|
||||
fn claim_fd(fd: RawFd) -> anyhow::Result<Self>;
|
||||
}
|
||||
|
||||
@@ -36,15 +75,17 @@ impl UnixListenerExt for UnixListener {
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait providing additional functionality for Unix streams
|
||||
/// Extension trait providing additional functionality for a Unix stream
|
||||
pub trait UnixStreamExt: Sized {
|
||||
/// Creates a new Unix stream from an owned file descriptor
|
||||
fn from_fd(fd: OwnedFd) -> anyhow::Result<Self>;
|
||||
|
||||
/// Claims ownership of a raw file descriptor and creates a new Unix stream
|
||||
/// (see [fd::claim_fd](crate::fd::claim_fd))
|
||||
fn claim_fd(fd: RawFd) -> anyhow::Result<Self>;
|
||||
|
||||
/// Claims ownership of a raw file descriptor in place and creates a new Unix stream
|
||||
/// (see [fd::claim_fd_inplace](crate::fd::claim_fd_inplace))
|
||||
fn claim_fd_inplace(fd: RawFd) -> anyhow::Result<Self>;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,58 @@ use crate::fd::{claim_fd_inplace, IntoStdioErr};
|
||||
/// A wrapper around a socket that combines reading from the socket with tracking
|
||||
/// received file descriptors. Limits the maximum number of file descriptors that
|
||||
/// can be received in a single read operation via the `MAX_FDS` parameter.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::collections::VecDeque;
|
||||
/// use std::io::Cursor;
|
||||
/// use std::io::Read;
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// use std::os::fd::OwnedFd;
|
||||
///
|
||||
/// use mio::net::UnixStream;
|
||||
/// use rosenpass_util::mio::ReadWithFileDescriptors;
|
||||
/// use rosenpass_util::io::TryIoResultKindHintExt;
|
||||
///
|
||||
/// const MAX_REQUEST_FDS : usize = 2; // Limit to 2 descriptors per read operation
|
||||
/// let mut read_fd_buffer = VecDeque::<OwnedFd>::new(); // File descriptor queue
|
||||
///
|
||||
/// // In this case, the unused writable end of the connection can be ignored
|
||||
/// let (io_stream, _) = UnixStream::pair().expect("failed to create socket pair");
|
||||
///
|
||||
/// // Wait until the output stream is writable...
|
||||
///
|
||||
/// // Wrap the socket to start tracking received file descriptors
|
||||
/// let mut fd_passing_sock = ReadWithFileDescriptors::<MAX_REQUEST_FDS, UnixStream, _, _>::new(
|
||||
/// &io_stream,
|
||||
/// &mut read_fd_buffer,
|
||||
/// );
|
||||
////
|
||||
/// // Simulated reads; the actual operations will depend on the protocol (implementation details)
|
||||
/// let mut recv_buffer = Vec::<u8>::new();
|
||||
/// let bytes_read = fd_passing_sock.read(&mut recv_buffer[..]).expect("error reading from socket");
|
||||
/// assert_eq!(bytes_read, 0);
|
||||
/// assert_eq!(&recv_buffer[..bytes_read], []);
|
||||
///
|
||||
/// // Alternatively, it's possible to use the try_io_err_kind_hint utility provided by this crate
|
||||
/// match fd_passing_sock.read(&mut recv_buffer).try_io_err_kind_hint() {
|
||||
/// Err(_) => {
|
||||
/// // Handle errors here ...
|
||||
/// }
|
||||
/// Ok(result) => {
|
||||
/// // Process messages here ...
|
||||
/// assert_eq!(0, result); // Nothing to read in this example
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// // The wrapped components can still be accessed
|
||||
/// assert_eq!(fd_passing_sock.socket().as_raw_fd(), io_stream.as_raw_fd());
|
||||
/// let (socket, fd_queue) = fd_passing_sock.into_parts();
|
||||
/// assert_eq!(socket.as_raw_fd(), io_stream.as_raw_fd());
|
||||
///
|
||||
/// // Shutdown, cleanup, etc. goes here ...
|
||||
/// ```
|
||||
pub struct ReadWithFileDescriptors<const MAX_FDS: usize, Sock, BorrowSock, BorrowFds>
|
||||
where
|
||||
Sock: FdPassingExt,
|
||||
|
||||
Reference in New Issue
Block a user