Files
rust-libp2p/transports/tls/tests/smoke.rs
Sumit c52a2fc3af feat(swarm): allow configuration to idle connection timeout
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 https://github.com/libp2p/rust-libp2p/issues/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 #4121.

Pull-Request: #4161.
2023-09-19 22:32:29 +00:00

72 lines
2.4 KiB
Rust

use futures::{future, StreamExt};
use libp2p_core::multiaddr::Protocol;
use libp2p_core::transport::MemoryTransport;
use libp2p_core::upgrade::Version;
use libp2p_core::Transport;
use libp2p_swarm::{dummy, Swarm, SwarmBuilder, SwarmEvent};
use std::time::Duration;
#[tokio::test]
async fn can_establish_connection() {
let mut swarm1 = make_swarm();
let mut swarm2 = make_swarm();
let listen_address = {
let expected_listener_id = swarm1.listen_on(Protocol::Memory(0).into()).unwrap();
loop {
match swarm1.next().await.unwrap() {
SwarmEvent::NewListenAddr {
address,
listener_id,
} if listener_id == expected_listener_id => break address,
_ => continue,
};
}
};
swarm2.dial(listen_address).unwrap();
let await_inbound_connection = async {
loop {
match swarm1.next().await.unwrap() {
SwarmEvent::ConnectionEstablished { peer_id, .. } => break peer_id,
SwarmEvent::IncomingConnectionError { error, .. } => {
panic!("Incoming connection failed: {error}")
}
_ => continue,
};
}
};
let await_outbound_connection = async {
loop {
match swarm2.next().await.unwrap() {
SwarmEvent::ConnectionEstablished { peer_id, .. } => break peer_id,
SwarmEvent::OutgoingConnectionError { error, .. } => {
panic!("Failed to dial: {error}")
}
_ => continue,
};
}
};
let (inbound_peer_id, outbound_peer_id) =
future::join(await_inbound_connection, await_outbound_connection).await;
assert_eq!(&inbound_peer_id, swarm2.local_peer_id());
assert_eq!(&outbound_peer_id, swarm1.local_peer_id());
}
fn make_swarm() -> Swarm<dummy::Behaviour> {
let identity = libp2p_identity::Keypair::generate_ed25519();
let transport = MemoryTransport::default()
.upgrade(Version::V1)
.authenticate(libp2p_tls::Config::new(&identity).unwrap())
.multiplex(libp2p_yamux::Config::default())
.boxed();
SwarmBuilder::without_executor(transport, dummy::Behaviour, identity.public().to_peer_id())
.idle_connection_timeout(Duration::from_secs(5))
.build()
}