Skip to content
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

Merged
merged 2 commits into from
Nov 11, 2020

Conversation

romanb
Copy link
Contributor

@romanb romanb commented Nov 10, 2020

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 of Framed 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 the Framed 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 of Framed, 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.

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.
@romanb romanb requested a review from mxinden November 10, 2020 17:53
// 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();
Copy link
Contributor Author

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.

Copy link
Member

@mxinden mxinden left a 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!

@romanb
Copy link
Contributor Author

romanb commented Nov 11, 2020

Thanks for the quick review. Any objections if I make a patch release straight away?

@mxinden
Copy link
Member

mxinden commented Nov 11, 2020

Thanks for the quick review. Any objections if I make a patch release straight away?

@romanb patch release sounds good to me. Thanks!

@romanb romanb merged commit f771bcc into libp2p:master Nov 11, 2020
@romanb romanb deleted the plaintext-drain-buffer branch November 11, 2020 13:09
@romanb
Copy link
Contributor Author

romanb commented Nov 11, 2020

libp2p-0.30.1 and libp2p-plaintext-0.24.1 published.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants