mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-07-02 19:21:37 +00:00
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:
@ -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;
|
||||
|
||||
|
@ -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())
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user