Embed the topology in the NetworkBehaviour (#889)

* Embed the topology in the NetworkBehaviour

* Put topologies inside of Floodsub and Kad

* Fix core tests

* Fix chat example

* More work

* Some cleanup

* Restore external addresses system
This commit is contained in:
Pierre Krieger
2019-01-26 23:57:53 +01:00
committed by GitHub
parent 30c082dfe5
commit df923526ca
21 changed files with 818 additions and 749 deletions

View File

@ -77,7 +77,6 @@ pub mod muxing;
pub mod nodes;
pub mod protocols_handler;
pub mod swarm;
pub mod topology;
pub mod transport;
pub mod upgrade;

View File

@ -42,7 +42,7 @@
//!
use crate::{
Transport, Multiaddr, PublicKey, PeerId, InboundUpgrade, OutboundUpgrade, UpgradeInfo, ProtocolName,
Transport, Multiaddr, PeerId, InboundUpgrade, OutboundUpgrade, UpgradeInfo, ProtocolName,
muxing::StreamMuxer,
nodes::{
handled_node::NodeHandler,
@ -50,9 +50,7 @@ use crate::{
raw_swarm::{RawSwarm, RawSwarmEvent}
},
protocols_handler::{NodeHandlerWrapperBuilder, NodeHandlerWrapper, IntoProtocolsHandler, ProtocolsHandler},
topology::Topology,
transport::TransportError,
topology::DisconnectReason,
};
use futures::prelude::*;
use smallvec::SmallVec;
@ -61,36 +59,36 @@ use std::{fmt, io, ops::{Deref, DerefMut}};
pub use crate::nodes::raw_swarm::ConnectedPoint;
/// Contains the state of the network, plus the way it should behave.
pub struct Swarm<TTransport, TBehaviour, TTopology>
pub struct Swarm<TTransport, TBehaviour>
where TTransport: Transport,
TBehaviour: NetworkBehaviour<TTopology>,
TBehaviour: NetworkBehaviour,
{
raw_swarm: RawSwarm<
TTransport,
<<<TBehaviour as NetworkBehaviour<TTopology>>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent,
<<<TBehaviour as NetworkBehaviour<TTopology>>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutEvent,
<<<TBehaviour as NetworkBehaviour>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent,
<<<TBehaviour as NetworkBehaviour>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutEvent,
NodeHandlerWrapperBuilder<TBehaviour::ProtocolsHandler>,
<<<TBehaviour as NetworkBehaviour<TTopology>>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::Error,
<<<TBehaviour as NetworkBehaviour>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::Error,
>,
/// Handles which nodes to connect to and how to handle the events sent back by the protocol
/// handlers.
behaviour: TBehaviour,
/// Holds the topology of the network. In other words all the nodes that we think exist, even
/// if we're not connected to them.
topology: TTopology,
/// List of protocols that the behaviour says it supports.
supported_protocols: SmallVec<[Vec<u8>; 16]>,
/// List of multiaddresses we're listening on.
listened_addrs: SmallVec<[Multiaddr; 8]>,
/// List of multiaddresses we're listening on, after account for external IP addresses and
/// similar mechanisms.
external_addrs: SmallVec<[Multiaddr; 8]>,
}
impl<TTransport, TBehaviour, TTopology> Deref for Swarm<TTransport, TBehaviour, TTopology>
impl<TTransport, TBehaviour> Deref for Swarm<TTransport, TBehaviour>
where TTransport: Transport,
TBehaviour: NetworkBehaviour<TTopology>,
TBehaviour: NetworkBehaviour,
{
type Target = TBehaviour;
@ -100,9 +98,9 @@ where TTransport: Transport,
}
}
impl<TTransport, TBehaviour, TTopology> DerefMut for Swarm<TTransport, TBehaviour, TTopology>
impl<TTransport, TBehaviour> DerefMut for Swarm<TTransport, TBehaviour>
where TTransport: Transport,
TBehaviour: NetworkBehaviour<TTopology>,
TBehaviour: NetworkBehaviour,
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
@ -110,8 +108,8 @@ where TTransport: Transport,
}
}
impl<TTransport, TBehaviour, TMuxer, TTopology> Swarm<TTransport, TBehaviour, TTopology>
where TBehaviour: NetworkBehaviour<TTopology>,
impl<TTransport, TBehaviour, TMuxer> Swarm<TTransport, TBehaviour>
where TBehaviour: NetworkBehaviour,
TMuxer: StreamMuxer + Send + Sync + 'static,
<TMuxer as StreamMuxer>::OutboundSubstream: Send + 'static,
<TMuxer as StreamMuxer>::Substream: Send + 'static,
@ -139,29 +137,12 @@ where TBehaviour: NetworkBehaviour<TTopology>,
<<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as OutboundUpgrade<Substream<TMuxer>>>::Future: Send + 'static,
<<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as OutboundUpgrade<Substream<TMuxer>>>::Error: fmt::Debug + Send + 'static,
<NodeHandlerWrapper<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler> as NodeHandler>::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
TTopology: Topology,
{
/// Builds a new `Swarm`.
#[inline]
pub fn new(transport: TTransport, mut behaviour: TBehaviour, topology: TTopology) -> Self {
let supported_protocols = behaviour
.new_handler()
.into_handler(topology.local_peer_id())
.listen_protocol()
.protocol_info()
.into_iter()
.map(|info| info.protocol_name().to_vec())
.collect();
let raw_swarm = RawSwarm::new(transport, topology.local_peer_id().clone());
Swarm {
raw_swarm,
behaviour,
topology,
supported_protocols,
listened_addrs: SmallVec::new(),
}
pub fn new(transport: TTransport, behaviour: TBehaviour, local_peer_id: PeerId) -> Self {
SwarmBuilder::new(transport, behaviour, local_peer_id)
.build()
}
/// Returns the transport passed when building this object.
@ -198,7 +179,7 @@ where TBehaviour: NetworkBehaviour<TTopology>,
/// peer.
#[inline]
pub fn dial(me: &mut Self, peer_id: PeerId) {
let addrs = me.topology.addresses_of_peer(&peer_id);
let addrs = me.behaviour.addresses_of_peer(&peer_id);
let handler = me.behaviour.new_handler().into_node_handler_builder();
if let Some(peer) = me.raw_swarm.peer(peer_id).as_not_connected() {
let _ = peer.connect_iter(addrs, handler);
@ -216,22 +197,10 @@ where TBehaviour: NetworkBehaviour<TTopology>,
pub fn local_peer_id(me: &Self) -> &PeerId {
&me.raw_swarm.local_peer_id()
}
/// Returns the topology of the swarm.
#[inline]
pub fn topology(me: &Self) -> &TTopology {
&me.topology
}
/// Returns the topology of the swarm.
#[inline]
pub fn topology_mut(me: &mut Self) -> &mut TTopology {
&mut me.topology
}
}
impl<TTransport, TBehaviour, TMuxer, TTopology> Stream for Swarm<TTransport, TBehaviour, TTopology>
where TBehaviour: NetworkBehaviour<TTopology>,
impl<TTransport, TBehaviour, TMuxer> Stream for Swarm<TTransport, TBehaviour>
where TBehaviour: NetworkBehaviour,
TMuxer: StreamMuxer + Send + Sync + 'static,
<TMuxer as StreamMuxer>::OutboundSubstream: Send + 'static,
<TMuxer as StreamMuxer>::Substream: Send + 'static,
@ -259,7 +228,6 @@ where TBehaviour: NetworkBehaviour<TTopology>,
<<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as UpgradeInfo>::InfoIter: Send + 'static,
<<<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send + 'static,
<NodeHandlerWrapper<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler> as NodeHandler>::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
TTopology: Topology,
{
type Item = TBehaviour::OutEvent;
type Error = io::Error;
@ -275,20 +243,15 @@ where TBehaviour: NetworkBehaviour<TTopology>,
self.behaviour.inject_node_event(peer_id, event);
},
Async::Ready(RawSwarmEvent::Connected { peer_id, endpoint }) => {
self.topology.set_connected(&peer_id, &endpoint);
self.behaviour.inject_connected(peer_id, endpoint);
},
Async::Ready(RawSwarmEvent::NodeClosed { peer_id, endpoint }) => {
self.topology.set_disconnected(&peer_id, &endpoint, DisconnectReason::Graceful);
self.behaviour.inject_disconnected(&peer_id, endpoint);
},
Async::Ready(RawSwarmEvent::NodeError { peer_id, endpoint, .. }) => {
self.topology.set_disconnected(&peer_id, &endpoint, DisconnectReason::Error);
self.behaviour.inject_disconnected(&peer_id, endpoint);
},
Async::Ready(RawSwarmEvent::Replaced { peer_id, closed_endpoint, endpoint }) => {
self.topology.set_disconnected(&peer_id, &closed_endpoint, DisconnectReason::Replaced);
self.topology.set_connected(&peer_id, &endpoint);
self.behaviour.inject_disconnected(&peer_id, closed_endpoint);
self.behaviour.inject_connected(peer_id, endpoint);
},
@ -298,20 +261,17 @@ where TBehaviour: NetworkBehaviour<TTopology>,
},
Async::Ready(RawSwarmEvent::ListenerClosed { .. }) => {},
Async::Ready(RawSwarmEvent::IncomingConnectionError { .. }) => {},
Async::Ready(RawSwarmEvent::DialError { multiaddr, .. }) => {
self.topology.set_unreachable(&multiaddr);
},
Async::Ready(RawSwarmEvent::UnknownPeerDialError { multiaddr, .. }) => {
self.topology.set_unreachable(&multiaddr);
},
Async::Ready(RawSwarmEvent::DialError { .. }) => {},
Async::Ready(RawSwarmEvent::UnknownPeerDialError { .. }) => {},
}
let behaviour_poll = {
let transport = self.raw_swarm.transport();
let mut parameters = PollParameters {
topology: &mut self.topology,
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,
nat_traversal: &move |a, b| transport.nat_traversal(a, b),
};
self.behaviour.poll(&mut parameters)
@ -335,7 +295,9 @@ where TBehaviour: NetworkBehaviour<TTopology>,
}
},
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => {
self.topology.add_local_external_addrs(self.raw_swarm.nat_traversal(&address));
for addr in self.raw_swarm.nat_traversal(&address) {
self.external_addrs.push(addr);
}
},
}
}
@ -346,7 +308,7 @@ where TBehaviour: NetworkBehaviour<TTopology>,
///
/// This trait has been designed to be composable. Multiple implementations can be combined into
/// one that handles all the behaviours at once.
pub trait NetworkBehaviour<TTopology> {
pub trait NetworkBehaviour {
/// Handler for all the protocols the network supports.
type ProtocolsHandler: IntoProtocolsHandler;
/// Event generated by the swarm.
@ -355,6 +317,10 @@ pub trait NetworkBehaviour<TTopology> {
/// Builds a new `ProtocolsHandler`.
fn new_handler(&mut self) -> Self::ProtocolsHandler;
/// Addresses that this behaviour is aware of for this specific peer, and that may allow
/// reaching the peer.
fn addresses_of_peer(&self, peer_id: &PeerId) -> Vec<Multiaddr>;
/// Indicates the behaviour that we connected to the node with the given peer id through the
/// given endpoint.
fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint);
@ -376,7 +342,7 @@ pub trait NetworkBehaviour<TTopology> {
/// Polls for things that swarm should do.
///
/// This API mimics the API of the `Stream` trait.
fn poll(&mut self, topology: &mut PollParameters<TTopology>) -> Async<NetworkBehaviourAction<<<Self::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent, Self::OutEvent>>;
fn poll(&mut self, topology: &mut PollParameters) -> Async<NetworkBehaviourAction<<<Self::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent, Self::OutEvent>>;
}
/// Used when deriving `NetworkBehaviour`. When deriving `NetworkBehaviour`, must be implemented
@ -390,20 +356,15 @@ pub trait NetworkBehaviourEventProcess<TEvent> {
/// Parameters passed to `poll()`, that the `NetworkBehaviour` has access to.
// TODO: #[derive(Debug)]
pub struct PollParameters<'a, TTopology: 'a> {
topology: &'a mut TTopology,
pub struct PollParameters<'a: 'a> {
local_peer_id: &'a PeerId,
supported_protocols: &'a [Vec<u8>],
listened_addrs: &'a [Multiaddr],
external_addrs: &'a [Multiaddr],
nat_traversal: &'a dyn Fn(&Multiaddr, &Multiaddr) -> Option<Multiaddr>,
}
impl<'a, TTopology> PollParameters<'a, TTopology> {
/// Returns a reference to the topology of the network.
#[inline]
pub fn topology(&mut self) -> &mut TTopology {
&mut self.topology
}
impl<'a> PollParameters<'a> {
/// Returns the list of protocol the behaviour supports when a remote negotiates a protocol on
/// an inbound substream.
///
@ -422,28 +383,16 @@ impl<'a, TTopology> PollParameters<'a, TTopology> {
}
/// Returns the list of the addresses nodes can use to reach us.
// TODO: should return references
#[inline]
pub fn external_addresses<'b>(&'b mut self) -> impl ExactSizeIterator<Item = Multiaddr> + 'b
where TTopology: Topology
{
let local_peer_id = self.topology.local_peer_id().clone();
self.topology.addresses_of_peer(&local_peer_id).into_iter()
}
/// Returns the public key of the local node.
#[inline]
pub fn local_public_key(&self) -> &PublicKey
where TTopology: Topology
{
self.topology.local_public_key()
pub fn external_addresses<'b>(&'b mut self) -> impl ExactSizeIterator<Item = Multiaddr> + 'b {
self.external_addrs.iter().cloned()
}
/// Returns the peer id of the local node.
#[inline]
pub fn local_peer_id(&self) -> &PeerId
where TTopology: Topology
{
self.topology.local_peer_id()
pub fn local_peer_id(&self) -> &PeerId {
self.local_peer_id
}
/// Calls the `nat_traversal` method on the underlying transport of the `Swarm`.
@ -493,18 +442,15 @@ pub enum NetworkBehaviourAction<TInEvent, TOutEvent> {
},
}
pub struct SwarmBuilder <TTransport, TBehaviour, TTopology>
where TTransport: Transport,
TBehaviour: NetworkBehaviour<TTopology>
{
pub struct SwarmBuilder<TTransport, TBehaviour> {
incoming_limit: Option<u32>,
topology: TTopology,
local_peer_id: PeerId,
transport: TTransport,
behaviour: TBehaviour,
}
impl<TTransport, TBehaviour, TMuxer, TTopology> SwarmBuilder<TTransport, TBehaviour, TTopology>
where TBehaviour: NetworkBehaviour<TTopology>,
impl<TTransport, TBehaviour, TMuxer> SwarmBuilder<TTransport, TBehaviour>
where TBehaviour: NetworkBehaviour,
TMuxer: StreamMuxer + Send + Sync + 'static,
<TMuxer as StreamMuxer>::OutboundSubstream: Send + 'static,
<TMuxer as StreamMuxer>::Substream: Send + 'static,
@ -532,59 +478,53 @@ where TBehaviour: NetworkBehaviour<TTopology>,
<<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as OutboundUpgrade<Substream<TMuxer>>>::Future: Send + 'static,
<<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as OutboundUpgrade<Substream<TMuxer>>>::Error: fmt::Debug + Send + 'static,
<NodeHandlerWrapper<<TBehaviour::ProtocolsHandler as IntoProtocolsHandler>::Handler> as NodeHandler>::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
TTopology: Topology,
{
pub fn new(transport: TTransport, behaviour: TBehaviour,
topology:TTopology) -> Self {
pub fn new(transport: TTransport, behaviour: TBehaviour, local_peer_id: PeerId) -> Self {
SwarmBuilder {
incoming_limit: None,
transport: transport,
topology: topology,
behaviour: behaviour,
local_peer_id,
transport,
behaviour,
}
}
pub fn incoming_limit(mut self, incoming_limit: Option<u32>) -> Self
{
pub fn incoming_limit(mut self, incoming_limit: Option<u32>) -> Self {
self.incoming_limit = incoming_limit;
self
}
pub fn build(mut self) ->
Swarm<TTransport, TBehaviour, TTopology>
{
pub fn build(mut self) -> Swarm<TTransport, TBehaviour> {
let supported_protocols = self.behaviour
.new_handler()
.into_handler(self.topology.local_peer_id())
.into_handler(&self.local_peer_id)
.listen_protocol()
.protocol_info()
.into_iter()
.map(|info| info.protocol_name().to_vec())
.collect();
let raw_swarm = RawSwarm::new_with_incoming_limit(self.transport,
self.topology.local_peer_id().clone(),
self.incoming_limit);
let raw_swarm = RawSwarm::new_with_incoming_limit(self.transport, self.local_peer_id, self.incoming_limit);
Swarm {
raw_swarm,
behaviour: self.behaviour,
topology: self.topology,
supported_protocols,
listened_addrs: SmallVec::new(),
external_addrs: SmallVec::new(),
}
}
}
#[cfg(test)]
mod tests {
use crate::nodes::raw_swarm::RawSwarm;
use crate::peer_id::PeerId;
use crate::protocols_handler::{DummyProtocolsHandler, ProtocolsHandler};
use crate::public_key::PublicKey;
use crate::tests::dummy_transport::DummyTransport;
use crate::topology::MemoryTopology;
use futures::prelude::*;
use multiaddr::Multiaddr;
use rand::random;
use smallvec::SmallVec;
use std::marker::PhantomData;
@ -600,7 +540,7 @@ mod tests {
trait TSubstream: AsyncRead + AsyncWrite {}
impl <TSubstream, TTopology> NetworkBehaviour<TTopology>
impl<TSubstream> NetworkBehaviour
for DummyBehaviour<TSubstream>
where TSubstream: AsyncRead + AsyncWrite
{
@ -611,6 +551,10 @@ mod tests {
DummyProtocolsHandler::default()
}
fn addresses_of_peer(&self, _: &PeerId) -> Vec<Multiaddr> {
Vec::new()
}
fn inject_connected(&mut self, _: PeerId, _: ConnectedPoint) {}
fn inject_disconnected(&mut self, _: &PeerId, _: ConnectedPoint) {}
@ -618,7 +562,7 @@ mod tests {
fn inject_node_event(&mut self, _: PeerId,
_: <Self::ProtocolsHandler as ProtocolsHandler>::OutEvent) {}
fn poll(&mut self, _:&mut PollParameters<TTopology>) ->
fn poll(&mut self, _: &mut PollParameters) ->
Async<NetworkBehaviourAction<<Self::ProtocolsHandler as
ProtocolsHandler>::InEvent, Self::OutEvent>>
{
@ -638,10 +582,9 @@ mod tests {
fn test_build_swarm() {
let id = get_random_id();
let transport = DummyTransport::new();
let topology = MemoryTopology::empty(id);
let behaviour = DummyBehaviour{marker: PhantomData};
let swarm = SwarmBuilder::new(transport, behaviour,
topology).incoming_limit(Some(4)).build();
id.into_peer_id()).incoming_limit(Some(4)).build();
assert_eq!(swarm.raw_swarm.incoming_limit(), Some(4));
}
@ -649,9 +592,8 @@ mod tests {
fn test_build_swarm_with_max_listeners_none() {
let id = get_random_id();
let transport = DummyTransport::new();
let topology = MemoryTopology::empty(id);
let behaviour = DummyBehaviour{marker: PhantomData};
let swarm = SwarmBuilder::new(transport, behaviour, topology)
let swarm = SwarmBuilder::new(transport, behaviour, id.into_peer_id())
.build();
assert!(swarm.raw_swarm.incoming_limit().is_none())

View File

@ -1,151 +0,0 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! A *network topology* is a collection of nodes that are part of the network or that we think
//! are part of the network. In other words, it is essentially a container whose layout is
//! optimized for certain operations.
//!
//! In libp2p, a *topology* is any struct that implements at least the `Topology` trait. In order
//! to build a `Swarm`, you have to give to it ownership of a type that implements this trait.
//!
//! In order to use some protocols defined outside of `libp2p-core` (such as Kademlia) in your
//! `Swarm`, you will have to implement additional traits on your topology.
//!
//! While the `MemoryTopology` is provided as a ready-to-go topology that is suitable for quick
//! prototyping, it shouldn't be used in an actual high-performance production software.
use std::collections::HashMap;
use crate::{swarm::ConnectedPoint, Multiaddr, PeerId, PublicKey};
/// Storage for the network topology.
///
/// The topology should also store information about the local node, including its public key, its
/// `PeerId`, and the addresses it's advertising.
pub trait Topology {
/// Returns the addresses to try use to reach the given peer.
///
/// > **Note**: Keep in mind that `peer` can be the local node.
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr>;
/// Returns the `PeerId` of the local node.
fn local_peer_id(&self) -> &PeerId;
/// Returns the public key of the local node.
fn local_public_key(&self) -> &PublicKey;
/// Adds an address that other nodes can use to connect to our local node.
///
/// > **Note**: Should later be returned when calling `addresses_of_peer()` with the `PeerId`
/// > of the local node.
fn add_local_external_addrs<TIter>(&mut self, addrs: TIter)
where TIter: Iterator<Item = Multiaddr>;
/// Indicates to the topology that we have successfully connected to the given address with the
/// given `PeerId`.
fn set_connected(&mut self, _peer_id: &PeerId, _addr: &ConnectedPoint) {}
/// Indicates to the topology that we have been disconnected from the given address with the
/// given `PeerId`.
fn set_disconnected(&mut self, _peer_id: &PeerId, _addr: &ConnectedPoint, _reason: DisconnectReason) {}
/// Indicates to the topology that we have failed to reach the given address.
fn set_unreachable(&mut self, _addr: &Multiaddr) {}
}
/// Reason why the peer has been disconnected.
#[derive(Debug, Copy, Clone)]
pub enum DisconnectReason {
Error,
Graceful,
Replaced,
}
/// Topology of the network stored in memory.
pub struct MemoryTopology {
list: HashMap<PeerId, Vec<Multiaddr>>,
local_peer_id: PeerId,
local_public_key: PublicKey,
}
impl MemoryTopology {
/// Creates an empty topology.
#[inline]
pub fn empty(pubkey: PublicKey) -> MemoryTopology {
let local_peer_id = pubkey.clone().into_peer_id();
MemoryTopology {
list: Default::default(),
local_peer_id,
local_public_key: pubkey,
}
}
/// Returns true if the topology is empty.
#[inline]
pub fn is_empty(&self) -> bool {
self.list.is_empty()
}
/// Adds an address to the topology.
#[inline]
pub fn add_address(&mut self, peer: PeerId, addr: Multiaddr) {
let addrs = self.list.entry(peer).or_insert_with(|| Vec::new());
if addrs.iter().all(|a| a != &addr) {
addrs.push(addr);
}
}
/// Returns a list of all the known peers in the topology.
#[inline]
pub fn peers(&self) -> impl Iterator<Item = &PeerId> {
self.list.keys()
}
/// Returns an iterator to all the entries in the topology.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&PeerId, &Multiaddr)> {
self.list.iter().flat_map(|(p, l)| l.iter().map(move |ma| (p, ma)))
}
}
impl Topology for MemoryTopology {
fn addresses_of_peer(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
self.list.get(peer).map(|v| v.clone()).unwrap_or(Vec::new())
}
fn add_local_external_addrs<TIter>(&mut self, addrs: TIter)
where TIter: Iterator<Item = Multiaddr>
{
for addr in addrs {
let id = self.local_peer_id.clone();
self.add_address(id, addr);
}
}
#[inline]
fn local_peer_id(&self) -> &PeerId {
&self.local_peer_id
}
#[inline]
fn local_public_key(&self) -> &PublicKey {
&self.local_public_key
}
}