Skip to main content

base_endpoint/tls/
rustls.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4//! Rustls client/server providers over Base scheduler stream sockets. Enable the `rustls` feature, supply an `Arc<ClientConfig>` or `Arc<ServerConfig>`, and compose the provider with the generic TLS endpoint adapters.
5//!
6//! Rustls connections take the scheduler explicitly for each operation. `write` reports plaintext accepted into buffering; call `flush` to send the final buffered output. Reads also drive pending TLS control output. `shutdown` sends `close_notify` while leaving reads available; `close` attempts shutdown and always closes the transport, even after cancellation. `abort` closes without a TLS notification. Await cancelled operations before closure. Partial ciphertext output is retained for a later flush, so accepted plaintext must not be replayed. Missing peer `close_notify` is reported as `UnexpectedEof` after buffered plaintext is consumed. `TlsStream` retains the sequential interface. No runtime or background task is created.
7//!
8//! `RustlsConnection::with_duplex` runs an application with independent plaintext reader and writer handles over one TLS connection while explicitly driving network input/output over persistent scheduler capabilities. The writer directly polls one retained transmitter future; successful writes need no supervisor handoff. A stable socket waker reaches both foreground and supervised pollers when output blocks. The writer handle carries the scheduler lifetime, while the codec and body types remain unchanged. Application reads drive the retained receiver until authenticated plaintext is available; input does not read ahead while plaintext awaits consumption. Control output and directional cleanup remain supervised. Incoming TLS control records are processed when the application reads. No lock spans an asynchronous wait, and no task is spawned. Await its completion to join lane retirement and socket closure.
9
10mod rustls_acceptor;
11mod rustls_connection;
12mod rustls_connector;
13
14pub use rustls_acceptor::RustlsAcceptor;
15pub use rustls_connection::{
16    EncryptedSocketStreamReader, EncryptedSocketStreamWriter, RustlsConnection,
17};
18pub use rustls_connector::RustlsConnector;
19
20use base_scheduler::{
21    Cancellation, OperationResult, SocketClose, SocketStreamReading, SocketStreamWriting,
22};
23use std::io;
24
25fn tls_error(error: ::rustls::Error) -> io::Error {
26    io::Error::new(io::ErrorKind::InvalidData, error)
27}
28
29async fn establish<S>(
30    scheduler: &S,
31    socket: S::Socket,
32    state: OperationResult<::rustls::Connection>,
33    cancellation: &Cancellation,
34) -> OperationResult<RustlsConnection<S::Socket>>
35where
36    S: SocketStreamReading + SocketStreamWriting + SocketClose + ?Sized,
37    S::Socket: 'static,
38{
39    let state = match state {
40        Ok(state) => state,
41        Err(error) => {
42            let _ = scheduler.socket_close(socket).await;
43            return Err(error);
44        }
45    };
46    let mut connection = RustlsConnection::new(socket, state);
47    match connection.handshake(scheduler, cancellation).await {
48        Ok(()) => Ok(connection),
49        Err(error) => {
50            let _ = connection.abort(scheduler).await;
51            Err(error)
52        }
53    }
54}