Add comments and LICENSE
This commit is contained in:
@@ -17,9 +17,9 @@ use embedded_io_async::{BufRead, Read as AsyncRead, Write as AsyncWrite};
|
||||
|
||||
pub use crate::config::*;
|
||||
|
||||
/// Type representing an async TLS connection. An instance of this type can
|
||||
/// be used to establish a TLS connection, write and read encrypted data over this connection,
|
||||
/// and closing to free up the underlying resources.
|
||||
/// An async TLS 1.3 client stream wrapping an underlying async transport.
|
||||
///
|
||||
/// Call [`open`](SecureStream::open) to perform the handshake before reading or writing.
|
||||
pub struct SecureStream<'a, Socket, CipherSuite>
|
||||
where
|
||||
Socket: AsyncRead + AsyncWrite + 'a,
|
||||
@@ -42,17 +42,6 @@ where
|
||||
pub fn is_opened(&mut self) -> bool {
|
||||
*self.opened.get_mut()
|
||||
}
|
||||
/// Create a new TLS connection with the provided context and a async I/O implementation
|
||||
///
|
||||
/// NOTE: The record read buffer should be sized to fit an encrypted TLS record. The size of this record
|
||||
/// depends on the server configuration, but the maximum allowed value for a TLS record is 16640 bytes,
|
||||
/// which should be a safe value to use.
|
||||
///
|
||||
/// The write record buffer can be smaller than the read buffer. During writes [`TLS_RECORD_OVERHEAD`] bytes of
|
||||
/// overhead is added per record, so the buffer must at least be this large. Large writes are split into multiple
|
||||
/// records if depending on the size of the write buffer.
|
||||
/// The largest of the two buffers will be used to encode the TLS handshake record, hence either of the
|
||||
/// buffers must at least be large enough to encode a handshake.
|
||||
pub fn new(
|
||||
delegate: Socket,
|
||||
record_read_buf: &'a mut [u8],
|
||||
@@ -69,29 +58,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the current flush policy.
|
||||
///
|
||||
/// The flush policy controls whether the underlying transport is flushed
|
||||
/// (via its `flush()` method) after writing a TLS record.
|
||||
#[inline]
|
||||
pub fn flush_policy(&self) -> FlushPolicy {
|
||||
self.flush_policy
|
||||
}
|
||||
|
||||
/// Replace the current flush policy with the provided one.
|
||||
///
|
||||
/// This sets how and when the connection will call `flush()` on the
|
||||
/// underlying transport after writing records.
|
||||
#[inline]
|
||||
pub fn set_flush_policy(&mut self, policy: FlushPolicy) {
|
||||
self.flush_policy = policy;
|
||||
}
|
||||
|
||||
/// Open a TLS connection, performing the handshake with the configuration provided when
|
||||
/// creating the connection instance.
|
||||
///
|
||||
/// Returns an error if the handshake does not proceed. If an error occurs, the connection
|
||||
/// instance must be recreated.
|
||||
pub async fn open<CP>(
|
||||
&mut self,
|
||||
mut context: ConnectContext<'_, CP>,
|
||||
@@ -128,16 +104,9 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encrypt and send the provided slice over the connection. The connection
|
||||
/// must be opened before writing.
|
||||
///
|
||||
/// The slice may be buffered internally and not written to the connection immediately.
|
||||
/// In this case [`Self::flush()`] should be called to force the currently buffered writes
|
||||
/// to be written to the connection.
|
||||
///
|
||||
/// Returns the number of bytes buffered/written.
|
||||
pub async fn write(&mut self, buf: &[u8]) -> Result<usize, ProtocolError> {
|
||||
if self.is_opened() {
|
||||
// Start a new ApplicationData record if none is in progress
|
||||
if !self
|
||||
.record_write_buf
|
||||
.contains(ClientRecordHeader::ApplicationData)
|
||||
@@ -159,8 +128,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Force all previously written, buffered bytes to be encoded into a tls record and written
|
||||
/// to the connection.
|
||||
pub async fn flush(&mut self) -> Result<(), ProtocolError> {
|
||||
if !self.record_write_buf.is_empty() {
|
||||
let key_schedule = self.key_schedule.write_state();
|
||||
@@ -193,7 +160,6 @@ where
|
||||
self.decrypted.create_read_buffer(self.record_reader.buf)
|
||||
}
|
||||
|
||||
/// Read and decrypt data filling the provided slice.
|
||||
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, ProtocolError> {
|
||||
if buf.is_empty() {
|
||||
return Ok(0);
|
||||
@@ -206,7 +172,6 @@ where
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Reads buffered data. If nothing is in memory, it'll wait for a TLS record and process it.
|
||||
pub async fn read_buffered(&mut self) -> Result<ReadBuffer<'_>, ProtocolError> {
|
||||
if self.is_opened() {
|
||||
while self.decrypted.is_empty() {
|
||||
@@ -240,12 +205,12 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Close a connection instance, returning the ownership of the config, random generator and the async I/O provider.
|
||||
async fn close_internal(&mut self) -> Result<(), ProtocolError> {
|
||||
self.flush().await?;
|
||||
|
||||
let is_opened = self.is_opened();
|
||||
let (write_key_schedule, read_key_schedule) = self.key_schedule.as_split();
|
||||
// Send a close_notify alert to signal clean shutdown (RFC 8446 §6.1)
|
||||
let slice = self.record_write_buf.write_record(
|
||||
&ClientRecord::close_notify(is_opened),
|
||||
write_key_schedule,
|
||||
@@ -262,7 +227,6 @@ where
|
||||
self.flush_transport().await
|
||||
}
|
||||
|
||||
/// Close a connection instance, returning the ownership of the async I/O provider.
|
||||
pub async fn close(mut self) -> Result<Socket, (Socket, ProtocolError)> {
|
||||
match self.close_internal().await {
|
||||
Ok(()) => Ok(self.delegate),
|
||||
@@ -279,6 +243,7 @@ where
|
||||
where
|
||||
Socket: Clone,
|
||||
{
|
||||
// Split requires a Clone socket so both halves can independently drive the same connection
|
||||
let (wks, rks) = self.key_schedule.as_split();
|
||||
|
||||
let reader = TlsReader {
|
||||
@@ -375,7 +340,6 @@ where
|
||||
self.decrypted.create_read_buffer(self.record_reader.buf)
|
||||
}
|
||||
|
||||
/// Reads buffered data. If nothing is in memory, it'll wait for a TLS record and process it.
|
||||
pub async fn read_buffered(&mut self) -> Result<ReadBuffer<'_>, ProtocolError> {
|
||||
if self.opened.load(Ordering::Acquire) {
|
||||
while self.decrypted.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user