mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-27 00:31:35 +00:00
Add back simple, optional keep-alive to libp2p-ping. (#1088)
This is now a very simple option serving multiple purposes: * It allows for stable (integration) tests involving a Swarm, which are otherwise subject to race conditions due to the connection being allowed to terminate at any time with `KeepAlive::No` (which remains the default). * It makes for a more entertaining ping example which continuously sends pings. * Maybe someone wants to use the ping protocol for application-layer connection keep-alive after all.
This commit is contained in:
@ -39,7 +39,7 @@
|
|||||||
//! and begin pinging each other.
|
//! and begin pinging each other.
|
||||||
|
|
||||||
use futures::{prelude::*, future};
|
use futures::{prelude::*, future};
|
||||||
use libp2p::{ identity, PeerId, ping::Ping, Swarm };
|
use libp2p::{ identity, PeerId, ping::{Ping, PingConfig}, Swarm };
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -54,7 +54,11 @@ fn main() {
|
|||||||
let transport = libp2p::build_development_transport(id_keys);
|
let transport = libp2p::build_development_transport(id_keys);
|
||||||
|
|
||||||
// Create a ping network behaviour.
|
// Create a ping network behaviour.
|
||||||
let behaviour = Ping::default();
|
//
|
||||||
|
// For illustrative purposes, the ping protocol is configured to
|
||||||
|
// keep the connection alive, so a continuous sequence of pings
|
||||||
|
// can be observed.
|
||||||
|
let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));
|
||||||
|
|
||||||
// Create a Swarm that establishes connections through the given transport
|
// Create a Swarm that establishes connections through the given transport
|
||||||
// and applies the ping behaviour on each connection.
|
// and applies the ping behaviour on each connection.
|
||||||
|
@ -45,6 +45,9 @@ pub struct PingConfig {
|
|||||||
/// connection is deemed unhealthy, indicating to the `Swarm` that it
|
/// connection is deemed unhealthy, indicating to the `Swarm` that it
|
||||||
/// should be closed.
|
/// should be closed.
|
||||||
max_failures: NonZeroU32,
|
max_failures: NonZeroU32,
|
||||||
|
/// Whether the connection should generally be kept alive unless
|
||||||
|
/// `max_failures` occur.
|
||||||
|
keep_alive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PingConfig {
|
impl PingConfig {
|
||||||
@ -53,6 +56,7 @@ impl PingConfig {
|
|||||||
/// * [`PingConfig::with_interval`] 15s
|
/// * [`PingConfig::with_interval`] 15s
|
||||||
/// * [`PingConfig::with_timeout`] 20s
|
/// * [`PingConfig::with_timeout`] 20s
|
||||||
/// * [`PingConfig::with_max_failures`] 1
|
/// * [`PingConfig::with_max_failures`] 1
|
||||||
|
/// * [`PingConfig::with_keep_alive`] false
|
||||||
///
|
///
|
||||||
/// These settings have the following effect:
|
/// These settings have the following effect:
|
||||||
///
|
///
|
||||||
@ -61,11 +65,15 @@ impl PingConfig {
|
|||||||
/// be successful.
|
/// be successful.
|
||||||
/// * A single ping failure is sufficient for the connection to be subject
|
/// * A single ping failure is sufficient for the connection to be subject
|
||||||
/// to being closed.
|
/// 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 {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
timeout: Duration::from_secs(20),
|
timeout: Duration::from_secs(20),
|
||||||
interval: Duration::from_secs(15),
|
interval: Duration::from_secs(15),
|
||||||
max_failures: NonZeroU32::new(1).expect("1 != 0"),
|
max_failures: NonZeroU32::new(1).expect("1 != 0"),
|
||||||
|
keep_alive: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +95,21 @@ impl PingConfig {
|
|||||||
self.max_failures = n;
|
self.max_failures = n;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets whether the ping protocol itself should keep the connection alive,
|
||||||
|
/// apart from the maximum allowed failures.
|
||||||
|
///
|
||||||
|
/// By default, the ping protocol itself allows the connection to be closed
|
||||||
|
/// at any time, i.e. in the absence of ping failures the connection lifetime
|
||||||
|
/// is determined by other protocol handlers.
|
||||||
|
///
|
||||||
|
/// If the maximum number of allowed ping failures is reached, the
|
||||||
|
/// connection is always terminated as a result of [`PingHandler::poll`]
|
||||||
|
/// returning an error, regardless of the keep-alive setting.
|
||||||
|
pub fn with_keep_alive(mut self, b: bool) -> Self {
|
||||||
|
self.keep_alive = b;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of an inbound or outbound ping.
|
/// The result of an inbound or outbound ping.
|
||||||
@ -198,11 +221,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn connection_keep_alive(&self) -> KeepAlive {
|
fn connection_keep_alive(&self) -> KeepAlive {
|
||||||
// Returning `Now` indicates that, as far as this handler is concerned,
|
if self.config.keep_alive {
|
||||||
// the connection may be closed. I.e. the ping handler does not keep
|
KeepAlive::Yes
|
||||||
// the connection alive, it merely adds another condition (failed pings)
|
} else {
|
||||||
// for terminating it.
|
KeepAlive::No
|
||||||
KeepAlive::No
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<ProtocolsHandlerEvent<protocol::Ping, (), PingResult>, Self::Error> {
|
fn poll(&mut self) -> Poll<ProtocolsHandlerEvent<protocol::Ping, (), PingResult>, Self::Error> {
|
||||||
|
@ -39,11 +39,13 @@ use tokio::runtime::Runtime;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ping() {
|
fn ping() {
|
||||||
|
let cfg = PingConfig::new().with_keep_alive(true);
|
||||||
|
|
||||||
let (peer1_id, trans) = mk_transport();
|
let (peer1_id, trans) = mk_transport();
|
||||||
let mut swarm1 = Swarm::new(trans, Ping::default(), peer1_id.clone());
|
let mut swarm1 = Swarm::new(trans, Ping::new(cfg.clone()), peer1_id.clone());
|
||||||
|
|
||||||
let (peer2_id, trans) = mk_transport();
|
let (peer2_id, trans) = mk_transport();
|
||||||
let mut swarm2 = Swarm::new(trans, Ping::default(), peer2_id.clone());
|
let mut swarm2 = Swarm::new(trans, Ping::new(cfg), peer2_id.clone());
|
||||||
|
|
||||||
let (tx, rx) = sync_channel::<Multiaddr>(1);
|
let (tx, rx) = sync_channel::<Multiaddr>(1);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user