Skip to content

Commit 01bcaf4

Browse files
jjyrquake
authored andcommitted
fix: prevent multi times dialing kad connection to the same peer (#20)
* fix: prevent multi times dialing kad connection to the same peer * fix: remove unused line * fix: update network log
1 parent 7119a40 commit 01bcaf4

2 files changed

Lines changed: 66 additions & 16 deletions

File tree

network/src/discovery_service.rs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ impl DiscoveryService {
102102
kademlia_stream: Box<Stream<Item = kad::KadIncomingRequest, Error = IoError> + Send>,
103103
) -> Result<Box<Future<Item = (), Error = IoError> + Send>, IoError> {
104104
let handling_future = Box::new(
105-
// why use loop_fn?????????????
106-
// does client disconnect after discovery?
107105
future::loop_fn(kademlia_stream, {
108106
let peer_id = peer_id.clone();
109107
let kad_system = Arc::clone(&self.kad_system);
@@ -179,7 +177,7 @@ impl DiscoveryService {
179177
if let Some(to_notify) = kad_manage.to_notify.take() {
180178
to_notify.notify();
181179
}
182-
kad_manage.new_kad_connection(peer_id.clone(), kad_connection_controller.clone());
180+
kad_manage.complete_kad_connection(peer_id.clone(), kad_connection_controller.clone());
183181
kad_manage.fetch_unique_connec(peer_id.clone())
184182
};
185183
Ok(Box::new(
@@ -190,11 +188,11 @@ impl DiscoveryService {
190188
// drop kad connection
191189
move |val| {
192190
info!("kad exit because {:?}", val);
193-
//kad_manage.lock().drop_connection(&peer_id);
194191
let mut kad_manage = kad_manage.lock();
195192
if let Some(to_notify) = kad_manage.to_notify.take() {
196193
to_notify.notify();
197194
}
195+
kad_manage.drop_connection(&peer_id);
198196
val
199197
}
200198
}),
@@ -503,29 +501,42 @@ where
503501

504502
let mut kad_manage = self.kad_manage.lock();
505503
kad_manage.to_notify = Some(task::current());
506-
trace!(target: "discovery", "handling discovery loop");
507504
Ok(Async::NotReady)
508505
}
509506
}
510507

508+
const MAX_DIALING_COUNT: usize = 30;
509+
const MAX_CONNECTING_COUNT: usize = 30;
510+
const KAD_DIAL_TIMEOUT_SECS: u64 = 15;
511+
511512
pub(crate) struct KadManage {
512-
connected_kad_peers: FnvHashMap<PeerId, UniqueConnec<kad::KadConnecController>>,
513+
kad_connections: FnvHashMap<PeerId, UniqueConnec<kad::KadConnecController>>,
513514
kad_pending_dials: FnvHashMap<PeerId, Vec<oneshot::Sender<kad::KadConnecController>>>,
515+
kad_dialing_peers: FnvHashMap<PeerId, Instant>,
514516
kad_upgrade: kad::KadConnecConfig,
515517
pub(crate) to_notify: Option<task::Task>,
516518
}
517519

518520
impl KadManage {
519521
pub fn new(_network: Arc<Network>, kad_upgrade: kad::KadConnecConfig) -> Self {
520522
KadManage {
521-
connected_kad_peers: FnvHashMap::with_capacity_and_hasher(10, Default::default()),
523+
kad_connections: FnvHashMap::with_capacity_and_hasher(10, Default::default()),
522524
kad_pending_dials: FnvHashMap::with_capacity_and_hasher(10, Default::default()),
525+
kad_dialing_peers: FnvHashMap::with_capacity_and_hasher(10, Default::default()),
523526
kad_upgrade,
524527
to_notify: None,
525528
}
526529
}
527530

528-
fn new_kad_connection(
531+
// check and remove timeout dials
532+
fn check_unused_conn(&mut self) {
533+
let now = Instant::now();
534+
let timeout = Duration::from_secs(KAD_DIAL_TIMEOUT_SECS);
535+
self.kad_dialing_peers
536+
.retain(move |_peer_id, added_at| now.duration_since(*added_at) > timeout);
537+
}
538+
539+
fn complete_kad_connection(
529540
&mut self,
530541
peer_id: PeerId,
531542
kad_connection_controller: kad::KadConnecController,
@@ -537,10 +548,24 @@ impl KadManage {
537548
let _ = tx.send(kad_connection_controller.clone());
538549
}
539550
}
551+
// remove dialing status
552+
self.kad_dialing_peers.remove(&peer_id);
553+
}
554+
555+
fn connected_peers(&self) -> impl Iterator<Item = &PeerId> {
556+
self.kad_connections
557+
.iter()
558+
.filter_map(|(key, unique_connec)| {
559+
if unique_connec.is_alive() {
560+
Some(key)
561+
} else {
562+
None
563+
}
564+
})
540565
}
541566

542567
fn fetch_unique_connec(&mut self, peer_id: PeerId) -> UniqueConnec<kad::KadConnecController> {
543-
self.connected_kad_peers
568+
self.kad_connections
544569
.entry(peer_id)
545570
.or_insert_with(UniqueConnec::empty)
546571
.to_owned()
@@ -553,7 +578,7 @@ impl KadManage {
553578
addr: &Multiaddr,
554579
transport: Tran,
555580
swarm_controller: &SwarmController<St, Box<Future<Item = (), Error = IoError> + Send>>,
556-
) -> Result<UniqueConnec<kad::KadConnecController>, IoError>
581+
) -> Result<(), IoError>
557582
where
558583
Tran: MuxedTransport<Output = TransportOutput<To>> + Clone + Send + 'static,
559584
Tran::MultiaddrFuture: Send + 'static,
@@ -574,8 +599,34 @@ impl KadManage {
574599
debug!(target: "discovery", "dial kad connection to {:?} {:?}", peer_id, addr);
575600
let kad_connection = self.fetch_unique_connec(peer_id.clone());
576601
if kad_connection.is_alive() {
577-
return Ok(kad_connection);
602+
return Ok(());
603+
}
604+
605+
// remove unused connections
606+
self.check_unused_conn();
607+
// check peer
608+
if self.kad_dialing_peers.contains_key(&peer_id)
609+
|| self.kad_dialing_peers.len() >= MAX_DIALING_COUNT
610+
{
611+
debug!(target: "discovery", "we are already dialing to {:?} {:?}", peer_id, addr);
612+
return Ok(());
578613
}
614+
let is_connected = self
615+
.kad_connections
616+
.get(&peer_id)
617+
.map(|unique_connec| unique_connec.is_alive())
618+
.unwrap_or(false);
619+
let count_of_connected_peers = self.connected_peers().collect::<Vec<_>>().len();
620+
if is_connected || count_of_connected_peers >= MAX_CONNECTING_COUNT {
621+
debug!(target: "discovery", "we are already connected to {:?} {:?}", peer_id, addr);
622+
// should return a error?
623+
return Ok(());
624+
}
625+
//set peer to dialing list
626+
self.kad_dialing_peers
627+
.entry(peer_id.clone())
628+
.or_insert_with(Instant::now);
629+
579630
let kad_upgrade = self.kad_upgrade.clone();
580631
let transport = transport
581632
.and_then(move |out, endpoint, client_addr| {
@@ -598,12 +649,11 @@ impl KadManage {
598649
});
599650

600651
let _ = kad_connection.dial(swarm_controller, addr, transport);
601-
Ok(kad_connection)
652+
Ok(())
602653
}
603654

604-
#[allow(dead_code)]
605655
fn drop_connection(&mut self, peer_id: &PeerId) {
606656
debug!(target: "discovery","disconnect kad connection from {:?}", peer_id);
607-
self.connected_kad_peers.remove(peer_id);
657+
self.kad_connections.remove(peer_id);
608658
}
609659
}

network/src/network.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,10 +392,10 @@ impl Network {
392392
let expected_peer_id = expected_peer_id.clone();
393393
move |(peer_id, protocol), _, client_addr| {
394394
if peer_id == expected_peer_id {
395-
trace!("dial success to {:?}", peer_id);
395+
debug!(target: "network", "success connect to {:?}", peer_id);
396396
future::ok((protocol, client_addr))
397397
} else {
398-
trace!("dial peer id mismatch {:?}", peer_id);
398+
debug!(target: "network", "connected peer id mismatch {:?}, disconnect!", peer_id);
399399
//Because multiaddrs is responsed by a third-part node, the mismatched
400400
//peer itself should not seems as a misbehaviour peer.
401401
//So we do not report this behaviour

0 commit comments

Comments
 (0)