Skip to main content

SslStream

Struct SslStream 

Source
pub struct SslStream<S: Unpin> { /* private fields */ }
Expand description

An asynchronous version of openssl::ssl::SslStream.

§Buffered output

OpenSSL writes into a buffer, from which the transport takes what it can. As with a BufWriter, a write completes once OpenSSL has encrypted its bytes, and a handshake call can complete with its last flight still buffered. Buffered output goes out with later writes, flushes and closes, and with reads, peeks and handshake calls that read from the transport, which flush it before they wait for the peer. flush returns once everything was sent and the transport flushed. close the stream rather than drop it, or close or flush its transport directly, or buffered output is lost.

A write first waits for buffered output, and for a transport flush that OpenSSL asked for: until then it returns Pending without writing, so it can be dropped or polled again with other bytes. Each write hands OpenSSL at most 16 KiB. Reads, peeks and handshake calls do not wait for output, so a peer that stops reading until it is read from cannot deadlock the stream, unless more than 64 KiB is waiting (what OpenSSL wrote by itself while reading or handshaking, on top of what writes left).

§Errors

A transport error while sending buffered output is returned by the write, flush or close that sends it, or by a call that would otherwise wait for the peer, who may be waiting for that output. A write whose own bytes the transport refuses still completes: OpenSSL wrote them. The output stays buffered and the error is not kept: a later call reports it if it recurs, so a transient error loses nothing.

Reads and writes return transport errors as they were, without passing them to OpenSSL. Peeks, handshake calls and read_early_data return them through OpenSSL, inside an ssl::Error. OpenSSL 4 then fails the session, unless the error is WouldBlock or NotConnected, which rust-openssl asks it to retry. LibreSSL replaces the error with its own, and may report the transport error again later as the cause of an unrelated end of stream. write_early_data never returns them.

A transport end without close_notify after the handshake reads as the end of the stream on OpenSSL 1.1.1, 3.x and LibreSSL, as with rust-openssl’s own streams. On OpenSSL 4 it is an error, and a close then fails too, unless the session has SslOptions::IGNORE_UNEXPECTED_EOF. A transport end or a close_notify during a handshake that a read drives, renegotiation included, is always an error.

§Closing

A close sends buffered output, writes close_notify once, sends it and closes the transport. A send error is returned with the transport left open, so that closing again retries; dropping the stream releases the transport. After the peer’s close_notify, failing to send ours is no error. Without a session to close (no handshake, a handshake or post-handshake exchange in progress, or a failed session), a close closes the transport and returns an error: the transport’s if closing it failed, else OpenSSL’s reason, if any. So does every later close. No write goes out after a close.

§Tasks

Waiting tasks are woken when the transport is ready or another task’s call failed to send, and those waiting for the peer also when another task’s call read from the transport. Keep one waker per task: each new one costs an extra wake, and more than 32 tasks waiting at once keep waking each other.

A panic in the transport poisons the stream: every later call that uses the transport fails.

Implementations§

Source§

impl<S> SslStream<S>
where S: AsyncRead + AsyncWrite + Unpin,

Source

pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack>

Source

pub fn poll_connect( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), Error>>

Like SslStream::connect.

It can complete while its last flight is still buffered, and returns transport errors through OpenSSL, as described.

Source

pub async fn connect(self: Pin<&mut Self>) -> Result<(), Error>

A convenience method wrapping poll_connect.

Source

pub fn poll_accept( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), Error>>

Like SslStream::accept.

It can complete while its last flight is still buffered, and returns transport errors through OpenSSL, as described.

Source

pub async fn accept(self: Pin<&mut Self>) -> Result<(), Error>

A convenience method wrapping poll_accept.

Source

pub fn poll_do_handshake( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), Error>>

Like SslStream::do_handshake.

It can complete while its last flight is still buffered, and returns transport errors through OpenSSL, as described.

Source

pub async fn do_handshake(self: Pin<&mut Self>) -> Result<(), Error>

A convenience method wrapping poll_do_handshake.

Source

