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