les: use negotiated protocol version

This commit is contained in:
Robert Habermeier 2016-12-09 15:04:54 +01:00
parent eec1929658
commit 5f37c93659
3 changed files with 32 additions and 5 deletions

View File

@ -38,6 +38,9 @@ pub trait IoContext {
/// Disable a peer -- this is a disconnect + a time-out.
fn disable_peer(&self, peer: PeerId);
/// Get a peer's protocol version.
fn protocol_version(&self, peer: PeerId) -> Option<u8>;
}
impl<'a> IoContext for NetworkContext<'a> {
@ -60,6 +63,10 @@ impl<'a> IoContext for NetworkContext<'a> {
fn disable_peer(&self, peer: PeerId) {
NetworkContext::disable_peer(self, peer);
}
fn protocol_version(&self, peer: PeerId) -> Option<u8> {
self.protocol_version(self.subprotocol_name(), peer)
}
}
/// Context for a protocol event.

View File

@ -58,6 +58,10 @@ pub enum Error {
UnsolicitedResponse,
/// Not a server.
NotServer,
/// Unsupported protocol version.
UnsupportedProtocolVersion(u8),
/// Bad protocol version.
BadProtocolVersion,
}
impl Error {
@ -73,6 +77,8 @@ impl Error {
Error::UnknownPeer => Punishment::Disconnect,
Error::UnsolicitedResponse => Punishment::Disable,
Error::NotServer => Punishment::Disable,
Error::UnsupportedProtocolVersion(_) => Punishment::Disable,
Error::BadProtocolVersion => Punishment::Disable,
}
}
}
@ -101,6 +107,8 @@ impl fmt::Display for Error {
Error::UnknownPeer => write!(f, "Unknown peer"),
Error::UnsolicitedResponse => write!(f, "Peer provided unsolicited data"),
Error::NotServer => write!(f, "Peer not a server."),
Error::UnsupportedProtocolVersion(pv) => write!(f, "Unsupported protocol version: {}", pv),
Error::BadProtocolVersion => write!(f, "Bad protocol version in handshake"),
}
}
}

View File

@ -23,7 +23,7 @@ use ethcore::transaction::SignedTransaction;
use ethcore::receipt::Receipt;
use io::TimerToken;
use network::{NetworkProtocolHandler, NetworkContext, NetworkError, PeerId};
use network::{NetworkProtocolHandler, NetworkContext, PeerId};
use rlp::{RlpStream, Stream, UntrustedRlp, View};
use util::hash::H256;
use util::{Bytes, Mutex, RwLock, U256};
@ -111,6 +111,7 @@ pub struct ReqId(usize);
struct PendingPeer {
sent_head: H256,
last_update: SteadyTime,
proto_version: u8,
}
// data about each peer.
@ -121,6 +122,7 @@ struct Peer {
remote_flow: Option<(Buffer, FlowParams)>,
sent_head: H256, // last head we've given them.
last_update: SteadyTime,
proto_version: u8,
}
impl Peer {
@ -507,17 +509,21 @@ impl LightProtocol {
}
// send status to a peer.
fn send_status(&self, peer: PeerId, io: &IoContext) -> Result<PendingPeer, NetworkError> {
let chain_info = self.provider.chain_info();
fn send_status(&self, peer: PeerId, io: &IoContext) -> Result<PendingPeer, Error> {
let proto_version = try!(io.protocol_version(peer).ok_or(Error::WrongNetwork));
// TODO: could update capabilities here.
if PROTOCOL_VERSIONS.iter().find(|x| **x == proto_version).is_none() {
return Err(Error::UnsupportedProtocolVersion(proto_version));
}
let chain_info = self.provider.chain_info();
let status = Status {
head_td: chain_info.total_difficulty,
head_hash: chain_info.best_block_hash,
head_num: chain_info.best_block_number,
genesis_hash: chain_info.genesis_hash,
protocol_version: MAX_PROTOCOL_VERSION as u32,
protocol_version: proto_version as u32, // match peer proto version
network_id: self.network_id,
last_head: None,
};
@ -530,6 +536,7 @@ impl LightProtocol {
Ok(PendingPeer {
sent_head: chain_info.best_block_hash,
last_update: SteadyTime::now(),
proto_version: proto_version,
})
}
@ -550,6 +557,10 @@ impl LightProtocol {
return Err(Error::WrongNetwork);
}
if Some(status.protocol_version as u8) != io.protocol_version(*peer) {
return Err(Error::BadProtocolVersion);
}
let remote_flow = flow_params.map(|params| (params.create_buffer(), params));
self.peers.write().insert(*peer, Mutex::new(Peer {
@ -559,6 +570,7 @@ impl LightProtocol {
remote_flow: remote_flow,
sent_head: pending.sent_head,
last_update: pending.last_update,
proto_version: pending.proto_version,
}));
for handler in &self.handlers {