diff --git a/core/src/swarm.rs b/core/src/swarm.rs index f6a41ade..8096572e 100644 --- a/core/src/swarm.rs +++ b/core/src/swarm.rs @@ -47,5 +47,5 @@ mod registry; pub mod toggle; pub use crate::nodes::raw_swarm::ConnectedPoint; -pub use self::behaviour::{NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess}; -pub use self::swarm::{PollParameters, ExpandedSwarm, Swarm, SwarmBuilder}; +pub use self::behaviour::{NetworkBehaviour, NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters}; +pub use self::swarm::{SwarmPollParameters, ExpandedSwarm, Swarm, SwarmBuilder}; diff --git a/core/src/swarm/behaviour.rs b/core/src/swarm/behaviour.rs index afd5c5d7..98f52f28 100644 --- a/core/src/swarm/behaviour.rs +++ b/core/src/swarm/behaviour.rs @@ -22,7 +22,6 @@ use crate::{ Multiaddr, PeerId, nodes::raw_swarm::ConnectedPoint, protocols_handler::{IntoProtocolsHandler, ProtocolsHandler}, - swarm::PollParameters, }; use futures::prelude::*; use std::error; @@ -129,10 +128,37 @@ pub trait NetworkBehaviour { /// /// This API mimics the API of the `Stream` trait. The method may register the current task in /// order to wake it up at a later point in time. - fn poll(&mut self, params: &mut PollParameters<'_>) + fn poll(&mut self, params: &mut impl PollParameters) -> Async::Handler as ProtocolsHandler>::InEvent, Self::OutEvent>>; } +/// Parameters passed to `poll()`, that the `NetworkBehaviour` has access to. +pub trait PollParameters { + /// Iterator returned by [`supported_protocols`]. + type SupportedProtocolsIter: ExactSizeIterator>; + /// Iterator returned by [`listened_addresses`]. + type ListenedAddressesIter: ExactSizeIterator; + /// Iterator returned by [`external_addresses`]. + type ExternalAddressesIter: ExactSizeIterator; + + /// Returns the list of protocol the behaviour supports when a remote negotiates a protocol on + /// an inbound substream. + /// + /// The iterator's elements are the ASCII names as reported on the wire. + /// + /// Note that the list is computed once at initialization and never refreshed. + fn supported_protocols(&self) -> Self::SupportedProtocolsIter; + + /// Returns the list of the addresses we're listening on. + fn listened_addresses(&self) -> Self::ListenedAddressesIter; + + /// Returns the list of the addresses nodes can use to reach us. + fn external_addresses(&self) -> Self::ExternalAddressesIter; + + /// Returns the peer id of the local node. + fn local_peer_id(&self) -> &PeerId; +} + /// Used when deriving `NetworkBehaviour`. When deriving `NetworkBehaviour`, must be implemented /// for all the possible event types generated by the various fields. // TODO: document how the custom behaviour works and link this here diff --git a/core/src/swarm/registry.rs b/core/src/swarm/registry.rs index 95151db3..067f85d4 100644 --- a/core/src/swarm/registry.rs +++ b/core/src/swarm/registry.rs @@ -27,7 +27,7 @@ use std::num::NonZeroUsize; /// Every address has an associated score and iterating over addresses will return them /// in order from highest to lowest. When reaching the limit, addresses with the lowest /// score will be dropped first. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Addresses { /// Max. length of `registry`. limit: NonZeroUsize, @@ -82,6 +82,13 @@ impl Addresses { pub fn iter(&self) -> AddressIter<'_> { AddressIter { items: &self.registry, offset: 0 } } + + /// Return an iterator over all [`Multiaddr`] values. + /// + /// The iteration is ordered by descending score. + pub fn into_iter(self) -> AddressIntoIter { + AddressIntoIter { items: self.registry } + } } /// An iterator over [`Multiaddr`] values. @@ -111,6 +118,31 @@ impl<'a> Iterator for AddressIter<'a> { impl<'a> ExactSizeIterator for AddressIter<'a> {} +/// An iterator over [`Multiaddr`] values. +#[derive(Clone)] +pub struct AddressIntoIter { + items: SmallVec<[Record; 8]>, +} + +impl Iterator for AddressIntoIter { + type Item = Multiaddr; + + fn next(&mut self) -> Option { + if !self.items.is_empty() { + Some(self.items.remove(0).addr) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + let n = self.items.len(); + (n, Some(n)) + } +} + +impl ExactSizeIterator for AddressIntoIter {} + // Reverse insertion sort. fn isort(xs: &mut [Record]) { for i in 1 .. xs.len() { diff --git a/core/src/swarm/swarm.rs b/core/src/swarm/swarm.rs index 1e32a042..e2d0e1f6 100644 --- a/core/src/swarm/swarm.rs +++ b/core/src/swarm/swarm.rs @@ -28,7 +28,7 @@ use crate::{ raw_swarm::{self, RawSwarm, RawSwarmEvent} }, protocols_handler::{NodeHandlerWrapperBuilder, NodeHandlerWrapper, NodeHandlerWrapperError, IntoProtocolsHandler, ProtocolsHandler}, - swarm::{NetworkBehaviour, NetworkBehaviourAction, registry::{Addresses, AddressIter}}, + swarm::{PollParameters, NetworkBehaviour, NetworkBehaviourAction, registry::{Addresses, AddressIntoIter}}, transport::TransportError, }; use futures::prelude::*; @@ -321,11 +321,11 @@ where TBehaviour: NetworkBehaviour, } let behaviour_poll = { - let mut parameters = PollParameters { + let mut parameters = SwarmPollParameters { local_peer_id: &mut self.raw_swarm.local_peer_id(), supported_protocols: &self.supported_protocols, listened_addrs: &self.listened_addrs, - external_addrs: self.external_addrs.iter() + external_addrs: &self.external_addrs }; self.behaviour.poll(&mut parameters) }; @@ -366,36 +366,31 @@ where TBehaviour: NetworkBehaviour, /// Parameters passed to `poll()`, that the `NetworkBehaviour` has access to. // TODO: #[derive(Debug)] -pub struct PollParameters<'a: 'a> { +pub struct SwarmPollParameters<'a> { local_peer_id: &'a PeerId, supported_protocols: &'a [Vec], listened_addrs: &'a [Multiaddr], - external_addrs: AddressIter<'a> + external_addrs: &'a Addresses, } -impl<'a> PollParameters<'a> { - /// Returns the list of protocol the behaviour supports when a remote negotiates a protocol on - /// an inbound substream. - /// - /// The iterator's elements are the ASCII names as reported on the wire. - /// - /// Note that the list is computed once at initialization and never refreshed. - pub fn supported_protocols(&self) -> impl ExactSizeIterator { - self.supported_protocols.iter().map(AsRef::as_ref) +impl<'a> PollParameters for SwarmPollParameters<'a> { + type SupportedProtocolsIter = std::vec::IntoIter>; + type ListenedAddressesIter = std::vec::IntoIter; + type ExternalAddressesIter = AddressIntoIter; + + fn supported_protocols(&self) -> Self::SupportedProtocolsIter { + self.supported_protocols.to_vec().into_iter() } - /// Returns the list of the addresses we're listening on. - pub fn listened_addresses(&self) -> impl ExactSizeIterator { - self.listened_addrs.iter() + fn listened_addresses(&self) -> Self::ListenedAddressesIter { + self.listened_addrs.to_vec().into_iter() } - /// Returns the list of the addresses nodes can use to reach us. - pub fn external_addresses(&self) -> impl ExactSizeIterator { - self.external_addrs.clone() + fn external_addresses(&self) -> Self::ExternalAddressesIter { + self.external_addrs.clone().into_iter() } - /// Returns the peer id of the local node. - pub fn local_peer_id(&self) -> &PeerId { + fn local_peer_id(&self) -> &PeerId { self.local_peer_id } } @@ -515,7 +510,7 @@ mod tests { fn inject_node_event(&mut self, _: PeerId, _: ::OutEvent) {} - fn poll(&mut self, _: &mut PollParameters<'_>) -> + fn poll(&mut self, _: &mut impl PollParameters) -> Async::InEvent, Self::OutEvent>> { diff --git a/core/src/swarm/toggle.rs b/core/src/swarm/toggle.rs index 819149f0..9e30e572 100644 --- a/core/src/swarm/toggle.rs +++ b/core/src/swarm/toggle.rs @@ -123,7 +123,7 @@ where } } - fn poll(&mut self, params: &mut PollParameters<'_>) + fn poll(&mut self, params: &mut impl PollParameters) -> Async::Handler as ProtocolsHandler>::InEvent, Self::OutEvent>> { if let Some(inner) = self.inner.as_mut() { diff --git a/misc/core-derive/src/lib.rs b/misc/core-derive/src/lib.rs index c30185ba..77795574 100644 --- a/misc/core-derive/src/lib.rs +++ b/misc/core-derive/src/lib.rs @@ -477,7 +477,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { } } - fn poll(&mut self, poll_params: &mut #poll_parameters) -> ::libp2p::futures::Async<#network_behaviour_action<<::Handler as #protocols_handler>::InEvent, Self::OutEvent>> { + fn poll(&mut self, poll_params: &mut impl #poll_parameters) -> ::libp2p::futures::Async<#network_behaviour_action<<::Handler as #protocols_handler>::InEvent, Self::OutEvent>> { use libp2p::futures::prelude::*; #(#poll_stmts)* let f: ::libp2p::futures::Async<#network_behaviour_action<<::Handler as #protocols_handler>::InEvent, Self::OutEvent>> = #poll_method; diff --git a/misc/mdns/src/behaviour.rs b/misc/mdns/src/behaviour.rs index 5aafacc7..fee65995 100644 --- a/misc/mdns/src/behaviour.rs +++ b/misc/mdns/src/behaviour.rs @@ -172,7 +172,7 @@ where fn poll( &mut self, - params: &mut PollParameters<'_>, + params: &mut impl PollParameters, ) -> Async< NetworkBehaviourAction< ::InEvent, @@ -214,7 +214,7 @@ where MdnsPacket::Query(query) => { let _ = query.respond( params.local_peer_id().clone(), - params.listened_addresses().cloned(), + params.listened_addresses(), Duration::from_secs(5 * 60) ); }, diff --git a/protocols/floodsub/src/layer.rs b/protocols/floodsub/src/layer.rs index 262affa3..fc1f0136 100644 --- a/protocols/floodsub/src/layer.rs +++ b/protocols/floodsub/src/layer.rs @@ -337,7 +337,7 @@ where fn poll( &mut self, - _: &mut PollParameters<'_>, + _: &mut impl PollParameters, ) -> Async< NetworkBehaviourAction< ::InEvent, diff --git a/protocols/identify/src/identify.rs b/protocols/identify/src/identify.rs index a870705b..816ebbef 100644 --- a/protocols/identify/src/identify.rs +++ b/protocols/identify/src/identify.rs @@ -129,7 +129,7 @@ where fn poll( &mut self, - params: &mut PollParameters<'_>, + params: &mut impl PollParameters, ) -> Async< NetworkBehaviourAction< ::InEvent, @@ -145,11 +145,11 @@ where // There's not much we can do to solve this conflict except strip non-UTF-8 characters. let protocols = params .supported_protocols() - .map(|p| String::from_utf8_lossy(p).to_string()) + .map(|p| String::from_utf8_lossy(&p).to_string()) .collect(); - let mut listen_addrs: Vec<_> = params.external_addresses().cloned().collect(); - listen_addrs.extend(params.listened_addresses().cloned()); + let mut listen_addrs: Vec<_> = params.external_addresses().collect(); + listen_addrs.extend(params.listened_addresses()); let send_back_info = IdentifyInfo { public_key: self.local_public_key.clone(), diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index a5a7961d..f6fd35c6 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -824,7 +824,7 @@ where fn poll( &mut self, - parameters: &mut PollParameters<'_>, + parameters: &mut impl PollParameters, ) -> Async< NetworkBehaviourAction< ::InEvent, @@ -964,7 +964,7 @@ where key: target.clone(), provider_peer: KadPeer { node_id: parameters.local_peer_id().clone(), - multiaddrs: parameters.external_addresses().cloned().collect(), + multiaddrs: parameters.external_addresses().collect(), connection_ty: KadConnectionType::Connected, } }, diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 1cfa3703..0e541c06 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -116,7 +116,7 @@ where self.events.push_front(PingEvent { peer, result }) } - fn poll(&mut self, _: &mut PollParameters<'_>) -> Async> + fn poll(&mut self, _: &mut impl PollParameters) -> Async> { if let Some(e) = self.events.pop_back() { Async::Ready(NetworkBehaviourAction::GenerateEvent(e))