Skip to content

Commit

Permalink
feat(swarm): allow configuration to idle connection timeout
Browse files Browse the repository at this point in the history
Previously, a connection would be shut down immediately as soon as its `ConnectionHandler` reports `KeepAlive::No`. As we have gained experience with libp2p, it turned out that this isn't ideal.

For one, tests often need to keep connections alive longer than the configured protocols require. Plus, some usecases require connections to be kept alive in general.

Both of these needs are currently served by the `keep_alive::Behaviour`. That one does essentially nothing other than statically returning `KeepAlive::Yes` from its `ConnectionHandler`.

It makes much more sense to deprecate `keep_alive::Behaviour` and instead allow users to globally configure an `idle_conncetion_timeout` on the `Swarm`. This timeout comes into effect once a `ConnectionHandler` reports `KeepAlive::No`. To start with, this timeout is 0. Together with libp2p#3844, this will allow us to move towards a much more aggressive closing of idle connections, together with a more ergonomic way of opting out of this behaviour.

Fixes libp2p#4121.

Pull-Request: libp2p#4161.
  • Loading branch information
startup-dreamer authored and thomaseizinger committed Sep 20, 2023
1 parent d14eb90 commit 2de759c
Show file tree
Hide file tree
Showing 22 changed files with 378 additions and 331 deletions.
19 changes: 6 additions & 13 deletions examples/browser-webrtc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use libp2p::{
identity,
multiaddr::{Multiaddr, Protocol},
ping,
swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{SwarmBuilder, SwarmEvent},
};
use libp2p_webrtc as webrtc;
use rand::thread_rng;
use std::net::{Ipv4Addr, SocketAddr};
use std::time::Duration;
use tower_http::cors::{Any, CorsLayer};

#[tokio::main]
Expand All @@ -36,12 +37,10 @@ async fn main() -> anyhow::Result<()> {
.map(|(peer_id, conn), _| (peer_id, StreamMuxerBox::new(conn)))
.boxed();

let behaviour = Behaviour {
ping: ping::Behaviour::new(ping::Config::new()),
keep_alive: keep_alive::Behaviour,
};

let mut swarm = SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build();
let mut swarm =
SwarmBuilder::with_tokio_executor(transport, ping::Behaviour::default(), local_peer_id)
.idle_connection_timeout(Duration::from_secs(30)) // Allows us to observe the pings.
.build();

let address_webrtc = Multiaddr::from(Ipv4Addr::UNSPECIFIED)
.with(Protocol::Udp(0))
Expand Down Expand Up @@ -84,12 +83,6 @@ async fn main() -> anyhow::Result<()> {
Ok(())
}

#[derive(NetworkBehaviour)]
struct Behaviour {
ping: ping::Behaviour,
keep_alive: keep_alive::Behaviour,
}

#[derive(rust_embed::RustEmbed)]
#[folder = "$CARGO_MANIFEST_DIR/static"]
struct StaticFiles;
Expand Down
9 changes: 3 additions & 6 deletions examples/metrics/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ use futures::stream::StreamExt;
use libp2p::core::{upgrade::Version, Multiaddr, Transport};
use libp2p::identity::PeerId;
use libp2p::metrics::{Metrics, Recorder};
use libp2p::swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent};
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent};
use libp2p::{identify, identity, noise, ping, tcp, yamux};
use log::info;
use prometheus_client::registry::Registry;
use std::error::Error;
use std::thread;
use std::time::Duration;

mod http_service;

Expand All @@ -51,6 +52,7 @@ fn main() -> Result<(), Box<dyn Error>> {
Behaviour::new(local_pub_key),
local_peer_id,
)
.idle_connection_timeout(Duration::from_secs(60))
.build();

swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
Expand Down Expand Up @@ -87,13 +89,9 @@ fn main() -> Result<(), Box<dyn Error>> {
}

/// Our network behaviour.
///
/// For illustrative purposes, this includes the [`keep_alive::Behaviour`]) behaviour so the ping actually happen
/// and can be observed via the metrics.
#[derive(NetworkBehaviour)]
struct Behaviour {
identify: identify::Behaviour,
keep_alive: keep_alive::Behaviour,
ping: ping::Behaviour,
}

Expand All @@ -105,7 +103,6 @@ impl Behaviour {
"/ipfs/0.1.0".into(),
local_pub_key,
)),
keep_alive: keep_alive::Behaviour,
}
}
}
16 changes: 4 additions & 12 deletions examples/ping-example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ use futures::prelude::*;
use libp2p::core::upgrade::Version;
use libp2p::{
identity, noise, ping,
swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{SwarmBuilder, SwarmEvent},
tcp, yamux, Multiaddr, PeerId, Transport,
};
use std::error::Error;
use std::time::Duration;

#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -42,7 +43,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
.boxed();

let mut swarm =
SwarmBuilder::with_async_std_executor(transport, Behaviour::default(), local_peer_id)
SwarmBuilder::with_async_std_executor(transport, ping::Behaviour::default(), local_peer_id)
.idle_connection_timeout(Duration::from_secs(60)) // For illustrative purposes, keep idle connections alive for a minute so we can observe a few pings.
.build();

// Tell the swarm to listen on all interfaces and a random, OS-assigned
Expand All @@ -65,13 +67,3 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
}
}

