mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-24 15:21:33 +00:00
fix(mdns): Don't expire mDNS nodes on connection close (#3367)
mDNS records should not be expiring when an unrelated connection timeout with said peer is reached. Fixes #3309.
This commit is contained in:
@ -6,7 +6,12 @@
|
|||||||
|
|
||||||
- Update to `libp2p-swarm` `v0.42.0`.
|
- Update to `libp2p-swarm` `v0.42.0`.
|
||||||
|
|
||||||
|
- Don't expire mDNS records when the last connection was closed.
|
||||||
|
mDNS records will only be expired when the TTL is reached and the DNS record is no longer valid.
|
||||||
|
See [PR 3367].
|
||||||
|
|
||||||
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
||||||
|
[PR 3367]: https://github.com/libp2p/rust-libp2p/pull/3367
|
||||||
|
|
||||||
# 0.42.0
|
# 0.42.0
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ use crate::Config;
|
|||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use if_watch::IfEvent;
|
use if_watch::IfEvent;
|
||||||
use libp2p_core::{Multiaddr, PeerId};
|
use libp2p_core::{Multiaddr, PeerId};
|
||||||
use libp2p_swarm::behaviour::{ConnectionClosed, FromSwarm};
|
use libp2p_swarm::behaviour::FromSwarm;
|
||||||
use libp2p_swarm::{
|
use libp2p_swarm::{
|
||||||
dummy, ListenAddresses, NetworkBehaviour, NetworkBehaviourAction, PollParameters,
|
dummy, ListenAddresses, NetworkBehaviour, NetworkBehaviourAction, PollParameters,
|
||||||
THandlerOutEvent,
|
THandlerOutEvent,
|
||||||
@ -199,22 +199,14 @@ where
|
|||||||
self.listen_addresses.on_swarm_event(&event);
|
self.listen_addresses.on_swarm_event(&event);
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
FromSwarm::ConnectionClosed(ConnectionClosed {
|
|
||||||
peer_id,
|
|
||||||
remaining_established,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if remaining_established == 0 {
|
|
||||||
self.expire_node(&peer_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FromSwarm::NewListener(_) => {
|
FromSwarm::NewListener(_) => {
|
||||||
log::trace!("waking interface state because listening address changed");
|
log::trace!("waking interface state because listening address changed");
|
||||||
for iface in self.iface_states.values_mut() {
|
for iface in self.iface_states.values_mut() {
|
||||||
iface.fire_timer();
|
iface.fire_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FromSwarm::ConnectionEstablished(_)
|
FromSwarm::ConnectionClosed(_)
|
||||||
|
| FromSwarm::ConnectionEstablished(_)
|
||||||
| FromSwarm::DialFailure(_)
|
| FromSwarm::DialFailure(_)
|
||||||
| FromSwarm::AddressChange(_)
|
| FromSwarm::AddressChange(_)
|
||||||
| FromSwarm::ListenFailure(_)
|
| FromSwarm::ListenFailure(_)
|
||||||
|
@ -55,6 +55,24 @@ async fn test_expired_async_std() -> Result<(), Box<dyn Error>> {
|
|||||||
.map_err(|e| Box::new(e) as Box<dyn Error>)
|
.map_err(|e| Box::new(e) as Box<dyn Error>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_no_expiration_on_close_async_std() -> Result<(), Box<dyn Error>> {
|
||||||
|
env_logger::try_init().ok();
|
||||||
|
let config = Config {
|
||||||
|
ttl: Duration::from_secs(120),
|
||||||
|
query_interval: Duration::from_secs(10),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
async_std::future::timeout(
|
||||||
|
Duration::from_secs(6),
|
||||||
|
run_no_expiration_on_close_test(config),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(|e| Box::new(e) as Box<dyn Error>)
|
||||||
|
}
|
||||||
|
|
||||||
async fn create_swarm(config: Config) -> Result<Swarm<Behaviour>, Box<dyn Error>> {
|
async fn create_swarm(config: Config) -> Result<Swarm<Behaviour>, Box<dyn Error>> {
|
||||||
let id_keys = identity::Keypair::generate_ed25519();
|
let id_keys = identity::Keypair::generate_ed25519();
|
||||||
let peer_id = PeerId::from(id_keys.public());
|
let peer_id = PeerId::from(id_keys.public());
|
||||||
@ -126,3 +144,66 @@ async fn run_peer_expiration_test(config: Config) -> Result<(), Box<dyn Error>>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn run_no_expiration_on_close_test(config: Config) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut a = create_swarm(config.clone()).await?;
|
||||||
|
let mut b = create_swarm(config).await?;
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum State {
|
||||||
|
Initial,
|
||||||
|
Dialed,
|
||||||
|
Closed,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut state = State::Initial;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
futures::select! {
|
||||||
|
ev = a.select_next_some() => match ev {
|
||||||
|
SwarmEvent::Behaviour(Event::Discovered(peers)) => {
|
||||||
|
if state == State::Initial {
|
||||||
|
for (peer, addr) in peers {
|
||||||
|
if peer == *b.local_peer_id() {
|
||||||
|
// Connect to all addresses of b to 'expire' all of them
|
||||||
|
a.dial(addr)?;
|
||||||
|
state = State::Dialed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SwarmEvent::ConnectionEstablished { peer_id, .. } => {
|
||||||
|
if peer_id == *b.local_peer_id() {
|
||||||
|
if state == State::Dialed {
|
||||||
|
// We disconnect the connection that was initiated
|
||||||
|
// in the discovered event
|
||||||
|
a.disconnect_peer_id(peer_id).unwrap();
|
||||||
|
} else if state == State::Closed {
|
||||||
|
// If the connection attempt after connection close
|
||||||
|
// succeeded the mDNS record wasn't expired by
|
||||||
|
// connection close
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SwarmEvent::ConnectionClosed { peer_id, num_established, .. } => {
|
||||||
|
if peer_id == *b.local_peer_id() && num_established == 0 {
|
||||||
|
// Dial a second time to make sure connection is still
|
||||||
|
// possible only via the peer id
|
||||||
|
state = State::Closed;
|
||||||
|
|
||||||
|
// Either wait for the expiration event to give mDNS enough time to expire
|
||||||
|
// or timeout after 1 second of not receiving the expiration event
|
||||||
|
let _ = async_std::future::timeout(Duration::from_secs(1), a.select_next_some()).await;
|
||||||
|
|
||||||
|
// If the record expired this will fail because the peer has no addresses
|
||||||
|
a.dial(peer_id).expect("Expected peer addresses to not expire after connection close");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ = b.select_next_some() => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user