mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-08-01 01:11:58 +00:00
feat(swarm)!: allow NetworkBehaviour
s 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:
@@ -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>) {
|
||||
|
@@ -27,70 +27,19 @@ use futures::prelude::*;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures_timer::Delay;
|
||||
use libp2p_core::upgrade::SelectUpgrade;
|
||||
use libp2p_core::{ConnectedPoint, Multiaddr, PeerId, PublicKey};
|
||||
use libp2p_core::{Multiaddr, PeerId, PublicKey};
|
||||
use libp2p_swarm::handler::{
|
||||
ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound,
|
||||
};
|
||||
use libp2p_swarm::{
|
||||
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, IntoConnectionHandler,
|
||||
KeepAlive, NegotiatedSubstream, SubstreamProtocol,
|
||||
ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive,
|
||||
NegotiatedSubstream, SubstreamProtocol,
|
||||
};
|
||||
use log::warn;
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::VecDeque;
|
||||
use std::{io, pin::Pin, task::Context, task::Poll, time::Duration};
|
||||
|
||||
pub struct Proto {
|
||||
initial_delay: Duration,
|
||||
interval: Duration,
|
||||
public_key: PublicKey,
|
||||
protocol_version: String,
|
||||
agent_version: String,
|
||||
}
|
||||
|
||||
impl Proto {
|
||||
pub fn new(
|
||||
initial_delay: Duration,
|
||||
interval: Duration,
|
||||
public_key: PublicKey,
|
||||
protocol_version: String,
|
||||
agent_version: String,
|
||||
) -> Self {
|
||||
Proto {
|
||||
initial_delay,
|
||||
interval,
|
||||
public_key,
|
||||
protocol_version,
|
||||
agent_version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoConnectionHandler for Proto {
|
||||
type Handler = Handler;
|
||||
|
||||
fn into_handler(self, remote_peer_id: &PeerId, endpoint: &ConnectedPoint) -> Self::Handler {
|
||||
let observed_addr = match endpoint {
|
||||
ConnectedPoint::Dialer { address, .. } => address,
|
||||
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
|
||||
};
|
||||
|
||||
Handler::new(
|
||||
self.initial_delay,
|
||||
self.interval,
|
||||
*remote_peer_id,
|
||||
self.public_key,
|
||||
self.protocol_version,
|
||||
self.agent_version,
|
||||
observed_addr.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
fn inbound_protocol(&self) -> <Self::Handler as ConnectionHandler>::InboundProtocol {
|
||||
SelectUpgrade::new(Identify, Push::inbound())
|
||||
}
|
||||
}
|
||||
|
||||
/// Protocol handler for sending and receiving identification requests.
|
||||
///
|
||||
/// Outbound requests are sent periodically. The handler performs expects
|
||||
|
Reference in New Issue
Block a user