p2p_chat/network/handlers/
swarm.rs

1//! This module contains the handler for `SwarmEvent`s.
2use super::super::{NetworkLayer, P2PBehaviourEvent};
3use crate::sync::SyncEvent;
4use crate::types::Message;
5use anyhow::Result;
6use libp2p::swarm::SwarmEvent;
7use tokio::sync::mpsc;
8use tracing::{info, trace, warn};
9
10impl NetworkLayer {
11    /// Handles a `SwarmEvent`.
12    ///
13    /// This function is the main entry point for handling events from the `libp2p` `Swarm`.
14    /// It dispatches the event to the appropriate handler based on its type.
15    ///
16    /// # Arguments
17    ///
18    /// * `event` - The `SwarmEvent<P2PBehaviourEvent>` to handle.
19    /// * `incoming_messages` - The sender for incoming chat messages.
20    ///
21    /// # Errors
22    ///
23    /// This function will return an error if handling the event fails.
24    pub(crate) async fn handle_swarm_event(
25        &mut self,
26        event: SwarmEvent<P2PBehaviourEvent>,
27        incoming_messages: &mpsc::UnboundedSender<Message>,
28    ) -> Result<()> {
29        match event {
30            SwarmEvent::NewListenAddr { address, .. } => {
31                info!("Listening on: {}", address);
32            }
33
34            SwarmEvent::Behaviour(P2PBehaviourEvent::Chat(chat_event)) => {
35                self.handle_chat_event(chat_event, incoming_messages)
36                    .await?;
37            }
38
39            SwarmEvent::Behaviour(P2PBehaviourEvent::Mailbox(mailbox_event)) => {
40                self.handle_mailbox_event(mailbox_event).await?;
41            }
42
43            SwarmEvent::Behaviour(P2PBehaviourEvent::Discovery(discovery_event)) => {
44                self.handle_discovery_event(discovery_event).await?;
45            }
46
47            SwarmEvent::Behaviour(P2PBehaviourEvent::Ping(ping_event)) => {
48                let libp2p::ping::Event { peer, result, .. } = ping_event;
49                match result {
50                    Ok(rtt) => {
51                        trace!("Ping to {} successful: RTT is {:?}", peer, rtt);
52                    }
53                    Err(failure) => {
54                        warn!("Ping to {} failed: {:?}", peer, failure);
55                    }
56                }
57            }
58
59            SwarmEvent::ConnectionEstablished { peer_id, .. } => {
60                info!("Connection established with peer: {}", peer_id);
61                if let Some(ref sync_tx) = self.sync_event_tx {
62                    let _ = sync_tx.send(SyncEvent::PeerConnected(peer_id));
63                }
64                if let Some(ref ui_tx) = self.ui_notify_tx {
65                    let _ = ui_tx.send(crate::cli::commands::UiNotification::PeerConnected(peer_id));
66                }
67            }
68
69            SwarmEvent::ConnectionClosed { peer_id, cause, .. } => {
70                info!("Disconnected from peer: {} (cause: {:?})", peer_id, cause);
71                if let Some(ref ui_tx) = self.ui_notify_tx {
72                    let _ = ui_tx.send(crate::cli::commands::UiNotification::PeerDisconnected(peer_id));
73                }
74            }
75
76            SwarmEvent::IncomingConnection { .. } => {
77                trace!("Incoming connection");
78            }
79
80            SwarmEvent::OutgoingConnectionError { peer_id, error, .. } => {
81                warn!("Outgoing connection error to {:?}: {}", peer_id, error);
82
83                if let Some(peer_id) = peer_id {
84                    if let Some(ref sync_tx) = self.sync_event_tx {
85                        let _ = sync_tx.send(SyncEvent::PeerConnectionFailed(peer_id));
86                    }
87                }
88            }
89
90            SwarmEvent::IncomingConnectionError { error, .. } => {
91                warn!("Incoming connection error: {}", error);
92            }
93
94            _ => {}
95        }
96
97        Ok(())
98    }
99}