@@ -21,8 +21,8 @@ use std::{
2121} ;
2222
2323use ed25519_dalek:: { VerifyingKey , pkcs8:: DecodePublicKey } ;
24- use iroh_base:: { NodeAddr , NodeId , SecretKey } ;
25- use iroh_relay:: RelayMap ;
24+ use iroh_base:: { NodeAddr , NodeId , RelayUrl , SecretKey } ;
25+ use iroh_relay:: { RelayMap , RelayNode } ;
2626use n0_future:: time:: Duration ;
2727use n0_watcher:: Watcher ;
2828use nested_enum_utils:: common_fields;
@@ -632,6 +632,24 @@ impl Endpoint {
632632 self . msock . endpoint ( ) . set_server_config ( Some ( server_config) ) ;
633633 }
634634
635+ /// Adds the provided configuration to the [`RelayMap`].
636+ ///
637+ /// Replacing and returning any existing configuration for [`RelayUrl`].
638+ pub async fn insert_relay (
639+ & self ,
640+ relay : RelayUrl ,
641+ node : Arc < RelayNode > ,
642+ ) -> Option < Arc < RelayNode > > {
643+ self . msock . insert_relay ( relay, node) . await
644+ }
645+
646+ /// Removes the configuration from the [`RelayMap`] for the provided [`RelayUrl`].
647+ ///
648+ /// Returns any existing configuration.
649+ pub async fn remove_relay ( & self , relay : & RelayUrl ) -> Option < Arc < RelayNode > > {
650+ self . msock . remove_relay ( relay) . await
651+ }
652+
635653 // # Methods for establishing connectivity.
636654
637655 /// Connects to a remote [`Endpoint`].
@@ -2430,6 +2448,115 @@ mod tests {
24302448 Ok ( ( ) )
24312449 }
24322450
2451+ #[ tokio:: test]
2452+ #[ traced_test]
2453+ async fn endpoint_relay_map_change ( ) -> Result {
2454+ let ( relay_map, relay_url, _guard1) = run_relay_server ( ) . await ?;
2455+ let client = Endpoint :: builder ( )
2456+ . insecure_skip_relay_cert_verify ( true )
2457+ . relay_mode ( RelayMode :: Custom ( relay_map. clone ( ) ) )
2458+ . bind ( )
2459+ . await ?;
2460+ let server = Endpoint :: builder ( )
2461+ . insecure_skip_relay_cert_verify ( true )
2462+ . relay_mode ( RelayMode :: Custom ( relay_map) )
2463+ . alpns ( vec ! [ TEST_ALPN . to_vec( ) ] )
2464+ . bind ( )
2465+ . await ?;
2466+
2467+ let task = tokio:: spawn ( {
2468+ let server = server. clone ( ) ;
2469+ async move {
2470+ for i in 0 ..2 {
2471+ println ! ( "accept: round {i}" ) ;
2472+ let Some ( conn) = server. accept ( ) . await else {
2473+ snafu:: whatever!( "Expected an incoming connection" ) ;
2474+ } ;
2475+ let conn = conn. await . e ( ) ?;
2476+ let ( mut send, mut recv) = conn. accept_bi ( ) . await . e ( ) ?;
2477+ let data = recv. read_to_end ( 1000 ) . await . e ( ) ?;
2478+ send. write_all ( & data) . await . e ( ) ?;
2479+ send. finish ( ) . e ( ) ?;
2480+ conn. closed ( ) . await ;
2481+ }
2482+ Ok :: < _ , Error > ( ( ) )
2483+ }
2484+ } ) ;
2485+
2486+ server. online ( ) . await ;
2487+
2488+ let mut addr = server. node_addr ( ) ;
2489+ println ! ( "round1: {:?}" , addr) ;
2490+
2491+ // remove direct addrs to force relay usage
2492+ addr. direct_addresses . clear ( ) ;
2493+
2494+ let conn = client. connect ( addr, TEST_ALPN ) . await ?;
2495+ let ( mut send, mut recv) = conn. open_bi ( ) . await . e ( ) ?;
2496+ send. write_all ( b"Hello, world!" ) . await . e ( ) ?;
2497+ send. finish ( ) . e ( ) ?;
2498+ let data = recv. read_to_end ( 1000 ) . await . e ( ) ?;
2499+ conn. close ( 0u32 . into ( ) , b"bye!" ) ;
2500+
2501+ assert_eq ! ( & data, b"Hello, world!" ) ;
2502+
2503+ // setup a second relay server
2504+ let ( new_relay_map, new_relay_url, _guard2) = run_relay_server ( ) . await ?;
2505+ let new_node = new_relay_map
2506+ . get_node ( & new_relay_url)
2507+ . expect ( "missing node" )
2508+ . clone ( ) ;
2509+ dbg ! ( & new_relay_map) ;
2510+
2511+ let addr_watcher = server. watch_node_addr ( ) ;
2512+
2513+ // add new new relay
2514+ assert ! (
2515+ server
2516+ . insert_relay( new_relay_url. clone( ) , new_node. clone( ) )
2517+ . await
2518+ . is_none( )
2519+ ) ;
2520+ // remove the old relay
2521+ assert ! ( server. remove_relay( & relay_url) . await . is_some( ) ) ;
2522+
2523+ println ! ( "------- changed ----- " ) ;
2524+
2525+ let mut addr = tokio:: time:: timeout ( Duration :: from_secs ( 10 ) , async move {
2526+ let mut stream = addr_watcher. stream ( ) ;
2527+ while let Some ( addr) = stream. next ( ) . await {
2528+ if addr. relay_url . as_ref ( ) != Some ( & relay_url) {
2529+ return addr;
2530+ }
2531+ }
2532+ panic ! ( "failed to change relay" ) ;
2533+ } )
2534+ . await
2535+ . e ( ) ?;
2536+
2537+ println ! ( "round2: {:?}" , addr) ;
2538+ assert_eq ! ( addr. relay_url, Some ( new_relay_url) ) ;
2539+
2540+ // remove direct addrs to force relay usage
2541+ addr. direct_addresses . clear ( ) ;
2542+
2543+ let conn = client. connect ( addr, TEST_ALPN ) . await ?;
2544+ let ( mut send, mut recv) = conn. open_bi ( ) . await . e ( ) ?;
2545+ send. write_all ( b"Hello, world!" ) . await . e ( ) ?;
2546+ send. finish ( ) . e ( ) ?;
2547+ let data = recv. read_to_end ( 1000 ) . await . e ( ) ?;
2548+ conn. close ( 0u32 . into ( ) , b"bye!" ) ;
2549+
2550+ task. await . e ( ) ??;
2551+
2552+ client. close ( ) . await ;
2553+ server. close ( ) . await ;
2554+
2555+ assert_eq ! ( & data, b"Hello, world!" ) ;
2556+
2557+ Ok ( ( ) )
2558+ }
2559+
24332560 #[ tokio:: test]
24342561 #[ traced_test]
24352562 async fn endpoint_bidi_send_recv ( ) -> Result {
0 commit comments