ckb_network/
peer.rs

1use crate::network_group::Group;
2use crate::{
3    ProtocolId, ProtocolVersion, RawSessionType, multiaddr::Multiaddr, protocols::identify::Flags,
4};
5use ckb_systemtime::{Duration, Instant};
6use p2p::SessionId;
7use std::collections::HashMap;
8
9/// Peer info from identify protocol message
10#[derive(Clone, Debug)]
11pub struct PeerIdentifyInfo {
12    /// Node version
13    pub client_version: String,
14    /// Node flags
15    pub flags: Flags,
16}
17
18/// Indicates the session type
19#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
20pub enum SessionType {
21    /// Representing yourself as the active party means that you are the client side
22    Outbound,
23    /// Representing yourself as a passive recipient means that you are the server side
24    Inbound,
25    /// We use block-relay-only connections to help prevent against partition
26    /// attacks. By not relaying transactions or addresses, these connections
27    /// are harder to detect by a third party, thus helping obfuscate the
28    /// network topology.
29    BlockRelayOnly,
30}
31
32/// RawSessionType only covers Inbound and Outbound,
33/// and that BlockRelayOnly is explicitly set during peer registration.
34impl From<RawSessionType> for SessionType {
35    #[inline]
36    fn from(ty: RawSessionType) -> Self {
37        match ty {
38            RawSessionType::Outbound => SessionType::Outbound,
39            RawSessionType::Inbound => SessionType::Inbound,
40        }
41    }
42}
43
44impl SessionType {
45    /// is outbound
46    pub fn is_outbound(&self) -> bool {
47        matches!(self, SessionType::Outbound)
48    }
49
50    /// is inbound
51    pub fn is_inbound(&self) -> bool {
52        matches!(self, SessionType::Inbound)
53    }
54
55    /// is block_relay_only
56    pub fn is_block_relay_only(&self) -> bool {
57        matches!(self, SessionType::BlockRelayOnly)
58    }
59}
60
61/// Peer info
62#[derive(Clone, Debug)]
63pub struct Peer {
64    /// Peer address
65    pub connected_addr: Multiaddr,
66    /// Peer listen addresses
67    pub listened_addrs: Vec<Multiaddr>,
68    /// Peer info from identify protocol message
69    pub identify_info: Option<PeerIdentifyInfo>,
70    /// Ping/Pong message last received time
71    pub last_ping_protocol_message_received_at: Option<Instant>,
72    /// ping pong rtt
73    pub ping_rtt: Option<Duration>,
74    /// Indicates whether it is a probe connection of the fleer protocol
75    pub is_feeler: bool,
76    /// Peer connected time
77    pub connected_time: Instant,
78    /// Session id
79    pub session_id: SessionId,
80    /// Session type, Inbound or Outbound
81    pub session_type: SessionType,
82    /// Opened protocols on this session
83    pub protocols: HashMap<ProtocolId, ProtocolVersion>,
84    /// Whether a whitelist
85    pub is_whitelist: bool,
86    /// Whether the remote peer is a light client, and it subscribes the chain state.
87    pub if_lightclient_subscribed: bool,
88}
89
90impl Peer {
91    /// Init session info
92    pub fn new(
93        session_id: SessionId,
94        session_type: SessionType,
95        connected_addr: Multiaddr,
96        is_whitelist: bool,
97    ) -> Self {
98        Peer {
99            connected_addr,
100            listened_addrs: Vec::new(),
101            identify_info: None,
102            ping_rtt: None,
103            last_ping_protocol_message_received_at: None,
104            connected_time: Instant::now(),
105            is_feeler: false,
106            session_id,
107            session_type,
108            protocols: HashMap::with_capacity_and_hasher(1, Default::default()),
109            is_whitelist,
110            if_lightclient_subscribed: false,
111        }
112    }
113
114    /// Whether outbound session
115    pub fn is_outbound(&self) -> bool {
116        self.session_type.is_outbound()
117    }
118
119    /// Whether inbound session
120    pub fn is_inbound(&self) -> bool {
121        self.session_type.is_inbound()
122    }
123
124    /// Whether block_re session
125    pub fn is_block_relay_only(&self) -> bool {
126        self.session_type.is_block_relay_only()
127    }
128
129    /// Get net group
130    pub fn network_group(&self) -> Group {
131        (&self.connected_addr).into()
132    }
133
134    /// Opened protocol version
135    pub fn protocol_version(&self, protocol_id: ProtocolId) -> Option<ProtocolVersion> {
136        self.protocols.get(&protocol_id).cloned()
137    }
138}