tokio-rustls icon indicating copy to clipboard operation
tokio-rustls copied to clipboard

Feature: `TlsStream::from_inner`

Open conradludgate opened this issue 2 months ago • 1 comments

Request

To complement TlsStream::into_inner(Self) -> (IO, ClientConnection), I would like to have a TlsStream::from_inner(IO, ClientConnection) -> Self.

Justification

Multiple tokio runtimes

I would like to move TlsStream connections between different tokio runtimes. In order to achieve this I can use tokio::net::TcpStream::into_std and tokio::net::TcpStream::from_std. But I cannot perform this on a TlsStream.

An alternative API could be:

  1. tokio supporting in-place runtime migration on a &mut TcpStream, and I can use TlsStream::get_mut().move_runtime()
  2. tokio-rustls supporting runtime migration with a TlsStream::move_runtime(Self) -> Result<Self> API (clunky)

Pipelined TLS negotiation

I work with the postgres protocol. For postgres version < 17, to establish a TLS encrypted postgres session you need to perform SSL negotiation. This involves the client sending an SSLRequest message to postgres, and postgres responds with b"S". Upon receiving b"S", the client must start the TLS session. If postgres does not support SSL, it responds with b"N".

For cases where SSL is required and the environment is known, I would like to pipeline this SSLRequest and the TLS session. For this I have written my own rustls handshake code to intercept the single byte response, but I now want to turn that into a TlsStream after the handshake is complete.

An alternative design for this could be for me to use a TlsStream<Negotiated<TcpStream>>, where Negotiated is an AsyncRead wrapper that errors if the first byte is not S and strips it from TlsStream, but I want to avoid having that branch on every single TlsStream read.

conradludgate avatar Oct 07 '25 09:10 conradludgate

The request seems reasonable. I think from_parts() is the more idiomatic name if there more than one part, though.

djc avatar Oct 09 '25 10:10 djc