@@ -101,10 +101,10 @@ fn log_active(remote_map: &RemoteMap) {
101101 "[{}] is_active {}, connections {}, ip_path {:?}, relay_path {:?}, current_min_rtt {:?}" ,
102102 id. fmt_short( ) ,
103103 info. is_active( ) ,
104- info. connections ( ) . count ( ) ,
104+ info. active_connections ( ) ,
105105 info. has_ip_path( ) ,
106106 info. has_relay_path( ) ,
107- info. current_min_rtt( )
107+ info. current_min_rtt( ) ,
108108 ) ;
109109 }
110110}
@@ -126,7 +126,7 @@ fn log_aggregate(remote_map: &RemoteMap) {
126126 aggregate. relay_path,
127127 SystemTime :: now( )
128128 . duration_since( aggregate. last_update)
129- . unwrap ( )
129+ . unwrap_or_default ( )
130130 ) ;
131131 }
132132}
@@ -166,14 +166,13 @@ mod remote_map {
166166 } ;
167167
168168 use iroh:: {
169- EndpointId , Watcher ,
169+ EndpointId , TransportAddr ,
170170 endpoint:: {
171- AfterHandshakeOutcome , Connection , EndpointHooks , PathInfo , WeakConnectionHandle ,
171+ AfterHandshakeOutcome , Connection , EndpointHooks , PathEvent , WeakConnectionHandle ,
172172 } ,
173173 } ;
174- use n0_future:: task:: AbortOnDropHandle ;
174+ use n0_future:: { StreamExt , task:: AbortOnDropHandle } ;
175175 use tokio:: { sync:: mpsc, task:: JoinSet } ;
176- use tokio_stream:: StreamExt ;
177176 use tracing:: { Instrument , debug, info, info_span} ;
178177
179178 /// Information about a remote info.
@@ -211,19 +210,13 @@ mod remote_map {
211210 }
212211
213212 impl Aggregate {
214- fn update ( & mut self , path : & PathInfo ) {
213+ fn update ( & mut self , addr : TransportAddr , stats : iroh :: endpoint :: PathStats ) {
215214 self . last_update = SystemTime :: now ( ) ;
216- if path. is_ip ( ) {
217- self . ip_path = true ;
218- }
219- if path. is_relay ( ) {
220- self . relay_path = true ;
221- }
222- if let Some ( stats) = path. stats ( ) {
223- debug ! ( "path update addr {:?} {stats:?}" , path. remote_addr( ) ) ;
224- self . rtt_min = self . rtt_min . min ( stats. rtt ) ;
225- self . rtt_max = self . rtt_max . max ( stats. rtt ) ;
226- }
215+ self . ip_path |= addr. is_ip ( ) ;
216+ self . relay_path |= addr. is_relay ( ) ;
217+ debug ! ( "path update {addr} {stats:?}" ) ;
218+ self . rtt_min = self . rtt_min . min ( stats. rtt ) ;
219+ self . rtt_max = self . rtt_max . max ( stats. rtt ) ;
227220 }
228221 }
229222
@@ -239,46 +232,37 @@ mod remote_map {
239232 ///
240233 /// Returns `None` if there are no active connections.
241234 pub fn current_min_rtt ( & self ) -> Option < Duration > {
242- self . connections ( )
243- . flat_map ( |c| c. upgrade ( ) )
244- . flat_map ( |c| c. paths ( ) . get ( ) . into_iter ( ) )
245- . flat_map ( |p| p. stats ( ) )
246- . map ( |s| s. rtt )
235+ self . upgraded ( )
236+ . filter_map ( |c| c. paths ( ) . iter ( ) . map ( |p| p. rtt ( ) ) . min ( ) )
247237 . min ( )
248238 }
249239
250240 /// Returns whether any active connection to the remote has an active IP path.
251- ///
252- /// Returns `None` if there are no active connections.
253- pub fn has_ip_path ( & self ) -> Option < bool > {
254- self . connections ( )
255- . flat_map ( |c| c. upgrade ( ) )
256- . flat_map ( |c| c. paths ( ) . get ( ) )
257- . filter ( |path| path. is_ip ( ) )
258- . map ( |_| true )
259- . next ( )
241+ pub fn has_ip_path ( & self ) -> bool {
242+ self . upgraded ( ) . any ( |c| c. paths ( ) . iter ( ) . any ( |p| p. is_ip ( ) ) )
260243 }
261244
262245 /// Returns whether any active connection to the remote has an active relay path.
263- ///
264- /// Returns `None` if there are no active connections.
265- pub fn has_relay_path ( & self ) -> Option < bool > {
266- self . connections ( )
267- . flat_map ( |c| c. upgrade ( ) )
268- . flat_map ( |c| c. paths ( ) . get ( ) )
269- . filter ( |path| path. is_relay ( ) )
270- . map ( |_| true )
271- . next ( )
246+ pub fn has_relay_path ( & self ) -> bool {
247+ self . upgraded ( )
248+ . any ( |c| c. paths ( ) . iter ( ) . any ( |p| p. is_relay ( ) ) )
272249 }
273250
274- /// Returns `true` if there are active connections to this node .
251+ /// Returns `true` if there are active connections to this remote .
275252 pub fn is_active ( & self ) -> bool {
276- ! self . connections . is_empty ( )
253+ self . active_connections ( ) > 0
277254 }
278255
279- /// Returns an iterator over [`WeakConnectionHandle`] for currently active connections to this remote.
280- pub fn connections ( & self ) -> impl Iterator < Item = & WeakConnectionHandle > {
281- self . connections . values ( )
256+ /// Returns the number of active connections to this remote.
257+ pub fn active_connections ( & self ) -> usize {
258+ self . upgraded ( ) . count ( )
259+ }
260+
261+ /// Returns an iterator over all active handles upgraded to a [`Connection`].
262+ fn upgraded ( & self ) -> impl Iterator < Item = Connection > {
263+ self . connections
264+ . values ( )
265+ . filter_map ( WeakConnectionHandle :: upgrade)
282266 }
283267 }
284268
@@ -368,18 +352,14 @@ mod remote_map {
368352 // Main loop
369353 loop {
370354 tokio:: select! {
371- conn = rx. recv( ) => {
372- match conn {
373- Some ( conn) => {
374- conn_id += 1 ;
375- Self :: on_connection( & mut tasks, map. clone( ) , conn_id, conn) ;
376- } ,
377- None => break ,
378- }
355+ Some ( conn) = rx. recv( ) => {
356+ conn_id += 1 ;
357+ Self :: on_connection( & mut tasks, map. clone( ) , conn_id, conn) ;
379358 }
380359 Some ( res) = tasks. join_next( ) , if !tasks. is_empty( ) => {
381360 res. expect( "conn close task panicked" ) ;
382361 }
362+ else => break ,
383363 }
384364 }
385365
@@ -417,34 +397,42 @@ mod remote_map {
417397 let map = map. clone ( ) ;
418398 async move {
419399 handle. closed ( ) . await ;
420- {
421- let mut inner = map. write ( ) . expect ( "poisoned" ) ;
422- let info = inner. entry ( remote_id) . or_default ( ) ;
423- info. connections . remove ( & conn_id) ;
424- info. aggregate . last_update = SystemTime :: now ( ) ;
425- }
400+ let mut inner = map. write ( ) . expect ( "poisoned" ) ;
401+ let info = inner. entry ( remote_id) . or_default ( ) ;
402+ info. connections . remove ( & conn_id) ;
403+ info. aggregate . last_update = SystemTime :: now ( ) ;
426404 }
427405 . instrument ( tracing:: Span :: current ( ) )
428406 } ) ;
429407
430408 // Track path changes to update stats aggregate.
431- if let Some ( watcher) = conn. handle . upgrade ( ) . map ( |c| c. paths ( ) ) {
432- let remote_id = conn. remote_id ;
433- tasks. spawn ( {
409+ if let Some ( mut path_events) = conn. handle . upgrade ( ) . map ( |conn| conn. path_events ( ) ) {
410+ tasks. spawn (
434411 async move {
435- let mut path_updates = watcher. stream ( ) ;
436- while let Some ( paths) = path_updates. next ( ) . await {
437- {
438- let mut inner = map. write ( ) . expect ( "poisoned" ) ;
439- let info = inner. entry ( remote_id) . or_default ( ) ;
440- for path in paths {
441- info. aggregate . update ( & path) ;
412+ while let Some ( event) = path_events. next ( ) . await {
413+ let mut inner = map. write ( ) . expect ( "poisoned" ) ;
414+ let info = inner. entry ( conn. remote_id ) . or_default ( ) ;
415+ match event {
416+ PathEvent :: Closed {
417+ remote_addr,
418+ last_stats,
419+ ..
420+ } => {
421+ info. aggregate . update ( remote_addr, * last_stats) ;
422+ }
423+ _ => {
424+ if let Some ( conn) = conn. handle . upgrade ( ) {
425+ for path in conn. paths ( ) . iter ( ) {
426+ info. aggregate
427+ . update ( path. remote_addr ( ) . clone ( ) , path. stats ( ) ) ;
428+ }
429+ }
442430 }
443431 }
444432 }
445433 }
446- . instrument ( tracing:: Span :: current ( ) )
447- } ) ;
434+ . instrument ( tracing:: Span :: current ( ) ) ,
435+ ) ;
448436 }
449437 }
450438
@@ -459,8 +447,10 @@ mod remote_map {
459447 let mut inner = map. write ( ) . expect ( "poisoned" ) ;
460448 inner. retain ( |_remote, info| {
461449 info. is_active ( )
462- || now. duration_since ( info. aggregate ( ) . last_update ) . unwrap ( )
463- < retention_time
450+ || now
451+ . duration_since ( info. aggregate ( ) . last_update )
452+ . map ( |age| age < retention_time)
453+ . unwrap_or ( true )
464454 } ) ;
465455 }
466456 }
0 commit comments