diff --git a/misc/core-derive/tests/test.rs b/misc/core-derive/tests/test.rs index d2377e02..a041147d 100644 --- a/misc/core-derive/tests/test.rs +++ b/misc/core-derive/tests/test.rs @@ -22,8 +22,6 @@ extern crate libp2p; extern crate void; -use void::Void; - /// Small utility to check that a type implements `NetworkBehaviour`. #[allow(dead_code)] fn require_net_behaviour>() {} @@ -41,12 +39,11 @@ fn one_field() { #[allow(dead_code)] #[derive(NetworkBehaviour)] struct Foo { - ping: libp2p::ping::PeriodicPing, + ping: libp2p::ping::Ping, } - impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { - fn inject_event(&mut self, event: Void) { - void::unreachable(event) + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::ping::PingEvent) { } } @@ -60,13 +57,17 @@ fn two_fields() { #[allow(dead_code)] #[derive(NetworkBehaviour)] struct Foo { - ping_dialer: libp2p::ping::PeriodicPing, - ping_listener: libp2p::ping::PingListen, + ping: libp2p::ping::Ping, + identify: libp2p::identify::Identify, } - impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { - fn inject_event(&mut self, event: Void) { - void::unreachable(event) + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::identify::IdentifyEvent) { + } + } + + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::ping::PingEvent) { } } @@ -80,16 +81,15 @@ fn three_fields() { #[allow(dead_code)] #[derive(NetworkBehaviour)] struct Foo { - ping_dialer: libp2p::ping::PeriodicPing, - ping_listener: libp2p::ping::PingListen, + ping: libp2p::ping::Ping, identify: libp2p::identify::Identify, + kad: libp2p::kad::Kademlia, #[behaviour(ignore)] foo: String, } - impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { - fn inject_event(&mut self, event: Void) { - void::unreachable(event) + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::ping::PingEvent) { } } @@ -98,6 +98,11 @@ fn three_fields() { } } + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::kad::KademliaOut) { + } + } + fn foo() { require_net_behaviour::>(); } @@ -109,13 +114,12 @@ fn custom_polling() { #[derive(NetworkBehaviour)] #[behaviour(poll_method = "foo")] struct Foo { - ping: libp2p::ping::PeriodicPing, + ping: libp2p::ping::Ping, identify: libp2p::identify::Identify, } - impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { - fn inject_event(&mut self, event: Void) { - void::unreachable(event) + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::ping::PingEvent) { } } @@ -139,13 +143,12 @@ fn custom_event_no_polling() { #[derive(NetworkBehaviour)] #[behaviour(out_event = "String")] struct Foo { - ping: libp2p::ping::PeriodicPing, + ping: libp2p::ping::Ping, identify: libp2p::identify::Identify, } - impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { - fn inject_event(&mut self, event: Void) { - void::unreachable(event) + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::ping::PingEvent) { } } @@ -165,13 +168,12 @@ fn custom_event_and_polling() { #[derive(NetworkBehaviour)] #[behaviour(poll_method = "foo", out_event = "String")] struct Foo { - ping: libp2p::ping::PeriodicPing, + ping: libp2p::ping::Ping, identify: libp2p::identify::Identify, } - impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { - fn inject_event(&mut self, event: Void) { - void::unreachable(event) + impl libp2p::core::swarm::NetworkBehaviourEventProcess for Foo { + fn inject_event(&mut self, _: libp2p::ping::PingEvent) { } } diff --git a/protocols/ping/src/dial_layer.rs b/protocols/ping/src/dial_layer.rs deleted file mode 100644 index c749904e..00000000 --- a/protocols/ping/src/dial_layer.rs +++ /dev/null @@ -1,84 +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. - -use crate::dial_handler::PeriodicPingHandler; -use futures::prelude::*; -use libp2p_core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p_core::{protocols_handler::ProtocolsHandler, PeerId}; -use std::marker::PhantomData; -use tokio_io::{AsyncRead, AsyncWrite}; -use void::Void; - -/// Network behaviour that handles receiving pings sent by other nodes. -pub struct PeriodicPing { - /// Marker to pin the generics. - marker: PhantomData, -} - -impl PeriodicPing { - /// Creates a `PeriodicPing`. - pub fn new() -> Self { - PeriodicPing { - marker: PhantomData, - } - } -} - -impl Default for PeriodicPing { - #[inline] - fn default() -> Self { - PeriodicPing::new() - } -} - -impl NetworkBehaviour for PeriodicPing -where - TSubstream: AsyncRead + AsyncWrite, -{ - type ProtocolsHandler = PeriodicPingHandler; - type OutEvent = Void; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - PeriodicPingHandler::new() - } - - fn inject_connected(&mut self, _: PeerId, _: ConnectedPoint) {} - - fn inject_disconnected(&mut self, _: &PeerId, _: ConnectedPoint) {} - - fn inject_node_event( - &mut self, - _: PeerId, - _: ::OutEvent, - ) { - } - - fn poll( - &mut self, - _: &mut PollParameters, - ) -> Async< - NetworkBehaviourAction< - ::InEvent, - Self::OutEvent, - >, - > { - Async::NotReady - } -} diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index b6fd975f..45ed723a 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -81,12 +81,99 @@ //! ``` //! -pub use self::dial_layer::PeriodicPing; -pub use self::listen_layer::PingListen; - pub mod dial_handler; pub mod listen_handler; pub mod protocol; -mod dial_layer; -mod listen_layer; +use futures::prelude::*; +use libp2p_core::either::EitherOutput; +use libp2p_core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; +use libp2p_core::{protocols_handler::ProtocolsHandler, protocols_handler::ProtocolsHandlerSelect, PeerId}; +use std::{marker::PhantomData, time::Duration}; +use tokio_io::{AsyncRead, AsyncWrite}; + +/// Network behaviour that handles receiving pings sent by other nodes and periodically pings the +/// nodes we connect to. +pub struct Ping { + /// Marker to pin the generics. + marker: PhantomData, + /// Queue of events to report to the user. + events: Vec, +} + +/// Event generated by the `Ping` behaviour. +pub enum PingEvent { + /// We have successfully pinged a peer we are connected to. + PingSuccess { + /// Id of the peer that we pinged. + peer: PeerId, + /// Time elapsed between when we sent the ping and when we received the response. + time: Duration, + } +} + +impl Ping { + /// Creates a `Ping`. + pub fn new() -> Self { + Ping { + marker: PhantomData, + events: Vec::new(), + } + } +} + +impl Default for Ping { + #[inline] + fn default() -> Self { + Ping::new() + } +} + +impl NetworkBehaviour for Ping +where + TSubstream: AsyncRead + AsyncWrite, +{ + type ProtocolsHandler = ProtocolsHandlerSelect, dial_handler::PeriodicPingHandler>; + type OutEvent = PingEvent; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + listen_handler::PingListenHandler::new() + .select(dial_handler::PeriodicPingHandler::new()) + } + + fn inject_connected(&mut self, _: PeerId, _: ConnectedPoint) {} + + fn inject_disconnected(&mut self, _: &PeerId, _: ConnectedPoint) {} + + fn inject_node_event( + &mut self, + source: PeerId, + event: ::OutEvent, + ) { + match event { + EitherOutput::Second(dial_handler::OutEvent::PingSuccess(time)) => { + self.events.push(PingEvent::PingSuccess { + peer: source, + time, + }) + }, + _ => () + } + } + + fn poll( + &mut self, + _: &mut PollParameters, + ) -> Async< + NetworkBehaviourAction< + ::InEvent, + Self::OutEvent, + >, + > { + if !self.events.is_empty() { + return Async::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0))); + } + + Async::NotReady + } +} diff --git a/protocols/ping/src/listen_layer.rs b/protocols/ping/src/listen_layer.rs deleted file mode 100644 index eafa4064..00000000 --- a/protocols/ping/src/listen_layer.rs +++ /dev/null @@ -1,84 +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. - -use crate::listen_handler::PingListenHandler; -use futures::prelude::*; -use libp2p_core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p_core::{protocols_handler::ProtocolsHandler, PeerId}; -use std::marker::PhantomData; -use tokio_io::{AsyncRead, AsyncWrite}; -use void::Void; - -/// Network behaviour that handles receiving pings sent by other nodes. -pub struct PingListen { - /// Marker to pin the generics. - marker: PhantomData, -} - -impl PingListen { - /// Creates a `PingListen`. - pub fn new() -> Self { - PingListen { - marker: PhantomData, - } - } -} - -impl Default for PingListen { - #[inline] - fn default() -> Self { - PingListen::new() - } -} - -impl NetworkBehaviour for PingListen -where - TSubstream: AsyncRead + AsyncWrite, -{ - type ProtocolsHandler = PingListenHandler; - type OutEvent = Void; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - PingListenHandler::new() - } - - fn inject_connected(&mut self, _: PeerId, _: ConnectedPoint) {} - - fn inject_disconnected(&mut self, _: &PeerId, _: ConnectedPoint) {} - - fn inject_node_event( - &mut self, - _: PeerId, - _: ::OutEvent, - ) { - } - - fn poll( - &mut self, - _: &mut PollParameters, - ) -> Async< - NetworkBehaviourAction< - ::InEvent, - Self::OutEvent, - >, - > { - Async::NotReady - } -}