From 4a9932a73bb45fb391292f2f31add9fdd3de4644 Mon Sep 17 00:00:00 2001 From: Darius Date: Thu, 2 Nov 2023 10:18:48 -0400 Subject: [PATCH 01/20] feat: Implement external address on successful reservation --- protocols/relay/src/priv_client.rs | 31 ++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index ae2ceb2e97d..996e14bcf21 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -33,6 +33,7 @@ use futures::future::{BoxFuture, FutureExt}; use futures::io::{AsyncRead, AsyncWrite}; use futures::ready; use futures::stream::StreamExt; +use libp2p_core::multiaddr::Protocol; use libp2p_core::{Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm}; @@ -79,6 +80,9 @@ pub struct Behaviour { /// connection. directly_connected_peers: HashMap>, + /// Direct connection address + direct_connection_addrs: HashMap, + /// Queue of actions to return when polled. queued_actions: VecDeque>>, @@ -92,6 +96,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) { local_peer_id, from_transport, directly_connected_peers: Default::default(), + direct_connection_addrs: Default::default(), queued_actions: Default::default(), pending_handler_commands: Default::default(), }; @@ -126,6 +131,7 @@ impl Behaviour { unreachable!("`on_connection_closed` for unconnected peer.") } }; + self.direct_connection_addrs.remove(&connection_id); } } } @@ -186,6 +192,10 @@ impl NetworkBehaviour for Behaviour { .entry(peer_id) .or_default() .push(connection_id); + + let addr = endpoint.get_remote_address().clone(); + + self.direct_connection_addrs.insert(connection_id, addr); } if let Some(event) = self.pending_handler_commands.remove(&connection_id) { @@ -218,7 +228,7 @@ impl NetworkBehaviour for Behaviour { fn on_connection_handler_event( &mut self, event_source: PeerId, - _connection: ConnectionId, + connection: ConnectionId, handler_event: THandlerOutEvent, ) { let handler_event = match handler_event { @@ -226,8 +236,21 @@ impl NetworkBehaviour for Behaviour { Either::Right(v) => void::unreachable(v), }; + let mut external_event = None; + let event = match handler_event { handler::Event::ReservationReqAccepted { renewal, limit } => { + let addr = self + .direct_connection_addrs + .get(&connection) + .cloned() + .expect("Connection to be direct") + .with(Protocol::P2p(event_source)) + .with(Protocol::P2pCircuit) + .with(Protocol::P2p(self.local_peer_id)); + + external_event = Some(ToSwarm::ExternalAddrConfirmed(addr)); + Event::ReservationReqAccepted { relay_peer_id: event_source, renewal, @@ -245,7 +268,11 @@ impl NetworkBehaviour for Behaviour { } }; - self.queued_actions.push_back(ToSwarm::GenerateEvent(event)) + self.queued_actions.push_back(ToSwarm::GenerateEvent(event)); + + if let Some(event) = external_event.take() { + self.queued_actions.push_back(event); + } } fn poll( From b8aa098f464a3b6b72a65ed48d7936a828ecc694 Mon Sep 17 00:00:00 2001 From: Darius Date: Thu, 2 Nov 2023 10:41:14 -0400 Subject: [PATCH 02/20] chore: Emit event before reservation accepted event --- protocols/relay/src/priv_client.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index 996e14bcf21..07b9e08d506 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -236,8 +236,6 @@ impl NetworkBehaviour for Behaviour { Either::Right(v) => void::unreachable(v), }; - let mut external_event = None; - let event = match handler_event { handler::Event::ReservationReqAccepted { renewal, limit } => { let addr = self @@ -249,7 +247,8 @@ impl NetworkBehaviour for Behaviour { .with(Protocol::P2pCircuit) .with(Protocol::P2p(self.local_peer_id)); - external_event = Some(ToSwarm::ExternalAddrConfirmed(addr)); + self.queued_actions + .push_back(ToSwarm::ExternalAddrConfirmed(addr)); Event::ReservationReqAccepted { relay_peer_id: event_source, @@ -269,10 +268,6 @@ impl NetworkBehaviour for Behaviour { }; self.queued_actions.push_back(ToSwarm::GenerateEvent(event)); - - if let Some(event) = external_event.take() { - self.queued_actions.push_back(event); - } } fn poll( From 02aff8692211817a206a8762a3cd10e62013a89f Mon Sep 17 00:00:00 2001 From: Darius Date: Thu, 2 Nov 2023 10:56:06 -0400 Subject: [PATCH 03/20] fix: remove extra protocol --- protocols/relay/src/priv_client.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index 07b9e08d506..2485792a326 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -243,7 +243,6 @@ impl NetworkBehaviour for Behaviour { .get(&connection) .cloned() .expect("Connection to be direct") - .with(Protocol::P2p(event_source)) .with(Protocol::P2pCircuit) .with(Protocol::P2p(self.local_peer_id)); From 441fccfb8b8c2343ec4d2da2c15da0ec4db7e8ea Mon Sep 17 00:00:00 2001 From: Darius Date: Thu, 2 Nov 2023 11:00:54 -0400 Subject: [PATCH 04/20] chore: Update CHANGELOG.md --- protocols/relay/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/relay/CHANGELOG.md b/protocols/relay/CHANGELOG.md index 200cc4bc18d..9d0b38e8c73 100644 --- a/protocols/relay/CHANGELOG.md +++ b/protocols/relay/CHANGELOG.md @@ -1,4 +1,6 @@ ## 0.17.0 - unreleased +- Emit an external address on making reservation. + See [PR XXXX](https://github.com/libp2p/rust-lib2pp/pulls/). - Don't close connections on protocol failures within the relay-server. To achieve this, error handling was restructured: From cbecab9180104eba286a57f37c349e0905d28be6 Mon Sep 17 00:00:00 2001 From: Darius Date: Mon, 6 Nov 2023 11:16:51 -0500 Subject: [PATCH 05/20] chore: Update test --- protocols/relay/tests/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/relay/tests/lib.rs b/protocols/relay/tests/lib.rs index d57ab144e9f..2cdc514610d 100644 --- a/protocols/relay/tests/lib.rs +++ b/protocols/relay/tests/lib.rs @@ -169,6 +169,7 @@ fn new_reservation_to_same_relay_replaces_old() { break; } } + SwarmEvent::ExternalAddrConfirmed { .. } => {} SwarmEvent::Behaviour(ClientEvent::Ping(_)) => {} e => panic!("{e:?}"), } @@ -521,6 +522,7 @@ async fn wait_for_reservation( loop { match client.select_next_some().await { + SwarmEvent::ExternalAddrConfirmed { .. } => {} SwarmEvent::Behaviour(ClientEvent::Relay( relay::client::Event::ReservationReqAccepted { relay_peer_id: peer_id, From 66c4fe73ec05cd4c48e8798b2d8f067063d628ad Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:04:19 -0500 Subject: [PATCH 06/20] chore: Check external addr --- protocols/relay/tests/lib.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/protocols/relay/tests/lib.rs b/protocols/relay/tests/lib.rs index 2cdc514610d..0b4b82762e7 100644 --- a/protocols/relay/tests/lib.rs +++ b/protocols/relay/tests/lib.rs @@ -119,7 +119,7 @@ fn new_reservation_to_same_relay_replaces_old() { )); // Trigger new reservation. - let new_listener = client.listen_on(client_addr).unwrap(); + let new_listener = client.listen_on(client_addr.clone()).unwrap(); // Wait for // - listener of old reservation to close @@ -169,7 +169,12 @@ fn new_reservation_to_same_relay_replaces_old() { break; } } - SwarmEvent::ExternalAddrConfirmed { .. } => {} + SwarmEvent::ExternalAddrConfirmed { address } => { + assert_eq!( + address, + client_addr.clone().with(Protocol::P2p(client_peer_id)) + ); + } SwarmEvent::Behaviour(ClientEvent::Ping(_)) => {} e => panic!("{e:?}"), } @@ -522,7 +527,9 @@ async fn wait_for_reservation( loop { match client.select_next_some().await { - SwarmEvent::ExternalAddrConfirmed { .. } => {} + SwarmEvent::ExternalAddrConfirmed { address } => { + assert!(address.iter().any(|p| matches!(p, Protocol::P2pCircuit))) + } SwarmEvent::Behaviour(ClientEvent::Relay( relay::client::Event::ReservationReqAccepted { relay_peer_id: peer_id, From b6c73471be6ee6da7e0e70f670950399aff54920 Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:07:21 -0500 Subject: [PATCH 07/20] chore: Use event to get relay address provided --- protocols/relay/src/priv_client.rs | 47 ++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index b107c4788fd..fa2fdd63562 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -80,8 +80,7 @@ pub struct Behaviour { /// connection. directly_connected_peers: HashMap>, - /// Direct connection address - direct_connection_addrs: HashMap, + relay_connection_addr: HashMap, /// Queue of actions to return when polled. queued_actions: VecDeque>>, @@ -96,7 +95,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) { local_peer_id, from_transport, directly_connected_peers: Default::default(), - direct_connection_addrs: Default::default(), + relay_connection_addr: Default::default(), queued_actions: Default::default(), pending_handler_commands: Default::default(), }; @@ -131,7 +130,14 @@ impl Behaviour { unreachable!("`on_connection_closed` for unconnected peer.") } }; - self.direct_connection_addrs.remove(&connection_id); + if let Some(addr) = self.relay_connection_addr.remove(&connection_id) { + let addr = addr + .with(Protocol::P2pCircuit) + .with(Protocol::P2p(self.local_peer_id)); + + self.queued_actions + .push_back(ToSwarm::ExternalAddrExpired(addr)); + } } } } @@ -192,10 +198,6 @@ impl NetworkBehaviour for Behaviour { .entry(peer_id) .or_default() .push(connection_id); - - let addr = endpoint.get_remote_address().clone(); - - self.direct_connection_addrs.insert(connection_id, addr); } if let Some(event) = self.pending_handler_commands.remove(&connection_id) { @@ -210,6 +212,7 @@ impl NetworkBehaviour for Behaviour { self.on_connection_closed(connection_closed) } FromSwarm::DialFailure(DialFailure { connection_id, .. }) => { + self.relay_connection_addr.remove(&connection_id); self.pending_handler_commands.remove(&connection_id); } _ => {} @@ -230,10 +233,10 @@ impl NetworkBehaviour for Behaviour { let event = match handler_event { handler::Event::ReservationReqAccepted { renewal, limit } => { let addr = self - .direct_connection_addrs + .relay_connection_addr .get(&connection) .cloned() - .expect("Connection to be direct") + .expect("Relay connection exist") .with(Protocol::P2pCircuit) .with(Protocol::P2p(self.local_peer_id)); @@ -279,18 +282,30 @@ impl NetworkBehaviour for Behaviour { .get(&relay_peer_id) .and_then(|cs| cs.first()) { - Some(connection_id) => ToSwarm::NotifyHandler { - peer_id: relay_peer_id, - handler: NotifyHandler::One(*connection_id), - event: Either::Left(handler::In::Reserve { to_listener }), - }, + Some(connection_id) => { + self.relay_connection_addr.insert( + *connection_id, + relay_addr.with(Protocol::P2p(relay_peer_id)), + ); + + ToSwarm::NotifyHandler { + peer_id: relay_peer_id, + handler: NotifyHandler::One(*connection_id), + event: Either::Left(handler::In::Reserve { to_listener }), + } + } None => { let opts = DialOpts::peer_id(relay_peer_id) - .addresses(vec![relay_addr]) + .addresses(vec![relay_addr.clone()]) .extend_addresses_through_behaviour() .build(); let relayed_connection_id = opts.connection_id(); + self.relay_connection_addr.insert( + relayed_connection_id, + relay_addr.with(Protocol::P2p(relay_peer_id)), + ); + self.pending_handler_commands .insert(relayed_connection_id, handler::In::Reserve { to_listener }); ToSwarm::Dial { opts } From 5f9104305d062a360012b25e4c516a3ea049bafb Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:25:54 -0500 Subject: [PATCH 08/20] chore: Update dcutr test --- protocols/dcutr/tests/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/protocols/dcutr/tests/lib.rs b/protocols/dcutr/tests/lib.rs index a939fbccd11..d55a8b1d3f3 100644 --- a/protocols/dcutr/tests/lib.rs +++ b/protocols/dcutr/tests/lib.rs @@ -199,7 +199,10 @@ async fn wait_for_reservation( addr_observed = true; } SwarmEvent::Behaviour(ClientEvent::Identify(_)) => {} - SwarmEvent::NewExternalAddrCandidate { .. } => {} + SwarmEvent::NewExternalAddrCandidate { .. } => {}, + SwarmEvent::ExternalAddrConfirmed { address } => { + assert_eq!(address, client_addr); + } e => panic!("{e:?}"), } } From b775b9c8fc3df11dbb6e0296fda1c4d354d01124 Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:32:32 -0500 Subject: [PATCH 09/20] chore: Format code --- protocols/dcutr/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/dcutr/tests/lib.rs b/protocols/dcutr/tests/lib.rs index d55a8b1d3f3..0e462aa4057 100644 --- a/protocols/dcutr/tests/lib.rs +++ b/protocols/dcutr/tests/lib.rs @@ -199,7 +199,7 @@ async fn wait_for_reservation( addr_observed = true; } SwarmEvent::Behaviour(ClientEvent::Identify(_)) => {} - SwarmEvent::NewExternalAddrCandidate { .. } => {}, + SwarmEvent::NewExternalAddrCandidate { .. } => {} SwarmEvent::ExternalAddrConfirmed { address } => { assert_eq!(address, client_addr); } From 7b1511080b6c0aa83b3c4a352efcea991e28e267 Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:33:56 -0500 Subject: [PATCH 10/20] chore: Update Cargo.toml --- Cargo.lock | 2 +- Cargo.toml | 2 +- protocols/relay/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1e0c52e6e1..08df35c0ff4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3000,7 +3000,7 @@ dependencies = [ [[package]] name = "libp2p-relay" -version = "0.17.0" +version = "0.17.1" dependencies = [ "asynchronous-codec 0.6.2", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 89790baf82e..7895bdc6e49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,7 @@ libp2p-ping = { version = "0.44.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.41.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.24.0", path = "transports/pnet" } libp2p-quic = { version = "0.10.0", path = "transports/quic" } -libp2p-relay = { version = "0.17.0", path = "protocols/relay" } +libp2p-relay = { version = "0.17.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.26.0", path = "protocols/request-response" } libp2p-server = { version = "0.12.3", path = "misc/server" } diff --git a/protocols/relay/Cargo.toml b/protocols/relay/Cargo.toml index 7ad23af9b0a..54336549c35 100644 --- a/protocols/relay/Cargo.toml +++ b/protocols/relay/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-relay" edition = "2021" rust-version = { workspace = true } description = "Communications relaying for libp2p" -version = "0.17.0" +version = "0.17.1" authors = ["Parity Technologies ", "Max Inden "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" From 84f59c925258cad1f39e2f474503658d6bfcbd05 Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:55:45 -0500 Subject: [PATCH 11/20] chore: Check client address --- protocols/relay/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/relay/tests/lib.rs b/protocols/relay/tests/lib.rs index 0b4b82762e7..cdca104e822 100644 --- a/protocols/relay/tests/lib.rs +++ b/protocols/relay/tests/lib.rs @@ -528,7 +528,7 @@ async fn wait_for_reservation( loop { match client.select_next_some().await { SwarmEvent::ExternalAddrConfirmed { address } => { - assert!(address.iter().any(|p| matches!(p, Protocol::P2pCircuit))) + assert_eq!(address, client_addr); } SwarmEvent::Behaviour(ClientEvent::Relay( relay::client::Event::ReservationReqAccepted { From 604bba71e40a19deeb32cb18e21f0997104de94a Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:56:20 -0500 Subject: [PATCH 12/20] chore: Emit event is reservation isnt renewed --- protocols/relay/src/priv_client.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index fa2fdd63562..c8a556423e8 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -232,16 +232,18 @@ impl NetworkBehaviour for Behaviour { let event = match handler_event { handler::Event::ReservationReqAccepted { renewal, limit } => { - let addr = self - .relay_connection_addr - .get(&connection) - .cloned() - .expect("Relay connection exist") - .with(Protocol::P2pCircuit) - .with(Protocol::P2p(self.local_peer_id)); - - self.queued_actions - .push_back(ToSwarm::ExternalAddrConfirmed(addr)); + if !renewal { + let addr = self + .relay_connection_addr + .get(&connection) + .cloned() + .expect("Relay connection exist") + .with(Protocol::P2pCircuit) + .with(Protocol::P2p(self.local_peer_id)); + + self.queued_actions + .push_back(ToSwarm::ExternalAddrConfirmed(addr)); + } Event::ReservationReqAccepted { relay_peer_id: event_source, From deb3182f711ecfaffeec5d187e10f8f1e4d259e5 Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 22:59:20 -0500 Subject: [PATCH 13/20] chore: Check renewal in test --- protocols/relay/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/relay/tests/lib.rs b/protocols/relay/tests/lib.rs index cdca104e822..2b28d5a50cd 100644 --- a/protocols/relay/tests/lib.rs +++ b/protocols/relay/tests/lib.rs @@ -527,7 +527,7 @@ async fn wait_for_reservation( loop { match client.select_next_some().await { - SwarmEvent::ExternalAddrConfirmed { address } => { + SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => { assert_eq!(address, client_addr); } SwarmEvent::Behaviour(ClientEvent::Relay( From 898246581268cae0afa92d002607d3e8ca35015e Mon Sep 17 00:00:00 2001 From: Darius Date: Wed, 8 Nov 2023 23:01:05 -0500 Subject: [PATCH 14/20] chore: Check renewal --- protocols/dcutr/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/dcutr/tests/lib.rs b/protocols/dcutr/tests/lib.rs index 0e462aa4057..9e1f0591e6d 100644 --- a/protocols/dcutr/tests/lib.rs +++ b/protocols/dcutr/tests/lib.rs @@ -200,7 +200,7 @@ async fn wait_for_reservation( } SwarmEvent::Behaviour(ClientEvent::Identify(_)) => {} SwarmEvent::NewExternalAddrCandidate { .. } => {} - SwarmEvent::ExternalAddrConfirmed { address } => { + SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => { assert_eq!(address, client_addr); } e => panic!("{e:?}"), From e9372d85064d4080b42e5845b2f002de7d090966 Mon Sep 17 00:00:00 2001 From: Darius Clark Date: Wed, 8 Nov 2023 23:01:57 -0500 Subject: [PATCH 15/20] Update protocols/relay/CHANGELOG.md Co-authored-by: Thomas Eizinger --- protocols/relay/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/relay/CHANGELOG.md b/protocols/relay/CHANGELOG.md index ccabf93089e..33270787bff 100644 --- a/protocols/relay/CHANGELOG.md +++ b/protocols/relay/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.17.1 - unreleased -- Emit an external address on making reservation. +- Automatically register relayed addresses as external addresses. See [PR 4809](https://github.com/libp2p/rust-lib2pp/pulls/4809). ## 0.17.0 From 17e7a8ea8093be64f904759c6a85c081a44e640e Mon Sep 17 00:00:00 2001 From: Darius Date: Mon, 13 Nov 2023 18:10:29 -0500 Subject: [PATCH 16/20] chore: check if reservation exist prior to emitting event --- protocols/relay/src/priv_client.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index c8a556423e8..3dec3f4c518 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -42,7 +42,7 @@ use libp2p_swarm::{ dummy, ConnectionDenied, ConnectionHandler, ConnectionId, DialFailure, NetworkBehaviour, NotifyHandler, Stream, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }; -use std::collections::{hash_map, HashMap, VecDeque}; +use std::collections::{hash_map, HashMap, HashSet, VecDeque}; use std::io::{Error, ErrorKind, IoSlice}; use std::pin::Pin; use std::task::{Context, Poll}; @@ -82,6 +82,8 @@ pub struct Behaviour { relay_connection_addr: HashMap, + reservation: HashSet, + /// Queue of actions to return when polled. queued_actions: VecDeque>>, @@ -96,6 +98,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) { from_transport, directly_connected_peers: Default::default(), relay_connection_addr: Default::default(), + reservation: Default::default(), queued_actions: Default::default(), pending_handler_commands: Default::default(), }; @@ -135,8 +138,10 @@ impl Behaviour { .with(Protocol::P2pCircuit) .with(Protocol::P2p(self.local_peer_id)); - self.queued_actions - .push_back(ToSwarm::ExternalAddrExpired(addr)); + if self.reservation.remove(&addr) { + self.queued_actions + .push_back(ToSwarm::ExternalAddrExpired(addr)); + } } } } @@ -232,15 +237,15 @@ impl NetworkBehaviour for Behaviour { let event = match handler_event { handler::Event::ReservationReqAccepted { renewal, limit } => { - if !renewal { - let addr = self - .relay_connection_addr - .get(&connection) - .cloned() - .expect("Relay connection exist") - .with(Protocol::P2pCircuit) - .with(Protocol::P2p(self.local_peer_id)); + let addr = self + .relay_connection_addr + .get(&connection) + .cloned() + .expect("Relay connection exist") + .with(Protocol::P2pCircuit) + .with(Protocol::P2p(self.local_peer_id)); + if !renewal && self.reservation.insert(addr.clone()) { self.queued_actions .push_back(ToSwarm::ExternalAddrConfirmed(addr)); } From b7816787a4ea7c43dae4caf3f2f414d7ce6ea241 Mon Sep 17 00:00:00 2001 From: Darius Date: Mon, 13 Nov 2023 18:23:35 -0500 Subject: [PATCH 17/20] fix: Correct package version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c09be06f39f..33a57077281 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,7 +93,7 @@ libp2p-perf = { version = "0.3.0", path = "protocols/perf" } libp2p-ping = { version = "0.44.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.41.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.24.0", path = "transports/pnet" } -libp2p-quic = { version = "0.10.0", path = "transports/quic" } +libp2p-quic = { version = "0.10.1", path = "transports/quic" } libp2p-relay = { version = "0.17.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.26.0", path = "protocols/request-response" } From 9e18f6baa1e166b78c17da62cf299829bd1fbb6c Mon Sep 17 00:00:00 2001 From: Darius Date: Mon, 13 Nov 2023 19:22:45 -0500 Subject: [PATCH 18/20] chore: use a single map to track reservation --- protocols/relay/src/priv_client.rs | 66 ++++++++++++++++++------------ 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index 3dec3f4c518..e93e5939334 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -42,7 +42,7 @@ use libp2p_swarm::{ dummy, ConnectionDenied, ConnectionHandler, ConnectionId, DialFailure, NetworkBehaviour, NotifyHandler, Stream, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }; -use std::collections::{hash_map, HashMap, HashSet, VecDeque}; +use std::collections::{hash_map, HashMap, VecDeque}; use std::io::{Error, ErrorKind, IoSlice}; use std::pin::Pin; use std::task::{Context, Poll}; @@ -70,6 +70,12 @@ pub enum Event { }, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum ReservationStatus { + Pending, + Confirm, +} + /// [`NetworkBehaviour`] implementation of the relay client /// functionality of the circuit relay v2 protocol. pub struct Behaviour { @@ -80,9 +86,10 @@ pub struct Behaviour { /// connection. directly_connected_peers: HashMap>, - relay_connection_addr: HashMap, - - reservation: HashSet, + /// Stores the address of a pending or confirmed reservation. + /// + /// This is indexed by the [`ConnectionId`] to a relay server and the address is the `/p2p-circuit` address we reserved on it. + reservation_addresses: HashMap, /// Queue of actions to return when polled. queued_actions: VecDeque>>, @@ -97,8 +104,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) { local_peer_id, from_transport, directly_connected_peers: Default::default(), - relay_connection_addr: Default::default(), - reservation: Default::default(), + reservation_addresses: Default::default(), queued_actions: Default::default(), pending_handler_commands: Default::default(), }; @@ -133,12 +139,8 @@ impl Behaviour { unreachable!("`on_connection_closed` for unconnected peer.") } }; - if let Some(addr) = self.relay_connection_addr.remove(&connection_id) { - let addr = addr - .with(Protocol::P2pCircuit) - .with(Protocol::P2p(self.local_peer_id)); - - if self.reservation.remove(&addr) { + if let Some((addr, status)) = self.reservation_addresses.remove(&connection_id) { + if matches!(status, ReservationStatus::Confirm) { self.queued_actions .push_back(ToSwarm::ExternalAddrExpired(addr)); } @@ -217,7 +219,7 @@ impl NetworkBehaviour for Behaviour { self.on_connection_closed(connection_closed) } FromSwarm::DialFailure(DialFailure { connection_id, .. }) => { - self.relay_connection_addr.remove(&connection_id); + self.reservation_addresses.remove(&connection_id); self.pending_handler_commands.remove(&connection_id); } _ => {} @@ -237,17 +239,15 @@ impl NetworkBehaviour for Behaviour { let event = match handler_event { handler::Event::ReservationReqAccepted { renewal, limit } => { - let addr = self - .relay_connection_addr - .get(&connection) - .cloned() - .expect("Relay connection exist") - .with(Protocol::P2pCircuit) - .with(Protocol::P2p(self.local_peer_id)); - - if !renewal && self.reservation.insert(addr.clone()) { + let (addr, status) = self + .reservation_addresses + .get_mut(&connection) + .expect("Relay connection exist"); + + if !renewal && matches!(status, ReservationStatus::Pending) { + *status = ReservationStatus::Confirm; self.queued_actions - .push_back(ToSwarm::ExternalAddrConfirmed(addr)); + .push_back(ToSwarm::ExternalAddrConfirmed(addr.clone())); } Event::ReservationReqAccepted { @@ -290,9 +290,15 @@ impl NetworkBehaviour for Behaviour { .and_then(|cs| cs.first()) { Some(connection_id) => { - self.relay_connection_addr.insert( + self.reservation_addresses.insert( *connection_id, - relay_addr.with(Protocol::P2p(relay_peer_id)), + ( + relay_addr + .with(Protocol::P2p(relay_peer_id)) + .with(Protocol::P2pCircuit) + .with(Protocol::P2p(self.local_peer_id)), + ReservationStatus::Pending, + ), ); ToSwarm::NotifyHandler { @@ -308,9 +314,15 @@ impl NetworkBehaviour for Behaviour { .build(); let relayed_connection_id = opts.connection_id(); - self.relay_connection_addr.insert( + self.reservation_addresses.insert( relayed_connection_id, - relay_addr.with(Protocol::P2p(relay_peer_id)), + ( + relay_addr + .with(Protocol::P2p(relay_peer_id)) + .with(Protocol::P2pCircuit) + .with(Protocol::P2p(self.local_peer_id)), + ReservationStatus::Pending, + ), ); self.pending_handler_commands From cc0c26b5180a1705a4ef0bca5a07709c9172a337 Mon Sep 17 00:00:00 2001 From: Darius Date: Mon, 13 Nov 2023 19:25:46 -0500 Subject: [PATCH 19/20] chore: Correct naming --- protocols/relay/src/priv_client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index e93e5939334..a1dfcbd3650 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -73,7 +73,7 @@ pub enum Event { #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum ReservationStatus { Pending, - Confirm, + Confirmed, } /// [`NetworkBehaviour`] implementation of the relay client @@ -140,7 +140,7 @@ impl Behaviour { } }; if let Some((addr, status)) = self.reservation_addresses.remove(&connection_id) { - if matches!(status, ReservationStatus::Confirm) { + if matches!(status, ReservationStatus::Confirmed) { self.queued_actions .push_back(ToSwarm::ExternalAddrExpired(addr)); } @@ -245,7 +245,7 @@ impl NetworkBehaviour for Behaviour { .expect("Relay connection exist"); if !renewal && matches!(status, ReservationStatus::Pending) { - *status = ReservationStatus::Confirm; + *status = ReservationStatus::Confirmed; self.queued_actions .push_back(ToSwarm::ExternalAddrConfirmed(addr.clone())); } From f9f2ee66ad764255bd2373745800ee3a61149fb0 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 14 Nov 2023 11:54:59 +1100 Subject: [PATCH 20/20] Don't use `matches!` if not necessary --- protocols/relay/src/priv_client.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/protocols/relay/src/priv_client.rs b/protocols/relay/src/priv_client.rs index a1dfcbd3650..b4f518418d4 100644 --- a/protocols/relay/src/priv_client.rs +++ b/protocols/relay/src/priv_client.rs @@ -139,11 +139,11 @@ impl Behaviour { unreachable!("`on_connection_closed` for unconnected peer.") } }; - if let Some((addr, status)) = self.reservation_addresses.remove(&connection_id) { - if matches!(status, ReservationStatus::Confirmed) { - self.queued_actions - .push_back(ToSwarm::ExternalAddrExpired(addr)); - } + if let Some((addr, ReservationStatus::Confirmed)) = + self.reservation_addresses.remove(&connection_id) + { + self.queued_actions + .push_back(ToSwarm::ExternalAddrExpired(addr)); } } } @@ -244,7 +244,7 @@ impl NetworkBehaviour for Behaviour { .get_mut(&connection) .expect("Relay connection exist"); - if !renewal && matches!(status, ReservationStatus::Pending) { + if !renewal && *status == ReservationStatus::Pending { *status = ReservationStatus::Confirmed; self.queued_actions .push_back(ToSwarm::ExternalAddrConfirmed(addr.clone()));