Move the peer manager to be a behaviour (#2773)

This simply moves some functions that were "swarm notifications" to a network behaviour implementation.

Notes
------
- We could disconnect from the peer manager but we would lose the rpc shutdown message
- We still notify from the swarm since this is the most reliable way to get some events. Ugly but best for now
- Events need to be pushed with "add event" to wake the waker

Co-authored-by: Divma <26765164+divagant-martian@users.noreply.github.com>
This commit is contained in:
Divma
2021-11-08 00:01:10 +00:00
parent df02639b71
commit fbafe416d1
6 changed files with 336 additions and 314 deletions

View File

@@ -15,7 +15,6 @@ use crate::types::{
};
use crate::Eth2Enr;
use crate::{error, metrics, Enr, NetworkConfig, NetworkGlobals, PubsubMessage, TopicHash};
use futures::prelude::*;
use libp2p::{
core::{
connection::ConnectionId, identity::Keypair, multiaddr::Protocol as MProtocol, Multiaddr,
@@ -139,11 +138,10 @@ pub struct Behaviour<TSpec: EthSpec> {
// NOTE: The id protocol is used for initial interop. This will be removed by mainnet.
/// Provides IP addresses and peer information.
identify: Identify,
/// The peer manager that keeps track of peer's reputation and status.
peer_manager: PeerManager<TSpec>,
/* Auxiliary Fields */
/// The peer manager that keeps track of peer's reputation and status.
#[behaviour(ignore)]
peer_manager: PeerManager<TSpec>,
/// The output events generated by this behaviour to be consumed in the swarm poll.
#[behaviour(ignore)]
events: VecDeque<BehaviourEvent<TSpec>>,
@@ -1088,71 +1086,6 @@ impl<TSpec: EthSpec> Behaviour<TSpec> {
}
}
// check the peer manager for events
loop {
match self.peer_manager.poll_next_unpin(cx) {
Poll::Ready(Some(event)) => match event {
PeerManagerEvent::PeerConnectedIncoming(peer_id) => {
return Poll::Ready(NBAction::GenerateEvent(
BehaviourEvent::PeerConnectedIncoming(peer_id),
));
}
PeerManagerEvent::PeerConnectedOutgoing(peer_id) => {
return Poll::Ready(NBAction::GenerateEvent(
BehaviourEvent::PeerConnectedOutgoing(peer_id),
));
}
PeerManagerEvent::PeerDisconnected(peer_id) => {
return Poll::Ready(NBAction::GenerateEvent(
BehaviourEvent::PeerDisconnected(peer_id),
));
}
PeerManagerEvent::Banned(peer_id, associated_ips) => {
self.discovery.ban_peer(&peer_id, associated_ips);
return Poll::Ready(NBAction::GenerateEvent(BehaviourEvent::PeerBanned(
peer_id,
)));
}
PeerManagerEvent::UnBanned(peer_id, associated_ips) => {
self.discovery.unban_peer(&peer_id, associated_ips);
return Poll::Ready(NBAction::GenerateEvent(BehaviourEvent::PeerUnbanned(
peer_id,
)));
}
PeerManagerEvent::Status(peer_id) => {
// it's time to status. We don't keep a beacon chain reference here, so we inform
// the network to send a status to this peer
return Poll::Ready(NBAction::GenerateEvent(BehaviourEvent::StatusPeer(
peer_id,
)));
}
PeerManagerEvent::DiscoverPeers => {
// Peer manager has requested a discovery query for more peers.
self.discovery.discover_peers();
}
PeerManagerEvent::DiscoverSubnetPeers(subnets_to_discover) => {
// Peer manager has requested a subnet discovery query for more peers.
self.discover_subnet_peers(subnets_to_discover);
}
PeerManagerEvent::Ping(peer_id) => {
// send a ping request to this peer
self.ping(RequestId::Behaviour, peer_id);
}
PeerManagerEvent::MetaData(peer_id) => {
self.send_meta_data_request(peer_id);
}
PeerManagerEvent::DisconnectPeer(peer_id, reason) => {
debug!(self.log, "Peer Manager disconnecting peer";
"peer_id" => %peer_id, "reason" => %reason);
// send one goodbye
self.eth2_rpc.shutdown(peer_id, reason);
}
},
Poll::Pending => break,
Poll::Ready(None) => break, // peer manager ended
}
}
if let Some(event) = self.events.pop_front() {
return Poll::Ready(NBAction::GenerateEvent(event));
}
@@ -1166,6 +1099,56 @@ impl<TSpec: EthSpec> Behaviour<TSpec> {
}
}
impl<TSpec: EthSpec> NetworkBehaviourEventProcess<PeerManagerEvent> for Behaviour<TSpec> {
fn inject_event(&mut self, event: PeerManagerEvent) {
match event {
PeerManagerEvent::PeerConnectedIncoming(peer_id) => {
self.add_event(BehaviourEvent::PeerConnectedIncoming(peer_id));
}
PeerManagerEvent::PeerConnectedOutgoing(peer_id) => {
self.add_event(BehaviourEvent::PeerConnectedOutgoing(peer_id));
}
PeerManagerEvent::PeerDisconnected(peer_id) => {
self.add_event(BehaviourEvent::PeerDisconnected(peer_id));
}
PeerManagerEvent::Banned(peer_id, associated_ips) => {
self.discovery.ban_peer(&peer_id, associated_ips);
self.add_event(BehaviourEvent::PeerBanned(peer_id));
}
PeerManagerEvent::UnBanned(peer_id, associated_ips) => {
self.discovery.unban_peer(&peer_id, associated_ips);
self.add_event(BehaviourEvent::PeerUnbanned(peer_id));
}
PeerManagerEvent::Status(peer_id) => {
// it's time to status. We don't keep a beacon chain reference here, so we inform
// the network to send a status to this peer
self.add_event(BehaviourEvent::StatusPeer(peer_id));
}
PeerManagerEvent::DiscoverPeers => {
// Peer manager has requested a discovery query for more peers.
self.discovery.discover_peers();
}
PeerManagerEvent::DiscoverSubnetPeers(subnets_to_discover) => {
// Peer manager has requested a subnet discovery query for more peers.
self.discover_subnet_peers(subnets_to_discover);
}
PeerManagerEvent::Ping(peer_id) => {
// send a ping request to this peer
self.ping(RequestId::Behaviour, peer_id);
}
PeerManagerEvent::MetaData(peer_id) => {
self.send_meta_data_request(peer_id);
}
PeerManagerEvent::DisconnectPeer(peer_id, reason) => {
debug!(self.log, "Peer Manager disconnecting peer";
"peer_id" => %peer_id, "reason" => %reason);
// send one goodbye
self.eth2_rpc.shutdown(peer_id, reason);
}
}
}
}
/* Public API types */
/// The type of RPC requests the Behaviour informs it has received and allows for sending.