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
use crate::network_group::Group;
use crate::{
    multiaddr::Multiaddr, protocols::identify::Flags, ProtocolId, ProtocolVersion, SessionType,
};
use p2p::SessionId;
use std::collections::HashMap;
use std::time::{Duration, Instant};

/// Peer info from identify protocol message
#[derive(Clone, Debug)]
pub struct PeerIdentifyInfo {
    /// Node version
    pub client_version: String,
    /// Node flags
    pub flags: Flags,
}

/// 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()
    }

    /// 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()
    }
}