@@ -22,8 +22,8 @@ use std::{
22
22
net:: { IpAddr , Ipv4Addr , Ipv6Addr , SocketAddr , SocketAddrV4 , SocketAddrV6 } ,
23
23
pin:: Pin ,
24
24
sync:: {
25
- Arc , Mutex , RwLock ,
26
25
atomic:: { AtomicBool , AtomicU64 , Ordering } ,
26
+ Arc , Mutex , RwLock ,
27
27
} ,
28
28
task:: { Context , Poll } ,
29
29
} ;
@@ -33,24 +33,24 @@ use data_encoding::HEXLOWER;
33
33
use iroh_base:: { NodeAddr , NodeId , PublicKey , RelayUrl , SecretKey } ;
34
34
use iroh_relay:: RelayMap ;
35
35
use n0_future:: {
36
- StreamExt ,
37
36
boxed:: BoxStream ,
38
37
task:: { self , AbortOnDropHandle } ,
39
38
time:: { self , Duration , Instant } ,
39
+ StreamExt ,
40
40
} ;
41
41
use n0_watcher:: { self , Watchable , Watcher } ;
42
42
use nested_enum_utils:: common_fields;
43
43
use netwatch:: netmon;
44
44
#[ cfg( not( wasm_browser) ) ]
45
- use netwatch:: { UdpSocket , ip:: LocalAddresses } ;
46
- use quinn:: { AsyncUdpSocket , ServerConfig } ;
45
+ use netwatch:: { ip:: LocalAddresses , UdpSocket } ;
46
+ use quinn:: { AsyncUdpSocket , ServerConfig , WeakConnectionHandle } ;
47
47
use rand:: Rng ;
48
48
use smallvec:: SmallVec ;
49
49
use snafu:: { ResultExt , Snafu } ;
50
- use tokio:: sync:: { Mutex as AsyncMutex , mpsc } ;
50
+ use tokio:: sync:: { mpsc , Mutex as AsyncMutex } ;
51
51
use tokio_util:: sync:: CancellationToken ;
52
52
use tracing:: {
53
- Instrument , Level , debug, error, event, info, info_span, instrument, trace, trace_span, warn,
53
+ debug, error, event, info, info_span, instrument, trace, trace_span, warn, Instrument , Level ,
54
54
} ;
55
55
use transports:: LocalAddrsWatch ;
56
56
use url:: Url ;
@@ -72,7 +72,7 @@ use crate::{
72
72
defaults:: timeouts:: NET_REPORT_TIMEOUT ,
73
73
disco:: { self , SendAddr } ,
74
74
discovery:: { Discovery , DiscoveryItem , DiscoverySubscribers , NodeData , UserData } ,
75
- key:: { DecryptionError , SharedSecret , public_ed_box , secret_ed_box } ,
75
+ key:: { public_ed_box , secret_ed_box , DecryptionError , SharedSecret } ,
76
76
metrics:: EndpointMetrics ,
77
77
net_report:: { self , IfStateDetails , IpMappedAddresses , Report } ,
78
78
} ;
@@ -199,6 +199,9 @@ pub(crate) struct MagicSock {
199
199
ipv6_reported : Arc < AtomicBool > ,
200
200
/// Tracks the networkmap node entity for each node discovery key.
201
201
node_map : NodeMap ,
202
+ /// Tracks existing connections
203
+ connection_map : ConnectionMap ,
204
+
202
205
/// Tracks the mapped IP addresses
203
206
ip_mapped_addrs : IpMappedAddresses ,
204
207
/// Local addresses
@@ -225,6 +228,22 @@ pub(crate) struct MagicSock {
225
228
pub ( crate ) metrics : EndpointMetrics ,
226
229
}
227
230
231
+ #[ derive( Default , Debug ) ]
232
+ struct ConnectionMap {
233
+ map : std:: sync:: Mutex < BTreeMap < NodeId , Vec < WeakConnectionHandle > > > ,
234
+ }
235
+
236
+ impl ConnectionMap {
237
+ fn insert ( & self , remote : NodeId , handle : WeakConnectionHandle ) {
238
+ self . map
239
+ . lock ( )
240
+ . expect ( "poisoned" )
241
+ . entry ( remote)
242
+ . or_default ( )
243
+ . push ( handle) ;
244
+ }
245
+ }
246
+
228
247
#[ allow( missing_docs) ]
229
248
#[ common_fields( {
230
249
backtrace: Option <snafu:: Backtrace >,
@@ -275,6 +294,10 @@ impl MagicSock {
275
294
self . local_addrs_watch . get ( ) . expect ( "disconnected" )
276
295
}
277
296
297
+ pub ( crate ) fn register_connection ( & self , remote : NodeId , conn : WeakConnectionHandle ) {
298
+ self . connection_map . insert ( remote, conn) ;
299
+ }
300
+
278
301
#[ cfg( not( wasm_browser) ) ]
279
302
fn ip_bind_addrs ( & self ) -> & [ SocketAddr ] {
280
303
& self . ip_bind_addrs
@@ -397,8 +420,45 @@ impl MagicSock {
397
420
}
398
421
}
399
422
if !addr. is_empty ( ) {
423
+ // Add addr to the internal NodeMap
400
424
self . node_map
401
- . add_node_addr ( addr, source, & self . metrics . magicsock ) ;
425
+ . add_node_addr ( addr. clone ( ) , source, & self . metrics . magicsock ) ;
426
+
427
+ // Add paths to the existing connections
428
+ {
429
+ let mut map = self . connection_map . map . lock ( ) . expect ( "poisoned" ) ;
430
+ let mut to_delete = Vec :: new ( ) ;
431
+ if let Some ( conns) = map. get_mut ( & addr. node_id ) {
432
+ for ( i, conn) in conns. into_iter ( ) . enumerate ( ) {
433
+ if let Some ( conn) = conn. upgrade ( ) {
434
+ for addr in addr. direct_addresses ( ) {
435
+ let conn = conn. clone ( ) ;
436
+ let addr = * addr;
437
+ task:: spawn ( async move {
438
+ if let Err ( err) = conn
439
+ . open_path ( addr, quinn_proto:: PathStatus :: Available )
440
+ . await
441
+ {
442
+ warn ! ( "failed to open path {:?}" , err) ;
443
+ }
444
+ } ) ;
445
+ }
446
+ // TODO: add relay path as mapped addr
447
+ } else {
448
+ to_delete. push ( i) ;
449
+ }
450
+ }
451
+ // cleanup dead connections
452
+ let mut i = 0 ;
453
+ conns. retain ( |_| {
454
+ let remove = to_delete. contains ( & i) ;
455
+ i += 1 ;
456
+
457
+ !remove
458
+ } ) ;
459
+ }
460
+ }
461
+
402
462
Ok ( ( ) )
403
463
} else if pruned != 0 {
404
464
Err ( EmptyPrunedSnafu { pruned } . build ( ) )
@@ -509,8 +569,8 @@ impl MagicSock {
509
569
let mut active_paths = SmallVec :: < [ _ ; 3 ] > :: new ( ) ;
510
570
511
571
match MappedAddr :: from ( transmit. destination ) {
512
- MappedAddr :: None ( dest ) => {
513
- error ! ( %dest , "Cannot convert to a mapped address." ) ;
572
+ MappedAddr :: None ( addr ) => {
573
+ active_paths . push ( transports :: Addr :: from ( addr ) ) ;
514
574
}
515
575
MappedAddr :: NodeId ( dest) => {
516
576
trace ! (
@@ -527,15 +587,14 @@ impl MagicSock {
527
587
self . ipv6_reported . load ( Ordering :: Relaxed ) ,
528
588
& self . metrics . magicsock ,
529
589
) {
530
- Some ( ( node_id, udp_addr , relay_url, ping_actions) ) => {
590
+ Some ( ( node_id, _udp_addr , relay_url, ping_actions) ) => {
531
591
if !ping_actions. is_empty ( ) {
532
592
self . actor_sender
533
593
. try_send ( ActorMessage :: PingActions ( ping_actions) )
534
594
. ok ( ) ;
535
595
}
536
- if let Some ( addr) = udp_addr {
537
- active_paths. push ( transports:: Addr :: from ( addr) ) ;
538
- }
596
+ // NodeId mapped addrs are only used for relays, currently.
597
+ // IP based addrs will have been added as individual paths
539
598
if let Some ( url) = relay_url {
540
599
active_paths. push ( transports:: Addr :: Relay ( url, node_id) ) ;
541
600
}
@@ -1297,6 +1356,7 @@ impl Handle {
1297
1356
actor_sender : actor_sender. clone ( ) ,
1298
1357
ipv6_reported,
1299
1358
node_map,
1359
+ connection_map : Default :: default ( ) ,
1300
1360
ip_mapped_addrs : ip_mapped_addrs. clone ( ) ,
1301
1361
discovery,
1302
1362
discovery_user_data : RwLock :: new ( discovery_user_data) ,
@@ -2415,23 +2475,22 @@ mod tests {
2415
2475
2416
2476
use data_encoding:: HEXLOWER ;
2417
2477
use iroh_base:: { NodeAddr , NodeId , PublicKey } ;
2418
- use n0_future:: { StreamExt , time } ;
2478
+ use n0_future:: { time , StreamExt } ;
2419
2479
use n0_snafu:: { Result , ResultExt } ;
2420
2480
use n0_watcher:: Watcher ;
2421
2481
use quinn:: ServerConfig ;
2422
2482
use rand:: { Rng , RngCore } ;
2423
2483
use tokio:: task:: JoinSet ;
2424
2484
use tokio_util:: task:: AbortOnDropHandle ;
2425
- use tracing:: { Instrument , error, info, info_span, instrument} ;
2485
+ use tracing:: { error, info, info_span, instrument, Instrument } ;
2426
2486
use tracing_test:: traced_test;
2427
2487
2428
2488
use super :: { NodeIdMappedAddr , Options } ;
2429
2489
use crate :: {
2430
- Endpoint , RelayMap , RelayMode , SecretKey ,
2431
2490
dns:: DnsResolver ,
2432
2491
endpoint:: { DirectAddr , PathSelection , Source } ,
2433
- magicsock:: { Handle , MagicSock , node_map } ,
2434
- tls,
2492
+ magicsock:: { node_map , Handle , MagicSock } ,
2493
+ tls, Endpoint , RelayMap , RelayMode , SecretKey ,
2435
2494
} ;
2436
2495
2437
2496
const ALPN : & [ u8 ] = b"n0/test/1" ;
@@ -3277,11 +3336,10 @@ mod tests {
3277
3336
. magic_sock ( )
3278
3337
. add_node_addr ( empty_addr, node_map:: Source :: App )
3279
3338
. unwrap_err ( ) ;
3280
- assert ! (
3281
- err. to_string( )
3282
- . to_lowercase( )
3283
- . contains( "empty addressing info" )
3284
- ) ;
3339
+ assert ! ( err
3340
+ . to_string( )
3341
+ . to_lowercase( )
3342
+ . contains( "empty addressing info" ) ) ;
3285
3343
3286
3344
// relay url only
3287
3345
let addr = NodeAddr {
0 commit comments