safer_ring/lib.rs
1//! # Safer-Ring: Safe `io_uring` for Rust
2//!
3//! A comprehensive, safe Rust wrapper around `io_uring` that provides zero-cost abstractions
4//! while preventing common memory safety issues. The library uses Rust's type system,
5//! lifetime management, and pinning to ensure that buffers remain valid during asynchronous
6//! I/O operations, eliminating use-after-free bugs and data races.
7//!
8//! ## Key Features
9//!
10//! ### Safety Guarantees
11//! - **Memory Safety**: Compile-time guarantees that buffers outlive their operations
12//! - **Type Safety**: State machines prevent operations in invalid states
13//! - **Lifetime Safety**: Automatic enforcement of buffer and operation lifetimes
14//! - **Thread Safety**: Safe sharing of resources across async tasks
15//!
16//! ### Performance Optimizations
17//! - **Zero-Cost Abstractions**: No runtime overhead compared to raw `io_uring`
18//! - **Batch Operations**: Submit multiple operations efficiently with dependency support
19//! - **Buffer Pooling**: Efficient buffer reuse to minimize allocations
20//! - **Advanced Features**: Support for buffer selection, multi-shot operations, and more
21//!
22//! ### Developer Experience
23//! - **Async/Await**: Seamless integration with Rust's async ecosystem
24//! - **Comprehensive Logging**: Structured logging and performance metrics
25//! - **Flexible Configuration**: Optimized presets for different use cases
26//! - **Graceful Degradation**: Automatic fallback for older kernel versions
27//!
28//! ## Quick Start
29//!
30//! ### Recommended: Ownership Transfer API
31//!
32//! ```rust,no_run
33//! use safer_ring::{Ring, OwnedBuffer};
34//!
35//! # #[tokio::main]
36//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
37//! // Create a new ring with 32 entries
38//! let mut ring = Ring::new(32)?;
39//!
40//! // Create a buffer - ownership will be transferred during I/O
41//! let buffer = OwnedBuffer::new(1024);
42//!
43//! // Safe read with ownership transfer ("hot potato" pattern)
44//! let (bytes_read, buffer) = ring.read_owned(0, buffer).await?;
45//! println!("Read {} bytes", bytes_read);
46//!
47//! // Buffer is safely returned and can be reused
48//! let (bytes_written, _buffer) = ring.write_owned(1, buffer).await?;
49//! println!("Wrote {} bytes", bytes_written);
50//!
51//! # Ok(())
52//! # }
53//! ```
54//!
55//! ## A Note on the `PinnedBuffer` API (Educational / Not Recommended)
56//!
57//! You may see a [`PinnedBuffer`] type and methods like [`read()`](Ring::read) or [`write()`](Ring::write) in the codebase.
58//!
59//! **This API is considered educational and is not suitable for practical use.** It suffers from
60//! fundamental lifetime constraints in Rust that make it impossible to use in loops or for
61//! concurrent operations on the same [`Ring`] instance. It exists to demonstrate the complexities
62//! that the [`OwnedBuffer`] model successfully solves. For all applications, please use the
63//! [`OwnedBuffer`] API.
64//!
65//! The example below is provided for completeness but is not a recommended pattern:
66//!
67//! ```rust,ignore
68//! use safer_ring::{Ring, PinnedBuffer};
69//!
70//! # #[tokio::main]
71//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
72//! let mut ring = Ring::new(32)?;
73//! let mut buffer = PinnedBuffer::with_capacity(1024);
74//!
75//! // This pattern works for a single, one-shot operation but fails in loops.
76//! let (bytes_read, buffer) = ring.read(0, buffer.as_mut_slice())?.await?;
77//! println!("Read {} bytes", bytes_read);
78//!
79//! # Ok(())
80//! # }
81//! ```
82//!
83//! ### High-Performance Batch Operations
84//!
85//! For high-throughput applications, submit multiple operations in a single batch:
86//!
87//! ```rust,ignore
88//! use safer_ring::{Ring, Batch, Operation, PinnedBuffer, BatchConfig};
89//!
90//! # #[tokio::main]
91//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
92//! // Note: Batch operations currently require careful lifetime management
93//! // See examples/async_demo.rs for working patterns
94//! let mut ring = Ring::new(128)?;
95//! let mut batch = Batch::new();
96//!
97//! // Prepare multiple buffers
98//! let mut read_buffer = PinnedBuffer::with_capacity(4096);
99//! let mut write_buffer = PinnedBuffer::from_slice(b"Hello, world!");
100//!
101//! // Add operations to the batch
102//! batch.add_operation(Operation::read().fd(0).buffer(read_buffer.as_mut_slice()))?;
103//! batch.add_operation(Operation::write().fd(1).buffer(write_buffer.as_mut_slice()))?;
104//!
105//! // Submit all operations at once
106//! let results = ring.submit_batch(batch)?.await?;
107//! println!("Batch completed: {} operations", results.results.len());
108//!
109//! # Ok(())
110//! # }
111//! ```
112//!
113//! > **Note**: Batch operations are fully implemented but have some API ergonomics
114//! > limitations. See `examples/async_demo.rs` for working usage patterns.
115//!
116//! ### Network Server Example
117//!
118//! ```rust,ignore
119//! use safer_ring::{Ring, PinnedBuffer, BufferPool};
120//! use std::os::unix::io::RawFd;
121//!
122//! # #[tokio::main]
123//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
124//! let ring = Ring::new(256)?;
125//! let buffer_pool = BufferPool::new(100, 4096);
126//! let listening_fd: RawFd = 3; // Assume we have a listening socket
127//!
128//! loop {
129//! // Accept a new connection
130//! let client_fd = ring.accept(listening_fd)?.await?;
131//!
132//! // Get a buffer from the pool
133//! let buffer = buffer_pool.get().unwrap();
134//!
135//! // Read data from the client
136//! let (bytes_read, buffer) = ring.recv(client_fd, buffer.as_mut_slice())?.await?;
137//!
138//! // Echo the data back
139//! let (bytes_written, _buffer) = ring.send(client_fd, buffer.as_mut_slice())?.await?;
140//!
141//! println!("Echoed {} bytes", bytes_written);
142//! // Buffer is automatically returned to pool when dropped
143//! }
144//! # }
145//! ```
146//!
147//! ## Configuration and Optimization
148//!
149//! Safer-ring provides pre-configured setups for different use cases:
150//!
151//! ```rust,no_run
152//! use safer_ring::{Ring, SaferRingConfig};
153//!
154//! # #[tokio::main]
155//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
156//! // Low-latency configuration for real-time applications
157//! let config = SaferRingConfig::low_latency();
158//! let ring = Ring::with_config(config)?;
159//!
160//! // High-throughput configuration for batch processing
161//! let config = SaferRingConfig::high_throughput();
162//! let ring = Ring::with_config(config)?;
163//!
164//! // Auto-detect optimal configuration for current system
165//! let config = SaferRingConfig::auto_detect()?;
166//! let ring = Ring::with_config(config)?;
167//!
168//! # Ok(())
169//! # }
170//! ```
171//!
172//! ## Advanced Features
173//!
174//! ### Buffer Selection and Provided Buffers
175//!
176//! ```rust,no_run
177//! use safer_ring::{Ring, BufferGroup, AdvancedConfig};
178//!
179//! # #[tokio::main]
180//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
181//! // Create a buffer group for kernel buffer selection
182//! let mut buffer_group = BufferGroup::new(1, 64, 4096)?;
183//!
184//! // Configure ring with advanced features
185//! let mut config = AdvancedConfig::default();
186//! config.buffer_selection = true;
187//! config.provided_buffers = true;
188//!
189//! let ring = Ring::with_advanced_config(config)?;
190//! // Use buffer selection for zero-copy reads
191//! # Ok(())
192//! # }
193//! ```
194//!
195//! ### Comprehensive Logging and Metrics
196//!
197//! ```rust,ignore
198//! use safer_ring::{Ring, SaferRingConfig, LogLevel};
199//!
200//! # #[tokio::main]
201//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
202//! // Enable detailed logging and metrics
203//! let mut config = SaferRingConfig::development();
204//! config.logging.enabled = true;
205//! config.logging.level = LogLevel::Debug;
206//! config.logging.metrics = true;
207//!
208//! let mut ring = Ring::with_config(config)?;
209//!
210//! // Operations are automatically logged with timing information
211//! let mut buffer = safer_ring::PinnedBuffer::with_capacity(1024);
212//! let (bytes_read, _) = ring.read(0, buffer.as_mut_slice())?.await?;
213//!
214//! # Ok(())
215//! # }
216//! ```
217//!
218//! ## Platform Support
219//!
220//! - **Linux**: Full `io_uring` support with all advanced features
221//! - **Other platforms**: Graceful degradation with stub implementations for testing
222//!
223//! ## Minimum Kernel Requirements
224//!
225//! - **Basic functionality**: Linux 5.1+
226//! - **Advanced features**: Linux 5.19+ (buffer selection, multi-shot operations)
227//! - **Optimal performance**: Linux 6.0+ (cooperative task running, defer taskrun)
228//!
229//! The library automatically detects available features and gracefully degrades
230//! functionality on older kernels while maintaining API compatibility.
231//!
232//! ## Security Considerations
233//!
234//! ### File Descriptor Responsibility
235//!
236//! **⚠️ CRITICAL SECURITY NOTICE**: This library accepts raw file descriptors (`RawFd`)
237//! from user code and does **NOT** perform any validation, permission checks, or access
238//! control. The application is **entirely responsible** for ensuring file descriptor security.
239//!
240//! ### Security Responsibilities
241//!
242//! **The calling application must ensure that all file descriptors:**
243//! - Are valid and owned by the current process
244//! - Have appropriate permissions for the intended operation (read/write/accept)
245//! - Are not subject to race conditions from concurrent access
246//! - Point to intended resources (files, sockets, devices)
247//! - Have been properly authenticated and authorized
248//! - Are not being used maliciously by untrusted code
249//!
250//! ### Potential Security Risks
251//!
252//! **Using invalid, unauthorized, or malicious file descriptors can result in:**
253//! - Reading from or writing to unintended files, sockets, or devices
254//! - Information disclosure or data corruption
255//! - Privilege escalation or unauthorized system access
256//! - Buffer overflow attacks or memory corruption (from network data)
257//! - Denial of service or system instability
258//!
259//! ### Security Best Practices
260//!
261//! **Always implement these security controls at the application level:**
262//! - Validate file descriptors at security boundaries
263//! - Use proper access control and permission checks
264//! - Implement input validation for all received data
265//! - Consider using sandboxing or privilege isolation
266//! - Apply principle of least privilege for file access
267//! - Use secure network protocols and authentication
268//! - Monitor and log suspicious file descriptor usage
269//!
270//! ### Data Validation
271//!
272//! **For network operations, the application must:**
273//! - Validate all received data before processing
274//! - Implement proper input sanitization and bounds checking
275//! - Use secure parsing for untrusted input data
276//! - Consider data confidentiality and integrity requirements
277//! - Protect against injection attacks and protocol exploitation
278//!
279//! This library provides **memory safety** and **async safety** but does **NOT** provide
280//! **security boundaries** or **access control**. Security must be implemented at the
281//! application layer.
282
283#![deny(unsafe_op_in_unsafe_fn)]
284#![warn(missing_docs, rust_2018_idioms)]
285#![cfg_attr(docsrs, feature(doc_cfg))]
286
287// Core modules - fundamental building blocks for safe io_uring operations
288pub mod backend; // Backend abstraction for io_uring and epoll
289pub mod buffer;
290pub mod error;
291pub mod operation;
292pub mod ownership; // Buffer ownership management for safety
293pub mod ring;
294pub mod runtime; // Runtime detection and fallback system
295pub mod safety; // Cancellation safety and orphaned operation tracking
296
297// Advanced features - performance optimizations and convenience APIs
298pub mod advanced; // Advanced io_uring features (buffer selection, multi-shot, etc.)
299pub mod compat; // AsyncRead/AsyncWrite compatibility adapters
300pub mod config; // Configuration options for different use cases
301pub mod future; // async/await integration
302pub mod logging; // Comprehensive logging and debugging support
303pub mod perf; // Performance profiling and optimization utilities
304pub mod pool; // Buffer pooling for reduced allocations
305pub mod registry; // FD/buffer registration for kernel optimization
306
307// Re-exports for convenience - commonly used types at crate root
308pub use advanced::{AdvancedConfig, BufferGroup, FeatureDetector, MultiShotConfig};
309pub use buffer::PinnedBuffer;
310pub use compat::{AsyncCompat, AsyncReadAdapter, AsyncWriteAdapter, File, Socket}; // Async compatibility
311pub use config::{
312 BufferConfig, ConfigBuilder, ErrorHandlingConfig, LoggingConfig, PerformanceConfig, RingConfig,
313 SaferRingConfig,
314};
315pub use error::{Result, SaferRingError};
316pub use logging::{LogLevel, Logger, PerformanceMetrics};
317pub use operation::{Operation, OperationState};
318pub use ownership::{BufferOwnership, OwnedBuffer, SafeBuffer}; // Core ownership types
319pub use pool::{BufferPool, PooledBuffer};
320pub use registry::{FixedFile, RegisteredBufferSlot, Registry};
321pub use ring::{Batch, BatchConfig, BatchResult, CompletionResult, OperationResult, Ring};
322pub use runtime::{get_environment_info, is_io_uring_available, Backend, EnvironmentInfo, Runtime}; // Runtime system
323pub use safety::{OrphanTracker, SafeOperation, SafeOperationFuture, SubmissionId}; // Cancellation safety
324
325// Type aliases for common patterns - reduces verbosity in user code
326/// Future type for read operations that can be awaited.
327pub type ReadFuture<'ring, 'buf> = future::ReadFuture<'ring, 'buf>;
328/// Future type for write operations that can be awaited.
329pub type WriteFuture<'ring, 'buf> = future::WriteFuture<'ring, 'buf>;
330/// Future type for accept operations that can be awaited.
331pub type AcceptFuture<'ring> = future::AcceptFuture<'ring>;
332/// Future type for send operations that can be awaited.
333pub type SendFuture<'ring, 'buf> = future::SendFuture<'ring, 'buf>;
334/// Future type for receive operations that can be awaited.
335pub type RecvFuture<'ring, 'buf> = future::RecvFuture<'ring, 'buf>;
336/// Future type for batch operations that can be awaited.
337pub type BatchFuture<'ring> = future::BatchFuture<'ring>;
338/// Standalone future type for batch operations that doesn't hold Ring references.
339pub type StandaloneBatchFuture = future::StandaloneBatchFuture;