/// Our network behaviour.
///
/// For illustrative purposes, this includes the [`KeepAlive`](keep_alive::Behaviour) behaviour so a continuous sequence of
/// pings can be observed.
#[derive(NetworkBehaviour, Default)]
struct Behaviour {
keep_alive: keep_alive::Behaviour,
ping: ping::Behaviour,
}
5 changes: 2 additions & 3 deletions examples/rendezvous/src/bin/rzv-discover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use libp2p::{
identity,
multiaddr::Protocol,
noise, ping, rendezvous,
swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
tcp, yamux, Multiaddr, PeerId, Transport,
};
use std::time::Duration;
Expand All @@ -50,10 +50,10 @@ async fn main() {
MyBehaviour {
rendezvous: rendezvous::client::Behaviour::new(key_pair.clone()),
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
keep_alive: keep_alive::Behaviour,
},
PeerId::from(key_pair.public()),
)
.idle_connection_timeout(Duration::from_secs(5))
.build();

swarm.dial(rendezvous_point_address.clone()).unwrap();
Expand Down Expand Up @@ -127,5 +127,4 @@ async fn main() {
struct MyBehaviour {
rendezvous: rendezvous::client::Behaviour,
ping: ping::Behaviour,
keep_alive: keep_alive::Behaviour,
}
5 changes: 2 additions & 3 deletions examples/rendezvous/src/bin/rzv-identify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use futures::StreamExt;
use libp2p::{
core::transport::upgrade::Version,
identify, identity, noise, ping, rendezvous,
swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
tcp, yamux, Multiaddr, PeerId, Transport,
};
use std::time::Duration;
Expand Down Expand Up @@ -50,10 +50,10 @@ async fn main() {
)),
rendezvous: rendezvous::client::Behaviour::new(key_pair.clone()),
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
keep_alive: keep_alive::Behaviour,
},
PeerId::from(key_pair.public()),
)
.idle_connection_timeout(Duration::from_secs(5))
.build();

let _ = swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap());
Expand Down Expand Up @@ -133,5 +133,4 @@ struct MyBehaviour {
identify: identify::Behaviour,
rendezvous: rendezvous::client::Behaviour,
ping: ping::Behaviour,
keep_alive: keep_alive::Behaviour,
}
5 changes: 2 additions & 3 deletions examples/rendezvous/src/bin/rzv-register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use futures::StreamExt;
use libp2p::{
core::transport::upgrade::Version,
identity, noise, ping, rendezvous,
swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
tcp, yamux, Multiaddr, PeerId, Transport,
};
use std::time::Duration;
Expand All @@ -46,10 +46,10 @@ async fn main() {
MyBehaviour {
rendezvous: rendezvous::client::Behaviour::new(key_pair.clone()),
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
keep_alive: keep_alive::Behaviour,
},
PeerId::from(key_pair.public()),
)
.idle_connection_timeout(Duration::from_secs(5))
.build();

// In production the external address should be the publicly facing IP address of the rendezvous point.
Expand Down Expand Up @@ -130,5 +130,4 @@ async fn main() {
struct MyBehaviour {
rendezvous: rendezvous::client::Behaviour,
ping: ping::Behaviour,
keep_alive: keep_alive::Behaviour,
}
5 changes: 2 additions & 3 deletions examples/rendezvous/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use futures::StreamExt;
use libp2p::{
core::transport::upgrade::Version,
identify, identity, noise, ping, rendezvous,
swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
tcp, yamux, PeerId, Transport,
};
use std::time::Duration;
Expand All @@ -48,10 +48,10 @@ async fn main() {
)),
rendezvous: rendezvous::server::Behaviour::new(rendezvous::server::Config::default()),
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
keep_alive: keep_alive::Behaviour,
},
PeerId::from(key_pair.public()),
)
.idle_connection_timeout(Duration::from_secs(5))
.build();

let _ = swarm.listen_on("/ip4/0.0.0.0/tcp/62649".parse().unwrap());
Expand Down Expand Up @@ -97,5 +97,4 @@ struct MyBehaviour {
identify: identify::Behaviour,
rendezvous: rendezvous::server::Behaviour,
ping: ping::Behaviour,
keep_alive: keep_alive::Behaviour,
}
9 changes: 4 additions & 5 deletions interop-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::time::Duration;

use anyhow::{bail, Context, Result};
use futures::{FutureExt, StreamExt};
use libp2p::swarm::{keep_alive, NetworkBehaviour, SwarmEvent};
use libp2p::{identify, identity, ping, Multiaddr, PeerId};
use libp2p::swarm::SwarmEvent;
use libp2p::{identify, identity, ping, swarm::NetworkBehaviour, Multiaddr, PeerId};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;

Expand Down Expand Up @@ -33,8 +33,7 @@ pub async fn run_test(
let mut swarm = swarm_builder(
boxed_transport,
Behaviour {
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
keep_alive: keep_alive::Behaviour,
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(10))),
// Need to include identify until https://github.com/status-im/nim-libp2p/issues/924 is resolved.
identify: identify::Behaviour::new(identify::Config::new(
"/interop-tests".to_owned(),
Expand All @@ -43,6 +42,7 @@ pub async fn run_test(
},
local_peer_id,
)
.idle_connection_timeout(Duration::from_secs(5))
.build();

log::info!("Running ping test: {}", swarm.local_peer_id());
Expand Down Expand Up @@ -242,7 +242,6 @@ impl FromStr for SecProtocol {
#[derive(NetworkBehaviour)]
struct Behaviour {
ping: ping::Behaviour,
keep_alive: keep_alive::Behaviour,
identify: identify::Behaviour,
}

Expand Down
Loading

0 comments on commit 2de759c

Please sign in to comment.