snapview / tokio-tungstenite

Future-based Tungstenite for Tokio. Lightweight stream-based WebSocket implementation
MIT License
1.88k stars 236 forks source link

Is MaybeTlsStream supposed to work for servers too? #323

Closed jmarshall-com closed 7 months ago

jmarshall-com commented 8 months ago

I'm writing an async WebSockets server that may or may not use TLS, so I'm trying to use MaybeTlsStream to handle both cases the same. Looking at the definition of the MaybeTlsStream enum in stream.rs, the Rustls variant is defined as Rustls(tokio_rustls::client::TlsStream<S>), i.e. client-side only, which is incompatible with the return value from tokio_rustls::TlsAcceptor::accept(), which is tokio_rustls::server::TlsStream<S>. Is this intentional, or should MaybeTlsStream::Rustls hold the more generic tokio_rustls::TlsStream?

The relevant part of the code I'm trying to compile is:

let tls_acceptor= tokio_rustls::TlsAcceptor::from(tls_config) ;
let listener= tokio::net::TcpListener::bind(&bind_addr).await? ;

while let Ok((stream, addr)) = listener.accept().await {
    let mut tls_stream= tls_acceptor.accept(stream).await? ;
    tokio::spawn(handle_connection(ctx.clone(),
                     MaybeTlsStream::Rustls(tls_stream),
                     addr));
}

The relevant block of compiler output is:

error[E0308]: mismatched types
   --> src/main.rs:211:49
    |
211 |          MaybeTlsStream::Rustls(tls_stream),
    |          ---------------------- ^^^^^^^^^^ expected `TlsStream<TcpStream>`, found a different `TlsStream<TcpStream>`
    |          |
    |          arguments to this enum variant are incorrect
    |
    = note: expected struct `tokio_rustls::client::TlsStream<tokio::net::TcpStream>`
               found struct `tokio_rustls::server::TlsStream<tokio::net::TcpStream>`

if this is how it's supposed to work, how can I accept an incoming TLS connection and use MaybeTlsStream with it? I'm fairly new to Rust, so please tell me if I'm missing something-- all advice welcome. Thanks!

daniel-abramov commented 7 months ago

MaybeTlsStream is currently used on the client side when, e.g., using a connect() feature. The server's accept_async() accepts a generic async stream, so you can pass any stream there.

If I understand your use case correctly, you don't need to use MaybeTlsStream. You can handle the TLS/non-TLS case separately (like you currently do) and just pass the stream to accept_async(). There is no need to use the crate's TLS features if you handle TLS separately.

jmarshall-com commented 7 months ago

OK, thanks for the explanation. It sounds like I can initiate the TLS and non-TLS connections separately, and then subsequently use them in the same way, transparently. This is indeed what I need. Cheers.