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

Flush unrecognized network messages from the read buffer #529

Merged

Conversation

afilini
Copy link
Contributor

@afilini afilini commented Dec 3, 2020

Currently whenever an unrecognized network message is received, it is never flushed from the read buffer, meaning that unless the stream is closed and recreated it will keep returning the same error every time read_next() is called.

This commit adds the length of the message to UnrecognizedNetworkCommand, so that the StreamReader can flush those bytes before returning the error to the caller.

@RCasatta and I encountered this issue while connecting to a Bitcoin Core 0.21-rc2 node using the latest release of rust-bitcoin. The specific error we were getting about sendaddrv2 being unrecognized should already be fixed here in master, but still this is probably an issue worth fixing for messages that could be added in the future to the P2P protocol.

@@ -70,7 +70,7 @@ impl Encodable for CommandString {
let mut rawbytes = [0u8; 12];
let strbytes = self.0.as_bytes();
if strbytes.len() > 12 {
return Err(encode::Error::UnrecognizedNetworkCommand(self.0.clone().into_owned()));
return Err(encode::Error::UnrecognizedNetworkCommand(self.0.clone().into_owned(), strbytes.len()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should give this a separate error variant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about NetworkCommandTooLong? or just a more generic InvalidNetworkCommand?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think TooLong is the better one. That's been the only invalidity condition for many years and I can't imagine it changing :).

Currently whenever an unrecognized network message is received, it is never
flushed from the read buffer, meaning that unless the stream is closed and
recreated it will keep returning the same error every time `read_next()` is
called.

This commit adds the length of the message to `UnrecognizedNetworkCommand`,
so that the `StreamReader` can flush those bytes before returning the error
to the caller.
@afilini afilini force-pushed the fix/flush-unrecognized-messages branch from 28034b3 to e33b914 Compare December 3, 2020 18:00
Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack e33b914

@apoelstra apoelstra added the API break This PR requires a version bump for the next release label Dec 3, 2020
@stevenroose
Copy link
Collaborator

It seems that some of the error variant changes are no longer required after https://github.com/rust-bitcoin/rust-bitcoin/pull/496/files.

Let's wait for #496 and #494 and rebase this on top of that.

But yeah I ended up not using the Stream thingy in bitcoin-p2p because it forces you to use a buffer per stream instead of one global buffer for all peers.

@apoelstra
Copy link
Member

Neither #496 nor #494 can get into the next version because they are too invasive, but this has practical use now.

Copy link
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

Copy link
Contributor

@sgeisler sgeisler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@@ -68,6 +68,10 @@ impl<R: Read> StreamReader<R> {
return Err(encode::Error::Io(io::Error::from(io::ErrorKind::UnexpectedEof)));
}
},
Err(encode::Error::UnrecognizedNetworkCommand(message, len)) => {
self.unparsed.drain(..len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note for future readers: This can't panic because for the UnrecognizedNetworkCommand error to be returned the payload length has to already have been verified in CheckedData::consensus_decode.

@sgeisler sgeisler merged commit 373f355 into rust-bitcoin:master Dec 15, 2020
@afilini afilini deleted the fix/flush-unrecognized-messages branch December 15, 2020 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API break This PR requires a version bump for the next release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants