libp2p_ping/lib.rs
1// Copyright 2017-2018 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! This module implements the `/ipfs/ping/1.0.0` protocol.
22//!
23//! The ping protocol can be used as a simple application-layer health check
24//! for connections of any [`Transport`] as well as to measure and record
25//! round-trip times.
26//!
27//! # Usage
28//!
29//! The [`Ping`] struct implements the [`NetworkBehaviour`] trait. When used with a [`Swarm`],
30//! it will respond to inbound ping requests and as necessary periodically send outbound
31//! ping requests on every established connection. If a configurable number of consecutive
32//! pings fail, the connection will be closed.
33//!
34//! The `Ping` network behaviour produces [`PingEvent`]s, which may be consumed from the `Swarm`
35//! by an application, e.g. to collect statistics.
36//!
37//! > **Note**: The ping protocol does not keep otherwise idle connections alive
38//! > by default, see [`PingConfig::with_keep_alive`] for changing this behaviour.
39//!
40//! [`Swarm`]: libp2p_swarm::Swarm
41//! [`Transport`]: libp2p_core::Transport
42
43pub mod protocol;
44pub mod handler;
45
46pub use handler::{PingConfig, PingResult, PingSuccess, PingFailure};
47use handler::PingHandler;
48
49use libp2p_core::{Multiaddr, PeerId, connection::ConnectionId};
50use libp2p_swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters};
51use std::{collections::VecDeque, task::Context, task::Poll};
52use void::Void;
53
54/// `Ping` is a [`NetworkBehaviour`] that responds to inbound pings and
55/// periodically sends outbound pings on every established connection.
56///
57/// See the crate root documentation for more information.
58pub struct Ping {
59 /// Configuration for outbound pings.
60 config: PingConfig,
61 /// Queue of events to yield to the swarm.
62 events: VecDeque<PingEvent>,
63}
64
65/// Event generated by the `Ping` network behaviour.
66#[derive(Debug)]
67pub struct PingEvent {
68 /// The peer ID of the remote.
69 pub peer: PeerId,
70 /// The result of an inbound or outbound ping.
71 pub result: PingResult,
72}
73
74impl Ping {
75 /// Creates a new `Ping` network behaviour with the given configuration.
76 pub fn new(config: PingConfig) -> Self {
77 Ping {
78 config,
79 events: VecDeque::new(),
80 }
81 }
82}
83
84impl Default for Ping {
85 fn default() -> Self {
86 Ping::new(PingConfig::new())
87 }
88}
89
90impl NetworkBehaviour for Ping {
91 type ProtocolsHandler = PingHandler;
92 type OutEvent = PingEvent;
93
94 fn new_handler(&mut self) -> Self::ProtocolsHandler {
95 PingHandler::new(self.config.clone())
96 }
97
98 fn addresses_of_peer(&mut self, _peer_id: &PeerId) -> Vec<Multiaddr> {
99 Vec::new()
100 }
101
102 fn inject_connected(&mut self, _: &PeerId) {}
103
104 fn inject_disconnected(&mut self, _: &PeerId) {}
105
106 fn inject_event(&mut self, peer: PeerId, _: ConnectionId, result: PingResult) {
107 self.events.push_front(PingEvent { peer, result })
108 }
109
110 fn poll(&mut self, _: &mut Context<'_>, _: &mut impl PollParameters)
111 -> Poll<NetworkBehaviourAction<Void, PingEvent>>
112 {
113 if let Some(e) = self.events.pop_back() {
114 Poll::Ready(NetworkBehaviourAction::GenerateEvent(e))
115 } else {
116 Poll::Pending
117 }
118 }
119}