Skip to main content

zebra_rpc/methods/types/
peer_info.rs

1//! An array of [`PeerInfo`] is the output of the `getpeerinfo` RPC method.
2
3use derive_getters::Getters;
4use derive_new::new;
5use zebra_network::{types::MetaAddr, PeerSocketAddr};
6
7/// Item of the `getpeerinfo` response
8#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
9#[allow(clippy::too_many_arguments)]
10pub struct PeerInfo {
11    /// The IP address and port of the peer
12    #[getter(copy)]
13    pub(crate) addr: PeerSocketAddr,
14
15    /// The services offered, as a zero-padded 16-character hex string
16    pub(crate) services: String,
17
18    /// The time in seconds since epoch of the last message received from this peer
19    pub(crate) lastrecv: u32,
20
21    /// Inbound (true) or Outbound (false)
22    pub(crate) inbound: bool,
23
24    /// The ban score for misbehavior
25    pub(crate) banscore: u32,
26
27    /// The peer's user agent string (e.g. "/Zebra:2.1.0/" or "/MagicBean:5.8.0/")
28    pub(crate) subver: String,
29
30    /// The negotiated protocol version
31    pub(crate) version: u32,
32
33    /// The connection state (e.g. "connected", "never_connected", "failed", "connecting")
34    pub(crate) connection_state: String,
35
36    /// The round-trip ping time in seconds.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub(crate) pingtime: Option<f64>,
39
40    /// The wait time on a ping response in seconds.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub(crate) pingwait: Option<f64>,
43}
44
45/// Response type for the `getpeerinfo` RPC method.
46pub type GetPeerInfoResponse = Vec<PeerInfo>;
47
48impl From<MetaAddr> for PeerInfo {
49    fn from(meta_addr: MetaAddr) -> Self {
50        let services = meta_addr
51            .services()
52            .map(|s| format!("{:016x}", s.bits()))
53            .unwrap_or_else(|| "0000000000000000".to_string());
54
55        let lastrecv = meta_addr.last_seen().map(|t| t.timestamp()).unwrap_or(0);
56
57        let connection_state = meta_addr.last_connection_state().to_string();
58
59        let subver = meta_addr.user_agent().unwrap_or("").to_string();
60
61        let version = meta_addr.negotiated_version().map(|v| v.0).unwrap_or(0);
62
63        Self {
64            addr: meta_addr.addr(),
65            services,
66            lastrecv,
67            inbound: meta_addr.is_inbound(),
68            banscore: meta_addr.misbehavior(),
69            subver,
70            version,
71            connection_state,
72            pingtime: meta_addr.rtt().map(|d| d.as_secs_f64()),
73            pingwait: meta_addr.ping_sent_at().map(|t| t.elapsed().as_secs_f64()),
74        }
75    }
76}
77
78impl Default for PeerInfo {
79    fn default() -> Self {
80        Self {
81            addr: PeerSocketAddr::unspecified(),
82            services: "0000000000000000".to_string(),
83            lastrecv: 0,
84            inbound: false,
85            banscore: 0,
86            subver: String::new(),
87            version: 0,
88            connection_state: String::new(),
89            pingtime: None,
90            pingwait: None,
91        }
92    }
93}