Enhance the swarm a bit (#711)

* Replace the &mut TTopology with a &mut PollParameters

* Add supported_protocols

* Add external_addresses

* Report out addresses in Kademlia

* Fix the custom derive

* Some comments

* Fix compilation on stable
This commit is contained in:
Pierre Krieger
2018-12-01 13:34:57 +01:00
committed by GitHub
parent 69eafd9869
commit c5d08ab48c
8 changed files with 113 additions and 26 deletions

View File

@ -30,6 +30,7 @@ use crate::{
topology::Topology
};
use futures::prelude::*;
use smallvec::SmallVec;
use std::{fmt, io, ops::{Deref, DerefMut}};
pub use crate::nodes::raw_swarm::ConnectedPoint;
@ -53,6 +54,12 @@ where TTransport: Transport,
/// 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 after NAT traversal.
external_addresses: SmallVec<[Multiaddr; 8]>,
}
impl<TTransport, TBehaviour, TTopology> Deref for Swarm<TTransport, TBehaviour, TTopology>
@ -105,12 +112,21 @@ where TBehaviour: NetworkBehaviour<TTopology>,
{
/// Builds a new `Swarm`.
#[inline]
pub fn new(transport: TTransport, behaviour: TBehaviour, topology: TTopology) -> Self {
pub fn new(transport: TTransport, mut behaviour: TBehaviour, topology: TTopology) -> Self {
let supported_protocols = behaviour
.new_handler()
.listen_protocol()
.protocol_names()
.map(|(name, _)| name.to_vec())
.collect();
let raw_swarm = RawSwarm::new(transport);
Swarm {
raw_swarm,
behaviour,
topology,
supported_protocols,
external_addresses: SmallVec::new(),
}
}
@ -230,7 +246,16 @@ where TBehaviour: NetworkBehaviour<TTopology>,
Async::Ready(RawSwarmEvent::UnknownPeerDialError { .. }) => {},
}
match self.behaviour.poll(&mut self.topology) {
let behaviour_poll = {
let mut parameters = PollParameters {
topology: &mut self.topology,
supported_protocols: &self.supported_protocols,
external_addresses: &self.external_addresses,
};
self.behaviour.poll(&mut parameters)
};
match behaviour_poll {
Async::NotReady if raw_swarm_not_ready => return Ok(Async::NotReady),
Async::NotReady => (),
Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
@ -247,6 +272,13 @@ where TBehaviour: NetworkBehaviour<TTopology>,
peer.send_event(event);
}
},
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => {
for addr in self.raw_swarm.nat_traversal(&address) {
// TODO: is it a good idea to add these addresses permanently? what about
// a TTL instead?
self.external_addresses.push(addr);
}
},
}
}
}
@ -286,7 +318,42 @@ 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 TTopology) -> Async<NetworkBehaviourAction<<Self::ProtocolsHandler as ProtocolsHandler>::InEvent, Self::OutEvent>>;
fn poll(&mut self, topology: &mut PollParameters<TTopology>) -> Async<NetworkBehaviourAction<<Self::ProtocolsHandler as ProtocolsHandler>::InEvent, Self::OutEvent>>;
}
/// Parameters passed to `poll()` that the `NetworkBehaviour` has access to.
#[derive(Debug)]
pub struct PollParameters<'a, TTopology: 'a> {
topology: &'a mut TTopology,
supported_protocols: &'a [Vec<u8>],
external_addresses: &'a [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
}
/// 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.
#[inline]
pub fn supported_protocols(&self) -> impl ExactSizeIterator<Item = &[u8]> {
self.supported_protocols.iter().map(AsRef::as_ref)
}
/// Returns the list of the addresses we're listening on, after accounting for NAT traversal.
///
/// This corresponds to the elements produced with `ReportObservedAddr`.
#[inline]
pub fn external_addresses(&self) -> impl ExactSizeIterator<Item = &Multiaddr> {
self.external_addresses.iter()
}
}
/// Action to perform.
@ -319,4 +386,12 @@ pub enum NetworkBehaviourAction<TInEvent, TOutEvent> {
/// Event to send to the peer.
event: TInEvent,
},
/// Reports that a remote observes us as this address.
///
/// The swarm will pass this address through the transport's NAT traversal.
ReportObservedAddr {
/// The address we're being observed as.
address: Multiaddr,
},
}