Search code examples
javascriptwebsocketrusttcpopenssl

How to connect to a Web Socket Server hosted via Rust?


I have a Web Socket Server written in Rust using native_tls because I need to eventually have it be able to receive connections remotely

use {
    native_tls::{Error as TlsError, HandshakeError, Identity, TlsAcceptor},
    std::{
        fs::File,
        io::{Error as IoError, Read},
        net::{TcpListener, TcpStream},
        sync::Arc,
        thread::spawn,
    },
};

#[derive(Debug)]
enum Error {
    IoError(IoError),
    TlsError(TlsError),
    HandshakeError(HandshakeError<TcpStream>),
}
impl From<IoError> for Error {
    fn from(error: IoError) -> Self {
        Self::IoError(error)
    }
}
impl From<TlsError> for Error {
    fn from(error: TlsError) -> Self {
        Self::TlsError(error)
    }
}
impl From<HandshakeError<TcpStream>> for Error {
    fn from(error: HandshakeError<TcpStream>) -> Self {
        Self::HandshakeError(error)
    }
}

fn main() -> Result<(), Error> {
    let identity = Identity::from_pkcs12(
        &{
            let mut identity = vec![];
            File::open("cert.p12")?.read_to_end(&mut identity)?;
            identity
        },
        "asdf",
    )?;

    let acceptor = Arc::new(TlsAcceptor::new(identity)?);

    for stream in TcpListener::bind("127.0.0.1:80")?.incoming() {
        let acceptor = acceptor.clone();

        spawn(move || -> Result<(), Error> {
            let client = acceptor.accept(stream?)?;
            println!("{:?}", client);
            Ok(())
        });
    }
    Ok(())
}

The javascript I use when attempting to connect:

let socket = new WebSocket(`wss://127.0.0.1:80`);

Everything works just fine but when I go to connect to it via Javascript, the host reveives and accepts the connection but it is dropped instantaneously with:

Firefox can’t establish a connection to the server at wss://127.0.0.1:80/.

I'm still unfamiliar with both Javascript and Certificate handling with the cert.p12 file. To get this file, I followed a basic tutorial from here but I'm not sure if this was the correct way of doing so.


Solution

  • The issue I was having is that native_tls wasn't able to work as a websocket itself. It would need some other websocket implementation to work with such as tungstenite. When using tungstenite, in order to have native_tls and itself work together, I would host a normal Tcp Server but instead of accepting it through tungstenite, I would accept it with an acceptor from native_tls then afterwards accept the connection through tungstenite which would allow for a tls connection with access to tungstenite's framework.