websockets-rs / rust-websocket

A WebSocket (RFC6455) library written in Rust

Home Page:http://websockets-rs.github.io/rust-websocket/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to create an optional ssl server?

kpp opened this issue · comments

commented

I want to create either a secure serve or insecure based on --args passed to my application.

Let's say I got:

use tokio::reactor::Handle as ReactorHandle;

use websocket::r#async::Server;

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
struct Opt {
    // ...
}

fn main() {
    let opt = Opt::from_args();

    let server = if opt.insecure {
        let srv = Server::bind("127.0.0.1:2794", &ReactorHandle::default()).unwrap();
        Box::new(srv) as Box<Server<_>>
    } else {
        let mut file = std::fs::File::open(opt.pfx_path.unwrap()).expect("Could not find pfx file");
        let mut pkcs12 = vec![];
        file.read_to_end(&mut pkcs12).expect("Could not read pfx file");
        let pkcs12 = native_tls::Identity::from_pkcs12(&pkcs12, &opt.pfx_pass.unwrap())
            .expect("Could not create pkcs12");

        let acceptor = native_tls::TlsAcceptor::builder(pkcs12).build()
            .expect("Could not create TlsAcceptor");

        let srv = Server::bind_secure("127.0.0.1:2794", acceptor, &ReactorHandle::default()).unwrap();
        Box::new(srv) as Box<Server<_>>
    };

    let f = server
        .incoming()
        //...

    let mut runtime = tokio::runtime::Builder::new().build().unwrap();
    runtime.block_on(f).unwrap();
}

However I got this error:

error[E0034]: multiple applicable items in scope
  --> src/main.rs:96:10
   |
96 |         .incoming()
   |          ^^^^^^^^ multiple `incoming` found
   |
   = note: candidate #1 is defined in an impl for the type `websocket::server::WsServer<websocket::server::NoTlsAcceptor, websocket::async::TcpListener>`
   = note: candidate #2 is defined in an impl for the type `websocket::server::WsServer<native_tls::TlsAcceptor, websocket::async::TcpListener>`

error: aborting due to previous error
commented
use websocket::server::{InvalidConnection, OptionalTlsAcceptor, NoTlsAcceptor};
use websocket::server::r#async::{Incoming};
use websocket::r#async::{Server, TcpStream as wsTcpStream, Stream as wsStream};

struct OptionalTlsServer<S: OptionalTlsAcceptor>
{
    pub server: Server<S>,
}

trait OptionalTlsServerTrait {
    type IncomingStream: Read + Write + wsStream + Send + 'static;
    fn incoming(self) -> Incoming<Self::IncomingStream>;
}

impl OptionalTlsServerTrait for OptionalTlsServer<native_tls::TlsAcceptor> {
    type IncomingStream = TlsStream<wsTcpStream>;
    fn incoming(self) -> Incoming<Self::IncomingStream> {
        self.server.incoming()
    }
}

impl OptionalTlsServerTrait for OptionalTlsServer<NoTlsAcceptor> {
    type IncomingStream = wsTcpStream;
    fn incoming(self) -> Incoming<Self::IncomingStream> {
        self.server.incoming()
    }
}

fn run_server(server: impl OptionalTlsServerTrait) {
    server.incoming()....
}

impl OptionalTlsServerTrait

This way the code in run_server may be duplicated, leading to increased executable size.

Another options should by usabe of trait object, like a dyn OptionalTlsServerTrait. But fn incoming should not accept self without reference then.

commented

leading to increased executable size

I don't care =) I did not want to duplicate my code manually.

Also one important thing: can I use WS but hide it behind nginx https somehow?

Yes.

Uncomment localhost: instead of unix:, but if needed rust-websocket can do over UNIX sockets as well.