tokio-rs/tokio-tls

Can't listen to two sockets at the same time.

chaaz opened this issue · 8 comments

chaaz commented

It seems impossible to use tokio_tls to listen to two sockets at the same time:

fn main() {
  let mut lp = Core::new().unwrap();
  let loop1 = serve_https(lp.handle(), "cert1.pfx", 8443);
  let loop2 = serve_https(lp.handle(), "cert2.pfx", 8444);
  lp.run(loop1.join(loop2) ... ).unwrap();
}

fn serve_https(handle: Handle, cert: &str, port: usize) -> Box<Future<Item=(), Error=io::Error>> {
  ...
  let listener = TcpListener::bind(&addr, &handle).unwrap();
  let acceptor = TlsAcceptor::builder(pfx).unwrap().build().unwrap();
  ...
  Box::new(listener.incoming().for_each(move |(socket, _)| {
    acceptor.accept_async(socket).then(move |r| match r {
      ...
    }
  }
}
$ curl -k https://localhost:8444
{"success": true}
$ curl -k https://localhost:8443
TLS connection failed: Error { code: -50, message: "One or more parameters passed to a function were not valid." }
curl: (35) Server aborted the SSL handshake
chaaz commented

Digging into this a bit, this seems to be related to sfackler/rust-native-tls#34, which affects native-tls parallelism on OSX. The provided patch sfackler/rust-native-tls#54 fixes the issue.

For anyone else having the same issue, I fixed with the following in my Cargo.toml until native-tls accepts the patch:

[replace]
"native-tls:0.1.4" = { git = "https://github.com/blackbeam/rust-native-tls" }

(you can alternately use the cargo "patch" feature when that becomes available).

Thanks for the debugging here! Sounds like we should wait for the native-tls crate to get fixed upstream

chaaz commented

I agree. Do you want to close this issue, or leave it here until native-tls is patched? Thanks!

Nah fine by me to leave this open!

I have determined that the fix @chaaz provided also resolves a slightly different problem where multiple ports are listened to, but only one of them uses tokio-tls (e.g. a dual HTTP & HTTPS server).

Intermittently the code handling the TLS port will receive errors. Then all operations on streams returned from that socket will return an error. Eventually the listener.accept() call will cease returning streams but clients can still connect and then immediately block. During all this the non-TLS socket processing seems to remain unaffected.

Here are the most common errors returned:

  • connection closed via error
  • UNIX[Resource temporarily unavailable]
  • UNIX[Operation not permitted]

I mention all this in case anyone else experiences a similar issue. The only way I have found to reliably reproduce this error is to use wrk to stress test the non-TLS port for approximately 10 seconds, then any testing of the TLS port will begin producing these errors.

FYI, It appears the patch (mentioned above) that fixes these problems was just released in native-tls v.0.1.5.

Ok sounds like the various pieces here are fixed now though? If so I'll go a head and close, but let me know if this is in error!

I think so. However Cargo refuses to let tokio-tls 0.1.4 live with native-tls v0.1.5 in the same project so it's hard for me to test ATM.

Hm did cargo update work? It seems to work for me locally?