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}