From 6481aa8804a9db50926a0b12d8b831214fccac65 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 13:49:14 +0200 Subject: [PATCH 01/20] Handle unreachable case explicitly --- protocols/ping/src/handler.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index c21b234b3e3..af3b59f59ff 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -221,6 +221,7 @@ impl Handler { } // Note: This timeout only covers protocol negotiation. StreamUpgradeError::Timeout => Failure::Timeout, + StreamUpgradeError::Apply(e) => void::unreachable(e), e => Failure::Other { error: Box::new(e) }, }; From a1d9a5303fdc04e3785d52798802abdbbdc6b3bf Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 13:50:21 +0200 Subject: [PATCH 02/20] ReadyUpgrade cannot time out --- protocols/ping/src/handler.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index af3b59f59ff..5cc2505f6f0 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -220,7 +220,10 @@ impl Handler { return; } // Note: This timeout only covers protocol negotiation. - StreamUpgradeError::Timeout => Failure::Timeout, + StreamUpgradeError::Timeout => { + debug_assert!(false, "ReadyUpgrade cannot time out"); + return; + } StreamUpgradeError::Apply(e) => void::unreachable(e), e => Failure::Other { error: Box::new(e) }, }; From dcb2256ccab5f86d694ca5fd9f075cf80c848172 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 13:55:25 +0200 Subject: [PATCH 03/20] Directly map error to `Failure::Other` --- protocols/ping/src/handler.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 5cc2505f6f0..7637f7e1443 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -130,6 +130,12 @@ pub enum Failure { }, } +impl Failure { + fn other(e: impl std::error::Error + Send + 'static) -> Self { + Self::Other { error: Box::new(e) } + } +} + impl fmt::Display for Failure { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -327,8 +333,7 @@ impl ConnectionHandler for Handler { }))); } Poll::Ready(Err(e)) => { - self.pending_errors - .push_front(Failure::Other { error: Box::new(e) }); + self.pending_errors.push_front(e); } }, Some(OutboundState::Idle(stream)) => match self.timer.poll_unpin(cx) { @@ -338,8 +343,9 @@ impl ConnectionHandler for Handler { } Poll::Ready(()) => { self.timer.reset(self.config.timeout); - self.outbound = - Some(OutboundState::Ping(protocol::send_ping(stream).boxed())); + self.outbound = Some(OutboundState::Ping( + protocol::send_ping(stream).map_err(Failure::other).boxed(), + )); } }, Some(OutboundState::OpenStream) => { @@ -381,7 +387,9 @@ impl ConnectionHandler for Handler { .. }) => { self.timer.reset(self.config.timeout); - self.outbound = Some(OutboundState::Ping(protocol::send_ping(stream).boxed())); + self.outbound = Some(OutboundState::Ping( + protocol::send_ping(stream).map_err(Failure::other).boxed(), + )); } ConnectionEvent::DialUpgradeError(dial_upgrade_error) => { self.on_dial_upgrade_error(dial_upgrade_error) @@ -394,7 +402,7 @@ impl ConnectionHandler for Handler { } } -type PingFuture = BoxFuture<'static, Result<(Stream, Duration), io::Error>>; +type PingFuture = BoxFuture<'static, Result<(Stream, Duration), Failure>>; type PongFuture = BoxFuture<'static, Result>; /// The current state w.r.t. outbound pings. From 61f4b1cd564e3117673e3aa869976653b037b5a0 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 13:59:01 +0200 Subject: [PATCH 04/20] fixup! ReadyUpgrade cannot time out --- protocols/ping/src/handler.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 7637f7e1443..310e8699f61 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -354,8 +354,7 @@ impl ConnectionHandler for Handler { } None => { self.outbound = Some(OutboundState::OpenStream); - let protocol = SubstreamProtocol::new(ReadyUpgrade::new(PROTOCOL_NAME), ()) - .with_timeout(self.config.timeout); + let protocol = SubstreamProtocol::new(ReadyUpgrade::new(PROTOCOL_NAME), ()); return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol, }); From 684063884592cfe1fc063bca739c6c70fa95cd62 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:03:45 +0200 Subject: [PATCH 05/20] Embed timeout in `send_ping` --- protocols/ping/src/handler.rs | 36 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 310e8699f61..1fa3b5b4387 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -19,7 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::{protocol, PROTOCOL_NAME}; -use futures::future::BoxFuture; +use futures::future::{BoxFuture, Either}; use futures::prelude::*; use futures_timer::Delay; use libp2p_core::upgrade::ReadyUpgrade; @@ -163,9 +163,8 @@ impl Error for Failure { pub struct Handler { /// Configuration options. config: Config, - /// The timer used for the delay to the next ping as well as - /// the ping timeout. - timer: Delay, + /// The timer used for the delay to the next ping. + interval: Delay, /// Outbound ping failures that are pending to be processed by `poll()`. pending_errors: VecDeque, /// The number of consecutive ping failures that occurred. @@ -200,7 +199,7 @@ impl Handler { pub fn new(config: Config) -> Self { Handler { config, - timer: Delay::new(Duration::new(0, 0)), + interval: Delay::new(Duration::new(0, 0)), pending_errors: VecDeque::with_capacity(2), failures: 0, outbound: None, @@ -317,16 +316,12 @@ impl ConnectionHandler for Handler { match self.outbound.take() { Some(OutboundState::Ping(mut ping)) => match ping.poll_unpin(cx) { Poll::Pending => { - if self.timer.poll_unpin(cx).is_ready() { - self.pending_errors.push_front(Failure::Timeout); - } else { - self.outbound = Some(OutboundState::Ping(ping)); - break; - } + self.outbound = Some(OutboundState::Ping(ping)); + break; } Poll::Ready(Ok((stream, rtt))) => { self.failures = 0; - self.timer.reset(self.config.interval); + self.interval.reset(self.config.interval); self.outbound = Some(OutboundState::Idle(stream)); return Poll::Ready(ConnectionHandlerEvent::Custom(Ok(Success::Ping { rtt, @@ -336,15 +331,14 @@ impl ConnectionHandler for Handler { self.pending_errors.push_front(e); } }, - Some(OutboundState::Idle(stream)) => match self.timer.poll_unpin(cx) { + Some(OutboundState::Idle(stream)) => match self.interval.poll_unpin(cx) { Poll::Pending => { self.outbound = Some(OutboundState::Idle(stream)); break; } Poll::Ready(()) => { - self.timer.reset(self.config.timeout); self.outbound = Some(OutboundState::Ping( - protocol::send_ping(stream).map_err(Failure::other).boxed(), + send_ping(stream, self.config.timeout).boxed(), )); } }, @@ -385,9 +379,8 @@ impl ConnectionHandler for Handler { protocol: stream, .. }) => { - self.timer.reset(self.config.timeout); self.outbound = Some(OutboundState::Ping( - protocol::send_ping(stream).map_err(Failure::other).boxed(), + send_ping(stream, self.config.timeout).boxed(), )); } ConnectionEvent::DialUpgradeError(dial_upgrade_error) => { @@ -413,3 +406,12 @@ enum OutboundState { /// A ping is being sent and the response awaited. Ping(PingFuture), } + +/// A wrapper around [`protocol::send_ping`] that enforces a time out. +async fn send_ping(stream: Stream, timeout: Duration) -> Result<(Stream, Duration), Failure> { + match future::select(protocol::send_ping(stream), Delay::new(timeout)).await { + Either::Left((Ok((stream, rtt)), _)) => Ok((stream, rtt)), + Either::Left((Err(e), _)) => Err(Failure::other(e)), + Either::Right(((), _)) => Err(Failure::Timeout), + } +} From da502da0cb168745b9b15688d4a26338b594ec9d Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:05:05 +0200 Subject: [PATCH 06/20] Exhaustively match --- protocols/ping/src/handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 1fa3b5b4387..ca8fb1ccdcf 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -230,7 +230,7 @@ impl Handler { return; } StreamUpgradeError::Apply(e) => void::unreachable(e), - e => Failure::Other { error: Box::new(e) }, + StreamUpgradeError::Io(e) => Failure::Other { error: Box::new(e) }, }; self.pending_errors.push_front(error); From 3e9d527d12e0250240ed079c94d7e3e5833bb9b9 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:42:04 +0200 Subject: [PATCH 07/20] fixup! Embed timeout in `send_ping` --- protocols/ping/src/handler.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index ca8fb1ccdcf..367447b8798 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -409,7 +409,10 @@ enum OutboundState { /// A wrapper around [`protocol::send_ping`] that enforces a time out. async fn send_ping(stream: Stream, timeout: Duration) -> Result<(Stream, Duration), Failure> { - match future::select(protocol::send_ping(stream), Delay::new(timeout)).await { + let ping = protocol::send_ping(stream); + futures::pin_mut!(ping); + + match future::select(ping, Delay::new(timeout)).await { Either::Left((Ok((stream, rtt)), _)) => Ok((stream, rtt)), Either::Left((Err(e), _)) => Err(Failure::other(e)), Either::Right(((), _)) => Err(Failure::Timeout), From 6ea4e753f6de2910afb27c51be208918df402d4f Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:42:24 +0200 Subject: [PATCH 08/20] Remove `Result` type alias Mostly adds noise --- protocols/ping/src/handler.rs | 12 +++++++++--- protocols/ping/src/lib.rs | 5 +---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 367447b8798..67bf31ba9c0 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -239,7 +239,7 @@ impl Handler { impl ConnectionHandler for Handler { type FromBehaviour = Void; - type ToBehaviour = crate::Result; + type ToBehaviour = Result; type Error = Failure; type InboundProtocol = ReadyUpgrade; type OutboundProtocol = ReadyUpgrade; @@ -259,8 +259,14 @@ impl ConnectionHandler for Handler { fn poll( &mut self, cx: &mut Context<'_>, - ) -> Poll, (), crate::Result, Self::Error>> - { + ) -> Poll< + ConnectionHandlerEvent< + ReadyUpgrade, + (), + Result, + Self::Error, + >, + > { match self.state { State::Inactive { reported: true } => { return Poll::Pending; // nothing to do on this connection diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 85be866dbf5..2574676cb96 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -57,9 +57,6 @@ use std::{ pub use self::protocol::PROTOCOL_NAME; -/// The result of an inbound or outbound ping. -pub type Result = std::result::Result; - /// A [`NetworkBehaviour`] that responds to inbound pings and /// periodically sends outbound pings on every established connection. /// @@ -77,7 +74,7 @@ pub struct Event { /// The peer ID of the remote. pub peer: PeerId, /// The result of an inbound or outbound ping. - pub result: Result, + pub result: Result, } impl Behaviour { From ceb7121aaa2648c4f1986a589de4648e0c1df00b Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:44:29 +0200 Subject: [PATCH 09/20] Remove unnecessary path prefixes --- protocols/ping/src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 2574676cb96..0e359668914 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -103,7 +103,7 @@ impl NetworkBehaviour for Behaviour { _: PeerId, _: &Multiaddr, _: &Multiaddr, - ) -> std::result::Result, ConnectionDenied> { + ) -> Result, ConnectionDenied> { Ok(Handler::new(self.config.clone())) } @@ -113,7 +113,7 @@ impl NetworkBehaviour for Behaviour { _: PeerId, _: &Multiaddr, _: Endpoint, - ) -> std::result::Result, ConnectionDenied> { + ) -> Result, ConnectionDenied> { Ok(Handler::new(self.config.clone())) } @@ -146,10 +146,7 @@ impl NetworkBehaviour for Behaviour { } } - fn on_swarm_event( - &mut self, - event: libp2p_swarm::behaviour::FromSwarm, - ) { + fn on_swarm_event(&mut self, event: FromSwarm) { match event { FromSwarm::ConnectionEstablished(_) | FromSwarm::ConnectionClosed(_) From ceb98991fc7caa52557dfda5376ec96447ea59b7 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:46:27 +0200 Subject: [PATCH 10/20] Move logging to handler --- protocols/ping/src/handler.rs | 10 +++++++++- protocols/ping/src/lib.rs | 16 ++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 67bf31ba9c0..7f15ce96394 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -23,6 +23,7 @@ use futures::future::{BoxFuture, Either}; use futures::prelude::*; use futures_timer::Delay; use libp2p_core::upgrade::ReadyUpgrade; +use libp2p_identity::PeerId; use libp2p_swarm::handler::{ ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, }; @@ -179,6 +180,8 @@ pub struct Handler { inbound: Option, /// Tracks the state of our handler. state: State, + /// The peer we are connected to. + peer: PeerId, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -196,8 +199,9 @@ enum State { impl Handler { /// Builds a new [`Handler`] with the given configuration. - pub fn new(config: Config) -> Self { + pub fn new(config: Config, peer: PeerId) -> Self { Handler { + peer, config, interval: Delay::new(Duration::new(0, 0)), pending_errors: VecDeque::with_capacity(2), @@ -287,6 +291,8 @@ impl ConnectionHandler for Handler { self.inbound = None; } Poll::Ready(Ok(stream)) => { + log::trace!("answered inbound ping from {}", self.peer); + // A ping from a remote peer has been answered, wait for the next. self.inbound = Some(protocol::recv_ping(stream).boxed()); return Poll::Ready(ConnectionHandlerEvent::Custom(Ok(Success::Pong))); @@ -326,6 +332,8 @@ impl ConnectionHandler for Handler { break; } Poll::Ready(Ok((stream, rtt))) => { + log::debug!("latency to {} is {}ms", self.peer, rtt.as_millis()); + self.failures = 0; self.interval.reset(self.config.interval); self.outbound = Some(OutboundState::Idle(stream)); diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 0e359668914..ed30c1cd8a6 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -100,21 +100,21 @@ impl NetworkBehaviour for Behaviour { fn handle_established_inbound_connection( &mut self, _: ConnectionId, - _: PeerId, + peer: PeerId, _: &Multiaddr, _: &Multiaddr, ) -> Result, ConnectionDenied> { - Ok(Handler::new(self.config.clone())) + Ok(Handler::new(self.config.clone(), peer)) } fn handle_established_outbound_connection( &mut self, _: ConnectionId, - _: PeerId, + peer: PeerId, _: &Multiaddr, _: Endpoint, ) -> Result, ConnectionDenied> { - Ok(Handler::new(self.config.clone())) + Ok(Handler::new(self.config.clone(), peer)) } fn on_connection_handler_event( @@ -132,14 +132,6 @@ impl NetworkBehaviour for Behaviour { _: &mut impl PollParameters, ) -> Poll>> { if let Some(e) = self.events.pop_back() { - let Event { result, peer } = &e; - - match result { - Ok(Success::Ping { .. }) => log::debug!("Ping sent to {:?}", peer), - Ok(Success::Pong) => log::debug!("Ping received from {:?}", peer), - _ => {} - } - Poll::Ready(ToSwarm::GenerateEvent(e)) } else { Poll::Pending From c85456116c217e61e8a6d924ddd931433a76b038 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:50:11 +0200 Subject: [PATCH 11/20] Remove `Pong` event This simplifies the API and reduces code. The hypothesis is that nobody is really interested in `Pong` events. --- examples/ipfs-private/src/main.rs | 8 +------- examples/rendezvous/src/bin/rzv-discover.rs | 2 +- examples/rendezvous/src/bin/rzv-identify.rs | 2 +- examples/rendezvous/src/bin/rzv-register.rs | 2 +- interop-tests/src/bin/ping.rs | 2 +- misc/metrics/CHANGELOG.md | 2 ++ misc/metrics/src/ping.rs | 19 ++----------------- protocols/ping/src/handler.rs | 20 +++----------------- protocols/ping/src/lib.rs | 5 +++-- protocols/ping/tests/ping.rs | 9 +++------ 10 files changed, 18 insertions(+), 53 deletions(-) diff --git a/examples/ipfs-private/src/main.rs b/examples/ipfs-private/src/main.rs index 364cccd02a1..814379bd258 100644 --- a/examples/ipfs-private/src/main.rs +++ b/examples/ipfs-private/src/main.rs @@ -249,7 +249,7 @@ async fn main() -> Result<(), Box> { match event { ping::Event { peer, - result: Result::Ok(ping::Success::Ping { rtt }), + result: Result::Ok(rtt), } => { println!( "ping: rtt to {} is {} ms", @@ -257,12 +257,6 @@ async fn main() -> Result<(), Box> { rtt.as_millis() ); } - ping::Event { - peer, - result: Result::Ok(ping::Success::Pong), - } => { - println!("ping: pong from {}", peer.to_base58()); - } ping::Event { peer, result: Result::Err(ping::Failure::Timeout), diff --git a/examples/rendezvous/src/bin/rzv-discover.rs b/examples/rendezvous/src/bin/rzv-discover.rs index bd551c68f5a..8aac6c066af 100644 --- a/examples/rendezvous/src/bin/rzv-discover.rs +++ b/examples/rendezvous/src/bin/rzv-discover.rs @@ -105,7 +105,7 @@ async fn main() { } SwarmEvent::Behaviour(MyBehaviourEvent::Ping(ping::Event { peer, - result: Ok(ping::Success::Ping { rtt }), + result: Ok(rtt), })) if peer != rendezvous_point => { log::info!("Ping to {} is {}ms", peer, rtt.as_millis()) } diff --git a/examples/rendezvous/src/bin/rzv-identify.rs b/examples/rendezvous/src/bin/rzv-identify.rs index b970fc01a6e..c7f5e5c3f02 100644 --- a/examples/rendezvous/src/bin/rzv-identify.rs +++ b/examples/rendezvous/src/bin/rzv-identify.rs @@ -106,7 +106,7 @@ async fn main() { } SwarmEvent::Behaviour(MyBehaviourEvent::Ping(ping::Event { peer, - result: Ok(ping::Success::Ping { rtt }), + result: Ok(rtt), })) if peer != rendezvous_point => { log::info!("Ping to {} is {}ms", peer, rtt.as_millis()) } diff --git a/examples/rendezvous/src/bin/rzv-register.rs b/examples/rendezvous/src/bin/rzv-register.rs index 40053aa96b9..c0ccc893524 100644 --- a/examples/rendezvous/src/bin/rzv-register.rs +++ b/examples/rendezvous/src/bin/rzv-register.rs @@ -104,7 +104,7 @@ async fn main() { } SwarmEvent::Behaviour(MyBehaviourEvent::Ping(ping::Event { peer, - result: Ok(ping::Success::Ping { rtt }), + result: Ok(rtt), })) if peer != rendezvous_point => { log::info!("Ping to {} is {}ms", peer, rtt.as_millis()) } diff --git a/interop-tests/src/bin/ping.rs b/interop-tests/src/bin/ping.rs index 042be8b3eb8..3993c1024bb 100644 --- a/interop-tests/src/bin/ping.rs +++ b/interop-tests/src/bin/ping.rs @@ -138,7 +138,7 @@ async fn main() -> Result<()> { let rtt = loop { if let Some(SwarmEvent::Behaviour(BehaviourEvent::Ping(ping::Event { peer: _, - result: Ok(ping::Success::Ping { rtt }), + result: Ok(rtt), }))) = swarm.next().await { log::info!("Ping successful: {rtt:?}"); diff --git a/misc/metrics/CHANGELOG.md b/misc/metrics/CHANGELOG.md index ca090d60171..bc186399fc2 100644 --- a/misc/metrics/CHANGELOG.md +++ b/misc/metrics/CHANGELOG.md @@ -22,6 +22,8 @@ - Raise MSRV to 1.65. See [PR 3715]. +- TODO: Removed `pong_received`. + [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3325]: https://github.com/libp2p/rust-libp2p/pull/3325 diff --git a/misc/metrics/src/ping.rs b/misc/metrics/src/ping.rs index 195cb302675..afdd05134a6 100644 --- a/misc/metrics/src/ping.rs +++ b/misc/metrics/src/ping.rs @@ -55,7 +55,6 @@ enum Failure { pub(crate) struct Metrics { rtt: Histogram, failure: Family, - pong_received: Counter, } impl Metrics { @@ -77,28 +76,14 @@ impl Metrics { failure.clone(), ); - let pong_received = Counter::default(); - sub_registry.register( - "pong_received", - "Number of 'pong's received", - pong_received.clone(), - ); - - Self { - rtt, - failure, - pong_received, - } + Self { rtt, failure } } } impl super::Recorder for Metrics { fn record(&self, event: &libp2p_ping::Event) { match &event.result { - Ok(libp2p_ping::Success::Pong) => { - self.pong_received.inc(); - } - Ok(libp2p_ping::Success::Ping { rtt }) => { + Ok(rtt) => { self.rtt.observe(rtt.as_secs_f64()); } Err(failure) => { diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 7f15ce96394..c9ebb37ec03 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -106,17 +106,6 @@ impl Default for Config { } } -/// The successful result of processing an inbound or outbound ping. -#[derive(Debug)] -pub enum Success { - /// Received a ping and sent back a pong. - Pong, - /// Sent a ping and received back a pong. - /// - /// Includes the round-trip time. - Ping { rtt: Duration }, -} - /// An outbound ping failure. #[derive(Debug)] pub enum Failure { @@ -243,7 +232,7 @@ impl Handler { impl ConnectionHandler for Handler { type FromBehaviour = Void; - type ToBehaviour = Result; + type ToBehaviour = Result; type Error = Failure; type InboundProtocol = ReadyUpgrade; type OutboundProtocol = ReadyUpgrade; @@ -267,7 +256,7 @@ impl ConnectionHandler for Handler { ConnectionHandlerEvent< ReadyUpgrade, (), - Result, + Result, Self::Error, >, > { @@ -295,7 +284,6 @@ impl ConnectionHandler for Handler { // A ping from a remote peer has been answered, wait for the next. self.inbound = Some(protocol::recv_ping(stream).boxed()); - return Poll::Ready(ConnectionHandlerEvent::Custom(Ok(Success::Pong))); } } } @@ -337,9 +325,7 @@ impl ConnectionHandler for Handler { self.failures = 0; self.interval.reset(self.config.interval); self.outbound = Some(OutboundState::Idle(stream)); - return Poll::Ready(ConnectionHandlerEvent::Custom(Ok(Success::Ping { - rtt, - }))); + return Poll::Ready(ConnectionHandlerEvent::Custom(Ok(rtt))); } Poll::Ready(Err(e)) => { self.pending_errors.push_front(e); diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index ed30c1cd8a6..02ae7956093 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -43,19 +43,20 @@ mod handler; mod protocol; use handler::Handler; -pub use handler::{Config, Failure, Success}; use libp2p_core::{Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_swarm::{ behaviour::FromSwarm, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }; +use std::time::Duration; use std::{ collections::VecDeque, task::{Context, Poll}, }; pub use self::protocol::PROTOCOL_NAME; +pub use handler::{Config, Failure}; /// A [`NetworkBehaviour`] that responds to inbound pings and /// periodically sends outbound pings on every established connection. @@ -74,7 +75,7 @@ pub struct Event { /// The peer ID of the remote. pub peer: PeerId, /// The result of an inbound or outbound ping. - pub result: Result, + pub result: Result, } impl Behaviour { diff --git a/protocols/ping/tests/ping.rs b/protocols/ping/tests/ping.rs index 4616b4fc81b..49a3252894c 100644 --- a/protocols/ping/tests/ping.rs +++ b/protocols/ping/tests/ping.rs @@ -59,11 +59,9 @@ fn ping_pong() { } fn assert_ping_rtt_less_than_50ms(e: ping::Event) { - let success = e.result.expect("a ping success"); + let rtt = e.result.expect("a ping success"); - if let ping::Success::Ping { rtt } = success { - assert!(rtt < Duration::from_millis(50)) - } + assert!(rtt < Duration::from_millis(50)) } /// Tests that the connection is closed upon a configurable @@ -102,8 +100,7 @@ async fn count_ping_failures_until_connection_closed(mut swarm: Swarm loop { match swarm.next_swarm_event().await { SwarmEvent::Behaviour(BehaviourEvent::Ping(ping::Event { - result: Ok(ping::Success::Ping { .. }), - .. + result: Ok(_rtt), .. })) => { failure_count = 0; // there may be an occasional success } From 32407257968959210ee46a5bf4c514e7b27177d8 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 15 May 2023 14:56:31 +0200 Subject: [PATCH 12/20] Don't close connection --- protocols/ping/CHANGELOG.md | 6 ++++ protocols/ping/src/handler.rs | 41 ++++----------------------- protocols/ping/tests/ping.rs | 52 ----------------------------------- 3 files changed, 12 insertions(+), 87 deletions(-) diff --git a/protocols/ping/CHANGELOG.md b/protocols/ping/CHANGELOG.md index f925c6e83fc..6c3f7de7297 100644 --- a/protocols/ping/CHANGELOG.md +++ b/protocols/ping/CHANGELOG.md @@ -2,10 +2,16 @@ - Raise MSRV to 1.65. See [PR 3715]. + - Remove deprecated items. See [PR 3702]. +- Don't close connections on ping failures. + This also removes the `max_failures` config option. + See [PR XXXX]. + [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3702]: https://github.com/libp2p/rust-libp2p/pull/3702 +[PR XXXX]: https://github.com/libp2p/rust-libp2p/pull/XXXX ## 0.42.0 diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index c9ebb37ec03..d064ac88a60 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -35,7 +35,6 @@ use std::collections::VecDeque; use std::{ error::Error, fmt, io, - num::NonZeroU32, task::{Context, Poll}, time::Duration, }; @@ -46,13 +45,8 @@ use void::Void; pub struct Config { /// The timeout of an outbound ping. timeout: Duration, - /// The duration between the last successful outbound or inbound ping - /// and the next outbound ping. + /// The duration between outbound pings. interval: Duration, - /// The maximum number of failed outbound pings before the associated - /// connection is deemed unhealthy, indicating to the `Swarm` that it - /// should be closed. - max_failures: NonZeroU32, } impl Config { @@ -60,23 +54,16 @@ impl Config { /// /// * [`Config::with_interval`] 15s /// * [`Config::with_timeout`] 20s - /// * [`Config::with_max_failures`] 1 /// /// These settings have the following effect: /// /// * A ping is sent every 15 seconds on a healthy connection. /// * Every ping sent must yield a response within 20 seconds in order to /// be successful. - /// * A single ping failure is sufficient for the connection to be subject - /// to being closed. - /// * The connection may be closed at any time as far as the ping protocol - /// is concerned, i.e. the ping protocol itself does not keep the - /// connection alive. pub fn new() -> Self { Self { timeout: Duration::from_secs(20), interval: Duration::from_secs(15), - max_failures: NonZeroU32::new(1).expect("1 != 0"), } } @@ -91,13 +78,6 @@ impl Config { self.interval = d; self } - - /// Sets the maximum number of consecutive ping failures upon which the remote - /// peer is considered unreachable and the connection closed. - pub fn with_max_failures(mut self, n: NonZeroU32) -> Self { - self.max_failures = n; - self - } } impl Default for Config { @@ -148,8 +128,6 @@ impl Error for Failure { /// Protocol handler that handles pinging the remote at a regular period /// and answering ping queries. -/// -/// If the remote doesn't respond, produces an error that closes the connection. pub struct Handler { /// Configuration options. config: Config, @@ -233,7 +211,7 @@ impl Handler { impl ConnectionHandler for Handler { type FromBehaviour = Void; type ToBehaviour = Result; - type Error = Failure; + type Error = Void; type InboundProtocol = ReadyUpgrade; type OutboundProtocol = ReadyUpgrade; type OutboundOpenInfo = (); @@ -295,19 +273,12 @@ impl ConnectionHandler for Handler { self.failures += 1; - // Note: For backward-compatibility, with configured - // `max_failures == 1`, the first failure is always "free" - // and silent. This allows peers who still use a new substream + // Note: For backward-compatibility the first failure is always "free" + // and silent. This allows peers who use a new substream // for each ping to have successful ping exchanges with peers // that use a single substream, since every successful ping - // resets `failures` to `0`, while at the same time emitting - // events only for `max_failures - 1` failures, as before. - if self.failures > 1 || self.config.max_failures.get() > 1 { - if self.failures >= self.config.max_failures.get() { - log::debug!("Too many failures ({}). Closing connection.", self.failures); - return Poll::Ready(ConnectionHandlerEvent::Close(error)); - } - + // resets `failures` to `0`. + if self.failures > 1 { return Poll::Ready(ConnectionHandlerEvent::Custom(Err(error))); } } diff --git a/protocols/ping/tests/ping.rs b/protocols/ping/tests/ping.rs index 49a3252894c..63836a15a78 100644 --- a/protocols/ping/tests/ping.rs +++ b/protocols/ping/tests/ping.rs @@ -20,7 +20,6 @@ //! Integration tests for the `Ping` network behaviour. -use futures::prelude::*; use libp2p_ping as ping; use libp2p_swarm::keep_alive; use libp2p_swarm::{NetworkBehaviour, Swarm, SwarmEvent}; @@ -64,57 +63,6 @@ fn assert_ping_rtt_less_than_50ms(e: ping::Event) { assert!(rtt < Duration::from_millis(50)) } -/// Tests that the connection is closed upon a configurable -/// number of consecutive ping failures. -#[test] -fn max_failures() { - fn prop(max_failures: NonZeroU8) { - let cfg = ping::Config::new() - .with_interval(Duration::from_millis(10)) - .with_timeout(Duration::from_millis(0)) - .with_max_failures(max_failures.into()); - - let mut swarm1 = Swarm::new_ephemeral(|_| Behaviour::new(cfg.clone())); - let mut swarm2 = Swarm::new_ephemeral(|_| Behaviour::new(cfg.clone())); - - let (count1, count2) = async_std::task::block_on(async { - swarm1.listen().await; - swarm2.connect(&mut swarm1).await; - - future::join( - count_ping_failures_until_connection_closed(swarm1), - count_ping_failures_until_connection_closed(swarm2), - ) - .await - }); - - assert_eq!(u8::max(count1, count2), max_failures.get() - 1); - } - - QuickCheck::new().tests(10).quickcheck(prop as fn(_)) -} - -async fn count_ping_failures_until_connection_closed(mut swarm: Swarm) -> u8 { - let mut failure_count = 0; - - loop { - match swarm.next_swarm_event().await { - SwarmEvent::Behaviour(BehaviourEvent::Ping(ping::Event { - result: Ok(_rtt), .. - })) => { - failure_count = 0; // there may be an occasional success - } - SwarmEvent::Behaviour(BehaviourEvent::Ping(ping::Event { result: Err(_), .. })) => { - failure_count += 1; - } - SwarmEvent::ConnectionClosed { .. } => { - return failure_count; - } - _ => {} - } - } -} - #[test] fn unsupported_doesnt_fail() { let mut swarm1 = Swarm::new_ephemeral(|_| keep_alive::Behaviour); From 458b35a9445b60eb519698bf4fe125807122a971 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 16 May 2023 06:34:54 +1000 Subject: [PATCH 13/20] Apply suggestions from code review --- misc/metrics/CHANGELOG.md | 4 +++- protocols/ping/CHANGELOG.md | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/misc/metrics/CHANGELOG.md b/misc/metrics/CHANGELOG.md index bc186399fc2..cc14819fe52 100644 --- a/misc/metrics/CHANGELOG.md +++ b/misc/metrics/CHANGELOG.md @@ -22,10 +22,12 @@ - Raise MSRV to 1.65. See [PR 3715]. -- TODO: Removed `pong_received`. +- Remove the `pong_received` counter because it is no longer exposed by `libp2p-ping`. + See [PR 3947]. [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3325]: https://github.com/libp2p/rust-libp2p/pull/3325 +[PR 3947]: https://github.com/libp2p/rust-libp2p/pull/3947 ## 0.12.0 diff --git a/protocols/ping/CHANGELOG.md b/protocols/ping/CHANGELOG.md index 6c3f7de7297..6d39ee326c0 100644 --- a/protocols/ping/CHANGELOG.md +++ b/protocols/ping/CHANGELOG.md @@ -7,11 +7,11 @@ - Don't close connections on ping failures. This also removes the `max_failures` config option. - See [PR XXXX]. + See [PR 3947]. [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3702]: https://github.com/libp2p/rust-libp2p/pull/3702 -[PR XXXX]: https://github.com/libp2p/rust-libp2p/pull/XXXX +[PR 3947]: https://github.com/libp2p/rust-libp2p/pull/3947 ## 0.42.0 From 2a910fa359df9edf72995256ed28f7301baec929 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 23 May 2023 22:05:21 +0200 Subject: [PATCH 14/20] Add `Swarm::close_connection` API --- swarm/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 0f2f3fc1093..a5e01d0b5b4 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -732,6 +732,24 @@ where } } + /// Attempt to gracefully close a connection. + /// + /// Closing a connection is asynchronous but this function will return immediately. + /// A [`SwarmEvent::ConnectionClosed`] event will be emitted once the connection is actually closed. + /// + /// # Returns + /// + /// - `true` if the connection was established and is now being closed. + /// - `false` if the connection was not found or is no longer established. + pub fn close_connection(&mut self, connection_id: ConnectionId) -> bool { + if let Some(established) = self.pool.get_established(connection_id) { + established.start_close(); + return true; + } + + false + } + /// Checks whether there is an established connection to a peer. pub fn is_connected(&self, peer_id: &PeerId) -> bool { self.pool.is_connected(*peer_id) From 772c8916c761fdb8743ee6d23acdd3a3ea16be61 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 23 May 2023 22:07:25 +0200 Subject: [PATCH 15/20] Expose connection ID on event --- protocols/ping/src/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 02ae7956093..617dbf1a67b 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -74,6 +74,8 @@ pub struct Behaviour { pub struct Event { /// The peer ID of the remote. pub peer: PeerId, + /// The connection the ping was executed on. + pub connection: ConnectionId, /// The result of an inbound or outbound ping. pub result: Result, } @@ -121,10 +123,14 @@ impl NetworkBehaviour for Behaviour { fn on_connection_handler_event( &mut self, peer: PeerId, - _: ConnectionId, + connection: ConnectionId, result: THandlerOutEvent, ) { - self.events.push_front(Event { peer, result }) + self.events.push_front(Event { + peer, + connection, + result, + }) } fn poll( From ea7c01c59060b2677005249e7e20a78311613f15 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 24 May 2023 06:08:54 +1000 Subject: [PATCH 16/20] Update protocols/ping/CHANGELOG.md --- protocols/ping/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/ping/CHANGELOG.md b/protocols/ping/CHANGELOG.md index 6d39ee326c0..f014ca8e6c9 100644 --- a/protocols/ping/CHANGELOG.md +++ b/protocols/ping/CHANGELOG.md @@ -6,6 +6,7 @@ - Remove deprecated items. See [PR 3702]. - Don't close connections on ping failures. + To restore the previous behaviour, users should call `Swarm::close_connection` upon receiving a `ping::Event` with a `ping::Failure`. This also removes the `max_failures` config option. See [PR 3947]. From c1fe6a1f010942b1c4f7948bbfa14efe59af59ae Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 23 May 2023 22:14:44 +0200 Subject: [PATCH 17/20] Document health check / connection management with ping --- protocols/ping/src/lib.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 617dbf1a67b..5ce355ddf69 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -28,12 +28,24 @@ //! //! The [`Behaviour`] struct implements the [`NetworkBehaviour`] trait. When used with a [`Swarm`], //! it will respond to inbound ping requests and as necessary periodically send outbound -//! ping requests on every established connection. If a configurable number of consecutive -//! pings fail, the connection will be closed. +//! ping requests on every established connection. //! //! The [`Behaviour`] network behaviour produces [`Event`]s, which may be consumed from the [`Swarm`] //! by an application, e.g. to collect statistics. //! +//! # Health checks / connection management +//! +//! It is up to the user to implement a health-check / connection management policy based on the ping protocol. +//! +//! For example: +//! +//! - Disconnect from peers with an RTT > 200ms +//! - Disconnect from peers which don't support the ping protocol +//! - Disconnect from peers upon the first ping failure +//! +//! Users should inspect emitted [`Event`] and call APIs on [`Swarm`] such as [`Swarm::close_connection`] +//! or [`Swarm::disconnect_peer_id`] as they see fit. +//! //! [`Swarm`]: libp2p_swarm::Swarm //! [`Transport`]: libp2p_core::Transport @@ -45,10 +57,7 @@ mod protocol; use handler::Handler; use libp2p_core::{Endpoint, Multiaddr}; use libp2p_identity::PeerId; -use libp2p_swarm::{ - behaviour::FromSwarm, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, - THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, -}; +use libp2p_swarm::{behaviour::FromSwarm, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, Swarm, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm}; use std::time::Duration; use std::{ collections::VecDeque, From ad6a882581a98800dc13f08229e1284b7b03721b Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 24 May 2023 10:28:19 +0200 Subject: [PATCH 18/20] Fix compile errors --- examples/ipfs-private/src/main.rs | 4 ++++ examples/rendezvous/src/bin/rzv-discover.rs | 1 + examples/rendezvous/src/bin/rzv-identify.rs | 1 + examples/rendezvous/src/bin/rzv-register.rs | 1 + interop-tests/src/bin/ping.rs | 2 +- protocols/ping/src/lib.rs | 5 ++++- 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/ipfs-private/src/main.rs b/examples/ipfs-private/src/main.rs index 814379bd258..d55b98c7941 100644 --- a/examples/ipfs-private/src/main.rs +++ b/examples/ipfs-private/src/main.rs @@ -250,6 +250,7 @@ async fn main() -> Result<(), Box> { ping::Event { peer, result: Result::Ok(rtt), + .. } => { println!( "ping: rtt to {} is {} ms", @@ -260,18 +261,21 @@ async fn main() -> Result<(), Box> { ping::Event { peer, result: Result::Err(ping::Failure::Timeout), + .. } => { println!("ping: timeout to {}", peer.to_base58()); } ping::Event { peer, result: Result::Err(ping::Failure::Unsupported), + .. } => { println!("ping: {} does not support ping protocol", peer.to_base58()); } ping::Event { peer, result: Result::Err(ping::Failure::Other { error }), + .. } => { println!("ping: ping::Failure with {}: {error}", peer.to_base58()); } diff --git a/examples/rendezvous/src/bin/rzv-discover.rs b/examples/rendezvous/src/bin/rzv-discover.rs index 8aac6c066af..8eb8b623791 100644 --- a/examples/rendezvous/src/bin/rzv-discover.rs +++ b/examples/rendezvous/src/bin/rzv-discover.rs @@ -106,6 +106,7 @@ async fn main() { SwarmEvent::Behaviour(MyBehaviourEvent::Ping(ping::Event { peer, result: Ok(rtt), + .. })) if peer != rendezvous_point => { log::info!("Ping to {} is {}ms", peer, rtt.as_millis()) } diff --git a/examples/rendezvous/src/bin/rzv-identify.rs b/examples/rendezvous/src/bin/rzv-identify.rs index c7f5e5c3f02..406f15bdcdb 100644 --- a/examples/rendezvous/src/bin/rzv-identify.rs +++ b/examples/rendezvous/src/bin/rzv-identify.rs @@ -107,6 +107,7 @@ async fn main() { SwarmEvent::Behaviour(MyBehaviourEvent::Ping(ping::Event { peer, result: Ok(rtt), + .. })) if peer != rendezvous_point => { log::info!("Ping to {} is {}ms", peer, rtt.as_millis()) } diff --git a/examples/rendezvous/src/bin/rzv-register.rs b/examples/rendezvous/src/bin/rzv-register.rs index c0ccc893524..9b9ed0da72f 100644 --- a/examples/rendezvous/src/bin/rzv-register.rs +++ b/examples/rendezvous/src/bin/rzv-register.rs @@ -105,6 +105,7 @@ async fn main() { SwarmEvent::Behaviour(MyBehaviourEvent::Ping(ping::Event { peer, result: Ok(rtt), + .. })) if peer != rendezvous_point => { log::info!("Ping to {} is {}ms", peer, rtt.as_millis()) } diff --git a/interop-tests/src/bin/ping.rs b/interop-tests/src/bin/ping.rs index 3993c1024bb..23cc86f4571 100644 --- a/interop-tests/src/bin/ping.rs +++ b/interop-tests/src/bin/ping.rs @@ -137,8 +137,8 @@ async fn main() -> Result<()> { let rtt = loop { if let Some(SwarmEvent::Behaviour(BehaviourEvent::Ping(ping::Event { - peer: _, result: Ok(rtt), + .. }))) = swarm.next().await { log::info!("Ping successful: {rtt:?}"); diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 5ce355ddf69..95f33b39063 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -57,7 +57,10 @@ mod protocol; use handler::Handler; use libp2p_core::{Endpoint, Multiaddr}; use libp2p_identity::PeerId; -use libp2p_swarm::{behaviour::FromSwarm, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, Swarm, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm}; +use libp2p_swarm::{ + behaviour::FromSwarm, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, + THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, +}; use std::time::Duration; use std::{ collections::VecDeque, From 9c4a656c4f473adfc76aa35a32f1d196fc1c77c2 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 24 May 2023 13:55:23 +0200 Subject: [PATCH 19/20] Tidy up docs --- protocols/ping/src/lib.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 95f33b39063..229baffbe42 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -26,14 +26,8 @@ //! //! # Usage //! -//! The [`Behaviour`] struct implements the [`NetworkBehaviour`] trait. When used with a [`Swarm`], -//! it will respond to inbound ping requests and as necessary periodically send outbound -//! ping requests on every established connection. -//! -//! The [`Behaviour`] network behaviour produces [`Event`]s, which may be consumed from the [`Swarm`] -//! by an application, e.g. to collect statistics. -//! -//! # Health checks / connection management +//! The [`Behaviour`] struct implements the [`NetworkBehaviour`] trait. +//! It will respond to inbound ping requests and periodically send outbound ping requests on every established connection. //! //! It is up to the user to implement a health-check / connection management policy based on the ping protocol. //! @@ -43,8 +37,10 @@ //! - Disconnect from peers which don't support the ping protocol //! - Disconnect from peers upon the first ping failure //! -//! Users should inspect emitted [`Event`] and call APIs on [`Swarm`] such as [`Swarm::close_connection`] -//! or [`Swarm::disconnect_peer_id`] as they see fit. +//! Users should inspect emitted [`Event`] and call APIs on [`Swarm`]: +//! +//! - [`Swarm::close_connection`](libp2p_swarm::Swarm::close_connection) to close a specific connection +//! - [`Swarm::disconnect_peer_id`](libp2p_swarm::Swarm::disconnect_peer_id) to close all connections to a peer //! //! [`Swarm`]: libp2p_swarm::Swarm //! [`Transport`]: libp2p_core::Transport From 5c79d3028b7602dc607ea6f5858de55d94f852f3 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 24 May 2023 13:55:45 +0200 Subject: [PATCH 20/20] Fix typo --- protocols/ping/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/ping/src/lib.rs b/protocols/ping/src/lib.rs index 229baffbe42..04a6c20a7c1 100644 --- a/protocols/ping/src/lib.rs +++ b/protocols/ping/src/lib.rs @@ -37,7 +37,7 @@ //! - Disconnect from peers which don't support the ping protocol //! - Disconnect from peers upon the first ping failure //! -//! Users should inspect emitted [`Event`] and call APIs on [`Swarm`]: +//! Users should inspect emitted [`Event`]s and call APIs on [`Swarm`]: //! //! - [`Swarm::close_connection`](libp2p_swarm::Swarm::close_connection) to close a specific connection //! - [`Swarm::disconnect_peer_id`](libp2p_swarm::Swarm::disconnect_peer_id) to close all connections to a peer