light: give free credits for reserved peers (#9448)
* light: give free credits for reserved peers * Fix ethcore-light tests * Test free_flow_params
This commit is contained in:
parent
2177a0179e
commit
44531e3009
@ -44,6 +44,9 @@ pub trait IoContext {
|
||||
|
||||
/// Persistent peer id
|
||||
fn persistent_peer_id(&self, peer: PeerId) -> Option<NodeId>;
|
||||
|
||||
/// Whether given peer id is reserved peer
|
||||
fn is_reserved_peer(&self, peer: PeerId) -> bool;
|
||||
}
|
||||
|
||||
impl<T> IoContext for T where T: ?Sized + NetworkContext {
|
||||
@ -76,6 +79,10 @@ impl<T> IoContext for T where T: ?Sized + NetworkContext {
|
||||
fn persistent_peer_id(&self, peer: PeerId) -> Option<NodeId> {
|
||||
self.session_info(peer).and_then(|info| info.id)
|
||||
}
|
||||
|
||||
fn is_reserved_peer(&self, peer: PeerId) -> bool {
|
||||
NetworkContext::is_reserved_peer(self, peer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic context for the protocol.
|
||||
|
@ -354,6 +354,7 @@ pub struct LightProtocol {
|
||||
peers: RwLock<PeerMap>,
|
||||
capabilities: RwLock<Capabilities>,
|
||||
flow_params: RwLock<Arc<FlowParams>>,
|
||||
free_flow_params: Arc<FlowParams>,
|
||||
handlers: Vec<Arc<Handler>>,
|
||||
req_id: AtomicUsize,
|
||||
sample_store: Box<SampleStore>,
|
||||
@ -383,6 +384,7 @@ impl LightProtocol {
|
||||
peers: RwLock::new(HashMap::new()),
|
||||
capabilities: RwLock::new(params.capabilities),
|
||||
flow_params: RwLock::new(Arc::new(flow_params)),
|
||||
free_flow_params: Arc::new(FlowParams::free()),
|
||||
handlers: Vec::new(),
|
||||
req_id: AtomicUsize::new(0),
|
||||
sample_store,
|
||||
@ -706,8 +708,13 @@ impl LightProtocol {
|
||||
};
|
||||
|
||||
let capabilities = self.capabilities.read();
|
||||
let local_flow = self.flow_params.read();
|
||||
let status_packet = status::write_handshake(&status, &capabilities, Some(&**local_flow));
|
||||
let cost_local_flow = self.flow_params.read();
|
||||
let local_flow = if io.is_reserved_peer(peer) {
|
||||
&*self.free_flow_params
|
||||
} else {
|
||||
&**cost_local_flow
|
||||
};
|
||||
let status_packet = status::write_handshake(&status, &capabilities, Some(local_flow));
|
||||
|
||||
self.pending_peers.write().insert(peer, PendingPeer {
|
||||
sent_head: chain_info.best_block_hash,
|
||||
@ -818,7 +825,11 @@ impl LightProtocol {
|
||||
}
|
||||
|
||||
let remote_flow = flow_params.map(|params| (params.create_credits(), params));
|
||||
let local_flow = self.flow_params.read().clone();
|
||||
let local_flow = if io.is_reserved_peer(peer) {
|
||||
self.free_flow_params.clone()
|
||||
} else {
|
||||
self.flow_params.read().clone()
|
||||
};
|
||||
|
||||
self.peers.write().insert(peer, Mutex::new(Peer {
|
||||
local_credits: local_flow.create_credits(),
|
||||
|
@ -87,6 +87,10 @@ impl IoContext for Expect {
|
||||
fn persistent_peer_id(&self, _peer: PeerId) -> Option<NodeId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_reserved_peer(&self, peer: PeerId) -> bool {
|
||||
peer == 0xff
|
||||
}
|
||||
}
|
||||
|
||||
// can't implement directly for Arc due to cross-crate orphan rules.
|
||||
@ -190,6 +194,10 @@ fn write_handshake(status: &Status, capabilities: &Capabilities, proto: &LightPr
|
||||
::net::status::write_handshake(status, capabilities, Some(&*flow_params))
|
||||
}
|
||||
|
||||
fn write_free_handshake(status: &Status, capabilities: &Capabilities, proto: &LightProtocol) -> Vec<u8> {
|
||||
::net::status::write_handshake(status, capabilities, Some(&proto.free_flow_params))
|
||||
}
|
||||
|
||||
// helper for setting up the protocol handler and provider.
|
||||
fn setup(capabilities: Capabilities) -> (Arc<TestProviderInner>, LightProtocol) {
|
||||
let provider = Arc::new(TestProviderInner {
|
||||
@ -231,6 +239,19 @@ fn handshake_expected() {
|
||||
proto.on_connect(1, &Expect::Send(1, packet::STATUS, packet_body));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reserved_handshake_expected() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities);
|
||||
|
||||
let status = status(provider.client.chain_info());
|
||||
|
||||
let packet_body = write_free_handshake(&status, &capabilities, &proto);
|
||||
|
||||
proto.on_connect(0xff, &Expect::Send(0xff, packet::STATUS, packet_body));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn genesis_mismatch() {
|
||||
|
@ -68,6 +68,7 @@ impl<'a> IoContext for TestIoContext<'a> {
|
||||
fn protocol_version(&self, _peer: PeerId) -> Option<u8> { Some(::light::net::MAX_PROTOCOL_VERSION) }
|
||||
|
||||
fn persistent_peer_id(&self, _peer: PeerId) -> Option<NodeId> { unimplemented!() }
|
||||
fn is_reserved_peer(&self, _peer: PeerId) -> bool { false }
|
||||
}
|
||||
|
||||
// peer-specific data.
|
||||
|
@ -102,7 +102,7 @@ pub struct NetworkContext<'s> {
|
||||
sessions: Arc<RwLock<Slab<SharedSession>>>,
|
||||
session: Option<SharedSession>,
|
||||
session_id: Option<StreamToken>,
|
||||
_reserved_peers: &'s HashSet<NodeId>,
|
||||
reserved_peers: &'s HashSet<NodeId>,
|
||||
}
|
||||
|
||||
impl<'s> NetworkContext<'s> {
|
||||
@ -121,7 +121,7 @@ impl<'s> NetworkContext<'s> {
|
||||
session_id: id,
|
||||
session,
|
||||
sessions,
|
||||
_reserved_peers: reserved_peers,
|
||||
reserved_peers: reserved_peers,
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +190,13 @@ impl<'s> NetworkContextTrait for NetworkContext<'s> {
|
||||
}
|
||||
|
||||
fn subprotocol_name(&self) -> ProtocolId { self.protocol }
|
||||
|
||||
fn is_reserved_peer(&self, peer: PeerId) -> bool {
|
||||
self.session_info(peer)
|
||||
.and_then(|info| info.id)
|
||||
.map(|node| self.reserved_peers.contains(&node))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared host information
|
||||
|
@ -285,6 +285,9 @@ pub trait NetworkContext {
|
||||
|
||||
/// Returns this object's subprotocol name.
|
||||
fn subprotocol_name(&self) -> ProtocolId;
|
||||
|
||||
/// Returns whether the given peer ID is a reserved peer.
|
||||
fn is_reserved_peer(&self, peer: PeerId) -> bool;
|
||||
}
|
||||
|
||||
impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext {
|
||||
@ -331,6 +334,10 @@ impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext {
|
||||
fn subprotocol_name(&self) -> ProtocolId {
|
||||
(**self).subprotocol_name()
|
||||
}
|
||||
|
||||
fn is_reserved_peer(&self, peer: PeerId) -> bool {
|
||||
(**self).is_reserved_peer(peer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Network IO protocol handler. This needs to be implemented for each new subprotocol.
|
||||
|
Loading…
Reference in New Issue
Block a user