Skip to content

Commit

Permalink
feat(relay): emit external address on reservation
Browse files Browse the repository at this point in the history
Resolves #4618.

Pull-Request: #4809.
  • Loading branch information
dariusc93 authored Nov 14, 2023
1 parent e57cd88 commit cf8a24d
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 13 deletions.
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 @@ -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.1", 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.4", path = "misc/server" }
Expand Down
3 changes: 3 additions & 0 deletions protocols/dcutr/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ async fn wait_for_reservation(
}
SwarmEvent::Behaviour(ClientEvent::Identify(_)) => {}
SwarmEvent::NewExternalAddrCandidate { .. } => {}
SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => {
assert_eq!(address, client_addr);
}
e => panic!("{e:?}"),
}
}
Expand Down
6 changes: 5 additions & 1 deletion protocols/relay/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## 0.17.0

## 0.17.1 - unreleased
- Automatically register relayed addresses as external addresses.
See [PR 4809](https://github.com/libp2p/rust-lib2pp/pulls/4809).

## 0.17.0
- Don't close connections on protocol failures within the relay-server.
To achieve this, error handling was restructured:
- `libp2p::relay::outbound::stop::FatalUpgradeError` has been removed.
Expand Down
2 changes: 1 addition & 1 deletion protocols/relay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>", "Max Inden <[email protected]>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down
71 changes: 63 additions & 8 deletions protocols/relay/src/priv_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -69,6 +70,12 @@ pub enum Event {
},
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ReservationStatus {
Pending,
Confirmed,
}

/// [`NetworkBehaviour`] implementation of the relay client
/// functionality of the circuit relay v2 protocol.
pub struct Behaviour {
Expand All @@ -79,6 +86,11 @@ pub struct Behaviour {
/// connection.
directly_connected_peers: HashMap<PeerId, Vec<ConnectionId>>,

/// 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<ConnectionId, (Multiaddr, ReservationStatus)>,

/// Queue of actions to return when polled.
queued_actions: VecDeque<ToSwarm<Event, Either<handler::In, Void>>>,

Expand All @@ -92,6 +104,7 @@ pub fn new(local_peer_id: PeerId) -> (Transport, Behaviour) {
local_peer_id,
from_transport,
directly_connected_peers: Default::default(),
reservation_addresses: Default::default(),
queued_actions: Default::default(),
pending_handler_commands: Default::default(),
};
Expand Down Expand Up @@ -126,6 +139,12 @@ impl Behaviour {
unreachable!("`on_connection_closed` for unconnected peer.")
}
};
if let Some((addr, ReservationStatus::Confirmed)) =
self.reservation_addresses.remove(&connection_id)
{
self.queued_actions
.push_back(ToSwarm::ExternalAddrExpired(addr));
}
}
}
}
Expand Down Expand Up @@ -200,6 +219,7 @@ impl NetworkBehaviour for Behaviour {
self.on_connection_closed(connection_closed)
}
FromSwarm::DialFailure(DialFailure { connection_id, .. }) => {
self.reservation_addresses.remove(&connection_id);
self.pending_handler_commands.remove(&connection_id);
}
_ => {}
Expand All @@ -209,7 +229,7 @@ impl NetworkBehaviour for Behaviour {
fn on_connection_handler_event(
&mut self,
event_source: PeerId,
_connection: ConnectionId,
connection: ConnectionId,
handler_event: THandlerOutEvent<Self>,
) {
let handler_event = match handler_event {
Expand All @@ -219,6 +239,17 @@ impl NetworkBehaviour for Behaviour {

let event = match handler_event {
handler::Event::ReservationReqAccepted { renewal, limit } => {
let (addr, status) = self
.reservation_addresses
.get_mut(&connection)
.expect("Relay connection exist");

if !renewal && *status == ReservationStatus::Pending {
*status = ReservationStatus::Confirmed;
self.queued_actions
.push_back(ToSwarm::ExternalAddrConfirmed(addr.clone()));
}

Event::ReservationReqAccepted {
relay_peer_id: event_source,
renewal,
Expand All @@ -236,7 +267,7 @@ impl NetworkBehaviour for Behaviour {
}
};

self.queued_actions.push_back(ToSwarm::GenerateEvent(event))
self.queued_actions.push_back(ToSwarm::GenerateEvent(event));
}

#[tracing::instrument(level = "trace", name = "NetworkBehaviour::poll", skip(self, cx))]
Expand All @@ -259,18 +290,42 @@ 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.reservation_addresses.insert(
*connection_id,
(
relay_addr
.with(Protocol::P2p(relay_peer_id))
.with(Protocol::P2pCircuit)
.with(Protocol::P2p(self.local_peer_id)),
ReservationStatus::Pending,
),
);

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.reservation_addresses.insert(
relayed_connection_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
.insert(relayed_connection_id, handler::In::Reserve { to_listener });
ToSwarm::Dial { opts }
Expand Down
11 changes: 10 additions & 1 deletion protocols/relay/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -169,6 +169,12 @@ fn new_reservation_to_same_relay_replaces_old() {
break;
}
}
SwarmEvent::ExternalAddrConfirmed { address } => {
assert_eq!(
address,
client_addr.clone().with(Protocol::P2p(client_peer_id))
);
}
SwarmEvent::Behaviour(ClientEvent::Ping(_)) => {}
e => panic!("{e:?}"),
}
Expand Down Expand Up @@ -521,6 +527,9 @@ async fn wait_for_reservation(

loop {
match client.select_next_some().await {
SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => {
assert_eq!(address, client_addr);
}
SwarmEvent::Behaviour(ClientEvent::Relay(
relay::client::Event::ReservationReqAccepted {
relay_peer_id: peer_id,
Expand Down

0 comments on commit cf8a24d

Please sign in to comment.