enhance admin rpc to return peers instead of dump (#128)

This commit is contained in:
Bo QIU 2024-07-16 14:57:36 +08:00 committed by GitHub
parent 0f9f1c7bf2
commit 920efe0b59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 108 additions and 19 deletions

View File

@ -1,4 +1,4 @@
use crate::types::NetworkInfo; use crate::types::{NetworkInfo, PeerInfo};
use jsonrpsee::core::RpcResult; use jsonrpsee::core::RpcResult;
use jsonrpsee::proc_macros::rpc; use jsonrpsee::proc_macros::rpc;
use std::collections::HashMap; use std::collections::HashMap;
@ -33,6 +33,6 @@ pub trait Rpc {
#[method(name = "getNetworkInfo")] #[method(name = "getNetworkInfo")]
async fn get_network_info(&self) -> RpcResult<NetworkInfo>; async fn get_network_info(&self) -> RpcResult<NetworkInfo>;
#[method(name = "dumpPeers")] #[method(name = "getPeers")]
async fn dump_peers(&self, file: Option<String>) -> RpcResult<usize>; async fn get_peers(&self) -> RpcResult<HashMap<String, PeerInfo>>;
} }

View File

@ -1,12 +1,10 @@
use super::api::RpcServer; use super::api::RpcServer;
use crate::types::NetworkInfo; use crate::types::{NetworkInfo, PeerInfo};
use crate::{error, Context}; use crate::{error, Context};
use futures::prelude::*; use futures::prelude::*;
use jsonrpsee::core::async_trait; use jsonrpsee::core::async_trait;
use jsonrpsee::core::RpcResult; use jsonrpsee::core::RpcResult;
use network::PeerInfo;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File;
use sync::{FileSyncInfo, SyncRequest, SyncResponse}; use sync::{FileSyncInfo, SyncRequest, SyncResponse};
use task_executor::ShutdownReason; use task_executor::ShutdownReason;
@ -150,20 +148,16 @@ impl RpcServer for RpcServerImpl {
}) })
} }
#[tracing::instrument(skip(self), err)] async fn get_peers(&self) -> RpcResult<HashMap<String, PeerInfo>> {
async fn dump_peers(&self, file: Option<String>) -> RpcResult<usize> { info!("admin_getPeers()");
info!("admin_dumpPeers()");
let db = self.ctx.network_globals.peers.read(); Ok(self
.ctx
let peers: HashMap<String, PeerInfo> = db .network_globals
.peers
.read()
.peers() .peers()
.map(|(peer_id, info)| (peer_id.to_base58(), info.clone())) .map(|(peer_id, info)| (peer_id.to_base58(), info.into()))
.collect(); .collect())
let file = File::create(file.unwrap_or("peers.json".into()))?;
serde_json::to_writer_pretty(&file, &peers)?;
Ok(peers.len())
} }
} }

View File

@ -9,7 +9,10 @@ use serde::{Deserialize, Serialize};
use shared_types::{ use shared_types::{
compute_padded_chunk_size, compute_segment_size, DataRoot, FileProof, Transaction, CHUNK_SIZE, compute_padded_chunk_size, compute_segment_size, DataRoot, FileProof, Transaction, CHUNK_SIZE,
}; };
use std::collections::HashSet;
use std::hash::Hasher; use std::hash::Hasher;
use std::net::IpAddr;
use std::time::Instant;
use storage::log_store::log_manager::bytes_to_entries; use storage::log_store::log_manager::bytes_to_entries;
use storage::H256; use storage::H256;
@ -255,6 +258,98 @@ impl SegmentWithProof {
} }
} }
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PeerInfo {
pub client: Client,
pub connection_status: PeerConnectionStatus,
pub listening_addresses: Vec<Multiaddr>,
pub seen_ips: HashSet<IpAddr>,
pub is_trusted: bool,
pub connection_direction: Option<String>, // Incoming/Outgoing
pub enr: Option<String>,
}
impl From<&network::PeerInfo> for PeerInfo {
fn from(value: &network::PeerInfo) -> Self {
Self {
client: value.client().clone().into(),
connection_status: value.connection_status().clone().into(),
listening_addresses: value.listening_addresses().clone(),
seen_ips: value.seen_ip_addresses().collect(),
is_trusted: value.is_trusted(),
connection_direction: value.connection_direction().map(|x| match x {
network::ConnectionDirection::Incoming => "Incoming".into(),
network::ConnectionDirection::Outgoing => "Outgoing".into(),
}),
enr: value.enr().map(|x| x.to_base64()),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Client {
pub version: String,
pub os: String,
pub protocol: String,
pub agent: Option<String>,
}
impl From<network::Client> for Client {
fn from(value: network::Client) -> Self {
Self {
version: value.version,
os: value.os_version,
protocol: value.protocol_version,
agent: value.agent_string,
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PeerConnectionStatus {
pub status: String,
pub connections_in: u8,
pub connections_out: u8,
pub last_seen_secs: u64,
}
impl PeerConnectionStatus {
fn new(status: &str, n_in: u8, n_out: u8, last_seen: Option<Instant>) -> Self {
Self {
status: status.into(),
connections_in: n_in,
connections_out: n_out,
last_seen_secs: last_seen.map_or(0, |x| x.elapsed().as_secs()),
}
}
}
impl From<network::PeerConnectionStatus> for PeerConnectionStatus {
fn from(value: network::PeerConnectionStatus) -> Self {
match value {
network::PeerConnectionStatus::Connected { n_in, n_out } => {
Self::new("connected", n_in, n_out, None)
}
network::PeerConnectionStatus::Disconnecting { .. } => {
Self::new("disconnecting", 0, 0, None)
}
network::PeerConnectionStatus::Disconnected { since } => {
Self::new("disconnected", 0, 0, Some(since))
}
network::PeerConnectionStatus::Banned { since } => {
Self::new("banned", 0, 0, Some(since))
}
network::PeerConnectionStatus::Dialing { since } => {
Self::new("dialing", 0, 0, Some(since))
}
network::PeerConnectionStatus::Unknown => Self::new("unknown", 0, 0, None),
}
}
}
mod base64 { mod base64 {
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};