qudag_protocol/
node_runner_adapter.rs

1use crate::node_runner::NodeRunner;
2use crate::rpc_server::{NetworkStats, NodeRunnerTrait, PeerInfo};
3use libp2p::Multiaddr;
4use std::pin::Pin;
5use std::sync::Arc;
6use std::time::{SystemTime, UNIX_EPOCH};
7use tokio::sync::RwLock;
8
9/// Adapter that implements NodeRunnerTrait for the actual NodeRunner
10pub struct NodeRunnerAdapter {
11    /// Reference to the actual NodeRunner
12    node_runner: Arc<RwLock<NodeRunner>>,
13    /// Start time for uptime calculation
14    start_time: SystemTime,
15}
16
17impl NodeRunnerAdapter {
18    pub fn new(node_runner: Arc<RwLock<NodeRunner>>) -> Self {
19        Self {
20            node_runner,
21            start_time: SystemTime::now(),
22        }
23    }
24}
25
26impl std::fmt::Debug for NodeRunnerAdapter {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        f.debug_struct("NodeRunnerAdapter")
29            .field("start_time", &self.start_time)
30            .finish()
31    }
32}
33
34impl NodeRunnerTrait for NodeRunnerAdapter {
35    fn get_status(
36        &self,
37    ) -> Pin<
38        Box<
39            dyn std::future::Future<
40                    Output = Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>>,
41                > + Send,
42        >,
43    > {
44        let node_runner = self.node_runner.clone();
45        Box::pin(async move {
46            let runner = node_runner.read().await;
47            runner.status().await.map_err(|e| e.into())
48        })
49    }
50
51    fn get_connected_peers(
52        &self,
53    ) -> Pin<Box<dyn std::future::Future<Output = Vec<PeerInfo>> + Send>> {
54        let node_runner = self.node_runner.clone();
55        Box::pin(async move {
56            let runner = node_runner.read().await;
57
58            // Get P2P handle if available
59            if let Some(p2p_handle) = runner.p2p_handle() {
60                let peer_ids = p2p_handle.connected_peers().await;
61
62                // Convert libp2p peer IDs to PeerInfo
63                peer_ids
64                    .into_iter()
65                    .map(|peer_id| {
66                        PeerInfo {
67                            id: peer_id.to_string(),
68                            address: "unknown".to_string(), // TODO: Get actual address
69                            connected_duration: 0,          // TODO: Track connection time
70                            messages_sent: 0,               // TODO: Get from metrics
71                            messages_received: 0,           // TODO: Get from metrics
72                            last_seen: SystemTime::now()
73                                .duration_since(UNIX_EPOCH)
74                                .unwrap()
75                                .as_secs(),
76                            status: "Connected".to_string(),
77                            latency: None, // TODO: Get from ping
78                        }
79                    })
80                    .collect()
81            } else {
82                Vec::new()
83            }
84        })
85    }
86
87    fn dial_peer(
88        &self,
89        address: String,
90    ) -> Pin<Box<dyn std::future::Future<Output = Result<(), String>> + Send>> {
91        let node_runner = self.node_runner.clone();
92        Box::pin(async move {
93            let runner = node_runner.read().await;
94
95            if let Some(p2p_handle) = runner.p2p_handle() {
96                // Parse the address as Multiaddr
97                let multiaddr: Multiaddr = address
98                    .parse()
99                    .map_err(|e| format!("Invalid multiaddr: {}", e))?;
100
101                p2p_handle
102                    .dial(multiaddr)
103                    .await
104                    .map_err(|e| format!("Failed to dial peer: {}", e))
105            } else {
106                Err("P2P handle not available".to_string())
107            }
108        })
109    }
110
111    fn disconnect_peer(
112        &self,
113        peer_id: &str,
114    ) -> Pin<Box<dyn std::future::Future<Output = Result<(), String>> + Send>> {
115        let peer_id = peer_id.to_string();
116        Box::pin(async move {
117            // libp2p doesn't have a direct "disconnect" method for individual peers
118            // We would need to implement this by closing all connections to the peer
119            // For now, return an error indicating this is not yet implemented
120            Err(format!(
121                "Disconnecting peer {} not yet implemented",
122                peer_id
123            ))
124        })
125    }
126
127    fn get_network_stats(&self) -> Pin<Box<dyn std::future::Future<Output = NetworkStats> + Send>> {
128        let node_runner = self.node_runner.clone();
129        let start_time = self.start_time;
130        Box::pin(async move {
131            let runner = node_runner.read().await;
132
133            if let Some(p2p_handle) = runner.p2p_handle() {
134                let connected_peers = p2p_handle.connected_peers().await;
135
136                NetworkStats {
137                    total_connections: connected_peers.len(),
138                    active_connections: connected_peers.len(),
139                    messages_sent: 0,     // TODO: Get from metrics
140                    messages_received: 0, // TODO: Get from metrics
141                    bytes_sent: 0,        // TODO: Get from metrics
142                    bytes_received: 0,    // TODO: Get from metrics
143                    average_latency: 0.0, // TODO: Calculate from ping data
144                    uptime: start_time.elapsed().unwrap_or_default().as_secs(),
145                }
146            } else {
147                NetworkStats {
148                    total_connections: 0,
149                    active_connections: 0,
150                    messages_sent: 0,
151                    messages_received: 0,
152                    bytes_sent: 0,
153                    bytes_received: 0,
154                    average_latency: 0.0,
155                    uptime: start_time.elapsed().unwrap_or_default().as_secs(),
156                }
157            }
158        })
159    }
160
161    fn shutdown(
162        &self,
163    ) -> Pin<
164        Box<
165            dyn std::future::Future<Output = Result<(), Box<dyn std::error::Error + Send + Sync>>>
166                + Send,
167        >,
168    > {
169        let node_runner = self.node_runner.clone();
170        Box::pin(async move {
171            let mut runner = node_runner.write().await;
172            runner.stop().await.map_err(|e| e.into())
173        })
174    }
175}