pub fn poll_peek( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Error>>

Like SslStream::ssl_peek.

Like a read, it sends buffered output without waiting for it below the limit, and it returns transport errors through OpenSSL, as described.

Source

pub async fn peek(self: Pin<&mut Self>, buf: &mut [u8]) -> Result<usize, Error>

A convenience method wrapping poll_peek.

Source

pub fn poll_read_early_data( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Error>>

Like SslStream::read_early_data, except that a handshake failure, or a transport failure or end, right after the early data is an error, not the end of early data (Ok(0)). After the end of early data, it advances the handshake without waiting; accept finishes it.

An empty buffer returns Ok(0) if no early data was accepted or it is over, and an error once an early-data record arrives.

Requires OpenSSL 1.1.1 or newer (LibreSSL only has stubs for early data).

Source

pub async fn read_early_data( self: Pin<&mut Self>, buf: &mut [u8], ) -> Result<usize, Error>

A convenience method wrapping poll_read_early_data.

Requires OpenSSL 1.1.1 or newer.

Source

pub fn poll_write_early_data( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize, Error>>

Like SslStream::write_early_data.

Like a write, it first waits for buffered output, and writes at most 16 KiB. Unlike a write, it goes on after a transport error, which it cannot return: an ssl::Error only carries one that OpenSSL read, and SSL_write_early_data never reads. The next call that sends reports it if it recurs. Until then, the output it leaves is bounded by the session’s maximum early data on a client, and only by the caller on a server.

Requires OpenSSL 1.1.1 or newer (LibreSSL only has stubs for early data).

Source

pub async fn write_early_data( self: Pin<&mut Self>, buf: &[u8], ) -> Result<usize, Error>

A convenience method wrapping poll_write_early_data.

Requires OpenSSL 1.1.1 or newer.

Source§

impl<S: Unpin> SslStream<S>

Source

pub fn ssl(&self) -> &SslRef

Returns a shared reference to the Ssl object associated with this stream.

Source

pub fn get_ref(&self) -> &S

Returns a shared reference to the underlying stream.

Source

pub fn get_mut(&mut self) -> &mut S

Returns a mutable reference to the underlying stream.

§Warning

Reading from or writing to the underlying stream directly will corrupt the TLS session, and closing or flushing it directly misses the buffered output.

Source

pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut S>

Returns a pinned mutable reference to the underlying stream.

§Warning

Reading from or writing to the underlying stream directly will corrupt the TLS session, and closing or flushing it directly misses the buffered output.

Trait Implementations§

Source§

impl<S> AsyncRead for SslStream<S>
where S: AsyncRead + AsyncWrite + Unpin,

Source§

fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize>>

Attempt to read from the AsyncRead into buf. Read more
Source§

fn poll_read_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll<Result<usize, Error>>

Attempt to read from the AsyncRead into bufs using vectored IO operations. Read more
Source§

impl<S> AsyncWrite for SslStream<S>
where S: AsyncRead + AsyncWrite + Unpin,

Source§

fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
Source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempt to flush the object, ensuring that any buffered data reach their destination. Read more
Source§

fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempt to close the object. Read more
Source§

fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize, Error>>

Attempt to write bytes from bufs into the object using vectored IO operations. Read more
Source§

impl<S> Debug for SslStream<S>
where S: Debug + Unpin,

Source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<S> Freeze for SslStream<S>
where SslStream<StreamWrapper<S>>: Freeze,

§

impl<S> RefUnwindSafe for SslStream<S>
where SslStream<StreamWrapper<S>>: RefUnwindSafe,

§

impl<S> Send for SslStream<S>
where SslStream<StreamWrapper<S>>: Send,

§

impl<S> Sync for SslStream<S>
where SslStream<StreamWrapper<S>>: Sync,

§

impl<S> Unpin for SslStream<S>
where SslStream<StreamWrapper<S>>: Unpin,

§

impl<S> UnsafeUnpin for SslStream<S>
where SslStream<StreamWrapper<S>>: UnsafeUnpin,

§

impl<S> UnwindSafe for SslStream<S>
where SslStream<StreamWrapper<S>>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.