From 3a84c141787d2206db1ace365fa1b19082d9f00a Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 11 Jan 2023 16:13:16 +1100 Subject: [PATCH 01/41] Use single quotes to avoid running commands --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ce4fc5fdea..a25fdf3c4e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -299,10 +299,10 @@ jobs: - name: Check PR title length run: | - title="${{ github.event.pull_request.title }}" + title='${{ github.event.pull_request.title }}' title_length=${#title} if [ $title_length -gt 72 ] then echo "PR title is too long (greater than 72 characters)" exit 1 - fi \ No newline at end of file + fi From 458aa533d9489aa374658bdba808f45446d4925d Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 13 Jan 2023 11:47:28 +1100 Subject: [PATCH 02/41] Use intermediary variable --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a25fdf3c4e0..c8725c7a332 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -298,9 +298,10 @@ jobs: require_scope: false - name: Check PR title length + env: + TITLE: ${{ github.event.pull_request.title }} run: | - title='${{ github.event.pull_request.title }}' - title_length=${#title} + title_length=${#TITLE} if [ $title_length -gt 72 ] then echo "PR title is too long (greater than 72 characters)" From d0d8b774536831db7a508a871d473a5702f86393 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 12:30:54 +1100 Subject: [PATCH 03/41] Make connection IDs globally unique --- core/src/connection.rs | 21 ++++++--------------- protocols/gossipsub/src/behaviour/tests.rs | 22 +++++++++++----------- protocols/kad/src/behaviour/test.rs | 2 +- swarm/src/connection/pool.rs | 15 ++------------- 4 files changed, 20 insertions(+), 40 deletions(-) diff --git a/core/src/connection.rs b/core/src/connection.rs index 91008408fe2..39a85750909 100644 --- a/core/src/connection.rs +++ b/core/src/connection.rs @@ -19,27 +19,18 @@ // DEALINGS IN THE SOFTWARE. use crate::multiaddr::{Multiaddr, Protocol}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static NEXT_CONNECTION_ID: AtomicUsize = AtomicUsize::new(0); /// Connection identifier. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ConnectionId(usize); impl ConnectionId { - /// Creates a `ConnectionId` from a non-negative integer. - /// - /// This is primarily useful for creating connection IDs - /// in test environments. There is in general no guarantee - /// that all connection IDs are based on non-negative integers. - pub fn new(id: usize) -> Self { - Self(id) - } -} - -impl std::ops::Add for ConnectionId { - type Output = Self; - - fn add(self, other: usize) -> Self { - Self(self.0 + other) + /// Returns the next available [`ConnectionId`]. + pub fn next() -> Self { + Self(NEXT_CONNECTION_ID.fetch_add(1, Ordering::SeqCst)) } } diff --git a/protocols/gossipsub/src/behaviour/tests.rs b/protocols/gossipsub/src/behaviour/tests.rs index 26af832e05f..7aa9adccbbc 100644 --- a/protocols/gossipsub/src/behaviour/tests.rs +++ b/protocols/gossipsub/src/behaviour/tests.rs @@ -225,13 +225,13 @@ where gs.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { peer_id: peer, - connection_id: ConnectionId::new(0), + connection_id: ConnectionId::next(), endpoint: &endpoint, failed_addresses: &[], other_established: 0, // first connection })); if let Some(kind) = kind { - gs.on_connection_handler_event(peer, ConnectionId::new(1), HandlerEvent::PeerKind(kind)); + gs.on_connection_handler_event(peer, ConnectionId::next(), HandlerEvent::PeerKind(kind)); } if explicit { gs.add_explicit_peer(&peer); @@ -579,7 +579,7 @@ fn test_join() { // inform the behaviour of a new peer gs.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { peer_id: random_peer, - connection_id: ConnectionId::new(1), + connection_id: ConnectionId::next(), endpoint: &ConnectedPoint::Dialer { address: "/ip4/127.0.0.1".parse::().unwrap(), role_override: Endpoint::Dialer, @@ -959,7 +959,7 @@ fn test_get_random_peers() { *p, PeerConnections { kind: PeerKind::Gossipsubv1_1, - connections: vec![ConnectionId::new(1)], + connections: vec![ConnectionId::next()], }, ) }) @@ -3009,7 +3009,7 @@ fn test_ignore_rpc_from_peers_below_graylist_threshold() { //receive from p1 gs.on_connection_handler_event( p1, - ConnectionId::new(0), + ConnectionId::next(), HandlerEvent::Message { rpc: GossipsubRpc { messages: vec![raw_message1], @@ -3035,7 +3035,7 @@ fn test_ignore_rpc_from_peers_below_graylist_threshold() { //receive from p2 gs.on_connection_handler_event( p2, - ConnectionId::new(0), + ConnectionId::next(), HandlerEvent::Message { rpc: GossipsubRpc { messages: vec![raw_message3], @@ -3647,7 +3647,7 @@ fn test_scoring_p4_invalid_signature() { gs.on_connection_handler_event( peers[0], - ConnectionId::new(0), + ConnectionId::next(), HandlerEvent::Message { rpc: GossipsubRpc { messages: vec![], @@ -4131,7 +4131,7 @@ fn test_scoring_p6() { for id in others.iter().take(3) { gs.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { peer_id: *id, - connection_id: ConnectionId::new(0), + connection_id: ConnectionId::next(), endpoint: &ConnectedPoint::Dialer { address: addr.clone(), role_override: Endpoint::Dialer, @@ -4152,7 +4152,7 @@ fn test_scoring_p6() { for peer in peers.iter().take(3) { gs.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { peer_id: *peer, - connection_id: ConnectionId::new(0), + connection_id: ConnectionId::next(), endpoint: &ConnectedPoint::Dialer { address: addr2.clone(), role_override: Endpoint::Dialer, @@ -4182,7 +4182,7 @@ fn test_scoring_p6() { //two times same ip doesn't count twice gs.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { peer_id: peers[0], - connection_id: ConnectionId::new(0), + connection_id: ConnectionId::next(), endpoint: &ConnectedPoint::Dialer { address: addr, role_override: Endpoint::Dialer, @@ -5194,7 +5194,7 @@ fn test_subscribe_and_graft_with_negative_score() { let (mut gs2, _, _) = inject_nodes1().create_network(); - let connection_id = ConnectionId::new(0); + let connection_id = ConnectionId::next(); let topic = Topic::new("test"); diff --git a/protocols/kad/src/behaviour/test.rs b/protocols/kad/src/behaviour/test.rs index bf3bd7cf17a..7c93e456404 100644 --- a/protocols/kad/src/behaviour/test.rs +++ b/protocols/kad/src/behaviour/test.rs @@ -1294,7 +1294,7 @@ fn network_behaviour_on_address_change() { let local_peer_id = PeerId::random(); let remote_peer_id = PeerId::random(); - let connection_id = ConnectionId::new(1); + let connection_id = ConnectionId::next(); let old_address: Multiaddr = Protocol::Memory(1).into(); let new_address: Multiaddr = Protocol::Memory(2).into(); diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index 30dff859d51..cf2392ab4d3 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -100,9 +100,6 @@ where /// The pending connections that are currently being negotiated. pending: HashMap>, - /// Next available identifier for a new connection / task. - next_connection_id: ConnectionId, - /// Size of the task command buffer (per task). task_command_buffer_size: usize, @@ -326,7 +323,6 @@ where counters: ConnectionCounters::new(limits), established: Default::default(), pending: Default::default(), - next_connection_id: ConnectionId::new(0), task_command_buffer_size: config.task_command_buffer_size, dial_concurrency_factor: config.dial_concurrency_factor, substream_upgrade_protocol_override: config.substream_upgrade_protocol_override, @@ -412,13 +408,6 @@ where self.established.keys() } - fn next_connection_id(&mut self) -> ConnectionId { - let connection_id = self.next_connection_id; - self.next_connection_id = self.next_connection_id + 1; - - connection_id - } - fn spawn(&mut self, task: BoxFuture<'static, ()>) { self.executor.spawn(task) } @@ -458,7 +447,7 @@ where dial_concurrency_factor_override.unwrap_or(self.dial_concurrency_factor), ); - let connection_id = self.next_connection_id(); + let connection_id = ConnectionId::next(); let (abort_notifier, abort_receiver) = oneshot::channel(); @@ -508,7 +497,7 @@ where return Err((limit, handler)); } - let connection_id = self.next_connection_id(); + let connection_id = ConnectionId::next(); let (abort_notifier, abort_receiver) = oneshot::channel(); From 11e5f74b33efb207a8dc82999a36bf6d50f47d1a Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 12:33:23 +1100 Subject: [PATCH 04/41] Deprecate old new function --- core/src/connection.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/src/connection.rs b/core/src/connection.rs index 39a85750909..3949921c3e1 100644 --- a/core/src/connection.rs +++ b/core/src/connection.rs @@ -28,6 +28,16 @@ static NEXT_CONNECTION_ID: AtomicUsize = AtomicUsize::new(0); pub struct ConnectionId(usize); impl ConnectionId { + /// Creates a `ConnectionId` from a non-negative integer. + /// + /// This is primarily useful for creating connection IDs + /// in test environments. There is in general no guarantee + /// that all connection IDs are based on non-negative integers. + #[deprecated(since = "0.39.0", note = "Use `ConnectionId::next` instead.")] + pub fn new(id: usize) -> Self { + Self(id) + } + /// Returns the next available [`ConnectionId`]. pub fn next() -> Self { Self(NEXT_CONNECTION_ID.fetch_add(1, Ordering::SeqCst)) From 47cf01ff7bcfd4f7d9a31d30690021fe2b61ce3b Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 12:34:39 +1100 Subject: [PATCH 05/41] Add changelog entry --- core/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index a7e24f5d616..18a45cccfaf 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.39.0 [unreleased] + +- Deprecate `ConnectionId::new` in favor of `ConnectionId::next`. See [PR 3327]. + +[PR 3327]: https://github.com/libp2p/rust-libp2p/pull/3327 + # 0.38.0 - Remove deprecated functions `StreamMuxerExt::next_{inbound,outbound}`. See [PR 3031]. From f77e443797d36b5e700c0b63cce4e6bce7e821a9 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 13:30:45 +1100 Subject: [PATCH 06/41] Remove `handler` field from `NetworkBehaviourAction::Dial` --- protocols/autonat/src/behaviour.rs | 19 +- protocols/autonat/src/behaviour/as_server.rs | 4 +- protocols/floodsub/src/layer.rs | 17 +- protocols/gossipsub/src/behaviour.rs | 16 +- protocols/gossipsub/src/behaviour/tests.rs | 10 +- protocols/identify/src/behaviour.rs | 9 +- protocols/kad/src/behaviour.rs | 22 +- protocols/mdns/src/behaviour.rs | 3 +- protocols/ping/src/lib.rs | 4 +- protocols/rendezvous/src/client.rs | 21 +- protocols/rendezvous/src/server.rs | 11 +- protocols/request-response/src/lib.rs | 16 +- swarm-derive/src/lib.rs | 122 ++----- swarm/src/behaviour.rs | 336 ++----------------- swarm/src/behaviour/either.rs | 29 +- swarm/src/behaviour/toggle.rs | 10 +- swarm/src/connection/pool.rs | 57 ++-- swarm/src/dummy.rs | 6 +- swarm/src/keep_alive.rs | 3 +- swarm/src/lib.rs | 49 ++- swarm/src/test.rs | 12 +- swarm/tests/swarm_derive.rs | 4 +- 22 files changed, 204 insertions(+), 576 deletions(-) diff --git a/protocols/autonat/src/behaviour.rs b/protocols/autonat/src/behaviour.rs index 995ee44072e..ea13afe8650 100644 --- a/protocols/autonat/src/behaviour.rs +++ b/protocols/autonat/src/behaviour.rs @@ -40,7 +40,7 @@ use libp2p_swarm::{ ExpiredListenAddr, FromSwarm, }, ConnectionHandler, ExternalAddresses, IntoConnectionHandler, ListenAddresses, NetworkBehaviour, - NetworkBehaviourAction, PollParameters, + NetworkBehaviourAction, PollParameters, THandlerInEvent, }; use std::{ collections::{HashMap, VecDeque}, @@ -210,10 +210,7 @@ pub struct Behaviour { last_probe: Option, pending_actions: VecDeque< - NetworkBehaviourAction< - ::OutEvent, - ::ConnectionHandler, - >, + NetworkBehaviourAction<::OutEvent, THandlerInEvent>, >, probe_id: ProbeId, @@ -391,14 +388,14 @@ impl Behaviour { &mut self, DialFailure { peer_id, - handler, + connection_id, error, - }: DialFailure<::ConnectionHandler>, + }: DialFailure, ) { self.inner .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id, - handler, + connection_id, error, })); if let Some(event) = self.as_server().on_outbound_dial_error(peer_id, error) { @@ -563,10 +560,8 @@ impl NetworkBehaviour for Behaviour { } } -type Action = NetworkBehaviourAction< - ::OutEvent, - ::ConnectionHandler, ->; +type Action = + NetworkBehaviourAction<::OutEvent, THandlerInEvent>; // Trait implemented for `AsClient` and `AsServer` to handle events from the inner [`request_response::Behaviour`] Protocol. trait HandleInnerEvent { diff --git a/protocols/autonat/src/behaviour/as_server.rs b/protocols/autonat/src/behaviour/as_server.rs index 8d08f7ed8d0..ea1e59821d4 100644 --- a/protocols/autonat/src/behaviour/as_server.rs +++ b/protocols/autonat/src/behaviour/as_server.rs @@ -29,7 +29,7 @@ use libp2p_request_response::{ }; use libp2p_swarm::{ dial_opts::{DialOpts, PeerCondition}, - DialError, NetworkBehaviour, NetworkBehaviourAction, PollParameters, + DialError, NetworkBehaviourAction, PollParameters, }; use std::{ collections::{HashMap, HashSet, VecDeque}, @@ -138,7 +138,7 @@ impl<'a> HandleInnerEvent for AsServer<'a> { ) .addresses(addrs) .build(), - handler: self.inner.new_handler(), + connection_id: ConnectionId::next(), }, ]) } diff --git a/protocols/floodsub/src/layer.rs b/protocols/floodsub/src/layer.rs index 776c0e8551b..109ebdca84a 100644 --- a/protocols/floodsub/src/layer.rs +++ b/protocols/floodsub/src/layer.rs @@ -30,7 +30,7 @@ use libp2p_core::{connection::ConnectionId, PeerId}; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm}; use libp2p_swarm::{ dial_opts::DialOpts, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, OneShotHandler, - PollParameters, + PollParameters, THandlerInEvent, }; use libp2p_swarm::{ConnectionHandler, IntoConnectionHandler}; use log::warn; @@ -42,12 +42,7 @@ use std::{collections::VecDeque, iter}; /// Network behaviour that handles the floodsub protocol. pub struct Floodsub { /// Events that need to be yielded to the outside when polling. - events: VecDeque< - NetworkBehaviourAction< - FloodsubEvent, - OneShotHandler, - >, - >, + events: VecDeque>, config: FloodsubConfig, @@ -108,10 +103,9 @@ impl Floodsub { } if self.target_peers.insert(peer_id) { - let handler = self.new_handler(); self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - handler, + connection_id: ConnectionId::next(), }); } } @@ -331,10 +325,9 @@ impl Floodsub { // We can be disconnected by the remote in case of inactivity for example, so we always // try to reconnect. if self.target_peers.contains(&peer_id) { - let handler = self.new_handler(); self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - handler, + connection_id: ConnectionId::next(), }); } } @@ -472,7 +465,7 @@ impl NetworkBehaviour for Floodsub { &mut self, _: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(event) = self.events.pop_front() { return Poll::Ready(event); } diff --git a/protocols/gossipsub/src/behaviour.rs b/protocols/gossipsub/src/behaviour.rs index fce25c12aff..3962433f56b 100644 --- a/protocols/gossipsub/src/behaviour.rs +++ b/protocols/gossipsub/src/behaviour.rs @@ -43,7 +43,7 @@ use libp2p_swarm::{ behaviour::{AddressChange, ConnectionClosed, ConnectionEstablished, FromSwarm}, dial_opts::DialOpts, ConnectionHandler, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction, - NotifyHandler, PollParameters, + NotifyHandler, PollParameters, THandlerInEvent, }; use wasm_timer::Instant; @@ -216,7 +216,7 @@ pub struct Gossipsub { config: GossipsubConfig, /// Events that need to be yielded to the outside when polling. - events: VecDeque>, + events: VecDeque>, /// Pools non-urgent control messages between heartbeats. control_pool: HashMap>, @@ -1134,10 +1134,9 @@ where if !self.peer_topics.contains_key(peer_id) { // Connect to peer debug!("Connecting to explicit peer {:?}", peer_id); - let handler = self.new_handler(); self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(*peer_id).build(), - handler, + connection_id: ConnectionId::next(), }); } } @@ -1635,10 +1634,9 @@ where self.px_peers.insert(peer_id); // dial peer - let handler = self.new_handler(); self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - handler, + connection_id: ConnectionId::next(), }); } } @@ -3442,7 +3440,7 @@ where &mut self, cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(event) = self.events.pop_front() { return Poll::Ready(event); } @@ -3491,7 +3489,7 @@ fn peer_added_to_mesh( new_topics: Vec<&TopicHash>, mesh: &HashMap>, known_topics: Option<&BTreeSet>, - events: &mut VecDeque>, + events: &mut VecDeque>, connections: &HashMap, ) { // Ensure there is an active connection @@ -3532,7 +3530,7 @@ fn peer_removed_from_mesh( old_topic: &TopicHash, mesh: &HashMap>, known_topics: Option<&BTreeSet>, - events: &mut VecDeque>, + events: &mut VecDeque>, connections: &HashMap, ) { // Ensure there is an active connection diff --git a/protocols/gossipsub/src/behaviour/tests.rs b/protocols/gossipsub/src/behaviour/tests.rs index 7aa9adccbbc..65914d6feea 100644 --- a/protocols/gossipsub/src/behaviour/tests.rs +++ b/protocols/gossipsub/src/behaviour/tests.rs @@ -1386,7 +1386,7 @@ fn test_explicit_peer_gets_connected() { .events .iter() .filter(|e| match e { - NetworkBehaviourAction::Dial { opts, handler: _ } => opts.get_peer_id() == Some(peer), + NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id() == Some(peer), _ => false, }) .count(); @@ -1427,8 +1427,7 @@ fn test_explicit_peer_reconnects() { gs.events .iter() .filter(|e| match e { - NetworkBehaviourAction::Dial { opts, handler: _ } => - opts.get_peer_id() == Some(*peer), + NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id() == Some(*peer), _ => false, }) .count(), @@ -1443,8 +1442,7 @@ fn test_explicit_peer_reconnects() { gs.events .iter() .filter(|e| match e { - NetworkBehaviourAction::Dial { opts, handler: _ } => - opts.get_peer_id() == Some(*peer), + NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id() == Some(*peer), _ => false, }) .count() @@ -1824,7 +1822,7 @@ fn test_connect_to_px_peers_on_handle_prune() { .events .iter() .filter_map(|e| match e { - NetworkBehaviourAction::Dial { opts, handler: _ } => opts.get_peer_id(), + NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id(), _ => None, }) .collect(); diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 123c8140ecd..64e765f6e22 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -27,7 +27,7 @@ use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailu use libp2p_swarm::{ dial_opts::DialOpts, AddressScore, ConnectionHandler, ConnectionHandlerUpgrErr, DialError, ExternalAddresses, IntoConnectionHandler, ListenAddresses, NetworkBehaviour, - NetworkBehaviourAction, NotifyHandler, PollParameters, + NetworkBehaviourAction, NotifyHandler, PollParameters, THandlerInEvent, }; use lru::LruCache; use std::num::NonZeroUsize; @@ -54,7 +54,7 @@ pub struct Behaviour { /// with current information about the local peer. requests: Vec, /// Pending events to be emitted when polled. - events: VecDeque>, + events: VecDeque>, /// The addresses of all peers that we have discovered. discovered_peers: PeerCache, @@ -199,10 +199,9 @@ impl Behaviour { if !self.requests.contains(&request) { self.requests.push(request); - let handler = self.new_handler(); self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(p).build(), - handler, + connection_id: ConnectionId::next(), }); } } @@ -310,7 +309,7 @@ impl NetworkBehaviour for Behaviour { &mut self, _cx: &mut Context<'_>, params: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(event) = self.events.pop_front() { return Poll::Ready(event); } diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index 6ceb8c73d54..48cf8dd9695 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -46,7 +46,7 @@ use libp2p_swarm::behaviour::{ use libp2p_swarm::{ dial_opts::{self, DialOpts}, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour, NetworkBehaviourAction, - NotifyHandler, PollParameters, + NotifyHandler, PollParameters, THandlerInEvent, }; use log::{debug, info, warn}; use smallvec::SmallVec; @@ -101,7 +101,7 @@ pub struct Kademlia { connection_idle_timeout: Duration, /// Queued events to return when the behaviour is being polled. - queued_events: VecDeque>>, + queued_events: VecDeque>>, listen_addresses: ListenAddresses, @@ -571,10 +571,9 @@ where RoutingUpdate::Failed } kbucket::InsertResult::Pending { disconnected } => { - let handler = self.new_handler(); self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(disconnected.into_preimage()).build(), - handler, + connection_id: ConnectionId::next(), }); RoutingUpdate::Pending } @@ -1221,11 +1220,10 @@ where // // Only try dialing peer if not currently connected. if !self.connected_peers.contains(disconnected.preimage()) { - let handler = self.new_handler(); self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(disconnected.into_preimage()) .build(), - handler, + connection_id: ConnectionId::next(), }) } } @@ -1917,12 +1915,7 @@ where } } - fn on_dial_failure( - &mut self, - DialFailure { peer_id, error, .. }: DialFailure< - ::ConnectionHandler, - >, - ) { + fn on_dial_failure(&mut self, DialFailure { peer_id, error, .. }: DialFailure) { let peer_id = match peer_id { Some(id) => id, // Not interested in dial failures to unknown peers. @@ -2293,7 +2286,7 @@ where &mut self, cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { let now = Instant::now(); // Calculate the available capacity for queries triggered by background jobs. @@ -2392,10 +2385,9 @@ where }); } else if &peer_id != self.kbuckets.local_key().preimage() { query.inner.pending_rpcs.push((peer_id, event)); - let handler = self.new_handler(); self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - handler, + connection_id: ConnectionId::next(), }); } } diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index 815a23c9bdc..e1b19a90acc 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -36,6 +36,7 @@ use libp2p_swarm::{ use smallvec::SmallVec; use std::collections::hash_map::{Entry, HashMap}; use std::{cmp, fmt, io, net::IpAddr, pin::Pin, task::Context, task::Poll, time::Instant}; +use void::Void; /// An abstraction to allow for compatibility with various async runtimes. pub trait Provider: 'static { @@ -231,7 +232,7 @@ where &mut self, cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll> { // Poll ifwatch. while let Poll::Ready(Some(event)) = Pin::new(&mut self.if_watch).poll_next(cx) { match event { diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 6e481500df9..23dccc769dc 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -49,7 +49,7 @@ use handler::Handler; pub use handler::{Config, Failure, Success}; use libp2p_core::{connection::ConnectionId, PeerId}; use libp2p_swarm::{ - behaviour::FromSwarm, NetworkBehaviour, NetworkBehaviourAction, PollParameters, + behaviour::FromSwarm, NetworkBehaviour, NetworkBehaviourAction, PollParameters, THandlerInEvent, }; use std::{ collections::VecDeque, @@ -131,7 +131,7 @@ impl NetworkBehaviour for Behaviour { &mut self, _: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(e) = self.events.pop_back() { let Event { result, peer } = &e; diff --git a/protocols/rendezvous/src/client.rs b/protocols/rendezvous/src/client.rs index 41c4daf0ec6..66e62602ae6 100644 --- a/protocols/rendezvous/src/client.rs +++ b/protocols/rendezvous/src/client.rs @@ -22,7 +22,7 @@ use crate::codec::{Cookie, ErrorCode, Namespace, NewRegistration, Registration, use crate::handler; use crate::handler::outbound; use crate::handler::outbound::OpenInfo; -use crate::substream_handler::SubstreamConnectionHandler; +use crate::substream_handler::{InEvent, SubstreamConnectionHandler}; use futures::future::BoxFuture; use futures::future::FutureExt; use futures::stream::FuturesUnordered; @@ -35,19 +35,15 @@ use libp2p_core::{Multiaddr, PeerId, PeerRecord}; use libp2p_swarm::behaviour::FromSwarm; use libp2p_swarm::{ CloseConnection, ExternalAddresses, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, - PollParameters, + PollParameters, THandlerInEvent, }; use std::collections::{HashMap, VecDeque}; use std::iter::FromIterator; use std::task::{Context, Poll}; +use void::Void; pub struct Behaviour { - events: VecDeque< - NetworkBehaviourAction< - Event, - SubstreamConnectionHandler, - >, - >, + events: VecDeque>>, keypair: Keypair, pending_register_requests: Vec<(Namespace, PeerId, Option)>, @@ -220,7 +216,7 @@ impl NetworkBehaviour for Behaviour { &mut self, cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(event) = self.events.pop_front() { return Poll::Ready(event); } @@ -294,12 +290,7 @@ fn handle_outbound_event( peer_id: PeerId, discovered_peers: &mut HashMap<(PeerId, Namespace), Vec>, expiring_registrations: &mut FuturesUnordered>, -) -> Vec< - NetworkBehaviourAction< - Event, - SubstreamConnectionHandler, - >, -> { +) -> Vec>> { match event { outbound::OutEvent::Registered { namespace, ttl } => { vec![NetworkBehaviourAction::GenerateEvent(Event::Registered { diff --git a/protocols/rendezvous/src/server.rs b/protocols/rendezvous/src/server.rs index 4126b6e3e28..840611eddb0 100644 --- a/protocols/rendezvous/src/server.rs +++ b/protocols/rendezvous/src/server.rs @@ -20,7 +20,7 @@ use crate::codec::{Cookie, ErrorCode, Namespace, NewRegistration, Registration, Ttl}; use crate::handler::inbound; -use crate::substream_handler::{InboundSubstreamId, SubstreamConnectionHandler}; +use crate::substream_handler::{InEvent, InboundSubstreamId, SubstreamConnectionHandler}; use crate::{handler, MAX_TTL, MIN_TTL}; use bimap::BiMap; use futures::future::BoxFuture; @@ -32,6 +32,7 @@ use libp2p_core::PeerId; use libp2p_swarm::behaviour::FromSwarm; use libp2p_swarm::{ CloseConnection, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters, + THandlerInEvent, }; use std::collections::{HashMap, HashSet, VecDeque}; use std::iter::FromIterator; @@ -40,9 +41,7 @@ use std::time::Duration; use void::Void; pub struct Behaviour { - events: VecDeque< - NetworkBehaviourAction>, - >, + events: VecDeque>>, registrations: Registrations, } @@ -148,7 +147,7 @@ impl NetworkBehaviour for Behaviour { &mut self, cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Poll::Ready(ExpiredRegistration(registration)) = self.registrations.poll(cx) { return Poll::Ready(NetworkBehaviourAction::GenerateEvent( Event::RegistrationExpired(registration), @@ -186,7 +185,7 @@ fn handle_inbound_event( connection: ConnectionId, id: InboundSubstreamId, registrations: &mut Registrations, -) -> Vec>> { +) -> Vec>> { match event { // bad registration inbound::OutEvent::RegistrationRequested(registration) diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index f5fa3067f80..a5e3ae95b82 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -75,6 +75,7 @@ use libp2p_swarm::{ behaviour::{AddressChange, ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}, dial_opts::DialOpts, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters, + THandlerInEvent, }; use smallvec::SmallVec; use std::{ @@ -348,8 +349,9 @@ where /// The protocol codec for reading and writing requests and responses. codec: TCodec, /// Pending events to return from `poll`. - pending_events: - VecDeque, Handler>>, + pending_events: VecDeque< + NetworkBehaviourAction, RequestProtocol>, + >, /// The currently connected peers, their pending outbound and inbound responses and their known, /// reachable addresses, if any. connected: HashMap>, @@ -416,10 +418,9 @@ where }; if let Some(request) = self.try_send_request(peer, request) { - let handler = self.new_handler(); self.pending_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(*peer).build(), - handler, + connection_id: ConnectionId::next(), }); self.pending_outbound_requests .entry(*peer) @@ -695,10 +696,7 @@ where } } - fn on_dial_failure( - &mut self, - DialFailure { peer_id, .. }: DialFailure<::ConnectionHandler>, - ) { + fn on_dial_failure(&mut self, DialFailure { peer_id, .. }: DialFailure) { if let Some(peer) = peer_id { // If there are pending outgoing requests when a dial failure occurs, // it is implied that we are not connected to the peer, since pending @@ -931,7 +929,7 @@ where &mut self, _: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(ev); } else if self.pending_events.capacity() > EMPTY_QUEUE_SHRINK_THRESHOLD { diff --git a/swarm-derive/src/lib.rs b/swarm-derive/src/lib.rs index 489ec8c7bc6..9ff690b323b 100644 --- a/swarm-derive/src/lib.rs +++ b/swarm-derive/src/lib.rs @@ -74,6 +74,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { let expired_external_addr = quote! { #prelude_path::ExpiredExternalAddr }; let listener_error = quote! { #prelude_path::ListenerError }; let listener_closed = quote! { #prelude_path::ListenerClosed }; + let t_handler_in_event = quote! { #prelude_path::THandlerInEvent }; // Build the generics. let impl_generics = { @@ -289,37 +290,24 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { .fields .iter() .enumerate() - // The outmost handler belongs to the last behaviour. - .rev() - .enumerate() - .map(|(enum_n, (field_n, field))| { - let handler = if field_n == 0 { - // Given that the iterator is reversed, this is the innermost handler only. - quote! { let handler = handlers } - } else { - quote! { - let (handlers, handler) = handlers.into_inner() - } - }; - + .map(|(enum_n, field)| { let inject = match field.ident { Some(ref i) => quote! { self.#i.on_swarm_event(#from_swarm::DialFailure(#dial_failure { peer_id, - handler, + connection_id, error, })); }, None => quote! { self.#enum_n.on_swarm_event(#from_swarm::DialFailure(#dial_failure { peer_id, - handler, + connection_id, error, })); }, }; quote! { - #handler; #inject; } }) @@ -327,42 +315,32 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { // Build the list of statements to put in the body of `on_swarm_event()` // for the `FromSwarm::ListenFailure` variant. - let on_listen_failure_stmts = - { - data_struct.fields.iter().enumerate().rev().enumerate().map( - |(enum_n, (field_n, field))| { - let handler = if field_n == 0 { - quote! { let handler = handlers } - } else { - quote! { - let (handlers, handler) = handlers.into_inner() - } - }; - - let inject = match field.ident { - Some(ref i) => quote! { - self.#i.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { - local_addr, - send_back_addr, - handler, - })); - }, - None => quote! { - self.#enum_n.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { - local_addr, - send_back_addr, - handler, - })); - }, - }; + let on_listen_failure_stmts = { + data_struct + .fields + .iter() + .enumerate() + .map(|(enum_n, field)| { + let inject = match field.ident { + Some(ref i) => quote! { + self.#i.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { + local_addr, + send_back_addr, + })); + }, + None => quote! { + self.#enum_n.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { + local_addr, + send_back_addr, + })); + }, + }; - quote! { - #handler; - #inject; - } - }, - ) - }; + quote! { + #inject; + } + }) + }; // Build the list of statements to put in the body of `on_swarm_event()` // for the `FromSwarm::NewListener` variant. @@ -607,38 +585,6 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { wrapped_event = quote!{ #either_ident::First(#wrapped_event) }; } - // `Dial` provides a handler of the specific behaviour triggering the - // event. Though in order for the final handler to be able to handle - // protocols of all behaviours, the provided handler needs to be - // combined with handlers of all other behaviours. - let provided_handler_and_new_handlers = { - let mut out_handler = None; - - for (f_n, f) in data_struct.fields.iter().enumerate() { - let f_name = match f.ident { - Some(ref i) => quote! { self.#i }, - None => quote! { self.#f_n }, - }; - - let builder = if field_n == f_n { - // The behaviour that triggered the event. Thus, instead of - // creating a new handler, use the provided handler. - quote! { provided_handler } - } else { - quote! { #f_name.new_handler() } - }; - - match out_handler { - Some(h) => { - out_handler = Some(quote! { #into_connection_handler::select(#h, #builder) }) - } - ref mut h @ None => *h = Some(builder), - } - } - - out_handler.unwrap_or(quote! {()}) // TODO: See test `empty`. - }; - let generate_event_match_arm = { // If the `NetworkBehaviour`'s `OutEvent` is generated by the derive macro, wrap the sub // `NetworkBehaviour` `OutEvent` in the variant of the generated `OutEvent`. If the @@ -666,8 +612,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { loop { match #trait_to_impl::poll(&mut self.#field, cx, poll_params) { #generate_event_match_arm - std::task::Poll::Ready(#network_behaviour_action::Dial { opts, handler: provided_handler }) => { - return std::task::Poll::Ready(#network_behaviour_action::Dial { opts, handler: #provided_handler_and_new_handlers }); + std::task::Poll::Ready(#network_behaviour_action::Dial { opts, connection_id }) => { + return std::task::Poll::Ready(#network_behaviour_action::Dial { opts, connection_id }); } std::task::Poll::Ready(#network_behaviour_action::NotifyHandler { peer_id, handler, event }) => { return std::task::Poll::Ready(#network_behaviour_action::NotifyHandler { @@ -726,7 +672,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { } } - fn poll(&mut self, cx: &mut std::task::Context, poll_params: &mut impl #poll_parameters) -> std::task::Poll<#network_behaviour_action> { + fn poll(&mut self, cx: &mut std::task::Context, poll_params: &mut impl #poll_parameters) -> std::task::Poll<#network_behaviour_action>> { use #prelude_path::futures::*; #(#poll_stmts)* std::task::Poll::Pending @@ -744,10 +690,10 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { #connection_closed { peer_id, connection_id, endpoint, handler: handlers, remaining_established }) => { #(#on_connection_closed_stmts)* } #from_swarm::DialFailure( - #dial_failure { peer_id, handler: handlers, error }) + #dial_failure { peer_id, connection_id, error }) => { #(#on_dial_failure_stmts)* } #from_swarm::ListenFailure( - #listen_failure { local_addr, send_back_addr, handler: handlers }) + #listen_failure { local_addr, send_back_addr }) => { #(#on_listen_failure_stmts)* } #from_swarm::NewListener( #new_listener { listener_id }) diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index 6fc494b1578..d964e2a103f 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -28,19 +28,12 @@ pub use listen_addresses::ListenAddresses; use crate::dial_opts::DialOpts; use crate::handler::{ConnectionHandler, IntoConnectionHandler}; -use crate::{AddressRecord, AddressScore, DialError}; +use crate::{AddressRecord, AddressScore, DialError, THandlerInEvent}; use libp2p_core::{ connection::ConnectionId, transport::ListenerId, ConnectedPoint, Multiaddr, PeerId, }; use std::{task::Context, task::Poll}; -/// Custom event that can be received by the [`ConnectionHandler`]. -pub(crate) type THandlerInEvent = - <::Handler as ConnectionHandler>::InEvent; - -pub(crate) type THandlerOutEvent = - <::Handler as ConnectionHandler>::OutEvent; - /// A [`NetworkBehaviour`] defines the behaviour of the local node on the network. /// /// In contrast to [`Transport`](libp2p_core::Transport) which defines **how** to send bytes on the @@ -184,7 +177,7 @@ pub trait NetworkBehaviour: 'static { &mut self, cx: &mut Context<'_>, params: &mut impl PollParameters, - ) -> Poll>; + ) -> Poll>>; } /// Parameters passed to `poll()`, that the `NetworkBehaviour` has access to. @@ -230,16 +223,8 @@ pub trait PollParameters { /// in whose context it is executing. /// /// [`Swarm`]: super::Swarm -// -// Note: `TInEvent` is needed to be able to implement -// [`NetworkBehaviourAction::map_in`], mapping the handler `InEvent` leaving the -// handler itself untouched. #[derive(Debug)] -pub enum NetworkBehaviourAction< - TOutEvent, - THandler: IntoConnectionHandler, - TInEvent = THandlerInEvent, -> { +pub enum NetworkBehaviourAction { /// Instructs the `Swarm` to return an event when it is being polled. GenerateEvent(TOutEvent), @@ -248,177 +233,13 @@ pub enum NetworkBehaviourAction< /// On success, [`NetworkBehaviour::on_swarm_event`] with `ConnectionEstablished` is invoked. /// On failure, [`NetworkBehaviour::on_swarm_event`] with `DialFailure` is invoked. /// - /// Note that the provided handler is returned to the [`NetworkBehaviour`] on connection failure - /// and connection closing. Thus it can be used to carry state, which otherwise would have to be - /// tracked in the [`NetworkBehaviour`] itself. E.g. a message destined to an unconnected peer - /// can be included in the handler, and thus directly send on connection success or extracted by - /// the [`NetworkBehaviour`] on connection failure. - /// - /// # Example carrying state in the handler - /// - /// ```rust - /// # use futures::executor::block_on; - /// # use futures::stream::StreamExt; - /// # use libp2p_core::connection::ConnectionId; - /// # use libp2p_core::identity; - /// # use libp2p_core::transport::{MemoryTransport, Transport}; - /// # use libp2p_core::upgrade::{self, DeniedUpgrade, InboundUpgrade, OutboundUpgrade}; - /// # use libp2p_core::PeerId; - /// # use libp2p_plaintext::PlainText2Config; - /// # use libp2p_swarm::{ - /// # FromSwarm, DialFailure, DialError, IntoConnectionHandler, KeepAlive, NegotiatedSubstream, - /// # NetworkBehaviour, NetworkBehaviourAction, PollParameters, ConnectionHandler, - /// # ConnectionHandlerEvent, ConnectionHandlerUpgrErr, SubstreamProtocol, Swarm, SwarmEvent, - /// # }; - /// # use libp2p_swarm::handler::ConnectionEvent; - /// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; - /// # use libp2p_yamux as yamux; - /// # use std::collections::VecDeque; - /// # use std::task::{Context, Poll}; - /// # use void::Void; - /// # - /// # let local_key = identity::Keypair::generate_ed25519(); - /// # let local_public_key = local_key.public(); - /// # let local_peer_id = PeerId::from(local_public_key.clone()); - /// # - /// # let transport = MemoryTransport::default() - /// # .upgrade(upgrade::Version::V1) - /// # .authenticate(PlainText2Config { local_public_key }) - /// # .multiplex(yamux::YamuxConfig::default()) - /// # .boxed(); - /// # - /// # let mut swarm = Swarm::with_threadpool_executor(transport, MyBehaviour::default(), local_peer_id); - /// # - /// // Super precious message that we should better not lose. - /// let message = PreciousMessage("My precious message".to_string()); - /// - /// // Unfortunately this peer is offline, thus sending our message to it will fail. - /// let offline_peer = PeerId::random(); - /// - /// // Let's send it anyways. We should get it back in case connecting to the peer fails. - /// swarm.behaviour_mut().send(offline_peer, message); - /// - /// block_on(async { - /// // As expected, sending failed. But great news, we got our message back. - /// matches!( - /// swarm.next().await.expect("Infinite stream"), - /// SwarmEvent::Behaviour(PreciousMessage(_)) - /// ); - /// }); - /// - /// #[derive(Default)] - /// struct MyBehaviour { - /// outbox_to_swarm: VecDeque>, - /// } - /// - /// impl MyBehaviour { - /// fn send(&mut self, peer_id: PeerId, msg: PreciousMessage) { - /// self.outbox_to_swarm - /// .push_back(NetworkBehaviourAction::Dial { - /// opts: DialOpts::peer_id(peer_id) - /// .condition(PeerCondition::Always) - /// .build(), - /// handler: MyHandler { message: Some(msg) }, - /// }); - /// } - /// } - /// # - /// impl NetworkBehaviour for MyBehaviour { - /// # type ConnectionHandler = MyHandler; - /// # type OutEvent = PreciousMessage; - /// # - /// # fn new_handler(&mut self) -> Self::ConnectionHandler { - /// # MyHandler { message: None } - /// # } - /// # - /// # - /// # fn on_connection_handler_event( - /// # &mut self, - /// # _: PeerId, - /// # _: ConnectionId, - /// # _: <::Handler as ConnectionHandler>::OutEvent, - /// # ) { - /// # unreachable!(); - /// # } - /// # - /// fn on_swarm_event( - /// &mut self, - /// event: FromSwarm, - /// ) { - /// // As expected, sending the message failed. But lucky us, we got the handler back, thus - /// // the precious message is not lost and we can return it back to the user. - /// if let FromSwarm::DialFailure(DialFailure { handler, .. }) = event { - /// let msg = handler.message.unwrap(); - /// self.outbox_to_swarm - /// .push_back(NetworkBehaviourAction::GenerateEvent(msg)) - /// } - /// } - /// # - /// # fn poll( - /// # &mut self, - /// # _: &mut Context<'_>, - /// # _: &mut impl PollParameters, - /// # ) -> Poll> { - /// # if let Some(action) = self.outbox_to_swarm.pop_front() { - /// # return Poll::Ready(action); - /// # } - /// # Poll::Pending - /// # } - /// } - /// - /// # struct MyHandler { - /// # message: Option, - /// # } - /// # - /// # impl ConnectionHandler for MyHandler { - /// # type InEvent = Void; - /// # type OutEvent = Void; - /// # type Error = Void; - /// # type InboundProtocol = DeniedUpgrade; - /// # type OutboundProtocol = DeniedUpgrade; - /// # type InboundOpenInfo = (); - /// # type OutboundOpenInfo = Void; - /// # - /// # fn listen_protocol( - /// # &self, - /// # ) -> SubstreamProtocol { - /// # SubstreamProtocol::new(DeniedUpgrade, ()) - /// # } - /// # - /// # fn on_behaviour_event(&mut self, _event: Self::InEvent) {} - /// # - /// # fn on_connection_event( - /// # &mut self, - /// # event: ConnectionEvent< - /// # Self::InboundProtocol, - /// # Self::OutboundProtocol, - /// # Self::InboundOpenInfo, - /// # Self::OutboundOpenInfo, - /// # >, - /// # ) {} - /// # - /// # fn connection_keep_alive(&self) -> KeepAlive { - /// # KeepAlive::Yes - /// # } - /// # - /// # fn poll( - /// # &mut self, - /// # _: &mut Context<'_>, - /// # ) -> Poll< - /// # ConnectionHandlerEvent< - /// # Self::OutboundProtocol, - /// # Self::OutboundOpenInfo, - /// # Self::OutEvent, - /// # Self::Error, - /// # >, - /// # > { - /// # todo!("If `Self::message.is_some()` send the message to the remote.") - /// # } - /// # } - /// # #[derive(Debug, PartialEq, Eq)] - /// # struct PreciousMessage(String); - /// ``` - Dial { opts: DialOpts, handler: THandler }, + /// The provided [`ConnectionId`] will be used throughout the connection's lifecycle to associate + /// events with it. This allows a [`NetworkBehaviour`] to identify a connection that resulted out + /// of its own dial request. + Dial { + opts: DialOpts, + connection_id: ConnectionId, + }, /// Instructs the `Swarm` to send an event to the handler dedicated to a /// connection with a peer. @@ -478,19 +299,21 @@ pub enum NetworkBehaviourAction< }, } -impl - NetworkBehaviourAction -{ +impl NetworkBehaviourAction { /// Map the handler event. pub fn map_in( self, f: impl FnOnce(TInEventOld) -> TInEventNew, - ) -> NetworkBehaviourAction { + ) -> NetworkBehaviourAction { match self { NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(e), - NetworkBehaviourAction::Dial { opts, handler } => { - NetworkBehaviourAction::Dial { opts, handler } - } + NetworkBehaviourAction::Dial { + opts, + connection_id, + } => NetworkBehaviourAction::Dial { + opts, + connection_id, + }, NetworkBehaviourAction::NotifyHandler { peer_id, handler, @@ -514,100 +337,20 @@ impl } } -impl NetworkBehaviourAction { +impl NetworkBehaviourAction { /// Map the event the swarm will return. - pub fn map_out(self, f: impl FnOnce(TOutEvent) -> E) -> NetworkBehaviourAction { - match self { - NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(f(e)), - NetworkBehaviourAction::Dial { opts, handler } => { - NetworkBehaviourAction::Dial { opts, handler } - } - NetworkBehaviourAction::NotifyHandler { - peer_id, - handler, - event, - } => NetworkBehaviourAction::NotifyHandler { - peer_id, - handler, - event, - }, - NetworkBehaviourAction::ReportObservedAddr { address, score } => { - NetworkBehaviourAction::ReportObservedAddr { address, score } - } - NetworkBehaviourAction::CloseConnection { - peer_id, - connection, - } => NetworkBehaviourAction::CloseConnection { - peer_id, - connection, - }, - } - } -} - -impl NetworkBehaviourAction -where - THandlerOld: IntoConnectionHandler, - ::Handler: ConnectionHandler, -{ - /// Map the handler. - pub fn map_handler( + pub fn map_out( self, - f: impl FnOnce(THandlerOld) -> THandlerNew, - ) -> NetworkBehaviourAction - where - THandlerNew: IntoConnectionHandler, - ::Handler: ConnectionHandler, - { + f: impl FnOnce(TOutEvent) -> E, + ) -> NetworkBehaviourAction { match self { - NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(e), - NetworkBehaviourAction::Dial { opts, handler } => NetworkBehaviourAction::Dial { + NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(f(e)), + NetworkBehaviourAction::Dial { opts, - handler: f(handler), - }, - NetworkBehaviourAction::NotifyHandler { - peer_id, - handler, - event, - } => NetworkBehaviourAction::NotifyHandler { - peer_id, - handler, - event, - }, - NetworkBehaviourAction::ReportObservedAddr { address, score } => { - NetworkBehaviourAction::ReportObservedAddr { address, score } - } - NetworkBehaviourAction::CloseConnection { - peer_id, - connection, - } => NetworkBehaviourAction::CloseConnection { - peer_id, - connection, - }, - } - } -} - -impl NetworkBehaviourAction -where - THandlerOld: IntoConnectionHandler, - ::Handler: ConnectionHandler, -{ - /// Map the handler and handler event. - pub fn map_handler_and_in( - self, - f_handler: impl FnOnce(THandlerOld) -> THandlerNew, - f_in_event: impl FnOnce(TInEventOld) -> TInEventNew, - ) -> NetworkBehaviourAction - where - THandlerNew: IntoConnectionHandler, - ::Handler: ConnectionHandler, - { - match self { - NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(e), - NetworkBehaviourAction::Dial { opts, handler } => NetworkBehaviourAction::Dial { + connection_id, + } => NetworkBehaviourAction::Dial { opts, - handler: f_handler(handler), + connection_id, }, NetworkBehaviourAction::NotifyHandler { peer_id, @@ -616,7 +359,7 @@ where } => NetworkBehaviourAction::NotifyHandler { peer_id, handler, - event: f_in_event(event), + event, }, NetworkBehaviourAction::ReportObservedAddr { address, score } => { NetworkBehaviourAction::ReportObservedAddr { address, score } @@ -672,13 +415,13 @@ pub enum FromSwarm<'a, Handler: IntoConnectionHandler> { AddressChange(AddressChange<'a>), /// Informs the behaviour that the dial to a known /// or unknown node failed. - DialFailure(DialFailure<'a, Handler>), + DialFailure(DialFailure<'a>), /// Informs the behaviour that an error /// happened on an incoming connection during its initial handshake. /// /// This can include, for example, an error during the handshake of the encryption layer, or the /// connection unexpectedly closed. - ListenFailure(ListenFailure<'a, Handler>), + ListenFailure(ListenFailure<'a>), /// Informs the behaviour that a new listener was created. NewListener(NewListener), /// Informs the behaviour that we have started listening on a new multiaddr. @@ -733,10 +476,10 @@ pub struct AddressChange<'a> { /// [`FromSwarm`] variant that informs the behaviour that the dial to a known /// or unknown node failed. #[derive(Clone, Copy)] -pub struct DialFailure<'a, Handler> { +pub struct DialFailure<'a> { pub peer_id: Option, - pub handler: Handler, pub error: &'a DialError, + pub connection_id: ConnectionId, } /// [`FromSwarm`] variant that informs the behaviour that an error @@ -745,10 +488,9 @@ pub struct DialFailure<'a, Handler> { /// This can include, for example, an error during the handshake of the encryption layer, or the /// connection unexpectedly closed. #[derive(Clone, Copy)] -pub struct ListenFailure<'a, Handler> { +pub struct ListenFailure<'a> { pub local_addr: &'a Multiaddr, pub send_back_addr: &'a Multiaddr, - pub handler: Handler, } /// [`FromSwarm`] variant that informs the behaviour that a new listener was created. @@ -804,7 +546,6 @@ pub struct ExpiredExternalAddr<'a> { impl<'a, Handler: IntoConnectionHandler> FromSwarm<'a, Handler> { fn map_handler( self, - map_into_handler: impl FnOnce(Handler) -> NewHandler, map_handler: impl FnOnce( ::Handler, ) -> ::Handler, @@ -812,13 +553,12 @@ impl<'a, Handler: IntoConnectionHandler> FromSwarm<'a, Handler> { where NewHandler: IntoConnectionHandler, { - self.maybe_map_handler(|h| Some(map_into_handler(h)), |h| Some(map_handler(h))) + self.maybe_map_handler(|h| Some(map_handler(h))) .expect("To return Some as all closures return Some.") } fn maybe_map_handler( self, - map_into_handler: impl FnOnce(Handler) -> Option, map_handler: impl FnOnce( ::Handler, ) -> Option<::Handler>, @@ -866,21 +606,19 @@ impl<'a, Handler: IntoConnectionHandler> FromSwarm<'a, Handler> { })), FromSwarm::DialFailure(DialFailure { peer_id, - handler, error, + connection_id, }) => Some(FromSwarm::DialFailure(DialFailure { peer_id, - handler: map_into_handler(handler)?, error, + connection_id, })), FromSwarm::ListenFailure(ListenFailure { local_addr, send_back_addr, - handler, }) => Some(FromSwarm::ListenFailure(ListenFailure { local_addr, send_back_addr, - handler: map_into_handler(handler)?, })), FromSwarm::NewListener(NewListener { listener_id }) => { Some(FromSwarm::NewListener(NewListener { listener_id })) diff --git a/swarm/src/behaviour/either.rs b/swarm/src/behaviour/either.rs index 073a0275548..b43ef73fbe8 100644 --- a/swarm/src/behaviour/either.rs +++ b/swarm/src/behaviour/either.rs @@ -20,6 +20,7 @@ use crate::behaviour::{self, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use crate::handler::either::IntoEitherHandler; +use crate::THandlerInEvent; use either::Either; use libp2p_core::{Multiaddr, PeerId}; use std::{task::Context, task::Poll}; @@ -49,20 +50,14 @@ where fn on_swarm_event(&mut self, event: behaviour::FromSwarm) { match self { - Either::Left(b) => b.on_swarm_event(event.map_handler( - |h| h.unwrap_left(), - |h| match h { - Either::Left(h) => h, - Either::Right(_) => unreachable!(), - }, - )), - Either::Right(b) => b.on_swarm_event(event.map_handler( - |h| h.unwrap_right(), - |h| match h { - Either::Right(h) => h, - Either::Left(_) => unreachable!(), - }, - )), + Either::Left(b) => b.on_swarm_event(event.map_handler(|h| match h { + Either::Left(h) => h, + Either::Right(_) => unreachable!(), + })), + Either::Right(b) => b.on_swarm_event(event.map_handler(|h| match h { + Either::Right(h) => h, + Either::Left(_) => unreachable!(), + })), } } @@ -87,14 +82,14 @@ where &mut self, cx: &mut Context<'_>, params: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { let event = match self { Either::Left(behaviour) => futures::ready!(behaviour.poll(cx, params)) .map_out(Either::Left) - .map_handler_and_in(IntoEitherHandler::Left, Either::Left), + .map_in(Either::Left), Either::Right(behaviour) => futures::ready!(behaviour.poll(cx, params)) .map_out(Either::Right) - .map_handler_and_in(IntoEitherHandler::Right, Either::Right), + .map_in(Either::Right), }; Poll::Ready(event) diff --git a/swarm/src/behaviour/toggle.rs b/swarm/src/behaviour/toggle.rs index ae198dc2bd3..6edcc3bd9ce 100644 --- a/swarm/src/behaviour/toggle.rs +++ b/swarm/src/behaviour/toggle.rs @@ -25,7 +25,7 @@ use crate::handler::{ IntoConnectionHandler, KeepAlive, ListenUpgradeError, SubstreamProtocol, }; use crate::upgrade::SendWrapper; -use crate::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; +use crate::{NetworkBehaviour, NetworkBehaviourAction, PollParameters, THandlerInEvent}; use either::Either; use libp2p_core::{ either::{EitherError, EitherOutput}, @@ -86,7 +86,7 @@ where fn on_swarm_event(&mut self, event: FromSwarm) { if let Some(behaviour) = &mut self.inner { - if let Some(event) = event.maybe_map_handler(|h| h.inner, |h| h.inner) { + if let Some(event) = event.maybe_map_handler(|h| h.inner) { behaviour.on_swarm_event(event); } } @@ -107,11 +107,9 @@ where &mut self, cx: &mut Context<'_>, params: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(inner) = self.inner.as_mut() { - inner.poll(cx, params).map(|action| { - action.map_handler(|h| ToggleIntoConnectionHandler { inner: Some(h) }) - }) + inner.poll(cx, params) } else { Poll::Pending } diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index cf2392ab4d3..60a96173030 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -21,7 +21,6 @@ use crate::connection::Connection; use crate::{ - behaviour::{THandlerInEvent, THandlerOutEvent}, connection::{ Connected, ConnectionError, ConnectionLimit, IncomingInfo, PendingConnectionError, PendingInboundConnectionError, PendingOutboundConnectionError, @@ -98,7 +97,7 @@ where >, /// The pending connections that are currently being negotiated. - pending: HashMap>, + pending: HashMap, /// Size of the task command buffer (per task). task_command_buffer_size: usize, @@ -184,11 +183,9 @@ impl EstablishedConnection { } } -struct PendingConnection { +struct PendingConnection { /// [`PeerId`] of the remote peer. peer_id: Option, - /// Handler to handle connection once no longer pending but established. - handler: THandler, endpoint: PendingPoint, /// When dropped, notifies the task which then knows to terminate. abort_notifier: Option>, @@ -196,7 +193,7 @@ struct PendingConnection { accepted_at: Instant, } -impl PendingConnection { +impl PendingConnection { fn is_for_same_remote_as(&self, other: PeerId) -> bool { self.peer_id.map_or(false, |peer| peer == other) } @@ -266,8 +263,6 @@ pub enum PoolEvent { id: ConnectionId, /// The error that occurred. error: PendingOutboundConnectionError, - /// The handler that was supposed to handle the connection. - handler: THandler, /// The (expected) peer of the failed connection. peer: Option, }, @@ -282,8 +277,6 @@ pub enum PoolEvent { local_addr: Multiaddr, /// The error that occurred. error: PendingInboundConnectionError, - /// The handler that was supposed to handle the connection. - handler: THandler, }, /// A node has produced an event. @@ -291,7 +284,7 @@ pub enum PoolEvent { id: ConnectionId, peer_id: PeerId, /// The produced event. - event: THandlerOutEvent, + event: <::Handler as ConnectionHandler>::OutEvent, }, /// The connection to a node has changed its address. @@ -344,7 +337,11 @@ where pub fn get_established( &mut self, id: ConnectionId, - ) -> Option<&mut EstablishedConnection>> { + ) -> Option< + &mut EstablishedConnection< + <::Handler as ConnectionHandler>::InEvent, + >, + > { self.established .values_mut() .find_map(|connections| connections.get_mut(&id)) @@ -434,21 +431,17 @@ where >, >, peer: Option, - handler: THandler, role_override: Endpoint, dial_concurrency_factor_override: Option, - ) -> Result { - if let Err(limit) = self.counters.check_max_pending_outgoing() { - return Err((limit, handler)); - }; + connection_id: ConnectionId, + ) -> Result<(), ConnectionLimit> { + self.counters.check_max_pending_outgoing()?; let dial = ConcurrentDial::new( dials, dial_concurrency_factor_override.unwrap_or(self.dial_concurrency_factor), ); - let connection_id = ConnectionId::next(); - let (abort_notifier, abort_receiver) = oneshot::channel(); self.spawn( @@ -468,13 +461,13 @@ where connection_id, PendingConnection { peer_id: peer, - handler, endpoint, abort_notifier: Some(abort_notifier), accepted_at: Instant::now(), }, ); - Ok(connection_id) + + Ok(()) } /// Adds a pending incoming connection to the pool in the form of a @@ -485,17 +478,14 @@ where pub fn add_incoming( &mut self, future: TFut, - handler: THandler, info: IncomingInfo<'_>, - ) -> Result + ) -> Result where TFut: Future> + Send + 'static, { let endpoint = info.create_connected_point(); - if let Err(limit) = self.counters.check_max_pending_incoming() { - return Err((limit, handler)); - } + self.counters.check_max_pending_incoming()?; let connection_id = ConnectionId::next(); @@ -516,7 +506,6 @@ where connection_id, PendingConnection { peer_id: None, - handler, endpoint: endpoint.into(), abort_notifier: Some(abort_notifier), accepted_at: Instant::now(), @@ -526,7 +515,11 @@ where } /// Polls the connection pool for events. - pub fn poll(&mut self, cx: &mut Context<'_>) -> Poll> + pub fn poll( + &mut self, + cx: &mut Context<'_>, + mut new_handler_fn: impl FnMut() -> THandler, + ) -> Poll> where THandler: IntoConnectionHandler + 'static, THandler::Handler: ConnectionHandler + Send, @@ -610,7 +603,6 @@ where } => { let PendingConnection { peer_id: expected_peer_id, - handler, endpoint, abort_notifier: _, accepted_at, @@ -713,7 +705,6 @@ where id, error: error .map(|t| vec![(endpoint.get_remote_address().clone(), t)]), - handler, peer: expected_peer_id.or(Some(obtained_peer_id)), }) } @@ -724,7 +715,6 @@ where return Poll::Ready(PoolEvent::PendingInboundConnectionError { id, error, - handler, send_back_addr, local_addr, }) @@ -749,7 +739,7 @@ where let connection = Connection::new( muxer, - handler.into_handler(&obtained_peer_id, &endpoint), + new_handler_fn().into_handler(&obtained_peer_id, &endpoint), self.substream_upgrade_protocol_override, self.max_negotiating_inbound_streams, ); @@ -776,7 +766,6 @@ where task::PendingConnectionEvent::PendingFailed { id, error } => { if let Some(PendingConnection { peer_id, - handler, endpoint, abort_notifier: _, accepted_at: _, // Ignoring the time it took for the connection to fail. @@ -789,7 +778,6 @@ where return Poll::Ready(PoolEvent::PendingOutboundConnectionError { id, error, - handler, peer: peer_id, }); } @@ -803,7 +791,6 @@ where return Poll::Ready(PoolEvent::PendingInboundConnectionError { id, error, - handler, send_back_addr, local_addr, }); diff --git a/swarm/src/dummy.rs b/swarm/src/dummy.rs index 4ec58581c2e..2a9ec75bccb 100644 --- a/swarm/src/dummy.rs +++ b/swarm/src/dummy.rs @@ -2,7 +2,9 @@ use crate::behaviour::{FromSwarm, NetworkBehaviour, NetworkBehaviourAction, Poll use crate::handler::{ ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, }; -use crate::{ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, SubstreamProtocol}; +use crate::{ + ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive, SubstreamProtocol, THandlerInEvent, +}; use libp2p_core::connection::ConnectionId; use libp2p_core::upgrade::DeniedUpgrade; use libp2p_core::PeerId; @@ -29,7 +31,7 @@ impl NetworkBehaviour for Behaviour { &mut self, _: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { Poll::Pending } diff --git a/swarm/src/keep_alive.rs b/swarm/src/keep_alive.rs index bd1ed812b8b..7e2c822fb31 100644 --- a/swarm/src/keep_alive.rs +++ b/swarm/src/keep_alive.rs @@ -3,6 +3,7 @@ use crate::handler::{ ConnectionEvent, ConnectionHandlerEvent, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, SubstreamProtocol, }; +use crate::THandlerInEvent; use libp2p_core::connection::ConnectionId; use libp2p_core::upgrade::DeniedUpgrade; use libp2p_core::PeerId; @@ -34,7 +35,7 @@ impl NetworkBehaviour for Behaviour { &mut self, _: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { Poll::Pending } diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index cf0b4c3b08a..522c911bbb2 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -91,6 +91,7 @@ pub mod derive_prelude { pub use crate::NetworkBehaviour; pub use crate::NetworkBehaviourAction; pub use crate::PollParameters; + pub use crate::THandlerInEvent; pub use futures::prelude as futures; pub use libp2p_core::connection::ConnectionId; pub use libp2p_core::either::EitherOutput; @@ -163,11 +164,11 @@ type THandler = ::ConnectionHandler; /// Custom event that can be received by the [`ConnectionHandler`] of the /// [`NetworkBehaviour`]. -type THandlerInEvent = +pub type THandlerInEvent = < as IntoConnectionHandler>::Handler as ConnectionHandler>::InEvent; /// Custom event that can be produced by the [`ConnectionHandler`] of the [`NetworkBehaviour`]. -type THandlerOutEvent = +pub type THandlerOutEvent = < as IntoConnectionHandler>::Handler as ConnectionHandler>::OutEvent; /// Custom error that can be produced by the [`ConnectionHandler`] of the [`NetworkBehaviour`]. @@ -503,14 +504,13 @@ where /// swarm.dial("/ip6/::1/tcp/12345".parse::().unwrap()); /// ``` pub fn dial(&mut self, opts: impl Into) -> Result<(), DialError> { - let handler = self.behaviour.new_handler(); - self.dial_with_handler(opts.into(), handler) + self.dial_with_id(opts.into(), ConnectionId::next()) } - fn dial_with_handler( + fn dial_with_id( &mut self, dial_opts: DialOpts, - handler: ::ConnectionHandler, + connection_id: ConnectionId, ) -> Result<(), DialError> { let peer_id = dial_opts .get_or_parse_peer_id() @@ -531,8 +531,8 @@ where self.behaviour .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id, - handler, error: &e, + connection_id, })); return Err(e); @@ -545,8 +545,8 @@ where self.behaviour .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id: Some(peer_id), - handler, error: &error, + connection_id, })); return Err(error); @@ -573,8 +573,8 @@ where self.behaviour .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id, - handler, error: &error, + connection_id, })); return Err(error); }; @@ -608,18 +608,18 @@ where match self.pool.add_outgoing( dials, peer_id, - handler, dial_opts.role_override(), dial_opts.dial_concurrency_override(), + connection_id, ) { - Ok(_connection_id) => Ok(()), - Err((connection_limit, handler)) => { + Ok(()) => Ok(()), + Err(connection_limit) => { let error = DialError::ConnectionLimit(connection_limit); self.behaviour .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id, - handler, error: &error, + connection_id, })); Err(error) @@ -819,9 +819,8 @@ where } } PoolEvent::PendingOutboundConnectionError { - id: _, + id: connection_id, error, - handler, peer, } => { let error = error.into(); @@ -829,8 +828,8 @@ where self.behaviour .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id: peer, - handler, error: &error, + connection_id, })); if let Some(peer) = peer { @@ -849,14 +848,12 @@ where send_back_addr, local_addr, error, - handler, } => { log::debug!("Incoming connection failed: {:?}", error); self.behaviour .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { local_addr: &local_addr, send_back_addr: &send_back_addr, - handler, })); return Some(SwarmEvent::IncomingConnectionError { local_addr, @@ -955,10 +952,8 @@ where local_addr, send_back_addr, } => { - let handler = self.behaviour.new_handler(); match self.pool.add_incoming( upgrade, - handler, IncomingInfo { local_addr: &local_addr, send_back_addr: &send_back_addr, @@ -970,12 +965,11 @@ where send_back_addr, }); } - Err((connection_limit, handler)) => { + Err(connection_limit) => { self.behaviour .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { local_addr: &local_addr, send_back_addr: &send_back_addr, - handler, })); log::warn!("Incoming connection rejected: {:?}", connection_limit); } @@ -1058,15 +1052,18 @@ where fn handle_behaviour_event( &mut self, - event: NetworkBehaviourAction, + event: NetworkBehaviourAction>, ) -> Option>> { match event { NetworkBehaviourAction::GenerateEvent(event) => { return Some(SwarmEvent::Behaviour(event)) } - NetworkBehaviourAction::Dial { opts, handler } => { + NetworkBehaviourAction::Dial { + opts, + connection_id, + } => { let peer_id = opts.get_or_parse_peer_id(); - if let Ok(()) = self.dial_with_handler(opts, handler) { + if let Ok(()) = self.dial_with_id(opts, connection_id) { if let Ok(Some(peer_id)) = peer_id { return Some(SwarmEvent::Dialing(peer_id)); } @@ -1212,7 +1209,7 @@ where } // Poll the known peers. - match this.pool.poll(cx) { + match this.pool.poll(cx, || this.behaviour.new_handler()) { Poll::Pending => {} Poll::Ready(pool_event) => { if let Some(swarm_event) = this.handle_pool_event(pool_event) { diff --git a/swarm/src/test.rs b/swarm/src/test.rs index d850a174bdd..87a7907bf03 100644 --- a/swarm/src/test.rs +++ b/swarm/src/test.rs @@ -24,7 +24,7 @@ use crate::behaviour::{ }; use crate::{ ConnectionHandler, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction, - PollParameters, + PollParameters, THandlerInEvent, }; use libp2p_core::{ connection::ConnectionId, multiaddr::Multiaddr, transport::ListenerId, ConnectedPoint, PeerId, @@ -47,7 +47,7 @@ where /// The next action to return from `poll`. /// /// An action is only returned once. - pub next_action: Option>, + pub next_action: Option>, } impl MockBehaviour @@ -84,7 +84,7 @@ where &mut self, _: &mut Context, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { self.next_action.take().map_or(Poll::Pending, Poll::Ready) } @@ -390,14 +390,14 @@ where } FromSwarm::DialFailure(DialFailure { peer_id, - handler, + connection_id, error, }) => { self.on_dial_failure.push(peer_id); self.inner .on_swarm_event(FromSwarm::DialFailure(DialFailure { peer_id, - handler, + connection_id, error, })); } @@ -481,7 +481,7 @@ where &mut self, cx: &mut Context, args: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { self.poll += 1; self.inner.poll(cx, args) } diff --git a/swarm/tests/swarm_derive.rs b/swarm/tests/swarm_derive.rs index 08f04081297..118b279bfc5 100644 --- a/swarm/tests/swarm_derive.rs +++ b/swarm/tests/swarm_derive.rs @@ -21,7 +21,7 @@ use futures::StreamExt; use libp2p_identify as identify; use libp2p_ping as ping; -use libp2p_swarm::{behaviour::FromSwarm, dummy, NetworkBehaviour, SwarmEvent}; +use libp2p_swarm::{behaviour::FromSwarm, dummy, NetworkBehaviour, SwarmEvent, THandlerInEvent}; use std::fmt::Debug; /// Small utility to check that a type implements `NetworkBehaviour`. @@ -401,7 +401,7 @@ fn custom_out_event_no_type_parameters() { &mut self, _ctx: &mut Context, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { Poll::Pending } From f6cf7514772e991f77f38af414d9f6e6d92c9903 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 14:20:49 +1100 Subject: [PATCH 07/41] Port dcutr protocol --- protocols/dcutr/src/behaviour_impl.rs | 148 +++++++++++++++---------- protocols/dcutr/src/handler.rs | 52 ++------- protocols/dcutr/src/handler/direct.rs | 18 +-- protocols/dcutr/src/handler/relayed.rs | 10 +- 4 files changed, 106 insertions(+), 122 deletions(-) diff --git a/protocols/dcutr/src/behaviour_impl.rs b/protocols/dcutr/src/behaviour_impl.rs index d4cae973da3..52e05d3c352 100644 --- a/protocols/dcutr/src/behaviour_impl.rs +++ b/protocols/dcutr/src/behaviour_impl.rs @@ -29,11 +29,12 @@ use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailu use libp2p_swarm::dial_opts::{self, DialOpts}; use libp2p_swarm::{ ConnectionHandler, ConnectionHandlerUpgrErr, ExternalAddresses, IntoConnectionHandler, - NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters, + NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters, THandlerInEvent, }; use std::collections::{HashMap, HashSet, VecDeque}; use std::task::{Context, Poll}; use thiserror::Error; +use void::Void; const MAX_NUMBER_OF_UPGRADE_ATTEMPTS: u8 = 3; @@ -67,7 +68,7 @@ pub enum Error { pub struct Behaviour { /// Queue of actions to return when polled. - queued_events: VecDeque>, + queued_events: VecDeque>>, /// All direct (non-relayed) connections. direct_connections: HashMap>, @@ -75,6 +76,10 @@ pub struct Behaviour { external_addresses: ExternalAddresses, local_peer_id: PeerId, + + direct_to_relayed_connections: HashMap, + + outgoing_direct_connection_attempts: HashMap<(ConnectionId, PeerId), u8>, } impl Behaviour { @@ -84,6 +89,8 @@ impl Behaviour { direct_connections: Default::default(), external_addresses: Default::default(), local_peer_id, + direct_to_relayed_connections: Default::default(), + outgoing_direct_connection_attempts: Default::default(), } } @@ -147,40 +154,57 @@ impl Behaviour { fn on_dial_failure( &mut self, DialFailure { - peer_id, handler, .. - }: DialFailure<::ConnectionHandler>, + peer_id, + connection_id: failed_direct_connection, + .. + }: DialFailure, ) { - if let handler::Prototype::DirectConnection { - relayed_connection_id, - role: handler::Role::Initiator { attempt }, - } = handler + let peer_id = if let Some(peer_id) = peer_id { + peer_id + } else { + return; + }; + + let relayed_connection_id = if let Some(relayed_connection_id) = self + .direct_to_relayed_connections + .get(&failed_direct_connection) { - let peer_id = peer_id.expect("Peer of `Prototype::DirectConnection` is always known."); - if attempt < MAX_NUMBER_OF_UPGRADE_ATTEMPTS { - self.queued_events - .push_back(NetworkBehaviourAction::NotifyHandler { - handler: NotifyHandler::One(relayed_connection_id), - peer_id, - event: Either::Left(handler::relayed::Command::Connect { - attempt: attempt + 1, - obs_addrs: self.observed_addreses(), - }), - }) - } else { - self.queued_events.extend([ - NetworkBehaviourAction::NotifyHandler { - peer_id, - handler: NotifyHandler::One(relayed_connection_id), - event: Either::Left( - handler::relayed::Command::UpgradeFinishedDontKeepAlive, - ), - }, - NetworkBehaviourAction::GenerateEvent(Event::DirectConnectionUpgradeFailed { - remote_peer_id: peer_id, - error: Error::Dial, + *relayed_connection_id + } else { + return; + }; + + let attempt = if let Some(attempt) = self + .outgoing_direct_connection_attempts + .get(&(relayed_connection_id, peer_id)) + { + *attempt + } else { + return; + }; + + if attempt < MAX_NUMBER_OF_UPGRADE_ATTEMPTS { + self.queued_events + .push_back(NetworkBehaviourAction::NotifyHandler { + handler: NotifyHandler::One(relayed_connection_id), + peer_id, + event: Either::Left(handler::relayed::Command::Connect { + attempt: attempt + 1, + obs_addrs: self.observed_addreses(), }), - ]); - } + }) + } else { + self.queued_events.extend([ + NetworkBehaviourAction::NotifyHandler { + peer_id, + handler: NotifyHandler::One(relayed_connection_id), + event: Either::Left(handler::relayed::Command::UpgradeFinishedDontKeepAlive), + }, + NetworkBehaviourAction::GenerateEvent(Event::DirectConnectionUpgradeFailed { + remote_peer_id: peer_id, + error: Error::Dial, + }), + ]); } } @@ -214,16 +238,26 @@ impl NetworkBehaviour for Behaviour { type OutEvent = Event; fn new_handler(&mut self) -> Self::ConnectionHandler { - handler::Prototype::UnknownConnection + handler::Prototype } fn on_connection_handler_event( &mut self, event_source: PeerId, - connection: ConnectionId, - handler_event: <::Handler as - ConnectionHandler>::OutEvent, + connection_id: ConnectionId, + handler_event: <::Handler as ConnectionHandler>::OutEvent, ) { + let relayed_connection_id = match handler_event.as_ref() { + Either::Left(_) => connection_id, + Either::Right(_) => match self.direct_to_relayed_connections.get(&connection_id) { + None => { + // If the connection ID is unknown to us, it means we didn't create it so ignore any event coming from it. + return; + } + Some(relayed_connection_id) => *relayed_connection_id, + }, + }; + match handler_event { Either::Left(handler::relayed::Event::InboundConnectRequest { inbound_connect, @@ -231,7 +265,7 @@ impl NetworkBehaviour for Behaviour { }) => { self.queued_events.extend([ NetworkBehaviourAction::NotifyHandler { - handler: NotifyHandler::One(connection), + handler: NotifyHandler::One(relayed_connection_id), peer_id: event_source, event: Either::Left(handler::relayed::Command::AcceptInboundConnect { inbound_connect, @@ -256,15 +290,17 @@ impl NetworkBehaviour for Behaviour { )); } Either::Left(handler::relayed::Event::InboundConnectNegotiated(remote_addrs)) => { + let maybe_direct_connection_id = ConnectionId::next(); + + self.direct_to_relayed_connections + .insert(maybe_direct_connection_id, relayed_connection_id); + self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(event_source) .addresses(remote_addrs) .condition(dial_opts::PeerCondition::Always) .build(), - handler: handler::Prototype::DirectConnection { - relayed_connection_id: connection, - role: handler::Role::Listener, - }, + connection_id: maybe_direct_connection_id, }); } Either::Left(handler::relayed::Event::OutboundNegotiationFailed { error }) => { @@ -276,27 +312,26 @@ impl NetworkBehaviour for Behaviour { }, )); } - Either::Left(handler::relayed::Event::OutboundConnectNegotiated { - remote_addrs, - attempt, - }) => { + Either::Left(handler::relayed::Event::OutboundConnectNegotiated { remote_addrs }) => { + let maybe_direct_connection_id = ConnectionId::next(); + + self.direct_to_relayed_connections + .insert(maybe_direct_connection_id, relayed_connection_id); + *self + .outgoing_direct_connection_attempts + .entry((maybe_direct_connection_id, event_source)) + .or_default() += 1; + self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(event_source) .condition(dial_opts::PeerCondition::Always) .addresses(remote_addrs) .override_role() .build(), - handler: handler::Prototype::DirectConnection { - relayed_connection_id: connection, - role: handler::Role::Initiator { attempt }, - }, + connection_id: maybe_direct_connection_id, }); } - Either::Right(Either::Left( - handler::direct::Event::DirectConnectionUpgradeSucceeded { - relayed_connection_id, - }, - )) => { + Either::Right(handler::direct::Event::DirectConnectionEstablished) => { self.queued_events.extend([ NetworkBehaviourAction::NotifyHandler { peer_id: event_source, @@ -312,7 +347,6 @@ impl NetworkBehaviour for Behaviour { ), ]); } - Either::Right(Either::Right(event)) => void::unreachable(event), }; } @@ -320,7 +354,7 @@ impl NetworkBehaviour for Behaviour { &mut self, _cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(event) = self.queued_events.pop_front() { return Poll::Ready(event); } diff --git a/protocols/dcutr/src/handler.rs b/protocols/dcutr/src/handler.rs index e854b395308..34392bde182 100644 --- a/protocols/dcutr/src/handler.rs +++ b/protocols/dcutr/src/handler.rs @@ -20,62 +20,30 @@ use crate::protocol; use either::Either; -use libp2p_core::connection::ConnectionId; -use libp2p_core::upgrade::{self, DeniedUpgrade}; +use libp2p_core::upgrade; use libp2p_core::{ConnectedPoint, PeerId}; -use libp2p_swarm::dummy; use libp2p_swarm::handler::SendWrapper; use libp2p_swarm::{ConnectionHandler, IntoConnectionHandler}; pub mod direct; pub mod relayed; -pub enum Prototype { - DirectConnection { - role: Role, - relayed_connection_id: ConnectionId, - }, - UnknownConnection, -} - -pub enum Role { - Initiator { attempt: u8 }, - Listener, -} +pub struct Prototype; impl IntoConnectionHandler for Prototype { - type Handler = Either>; + type Handler = Either; fn into_handler(self, _remote_peer_id: &PeerId, endpoint: &ConnectedPoint) -> Self::Handler { - match self { - Self::UnknownConnection => { - if endpoint.is_relayed() { - Either::Left(relayed::Handler::new(endpoint.clone())) - } else { - Either::Right(Either::Right(dummy::ConnectionHandler)) - } - } - Self::DirectConnection { - relayed_connection_id, - .. - } => { - assert!( - !endpoint.is_relayed(), - "`Prototype::DirectConnection` is never created for relayed connection." - ); - Either::Right(Either::Left(direct::Handler::new(relayed_connection_id))) - } + if endpoint.is_relayed() { + Either::Left(relayed::Handler::new(endpoint.clone())) + } else { + Either::Right(direct::Handler::default()) // This is a direct connection. What we don't know is whether it is the one we created or another one that happened accidentally. } } fn inbound_protocol(&self) -> ::InboundProtocol { - match self { - Prototype::UnknownConnection => upgrade::EitherUpgrade::A(SendWrapper( - upgrade::EitherUpgrade::A(protocol::inbound::Upgrade {}), - )), - Prototype::DirectConnection { .. } => { - upgrade::EitherUpgrade::A(SendWrapper(upgrade::EitherUpgrade::B(DeniedUpgrade))) - } - } + upgrade::EitherUpgrade::A(SendWrapper(upgrade::EitherUpgrade::A( + protocol::inbound::Upgrade {}, + ))) } } diff --git a/protocols/dcutr/src/handler/direct.rs b/protocols/dcutr/src/handler/direct.rs index 9e6759977ad..aab212483eb 100644 --- a/protocols/dcutr/src/handler/direct.rs +++ b/protocols/dcutr/src/handler/direct.rs @@ -20,7 +20,6 @@ //! [`ConnectionHandler`] handling direct connection upgraded through a relayed connection. -use libp2p_core::connection::ConnectionId; use libp2p_core::upgrade::DeniedUpgrade; use libp2p_swarm::handler::ConnectionEvent; use libp2p_swarm::{ @@ -32,23 +31,14 @@ use void::Void; #[derive(Debug)] pub enum Event { - DirectConnectionUpgradeSucceeded { relayed_connection_id: ConnectionId }, + DirectConnectionEstablished, } +#[derive(Default)] pub struct Handler { - relayed_connection_id: ConnectionId, reported: bool, } -impl Handler { - pub(crate) fn new(relayed_connection_id: ConnectionId) -> Self { - Self { - reported: false, - relayed_connection_id, - } - } -} - impl ConnectionHandler for Handler { type InEvent = void::Void; type OutEvent = Event; @@ -82,9 +72,7 @@ impl ConnectionHandler for Handler { if !self.reported { self.reported = true; return Poll::Ready(ConnectionHandlerEvent::Custom( - Event::DirectConnectionUpgradeSucceeded { - relayed_connection_id: self.relayed_connection_id, - }, + Event::DirectConnectionEstablished, )); } Poll::Pending diff --git a/protocols/dcutr/src/handler/relayed.rs b/protocols/dcutr/src/handler/relayed.rs index 301f2ee3d82..bb4732ee81a 100644 --- a/protocols/dcutr/src/handler/relayed.rs +++ b/protocols/dcutr/src/handler/relayed.rs @@ -91,7 +91,6 @@ pub enum Event { }, OutboundConnectNegotiated { remote_addrs: Vec, - attempt: u8, }, } @@ -117,13 +116,9 @@ impl fmt::Debug for Event { .debug_struct("Event::OutboundNegotiationFailed") .field("error", error) .finish(), - Event::OutboundConnectNegotiated { - remote_addrs, - attempt, - } => f + Event::OutboundConnectNegotiated { remote_addrs } => f .debug_struct("Event::OutboundConnectNegotiated") .field("remote_addrs", remote_addrs) - .field("attempt", attempt) .finish(), } } @@ -194,7 +189,7 @@ impl Handler { &mut self, FullyNegotiatedOutbound { protocol: protocol::outbound::Connect { obs_addrs }, - info: attempt, + .. }: FullyNegotiatedOutbound< ::OutboundProtocol, ::OutboundOpenInfo, @@ -207,7 +202,6 @@ impl Handler { self.queued_events.push_back(ConnectionHandlerEvent::Custom( Event::OutboundConnectNegotiated { remote_addrs: obs_addrs, - attempt, }, )); } From 08c51608ddcef1a9201a4fdad3ae85859d31f435 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 14:20:55 +1100 Subject: [PATCH 08/41] Port relay protocol --- protocols/relay/src/behaviour.rs | 13 ++-- protocols/relay/src/priv_client.rs | 110 ++++++++++++++++------------- 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/protocols/relay/src/behaviour.rs b/protocols/relay/src/behaviour.rs index b478de2e70b..22d45b38608 100644 --- a/protocols/relay/src/behaviour.rs +++ b/protocols/relay/src/behaviour.rs @@ -33,13 +33,14 @@ use libp2p_core::PeerId; use libp2p_swarm::behaviour::{ConnectionClosed, FromSwarm}; use libp2p_swarm::{ ConnectionHandlerUpgrErr, ExternalAddresses, NetworkBehaviour, NetworkBehaviourAction, - NotifyHandler, PollParameters, + NotifyHandler, PollParameters, THandlerInEvent, }; use std::collections::{hash_map, HashMap, HashSet, VecDeque}; use std::num::NonZeroU32; use std::ops::Add; use std::task::{Context, Poll}; use std::time::Duration; +use void::Void; /// Configuration for the relay [`Behaviour`]. /// @@ -643,7 +644,7 @@ impl NetworkBehaviour for Behaviour { &mut self, _cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { if let Some(action) = self.queued_actions.pop_front() { return Poll::Ready(action.build(self.local_peer_id, &self.external_addresses)); } @@ -746,7 +747,7 @@ impl Add for CircuitId { /// before being returned in [`Behaviour::poll`]. #[allow(clippy::large_enum_variant)] enum Action { - Done(NetworkBehaviourAction), + Done(NetworkBehaviourAction>), AcceptReservationPrototype { inbound_reservation_req: inbound_hop::ReservationReq, handler: NotifyHandler, @@ -754,8 +755,8 @@ enum Action { }, } -impl From> for Action { - fn from(action: NetworkBehaviourAction) -> Self { +impl From>> for Action { + fn from(action: NetworkBehaviourAction>) -> Self { Self::Done(action) } } @@ -765,7 +766,7 @@ impl Action { self, local_peer_id: PeerId, external_addresses: &ExternalAddresses, - ) -> NetworkBehaviourAction { + ) -> NetworkBehaviourAction> { match self { Action::Done(action) => action, Action::AcceptReservationPrototype { diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index 7bb79f5d246..e0e9e512426 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -38,7 +38,7 @@ use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm use libp2p_swarm::dial_opts::DialOpts; use libp2p_swarm::{ ConnectionHandlerUpgrErr, NegotiatedSubstream, NetworkBehaviour, NetworkBehaviourAction, - NotifyHandler, PollParameters, + NotifyHandler, PollParameters, THandlerInEvent, }; use std::collections::{hash_map, HashMap, VecDeque}; use std::io::{Error, ErrorKind, IoSlice}; @@ -46,6 +46,7 @@ use std::ops::DerefMut; use std::pin::Pin; use std::task::{Context, Poll}; use transport::Transport; +use void::Void; /// The events produced by the client `Behaviour`. #[derive(Debug)] @@ -100,7 +101,9 @@ pub struct Behaviour { directly_connected_peers: HashMap>, /// Queue of actions to return when polled. - queued_actions: VecDeque, + queued_actions: VecDeque>>, + + pending_handler_commands: HashMap, } /// Create a new client relay [`Behaviour`] with it's corresponding [`Transport`]. @@ -111,6 +114,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) { from_transport, directly_connected_peers: Default::default(), queued_actions: Default::default(), + pending_handler_commands: Default::default(), }; (transport, behaviour) } @@ -174,6 +178,15 @@ impl NetworkBehaviour for Behaviour { .or_default() .push(connection_id); } + + if let Some(event) = self.pending_handler_commands.remove(&connection_id) { + self.queued_actions + .push_back(NetworkBehaviourAction::NotifyHandler { + peer_id, + handler: NotifyHandler::One(connection_id), + event: Either::Left(event), + }) + } } FromSwarm::ConnectionClosed(connection_closed) => { self.on_connection_closed(connection_closed) @@ -202,61 +215,57 @@ impl NetworkBehaviour for Behaviour { Either::Right(v) => void::unreachable(v), }; - match handler_event { - handler::Event::ReservationReqAccepted { renewal, limit } => self - .queued_actions - .push_back(Event::ReservationReqAccepted { + let event = match handler_event { + handler::Event::ReservationReqAccepted { renewal, limit } => { + Event::ReservationReqAccepted { relay_peer_id: event_source, renewal, limit, - }), + } + } handler::Event::ReservationReqFailed { renewal, error } => { - self.queued_actions.push_back(Event::ReservationReqFailed { + Event::ReservationReqFailed { relay_peer_id: event_source, renewal, error, - }) + } } handler::Event::OutboundCircuitEstablished { limit } => { - self.queued_actions - .push_back(Event::OutboundCircuitEstablished { - relay_peer_id: event_source, - limit, - }) + Event::OutboundCircuitEstablished { + relay_peer_id: event_source, + limit, + } } - handler::Event::OutboundCircuitReqFailed { error } => { - self.queued_actions - .push_back(Event::OutboundCircuitReqFailed { - relay_peer_id: event_source, - error, - }) + handler::Event::OutboundCircuitReqFailed { error } => Event::OutboundCircuitReqFailed { + relay_peer_id: event_source, + error, + }, + handler::Event::InboundCircuitEstablished { src_peer_id, limit } => { + Event::InboundCircuitEstablished { src_peer_id, limit } } - handler::Event::InboundCircuitEstablished { src_peer_id, limit } => self - .queued_actions - .push_back(Event::InboundCircuitEstablished { src_peer_id, limit }), - handler::Event::InboundCircuitReqFailed { error } => { - self.queued_actions - .push_back(Event::InboundCircuitReqFailed { - relay_peer_id: event_source, - error, - }) + handler::Event::InboundCircuitReqFailed { error } => Event::InboundCircuitReqFailed { + relay_peer_id: event_source, + error, + }, + handler::Event::InboundCircuitReqDenied { src_peer_id } => { + Event::InboundCircuitReqDenied { src_peer_id } } - handler::Event::InboundCircuitReqDenied { src_peer_id } => self - .queued_actions - .push_back(Event::InboundCircuitReqDenied { src_peer_id }), - handler::Event::InboundCircuitReqDenyFailed { src_peer_id, error } => self - .queued_actions - .push_back(Event::InboundCircuitReqDenyFailed { src_peer_id, error }), - } + handler::Event::InboundCircuitReqDenyFailed { src_peer_id, error } => { + Event::InboundCircuitReqDenyFailed { src_peer_id, error } + } + }; + + self.queued_actions + .push_back(NetworkBehaviourAction::GenerateEvent(event)) } fn poll( &mut self, cx: &mut Context<'_>, _poll_parameters: &mut impl PollParameters, - ) -> Poll> { - if let Some(event) = self.queued_actions.pop_front() { - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); + ) -> Poll>> { + if let Some(action) = self.queued_actions.pop_front() { + return Poll::Ready(action); } let action = match ready!(self.from_transport.poll_next_unpin(cx)) { @@ -276,16 +285,16 @@ impl NetworkBehaviour for Behaviour { event: Either::Left(handler::In::Reserve { to_listener }), }, None => { - let handler = handler::Prototype::new( - self.local_peer_id, - Some(handler::In::Reserve { to_listener }), - ); + let relayed_connection_id = ConnectionId::next(); + + self.pending_handler_commands + .insert(relayed_connection_id, handler::In::Reserve { to_listener }); NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(relay_peer_id) .addresses(vec![relay_addr]) .extend_addresses_through_behaviour() .build(), - handler, + connection_id: relayed_connection_id, } } } @@ -311,19 +320,22 @@ impl NetworkBehaviour for Behaviour { }), }, None => { - let handler = handler::Prototype::new( - self.local_peer_id, - Some(handler::In::EstablishCircuit { + let connection_id = ConnectionId::next(); + + self.pending_handler_commands.insert( + connection_id, + handler::In::EstablishCircuit { send_back, dst_peer_id, - }), + }, ); + NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(relay_peer_id) .addresses(vec![relay_addr]) .extend_addresses_through_behaviour() .build(), - handler, + connection_id, } } } From 8e0d7d844ef859d69b522562c6491375d50dd7b5 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 16 Jan 2023 14:26:10 +1100 Subject: [PATCH 09/41] Add changelog entry to swarm --- swarm/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 25969d67052..904c442ad72 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -15,11 +15,18 @@ - Remove type parameter from `PendingOutboundConnectionError` and `PendingInboundConnectionError`. These two types are always used with `std::io::Error`. See [PR 3272]. +- Remove `handler` field from `NetworkBehaviourAction::Dial`. + Instead of constructing the handler early, you now get to pass a `ConnectionId`. + `ConnectionId` are `Copy` and will be used throughout the entire lifetime of the connection to report events. + This allows you to send events to a very specific connection, much like you previously could directly set state in the handler. + See [PR 3328]. + [PR 3170]: https://github.com/libp2p/rust-libp2p/pull/3170 [PR 3134]: https://github.com/libp2p/rust-libp2p/pull/3134 [PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153 [PR 3264]: https://github.com/libp2p/rust-libp2p/pull/3264 [PR 3272]: https://github.com/libp2p/rust-libp2p/pull/3272 +[PR 3328]: https://github.com/libp2p/rust-libp2p/pull/3328 # 0.41.1 From 1beec8cb3755932f26e02434aa712cb74ae2467f Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:05:09 +1100 Subject: [PATCH 10/41] Remove ordering functionality from `ConnectionId` --- core/src/connection.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/connection.rs b/core/src/connection.rs index 3949921c3e1..3496848aa2e 100644 --- a/core/src/connection.rs +++ b/core/src/connection.rs @@ -24,7 +24,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; static NEXT_CONNECTION_ID: AtomicUsize = AtomicUsize::new(0); /// Connection identifier. -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ConnectionId(usize); impl ConnectionId { From de9f152c65eaa750ddc25d1b97957e63a94993b8 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:09:57 +1100 Subject: [PATCH 11/41] Remove unnecessary visibility qualifiers --- swarm/src/dial_opts.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/swarm/src/dial_opts.rs b/swarm/src/dial_opts.rs index acc1b69a617..4137a4a4d67 100644 --- a/swarm/src/dial_opts.rs +++ b/swarm/src/dial_opts.rs @@ -36,7 +36,7 @@ use std::num::NonZeroU8; /// /// - [`DialOpts::unknown_peer_id`] dialing an unknown peer #[derive(Debug)] -pub struct DialOpts(pub(super) Opts); +pub struct DialOpts(Opts); impl DialOpts { /// Dial a known peer. @@ -200,7 +200,7 @@ impl From for DialOpts { /// - [`DialOpts::peer_id`] dialing a known peer /// - [`DialOpts::unknown_peer_id`] dialing an unknown peer #[derive(Debug)] -pub(super) enum Opts { +enum Opts { WithPeerId(WithPeerId), WithPeerIdWithAddresses(WithPeerIdWithAddresses), WithoutPeerIdWithAddress(WithoutPeerIdWithAddress), @@ -208,10 +208,10 @@ pub(super) enum Opts { #[derive(Debug)] pub struct WithPeerId { - pub(crate) peer_id: PeerId, - pub(crate) condition: PeerCondition, - pub(crate) role_override: Endpoint, - pub(crate) dial_concurrency_factor_override: Option, + peer_id: PeerId, + condition: PeerCondition, + role_override: Endpoint, + dial_concurrency_factor_override: Option, } impl WithPeerId { @@ -262,12 +262,12 @@ impl WithPeerId { #[derive(Debug)] pub struct WithPeerIdWithAddresses { - pub(crate) peer_id: PeerId, - pub(crate) condition: PeerCondition, - pub(crate) addresses: Vec, - pub(crate) extend_addresses_through_behaviour: bool, - pub(crate) role_override: Endpoint, - pub(crate) dial_concurrency_factor_override: Option, + peer_id: PeerId, + condition: PeerCondition, + addresses: Vec, + extend_addresses_through_behaviour: bool, + role_override: Endpoint, + dial_concurrency_factor_override: Option, } impl WithPeerIdWithAddresses { @@ -323,8 +323,8 @@ impl WithoutPeerId { #[derive(Debug)] pub struct WithoutPeerIdWithAddress { - pub(crate) address: Multiaddr, - pub(crate) role_override: Endpoint, + address: Multiaddr, + role_override: Endpoint, } impl WithoutPeerIdWithAddress { From 7692c770a84e5eed08ba7b69fa743369e3b5a943 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:11:32 +1100 Subject: [PATCH 12/41] Convert `DialOpts` to struct variant --- swarm/src/dial_opts.rs | 141 +++++++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 54 deletions(-) diff --git a/swarm/src/dial_opts.rs b/swarm/src/dial_opts.rs index 4137a4a4d67..1fb49ca1bd4 100644 --- a/swarm/src/dial_opts.rs +++ b/swarm/src/dial_opts.rs @@ -36,7 +36,9 @@ use std::num::NonZeroU8; /// /// - [`DialOpts::unknown_peer_id`] dialing an unknown peer #[derive(Debug)] -pub struct DialOpts(Opts); +pub struct DialOpts { + inner: Opts, +} impl DialOpts { /// Dial a known peer. @@ -74,11 +76,15 @@ impl DialOpts { /// Get the [`PeerId`] specified in a [`DialOpts`] if any. pub fn get_peer_id(&self) -> Option { match self { - DialOpts(Opts::WithPeerId(WithPeerId { peer_id, .. })) => Some(*peer_id), - DialOpts(Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - peer_id, .. - })) => Some(*peer_id), - DialOpts(Opts::WithoutPeerIdWithAddress(_)) => None, + DialOpts { + inner: Opts::WithPeerId(WithPeerId { peer_id, .. }), + } => Some(*peer_id), + DialOpts { + inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { peer_id, .. }), + } => Some(*peer_id), + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(_), + } => None, } } @@ -93,13 +99,15 @@ impl DialOpts { /// See . pub(crate) fn get_or_parse_peer_id(&self) -> Result, Multihash> { match self { - DialOpts(Opts::WithPeerId(WithPeerId { peer_id, .. })) => Ok(Some(*peer_id)), - DialOpts(Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - peer_id, .. - })) => Ok(Some(*peer_id)), - DialOpts(Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { - address, .. - })) => { + DialOpts { + inner: Opts::WithPeerId(WithPeerId { peer_id, .. }), + } => Ok(Some(*peer_id)), + DialOpts { + inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { peer_id, .. }), + } => Ok(Some(*peer_id)), + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { address, .. }), + } => { let peer_id = address .iter() .last() @@ -119,64 +127,83 @@ impl DialOpts { pub(crate) fn get_addresses(&self) -> Vec { match self { - DialOpts(Opts::WithPeerId(WithPeerId { .. })) => vec![], - DialOpts(Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - addresses, .. - })) => addresses.clone(), - DialOpts(Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { - address, .. - })) => vec![address.clone()], + DialOpts { + inner: Opts::WithPeerId(WithPeerId { .. }), + } => vec![], + DialOpts { + inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { addresses, .. }), + } => addresses.clone(), + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { address, .. }), + } => vec![address.clone()], } } pub(crate) fn extend_addresses_through_behaviour(&self) -> bool { match self { - DialOpts(Opts::WithPeerId(WithPeerId { .. })) => true, - DialOpts(Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - extend_addresses_through_behaviour, - .. - })) => *extend_addresses_through_behaviour, - DialOpts(Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. })) => true, + DialOpts { + inner: Opts::WithPeerId(WithPeerId { .. }), + } => true, + DialOpts { + inner: + Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { + extend_addresses_through_behaviour, + .. + }), + } => *extend_addresses_through_behaviour, + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. }), + } => true, } } pub(crate) fn peer_condition(&self) -> PeerCondition { match self { - DialOpts( - Opts::WithPeerId(WithPeerId { condition, .. }) - | Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { condition, .. }), - ) => *condition, - DialOpts(Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. })) => { - PeerCondition::Always - } + DialOpts { + inner: + Opts::WithPeerId(WithPeerId { condition, .. }) + | Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { condition, .. }), + } => *condition, + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. }), + } => PeerCondition::Always, } } pub(crate) fn dial_concurrency_override(&self) -> Option { match self { - DialOpts(Opts::WithPeerId(WithPeerId { - dial_concurrency_factor_override, - .. - })) => *dial_concurrency_factor_override, - DialOpts(Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - dial_concurrency_factor_override, - .. - })) => *dial_concurrency_factor_override, - DialOpts(Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. })) => None, + DialOpts { + inner: + Opts::WithPeerId(WithPeerId { + dial_concurrency_factor_override, + .. + }), + } => *dial_concurrency_factor_override, + DialOpts { + inner: + Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { + dial_concurrency_factor_override, + .. + }), + } => *dial_concurrency_factor_override, + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. }), + } => None, } } pub(crate) fn role_override(&self) -> Endpoint { match self { - DialOpts(Opts::WithPeerId(WithPeerId { role_override, .. })) => *role_override, - DialOpts(Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - role_override, - .. - })) => *role_override, - DialOpts(Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { - role_override, - .. - })) => *role_override, + DialOpts { + inner: Opts::WithPeerId(WithPeerId { role_override, .. }), + } => *role_override, + DialOpts { + inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { role_override, .. }), + } => *role_override, + DialOpts { + inner: + Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { role_override, .. }), + } => *role_override, } } } @@ -256,7 +283,9 @@ impl WithPeerId { /// Addresses to dial the peer are retrieved via /// [`NetworkBehaviour::addresses_of_peer`](crate::behaviour::NetworkBehaviour::addresses_of_peer). pub fn build(self) -> DialOpts { - DialOpts(Opts::WithPeerId(self)) + DialOpts { + inner: Opts::WithPeerId(self), + } } } @@ -304,7 +333,9 @@ impl WithPeerIdWithAddresses { /// Build the final [`DialOpts`]. pub fn build(self) -> DialOpts { - DialOpts(Opts::WithPeerIdWithAddresses(self)) + DialOpts { + inner: Opts::WithPeerIdWithAddresses(self), + } } } @@ -340,7 +371,9 @@ impl WithoutPeerIdWithAddress { } /// Build the final [`DialOpts`]. pub fn build(self) -> DialOpts { - DialOpts(Opts::WithoutPeerIdWithAddress(self)) + DialOpts { + inner: Opts::WithoutPeerIdWithAddress(self), + } } } From b492236f8cdeb6a0bc82326b454777b9b8fb6321 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:25:27 +1100 Subject: [PATCH 13/41] Eagerly set defaults in `DialOpts` Instead of carrying around an enum and parsing its contents later, directly set the correct values as we construct the final `DialOpts`. --- swarm/src/dial_opts.rs | 170 +++++++++++++---------------------------- 1 file changed, 51 insertions(+), 119 deletions(-) diff --git a/swarm/src/dial_opts.rs b/swarm/src/dial_opts.rs index 1fb49ca1bd4..5362ad99e91 100644 --- a/swarm/src/dial_opts.rs +++ b/swarm/src/dial_opts.rs @@ -37,7 +37,12 @@ use std::num::NonZeroU8; /// - [`DialOpts::unknown_peer_id`] dialing an unknown peer #[derive(Debug)] pub struct DialOpts { - inner: Opts, + peer_id: Option, + condition: PeerCondition, + addresses: Vec, + extend_addresses_through_behaviour: bool, + role_override: Endpoint, + dial_concurrency_factor_override: Option, } impl DialOpts { @@ -75,17 +80,7 @@ impl DialOpts { /// Get the [`PeerId`] specified in a [`DialOpts`] if any. pub fn get_peer_id(&self) -> Option { - match self { - DialOpts { - inner: Opts::WithPeerId(WithPeerId { peer_id, .. }), - } => Some(*peer_id), - DialOpts { - inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { peer_id, .. }), - } => Some(*peer_id), - DialOpts { - inner: Opts::WithoutPeerIdWithAddress(_), - } => None, - } + self.peer_id } /// Retrieves the [`PeerId`] from the [`DialOpts`] if specified or otherwise tries to parse it @@ -98,113 +93,48 @@ impl DialOpts { /// /// See . pub(crate) fn get_or_parse_peer_id(&self) -> Result, Multihash> { - match self { - DialOpts { - inner: Opts::WithPeerId(WithPeerId { peer_id, .. }), - } => Ok(Some(*peer_id)), - DialOpts { - inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { peer_id, .. }), - } => Ok(Some(*peer_id)), - DialOpts { - inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { address, .. }), - } => { - let peer_id = address - .iter() - .last() - .and_then(|p| { - if let Protocol::P2p(ma) = p { - Some(PeerId::try_from(ma)) - } else { - None - } - }) - .transpose()?; - - Ok(peer_id) - } + if let Some(peer_id) = self.peer_id { + return Ok(Some(peer_id)) } + + let first_address = match self.addresses.first() { + Some(first_address) => first_address, + None => return Ok(None) + }; + + let maybe_peer_id = first_address + .iter() + .last() + .and_then(|p| { + if let Protocol::P2p(ma) = p { + Some(PeerId::try_from(ma)) + } else { + None + } + }) + .transpose()?; + + Ok(maybe_peer_id) } pub(crate) fn get_addresses(&self) -> Vec { - match self { - DialOpts { - inner: Opts::WithPeerId(WithPeerId { .. }), - } => vec![], - DialOpts { - inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { addresses, .. }), - } => addresses.clone(), - DialOpts { - inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { address, .. }), - } => vec![address.clone()], - } + self.addresses.clone() } pub(crate) fn extend_addresses_through_behaviour(&self) -> bool { - match self { - DialOpts { - inner: Opts::WithPeerId(WithPeerId { .. }), - } => true, - DialOpts { - inner: - Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - extend_addresses_through_behaviour, - .. - }), - } => *extend_addresses_through_behaviour, - DialOpts { - inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. }), - } => true, - } + self.extend_addresses_through_behaviour } pub(crate) fn peer_condition(&self) -> PeerCondition { - match self { - DialOpts { - inner: - Opts::WithPeerId(WithPeerId { condition, .. }) - | Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { condition, .. }), - } => *condition, - DialOpts { - inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. }), - } => PeerCondition::Always, - } + self.condition } pub(crate) fn dial_concurrency_override(&self) -> Option { - match self { - DialOpts { - inner: - Opts::WithPeerId(WithPeerId { - dial_concurrency_factor_override, - .. - }), - } => *dial_concurrency_factor_override, - DialOpts { - inner: - Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { - dial_concurrency_factor_override, - .. - }), - } => *dial_concurrency_factor_override, - DialOpts { - inner: Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { .. }), - } => None, - } + self.dial_concurrency_factor_override } pub(crate) fn role_override(&self) -> Endpoint { - match self { - DialOpts { - inner: Opts::WithPeerId(WithPeerId { role_override, .. }), - } => *role_override, - DialOpts { - inner: Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses { role_override, .. }), - } => *role_override, - DialOpts { - inner: - Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { role_override, .. }), - } => *role_override, - } + self.role_override } } @@ -220,19 +150,6 @@ impl From for DialOpts { } } -/// Internal options type. -/// -/// Not to be constructed manually. Use either of the below instead: -/// -/// - [`DialOpts::peer_id`] dialing a known peer -/// - [`DialOpts::unknown_peer_id`] dialing an unknown peer -#[derive(Debug)] -enum Opts { - WithPeerId(WithPeerId), - WithPeerIdWithAddresses(WithPeerIdWithAddresses), - WithoutPeerIdWithAddress(WithoutPeerIdWithAddress), -} - #[derive(Debug)] pub struct WithPeerId { peer_id: PeerId, @@ -284,7 +201,12 @@ impl WithPeerId { /// [`NetworkBehaviour::addresses_of_peer`](crate::behaviour::NetworkBehaviour::addresses_of_peer). pub fn build(self) -> DialOpts { DialOpts { - inner: Opts::WithPeerId(self), + peer_id: Some(self.peer_id), + condition: self.condition, + addresses: vec![], + extend_addresses_through_behaviour: false, + role_override: self.role_override, + dial_concurrency_factor_override: self.dial_concurrency_factor_override, } } } @@ -334,7 +256,12 @@ impl WithPeerIdWithAddresses { /// Build the final [`DialOpts`]. pub fn build(self) -> DialOpts { DialOpts { - inner: Opts::WithPeerIdWithAddresses(self), + peer_id: Some(self.peer_id), + condition: self.condition, + addresses: self.addresses, + extend_addresses_through_behaviour: self.extend_addresses_through_behaviour, + role_override: self.role_override, + dial_concurrency_factor_override: self.dial_concurrency_factor_override, } } } @@ -372,7 +299,12 @@ impl WithoutPeerIdWithAddress { /// Build the final [`DialOpts`]. pub fn build(self) -> DialOpts { DialOpts { - inner: Opts::WithoutPeerIdWithAddress(self), + peer_id: None, + condition: PeerCondition::Always, + addresses: vec![self.address], + extend_addresses_through_behaviour: false, + role_override: self.role_override, + dial_concurrency_factor_override: None, } } } From 951a0dcca78c134a6045f4b45ace81db148ac747 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:39:57 +1100 Subject: [PATCH 14/41] Make `ConnectionId` part of `DialOpts` --- protocols/autonat/src/behaviour/as_server.rs | 1 - protocols/dcutr/src/behaviour_impl.rs | 36 +++++++++----------- protocols/floodsub/src/layer.rs | 2 -- protocols/gossipsub/src/behaviour.rs | 2 -- protocols/identify/src/behaviour.rs | 1 - protocols/kad/src/behaviour.rs | 3 -- protocols/relay/src/priv_client.rs | 28 +++++++-------- protocols/request-response/src/lib.rs | 1 - swarm-derive/src/lib.rs | 4 +-- swarm/src/behaviour.rs | 27 ++++----------- swarm/src/dial_opts.rs | 18 ++++++++-- swarm/src/lib.rs | 16 +++------ 12 files changed, 57 insertions(+), 82 deletions(-) diff --git a/protocols/autonat/src/behaviour/as_server.rs b/protocols/autonat/src/behaviour/as_server.rs index ea1e59821d4..f250fc855be 100644 --- a/protocols/autonat/src/behaviour/as_server.rs +++ b/protocols/autonat/src/behaviour/as_server.rs @@ -138,7 +138,6 @@ impl<'a> HandleInnerEvent for AsServer<'a> { ) .addresses(addrs) .build(), - connection_id: ConnectionId::next(), }, ]) } diff --git a/protocols/dcutr/src/behaviour_impl.rs b/protocols/dcutr/src/behaviour_impl.rs index 52e05d3c352..1f77bbb67fb 100644 --- a/protocols/dcutr/src/behaviour_impl.rs +++ b/protocols/dcutr/src/behaviour_impl.rs @@ -290,18 +290,17 @@ impl NetworkBehaviour for Behaviour { )); } Either::Left(handler::relayed::Event::InboundConnectNegotiated(remote_addrs)) => { - let maybe_direct_connection_id = ConnectionId::next(); + let opts = DialOpts::peer_id(event_source) + .addresses(remote_addrs) + .condition(dial_opts::PeerCondition::Always) + .build(); + + let maybe_direct_connection_id = opts.connection_id(); self.direct_to_relayed_connections .insert(maybe_direct_connection_id, relayed_connection_id); - - self.queued_events.push_back(NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(event_source) - .addresses(remote_addrs) - .condition(dial_opts::PeerCondition::Always) - .build(), - connection_id: maybe_direct_connection_id, - }); + self.queued_events + .push_back(NetworkBehaviourAction::Dial { opts }); } Either::Left(handler::relayed::Event::OutboundNegotiationFailed { error }) => { self.queued_events @@ -313,7 +312,13 @@ impl NetworkBehaviour for Behaviour { )); } Either::Left(handler::relayed::Event::OutboundConnectNegotiated { remote_addrs }) => { - let maybe_direct_connection_id = ConnectionId::next(); + let opts = DialOpts::peer_id(event_source) + .condition(dial_opts::PeerCondition::Always) + .addresses(remote_addrs) + .override_role() + .build(); + + let maybe_direct_connection_id = opts.connection_id(); self.direct_to_relayed_connections .insert(maybe_direct_connection_id, relayed_connection_id); @@ -321,15 +326,8 @@ impl NetworkBehaviour for Behaviour { .outgoing_direct_connection_attempts .entry((maybe_direct_connection_id, event_source)) .or_default() += 1; - - self.queued_events.push_back(NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(event_source) - .condition(dial_opts::PeerCondition::Always) - .addresses(remote_addrs) - .override_role() - .build(), - connection_id: maybe_direct_connection_id, - }); + self.queued_events + .push_back(NetworkBehaviourAction::Dial { opts }); } Either::Right(handler::direct::Event::DirectConnectionEstablished) => { self.queued_events.extend([ diff --git a/protocols/floodsub/src/layer.rs b/protocols/floodsub/src/layer.rs index 109ebdca84a..e82557ae2a6 100644 --- a/protocols/floodsub/src/layer.rs +++ b/protocols/floodsub/src/layer.rs @@ -105,7 +105,6 @@ impl Floodsub { if self.target_peers.insert(peer_id) { self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - connection_id: ConnectionId::next(), }); } } @@ -327,7 +326,6 @@ impl Floodsub { if self.target_peers.contains(&peer_id) { self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - connection_id: ConnectionId::next(), }); } } diff --git a/protocols/gossipsub/src/behaviour.rs b/protocols/gossipsub/src/behaviour.rs index 3962433f56b..12692348281 100644 --- a/protocols/gossipsub/src/behaviour.rs +++ b/protocols/gossipsub/src/behaviour.rs @@ -1136,7 +1136,6 @@ where debug!("Connecting to explicit peer {:?}", peer_id); self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(*peer_id).build(), - connection_id: ConnectionId::next(), }); } } @@ -1636,7 +1635,6 @@ where // dial peer self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - connection_id: ConnectionId::next(), }); } } diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 64e765f6e22..7cb9e7d6226 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -201,7 +201,6 @@ impl Behaviour { self.events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(p).build(), - connection_id: ConnectionId::next(), }); } } diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index 48cf8dd9695..acf77ddda58 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -573,7 +573,6 @@ where kbucket::InsertResult::Pending { disconnected } => { self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(disconnected.into_preimage()).build(), - connection_id: ConnectionId::next(), }); RoutingUpdate::Pending } @@ -1223,7 +1222,6 @@ where self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(disconnected.into_preimage()) .build(), - connection_id: ConnectionId::next(), }) } } @@ -2387,7 +2385,6 @@ where query.inner.pending_rpcs.push((peer_id, event)); self.queued_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(peer_id).build(), - connection_id: ConnectionId::next(), }); } } diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index e0e9e512426..bc1a19d94e7 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -285,17 +285,15 @@ impl NetworkBehaviour for Behaviour { event: Either::Left(handler::In::Reserve { to_listener }), }, None => { - let relayed_connection_id = ConnectionId::next(); + let opts = DialOpts::peer_id(relay_peer_id) + .addresses(vec![relay_addr]) + .extend_addresses_through_behaviour() + .build(); + let relayed_connection_id = opts.connection_id(); self.pending_handler_commands .insert(relayed_connection_id, handler::In::Reserve { to_listener }); - NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(relay_peer_id) - .addresses(vec![relay_addr]) - .extend_addresses_through_behaviour() - .build(), - connection_id: relayed_connection_id, - } + NetworkBehaviourAction::Dial { opts } } } } @@ -320,7 +318,11 @@ impl NetworkBehaviour for Behaviour { }), }, None => { - let connection_id = ConnectionId::next(); + let opts = DialOpts::peer_id(relay_peer_id) + .addresses(vec![relay_addr]) + .extend_addresses_through_behaviour() + .build(); + let connection_id = opts.connection_id(); self.pending_handler_commands.insert( connection_id, @@ -330,13 +332,7 @@ impl NetworkBehaviour for Behaviour { }, ); - NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(relay_peer_id) - .addresses(vec![relay_addr]) - .extend_addresses_through_behaviour() - .build(), - connection_id, - } + NetworkBehaviourAction::Dial { opts } } } } diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index a5e3ae95b82..8861e74175f 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -420,7 +420,6 @@ where if let Some(request) = self.try_send_request(peer, request) { self.pending_events.push_back(NetworkBehaviourAction::Dial { opts: DialOpts::peer_id(*peer).build(), - connection_id: ConnectionId::next(), }); self.pending_outbound_requests .entry(*peer) diff --git a/swarm-derive/src/lib.rs b/swarm-derive/src/lib.rs index 9ff690b323b..0072bbb7dce 100644 --- a/swarm-derive/src/lib.rs +++ b/swarm-derive/src/lib.rs @@ -612,8 +612,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { loop { match #trait_to_impl::poll(&mut self.#field, cx, poll_params) { #generate_event_match_arm - std::task::Poll::Ready(#network_behaviour_action::Dial { opts, connection_id }) => { - return std::task::Poll::Ready(#network_behaviour_action::Dial { opts, connection_id }); + std::task::Poll::Ready(#network_behaviour_action::Dial { opts }) => { + return std::task::Poll::Ready(#network_behaviour_action::Dial { opts }); } std::task::Poll::Ready(#network_behaviour_action::NotifyHandler { peer_id, handler, event }) => { return std::task::Poll::Ready(#network_behaviour_action::NotifyHandler { diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index d964e2a103f..e9bcb69e386 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -233,13 +233,10 @@ pub enum NetworkBehaviourAction { /// On success, [`NetworkBehaviour::on_swarm_event`] with `ConnectionEstablished` is invoked. /// On failure, [`NetworkBehaviour::on_swarm_event`] with `DialFailure` is invoked. /// - /// The provided [`ConnectionId`] will be used throughout the connection's lifecycle to associate - /// events with it. This allows a [`NetworkBehaviour`] to identify a connection that resulted out - /// of its own dial request. - Dial { - opts: DialOpts, - connection_id: ConnectionId, - }, + /// [`DialOpts`] provides access to the [`ConnectionId`] via [`DialOpts::connection_id`]. + /// This [`ConnectionId`] will be used throughout the connection's lifecycle to associate events with it. + /// This allows a [`NetworkBehaviour`] to identify a connection that resulted out of its own dial request. + Dial { opts: DialOpts }, /// Instructs the `Swarm` to send an event to the handler dedicated to a /// connection with a peer. @@ -307,13 +304,7 @@ impl NetworkBehaviourAction { ) -> NetworkBehaviourAction { match self { NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(e), - NetworkBehaviourAction::Dial { - opts, - connection_id, - } => NetworkBehaviourAction::Dial { - opts, - connection_id, - }, + NetworkBehaviourAction::Dial { opts } => NetworkBehaviourAction::Dial { opts }, NetworkBehaviourAction::NotifyHandler { peer_id, handler, @@ -345,13 +336,7 @@ impl NetworkBehaviourAction { ) -> NetworkBehaviourAction { match self { NetworkBehaviourAction::GenerateEvent(e) => NetworkBehaviourAction::GenerateEvent(f(e)), - NetworkBehaviourAction::Dial { - opts, - connection_id, - } => NetworkBehaviourAction::Dial { - opts, - connection_id, - }, + NetworkBehaviourAction::Dial { opts } => NetworkBehaviourAction::Dial { opts }, NetworkBehaviourAction::NotifyHandler { peer_id, handler, diff --git a/swarm/src/dial_opts.rs b/swarm/src/dial_opts.rs index 5362ad99e91..591ef157b41 100644 --- a/swarm/src/dial_opts.rs +++ b/swarm/src/dial_opts.rs @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use libp2p_core::connection::Endpoint; +use libp2p_core::connection::{ConnectionId, Endpoint}; use libp2p_core::multiaddr::Protocol; use libp2p_core::multihash::Multihash; use libp2p_core::{Multiaddr, PeerId}; @@ -43,6 +43,7 @@ pub struct DialOpts { extend_addresses_through_behaviour: bool, role_override: Endpoint, dial_concurrency_factor_override: Option, + connection_id: ConnectionId, } impl DialOpts { @@ -83,6 +84,14 @@ impl DialOpts { self.peer_id } + /// Get the [`ConnectionId`] of this dial attempt. + /// + /// All future events of this dial will be associated with this ID. + /// See [`DialFailure`](crate::DialFailure) and [`ConnectionEstablished`](crate::behaviour::ConnectionEstablished). + pub fn connection_id(&self) -> ConnectionId { + self.connection_id + } + /// Retrieves the [`PeerId`] from the [`DialOpts`] if specified or otherwise tries to parse it /// from the multihash in the `/p2p` part of the address, if present. /// @@ -94,12 +103,12 @@ impl DialOpts { /// See . pub(crate) fn get_or_parse_peer_id(&self) -> Result, Multihash> { if let Some(peer_id) = self.peer_id { - return Ok(Some(peer_id)) + return Ok(Some(peer_id)); } let first_address = match self.addresses.first() { Some(first_address) => first_address, - None => return Ok(None) + None => return Ok(None), }; let maybe_peer_id = first_address @@ -207,6 +216,7 @@ impl WithPeerId { extend_addresses_through_behaviour: false, role_override: self.role_override, dial_concurrency_factor_override: self.dial_concurrency_factor_override, + connection_id: ConnectionId::next(), } } } @@ -262,6 +272,7 @@ impl WithPeerIdWithAddresses { extend_addresses_through_behaviour: self.extend_addresses_through_behaviour, role_override: self.role_override, dial_concurrency_factor_override: self.dial_concurrency_factor_override, + connection_id: ConnectionId::next(), } } } @@ -305,6 +316,7 @@ impl WithoutPeerIdWithAddress { extend_addresses_through_behaviour: false, role_override: self.role_override, dial_concurrency_factor_override: None, + connection_id: ConnectionId::next(), } } } diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 522c911bbb2..4c47ec757b9 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -504,18 +504,15 @@ where /// swarm.dial("/ip6/::1/tcp/12345".parse::().unwrap()); /// ``` pub fn dial(&mut self, opts: impl Into) -> Result<(), DialError> { - self.dial_with_id(opts.into(), ConnectionId::next()) + self._dial(opts.into()) } - fn dial_with_id( - &mut self, - dial_opts: DialOpts, - connection_id: ConnectionId, - ) -> Result<(), DialError> { + fn _dial(&mut self, dial_opts: DialOpts) -> Result<(), DialError> { let peer_id = dial_opts .get_or_parse_peer_id() .map_err(DialError::InvalidPeerId)?; let condition = dial_opts.peer_condition(); + let connection_id = dial_opts.connection_id(); let should_dial = match (condition, peer_id) { (PeerCondition::Always, _) => true, @@ -1058,12 +1055,9 @@ where NetworkBehaviourAction::GenerateEvent(event) => { return Some(SwarmEvent::Behaviour(event)) } - NetworkBehaviourAction::Dial { - opts, - connection_id, - } => { + NetworkBehaviourAction::Dial { opts } => { let peer_id = opts.get_or_parse_peer_id(); - if let Ok(()) = self.dial_with_id(opts, connection_id) { + if let Ok(()) = self._dial(opts) { if let Ok(Some(peer_id)) = peer_id { return Some(SwarmEvent::Dialing(peer_id)); } From 41e49a5fedaeeec4d19068095d99da06f6b5759d Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:40:52 +1100 Subject: [PATCH 15/41] Inline `_dial` --- swarm/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 4c47ec757b9..fb7bc647eca 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -504,10 +504,8 @@ where /// swarm.dial("/ip6/::1/tcp/12345".parse::().unwrap()); /// ``` pub fn dial(&mut self, opts: impl Into) -> Result<(), DialError> { - self._dial(opts.into()) - } + let dial_opts = opts.into(); - fn _dial(&mut self, dial_opts: DialOpts) -> Result<(), DialError> { let peer_id = dial_opts .get_or_parse_peer_id() .map_err(DialError::InvalidPeerId)?; @@ -1057,7 +1055,7 @@ where } NetworkBehaviourAction::Dial { opts } => { let peer_id = opts.get_or_parse_peer_id(); - if let Ok(()) = self._dial(opts) { + if let Ok(()) = self.dial(opts) { if let Ok(Some(peer_id)) = peer_id { return Some(SwarmEvent::Dialing(peer_id)); } From 3547b53dd5a7c5ad883aaa89a9fc55025cf4b3a5 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:42:26 +1100 Subject: [PATCH 16/41] Rustfmt --- swarm/src/dial_opts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swarm/src/dial_opts.rs b/swarm/src/dial_opts.rs index 5362ad99e91..5cbb5370d18 100644 --- a/swarm/src/dial_opts.rs +++ b/swarm/src/dial_opts.rs @@ -94,12 +94,12 @@ impl DialOpts { /// See . pub(crate) fn get_or_parse_peer_id(&self) -> Result, Multihash> { if let Some(peer_id) = self.peer_id { - return Ok(Some(peer_id)) + return Ok(Some(peer_id)); } let first_address = match self.addresses.first() { Some(first_address) => first_address, - None => return Ok(None) + None => return Ok(None), }; let maybe_peer_id = first_address From 75b30ac00315468dfa884524fdd46e1739b2be5b Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 17 Jan 2023 15:44:14 +1100 Subject: [PATCH 17/41] Fix wrong default --- swarm/src/dial_opts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm/src/dial_opts.rs b/swarm/src/dial_opts.rs index 5cbb5370d18..eb375c6ce74 100644 --- a/swarm/src/dial_opts.rs +++ b/swarm/src/dial_opts.rs @@ -204,7 +204,7 @@ impl WithPeerId { peer_id: Some(self.peer_id), condition: self.condition, addresses: vec![], - extend_addresses_through_behaviour: false, + extend_addresses_through_behaviour: true, role_override: self.role_override, dial_concurrency_factor_override: self.dial_concurrency_factor_override, } From 42c9758c6c12e922a6c380b323b07ba07e0de83a Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 18 Jan 2023 22:11:29 +1100 Subject: [PATCH 18/41] Expand changelog entry --- swarm/CHANGELOG.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 0000e6263e8..681cdeb204b 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -18,9 +18,33 @@ - Remove `ConnectionId::new`. Manually creating `ConnectionId`s is now unsupported. See [PR 3327]. - Remove `handler` field from `NetworkBehaviourAction::Dial`. - Instead of constructing the handler early, you now get to pass a `ConnectionId`. - `ConnectionId` are `Copy` and will be used throughout the entire lifetime of the connection to report events. + Instead of constructing the handler early, you can now access the `ConnectionId` of the future connection on `DialOpts`. + `ConnectionId`s are `Copy` and will be used throughout the entire lifetime of the connection to report events. This allows you to send events to a very specific connection, much like you previously could directly set state in the handler. + + Removing the `handler` field also reduces the type parameters of `NetworkBehaviourAction` from three to two. + The third one used to be defaulted to the `InEvent` of the `ConnectionHandler`. + You now have to manually specify that where you previously had to specify the `ConnectionHandler`. + This very likely will trigger **convoluted compile errors** about traits not being implemented. + + Within `NetworkBehaviourAction::poll`, the easiest way to migrate is to do this (in the example of `libp2p-floodsub`): + ```diff + --- a/protocols/floodsub/src/layer.rs + +++ b/protocols/floodsub/src/layer.rs + @@ -472,7 +465,7 @@ impl NetworkBehaviour for Floodsub { + &mut self, + _: &mut Context<'_>, + _: &mut impl PollParameters, + - ) -> Poll> { + + ) -> Poll>> { + ``` + + In other words: + + |Search|Replace| + |---|---| + |`NetworkBehaviourAction`|`NetworkBehaviourAction>`| + See [PR 3328]. [PR 3170]: https://github.com/libp2p/rust-libp2p/pull/3170 From 14b9841902685ff8c92686749b34f6bf8a779b46 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 18 Jan 2023 22:11:48 +1100 Subject: [PATCH 19/41] Move most important changelog entry to the top --- swarm/CHANGELOG.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 681cdeb204b..a8fbfd1723d 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,22 +1,5 @@ # 0.42.0 [unreleased] -- Update to `libp2p-core` `v0.39.0`. - -- Removed deprecated Swarm constructors. For transition notes see [0.41.0](#0.41.0). See [PR 3170]. -- Deprecate functions on `PollParameters` in preparation for `PollParameters` to be removed entirely eventually. See [PR 3153]. - -- Add `estblished_in` to `SwarmEvent::ConnectionEstablished`. See [PR 3134]. - -- Remove deprecated `inject_*` methods from `NetworkBehaviour` and `ConnectionHandler`. - see [PR 3264]. - -- Update to `libp2p-swarm-derive` `v0.32.0`. - -- Remove type parameter from `PendingOutboundConnectionError` and `PendingInboundConnectionError`. - These two types are always used with `std::io::Error`. See [PR 3272]. - -- Remove `ConnectionId::new`. Manually creating `ConnectionId`s is now unsupported. See [PR 3327]. - - Remove `handler` field from `NetworkBehaviourAction::Dial`. Instead of constructing the handler early, you can now access the `ConnectionId` of the future connection on `DialOpts`. `ConnectionId`s are `Copy` and will be used throughout the entire lifetime of the connection to report events. @@ -26,7 +9,7 @@ The third one used to be defaulted to the `InEvent` of the `ConnectionHandler`. You now have to manually specify that where you previously had to specify the `ConnectionHandler`. This very likely will trigger **convoluted compile errors** about traits not being implemented. - + Within `NetworkBehaviourAction::poll`, the easiest way to migrate is to do this (in the example of `libp2p-floodsub`): ```diff --- a/protocols/floodsub/src/layer.rs @@ -38,15 +21,32 @@ - ) -> Poll> { + ) -> Poll>> { ``` - + In other words: |Search|Replace| - |---|---| + |---|---| |`NetworkBehaviourAction`|`NetworkBehaviourAction>`| See [PR 3328]. +- Update to `libp2p-core` `v0.39.0`. + +- Removed deprecated Swarm constructors. For transition notes see [0.41.0](#0.41.0). See [PR 3170]. +- Deprecate functions on `PollParameters` in preparation for `PollParameters` to be removed entirely eventually. See [PR 3153]. + +- Add `estblished_in` to `SwarmEvent::ConnectionEstablished`. See [PR 3134]. + +- Remove deprecated `inject_*` methods from `NetworkBehaviour` and `ConnectionHandler`. + see [PR 3264]. + +- Update to `libp2p-swarm-derive` `v0.32.0`. + +- Remove type parameter from `PendingOutboundConnectionError` and `PendingInboundConnectionError`. + These two types are always used with `std::io::Error`. See [PR 3272]. + +- Remove `ConnectionId::new`. Manually creating `ConnectionId`s is now unsupported. See [PR 3327]. + [PR 3170]: https://github.com/libp2p/rust-libp2p/pull/3170 [PR 3134]: https://github.com/libp2p/rust-libp2p/pull/3134 [PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153 From 1a3a1009fd2b0854cf88c087fe96606c2d7ab2b3 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 18 Jan 2023 22:13:59 +1100 Subject: [PATCH 20/41] Add more text to changelog entry --- swarm/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index a8fbfd1723d..b8e3f9d1a74 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -28,6 +28,9 @@ |---|---| |`NetworkBehaviourAction`|`NetworkBehaviourAction>`| + If you reference `NetworkBehaviourAction` somewhere else as well, + you may have to fill in the type of `ConnectionHandler::InEvent` manually as the 2nd parameter. + See [PR 3328]. - Update to `libp2p-core` `v0.39.0`. From 5535395ec51a7998c3fcf137f458127882ddbfa6 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 18 Jan 2023 22:15:21 +1100 Subject: [PATCH 21/41] Fix formatting --- protocols/ping/src/lib.rs | 3 ++- protocols/rendezvous/src/server.rs | 3 +-- protocols/request-response/src/lib.rs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 8f575e29a95..d675eb9c89b 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -49,7 +49,8 @@ use handler::Handler; pub use handler::{Config, Failure, Success}; use libp2p_core::PeerId; use libp2p_swarm::{ - behaviour::FromSwarm, ConnectionId, NetworkBehaviour, NetworkBehaviourAction, PollParameters, THandlerInEvent, + behaviour::FromSwarm, ConnectionId, NetworkBehaviour, NetworkBehaviourAction, PollParameters, + THandlerInEvent, }; use std::{ collections::VecDeque, diff --git a/protocols/rendezvous/src/server.rs b/protocols/rendezvous/src/server.rs index 14781a929f0..099b5979da9 100644 --- a/protocols/rendezvous/src/server.rs +++ b/protocols/rendezvous/src/server.rs @@ -31,8 +31,7 @@ use libp2p_core::PeerId; use libp2p_swarm::behaviour::FromSwarm; use libp2p_swarm::{ CloseConnection, ConnectionId, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, - PollParameters, - THandlerInEvent, + PollParameters, THandlerInEvent, }; use std::collections::{HashMap, HashSet, VecDeque}; use std::iter::FromIterator; diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index 4f92acde52a..97513d6a145 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -75,8 +75,7 @@ use libp2p_swarm::{ behaviour::{AddressChange, ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}, dial_opts::DialOpts, ConnectionId, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, - PollParameters, - THandlerInEvent, + PollParameters, THandlerInEvent, }; use smallvec::SmallVec; use std::{ From c0a7d2a22b67fd42937339f8c1aa31e10b2fe375 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 24 Jan 2023 12:31:42 +1100 Subject: [PATCH 22/41] Remove unnecessary `..` --- protocols/gossipsub/src/behaviour/tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protocols/gossipsub/src/behaviour/tests.rs b/protocols/gossipsub/src/behaviour/tests.rs index 5329ab5a1e1..948867e0a1a 100644 --- a/protocols/gossipsub/src/behaviour/tests.rs +++ b/protocols/gossipsub/src/behaviour/tests.rs @@ -1392,7 +1392,7 @@ fn test_explicit_peer_gets_connected() { .events .iter() .filter(|e| match e { - NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id() == Some(peer), + NetworkBehaviourAction::Dial { opts } => opts.get_peer_id() == Some(peer), _ => false, }) .count(); @@ -1433,7 +1433,7 @@ fn test_explicit_peer_reconnects() { gs.events .iter() .filter(|e| match e { - NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id() == Some(*peer), + NetworkBehaviourAction::Dial { opts } => opts.get_peer_id() == Some(*peer), _ => false, }) .count(), @@ -1448,7 +1448,7 @@ fn test_explicit_peer_reconnects() { gs.events .iter() .filter(|e| match e { - NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id() == Some(*peer), + NetworkBehaviourAction::Dial { opts } => opts.get_peer_id() == Some(*peer), _ => false, }) .count() @@ -1828,7 +1828,7 @@ fn test_connect_to_px_peers_on_handle_prune() { .events .iter() .filter_map(|e| match e { - NetworkBehaviourAction::Dial { opts, .. } => opts.get_peer_id(), + NetworkBehaviourAction::Dial { opts } => opts.get_peer_id(), _ => None, }) .collect(); From 9a420e4b94ff50b3ed38a8f7382036f4b712c6f5 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 26 Jan 2023 17:04:47 +1100 Subject: [PATCH 23/41] Don't use else block if we return in the previous one --- swarm/src/lib.rs | 74 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 6a64b4c10ab..9979f7c569c 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -767,50 +767,50 @@ where self.banned_peer_connections.insert(id); self.pool.disconnect(peer_id); return Some(SwarmEvent::BannedPeer { peer_id, endpoint }); - } else { - let num_established = NonZeroU32::new( - u32::try_from(other_established_connection_ids.len() + 1).unwrap(), - ) - .expect("n + 1 is always non-zero; qed"); - let non_banned_established = other_established_connection_ids - .into_iter() - .filter(|conn_id| !self.banned_peer_connections.contains(conn_id)) - .count(); + } - log::debug!( + let num_established = NonZeroU32::new( + u32::try_from(other_established_connection_ids.len() + 1).unwrap(), + ) + .expect("n + 1 is always non-zero; qed"); + let non_banned_established = other_established_connection_ids + .into_iter() + .filter(|conn_id| !self.banned_peer_connections.contains(conn_id)) + .count(); + + log::debug!( "Connection established: {:?} {:?}; Total (peer): {}. Total non-banned (peer): {}", peer_id, endpoint, num_established, non_banned_established + 1, ); - let failed_addresses = concurrent_dial_errors - .as_ref() - .map(|es| { - es.iter() - .map(|(a, _)| a) - .cloned() - .collect::>() - }) - .unwrap_or_default(); - self.behaviour - .on_swarm_event(FromSwarm::ConnectionEstablished( - behaviour::ConnectionEstablished { - peer_id, - connection_id: id, - endpoint: &endpoint, - failed_addresses: &failed_addresses, - other_established: non_banned_established, - }, - )); - return Some(SwarmEvent::ConnectionEstablished { - peer_id, - num_established, - endpoint, - concurrent_dial_errors, - established_in, - }); - } + let failed_addresses = concurrent_dial_errors + .as_ref() + .map(|es| { + es.iter() + .map(|(a, _)| a) + .cloned() + .collect::>() + }) + .unwrap_or_default(); + self.behaviour + .on_swarm_event(FromSwarm::ConnectionEstablished( + behaviour::ConnectionEstablished { + peer_id, + connection_id: id, + endpoint: &endpoint, + failed_addresses: &failed_addresses, + other_established: non_banned_established, + }, + )); + return Some(SwarmEvent::ConnectionEstablished { + peer_id, + num_established, + endpoint, + concurrent_dial_errors, + established_in, + }); } PoolEvent::PendingOutboundConnectionError { id: connection_id, From f5f37ab3a2f78a25bf9ecc41cea92d2e41f629bb Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 26 Jan 2023 17:12:38 +1100 Subject: [PATCH 24/41] Remove closure in favor of spawning connection from the outside --- core/src/muxing/boxed.rs | 6 +++ swarm/src/connection/pool.rs | 98 ++++++++++++++++++------------------ swarm/src/lib.rs | 15 +++++- 3 files changed, 68 insertions(+), 51 deletions(-) diff --git a/core/src/muxing/boxed.rs b/core/src/muxing/boxed.rs index 99f7a87c6a5..e909fb9fbf1 100644 --- a/core/src/muxing/boxed.rs +++ b/core/src/muxing/boxed.rs @@ -13,6 +13,12 @@ pub struct StreamMuxerBox { inner: Pin + Send>>, } +impl fmt::Debug for StreamMuxerBox { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StreamMuxerBox").finish_non_exhaustive() + } +} + /// Abstract type for asynchronous reading and writing. /// /// A [`SubstreamBox`] erases the concrete type it is given and only retains its `AsyncRead` diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index b12a2d3985f..dd8eda322f7 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -225,10 +225,7 @@ pub enum PoolEvent { id: ConnectionId, peer_id: PeerId, endpoint: ConnectedPoint, - /// List of other connections to the same peer. - /// - /// Note: Does not include the connection reported through this event. - other_established_connection_ids: Vec, + connection: StreamMuxerBox, /// [`Some`] when the new connection is an outgoing connection. /// Addresses are dialed in parallel. Contains the addresses and errors /// of dial attempts that failed before the one successful dial. @@ -516,12 +513,53 @@ where Ok(connection_id) } - /// Polls the connection pool for events. - pub fn poll( + pub fn spawn_connection( &mut self, - cx: &mut Context<'_>, - mut new_handler_fn: impl FnMut() -> THandler, - ) -> Poll> + id: ConnectionId, + obtained_peer_id: PeerId, + endpoint: &ConnectedPoint, + muxer: StreamMuxerBox, + handler: ::Handler, + ) { + let conns = self.established.entry(obtained_peer_id).or_default(); + self.counters.inc_established(endpoint); + + let (command_sender, command_receiver) = mpsc::channel(self.task_command_buffer_size); + let (event_sender, event_receiver) = mpsc::channel(self.per_connection_event_buffer_size); + + conns.insert( + id, + EstablishedConnection { + endpoint: endpoint.clone(), + sender: command_sender, + }, + ); + self.established_connection_events.push(event_receiver); + if let Some(waker) = self.no_established_connections_waker.take() { + waker.wake(); + } + + let connection = Connection::new( + muxer, + handler, + self.substream_upgrade_protocol_override, + self.max_negotiating_inbound_streams, + ); + + self.spawn( + task::new_for_established_connection( + id, + obtained_peer_id, + connection, + command_receiver, + event_sender, + ) + .boxed(), + ); + } + + /// Polls the connection pool for events. + pub fn poll(&mut self, cx: &mut Context<'_>) -> Poll> where THandler: IntoConnectionHandler + 'static, THandler::Handler: ConnectionHandler + Send, @@ -726,51 +764,13 @@ where }; } - // Add the connection to the pool. - let conns = self.established.entry(obtained_peer_id).or_default(); - let other_established_connection_ids = conns.keys().cloned().collect(); - self.counters.inc_established(&endpoint); - - let (command_sender, command_receiver) = - mpsc::channel(self.task_command_buffer_size); - let (event_sender, event_receiver) = - mpsc::channel(self.per_connection_event_buffer_size); - - conns.insert( - id, - EstablishedConnection { - endpoint: endpoint.clone(), - sender: command_sender, - }, - ); - self.established_connection_events.push(event_receiver); - if let Some(waker) = self.no_established_connections_waker.take() { - waker.wake(); - } - - let connection = Connection::new( - muxer, - new_handler_fn().into_handler(&obtained_peer_id, &endpoint), - self.substream_upgrade_protocol_override, - self.max_negotiating_inbound_streams, - ); - - self.spawn( - task::new_for_established_connection( - id, - obtained_peer_id, - connection, - command_receiver, - event_sender, - ) - .boxed(), - ); let established_in = accepted_at.elapsed(); + return Poll::Ready(PoolEvent::ConnectionEstablished { peer_id: obtained_peer_id, endpoint, id, - other_established_connection_ids, + connection: muxer, concurrent_dial_errors, established_in, }); diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 9979f7c569c..dea4b4e5f36 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -757,7 +757,7 @@ where peer_id, id, endpoint, - other_established_connection_ids, + connection, concurrent_dial_errors, established_in, } => { @@ -769,6 +769,17 @@ where return Some(SwarmEvent::BannedPeer { peer_id, endpoint }); } + let handler = self + .behaviour + .new_handler() + .into_handler(&peer_id, &endpoint); + self.pool + .spawn_connection(id, peer_id, &endpoint, connection, handler); + + let other_established_connection_ids = self + .pool + .iter_established_connections_of_peer(&peer_id) + .collect::>(); let num_established = NonZeroU32::new( u32::try_from(other_established_connection_ids.len() + 1).unwrap(), ) @@ -1200,7 +1211,7 @@ where } // Poll the known peers. - match this.pool.poll(cx, || this.behaviour.new_handler()) { + match this.pool.poll(cx) { Poll::Pending => {} Poll::Ready(pool_event) => { if let Some(swarm_event) = this.handle_pool_event(pool_event) { From dd1eb8c7b0ab08b6bfab6e240c2efb10e49db297 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 26 Jan 2023 17:23:44 +1100 Subject: [PATCH 25/41] Add `ConnectionId` to `ListenFailure` --- swarm-derive/src/lib.rs | 4 +++- swarm/src/behaviour.rs | 3 +++ swarm/src/connection/pool.rs | 7 +++---- swarm/src/lib.rs | 9 +++++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/swarm-derive/src/lib.rs b/swarm-derive/src/lib.rs index f929b771f04..9055546da5f 100644 --- a/swarm-derive/src/lib.rs +++ b/swarm-derive/src/lib.rs @@ -326,12 +326,14 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { self.#i.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { local_addr, send_back_addr, + connection_id })); }, None => quote! { self.#enum_n.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { local_addr, send_back_addr, + connection_id })); }, }; @@ -693,7 +695,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { #dial_failure { peer_id, connection_id, error }) => { #(#on_dial_failure_stmts)* } #from_swarm::ListenFailure( - #listen_failure { local_addr, send_back_addr }) + #listen_failure { local_addr, send_back_addr, connection_id }) => { #(#on_listen_failure_stmts)* } #from_swarm::NewListener( #new_listener { listener_id }) diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index 92cea23f1ee..419eebf463b 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -474,6 +474,7 @@ pub struct DialFailure<'a> { pub struct ListenFailure<'a> { pub local_addr: &'a Multiaddr, pub send_back_addr: &'a Multiaddr, + pub connection_id: ConnectionId, } /// [`FromSwarm`] variant that informs the behaviour that a new listener was created. @@ -599,9 +600,11 @@ impl<'a, Handler: IntoConnectionHandler> FromSwarm<'a, Handler> { FromSwarm::ListenFailure(ListenFailure { local_addr, send_back_addr, + connection_id, }) => Some(FromSwarm::ListenFailure(ListenFailure { local_addr, send_back_addr, + connection_id, })), FromSwarm::NewListener(NewListener { listener_id }) => { Some(FromSwarm::NewListener(NewListener { listener_id })) diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index dd8eda322f7..45dfc5dda84 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -478,7 +478,8 @@ where &mut self, future: TFut, info: IncomingInfo<'_>, - ) -> Result + connection_id: ConnectionId, + ) -> Result<(), ConnectionLimit> where TFut: Future> + Send + 'static, { @@ -486,8 +487,6 @@ where self.counters.check_max_pending_incoming()?; - let connection_id = ConnectionId::next(); - let (abort_notifier, abort_receiver) = oneshot::channel(); self.spawn( @@ -510,7 +509,7 @@ where accepted_at: Instant::now(), }, ); - Ok(connection_id) + Ok(()) } pub fn spawn_connection( diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 1be4b1c427f..babb4f3226f 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -849,7 +849,7 @@ where }); } PoolEvent::PendingInboundConnectionError { - id: _, + id, send_back_addr, local_addr, error, @@ -859,6 +859,7 @@ where .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { local_addr: &local_addr, send_back_addr: &send_back_addr, + connection_id: id, })); return Some(SwarmEvent::IncomingConnectionError { local_addr, @@ -957,14 +958,17 @@ where local_addr, send_back_addr, } => { + let connection_id = ConnectionId::next(); + match self.pool.add_incoming( upgrade, IncomingInfo { local_addr: &local_addr, send_back_addr: &send_back_addr, }, + connection_id, ) { - Ok(_connection_id) => { + Ok(()) => { return Some(SwarmEvent::IncomingConnection { local_addr, send_back_addr, @@ -975,6 +979,7 @@ where .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { local_addr: &local_addr, send_back_addr: &send_back_addr, + connection_id, })); log::warn!("Incoming connection rejected: {:?}", connection_limit); } From 32a465be2b23bf91a5bfb93c41b2d7e74fc1cdff Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 26 Jan 2023 17:29:22 +1100 Subject: [PATCH 26/41] Clean up pending commands on failure --- protocols/relay/src/priv_client.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index 4915efb6f55..c3bc617b202 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -36,7 +36,7 @@ use libp2p_core::PeerId; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm}; use libp2p_swarm::dial_opts::DialOpts; use libp2p_swarm::{ - ConnectionHandlerUpgrErr, ConnectionId, NegotiatedSubstream, NetworkBehaviour, + ConnectionHandlerUpgrErr, ConnectionId, DialFailure, NegotiatedSubstream, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters, THandlerInEvent, }; use std::collections::{hash_map, HashMap, VecDeque}; @@ -190,8 +190,10 @@ impl NetworkBehaviour for Behaviour { FromSwarm::ConnectionClosed(connection_closed) => { self.on_connection_closed(connection_closed) } + FromSwarm::DialFailure(DialFailure { connection_id, .. }) => { + self.pending_handler_commands.remove(&connection_id); + } FromSwarm::AddressChange(_) - | FromSwarm::DialFailure(_) | FromSwarm::ListenFailure(_) | FromSwarm::NewListener(_) | FromSwarm::NewListenAddr(_) From 91f942fb5f54759fc579c571ee6efc6010959673 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 26 Jan 2023 17:32:50 +1100 Subject: [PATCH 27/41] Add docs and fix bug --- protocols/dcutr/src/behaviour_impl.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/protocols/dcutr/src/behaviour_impl.rs b/protocols/dcutr/src/behaviour_impl.rs index c658dd705ae..a8f73f55ebc 100644 --- a/protocols/dcutr/src/behaviour_impl.rs +++ b/protocols/dcutr/src/behaviour_impl.rs @@ -80,6 +80,8 @@ pub struct Behaviour { direct_to_relayed_connections: HashMap, + /// Indexed by the [`ConnectionId`] of the relayed connection and + /// the [`PeerId`] we are trying to establish a direct connection to. outgoing_direct_connection_attempts: HashMap<(ConnectionId, PeerId), u8>, } @@ -325,7 +327,7 @@ impl NetworkBehaviour for Behaviour { .insert(maybe_direct_connection_id, relayed_connection_id); *self .outgoing_direct_connection_attempts - .entry((maybe_direct_connection_id, event_source)) + .entry((relayed_connection_id, event_source)) .or_default() += 1; self.queued_events .push_back(NetworkBehaviourAction::Dial { opts }); From d704e89162436e402df130fb33c5acb5c973076d Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 10:37:52 +1100 Subject: [PATCH 28/41] Consistently use `THandlerInEvent` --- protocols/mdns/src/behaviour.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index 629bae53371..7333530bd0f 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -31,12 +31,11 @@ use libp2p_core::{Multiaddr, PeerId}; use libp2p_swarm::behaviour::{ConnectionClosed, FromSwarm}; use libp2p_swarm::{ dummy, ListenAddresses, NetworkBehaviour, NetworkBehaviourAction, PollParameters, - THandlerOutEvent, + THandlerInEvent, THandlerOutEvent, }; use smallvec::SmallVec; use std::collections::hash_map::{Entry, HashMap}; use std::{cmp, fmt, io, net::IpAddr, pin::Pin, task::Context, task::Poll, time::Instant}; -use void::Void; /// An abstraction to allow for compatibility with various async runtimes. pub trait Provider: 'static { @@ -232,7 +231,7 @@ where &mut self, cx: &mut Context<'_>, _: &mut impl PollParameters, - ) -> Poll> { + ) -> Poll>> { // Poll ifwatch. while let Poll::Ready(Some(event)) = Pin::new(&mut self.if_watch).poll_next(cx) { match event { From 55baab174051abfd69ca41d1793878d41b65a1cb Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 10:42:07 +1100 Subject: [PATCH 29/41] Use type alias --- protocols/rendezvous/src/client.rs | 2 +- protocols/rendezvous/src/server.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/rendezvous/src/client.rs b/protocols/rendezvous/src/client.rs index d3fd7546a00..ea722e7a7d7 100644 --- a/protocols/rendezvous/src/client.rs +++ b/protocols/rendezvous/src/client.rs @@ -289,7 +289,7 @@ fn handle_outbound_event( peer_id: PeerId, discovered_peers: &mut HashMap<(PeerId, Namespace), Vec>, expiring_registrations: &mut FuturesUnordered>, -) -> Vec>> { +) -> Vec>> { match event { outbound::OutEvent::Registered { namespace, ttl } => { vec![NetworkBehaviourAction::GenerateEvent(Event::Registered { diff --git a/protocols/rendezvous/src/server.rs b/protocols/rendezvous/src/server.rs index 5db364ea93e..c38b8e760f3 100644 --- a/protocols/rendezvous/src/server.rs +++ b/protocols/rendezvous/src/server.rs @@ -184,7 +184,7 @@ fn handle_inbound_event( connection: ConnectionId, id: InboundSubstreamId, registrations: &mut Registrations, -) -> Vec>> { +) -> Vec>> { match event { // bad registration inbound::OutEvent::RegistrationRequested(registration) From 2c84f28d75616391b60fe5f0cdcb27a5a782e860 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 10:42:18 +1100 Subject: [PATCH 30/41] Remove unnecessary indentation and "quote"-ing --- swarm-derive/src/lib.rs | 99 +++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 57 deletions(-) diff --git a/swarm-derive/src/lib.rs b/swarm-derive/src/lib.rs index 5628f157736..4bf1eaa357c 100644 --- a/swarm-derive/src/lib.rs +++ b/swarm-derive/src/lib.rs @@ -285,66 +285,51 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { // Build the list of statements to put in the body of `on_swarm_event()` // for the `FromSwarm::DialFailure` variant. - let on_dial_failure_stmts = { - data_struct - .fields - .iter() - .enumerate() - .map(|(enum_n, field)| { - let inject = match field.ident { - Some(ref i) => quote! { - self.#i.on_swarm_event(#from_swarm::DialFailure(#dial_failure { - peer_id, - connection_id, - error, - })); - }, - None => quote! { - self.#enum_n.on_swarm_event(#from_swarm::DialFailure(#dial_failure { - peer_id, - connection_id, - error, - })); - }, - }; - quote! { - #inject; - } - }) - }; + let on_dial_failure_stmts = data_struct + .fields + .iter() + .enumerate() + .map(|(enum_n, field)| match field.ident { + Some(ref i) => quote! { + self.#i.on_swarm_event(#from_swarm::DialFailure(#dial_failure { + peer_id, + connection_id, + error, + })); + }, + None => quote! { + self.#enum_n.on_swarm_event(#from_swarm::DialFailure(#dial_failure { + peer_id, + connection_id, + error, + })); + }, + }); // Build the list of statements to put in the body of `on_swarm_event()` // for the `FromSwarm::ListenFailure` variant. - let on_listen_failure_stmts = { - data_struct - .fields - .iter() - .enumerate() - .map(|(enum_n, field)| { - let inject = match field.ident { - Some(ref i) => quote! { - self.#i.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { - local_addr, - send_back_addr, - connection_id, - error - })); - }, - None => quote! { - self.#enum_n.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { - local_addr, - send_back_addr, - connection_id, - error - })); - }, - }; - - quote! { - #inject; - } - }) - }; + let on_listen_failure_stmts = data_struct + .fields + .iter() + .enumerate() + .map(|(enum_n, field)| match field.ident { + Some(ref i) => quote! { + self.#i.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { + local_addr, + send_back_addr, + connection_id, + error + })); + }, + None => quote! { + self.#enum_n.on_swarm_event(#from_swarm::ListenFailure(#listen_failure { + local_addr, + send_back_addr, + connection_id, + error + })); + }, + }); // Build the list of statements to put in the body of `on_swarm_event()` // for the `FromSwarm::NewListener` variant. From cf772461f7385a4f91fad3980a48e4e8d6723e78 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 10:44:32 +1100 Subject: [PATCH 31/41] Fix bad changelog entry --- swarm/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 53ccd7e3b10..2c6f116571e 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -69,9 +69,9 @@ - Introduce `ListenError` and use it within `SwarmEvent::IncomingConnectionError`. See [PR 3375]. -[PR 3364]: https://github.com/libp2p/rust-libp2p/pull/3364 - Remove `ConnectionId::new`. Manually creating `ConnectionId`s is now unsupported. See [PR 3327]. +[PR 3364]: https://github.com/libp2p/rust-libp2p/pull/3364 [PR 3170]: https://github.com/libp2p/rust-libp2p/pull/3170 [PR 3134]: https://github.com/libp2p/rust-libp2p/pull/3134 [PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153 From 92a96255868ba07fba97747d585b12e1ee93e548 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 11:51:17 +1100 Subject: [PATCH 32/41] Spawn connection at right point in time Otherwise the num-established counter is wrong. --- swarm/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 7fee4b001ec..641f2a9cf4d 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -773,8 +773,6 @@ where .behaviour .new_handler() .into_handler(&peer_id, &endpoint); - self.pool - .spawn_connection(id, peer_id, &endpoint, connection, handler); let other_established_connection_ids = self .pool @@ -789,6 +787,9 @@ where .filter(|conn_id| !self.banned_peer_connections.contains(conn_id)) .count(); + self.pool + .spawn_connection(id, peer_id, &endpoint, connection, handler); + log::debug!( "Connection established: {:?} {:?}; Total (peer): {}. Total non-banned (peer): {}", peer_id, From d90ac81fb9fa05824fe7b5f0d27b0bbfd33ba4ea Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 12:12:13 +1100 Subject: [PATCH 33/41] Fix rustdoc --- swarm/src/behaviour.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index 19b55883ea6..06b9a906c45 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -124,7 +124,7 @@ pub trait NetworkBehaviour: 'static { /// Event generated by the `NetworkBehaviour` and that the swarm will report back. type OutEvent: Send + 'static; - /// Creates a new [`ConnectionHandler`] for a connection with a peer. + /// Creates a new [`ConnectionHandler`](crate::ConnectionHandler) for a connection with a peer. /// /// Every time an incoming connection is opened, and every time another [`NetworkBehaviour`] /// emitted a dial request, this method is called. @@ -156,8 +156,8 @@ pub trait NetworkBehaviour: 'static { /// Informs the behaviour about an event from the [`Swarm`](crate::Swarm). fn on_swarm_event(&mut self, event: FromSwarm); - /// Informs the behaviour about an event generated by the [`ConnectionHandler`] dedicated to the - /// peer identified by `peer_id`. for the behaviour. + /// Informs the behaviour about an event generated by the [`ConnectionHandler`](crate::ConnectionHandler) + /// dedicated to the peer identified by `peer_id`. for the behaviour. /// /// The [`PeerId`] is guaranteed to be in a connected state. In other words, /// [`FromSwarm::ConnectionEstablished`] has previously been received with this [`PeerId`]. @@ -241,19 +241,19 @@ pub enum NetworkBehaviourAction { /// connection with a peer. /// /// If the `Swarm` is connected to the peer, the message is delivered to the - /// [`ConnectionHandler`] instance identified by the peer ID and connection ID. + /// [`ConnectionHandler`](crate::ConnectionHandler) instance identified by the peer ID and connection ID. /// /// If the specified connection no longer exists, the event is silently dropped. /// /// Typically the connection ID given is the same as the one passed to /// [`NetworkBehaviour::on_connection_handler_event`], i.e. whenever the behaviour wishes to /// respond to a request on the same connection (and possibly the same - /// substream, as per the implementation of [`ConnectionHandler`]). + /// substream, as per the implementation of [`ConnectionHandler`](crate::ConnectionHandler)). /// /// Note that even if the peer is currently connected, connections can get closed /// at any time and thus the event may not reach a handler. NotifyHandler { - /// The peer for whom a [`ConnectionHandler`] should be notified. + /// The peer for whom a [`ConnectionHandler`](crate::ConnectionHandler) should be notified. peer_id: PeerId, /// The options w.r.t. which connection handler to notify of the event. handler: NotifyHandler, @@ -282,9 +282,9 @@ pub enum NetworkBehaviourAction { /// /// Note: Closing a connection via /// [`NetworkBehaviourAction::CloseConnection`] does not inform the - /// corresponding [`ConnectionHandler`]. - /// Closing a connection via a [`ConnectionHandler`] can be done - /// either in a collaborative manner across [`ConnectionHandler`]s + /// corresponding [`ConnectionHandler`](crate::ConnectionHandler). + /// Closing a connection via a [`ConnectionHandler`](crate::ConnectionHandler) can be done + /// either in a collaborative manner across [`ConnectionHandler`](crate::ConnectionHandler)s /// with [`ConnectionHandler::connection_keep_alive`] or directly with /// [`ConnectionHandlerEvent::Close`](crate::ConnectionHandlerEvent::Close). CloseConnection { From cfe9f958cba987efde2a5b1ddbf0a665e352c563 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 12:22:43 +1100 Subject: [PATCH 34/41] One more missing rustdoc link --- swarm/src/behaviour.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index 06b9a906c45..44d69fed654 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -285,7 +285,7 @@ pub enum NetworkBehaviourAction { /// corresponding [`ConnectionHandler`](crate::ConnectionHandler). /// Closing a connection via a [`ConnectionHandler`](crate::ConnectionHandler) can be done /// either in a collaborative manner across [`ConnectionHandler`](crate::ConnectionHandler)s - /// with [`ConnectionHandler::connection_keep_alive`] or directly with + /// with [`ConnectionHandler::connection_keep_alive`](crate::ConnectionHandler::connection_keep_alive) or directly with /// [`ConnectionHandlerEvent::Close`](crate::ConnectionHandlerEvent::Close). CloseConnection { /// The peer to disconnect. From 3f8f73c7bed55d8b662e2de37054de7a7ce0e10c Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 15:18:23 +1100 Subject: [PATCH 35/41] Remove `banned_peer_connections` We no longer add connections for banned peers to the pool so we don't have to filter them later. --- swarm/src/lib.rs | 76 +++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 52 deletions(-) diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 641f2a9cf4d..d950927fd05 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -327,12 +327,6 @@ where /// List of nodes for which we deny any incoming connection. banned_peers: HashSet, - /// Connections for which we withhold any reporting. These belong to banned peers. - /// - /// Note: Connections to a peer that are established at the time of banning that peer - /// are not added here. Instead they are simply closed. - banned_peer_connections: HashSet, - /// Pending event to be delivered to connection handlers /// (or dropped if the peer disconnected) before the `behaviour` /// can be polled again. @@ -762,9 +756,6 @@ where established_in, } => { if self.banned_peers.contains(&peer_id) { - // Mark the connection for the banned peer as banned, thus withholding any - // future events from the connection to the behaviour. - self.banned_peer_connections.insert(id); self.pool.disconnect(peer_id); return Some(SwarmEvent::BannedPeer { peer_id, endpoint }); } @@ -782,21 +773,16 @@ where u32::try_from(other_established_connection_ids.len() + 1).unwrap(), ) .expect("n + 1 is always non-zero; qed"); - let non_banned_established = other_established_connection_ids - .into_iter() - .filter(|conn_id| !self.banned_peer_connections.contains(conn_id)) - .count(); self.pool .spawn_connection(id, peer_id, &endpoint, connection, handler); log::debug!( - "Connection established: {:?} {:?}; Total (peer): {}. Total non-banned (peer): {}", - peer_id, - endpoint, - num_established, - non_banned_established + 1, - ); + "Connection established: {:?} {:?}; Total (peer): {}.", + peer_id, + endpoint, + num_established, + ); let failed_addresses = concurrent_dial_errors .as_ref() .map(|es| { @@ -813,7 +799,7 @@ where connection_id: id, endpoint: &endpoint, failed_addresses: &failed_addresses, - other_established: non_banned_established, + other_established: other_established_connection_ids.len(), }, )); return Some(SwarmEvent::ConnectionEstablished { @@ -897,21 +883,15 @@ where let endpoint = connected.endpoint; let num_established = u32::try_from(remaining_established_connection_ids.len()).unwrap(); - let conn_was_reported = !self.banned_peer_connections.remove(&id); - if conn_was_reported { - let remaining_non_banned = remaining_established_connection_ids - .into_iter() - .filter(|conn_id| !self.banned_peer_connections.contains(conn_id)) - .count(); - self.behaviour - .on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { - peer_id, - connection_id: id, - endpoint: &endpoint, - handler, - remaining_established: remaining_non_banned, - })); - } + + self.behaviour + .on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id, + connection_id: id, + endpoint: &endpoint, + handler, + remaining_established: num_established as usize, + })); return Some(SwarmEvent::ConnectionClosed { peer_id, endpoint, @@ -920,12 +900,8 @@ where }); } PoolEvent::ConnectionEvent { peer_id, id, event } => { - if self.banned_peer_connections.contains(&id) { - log::debug!("Ignoring event from banned peer: {} {:?}.", peer_id, id); - } else { - self.behaviour - .on_connection_handler_event(peer_id, id, event); - } + self.behaviour + .on_connection_handler_event(peer_id, id, event); } PoolEvent::AddressChange { peer_id, @@ -933,15 +909,13 @@ where new_endpoint, old_endpoint, } => { - if !self.banned_peer_connections.contains(&id) { - self.behaviour - .on_swarm_event(FromSwarm::AddressChange(AddressChange { - peer_id, - connection_id: id, - old: &old_endpoint, - new: &new_endpoint, - })); - } + self.behaviour + .on_swarm_event(FromSwarm::AddressChange(AddressChange { + peer_id, + connection_id: id, + old: &old_endpoint, + new: &new_endpoint, + })); } } @@ -1577,7 +1551,6 @@ where listened_addrs: HashMap::new(), external_addrs: Addresses::default(), banned_peers: HashSet::new(), - banned_peer_connections: HashSet::new(), pending_event: None, } } @@ -2004,7 +1977,6 @@ mod tests { swarm2.behaviour.on_connection_closed.len(), s2_expected_conns, "No additional closed connections should be reported for the banned peer" ); - assert!(swarm2.banned_peer_connections.is_empty()); // Setup to test that a ban lifted does not affect future connections. for _ in 0..num_connections { From 063ef5c2a0835f42c46c97e5e4ce694724193838 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 27 Jan 2023 15:22:26 +1100 Subject: [PATCH 36/41] Fix test Now that we no longer add connections to banned peers, we need to: - Reduce the number of expected connections by 1 (i.e. delete line 1954) - Act in `Stage::BannedDial` earlier (i.e. remove the `if`) --- swarm/src/lib.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index d950927fd05..45c389932f3 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -1951,24 +1951,22 @@ mod tests { { // Setup to test that new connections of banned peers are not reported. swarm1.dial(addr2.clone()).unwrap(); - s1_expected_conns += 1; stage = Stage::BannedDial; } } Stage::BannedDial => { - if swarm2.network_info().num_peers() == 1 { - // The banned connection was established. Check that it was not reported to - // the behaviour of the banning swarm. - assert_eq!( - swarm2.behaviour.on_connection_established.len(), s2_expected_conns, - "No additional closed connections should be reported for the banned peer" - ); + // The banned connection was established. Check that it was not reported to + // the behaviour of the banning swarm. + assert_eq!( + swarm2.behaviour.on_connection_established.len(), + s2_expected_conns, + "No additional closed connections should be reported for the banned peer" + ); - // Setup to test that the banned connection is not reported upon closing - // even if the peer is unbanned. - swarm2.unban_peer_id(swarm1_id); - stage = Stage::Unbanned; - } + // Setup to test that the banned connection is not reported upon closing + // even if the peer is unbanned. + swarm2.unban_peer_id(swarm1_id); + stage = Stage::Unbanned; } Stage::Unbanned => { if swarm2.network_info().num_peers() == 0 { From 3ecd62359a366d8d310286a97d228e84fd8d484e Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 10 Feb 2023 19:16:17 +1300 Subject: [PATCH 37/41] Inline `spawn` function --- swarm/src/connection/pool.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index 3e04b058165..36b26860e3b 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -403,10 +403,6 @@ where pub fn iter_connected(&self) -> impl Iterator { self.established.keys() } - - fn spawn(&mut self, task: BoxFuture<'static, ()>) { - self.executor.spawn(task) - } } impl Pool @@ -443,7 +439,7 @@ where let (abort_notifier, abort_receiver) = oneshot::channel(); - self.spawn( + self.executor.spawn( task::new_for_pending_outgoing_connection( connection_id, dial, @@ -489,7 +485,7 @@ where let (abort_notifier, abort_receiver) = oneshot::channel(); - self.spawn( + self.executor.spawn( task::new_for_pending_incoming_connection( connection_id, future, @@ -545,7 +541,7 @@ where self.max_negotiating_inbound_streams, ); - self.spawn( + self.executor.spawn( task::new_for_established_connection( id, obtained_peer_id, @@ -554,7 +550,7 @@ where event_sender, ) .boxed(), - ); + ) } /// Polls the connection pool for events. @@ -724,7 +720,7 @@ where }); if let Err(error) = error { - self.spawn( + self.executor.spawn( poll_fn(move |cx| { if let Err(e) = ready!(muxer.poll_close_unpin(cx)) { log::debug!( From 02cbf4288d4c7d32ecd3507cc53eab7f1703a4db Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 10 Feb 2023 19:19:50 +1300 Subject: [PATCH 38/41] Box future inside `spawn` --- swarm/src/connection/pool.rs | 62 ++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index 36b26860e3b..0c482a3ac12 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -71,7 +71,9 @@ impl ExecSwitch { } } - fn spawn(&mut self, task: BoxFuture<'static, ()>) { + fn spawn(&mut self, task: impl Future + Send + 'static) { + let task = task.boxed(); + match self { Self::Executor(executor) => executor.exec(task), Self::LocalSpawn(local) => local.push(task), @@ -439,15 +441,13 @@ where let (abort_notifier, abort_receiver) = oneshot::channel(); - self.executor.spawn( - task::new_for_pending_outgoing_connection( + self.executor + .spawn(task::new_for_pending_outgoing_connection( connection_id, dial, abort_receiver, self.pending_connection_events_tx.clone(), - ) - .boxed(), - ); + )); let endpoint = PendingPoint::Dialer { role_override }; @@ -485,15 +485,13 @@ where let (abort_notifier, abort_receiver) = oneshot::channel(); - self.executor.spawn( - task::new_for_pending_incoming_connection( + self.executor + .spawn(task::new_for_pending_incoming_connection( connection_id, future, abort_receiver, self.pending_connection_events_tx.clone(), - ) - .boxed(), - ); + )); self.counters.inc_pending_incoming(); self.pending.insert( @@ -541,16 +539,13 @@ where self.max_negotiating_inbound_streams, ); - self.executor.spawn( - task::new_for_established_connection( - id, - obtained_peer_id, - connection, - command_receiver, - event_sender, - ) - .boxed(), - ) + self.executor.spawn(task::new_for_established_connection( + id, + obtained_peer_id, + connection, + command_receiver, + event_sender, + )) } /// Polls the connection pool for events. @@ -720,20 +715,17 @@ where }); if let Err(error) = error { - self.executor.spawn( - poll_fn(move |cx| { - if let Err(e) = ready!(muxer.poll_close_unpin(cx)) { - log::debug!( - "Failed to close connection {:?} to peer {}: {:?}", - id, - obtained_peer_id, - e - ); - } - Poll::Ready(()) - }) - .boxed(), - ); + self.executor.spawn(poll_fn(move |cx| { + if let Err(e) = ready!(muxer.poll_close_unpin(cx)) { + log::debug!( + "Failed to close connection {:?} to peer {}: {:?}", + id, + obtained_peer_id, + e + ); + } + Poll::Ready(()) + })); match endpoint { ConnectedPoint::Dialer { .. } => { From 1c906db93c28577ef9762fe0a6aa01f0cc543963 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 10 Feb 2023 19:20:59 +1300 Subject: [PATCH 39/41] Merge impl blocks --- swarm/src/connection/pool.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index 0c482a3ac12..74f0eab557f 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -405,12 +405,7 @@ where pub fn iter_connected(&self) -> impl Iterator { self.established.keys() } -} -impl Pool -where - THandler: IntoConnectionHandler, -{ /// Adds a pending outgoing connection to the pool in the form of a `Future` /// that establishes and negotiates the connection. /// From 87cf5fd5481c5f444411dba77b0f22b132ff5c3a Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 10 Feb 2023 19:22:53 +1300 Subject: [PATCH 40/41] Gracefully close connection to banned peer --- swarm/src/connection/pool.rs | 4 ++++ swarm/src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index 74f0eab557f..28e98968e20 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -543,6 +543,10 @@ where )) } + pub fn close_connection(&mut self, muxer: StreamMuxerBox) { + self.executor.spawn(muxer.close()); + } + /// Polls the connection pool for events. pub fn poll(&mut self, cx: &mut Context<'_>) -> Poll> where diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index ec8e27a9196..f2cacec67ff 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -756,7 +756,7 @@ where established_in, } => { if self.banned_peers.contains(&peer_id) { - self.pool.disconnect(peer_id); + self.pool.close_connection(connection); return Some(SwarmEvent::BannedPeer { peer_id, endpoint }); } From f20485908d38da288b193e0b4f0fde08b4648339 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 10 Feb 2023 20:40:11 +1300 Subject: [PATCH 41/41] Ignore error when closing connection --- swarm/src/connection/pool.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/swarm/src/connection/pool.rs b/swarm/src/connection/pool.rs index 28e98968e20..ed132accc3e 100644 --- a/swarm/src/connection/pool.rs +++ b/swarm/src/connection/pool.rs @@ -544,7 +544,9 @@ where } pub fn close_connection(&mut self, muxer: StreamMuxerBox) { - self.executor.spawn(muxer.close()); + self.executor.spawn(async move { + let _ = muxer.close().await; + }); } /// Polls the connection pool for events.