use crate::node_runner::NodeRunner;
use crate::rpc_server::{NetworkStats, NodeRunnerTrait, PeerInfo};
use libp2p::Multiaddr;
use std::pin::Pin;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;
pub struct NodeRunnerAdapter {
node_runner: Arc<RwLock<NodeRunner>>,
start_time: SystemTime,
}
impl NodeRunnerAdapter {
pub fn new(node_runner: Arc<RwLock<NodeRunner>>) -> Self {
Self {
node_runner,
start_time: SystemTime::now(),
}
}
}
impl std::fmt::Debug for NodeRunnerAdapter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NodeRunnerAdapter")
.field("start_time", &self.start_time)
.finish()
}
}
impl NodeRunnerTrait for NodeRunnerAdapter {
fn get_status(
&self,
) -> Pin<
Box<
dyn std::future::Future<
Output = Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>>,
> + Send,
>,
> {
let node_runner = self.node_runner.clone();
Box::pin(async move {
let runner = node_runner.read().await;
runner.status().await.map_err(|e| e.into())
})
}
fn get_connected_peers(
&self,
) -> Pin<Box<dyn std::future::Future<Output = Vec<PeerInfo>> + Send>> {
let node_runner = self.node_runner.clone();
Box::pin(async move {
let runner = node_runner.read().await;
if let Some(p2p_handle) = runner.p2p_handle() {
let peer_ids = p2p_handle.connected_peers().await;
peer_ids
.into_iter()
.map(|peer_id| {
PeerInfo {
id: peer_id.to_string(),
address: "unknown".to_string(), connected_duration: 0, messages_sent: 0, messages_received: 0, last_seen: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
status: "Connected".to_string(),
latency: None, }
})
.collect()
} else {
Vec::new()
}
})
}
fn dial_peer(
&self,
address: String,
) -> Pin<Box<dyn std::future::Future<Output = Result<(), String>> + Send>> {
let node_runner = self.node_runner.clone();
Box::pin(async move {
let runner = node_runner.read().await;
if let Some(p2p_handle) = runner.p2p_handle() {
let multiaddr: Multiaddr = address
.parse()
.map_err(|e| format!("Invalid multiaddr: {}", e))?;
p2p_handle
.dial(multiaddr)
.await
.map_err(|e| format!("Failed to dial peer: {}", e))
} else {
Err("P2P handle not available".to_string())
}
})
}
fn disconnect_peer(
&self,
peer_id: &str,
) -> Pin<Box<dyn std::future::Future<Output = Result<(), String>> + Send>> {
let peer_id = peer_id.to_string();
Box::pin(async move {
Err(format!(
"Disconnecting peer {} not yet implemented",
peer_id
))
})
}
fn get_network_stats(&self) -> Pin<Box<dyn std::future::Future<Output = NetworkStats> + Send>> {
let node_runner = self.node_runner.clone();
let start_time = self.start_time;
Box::pin(async move {
let runner = node_runner.read().await;
if let Some(p2p_handle) = runner.p2p_handle() {
let connected_peers = p2p_handle.connected_peers().await;
NetworkStats {
total_connections: connected_peers.len(),
active_connections: connected_peers.len(),
messages_sent: 0, messages_received: 0, bytes_sent: 0, bytes_received: 0, average_latency: 0.0, uptime: start_time.elapsed().unwrap_or_default().as_secs(),
}
} else {
NetworkStats {
total_connections: 0,
active_connections: 0,
messages_sent: 0,
messages_received: 0,
bytes_sent: 0,
bytes_received: 0,
average_latency: 0.0,
uptime: start_time.elapsed().unwrap_or_default().as_secs(),
}
}
})
}
fn shutdown(
&self,
) -> Pin<
Box<
dyn std::future::Future<Output = Result<(), Box<dyn std::error::Error + Send + Sync>>>
+ Send,
>,
> {
let node_runner = self.node_runner.clone();
Box::pin(async move {
let mut runner = node_runner.write().await;
runner.stop().await.map_err(|e| e.into())
})
}
}