@@ -29,7 +29,7 @@ use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey};
2929use futures_util:: { FutureExt , future:: Shared } ;
3030use iroh_base:: { EndpointId , RelayUrl } ;
3131use n0_error:: { e, stack_error} ;
32- use n0_future:: { TryFutureExt , future:: Boxed as BoxFuture , time:: Duration } ;
32+ use n0_future:: { Stream , StreamExt , TryFutureExt , future:: Boxed as BoxFuture , time:: Duration } ;
3333use noq:: WeakConnectionHandle as NoqWeakConnectionHandle ;
3434use pin_project:: pin_project;
3535use tracing:: { event, warn} ;
@@ -1134,7 +1134,20 @@ impl Connection<HandshakeCompleted> {
11341134 /// [`PathEvent`]: crate::endpoint::PathEvent
11351135 /// [`PathEvent::Lagged`]: crate::endpoint::PathEvent::Lagged
11361136 pub fn path_events ( & self ) -> PathEventStream {
1137- self . data . paths . updates ( )
1137+ self . data . paths . events ( )
1138+ }
1139+
1140+ /// Returns a new [`PathList`] whenever it changes, starting with the current value.
1141+ ///
1142+ /// TODO(Frando): Do we want this?
1143+ pub fn path_updates ( & self ) -> impl Stream < Item = PathList < ' _ > > {
1144+ let events = self . path_events ( ) ;
1145+ n0_future:: stream:: unfold ( ( true , events) , async |( is_first, mut events) | {
1146+ if !is_first {
1147+ events. next ( ) . await ?;
1148+ }
1149+ Some ( ( self . paths ( ) , ( false , events) ) )
1150+ } )
11381151 }
11391152
11401153 /// Returns the side of the connection (client or server).
@@ -1318,7 +1331,7 @@ mod tests {
13181331 use super :: Endpoint ;
13191332 use crate :: {
13201333 RelayMode ,
1321- endpoint:: { ConnectOptions , Incoming , PathEvent , PathEventStream , ZeroRttStatus , presets} ,
1334+ endpoint:: { ConnectOptions , Connection , Incoming , ZeroRttStatus , presets} ,
13221335 test_utils:: run_relay_server,
13231336 } ;
13241337
@@ -1562,68 +1575,42 @@ mod tests {
15621575 async { server. accept( ) . await . unwrap( ) . await . unwrap( ) }
15631576 ) ;
15641577 info ! ( "connected" ) ;
1565- // Subscribe before the initial check to avoid missing events emitted
1566- // during the early exchange.
1578+
15671579 let mut events_client = conn_client. path_events ( ) ;
15681580 let mut events_server = conn_server. path_events ( ) ;
15691581
1570- /// Advance the event stream until we have seen at least one IP and
1571- /// one relay Opened event (current snapshot may also already satisfy
1572- /// the condition, which is checked first).
1573- async fn wait_for_paths (
1574- events : & mut PathEventStream ,
1575- snapshot : impl Fn ( ) -> ( bool , bool ) + Send + Sync + ' static ,
1576- ) {
1577- let ( mut has_ip, mut has_relay) = snapshot ( ) ;
1578- while !( has_ip && has_relay) {
1579- let Some ( ev) = events. next ( ) . await else {
1582+ /// Advances the path stream until at least one IP and one relay paths are available.
1583+ ///
1584+ /// Panics if the path stream finishes before that happens.
1585+ async fn wait_for_paths ( conn : & Connection ) {
1586+ let mut events = conn. path_events ( ) ;
1587+ loop {
1588+ let paths = conn. paths ( ) ;
1589+ if paths. len ( ) >= 2
1590+ && paths. iter ( ) . any ( |p| p. is_ip ( ) )
1591+ && paths. iter ( ) . any ( |p| p. is_relay ( ) )
1592+ {
1593+ break ;
1594+ }
1595+ if events. next ( ) . await . is_none ( ) {
15801596 panic ! ( "path event stream ended before reaching target state" ) ;
15811597 } ;
1582- if let PathEvent :: Opened { remote_addr, .. } = ev {
1583- if remote_addr. is_ip ( ) {
1584- has_ip = true ;
1585- }
1586- if remote_addr. is_relay ( ) {
1587- has_relay = true ;
1588- }
1589- }
1590- // Also re-check snapshot in case the opens happened before
1591- // we subscribed (unlikely here since we subscribed right
1592- // after connect, but cheap).
1593- let ( ip2, relay2) = snapshot ( ) ;
1594- has_ip |= ip2;
1595- has_relay |= relay2;
15961598 }
15971599 }
15981600
1599- let conn_server_for_snap = conn_server. clone ( ) ;
1600- let conn_client_for_snap = conn_client. clone ( ) ;
1601- // Verify that both connections are notified of path changes and get
1602- // an IP and a relay path.
1601+ // Verify that both connections are notified of path changes and get an IP and a relay path.
16031602 tokio:: join!(
16041603 async {
1605- tokio:: time:: timeout(
1606- Duration :: from_secs( 1 ) ,
1607- wait_for_paths( & mut events_server, move || {
1608- let p = conn_server_for_snap. paths( ) ;
1609- ( p. iter( ) . any( |p| p. is_ip( ) ) , p. iter( ) . any( |p| p. is_relay( ) ) )
1610- } ) ,
1611- )
1612- . instrument( error_span!( "paths-server" ) )
1613- . await
1614- . unwrap( )
1604+ tokio:: time:: timeout( Duration :: from_secs( 1 ) , wait_for_paths( & conn_server) )
1605+ . instrument( error_span!( "paths-server" ) )
1606+ . await
1607+ . unwrap( )
16151608 } ,
16161609 async {
1617- tokio:: time:: timeout(
1618- Duration :: from_secs( 1 ) ,
1619- wait_for_paths( & mut events_client, move || {
1620- let p = conn_client_for_snap. paths( ) ;
1621- ( p. iter( ) . any( |p| p. is_ip( ) ) , p. iter( ) . any( |p| p. is_relay( ) ) )
1622- } ) ,
1623- )
1624- . instrument( error_span!( "paths-client" ) )
1625- . await
1626- . unwrap( )
1610+ tokio:: time:: timeout( Duration :: from_secs( 1 ) , wait_for_paths( & conn_client) )
1611+ . instrument( error_span!( "paths-client" ) )
1612+ . await
1613+ . unwrap( )
16271614 }
16281615 ) ;
16291616
0 commit comments