feat(swarm)!: allow NetworkBehaviours to manage connections

Previously, a `ConnectionHandler` was immediately requested from the `NetworkBehaviour` as soon as a new dial was initiated or a new incoming connection accepted.

With this patch, we delay the creation of the handler until the connection is actually established and fully upgraded, i.e authenticated and multiplexed.

As a consequence, `NetworkBehaviour::new_handler` is now deprecated in favor of a new set of callbacks:

- `NetworkBehaviour::handle_pending_inbound_connection`
- `NetworkBehaviour::handle_pending_outbound_connection`
- `NetworkBehaviour::handle_established_inbound_connection`
- `NetworkBehaviour::handle_established_outbound_connection`

All callbacks are fallible, allowing the `NetworkBehaviour` to abort the connection either immediately or after it is fully established. All callbacks also receive a `ConnectionId` parameter which uniquely identifies the connection. For example, in case a `NetworkBehaviour` issues a dial via `NetworkBehaviourAction::Dial`, it can unambiguously detect this dial in these lifecycle callbacks via the `ConnectionId`.

Finally, `NetworkBehaviour::handle_pending_outbound_connection` also replaces `NetworkBehaviour::addresses_of_peer` by allowing the behaviour to return more addresses to be used for the dial.

Resolves #2824.

Pull-Request: #3254.
This commit is contained in:
Thomas Eizinger
2023-02-24 10:43:33 +11:00
committed by GitHub
parent 794b2a23d0
commit 19a554965f
42 changed files with 1543 additions and 540 deletions

View File

@ -30,11 +30,12 @@ use futures::stream::StreamExt;
use instant::Duration;
use libp2p_core::identity::error::SigningError;
use libp2p_core::identity::Keypair;
use libp2p_core::{Multiaddr, PeerId, PeerRecord};
use libp2p_core::{Endpoint, Multiaddr, PeerId, PeerRecord};
use libp2p_swarm::behaviour::FromSwarm;
use libp2p_swarm::{
CloseConnection, ConnectionId, ExternalAddresses, NetworkBehaviour, NetworkBehaviourAction,
NotifyHandler, PollParameters, THandlerInEvent, THandlerOutEvent,
CloseConnection, ConnectionDenied, ConnectionId, ExternalAddresses, NetworkBehaviour,
NetworkBehaviourAction, NotifyHandler, PollParameters, THandler, THandlerInEvent,
THandlerOutEvent,
};
use std::collections::{HashMap, VecDeque};
use std::iter::FromIterator;
@ -168,19 +169,51 @@ impl NetworkBehaviour for Behaviour {
SubstreamConnectionHandler<void::Void, outbound::Stream, outbound::OpenInfo>;
type OutEvent = Event;
fn new_handler(&mut self) -> Self::ConnectionHandler {
let initial_keep_alive = Duration::from_secs(30);
SubstreamConnectionHandler::new_outbound_only(initial_keep_alive)
fn handle_established_inbound_connection(
&mut self,
_: ConnectionId,
_: PeerId,
_: &Multiaddr,
_: &Multiaddr,
) -> Result<THandler<Self>, ConnectionDenied> {
Ok(SubstreamConnectionHandler::new_outbound_only(
Duration::from_secs(30),
))
}
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
self.discovered_peers
fn handle_pending_outbound_connection(
&mut self,
_connection_id: ConnectionId,
maybe_peer: Option<PeerId>,
_addresses: &[Multiaddr],
_effective_role: Endpoint,
) -> Result<Vec<Multiaddr>, ConnectionDenied> {
let peer = match maybe_peer {
None => return Ok(vec![]),
Some(peer) => peer,
};
let addresses = self
.discovered_peers
.iter()
.filter_map(|((candidate, _), addresses)| (candidate == peer).then_some(addresses))
.filter_map(|((candidate, _), addresses)| (candidate == &peer).then_some(addresses))
.flatten()
.cloned()
.collect()
.collect();
Ok(addresses)
}
fn handle_established_outbound_connection(
&mut self,
_: ConnectionId,
_: PeerId,
_: &Multiaddr,
_: Endpoint,
) -> Result<THandler<Self>, ConnectionDenied> {
Ok(SubstreamConnectionHandler::new_outbound_only(
Duration::from_secs(30),
))
}
fn on_connection_handler_event(

View File

@ -27,11 +27,11 @@ use futures::future::BoxFuture;
use futures::ready;
use futures::stream::FuturesUnordered;
use futures::{FutureExt, StreamExt};
use libp2p_core::PeerId;
use libp2p_core::{Endpoint, Multiaddr, PeerId};
use libp2p_swarm::behaviour::FromSwarm;
use libp2p_swarm::{
CloseConnection, ConnectionId, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler,
PollParameters, THandlerInEvent, THandlerOutEvent,
CloseConnection, ConnectionDenied, ConnectionId, NetworkBehaviour, NetworkBehaviourAction,
NotifyHandler, PollParameters, THandler, THandlerInEvent, THandlerOutEvent,
};
use std::collections::{HashMap, HashSet, VecDeque};
use std::iter::FromIterator;
@ -111,10 +111,28 @@ impl NetworkBehaviour for Behaviour {
type ConnectionHandler = SubstreamConnectionHandler<inbound::Stream, Void, ()>;
type OutEvent = Event;
fn new_handler(&mut self) -> Self::ConnectionHandler {
let initial_keep_alive = Duration::from_secs(30);
fn handle_established_inbound_connection(
&mut self,
_: ConnectionId,
_: PeerId,
_: &Multiaddr,
_: &Multiaddr,
) -> Result<THandler<Self>, ConnectionDenied> {
Ok(SubstreamConnectionHandler::new_inbound_only(
Duration::from_secs(30),
))
}
SubstreamConnectionHandler::new_inbound_only(initial_keep_alive)
fn handle_established_outbound_connection(
&mut self,
_: ConnectionId,
_: PeerId,
_: &Multiaddr,
_: Endpoint,
) -> Result<THandler<Self>, ConnectionDenied> {
Ok(SubstreamConnectionHandler::new_inbound_only(
Duration::from_secs(30),
))
}
fn on_connection_handler_event(