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

@ -18,16 +18,16 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use crate::handler::{self, InEvent, Proto};
use crate::handler::{self, Handler, InEvent};
use crate::protocol::{Info, Protocol, UpgradeError};
use libp2p_core::{multiaddr, ConnectedPoint, Multiaddr, PeerId, PublicKey};
use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr, PeerId, PublicKey};
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
use libp2p_swarm::{
behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm},
dial_opts::DialOpts,
AddressScore, ConnectionHandlerUpgrErr, ConnectionId, DialError, ExternalAddresses,
ListenAddresses, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters,
THandlerInEvent, THandlerOutEvent,
dial_opts::DialOpts, AddressScore, ConnectionDenied, ConnectionHandlerUpgrErr, DialError,
ExternalAddresses, ListenAddresses, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler,
PollParameters, THandlerInEvent,
};
use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent};
use lru::LruCache;
use std::num::NonZeroUsize;
use std::{
@ -234,17 +234,43 @@ impl Behaviour {
}
impl NetworkBehaviour for Behaviour {
type ConnectionHandler = Proto;
type ConnectionHandler = Handler;
type OutEvent = Event;
fn new_handler(&mut self) -> Self::ConnectionHandler {
Proto::new(
fn handle_established_inbound_connection(
&mut self,
_: ConnectionId,
peer: PeerId,
_: &Multiaddr,
remote_addr: &Multiaddr,
) -> Result<THandler<Self>, ConnectionDenied> {
Ok(Handler::new(
self.config.initial_delay,
self.config.interval,
peer,
self.config.local_public_key.clone(),
self.config.protocol_version.clone(),
self.config.agent_version.clone(),
)
remote_addr.clone(),
))
}
fn handle_established_outbound_connection(
&mut self,
_: ConnectionId,
peer: PeerId,
addr: &Multiaddr,
_: Endpoint,
) -> Result<THandler<Self>, ConnectionDenied> {
Ok(Handler::new(
self.config.initial_delay,
self.config.interval,
peer,
self.config.local_public_key.clone(),
self.config.protocol_version.clone(),
self.config.agent_version.clone(),
addr.clone(), // TODO: This is weird? That is the public address we dialed, shouldn't need to tell the other party?
))
}
fn on_connection_handler_event(
@ -352,8 +378,19 @@ impl NetworkBehaviour for Behaviour {
}
}
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
self.discovered_peers.get(peer)
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,
};
Ok(self.discovered_peers.get(&peer))
}
fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {