Skip to content

Commit cf8a24d

Browse files
authored
feat(relay): emit external address on reservation
Resolves #4618. Pull-Request: #4809.
1 parent e57cd88 commit cf8a24d

File tree

7 files changed

+84
-13
lines changed

7 files changed

+84
-13
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ libp2p-ping = { version = "0.44.0", path = "protocols/ping" }
9494
libp2p-plaintext = { version = "0.41.0", path = "transports/plaintext" }
9595
libp2p-pnet = { version = "0.24.0", path = "transports/pnet" }
9696
libp2p-quic = { version = "0.10.1", path = "transports/quic" }
97-
libp2p-relay = { version = "0.17.0", path = "protocols/relay" }
97+
libp2p-relay = { version = "0.17.1", path = "protocols/relay" }
9898
libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" }
9999
libp2p-request-response = { version = "0.26.0", path = "protocols/request-response" }
100100
libp2p-server = { version = "0.12.4", path = "misc/server" }

protocols/dcutr/tests/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ async fn wait_for_reservation(
200200
}
201201
SwarmEvent::Behaviour(ClientEvent::Identify(_)) => {}
202202
SwarmEvent::NewExternalAddrCandidate { .. } => {}
203+
SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => {
204+
assert_eq!(address, client_addr);
205+
}
203206
e => panic!("{e:?}"),
204207
}
205208
}

protocols/relay/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
## 0.17.0
21

2+
## 0.17.1 - unreleased
3+
- Automatically register relayed addresses as external addresses.
4+
See [PR 4809](https://github.com/libp2p/rust-lib2pp/pulls/4809).
5+
6+
## 0.17.0
37
- Don't close connections on protocol failures within the relay-server.
48
To achieve this, error handling was restructured:
59
- `libp2p::relay::outbound::stop::FatalUpgradeError` has been removed.

protocols/relay/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "libp2p-relay"
33
edition = "2021"
44
rust-version = { workspace = true }
55
description = "Communications relaying for libp2p"
6-
version = "0.17.0"
6+
version = "0.17.1"
77
authors = ["Parity Technologies <[email protected]>", "Max Inden <[email protected]>"]
88
license = "MIT"
99
repository = "https://github.com/libp2p/rust-libp2p"

protocols/relay/src/priv_client.rs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use futures::future::{BoxFuture, FutureExt};
3333
use futures::io::{AsyncRead, AsyncWrite};
3434
use futures::ready;
3535
use futures::stream::StreamExt;
36+
use libp2p_core::multiaddr::Protocol;
3637
use libp2p_core::{Endpoint, Multiaddr};
3738
use libp2p_identity::PeerId;
3839
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, FromSwarm};
@@ -69,6 +70,12 @@ pub enum Event {
6970
},
7071
}
7172

