@@ -3216,4 +3216,82 @@ mod tests {
32163216
32173217 Ok ( ( ) )
32183218 }
3219+
3220+ /// Test that we can immediately reconnect after respawning an endpoint with the same node id.
3221+ #[ tokio:: test]
3222+ #[ traced_test]
3223+ async fn can_abort_and_reconnect ( ) -> Result {
3224+ const TEST_ALPN : & [ u8 ] = b"/iroh/test/1" ;
3225+ const TIMEOUT : Duration = Duration :: from_secs ( 5 ) ;
3226+
3227+ let mut rng = & mut rand_chacha:: ChaCha12Rng :: seed_from_u64 ( 1 ) ;
3228+
3229+ // Spawn a server endpoint.
3230+ let server = Endpoint :: builder ( )
3231+ . secret_key ( SecretKey :: generate ( & mut rng) )
3232+ . relay_mode ( RelayMode :: Disabled )
3233+ . alpns ( vec ! [ TEST_ALPN . to_vec( ) ] )
3234+ . bind ( )
3235+ . await ?;
3236+ let server_addr = server. node_addr ( ) . initialized ( ) . await . e ( ) ?;
3237+
3238+ // The server accepts all connections, waits for them being closed, and sends the
3239+ // close code over a channel.
3240+ let ( tx, mut rx) = tokio:: sync:: mpsc:: channel ( 1 ) ;
3241+ let server_loop = tokio:: task:: spawn ( async move {
3242+ while let Some ( conn) = server. accept ( ) . await {
3243+ let conn = conn. accept ( ) . e ( ) ?. await . e ( ) ?;
3244+ let res = match conn. closed ( ) . await {
3245+ ConnectionError :: ApplicationClosed ( frame) => Ok ( u64:: from ( frame. error_code ) ) ,
3246+ reason @ _ => Err ( reason) ,
3247+ } ;
3248+ tx. send ( res) . await . e ( ) ?;
3249+ }
3250+ Result :: < _ , n0_snafu:: Error > :: Ok ( ( ) )
3251+ } ) ;
3252+
3253+ // Clients connect to the server, and immediately close the connection with a code
3254+ // and then close the endpoint.
3255+ async fn connect ( secret_key : SecretKey , addr : NodeAddr , code : u32 ) -> Result < ( ) > {
3256+ info ! ( "spawn client node {}" , secret_key. public( ) . fmt_short( ) ) ;
3257+ let ep = Endpoint :: builder ( )
3258+ . secret_key ( secret_key)
3259+ . relay_mode ( RelayMode :: Disabled )
3260+ . bind ( )
3261+ . await ?;
3262+ info ! (
3263+ "connect client {} ({:?}) to {addr:?}" ,
3264+ ep. node_id( ) . fmt_short( ) ,
3265+ ep. bound_sockets( ) ,
3266+ ) ;
3267+ let conn = ep. connect ( addr, TEST_ALPN ) . await ?;
3268+ conn. close ( code. into ( ) , b"bye" ) ;
3269+ ep. close ( ) . await ;
3270+ info ! ( "client closed" ) ;
3271+ Ok ( ( ) )
3272+ }
3273+
3274+ let client_secret_key = SecretKey :: generate ( & mut rng) ;
3275+
3276+ // First connection
3277+ n0_future:: time:: timeout (
3278+ TIMEOUT ,
3279+ connect ( client_secret_key. clone ( ) , server_addr. clone ( ) , 23 ) ,
3280+ )
3281+ . await
3282+ . e ( ) ??;
3283+ assert_eq ! ( rx. recv( ) . await . unwrap( ) . unwrap( ) , 23 ) ;
3284+
3285+ // Second connection
3286+ n0_future:: time:: timeout (
3287+ TIMEOUT ,
3288+ connect ( client_secret_key. clone ( ) , server_addr. clone ( ) , 24 ) ,
3289+ )
3290+ . await
3291+ . e ( ) ??;
3292+ assert_eq ! ( rx. recv( ) . await . unwrap( ) . unwrap( ) , 24 ) ;
3293+ server_loop. abort ( ) ;
3294+
3295+ Ok ( ( ) )
3296+ }
32193297}
0 commit comments