@@ -33,6 +33,7 @@ use futures::future::{BoxFuture, FutureExt};
3333use futures:: io:: { AsyncRead , AsyncWrite } ;
3434use futures:: ready;
3535use futures:: stream:: StreamExt ;
36+ use libp2p_core:: multiaddr:: Protocol ;
3637use libp2p_core:: { Endpoint , Multiaddr } ;
3738use libp2p_identity:: PeerId ;
3839use 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.
7481pub 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 }
0 commit comments