Skip to main content

ab_networking/
node_runner.rs

1#![expect(
2    clippy::rest_pattern_accessible_field,
3    reason = "Too verbose otherwise"
4)]
5
6use crate::behavior::persistent_parameters::{
7    KnownPeersRegistry, PeerAddressRemovedEvent, append_p2p_suffix, remove_p2p_suffix,
8};
9use crate::behavior::{Behavior, Event};
10use crate::constructor::DummyRecordStore;
11use crate::constructor::temporary_bans::TemporaryBans;
12use crate::protocols::request_response::request_response_factory::{
13    Event as RequestResponseEvent, IfDisconnected,
14};
15use crate::shared::{Command, CreatedSubscription, PeerDiscovered, Shared};
16use crate::utils::{SubspaceMetrics, is_global_address_or_dns, strip_peer_id};
17use async_lock::Mutex as AsyncMutex;
18use bytes::Bytes;
19use event_listener_primitives::HandlerId;
20use futures::channel::mpsc;
21use futures::future::Fuse;
22use futures::{FutureExt, StreamExt};
23use libp2p::autonat::{Event as AutonatEvent, NatStatus, OutboundProbeEvent};
24use libp2p::core::ConnectedPoint;
25use libp2p::gossipsub::{Event as GossipsubEvent, TopicHash};
26use libp2p::identify::Event as IdentifyEvent;
27use libp2p::kad::{
28    Behaviour as Kademlia, BootstrapOk, Event as KademliaEvent, GetClosestPeersError,
29    GetClosestPeersOk, GetProvidersError, GetProvidersOk, GetRecordError, GetRecordOk,
30    InboundRequest, KBucketKey, PeerRecord, ProgressStep, PutRecordOk, QueryId, QueryResult,
31    Quorum, Record, RecordKey,
32};
33use libp2p::metrics::{Metrics, Recorder};
34use libp2p::multiaddr::Protocol;
35use libp2p::swarm::dial_opts::DialOpts;
36use libp2p::swarm::{DialError, SwarmEvent};
37use libp2p::{Multiaddr, PeerId, Swarm, TransportError};
38use nohash_hasher::IntMap;
39use parking_lot::Mutex;
40use std::collections::hash_map::Entry;
41use std::collections::{HashMap, HashSet};
42use std::net::IpAddr;
43use std::pin::Pin;
44use std::sync::atomic::Ordering;
45use std::sync::{Arc as StdArc, Weak};
46use std::time::Duration;
47use std::{fmt, slice};
48use tokio::sync::OwnedSemaphorePermit;
49use tokio::task::yield_now;
50use tokio::time::Sleep;
51use tracing::{debug, error, trace, warn};
52use triomphe::Arc;
53
54enum QueryResultSender {
55    Value {
56        sender: mpsc::UnboundedSender<PeerRecord>,
57        // Just holding onto permit while data structure is not dropped
58        _permit: OwnedSemaphorePermit,
59    },
60    ClosestPeers {
61        sender: mpsc::UnboundedSender<PeerId>,
62        // Just holding onto permit while data structure is not dropped
63        _permit: Option<OwnedSemaphorePermit>,
64    },
65    Providers {
66        key: RecordKey,
67        sender: mpsc::UnboundedSender<PeerId>,
68        // Just holding onto permit while data structure is not dropped
69        _permit: Option<OwnedSemaphorePermit>,
70    },
71    PutValue {
72        sender: mpsc::UnboundedSender<()>,
73        // Just holding onto permit while data structure is not dropped
74        _permit: OwnedSemaphorePermit,
75    },
76    Bootstrap {
77        sender: mpsc::UnboundedSender<()>,
78    },
79}
80
81#[derive(Debug, Default)]
82enum BootstrapCommandState {
83    #[default]
84    NotStarted,
85    InProgress(mpsc::UnboundedReceiver<()>),
86    Finished,
87}
88
89/// Runner for the Node.
90#[must_use = "Node does not function properly unless its runner is driven forward"]
91pub struct NodeRunner {
92    /// Should non-global addresses be added to the DHT?
93    allow_non_global_addresses_in_dht: bool,
94    /// Whether node is listening on some addresses
95    is_listening: bool,
96    command_receiver: mpsc::Receiver<Command>,
97    swarm: Swarm<Behavior>,
98    shared_weak: Weak<Shared>,
99    /// How frequently should random queries be done using Kademlia DHT to populate routing table.
100    next_random_query_interval: Duration,
101    query_id_receivers: HashMap<QueryId, QueryResultSender>,
102    /// Global subscription counter, is assigned to every (logical) subscription and is used for
103    /// unsubscribing.
104    next_subscription_id: usize,
105    /// Topic subscription senders for logical subscriptions (multiple logical subscriptions can be
106    /// present for the same physical subscription).
107    topic_subscription_senders: HashMap<TopicHash, IntMap<usize, mpsc::UnboundedSender<Bytes>>>,
108    random_query_timeout: Pin<Box<Fuse<Sleep>>>,
109    /// Defines an interval between periodical tasks.
110    periodical_tasks_interval: Pin<Box<Fuse<Sleep>>>,
111    /// Manages the networking parameters like known peers and addresses
112    known_peers_registry: Box<dyn KnownPeersRegistry>,
113    connected_servers: HashSet<PeerId>,
114    /// Defines set of peers with a permanent connection (and reconnection if necessary).
115    reserved_peers: HashMap<PeerId, Multiaddr>,
116    /// Temporarily banned peers.
117    temporary_bans: Arc<Mutex<TemporaryBans>>,
118    /// Libp2p Prometheus metrics.
119    libp2p_metrics: Option<Metrics>,
120    /// Subspace Prometheus metrics.
121    metrics: Option<SubspaceMetrics>,
122    /// Mapping from specific peer to ip addresses
123    peer_ip_addresses: HashMap<PeerId, HashSet<IpAddr>>,
124    /// Defines protocol version for the network peers. Affects network partition.
125    protocol_version: String,
126    /// Addresses to bootstrap Kademlia network
127    bootstrap_addresses: Vec<Multiaddr>,
128    /// Ensures a single bootstrap on run() invocation.
129    bootstrap_command_state: Arc<AsyncMutex<BootstrapCommandState>>,
130    /// Receives an event on peer address removal from the persistent storage.
131    removed_addresses_rx: mpsc::UnboundedReceiver<PeerAddressRemovedEvent>,
132    /// Optional storage for the [`HandlerId`] of the address removal task.
133    /// We keep to stop the task along with the rest of the networking.
134    _address_removal_task_handler_id: Option<HandlerId>,
135}
136
137impl fmt::Debug for NodeRunner {
138    #[inline]
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        f.debug_struct("NodeRunner").finish_non_exhaustive()
141    }
142}
143
144// Helper struct for NodeRunner configuration (clippy requirement).
145pub(crate) struct NodeRunnerConfig {
146    pub(crate) allow_non_global_addresses_in_dht: bool,
147    /// Whether node is listening on some addresses
148    pub(crate) is_listening: bool,
149    pub(crate) command_receiver: mpsc::Receiver<Command>,
150    pub(crate) swarm: Swarm<Behavior>,
151    pub(crate) shared_weak: Weak<Shared>,
152    pub(crate) next_random_query_interval: Duration,
153    pub(crate) known_peers_registry: Box<dyn KnownPeersRegistry>,
154    pub(crate) reserved_peers: HashMap<PeerId, Multiaddr>,
155    pub(crate) temporary_bans: Arc<Mutex<TemporaryBans>>,
156    pub(crate) libp2p_metrics: Option<Metrics>,
157    pub(crate) metrics: Option<SubspaceMetrics>,
158    pub(crate) protocol_version: String,
159    pub(crate) bootstrap_addresses: Vec<Multiaddr>,
160}
161
162impl NodeRunner {
163    pub(crate) fn new(
164        NodeRunnerConfig {
165            allow_non_global_addresses_in_dht,
166            is_listening,
167            command_receiver,
168            swarm,
169            shared_weak,
170            next_random_query_interval,
171            mut known_peers_registry,
172            reserved_peers,
173            temporary_bans,
174            libp2p_metrics,
175            metrics,
176            protocol_version,
177            bootstrap_addresses,
178        }: NodeRunnerConfig,
179    ) -> Self {
180        // Setup the address removal events exchange between persistent params storage and Kademlia.
181        let (removed_addresses_tx, removed_addresses_rx) = mpsc::unbounded();
182        let mut address_removal_task_handler_id = None;
183        if let Some(handler_id) = known_peers_registry.on_unreachable_address({
184            StdArc::new(move |event| {
185                if let Err(error) = removed_addresses_tx.unbounded_send(event.clone()) {
186                    debug!(?error, ?event, "Cannot send PeerAddressRemovedEvent");
187                }
188            })
189        }) {
190            address_removal_task_handler_id.replace(handler_id);
191        }
192
193        Self {
194            allow_non_global_addresses_in_dht,
195            is_listening,
196            command_receiver,
197            swarm,
198            shared_weak,
199            next_random_query_interval,
200            query_id_receivers: HashMap::default(),
201            next_subscription_id: 0,
202            topic_subscription_senders: HashMap::default(),
203            // We'll make the first query right away and continue at the interval.
204            random_query_timeout: Box::pin(tokio::time::sleep(Duration::from_secs(0)).fuse()),
205            // We'll make the first dial right away and continue at the interval.
206            periodical_tasks_interval: Box::pin(tokio::time::sleep(Duration::from_secs(0)).fuse()),
207            known_peers_registry,
208            connected_servers: HashSet::new(),
209            reserved_peers,
210            temporary_bans,
211            libp2p_metrics,
212            metrics,
213            peer_ip_addresses: HashMap::new(),
214            protocol_version,
215            bootstrap_addresses,
216            bootstrap_command_state: Arc::new(AsyncMutex::new(BootstrapCommandState::default())),
217            removed_addresses_rx,
218            _address_removal_task_handler_id: address_removal_task_handler_id,
219        }
220    }
221
222    /// Drives the main networking future forward.
223    pub async fn run(&mut self) {
224        if self.is_listening {
225            // Wait for listen addresses, otherwise we will get ephemeral addresses in external
226            // address candidates that we do not want
227            loop {
228                if self.swarm.listeners().next().is_some() {
229                    break;
230                }
231
232                if let Some(swarm_event) = self.swarm.next().await {
233                    self.register_event_metrics(&swarm_event);
234                    self.handle_swarm_event(swarm_event).await;
235                } else {
236                    break;
237                }
238            }
239        }
240
241        self.bootstrap().await;
242
243        loop {
244            futures::select! {
245                () = &mut self.random_query_timeout => {
246                    self.handle_random_query_interval();
247                    // Increase interval 2x, but to at most 1 minute.
248                    self.random_query_timeout =
249                        Box::pin(tokio::time::sleep(self.next_random_query_interval).fuse());
250                    self.next_random_query_interval =
251                        (self.next_random_query_interval * 2).min(Duration::from_mins(1));
252                },
253                swarm_event = self.swarm.next() => {
254                    if let Some(swarm_event) = swarm_event {
255                        self.register_event_metrics(&swarm_event);
256                        self.handle_swarm_event(swarm_event).await;
257                    } else {
258                        break;
259                    }
260                },
261                command = self.command_receiver.next() => {
262                    if let Some(command) = command {
263                        self.handle_command(command);
264                    } else {
265                        break;
266                    }
267                },
268                () = self.known_peers_registry.run().fuse() => {
269                    trace!("Network parameters registry runner exited");
270                },
271                () = &mut self.periodical_tasks_interval => {
272                    self.handle_periodical_tasks();
273
274                    self.periodical_tasks_interval =
275                        Box::pin(tokio::time::sleep(Duration::from_secs(5)).fuse());
276                },
277                event = self.removed_addresses_rx.select_next_some() => {
278                    self.handle_removed_address_event(event);
279                },
280            }
281
282            // Allow to exit from busy loop during graceful shutdown
283            yield_now().await;
284        }
285    }
286
287    /// Bootstraps Kademlia network
288    async fn bootstrap(&mut self) {
289        // Add bootstrap nodes first to make sure there is space for them in k-buckets
290        for (peer_id, address) in strip_peer_id(self.bootstrap_addresses.clone()) {
291            self.swarm
292                .behaviour_mut()
293                .kademlia
294                .add_address(&peer_id, address);
295        }
296
297        let known_peers = self.known_peers_registry.all_known_peers().await;
298
299        if !known_peers.is_empty() {
300            for (peer_id, addresses) in known_peers {
301                for address in addresses.clone() {
302                    let address = match address.with_p2p(peer_id) {
303                        Ok(address) => address,
304                        Err(address) => {
305                            warn!(%peer_id, %address, "Failed to add peer ID to known peer address");
306                            break;
307                        }
308                    };
309                    self.swarm
310                        .behaviour_mut()
311                        .kademlia
312                        .add_address(&peer_id, address);
313                }
314
315                if let Err(error) = self
316                    .swarm
317                    .dial(DialOpts::peer_id(peer_id).addresses(addresses).build())
318                {
319                    warn!(%peer_id, %error, "Failed to dial peer during bootstrapping");
320                }
321            }
322
323            // Do bootstrap asynchronously
324            self.handle_command(Command::Bootstrap {
325                result_sender: None,
326            });
327            return;
328        }
329
330        let bootstrap_command_state = Arc::clone(&self.bootstrap_command_state);
331        let mut bootstrap_command_state = bootstrap_command_state.lock().await;
332        let bootstrap_command_receiver = match &mut *bootstrap_command_state {
333            BootstrapCommandState::NotStarted => {
334                debug!("Bootstrap started.");
335
336                let (bootstrap_command_sender, bootstrap_command_receiver) = mpsc::unbounded();
337
338                self.handle_command(Command::Bootstrap {
339                    result_sender: Some(bootstrap_command_sender),
340                });
341
342                *bootstrap_command_state =
343                    BootstrapCommandState::InProgress(bootstrap_command_receiver);
344                match &mut *bootstrap_command_state {
345                    BootstrapCommandState::InProgress(bootstrap_command_receiver) => {
346                        bootstrap_command_receiver
347                    }
348                    _ => {
349                        unreachable!("Was just set to that exact value");
350                    }
351                }
352            }
353            BootstrapCommandState::InProgress(bootstrap_command_receiver) => {
354                bootstrap_command_receiver
355            }
356            BootstrapCommandState::Finished => {
357                return;
358            }
359        };
360
361        let mut bootstrap_step = 0usize;
362        loop {
363            futures::select! {
364                swarm_event = self.swarm.next() => {
365                    if let Some(swarm_event) = swarm_event {
366                        self.register_event_metrics(&swarm_event);
367                        self.handle_swarm_event(swarm_event).await;
368                    } else {
369                        break;
370                    }
371                },
372                result = bootstrap_command_receiver.next() => {
373                    if result.is_some() {
374                        debug!(%bootstrap_step, "Kademlia bootstrapping...");
375                        bootstrap_step += 1;
376                    } else {
377                        break;
378                    }
379                }
380            }
381        }
382
383        debug!("Bootstrap finished.");
384        *bootstrap_command_state = BootstrapCommandState::Finished;
385    }
386
387    /// Handles periodical tasks.
388    fn handle_periodical_tasks(&mut self) {
389        // Log current connections.
390        let network_info = self.swarm.network_info();
391        let connections = network_info.connection_counters();
392
393        debug!(?connections, "Current connections and limits.");
394
395        // Renew known external addresses.
396        let mut external_addresses = self.swarm.external_addresses().cloned().collect::<Vec<_>>();
397
398        if let Some(shared) = self.shared_weak.upgrade() {
399            debug!(?external_addresses, "Renew external addresses.");
400            let mut addresses = shared.external_addresses.lock();
401            addresses.clear();
402            addresses.append(&mut external_addresses);
403        }
404
405        self.log_kademlia_stats();
406    }
407
408    fn handle_random_query_interval(&mut self) {
409        let random_peer_id = PeerId::random();
410
411        trace!("Starting random Kademlia query for {}", random_peer_id);
412
413        self.swarm
414            .behaviour_mut()
415            .kademlia
416            .get_closest_peers(random_peer_id);
417    }
418
419    fn handle_removed_address_event(&mut self, event: PeerAddressRemovedEvent) {
420        trace!(?event, "Peer address removed event.");
421
422        let bootstrap_node_ids = strip_peer_id(self.bootstrap_addresses.clone())
423            .into_iter()
424            .map(|(peer_id, _)| peer_id)
425            .collect::<Vec<_>>();
426
427        if bootstrap_node_ids.contains(&event.peer_id) {
428            debug!(
429                ?event,
430                ?bootstrap_node_ids,
431                "Skipped removing bootstrap node from Kademlia buckets."
432            );
433
434            return;
435        }
436
437        // Remove both versions of the address
438        self.swarm.behaviour_mut().kademlia.remove_address(
439            &event.peer_id,
440            &append_p2p_suffix(event.peer_id, event.address.clone()),
441        );
442
443        self.swarm
444            .behaviour_mut()
445            .kademlia
446            .remove_address(&event.peer_id, &remove_p2p_suffix(event.address));
447    }
448
449    fn handle_remove_listeners(&mut self, removed_listeners: &[Multiaddr]) {
450        let Some(shared) = self.shared_weak.upgrade() else {
451            return;
452        };
453
454        // Remove both versions of the address
455        let peer_id = shared.id;
456        shared.listeners.lock().retain(|old_listener| {
457            !removed_listeners.contains(&append_p2p_suffix(peer_id, old_listener.clone()))
458                && !removed_listeners.contains(&remove_p2p_suffix(old_listener.clone()))
459        });
460    }
461
462    async fn handle_swarm_event(&mut self, swarm_event: SwarmEvent<Event>) {
463        #[expect(clippy::ref_patterns, reason = "Much less awkward this way")]
464        match swarm_event {
465            SwarmEvent::Behaviour(Event::Identify(event)) => {
466                self.handle_identify_event(*event);
467            }
468            SwarmEvent::Behaviour(Event::Kademlia(event)) => {
469                self.handle_kademlia_event(event);
470            }
471            SwarmEvent::Behaviour(Event::Gossipsub(event)) => {
472                self.handle_gossipsub_event(event);
473            }
474            SwarmEvent::Behaviour(Event::RequestResponse(event)) => {
475                self.handle_request_response_event(event);
476            }
477            SwarmEvent::Behaviour(Event::Autonat(event)) => {
478                self.handle_autonat_event(event);
479            }
480            ref event @ SwarmEvent::NewListenAddr { ref address, .. } => {
481                trace!(?event, "New local listener  event.");
482
483                let Some(shared) = self.shared_weak.upgrade() else {
484                    return;
485                };
486                shared.listeners.lock().push(address.clone());
487                shared.handlers.new_listener.call_simple(address);
488            }
489            ref event @ SwarmEvent::ListenerClosed { ref addresses, .. } => {
490                trace!(?event, "Local listener closed event.");
491                self.handle_remove_listeners(addresses);
492            }
493            ref event @ SwarmEvent::ExpiredListenAddr { ref address, .. } => {
494                trace!(?event, "Local listener expired event.");
495                self.handle_remove_listeners(slice::from_ref(address));
496            }
497            SwarmEvent::ConnectionEstablished {
498                peer_id,
499                endpoint,
500                num_established,
501                ..
502            } => {
503                // Save known addresses that were successfully dialed.
504                if let ConnectedPoint::Dialer { address, .. } = &endpoint {
505                    // filter non-global addresses when non-globals addresses are disabled
506                    if self.allow_non_global_addresses_in_dht || is_global_address_or_dns(address) {
507                        self.known_peers_registry
508                            .add_known_peer(peer_id, vec![address.clone()])
509                            .await;
510                    }
511                }
512
513                let Some(shared) = self.shared_weak.upgrade() else {
514                    return;
515                };
516
517                let is_reserved_peer = self.reserved_peers.contains_key(&peer_id);
518                debug!(
519                    %peer_id,
520                    %is_reserved_peer,
521                    ?endpoint,
522                    %num_established,
523                    "Connection established"
524                );
525
526                let maybe_remote_ip =
527                    endpoint
528                        .get_remote_address()
529                        .iter()
530                        .find_map(|protocol| match protocol {
531                            Protocol::Ip4(ip) => Some(IpAddr::V4(ip)),
532                            Protocol::Ip6(ip) => Some(IpAddr::V6(ip)),
533                            _ => None,
534                        });
535                if let Some(ip) = maybe_remote_ip {
536                    self.peer_ip_addresses
537                        .entry(peer_id)
538                        .and_modify(|ips| {
539                            ips.insert(ip);
540                        })
541                        .or_insert(HashSet::from([ip]));
542                }
543
544                let num_established_peer_connections = shared
545                    .num_established_peer_connections
546                    .fetch_add(1, Ordering::SeqCst)
547                    + 1;
548
549                shared
550                    .handlers
551                    .num_established_peer_connections_change
552                    .call_simple(&num_established_peer_connections);
553
554                // A new connection
555                if num_established.get() == 1 {
556                    shared.handlers.connected_peer.call_simple(&peer_id);
557                }
558
559                if let Some(metrics) = self.metrics.as_ref() {
560                    metrics.inc_established_connections();
561                }
562            }
563            SwarmEvent::ConnectionClosed {
564                peer_id,
565                num_established,
566                cause,
567                ..
568            } => {
569                let Some(shared) = self.shared_weak.upgrade() else {
570                    return;
571                };
572
573                debug!(
574                    %peer_id,
575                    ?cause,
576                    %num_established,
577                    "Connection closed with peer"
578                );
579
580                if num_established == 0 {
581                    self.peer_ip_addresses.remove(&peer_id);
582                    self.connected_servers.remove(&peer_id);
583                }
584                let num_established_peer_connections = shared
585                    .num_established_peer_connections
586                    .fetch_sub(1, Ordering::SeqCst)
587                    - 1;
588
589                shared
590                    .handlers
591                    .num_established_peer_connections_change
592                    .call_simple(&num_established_peer_connections);
593
594                // No more connections
595                if num_established == 0 {
596                    shared.handlers.disconnected_peer.call_simple(&peer_id);
597                }
598
599                if let Some(metrics) = self.metrics.as_ref() {
600                    metrics.dec_established_connections();
601                }
602            }
603            SwarmEvent::OutgoingConnectionError { peer_id, error, .. } => {
604                if let Some(peer_id) = &peer_id {
605                    let should_ban_temporarily =
606                        self.should_temporary_ban_on_dial_error(peer_id, &error);
607
608                    trace!(%should_ban_temporarily, "Temporary bans conditions.");
609
610                    if should_ban_temporarily {
611                        self.temporary_bans.lock().create_or_extend(peer_id);
612                        debug!(%peer_id, ?error, "Peer was temporarily banned.");
613                    }
614                }
615
616                debug!(
617                    ?peer_id,
618                    ?error,
619                    "SwarmEvent::OutgoingConnectionError for peer."
620                );
621
622                match error {
623                    DialError::Transport(ref addresses) => {
624                        for (addr, _) in addresses {
625                            trace!(?error, ?peer_id, %addr, "SwarmEvent::OutgoingConnectionError (DialError::Transport) for peer.");
626                            if let Some(peer_id) = peer_id {
627                                self.known_peers_registry
628                                    .remove_known_peer_addresses(peer_id, vec![addr.clone()])
629                                    .await;
630                            }
631                        }
632                    }
633                    DialError::WrongPeerId { obtained, .. } => {
634                        trace!(?error, ?peer_id, obtained_peer_id=?obtained, "SwarmEvent::WrongPeerId (DialError::WrongPeerId) for peer.");
635
636                        if let Some(ref peer_id) = peer_id {
637                            let kademlia = &mut self.swarm.behaviour_mut().kademlia;
638                            let _: Option<_> = kademlia.remove_peer(peer_id);
639                        }
640                    }
641                    _ => {
642                        trace!(?error, ?peer_id, "SwarmEvent::OutgoingConnectionError");
643                    }
644                }
645            }
646            SwarmEvent::NewExternalAddrCandidate { address } => {
647                trace!(%address, "External address candidate");
648            }
649            SwarmEvent::ExternalAddrConfirmed { address } => {
650                debug!(%address, "Confirmed external address");
651
652                let connected_peers = self.swarm.connected_peers().copied().collect::<Vec<_>>();
653                self.swarm.behaviour_mut().identify.push(connected_peers);
654            }
655            SwarmEvent::ExternalAddrExpired { address } => {
656                debug!(%address, "External address expired");
657
658                let connected_peers = self.swarm.connected_peers().copied().collect::<Vec<_>>();
659                self.swarm.behaviour_mut().identify.push(connected_peers);
660            }
661            other => {
662                trace!("Other swarm event: {:?}", other);
663            }
664        }
665    }
666
667    fn should_temporary_ban_on_dial_error(&self, peer_id: &PeerId, error: &DialError) -> bool {
668        // TODO: Replace with banning of addresses rather peer IDs if this helps
669        if true {
670            return false;
671        }
672
673        // Ban temporarily only peers without active connections.
674        if self.swarm.is_connected(peer_id) {
675            return false;
676        }
677
678        match &error {
679            DialError::Transport(addresses) => {
680                for (_, error) in addresses {
681                    match error {
682                        TransportError::MultiaddrNotSupported(_) => {
683                            return true;
684                        }
685                        TransportError::Other(_) => {
686                            // Ignore "temporary ban" errors
687                            if self.temporary_bans.lock().is_banned(peer_id) {
688                                return false;
689                            }
690                        }
691                    }
692                }
693                // Other errors that are not related to temporary bans
694                true
695            }
696            DialError::LocalPeerId { .. } => {
697                // We don't ban ourselves
698                debug!("Local peer dial attempt detected.");
699
700                false
701            }
702            DialError::NoAddresses => {
703                // Let's wait until we get addresses
704                true
705            }
706            DialError::DialPeerConditionFalse(_) => {
707                // These are local conditions, we don't need to ban remote peers
708                false
709            }
710            DialError::Aborted => {
711                // Seems like a transient event
712                false
713            }
714            DialError::WrongPeerId { .. } => {
715                // It's likely that peer was restarted with different identity
716                false
717            }
718            DialError::Denied { .. } => {
719                // We exceeded the connection limits or we hit a black listed peer
720                false
721            }
722        }
723    }
724
725    fn handle_identify_event(&mut self, event: IdentifyEvent) {
726        let local_peer_id = *self.swarm.local_peer_id();
727
728        if let IdentifyEvent::Received {
729            peer_id, mut info, ..
730        } = event
731        {
732            debug!(?peer_id, protocols = ?info.protocols, "IdentifyEvent::Received");
733
734            // Check for network partition
735            if info.protocol_version != self.protocol_version {
736                debug!(
737                    %local_peer_id,
738                    %peer_id,
739                    local_protocol_version = %self.protocol_version,
740                    peer_protocol_version = %info.protocol_version,
741                    "Peer has different protocol version, banning temporarily",
742                );
743
744                self.temporary_bans.lock().create_or_extend(&peer_id);
745                // Forget about this peer until they upgrade
746                let _: Result<(), ()> = self.swarm.disconnect_peer_id(peer_id);
747                self.swarm.behaviour_mut().kademlia.remove_peer(&peer_id);
748                self.known_peers_registry
749                    .remove_all_known_peer_addresses(peer_id);
750
751                return;
752            }
753
754            // Remove temporary ban if there was any
755            self.temporary_bans.lock().remove(&peer_id);
756
757            if info.listen_addrs.len() > 30 {
758                debug!(
759                    %local_peer_id,
760                    %peer_id,
761                    "Node has reported more than 30 addresses; it is identified by {} and {}",
762                    info.protocol_version, info.agent_version
763                );
764                info.listen_addrs.truncate(30);
765            }
766
767            let kademlia = &mut self.swarm.behaviour_mut().kademlia;
768            let full_kademlia_support = kademlia
769                .protocol_names()
770                .iter()
771                .all(|local_protocol| info.protocols.contains(local_protocol));
772
773            if full_kademlia_support {
774                let received_addresses = info
775                    .listen_addrs
776                    .into_iter()
777                    .filter(|address| {
778                        if self.allow_non_global_addresses_in_dht
779                            || is_global_address_or_dns(address)
780                        {
781                            true
782                        } else {
783                            trace!(
784                                %local_peer_id,
785                                %peer_id,
786                                %address,
787                                "Ignoring self-reported non-global address",
788                            );
789
790                            false
791                        }
792                    })
793                    .collect::<Vec<_>>();
794                let received_address_strings = received_addresses
795                    .iter()
796                    .map(ToString::to_string)
797                    .collect::<Vec<_>>();
798                let old_addresses = kademlia
799                    .kbucket(peer_id)
800                    .and_then(|peers| {
801                        let key = peer_id.into();
802                        peers.iter().find_map(|peer| {
803                            (peer.node.key == &key).then_some(
804                                peer.node
805                                    .value
806                                    .iter()
807                                    .filter(|existing_address| {
808                                        let existing_address = existing_address.to_string();
809
810                                        !received_address_strings.iter().any(|received_address| {
811                                            received_address.starts_with(&existing_address)
812                                                || existing_address.starts_with(received_address)
813                                        })
814                                    })
815                                    .cloned()
816                                    .collect::<Vec<_>>(),
817                            )
818                        })
819                    })
820                    .unwrap_or_default();
821
822                for address in received_addresses {
823                    debug!(
824                        %local_peer_id,
825                        %peer_id,
826                        %address,
827                        protocol_names = ?kademlia.protocol_names(),
828                        "Adding self-reported address to Kademlia DHT",
829                    );
830
831                    kademlia.add_address(&peer_id, address);
832                }
833
834                for old_address in old_addresses {
835                    trace!(
836                        %local_peer_id,
837                        %peer_id,
838                        %old_address,
839                        "Removing old self-reported address from Kademlia DHT",
840                    );
841
842                    kademlia.remove_address(&peer_id, &old_address);
843                }
844
845                self.connected_servers.insert(peer_id);
846            } else {
847                debug!(
848                    %local_peer_id,
849                    %peer_id,
850                    peer_protocols = ?info.protocols,
851                    protocol_names = ?kademlia.protocol_names(),
852                    "Peer doesn't support our Kademlia DHT protocol",
853                );
854
855                kademlia.remove_peer(&peer_id);
856                self.connected_servers.remove(&peer_id);
857            }
858        }
859    }
860
861    fn handle_kademlia_event(&mut self, event: KademliaEvent) {
862        trace!("Kademlia event: {:?}", event);
863
864        match event {
865            KademliaEvent::InboundRequest {
866                request: InboundRequest::AddProvider { record },
867            } => {
868                debug!("Unexpected AddProvider request received: {:?}", record);
869            }
870            KademliaEvent::UnroutablePeer { peer } => {
871                debug!(%peer, "Unroutable peer detected");
872
873                self.swarm.behaviour_mut().kademlia.remove_peer(&peer);
874
875                if let Some(shared) = self.shared_weak.upgrade() {
876                    shared
877                        .handlers
878                        .peer_discovered
879                        .call_simple(&PeerDiscovered::UnroutablePeer { peer_id: peer });
880                }
881            }
882            KademliaEvent::RoutablePeer { peer, address } => {
883                debug!(?address, "Routable peer detected: {:?}", peer);
884
885                if let Some(shared) = self.shared_weak.upgrade() {
886                    shared
887                        .handlers
888                        .peer_discovered
889                        .call_simple(&PeerDiscovered::RoutablePeer {
890                            peer_id: peer,
891                            address,
892                        });
893                }
894            }
895            KademliaEvent::PendingRoutablePeer { peer, address } => {
896                debug!(?address, "Pending routable peer detected: {:?}", peer);
897
898                if let Some(shared) = self.shared_weak.upgrade() {
899                    shared
900                        .handlers
901                        .peer_discovered
902                        .call_simple(&PeerDiscovered::RoutablePeer {
903                            peer_id: peer,
904                            address,
905                        });
906                }
907            }
908            KademliaEvent::OutboundQueryProgressed {
909                step: ProgressStep { last, .. },
910                id,
911                result: QueryResult::GetClosestPeers(result),
912                ..
913            } => {
914                let mut cancelled = false;
915                if let Some(QueryResultSender::ClosestPeers { sender, .. }) =
916                    self.query_id_receivers.get(&id)
917                {
918                    match result {
919                        Ok(GetClosestPeersOk { key, peers }) => {
920                            trace!(
921                                "Get closest peers query for {} yielded {} results",
922                                hex::encode(key),
923                                peers.len(),
924                            );
925
926                            if peers.is_empty()
927                                // Connected peers collection is not empty.
928                                && self.swarm.connected_peers().next().is_some()
929                            {
930                                debug!("Random Kademlia query has yielded empty list of peers");
931                            }
932
933                            for peer in peers {
934                                cancelled = Self::unbounded_send_and_cancel_on_error(
935                                    &mut self.swarm.behaviour_mut().kademlia,
936                                    sender,
937                                    peer.peer_id,
938                                    "GetClosestPeersOk",
939                                    id,
940                                ) || cancelled;
941                            }
942                        }
943                        Err(GetClosestPeersError::Timeout { key, peers }) => {
944                            debug!(
945                                "Get closest peers query for {} timed out with {} results",
946                                hex::encode(key),
947                                peers.len(),
948                            );
949
950                            for peer in peers {
951                                cancelled = Self::unbounded_send_and_cancel_on_error(
952                                    &mut self.swarm.behaviour_mut().kademlia,
953                                    sender,
954                                    peer.peer_id,
955                                    "GetClosestPeersError::Timeout",
956                                    id,
957                                ) || cancelled;
958                            }
959                        }
960                    }
961                }
962
963                if last || cancelled {
964                    // There will be no more progress
965                    self.query_id_receivers.remove(&id);
966                }
967            }
968            KademliaEvent::OutboundQueryProgressed {
969                step: ProgressStep { last, .. },
970                id,
971                result: QueryResult::GetRecord(result),
972                ..
973            } => {
974                let mut cancelled = false;
975                if let Some(QueryResultSender::Value { sender, .. }) =
976                    self.query_id_receivers.get(&id)
977                {
978                    match result {
979                        Ok(GetRecordOk::FoundRecord(rec)) => {
980                            trace!(
981                                key = hex::encode(&rec.record.key),
982                                "Get record query succeeded",
983                            );
984
985                            cancelled = Self::unbounded_send_and_cancel_on_error(
986                                &mut self.swarm.behaviour_mut().kademlia,
987                                sender,
988                                rec,
989                                "GetRecordOk",
990                                id,
991                            ) || cancelled;
992                        }
993                        Ok(GetRecordOk::FinishedWithNoAdditionalRecord { .. }) => {
994                            trace!("Get record query yielded no results");
995                        }
996                        Err(error) => match error {
997                            GetRecordError::NotFound { key, .. } => {
998                                debug!(
999                                    key = hex::encode(&key),
1000                                    "Get record query failed with no results",
1001                                );
1002                            }
1003                            GetRecordError::Timeout { key } => {
1004                                debug!(key = hex::encode(&key), "Get record query timed out");
1005                            }
1006                        },
1007                    }
1008                }
1009
1010                if last || cancelled {
1011                    // There will be no more progress
1012                    self.query_id_receivers.remove(&id);
1013                }
1014            }
1015            KademliaEvent::OutboundQueryProgressed {
1016                step: ProgressStep { last, .. },
1017                id,
1018                result: QueryResult::GetProviders(result),
1019                ..
1020            } => {
1021                let mut cancelled = false;
1022                if let Some(QueryResultSender::Providers { key, sender, .. }) =
1023                    self.query_id_receivers.get(&id)
1024                {
1025                    match result {
1026                        Ok(GetProvidersOk::FoundProviders { key, providers }) => {
1027                            trace!(
1028                                key = hex::encode(&key),
1029                                "Get providers query yielded {} results",
1030                                providers.len(),
1031                            );
1032
1033                            for provider in providers {
1034                                cancelled = Self::unbounded_send_and_cancel_on_error(
1035                                    &mut self.swarm.behaviour_mut().kademlia,
1036                                    sender,
1037                                    provider,
1038                                    "GetProvidersOk",
1039                                    id,
1040                                ) || cancelled;
1041                            }
1042                        }
1043                        Ok(GetProvidersOk::FinishedWithNoAdditionalRecord { closest_peers }) => {
1044                            trace!(
1045                                key = hex::encode(key),
1046                                closest_peers = %closest_peers.len(),
1047                                "Get providers query yielded no results"
1048                            );
1049                        }
1050                        Err(error) => {
1051                            let GetProvidersError::Timeout { key, .. } = error;
1052
1053                            debug!(
1054                                key = hex::encode(&key),
1055                                "Get providers query failed with no results",
1056                            );
1057                        }
1058                    }
1059                }
1060
1061                if last || cancelled {
1062                    // There will be no more progress
1063                    self.query_id_receivers.remove(&id);
1064                }
1065            }
1066            KademliaEvent::OutboundQueryProgressed {
1067                step: ProgressStep { last, .. },
1068                id,
1069                result: QueryResult::PutRecord(result),
1070                ..
1071            } => {
1072                let mut cancelled = false;
1073                if let Some(QueryResultSender::PutValue { sender, .. }) =
1074                    self.query_id_receivers.get(&id)
1075                {
1076                    match result {
1077                        Ok(PutRecordOk { key }) => {
1078                            trace!("Put record query for {} succeeded", hex::encode(&key));
1079
1080                            cancelled = Self::unbounded_send_and_cancel_on_error(
1081                                &mut self.swarm.behaviour_mut().kademlia,
1082                                sender,
1083                                (),
1084                                "PutRecordOk",
1085                                id,
1086                            ) || cancelled;
1087                        }
1088                        Err(error) => {
1089                            debug!(?error, "Put record query failed.");
1090                        }
1091                    }
1092                }
1093
1094                if last || cancelled {
1095                    // There will be no more progress
1096                    self.query_id_receivers.remove(&id);
1097                }
1098            }
1099            KademliaEvent::OutboundQueryProgressed {
1100                step: ProgressStep { last, count },
1101                id,
1102                result: QueryResult::Bootstrap(result),
1103                stats,
1104            } => {
1105                debug!(?stats, %last, %count, ?id, ?result, "Bootstrap OutboundQueryProgressed step.");
1106
1107                let mut cancelled = false;
1108                if let Some(QueryResultSender::Bootstrap { sender }) =
1109                    self.query_id_receivers.get_mut(&id)
1110                {
1111                    match result {
1112                        Ok(BootstrapOk {
1113                            peer,
1114                            num_remaining,
1115                        }) => {
1116                            trace!(%peer, %num_remaining, %last, "Bootstrap query step succeeded");
1117
1118                            cancelled = Self::unbounded_send_and_cancel_on_error(
1119                                &mut self.swarm.behaviour_mut().kademlia,
1120                                sender,
1121                                (),
1122                                "Bootstrap",
1123                                id,
1124                            ) || cancelled;
1125                        }
1126                        Err(error) => {
1127                            debug!(?error, "Bootstrap query failed.");
1128                        }
1129                    }
1130                }
1131
1132                if last || cancelled {
1133                    // There will be no more progress
1134                    self.query_id_receivers.remove(&id);
1135                }
1136            }
1137            _ => {}
1138        }
1139    }
1140
1141    // Returns `true` if query was cancelled
1142    fn unbounded_send_and_cancel_on_error<T>(
1143        kademlia: &mut Kademlia<DummyRecordStore>,
1144        sender: &mpsc::UnboundedSender<T>,
1145        value: T,
1146        channel: &'static str,
1147        id: QueryId,
1148    ) -> bool {
1149        if sender.unbounded_send(value).is_err() {
1150            debug!("{} channel was dropped", channel);
1151
1152            // Cancel query
1153            if let Some(mut query) = kademlia.query_mut(&id) {
1154                query.finish();
1155            }
1156            true
1157        } else {
1158            false
1159        }
1160    }
1161
1162    fn handle_gossipsub_event(&mut self, event: GossipsubEvent) {
1163        if let GossipsubEvent::Message { message, .. } = event
1164            && let Some(senders) = self.topic_subscription_senders.get(&message.topic)
1165        {
1166            let bytes = Bytes::from(message.data);
1167
1168            for sender in senders.values() {
1169                // Doesn't matter if receiver is still listening for messages or not.
1170                let _: Result<(), _> = sender.unbounded_send(bytes.clone());
1171            }
1172        }
1173    }
1174
1175    fn handle_request_response_event(&mut self, event: RequestResponseEvent) {
1176        // No actions on statistics events.
1177        trace!("Request response event: {:?}", event);
1178    }
1179
1180    fn handle_autonat_event(&mut self, event: AutonatEvent) {
1181        trace!(?event, "Autonat event received.");
1182        let autonat = &self.swarm.behaviour().autonat;
1183        debug!(
1184            public_address=?autonat.public_address(),
1185            confidence=%autonat.confidence(),
1186            "Current public address confidence."
1187        );
1188
1189        match event {
1190            AutonatEvent::InboundProbe(_inbound_probe_event) => {
1191                // We do not care about this event
1192            }
1193            AutonatEvent::OutboundProbe(outbound_probe_event) => {
1194                match outbound_probe_event {
1195                    OutboundProbeEvent::Request { peer, .. } => {
1196                        // For outbound probe request add peer to allow list to ensure they can dial
1197                        // us back and not hit global incoming connection limit
1198                        self.swarm
1199                            .behaviour_mut()
1200                            .connection_limits
1201                            // We expect a single successful dial from this peer
1202                            .add_to_incoming_allow_list(
1203                                peer,
1204                                self.peer_ip_addresses
1205                                    .get(&peer)
1206                                    .iter()
1207                                    .flat_map(|ip_addresses| ip_addresses.iter())
1208                                    .copied(),
1209                                1,
1210                            );
1211                    }
1212                    OutboundProbeEvent::Response { peer, .. } => {
1213                        self.swarm
1214                            .behaviour_mut()
1215                            .connection_limits
1216                            .remove_from_incoming_allow_list(&peer, Some(1));
1217                    }
1218                    OutboundProbeEvent::Error { peer, .. } => {
1219                        if let Some(peer) = peer {
1220                            self.swarm
1221                                .behaviour_mut()
1222                                .connection_limits
1223                                .remove_from_incoming_allow_list(&peer, Some(1));
1224                        }
1225                    }
1226                }
1227            }
1228            AutonatEvent::StatusChanged { old, new } => {
1229                debug!(?old, ?new, "Public address status changed.");
1230
1231                // TODO: Remove block once https://github.com/libp2p/rust-libp2p/issues/4863 is resolved
1232                if let (NatStatus::Public(old_address), NatStatus::Private) = (old, new.clone()) {
1233                    self.swarm.remove_external_address(&old_address);
1234                    debug!(
1235                        ?old_address,
1236                        new_status = ?new,
1237                        "Removing old external address...",
1238                    );
1239
1240                    // Trigger potential mode change manually
1241                    self.swarm.behaviour_mut().kademlia.set_mode(None);
1242                }
1243
1244                let connected_peers = self.swarm.connected_peers().copied().collect::<Vec<_>>();
1245                self.swarm.behaviour_mut().identify.push(connected_peers);
1246            }
1247        }
1248    }
1249
1250    fn handle_command(&mut self, command: Command) {
1251        match command {
1252            Command::GetValue {
1253                key,
1254                result_sender,
1255                permit,
1256            } => {
1257                let query_id = self
1258                    .swarm
1259                    .behaviour_mut()
1260                    .kademlia
1261                    .get_record(key.to_bytes().into());
1262
1263                self.query_id_receivers.insert(
1264                    query_id,
1265                    QueryResultSender::Value {
1266                        sender: result_sender,
1267                        _permit: permit,
1268                    },
1269                );
1270            }
1271            Command::PutValue {
1272                key,
1273                value,
1274                result_sender,
1275                permit,
1276            } => {
1277                let local_peer_id = *self.swarm.local_peer_id();
1278
1279                let record = Record {
1280                    key: key.into(),
1281                    value,
1282                    publisher: Some(local_peer_id),
1283                    expires: None, // No time expiration.
1284                };
1285                let query_result = self
1286                    .swarm
1287                    .behaviour_mut()
1288                    .kademlia
1289                    .put_record(record, Quorum::One);
1290
1291                match query_result {
1292                    Ok(query_id) => {
1293                        self.query_id_receivers.insert(
1294                            query_id,
1295                            QueryResultSender::PutValue {
1296                                sender: result_sender,
1297                                _permit: permit,
1298                            },
1299                        );
1300                    }
1301                    Err(err) => {
1302                        warn!(?err, "Failed to put value.");
1303                    }
1304                }
1305            }
1306            Command::Subscribe {
1307                topic,
1308                result_sender,
1309            } => {
1310                assert!(
1311                    self.swarm.behaviour().gossipsub.is_enabled(),
1312                    "Gossipsub protocol is disabled."
1313                );
1314
1315                let topic_hash = topic.hash();
1316                let (sender, receiver) = mpsc::unbounded();
1317
1318                // Unconditionally create subscription ID, code is simpler this way.
1319                let subscription_id = self.next_subscription_id;
1320                self.next_subscription_id += 1;
1321
1322                let created_subscription = CreatedSubscription {
1323                    subscription_id,
1324                    receiver,
1325                };
1326
1327                match self.topic_subscription_senders.entry(topic_hash) {
1328                    Entry::Occupied(mut entry) => {
1329                        // In case subscription already exists, just add one more sender to it.
1330                        if result_sender.send(Ok(created_subscription)).is_ok() {
1331                            entry.get_mut().insert(subscription_id, sender);
1332                        }
1333                    }
1334                    Entry::Vacant(entry) => {
1335                        // Otherwise subscription needs to be created.
1336
1337                        if let Some(gossipsub) = self.swarm.behaviour_mut().gossipsub.as_mut() {
1338                            match gossipsub.subscribe(&topic) {
1339                                Ok(true) => {
1340                                    if result_sender.send(Ok(created_subscription)).is_ok() {
1341                                        entry
1342                                            .insert(IntMap::from_iter([(subscription_id, sender)]));
1343                                    }
1344                                }
1345                                Ok(false) => {
1346                                    panic!(
1347                                        "Logic error, topic subscription wasn't created, this \
1348                                        must never happen"
1349                                    );
1350                                }
1351                                Err(error) => {
1352                                    let _: Result<(), _> = result_sender.send(Err(error));
1353                                }
1354                            }
1355                        }
1356                    }
1357                }
1358            }
1359            Command::Unsubscribe {
1360                topic,
1361                subscription_id,
1362            } => {
1363                assert!(
1364                    self.swarm.behaviour().gossipsub.is_enabled(),
1365                    "Gossipsub protocol is disabled."
1366                );
1367
1368                if let Entry::Occupied(mut entry) =
1369                    self.topic_subscription_senders.entry(topic.hash())
1370                {
1371                    entry.get_mut().remove(&subscription_id);
1372
1373                    // If last sender was removed - unsubscribe.
1374                    if entry.get().is_empty() {
1375                        entry.remove_entry();
1376
1377                        if let Some(gossipsub) = self.swarm.behaviour_mut().gossipsub.as_mut()
1378                            && !gossipsub.unsubscribe(&topic)
1379                        {
1380                            warn!(
1381                                "Can't unsubscribe from topic {topic} because subscription doesn't \
1382                                exist, this is a logic error in the subspace or swarm libraries"
1383                            );
1384                        }
1385                    }
1386                } else {
1387                    error!(
1388                        "Can't unsubscribe from topic {topic} because subscription doesn't exist, \
1389                        this is a logic error in the subspace library"
1390                    );
1391                }
1392            }
1393            Command::Publish {
1394                topic,
1395                message,
1396                result_sender,
1397            } => {
1398                assert!(
1399                    self.swarm.behaviour().gossipsub.is_enabled(),
1400                    "Gossipsub protocol is disabled"
1401                );
1402
1403                if let Some(gossipsub) = self.swarm.behaviour_mut().gossipsub.as_mut() {
1404                    // Doesn't matter if receiver still waits for response.
1405                    let _: Result<(), _> =
1406                        result_sender.send(gossipsub.publish(topic, message).map(|_message_id| ()));
1407                }
1408            }
1409            Command::GetClosestPeers {
1410                key,
1411                result_sender,
1412                permit,
1413            } => {
1414                let query_id = self.swarm.behaviour_mut().kademlia.get_closest_peers(key);
1415
1416                self.query_id_receivers.insert(
1417                    query_id,
1418                    QueryResultSender::ClosestPeers {
1419                        sender: result_sender,
1420                        _permit: permit,
1421                    },
1422                );
1423            }
1424            Command::GetClosestLocalPeers {
1425                key,
1426                source,
1427                result_sender,
1428            } => {
1429                let source = source.unwrap_or_else(|| *self.swarm.local_peer_id());
1430                let result = self
1431                    .swarm
1432                    .behaviour_mut()
1433                    .kademlia
1434                    .find_closest_local_peers(&KBucketKey::from(key), &source)
1435                    .filter(|peer| !peer.multiaddrs.is_empty())
1436                    .map(|peer| (peer.node_id, peer.multiaddrs))
1437                    .collect();
1438
1439                // Doesn't matter if receiver still waits for response.
1440                let _: Result<(), _> = result_sender.send(result);
1441            }
1442            Command::GenericRequest {
1443                peer_id,
1444                addresses,
1445                protocol_name,
1446                request,
1447                result_sender,
1448            } => {
1449                self.swarm.behaviour_mut().request_response.send_request(
1450                    &peer_id,
1451                    protocol_name,
1452                    request,
1453                    result_sender,
1454                    IfDisconnected::TryConnect,
1455                    addresses,
1456                );
1457            }
1458            Command::GetProviders {
1459                key,
1460                result_sender,
1461                permit,
1462            } => {
1463                let query_id = self
1464                    .swarm
1465                    .behaviour_mut()
1466                    .kademlia
1467                    .get_providers(key.clone());
1468
1469                self.query_id_receivers.insert(
1470                    query_id,
1471                    QueryResultSender::Providers {
1472                        key,
1473                        sender: result_sender,
1474                        _permit: permit,
1475                    },
1476                );
1477            }
1478            Command::BanPeer { peer_id } => {
1479                self.ban_peer(peer_id);
1480            }
1481            Command::Dial { address } => {
1482                let _: Result<(), _> = self.swarm.dial(address);
1483            }
1484            Command::ConnectedPeers { result_sender } => {
1485                let connected_peers = self.swarm.connected_peers().copied().collect();
1486
1487                let _: Result<(), _> = result_sender.send(connected_peers);
1488            }
1489            Command::ConnectedServers { result_sender } => {
1490                let connected_servers = self.connected_servers.iter().copied().collect();
1491
1492                let _: Result<(), _> = result_sender.send(connected_servers);
1493            }
1494            Command::Bootstrap { result_sender } => {
1495                let kademlia = &mut self.swarm.behaviour_mut().kademlia;
1496
1497                match kademlia.bootstrap() {
1498                    Ok(query_id) => {
1499                        if let Some(result_sender) = result_sender {
1500                            self.query_id_receivers.insert(
1501                                query_id,
1502                                QueryResultSender::Bootstrap {
1503                                    sender: result_sender,
1504                                },
1505                            );
1506                        }
1507                    }
1508                    Err(err) => {
1509                        debug!(?err, "Bootstrap error.");
1510                    }
1511                }
1512            }
1513        }
1514    }
1515
1516    fn ban_peer(&mut self, peer_id: PeerId) {
1517        // Remove temporary ban if there is one, before creating a permanent one.
1518        self.temporary_bans.lock().remove(&peer_id);
1519
1520        debug!(?peer_id, "Banning peer on network level");
1521
1522        self.swarm.behaviour_mut().block_list.block_peer(peer_id);
1523        self.swarm.behaviour_mut().kademlia.remove_peer(&peer_id);
1524        self.known_peers_registry
1525            .remove_all_known_peer_addresses(peer_id);
1526
1527        // Immediately disconnect the peer to cancel any in-flight requests.
1528        let _: Result<(), ()> = self.swarm.disconnect_peer_id(peer_id);
1529    }
1530
1531    fn register_event_metrics(&mut self, swarm_event: &SwarmEvent<Event>) {
1532        if let Some(ref mut metrics) = self.libp2p_metrics {
1533            match swarm_event {
1534                SwarmEvent::Behaviour(Event::Ping(ping_event)) => {
1535                    metrics.record(ping_event);
1536                }
1537                SwarmEvent::Behaviour(Event::Identify(identify_event)) => {
1538                    metrics.record(identify_event.as_ref());
1539                }
1540                SwarmEvent::Behaviour(Event::Kademlia(kademlia_event)) => {
1541                    metrics.record(kademlia_event);
1542                }
1543                SwarmEvent::Behaviour(Event::Gossipsub(gossipsub_event)) => {
1544                    metrics.record(gossipsub_event);
1545                }
1546                // TODO: implement in the upstream repository
1547                // SwarmEvent::Behaviour(Event::RequestResponse(request_response_event)) => {
1548                //     self.metrics.record(request_response_event);
1549                // }
1550                swarm_event => {
1551                    metrics.record(swarm_event);
1552                }
1553            }
1554        }
1555    }
1556
1557    fn log_kademlia_stats(&mut self) {
1558        let mut peer_counter = 0usize;
1559        let mut peer_with_no_address_counter = 0usize;
1560        for kbucket in self.swarm.behaviour_mut().kademlia.kbuckets() {
1561            for entry in kbucket.iter() {
1562                peer_counter += 1;
1563                if entry.node.value.len() == 0 {
1564                    peer_with_no_address_counter += 1;
1565                }
1566            }
1567        }
1568
1569        debug!(
1570            peers = %peer_counter,
1571            peers_with_no_address = %peer_with_no_address_counter,
1572            "Kademlia stats"
1573        );
1574    }
1575}