Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rendezous): refresh registration on change to external addresses #4629

Merged
merged 14 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ libp2p-plaintext = { version = "0.40.1", path = "transports/plaintext" }
libp2p-pnet = { version = "0.23.0", path = "transports/pnet" }
libp2p-quic = { version = "0.9.3", path = "transports/quic" }
libp2p-relay = { version = "0.16.1", path = "protocols/relay" }
libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" }
libp2p-rendezvous = { version = "0.13.1", path = "protocols/rendezvous" }
libp2p-upnp = { version = "0.1.1", path = "protocols/upnp" }
libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" }
libp2p-server = { version = "0.12.3", path = "misc/server" }
Expand Down
6 changes: 6 additions & 0 deletions protocols/rendezvous/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.13.1 - unreleased
- Refresh registration upon a change in external addresses.
See [PR 4629].

[PR 4629]: https://github.com/libp2p/rust-libp2p/pull/4629

## 0.13.0

- Changed the signature of the function `client::Behavior::register()`,
Expand Down
2 changes: 1 addition & 1 deletion protocols/rendezvous/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "libp2p-rendezvous"
edition = "2021"
rust-version = { workspace = true }
description = "Rendezvous protocol for libp2p"
version = "0.13.0"
version = "0.13.1"
authors = ["The COMIT guys <hello@comit.network>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down
20 changes: 19 additions & 1 deletion protocols/rendezvous/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub struct Behaviour {
/// Storing these internally allows us to assist the [`libp2p_swarm::Swarm`] in dialing by returning addresses from [`NetworkBehaviour::handle_pending_outbound_connection`].
discovered_peers: HashMap<(PeerId, Namespace), Vec<Multiaddr>>,

registered_namespaces: HashMap<(PeerId, Namespace), Ttl>,

/// Tracks the expiry of registrations that we have discovered and stored in `discovered_peers` otherwise we have a memory leak.
expiring_registrations: FuturesUnordered<BoxFuture<'static, (PeerId, Namespace)>>,

Expand All @@ -68,6 +70,7 @@ impl Behaviour {
waiting_for_register: Default::default(),
waiting_for_discovery: Default::default(),
discovered_peers: Default::default(),
registered_namespaces: Default::default(),
expiring_registrations: FuturesUnordered::from_iter(vec![
futures::future::pending().boxed()
]),
Expand Down Expand Up @@ -103,6 +106,9 @@ impl Behaviour {

/// Unregister ourselves from the given namespace with the given rendezvous peer.
pub fn unregister(&mut self, namespace: Namespace, rendezvous_node: PeerId) {
self.registered_namespaces
.retain(|(rz_node, ns), _| rz_node.ne(&rendezvous_node) && ns.ne(&namespace));

self.inner
.send_request(&rendezvous_node, Unregister(namespace));
}
Expand Down Expand Up @@ -218,9 +224,18 @@ impl NetworkBehaviour for Behaviour {
}

fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
self.external_addresses.on_swarm_event(&event);
let changed = self.external_addresses.on_swarm_event(&event);

self.inner.on_swarm_event(event);

if changed && self.external_addresses.iter().count() > 0 {
let registered = self.registered_namespaces.clone();
dariusc93 marked this conversation as resolved.
Show resolved Hide resolved
for ((rz_node, ns), ttl) in registered {
if let Err(e) = self.register(ns, rz_node, Some(ttl)) {
log::warn!("refreshing registration failed: {e}")
}
}
}
}

fn poll(
Expand Down Expand Up @@ -348,6 +363,9 @@ impl Behaviour {
if let Some((rendezvous_node, namespace)) =
self.waiting_for_register.remove(request_id)
{
self.registered_namespaces
.insert((rendezvous_node, namespace.clone()), ttl);

return Some(Event::Registered {
rendezvous_node,
ttl,
Expand Down
53 changes: 53 additions & 0 deletions protocols/rendezvous/tests/rendezvous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

use futures::stream::FuturesUnordered;
use futures::StreamExt;
use libp2p_core::multiaddr::Protocol;
use libp2p_core::Multiaddr;
use libp2p_identity as identity;
use libp2p_rendezvous as rendezvous;
use libp2p_rendezvous::client::RegisterError;
Expand Down Expand Up @@ -162,6 +164,57 @@ async fn given_successful_registration_then_refresh_ttl() {
}
}

#[tokio::test]
async fn given_successful_registration_then_refresh_external_addrs() {
let _ = env_logger::try_init();
let namespace = rendezvous::Namespace::from_static("some-namespace");
let ([mut alice], mut robert) =
new_server_with_connected_clients(rendezvous::server::Config::default()).await;

let roberts_peer_id = *robert.local_peer_id();

alice
.behaviour_mut()
.register(namespace.clone(), roberts_peer_id, None)
.unwrap();

match libp2p_swarm_test::drive(&mut alice, &mut robert).await {
(
[rendezvous::client::Event::Registered { .. }],
[rendezvous::server::Event::PeerRegistered { .. }],
) => {}
events => panic!("Unexpected events: {events:?}"),
}

let external_addr = Multiaddr::empty().with(Protocol::Memory(0));

alice.add_external_address(external_addr.clone());

match libp2p_swarm_test::drive(&mut alice, &mut robert).await {
(
[rendezvous::client::Event::Registered { .. }],
[rendezvous::server::Event::PeerRegistered { registration, .. }],
) => {
let record = registration.record;
assert!(record.addresses().contains(&external_addr));
}
events => panic!("Unexpected events: {events:?}"),
}

alice.remove_external_address(&external_addr);

match libp2p_swarm_test::drive(&mut alice, &mut robert).await {
(
[rendezvous::client::Event::Registered { .. }],
[rendezvous::server::Event::PeerRegistered { registration, .. }],
) => {
let record = registration.record;
assert!(!record.addresses().contains(&external_addr));
}
events => panic!("Unexpected events: {events:?}"),
}
}

#[tokio::test]
async fn given_invalid_ttl_then_unsuccessful_registration() {
let _ = env_logger::try_init();
Expand Down