swarm/src/lib: Refactor trait usage (#2182)

- Removes the `Swarm` type alias, renaming `ExpandedSwarm` to `Swarm`.
- Remove `TInEvent`, `TOutEvent` and `THandler` trait parameters on
`Swarm`, instead deriving them through `TBehaviour`. Move derive logic
to separate type aliases.
- Simplify trait bounds on `Swarm` main `impl` and `Stream` `impl`.
This commit is contained in:
Max Inden
2021-08-09 15:29:58 +02:00
committed by GitHub
parent 68b5f743ad
commit a0d690e259
2 changed files with 63 additions and 64 deletions

View File

@ -6,7 +6,12 @@
except for `new_handler`, `inject_event` and `poll`. except for `new_handler`, `inject_event` and `poll`.
This should make it easier to create new implementations. See [PR 2150]. This should make it easier to create new implementations. See [PR 2150].
- Remove `Swarm` type alias and rename `ExpandedSwarm` to `Swarm`. Reduce direct
trait parameters on `Swarm` (previously `ExpandedSwarm`), deriving parameters
through associated types on `TBehaviour`. See [PR 2182].
[PR 2150]: https://github.com/libp2p/rust-libp2p/pull/2150/ [PR 2150]: https://github.com/libp2p/rust-libp2p/pull/2150/
[PR 2182]: https://github.com/libp2p/rust-libp2p/pull/2182
# 0.30.0 [2021-07-12] # 0.30.0 [2021-07-12]

View File

@ -120,25 +120,34 @@ use std::collections::HashSet;
use std::num::{NonZeroU32, NonZeroUsize}; use std::num::{NonZeroU32, NonZeroUsize};
use upgrade::UpgradeInfoSend as _; use upgrade::UpgradeInfoSend as _;
/// Contains the state of the network, plus the way it should behave.
pub type Swarm<TBehaviour> = ExpandedSwarm<
TBehaviour,
<<<TBehaviour as NetworkBehaviour>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent,
<<<TBehaviour as NetworkBehaviour>::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutEvent,
<TBehaviour as NetworkBehaviour>::ProtocolsHandler,
>;
/// Substream for which a protocol has been chosen. /// Substream for which a protocol has been chosen.
/// ///
/// Implements the [`AsyncRead`](futures::io::AsyncRead) and /// Implements the [`AsyncRead`](futures::io::AsyncRead) and
/// [`AsyncWrite`](futures::io::AsyncWrite) traits. /// [`AsyncWrite`](futures::io::AsyncWrite) traits.
pub type NegotiatedSubstream = Negotiated<Substream<StreamMuxerBox>>; pub type NegotiatedSubstream = Negotiated<Substream<StreamMuxerBox>>;
/// Event generated by the [`NetworkBehaviour`] that the swarm will report back.
type TBehaviourOutEvent<TBehaviour> = <TBehaviour as NetworkBehaviour>::OutEvent;
/// [`ProtocolsHandler`] of the [`NetworkBehaviour`] for all the protocols the [`NetworkBehaviour`]
/// supports.
type THandler<TBehaviour> = <TBehaviour as NetworkBehaviour>::ProtocolsHandler;
/// Custom event that can be received by the [`ProtocolsHandler`] of the
/// [`NetworkBehaviour`].
type THandlerInEvent<TBehaviour> = <<THandler<TBehaviour> as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent;
/// Custom event that can be produced by the [`ProtocolsHandler`] of the [`NetworkBehaviour`].
type THandlerOutEvent<TBehaviour> = <<THandler<TBehaviour> as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutEvent;
/// Custom error that can be produced by the [`ProtocolsHandler`] of the [`NetworkBehaviour`].
type THandlerErr<TBehaviour> = <<THandler<TBehaviour> as IntoProtocolsHandler>::Handler as ProtocolsHandler>::Error;
/// Event generated by the `Swarm`. /// Event generated by the `Swarm`.
#[derive(Debug)] #[derive(Debug)]
pub enum SwarmEvent<TBvEv, THandleErr> { pub enum SwarmEvent<TBehaviourOutEvent, THandlerErr> {
/// Event generated by the `NetworkBehaviour`. /// Event generated by the `NetworkBehaviour`.
Behaviour(TBvEv), Behaviour(TBehaviourOutEvent),
/// A connection to the given peer has been opened. /// A connection to the given peer has been opened.
ConnectionEstablished { ConnectionEstablished {
/// Identity of the peer that we have connected to. /// Identity of the peer that we have connected to.
@ -160,7 +169,7 @@ pub enum SwarmEvent<TBvEv, THandleErr> {
num_established: u32, num_established: u32,
/// Reason for the disconnection, if it was not a successful /// Reason for the disconnection, if it was not a successful
/// active close. /// active close.
cause: Option<ConnectionError<NodeHandlerWrapperError<THandleErr>>>, cause: Option<ConnectionError<NodeHandlerWrapperError<THandlerErr>>>,
}, },
/// A new connection arrived on a listener and is in the process of protocol negotiation. /// A new connection arrived on a listener and is in the process of protocol negotiation.
/// ///
@ -261,17 +270,17 @@ pub enum SwarmEvent<TBvEv, THandleErr> {
/// Contains the state of the network, plus the way it should behave. /// Contains the state of the network, plus the way it should behave.
/// ///
/// Note: Needs to be polled via `<ExpandedSwarm as Stream>` in order to make /// Note: Needs to be polled via `<Swarm as Stream>` in order to make
/// progress. /// progress.
pub struct ExpandedSwarm<TBehaviour, TInEvent, TOutEvent, THandler> pub struct Swarm<TBehaviour>
where where
THandler: IntoProtocolsHandler, TBehaviour: NetworkBehaviour,
{ {
network: Network< network: Network<
transport::Boxed<(PeerId, StreamMuxerBox)>, transport::Boxed<(PeerId, StreamMuxerBox)>,
TInEvent, THandlerInEvent<TBehaviour>,
TOutEvent, THandlerOutEvent<TBehaviour>,
NodeHandlerWrapperBuilder<THandler>, NodeHandlerWrapperBuilder<THandler<TBehaviour>>,
>, >,
/// Handles which nodes to connect to and how to handle the events sent back by the protocol /// Handles which nodes to connect to and how to handle the events sent back by the protocol
@ -294,27 +303,21 @@ where
/// Pending event to be delivered to connection handlers /// Pending event to be delivered to connection handlers
/// (or dropped if the peer disconnected) before the `behaviour` /// (or dropped if the peer disconnected) before the `behaviour`
/// can be polled again. /// can be polled again.
pending_event: Option<(PeerId, PendingNotifyHandler, TInEvent)>, pending_event: Option<(PeerId, PendingNotifyHandler, THandlerInEvent<TBehaviour>)>,
/// The configured override for substream protocol upgrades, if any. /// The configured override for substream protocol upgrades, if any.
substream_upgrade_protocol_override: Option<libp2p_core::upgrade::Version>, substream_upgrade_protocol_override: Option<libp2p_core::upgrade::Version>,
} }
impl<TBehaviour, TInEvent, TOutEvent, THandler> Unpin for impl<TBehaviour> Unpin for Swarm<TBehaviour>
ExpandedSwarm<TBehaviour, TInEvent, TOutEvent, THandler>
where where
THandler: IntoProtocolsHandler, TBehaviour: NetworkBehaviour,
{ {
} }
impl<TBehaviour, TInEvent, TOutEvent, THandler, THandleErr> impl<TBehaviour> Swarm<TBehaviour>
ExpandedSwarm<TBehaviour, TInEvent, TOutEvent, THandler> where
where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>, TBehaviour: NetworkBehaviour,
TInEvent: Send + 'static,
TOutEvent: Send + 'static,
THandler: IntoProtocolsHandler + Send + 'static,
THandler::Handler: ProtocolsHandler<InEvent = TInEvent, OutEvent = TOutEvent, Error = THandleErr>,
THandleErr: error::Error + Send + 'static,
{ {
/// Builds a new `Swarm`. /// Builds a new `Swarm`.
pub fn new( pub fn new(
@ -438,7 +441,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
} }
/// Removes an external address of the local node, regardless of /// Removes an external address of the local node, regardless of
/// its current score. See [`ExpandedSwarm::add_external_address`] /// its current score. See [`Swarm::add_external_address`]
/// for details. /// for details.
/// ///
/// Returns `true` if the address existed and was removed, `false` /// Returns `true` if the address existed and was removed, `false`
@ -473,7 +476,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
/// ///
/// Returns `Ok(())` if there was one or more established connections to the peer. /// Returns `Ok(())` if there was one or more established connections to the peer.
/// ///
/// Note: Closing a connection via [`ExpandedSwarm::disconnect_peer_id`] does /// Note: Closing a connection via [`Swarm::disconnect_peer_id`] does
/// not inform the corresponding [`ProtocolsHandler`]. /// not inform the corresponding [`ProtocolsHandler`].
/// Closing a connection via a [`ProtocolsHandler`] can be done either in a /// Closing a connection via a [`ProtocolsHandler`] can be done either in a
/// collaborative manner across [`ProtocolsHandler`]s /// collaborative manner across [`ProtocolsHandler`]s
@ -507,7 +510,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
/// ///
/// Polls the `Swarm` for the next event. /// Polls the `Swarm` for the next event.
fn poll_next_event(mut self: Pin<&mut Self>, cx: &mut Context<'_>) fn poll_next_event(mut self: Pin<&mut Self>, cx: &mut Context<'_>)
-> Poll<SwarmEvent<TBehaviour::OutEvent, THandleErr>> -> Poll<SwarmEvent<TBehaviour::OutEvent, THandlerErr<TBehaviour>>>
{ {
// We use a `this` variable because the compiler can't mutably borrow multiple times // We use a `this` variable because the compiler can't mutably borrow multiple times
// across a `Deref`. // across a `Deref`.
@ -708,7 +711,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
return Poll::Ready(SwarmEvent::Behaviour(event)) return Poll::Ready(SwarmEvent::Behaviour(event))
}, },
Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => { Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => {
let _ = ExpandedSwarm::dial_addr(&mut *this, address); let _ = Swarm::dial_addr(&mut *this, address);
}, },
Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => { Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id, condition }) => {
if this.banned_peers.contains(&peer_id) { if this.banned_peers.contains(&peer_id) {
@ -720,7 +723,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
DialPeerCondition::Always => true, DialPeerCondition::Always => true,
}; };
if condition_matched { if condition_matched {
if ExpandedSwarm::dial(this, &peer_id).is_ok() { if Swarm::dial(this, &peer_id).is_ok() {
return Poll::Ready(SwarmEvent::Dialing(peer_id)) return Poll::Ready(SwarmEvent::Dialing(peer_id))
} }
} else { } else {
@ -808,11 +811,11 @@ enum PendingNotifyHandler {
/// ///
/// Returns `None` if the connection is closing or the event has been /// Returns `None` if the connection is closing or the event has been
/// successfully sent, in either case the event is consumed. /// successfully sent, in either case the event is consumed.
fn notify_one<'a, TInEvent>( fn notify_one<'a, THandlerInEvent>(
conn: &mut EstablishedConnection<'a, TInEvent>, conn: &mut EstablishedConnection<'a, THandlerInEvent>,
event: TInEvent, event: THandlerInEvent,
cx: &mut Context<'_>, cx: &mut Context<'_>,
) -> Option<TInEvent> ) -> Option<THandlerInEvent>
{ {
match conn.poll_ready_notify_handler(cx) { match conn.poll_ready_notify_handler(cx) {
Poll::Pending => Some(event), Poll::Pending => Some(event),
@ -835,12 +838,12 @@ fn notify_one<'a, TInEvent>(
/// ///
/// Returns `None` if either all connections are closing or the event /// Returns `None` if either all connections are closing or the event
/// was successfully sent to a handler, in either case the event is consumed. /// was successfully sent to a handler, in either case the event is consumed.
fn notify_any<'a, TTrans, TInEvent, TOutEvent, THandler>( fn notify_any<'a, TTrans, THandlerInEvent, THandlerOutEvent, THandler>(
ids: SmallVec<[ConnectionId; 10]>, ids: SmallVec<[ConnectionId; 10]>,
peer: &mut ConnectedPeer<'a, TTrans, TInEvent, TOutEvent, THandler>, peer: &mut ConnectedPeer<'a, TTrans, THandlerInEvent, THandlerOutEvent, THandler>,
event: TInEvent, event: THandlerInEvent,
cx: &mut Context<'_>, cx: &mut Context<'_>,
) -> Option<(TInEvent, SmallVec<[ConnectionId; 10]>)> ) -> Option<(THandlerInEvent, SmallVec<[ConnectionId; 10]>)>
where where
TTrans: Transport, TTrans: Transport,
THandler: IntoConnectionHandler, THandler: IntoConnectionHandler,
@ -872,24 +875,18 @@ where
}) })
} }
/// Stream of events returned by [`ExpandedSwarm`]. /// Stream of events returned by [`Swarm`].
/// ///
/// Includes events from the [`NetworkBehaviour`] as well as events about /// Includes events from the [`NetworkBehaviour`] as well as events about
/// connection and listener status. See [`SwarmEvent`] for details. /// connection and listener status. See [`SwarmEvent`] for details.
/// ///
/// Note: This stream is infinite and it is guaranteed that /// Note: This stream is infinite and it is guaranteed that
/// [`Stream::poll_next`] will never return `Poll::Ready(None)`. /// [`Stream::poll_next`] will never return `Poll::Ready(None)`.
impl<TBehaviour, TInEvent, TOutEvent, THandler, THandleErr> Stream for impl<TBehaviour> Stream for Swarm<TBehaviour>
ExpandedSwarm<TBehaviour, TInEvent, TOutEvent, THandler> where
where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>, TBehaviour: NetworkBehaviour,
THandler: IntoProtocolsHandler + Send + 'static,
TInEvent: Send + 'static,
TOutEvent: Send + 'static,
THandler::Handler:
ProtocolsHandler<InEvent = TInEvent, OutEvent = TOutEvent, Error = THandleErr>,
THandleErr: error::Error + Send + 'static,
{ {
type Item = SwarmEvent<TBehaviour::OutEvent, THandleErr>; type Item = SwarmEvent<TBehaviourOutEvent<TBehaviour>, THandlerErr<TBehaviour>>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.as_mut() self.as_mut()
@ -899,13 +896,9 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
} }
/// The stream of swarm events never terminates, so we can implement fused for it. /// The stream of swarm events never terminates, so we can implement fused for it.
impl<TBehaviour, TInEvent, TOutEvent, THandler> FusedStream for impl<TBehaviour> FusedStream for Swarm<TBehaviour>
ExpandedSwarm<TBehaviour, TInEvent, TOutEvent, THandler> where
where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>, TBehaviour: NetworkBehaviour,
THandler: IntoProtocolsHandler + Send + 'static,
TInEvent: Send + 'static,
TOutEvent: Send + 'static,
THandler::Handler: ProtocolsHandler<InEvent = TInEvent, OutEvent = TOutEvent>,
{ {
fn is_terminated(&self) -> bool { fn is_terminated(&self) -> bool {
false false
@ -954,7 +947,8 @@ pub struct SwarmBuilder<TBehaviour> {
} }
impl<TBehaviour> SwarmBuilder<TBehaviour> impl<TBehaviour> SwarmBuilder<TBehaviour>
where TBehaviour: NetworkBehaviour, where
TBehaviour: NetworkBehaviour,
{ {
/// Creates a new `SwarmBuilder` from the given transport, behaviour and /// Creates a new `SwarmBuilder` from the given transport, behaviour and
/// local peer ID. The `Swarm` with its underlying `Network` is obtained /// local peer ID. The `Swarm` with its underlying `Network` is obtained
@ -1073,7 +1067,7 @@ where TBehaviour: NetworkBehaviour,
let network = Network::new(self.transport, self.local_peer_id, network_cfg); let network = Network::new(self.transport, self.local_peer_id, network_cfg);
ExpandedSwarm { Swarm {
network, network,
behaviour: self.behaviour, behaviour: self.behaviour,
supported_protocols, supported_protocols,
@ -1086,7 +1080,7 @@ where TBehaviour: NetworkBehaviour,
} }
} }
/// The possible failures of [`ExpandedSwarm::dial`]. /// The possible failures of [`Swarm::dial`].
#[derive(Debug)] #[derive(Debug)]
pub enum DialError { pub enum DialError {
/// The peer is currently banned. /// The peer is currently banned.
@ -1346,7 +1340,7 @@ mod tests {
} }
/// Establishes multiple connections between two peers, /// Establishes multiple connections between two peers,
/// after which one peer disconnects the other using [`ExpandedSwarm::disconnect_peer_id`]. /// after which one peer disconnects the other using [`Swarm::disconnect_peer_id`].
/// ///
/// The test expects both behaviours to be notified via pairs of /// The test expects both behaviours to be notified via pairs of
/// inject_connected / inject_disconnected as well as /// inject_connected / inject_disconnected as well as