-
Notifications
You must be signed in to change notification settings - Fork 996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[plaintext] Retain remaining read buffer after handshake. #1831
Conversation
When the plaintext protocol handshake finishes and the `Framed` I/O is discarded in favour of the underlying I/O stream, the remaining read buffer of `Framed` must be retained, as it may have buffered data beyond the end of the handshake.
// was already received but is no longer part of the plaintext | ||
// handshake. We need to capture that data before dropping | ||
// the `Framed` wrapper via `Framed::into_inner()`. | ||
let read_buffer = framed_socket.read_buffer().clone().freeze(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may be able to avoid cloning here in the future, if something like matthunz/futures-codec#54 is available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well spotted. Thanks for fixing this!
Thanks for the quick review. Any objections if I make a patch release straight away? |
@romanb patch release sounds good to me. Thanks! |
|
When the plaintext protocol handshake finishes and the
Framed
I/O used during the handshake is discarded in favor of the underlying I/O stream, the remaining read buffer ofFramed
must be retained, as it may have buffered data beyond the end of the handshake. This problem manifests itself in potential stalls / timeouts during protocol negotiation, because a peer does not necessarily wait for confirmation of a protocol before it sends the proposal for the next protocol upgrade. E.g./multistream/1.0.0 \n /mplex/6.7.0
for the mplex upgrade may already be received and buffered by theFramed
of the plaintext handshake by a peer before the handshake is complete. That peer will read the final handshake frame but then discard the remaining read buffer ofFramed
, leaving the remote waiting for the protocol confirmation for the next upgrade, but that proposal got "lost". The problem first appeared in #1765 where it was missed during review.This surfaced, without looking for it, during some benchmark attempts with the TCP transport and plaintext protocol in order to settle #802. However, because the symptoms are the same, I'm reasonably certain that this is the actual cause of the early connection negotiation stalls observed in #1629 (comment), unrelated to the random upgrade timeouts (which should already be fixed), since that test setup intentionally uses the plaintext protocol. So hopefully this should resolve the remaining problem(s) mentioned in #1629 that I had trouble to reproduce earlier.