Antti / rust-amqp

AMQP client in pure rust. Corresponds to rabbitmq spec.
MIT License
249 stars 45 forks source link

`try_clone` "does not behave as expected and will be removed in a future release" #72

Open emk opened 6 years ago

emk commented 6 years ago

Greetings. We use rust-amqp heavily at work, in production. Thank you for implementing it!

rust-amqp relies on try_clone, which is missing in newer versions of OpenSSL (and in portability libraries like native-tls). But even in older versions of OpenSSL, try_clone comes with a pretty serious warning:

Deprecated

This method does not behave as expected and will be removed in a future release.

According to a discussion at sfackler/rust-native-tls#89:

It is not possible to implement try_clone on any backend. A TLS stream is inherently stateful.

Since we have no choice but to use TLS at work, we need to address this issue for our own projects.

We actually have a partial port of rust-amqp to native-tls, but it's buggy because of the unresolved try_clone issue, so we've never submitted a PR for it.

We would be happy to contribute significant labor to updating rust-amqp. Do you have any ideas on the best way to proceed? We've roughed out a couple of ideas ourselves, including the possibility of converting rust-amqp to a single-threaded library and using one Session per thread. We've also thought about switching over to async, but we haven't thought through the issues yet. (And while addressing these issues, we'd really like to add/merge heartbeat support.)

Thank you for your advice and for your library!

emk commented 6 years ago

OK, I took a look at several other AMQP libraries, and consulted with my co-workers, and we decided that the easiest fix would be to reimplement the core socket code using tokio and tokio_openssl. This would allow us to implement full-duplex TLS connections and fix the event loop to no longer need try_clone.

I'm currently working on some proof-of-concept code here. Over the next couple of days, I hope to turn this into a demonstration of a full-duplex TLS client.

emk commented 6 years ago

OK, I've implemented a Tokio-based Connection class with a synchronous interface designed to mimic amqp::Connection. Here are the interesting bits of code:

This needs an AmqpFrameCodec to replace LineCodec, as well as some code to handle frame splitting, and the error and shutdown conditions could be made much more graceful. But I think it demonstrates that the basic strategy really ought to work.