Skip to main content

base_endpoint/tls/
tls_stream.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use super::TlsSession;
5use base_scheduler::{Cancellation, OperationResult};
6use std::{future::Future, io};
7
8/// Sequential TLS application I/O, independent of a particular TLS provider. `S` supplies explicit execution/I/O capabilities. A stream owns its transport and TLS state; no background task or split reader/writer is implied.
9///
10/// Await operations after cooperative cancellation before closing. Write acceptance and delivery are separate: `write` reports the accepted plaintext prefix, while `flush` drives its encrypted output. Cancellation must preserve queued output without replaying already accepted plaintext. Fatal TLS or transport errors require closing or aborting the stream.
11pub trait TlsStream<S: ?Sized>: TlsSession {
12    /// Read a possibly short plaintext prefix. A nonempty destination returns zero after an authenticated TLS close notification. Unexpected transport EOF reports `UnexpectedEof` after buffered plaintext is consumed. Empty storage returns zero after checking cancellation.
13    fn read(
14        &mut self,
15        scheduler: &S,
16        buffer: &mut [u8],
17        cancellation: &Cancellation,
18    ) -> impl Future<Output = OperationResult<usize>> + Send;
19
20    /// Flush previous output, then accept a possibly short plaintext prefix. Return its accepted byte count without any subsequent asynchronous wait; use `flush` to send the final queued output. No bytes are accepted on an error return. Writing after local TLS shutdown fails.
21    fn write(
22        &mut self,
23        scheduler: &S,
24        buffer: &[u8],
25        cancellation: &Cancellation,
26    ) -> impl Future<Output = OperationResult<usize>> + Send;
27
28    /// Send queued output. Cancellation leaves the unsent ciphertext available for a subsequent flush.
29    fn flush(
30        &mut self,
31        scheduler: &S,
32        cancellation: &Cancellation,
33    ) -> impl Future<Output = OperationResult<()>> + Send;
34
35    /// Stop accepting plaintext writes and send a TLS close notification. Reads remain available. Retry after cancellation to finish sending the notification; this does not wait for peer closure.
36    fn shutdown(
37        &mut self,
38        scheduler: &S,
39        cancellation: &Cancellation,
40    ) -> impl Future<Output = OperationResult<()>> + Send;
41
42    /// Attempt TLS shutdown and consume/close the transport even if shutdown fails or is cancelled. Return the primary shutdown error if closure also fails.
43    fn close(
44        self,
45        scheduler: &S,
46        cancellation: &Cancellation,
47    ) -> impl Future<Output = OperationResult<()>> + Send
48    where
49        Self: Sized;
50
51    /// Consume and close the transport without a TLS close notification, for example after a fatal handshake or application-data error.
52    fn abort(self, scheduler: &S) -> impl Future<Output = io::Result<()>> + Send
53    where
54        Self: Sized;
55}