network: correct parsing of reject messages

Not all reject messages include a data field.  This change partially addresses
a problem that could lead to a depleted peer set:

1. We send a response to a `getheaders` message;
2. The remote peer `reject`s our `headers` message for some reason;
3. We fail to parse their `reject` message and close the connection;
4. Repeating this process, we have no more peers.

This commit fixes (3) but does not address (2).
This commit is contained in:
Henry de Valence 2020-12-01 14:56:38 -08:00 committed by Deirdre Connolly
parent 34518525a5
commit 69ba5584f3
1 changed files with 8 additions and 1 deletions

View File

@ -465,7 +465,14 @@ impl Codec {
_ => return Err(Error::Parse("invalid RejectReason value in ccode field")),
},
reason: reader.read_string()?,
data: Some(reader.read_32_bytes()?),
// Sometimes there's data, sometimes there isn't. There's no length
// field, this is just implicitly encoded by the body_len.
// Apparently all existing implementations only supply 32 bytes of
// data (hash identifying the rejected object) or none (and we model
// the Reject message that way), so instead of passing in the
// body_len separately and calculating remaining bytes, just try to
// read 32 bytes and ignore any failures.
data: reader.read_32_bytes().ok(),
})
}