73+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
74+
enum ReservationStatus {
75+
Pending,
76+
Confirmed,
77+
}
78+
7279
/// [`NetworkBehaviour`] implementation of the relay client
7380
/// functionality of the circuit relay v2 protocol.
7481
pub struct Behaviour {
@@ -79,6 +86,11 @@ pub struct Behaviour {
7986
/// connection.
8087
directly_connected_peers: HashMap<PeerId, Vec<ConnectionId>>,
8188

89+
/// Stores the address of a pending or confirmed reservation.
90+
///
91+
/// This is indexed by the [`ConnectionId`] to a relay server and the address is the `/p2p-circuit` address we reserved on it.
92+
reservation_addresses: HashMap<ConnectionId, (Multiaddr, ReservationStatus)>,
93+
8294
/// Queue of actions to return when polled.
8395
queued_actions: VecDeque<ToSwarm<Event, Either<handler::In, Void>>>,
8496

@@ -92,6 +104,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) {
92104
local_peer_id,
93105
from_transport,
94106
directly_connected_peers: Default::default(),
107+
reservation_addresses: Default::default(),
95108
queued_actions: Default::default(),
96109
pending_handler_commands: Default::default(),
97110
};
@@ -126,6 +139,12 @@ impl Behaviour {
126139
unreachable!("`on_connection_closed` for unconnected peer.")
127140
}
128141
};
142+
if let Some((addr, ReservationStatus::Confirmed)) =
143+
self.reservation_addresses.remove(&connection_id)
144+
{
145+
self.queued_actions
146+
.push_back(ToSwarm::ExternalAddrExpired(addr));
147+
}
129148
}
130149
}
131150
}
@@ -200,6 +219,7 @@ impl NetworkBehaviour for Behaviour {
200219
self.on_connection_closed(connection_closed)
201220
}
202221
FromSwarm::DialFailure(DialFailure { connection_id, .. }) => {
222+
self.reservation_addresses.remove(&connection_id);
203223
self.pending_handler_commands.remove(&connection_id);
204224
}
205225
_ => {}
@@ -209,7 +229,7 @@ impl NetworkBehaviour for Behaviour {
209229
fn on_connection_handler_event(
210230
&mut self,
211231
event_source: PeerId,
212-
_connection: ConnectionId,
232+
connection: ConnectionId,
213233
handler_event: THandlerOutEvent<Self>,
214234
) {
215235
let handler_event = match handler_event {
@@ -219,6 +239,17 @@ impl NetworkBehaviour for Behaviour {
219239

220240
let event = match handler_event {
221241
handler::Event::ReservationReqAccepted { renewal, limit } => {
242+
let (addr, status) = self
243+
.reservation_addresses
244+
.get_mut(&connection)
245+
.expect("Relay connection exist");
246+
247+
if !renewal && *status == ReservationStatus::Pending {
248+
*status = ReservationStatus::Confirmed;
249+
self.queued_actions
250+
.push_back(ToSwarm::ExternalAddrConfirmed(addr.clone()));
251+
}
252+
222253
Event::ReservationReqAccepted {
223254
relay_peer_id: event_source,
224255
renewal,
@@ -236,7 +267,7 @@ impl NetworkBehaviour for Behaviour {
236267
}
237268
};
238269

239-
self.queued_actions.push_back(ToSwarm::GenerateEvent(event))
270+
self.queued_actions.push_back(ToSwarm::GenerateEvent(event));
240271
}
241272

242273
#[tracing::instrument(level = "trace", name = "NetworkBehaviour::poll", skip(self, cx))]
@@ -259,18 +290,42 @@ impl NetworkBehaviour for Behaviour {
259290
.get(&relay_peer_id)
260291
.and_then(|cs| cs.first())
261292
{
262-
Some(connection_id) => ToSwarm::NotifyHandler {
263-
peer_id: relay_peer_id,
264-
handler: NotifyHandler::One(*connection_id),
265-
event: Either::Left(handler::In::Reserve { to_listener }),
266-
},
293+
Some(connection_id) => {
294+
self.reservation_addresses.insert(
295+
*connection_id,
296+
(
297+
relay_addr
298+
.with(Protocol::P2p(relay_peer_id))
299+
.with(Protocol::P2pCircuit)
300+
.with(Protocol::P2p(self.local_peer_id)),
301+
ReservationStatus::Pending,
302+
),
303+
);
304+
305+
ToSwarm::NotifyHandler {
306+
peer_id: relay_peer_id,
307+
handler: NotifyHandler::One(*connection_id),
308+
event: Either::Left(handler::In::Reserve { to_listener }),
309+
}
310+
}
267311
None => {
268312
let opts = DialOpts::peer_id(relay_peer_id)
269-
.addresses(vec![relay_addr])
313+
.addresses(vec![relay_addr.clone()])
270314
.extend_addresses_through_behaviour()
271315
.build();
272316
let relayed_connection_id = opts.connection_id();
273317

318+
self.reservation_addresses.insert(
319+
relayed_connection_id,
320+
(
321+
relay_addr
322+
.with(Protocol::P2p(relay_peer_id))
323+
.with(Protocol::P2pCircuit)
324+
.with(Protocol::P2p(self.local_peer_id)),
325+
ReservationStatus::Pending,
326+
),
327+
);
328+
274329
self.pending_handler_commands
275330
.insert(relayed_connection_id, handler::In::Reserve { to_listener });
276331
ToSwarm::Dial { opts }

protocols/relay/tests/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ fn new_reservation_to_same_relay_replaces_old() {
119119
));
120120

121121
// Trigger new reservation.
122-
let new_listener = client.listen_on(client_addr).unwrap();
122+
let new_listener = client.listen_on(client_addr.clone()).unwrap();
123123

124124
// Wait for
125125
// - listener of old reservation to close
@@ -169,6 +169,12 @@ fn new_reservation_to_same_relay_replaces_old() {
169169
break;
170170
}
171171
}
172+
SwarmEvent::ExternalAddrConfirmed { address } => {
173+
assert_eq!(
174+
address,
175+
client_addr.clone().with(Protocol::P2p(client_peer_id))
176+
);
177+
}
172178
SwarmEvent::Behaviour(ClientEvent::Ping(_)) => {}
173179
e => panic!("{e:?}"),
174180
}
@@ -521,6 +527,9 @@ async fn wait_for_reservation(
521527

522528
loop {
523529
match client.select_next_some().await {
530+
SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => {
531+
assert_eq!(address, client_addr);
532+
}
524533
SwarmEvent::Behaviour(ClientEvent::Relay(
525534
relay::client::Event::ReservationReqAccepted {
526535
relay_peer_id: peer_id,

0 commit comments

Comments
 (0)