While trying to write a secured WebSocket server using tungstenite-rs, I found this strange behavior of native-tls (it does not require tungstenite to reproduce). When a client incorrectly requests a non-TLS WebSocket handshake to the server, TlsAcceptor::accept(&self, stream) goes into an infinite loop and never returns unless the client explicitly closes the connection. Even worse, it makes the server (= TcpListener) stop handling other (TLS secured) WebSocket requests. I'm new to Rust so I couldn't determine why accepting one wrong request in the separated thread makes TcpListener in the main thread stop working.
Environment
native-tls = "0.2.10"
rustc 1.63.0 (4b91a6ea7 2022-08-08)
cargo 1.63.0 (fd9c4297c 2022-07-01)
Windows 11
Microsoft Edge
How to reproduce
Run the below program
use std::sync::Arc;
use std::thread;
use std::{fs::File, net::TcpListener};
use std::io::{Read};
use native_tls::{TlsAcceptor, Identity};
fn main() {
let mut file = File::open("./cert/server.pfx").unwrap();
let mut identity = vec![];
file.read_to_end(&mut identity).unwrap();
let identity = Identity::from_pkcs12(&identity, "").unwrap();
let acceptor = TlsAcceptor::new(identity).unwrap();
let acceptor = Arc::new(acceptor);
let server = TcpListener::bind("127.0.0.1:8080").unwrap();
let t = thread::spawn(move || {
for stream in server.incoming() {
println!("incoming!");
let acceptor = acceptor.clone();
thread::spawn(move || {
acceptor.accept(stream.unwrap()).unwrap();
println!("accepted!");
});
}
});
t.join().unwrap();
}
Send a non-TLS WebSocket request from a browser
> var ws = new WebSocket('ws://127.0.0.1:8080');
The server prints "incoming!" but not "accepted!"
Send another (but this time using TLS) WebSocketSecure request from a browser
> var ws = new WebSocket('wss://127.0.0.1:8080');
The server prints neither "incoming!" nor "accepted!", which means TcpListener itself is hanging?
Description
While trying to write a secured WebSocket server using tungstenite-rs, I found this strange behavior of native-tls (it does not require tungstenite to reproduce). When a client incorrectly requests a non-TLS WebSocket handshake to the server,
TlsAcceptor::accept(&self, stream)
goes into an infinite loop and never returns unless the client explicitly closes the connection. Even worse, it makes the server (= TcpListener) stop handling other (TLS secured) WebSocket requests. I'm new to Rust so I couldn't determine why accepting one wrong request in the separated thread makes TcpListener in the main thread stop working.Environment
How to reproduce
Run the below program
Send a non-TLS WebSocket request from a browser
The server prints "incoming!" but not "accepted!"
Send another (but this time using TLS) WebSocketSecure request from a browser
The server prints neither "incoming!" nor "accepted!", which means TcpListener itself is hanging?