@@ -50,6 +50,7 @@ use crate::{
50
50
} ;
51
51
use fnv:: { FnvHashMap } ;
52
52
use futures:: { prelude:: * , future} ;
53
+ use smallvec:: SmallVec ;
53
54
use std:: {
54
55
collections:: hash_map,
55
56
convert:: TryFrom as _,
@@ -78,21 +79,17 @@ where
78
79
79
80
/// The ongoing dialing attempts.
80
81
///
81
- /// The `Network` enforces a single ongoing dialing attempt per peer,
82
- /// even if multiple (established) connections per peer are allowed.
83
- /// However, a single dialing attempt operates on a list of addresses
84
- /// to connect to, which can be extended with new addresses while
85
- /// the connection attempt is still in progress. Thereby each
86
- /// dialing attempt is associated with a new connection and hence a new
87
- /// connection ID.
82
+ /// There may be multiple ongoing dialing attempts to the same peer.
83
+ /// Each dialing attempt is associated with a new connection and hence
84
+ /// a new connection ID.
88
85
///
89
86
/// > **Note**: `dialing` must be consistent with the pending outgoing
90
87
/// > connections in `pool`. That is, for every entry in `dialing`
91
88
/// > there must exist a pending outgoing connection in `pool` with
92
89
/// > the same connection ID. This is ensured by the implementation of
93
90
/// > `Network` (see `dial_peer_impl` and `on_connection_failed`)
94
- /// > together with the implementation of `DialingConnection ::abort`.
95
- dialing : FnvHashMap < TPeerId , peer:: DialingAttempt > ,
91
+ /// > together with the implementation of `DialingAttempt ::abort`.
92
+ dialing : FnvHashMap < TPeerId , SmallVec < [ peer:: DialingState ; 10 ] > > ,
96
93
}
97
94
98
95
impl < TTrans , TInEvent , TOutEvent , THandler , TConnInfo , TPeerId > fmt:: Debug for
@@ -381,8 +378,11 @@ where
381
378
Poll :: Pending => return Poll :: Pending ,
382
379
Poll :: Ready ( PoolEvent :: ConnectionEstablished { connection, num_established } ) => {
383
380
match self . dialing . entry ( connection. peer_id ( ) . clone ( ) ) {
384
- hash_map:: Entry :: Occupied ( e) if e. get ( ) . id == connection. id ( ) => {
385
- e. remove ( ) ;
381
+ hash_map:: Entry :: Occupied ( mut e) => {
382
+ e. get_mut ( ) . retain ( |s| s. current . 0 != connection. id ( ) ) ;
383
+ if e. get ( ) . is_empty ( ) {
384
+ e. remove ( ) ;
385
+ }
386
386
} ,
387
387
_ => { }
388
388
}
@@ -453,7 +453,7 @@ fn dial_peer_impl<TMuxer, TInEvent, TOutEvent, THandler, TTrans, TConnInfo, TPee
453
453
transport : TTrans ,
454
454
pool : & mut Pool < TInEvent , TOutEvent , THandler , TTrans :: Error ,
455
455
<THandler :: Handler as ConnectionHandler >:: Error , TConnInfo , TPeerId > ,
456
- dialing : & mut FnvHashMap < TPeerId , peer:: DialingAttempt > ,
456
+ dialing : & mut FnvHashMap < TPeerId , SmallVec < [ peer:: DialingState ; 10 ] > > ,
457
457
opts : DialingOpts < TPeerId , THandler >
458
458
) -> Result < ConnectionId , ConnectionLimit >
459
459
where
@@ -489,14 +489,12 @@ where
489
489
} ;
490
490
491
491
if let Ok ( id) = & result {
492
- let former = dialing. insert ( opts. peer ,
493
- peer:: DialingAttempt {
494
- id : * id,
495
- current : opts. address ,
496
- next : opts. remaining ,
492
+ dialing. entry ( opts. peer ) . or_default ( ) . push (
493
+ peer:: DialingState {
494
+ current : ( * id, opts. address ) ,
495
+ remaining : opts. remaining ,
497
496
} ,
498
497
) ;
499
- debug_assert ! ( former. is_none( ) ) ;
500
498
}
501
499
502
500
result
@@ -508,7 +506,7 @@ where
508
506
/// If the failed connection attempt was a dialing attempt and there
509
507
/// are more addresses to try, new `DialingOpts` are returned.
510
508
fn on_connection_failed < ' a , TTrans , TInEvent , TOutEvent , THandler , TConnInfo , TPeerId > (
511
- dialing : & mut FnvHashMap < TPeerId , peer:: DialingAttempt > ,
509
+ dialing : & mut FnvHashMap < TPeerId , SmallVec < [ peer:: DialingState ; 10 ] > > ,
512
510
id : ConnectionId ,
513
511
endpoint : ConnectedPoint ,
514
512
error : PendingConnectionError < TTrans :: Error > ,
@@ -521,27 +519,34 @@ where
521
519
TPeerId : Eq + Hash + Clone ,
522
520
{
523
521
// Check if the failed connection is associated with a dialing attempt.
524
- // TODO: could be more optimal than iterating over everything
525
- let dialing_peer = dialing. iter ( ) // (1)
526
- . find ( |( _, a) | a. id == id)
527
- . map ( |( p, _) | p. clone ( ) ) ;
522
+ let dialing_failed = dialing. iter_mut ( )
523
+ . find_map ( |( peer, attempts) | {
524
+ if let Some ( pos) = attempts. iter ( ) . position ( |s| s. current . 0 == id) {
525
+ let attempt = attempts. remove ( pos) ;
526
+ let last = attempts. is_empty ( ) ;
527
+ Some ( ( peer. clone ( ) , attempt, last) )
528
+ } else {
529
+ None
530
+ }
531
+ } ) ;
528
532
529
- if let Some ( peer_id) = dialing_peer {
530
- // A pending outgoing connection to a known peer failed.
531
- let mut attempt = dialing. remove ( & peer_id) . expect ( "by (1)" ) ;
533
+ if let Some ( ( peer_id, mut attempt, last) ) = dialing_failed {
534
+ if last {
535
+ dialing. remove ( & peer_id) ;
536
+ }
532
537
533
- let num_remain = u32:: try_from ( attempt. next . len ( ) ) . unwrap ( ) ;
534
- let failed_addr = attempt. current . clone ( ) ;
538
+ let num_remain = u32:: try_from ( attempt. remaining . len ( ) ) . unwrap ( ) ;
539
+ let failed_addr = attempt. current . 1 . clone ( ) ;
535
540
536
541
let ( opts, attempts_remaining) =
537
542
if num_remain > 0 {
538
543
if let Some ( handler) = handler {
539
- let next_attempt = attempt. next . remove ( 0 ) ;
544
+ let next_attempt = attempt. remaining . remove ( 0 ) ;
540
545
let opts = DialingOpts {
541
546
peer : peer_id. clone ( ) ,
542
547
handler,
543
548
address : next_attempt,
544
- remaining : attempt. next
549
+ remaining : attempt. remaining
545
550
} ;
546
551
( Some ( opts) , num_remain)
547
552
} else {
@@ -581,9 +586,13 @@ where
581
586
/// Information about the network obtained by [`Network::info()`].
582
587
#[ derive( Clone , Debug ) ]
583
588
pub struct NetworkInfo {
589
+ /// The total number of connected peers.
584
590
pub num_peers : usize ,
591
+ /// The total number of connections, both established and pending.
585
592
pub num_connections : usize ,
593
+ /// The total number of pending connections, both incoming and outgoing.
586
594
pub num_connections_pending : usize ,
595
+ /// The total number of established connections.
587
596
pub num_connections_established : usize ,
588
597
}
589
598
@@ -633,4 +642,9 @@ impl NetworkConfig {
633
642
self . pool_limits . max_established_per_peer = Some ( n) ;
634
643
self
635
644
}
645
+
646
+ pub fn set_outgoing_per_peer_limit ( & mut self , n : usize ) -> & mut Self {
647
+ self . pool_limits . max_outgoing_per_peer = Some ( n) ;
648
+ self
649
+ }
636
650
}
0 commit comments