async-rs / async-tls

A TLS implementation over AsyncRead and AsyncWrite
https://async.rs
Apache License 2.0
167 stars 47 forks source link

Reuse TcpStream in case handshake fails #13

Closed asynkayo closed 4 years ago

asynkayo commented 4 years ago

I currently have these types at hand: reader: BufReader<Take<ReadHalf>> writer: BufWriter<WriteHalf>

During the session, the connection can switch to using TLS and I'd like to switch the types to: reader: BufReader<Take<ReadHalf<TlsStream>>> writer: BufWriter<WriteHalf<TlsStream>> But in case the handshake fails, I'd like to continue as before.

I tried many things in order to get back the original TcpStream (but there's no reuinite() on ReadHalf and WriteHalf yet). Also I did not manage to have something working by borrowing the TcpStream in the first place.

I must be missing something as I'm rather new to Rust programming. Thanks for your help, and thanks for your work !

yoshuawuyts commented 4 years ago

With async-std, you can put TlsStream in an Arc wrapper, and then freely clone it around to pass it into async-tls:

Wrapper Code


#[derive(Clone)]
struct Stream(Arc<TcpStream>);

impl Read for Stream {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        Pin::new(&mut &*self.0).poll_read(cx, buf)
    }
}

impl Write for Stream {
    fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> {
        Pin::new(&mut &*self.0).poll_write(cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
        Pin::new(&mut &*self.0).poll_flush(cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
        Pin::new(&mut &*self.0).poll_close(cx)
    }
}

Usage

let stream = Arc::new(stream);
tls::connect(stream.clone());

// can still use tcp stream after this

This means you're able to reuse the connection even if connecting fails the first time. We're currently tracking making TcpStream implement Clone in https://github.com/async-rs/async-std/issues/553, allowing us to get rid of the wrapper above entirely.

Hope this is helpful!

asynkayo commented 4 years ago

That certainly did help ! Thanks Yoshua.