everscale_network/adnl/
peer.rs

1use std::net::{Ipv4Addr, SocketAddrV4};
2use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
3
4use everscale_crypto::ed25519;
5
6use super::node_id::{NodeIdFull, NodeIdShort};
7use crate::util::*;
8
9pub type Peers = FastDashMap<NodeIdShort, Peer>;
10
11/// Remote peer info
12pub struct Peer {
13    /// Remove peer public key
14    id: NodeIdFull,
15    /// IPv4 address
16    addr: AtomicU64,
17    /// Adnl channel key pair to encrypt messages from our side
18    channel_key: ed25519::KeyPair,
19    /// Packets receiver state
20    receiver_state: PeerState,
21    /// Packets sender state
22    sender_state: PeerState,
23}
24
25impl Peer {
26    /// Creates new peer with receiver state initialized with the local reinit date
27    pub fn new(local_reinit_date: u32, addr: SocketAddrV4, id: NodeIdFull) -> Self {
28        Self {
29            id,
30            addr: AtomicU64::new(pack_socket_addr(&addr)),
31            channel_key: ed25519::KeyPair::generate(&mut rand::thread_rng()),
32            receiver_state: PeerState::for_receive_with_reinit_date(local_reinit_date),
33            sender_state: PeerState::for_send(),
34        }
35    }
36
37    /// Tries to update peer reinit date
38    ///
39    /// It is only allowed to update peer reinit date if it is greater or equal to the known one
40    #[inline(always)]
41    pub fn try_reinit_sender(&self, reinit_date: u32) -> bool {
42        let sender_reinit_date = self.sender_state.reinit_date();
43        match reinit_date.cmp(&sender_reinit_date) {
44            std::cmp::Ordering::Equal => true,
45            std::cmp::Ordering::Greater => {
46                self.sender_state.set_reinit_date(reinit_date);
47                if sender_reinit_date != 0 {
48                    self.sender_state.history(false).reset();
49                    self.sender_state.history(true).reset();
50                    self.receiver_state.history(false).reset();
51                    self.receiver_state.history(true).reset();
52                }
53                true
54            }
55            std::cmp::Ordering::Less => false,
56        }
57    }
58
59    /// Returns peer full id (public key)
60    #[inline(always)]
61    pub fn id(&self) -> &NodeIdFull {
62        &self.id
63    }
64
65    #[inline(always)]
66    pub fn addr(&self) -> SocketAddrV4 {
67        unpack_socket_addr(self.addr.load(Ordering::Acquire))
68    }
69
70    #[inline(always)]
71    pub fn set_addr(&self, addr: SocketAddrV4) {
72        self.addr.store(pack_socket_addr(&addr), Ordering::Release);
73    }
74
75    /// Adnl channel key pair to encrypt messages from our side
76    #[inline(always)]
77    pub fn channel_key(&self) -> &ed25519::KeyPair {
78        &self.channel_key
79    }
80
81    /// Packets receiver state
82    #[inline(always)]
83    pub fn receiver_state(&self) -> &PeerState {
84        &self.receiver_state
85    }
86
87    /// Packets sender state
88    #[inline(always)]
89    pub fn sender_state(&self) -> &PeerState {
90        &self.sender_state
91    }
92
93    /// Generates new channel key pair and resets receiver/sender states
94    ///
95    /// NOTE: Receiver state increments its reinit date so the peer will reset states
96    /// on the next message (see [`try_reinit_sender`])
97    ///
98    /// [`try_reinit_sender`]: fn@crate::adnl::Peer::try_reinit_sender
99    pub fn reset(&mut self) {
100        let reinit_date = self.receiver_state.reinit_date();
101
102        self.channel_key = ed25519::KeyPair::generate(&mut rand::thread_rng());
103        self.receiver_state = PeerState::for_receive_with_reinit_date(reinit_date + 1);
104        self.sender_state = PeerState::for_send();
105    }
106}
107
108pub fn pack_socket_addr(addr: &SocketAddrV4) -> u64 {
109    let mut result = [0; 8];
110    result[0..4].copy_from_slice(&addr.ip().octets());
111    result[4..6].copy_from_slice(&addr.port().to_le_bytes());
112    u64::from_le_bytes(result)
113}
114
115#[inline(always)]
116pub fn unpack_socket_addr(addr: u64) -> SocketAddrV4 {
117    let result = addr.to_le_bytes();
118    let addr: [u8; 4] = result[0..4].try_into().unwrap();
119    SocketAddrV4::new(
120        Ipv4Addr::from(addr),
121        u16::from_le_bytes([result[4], result[5]]),
122    )
123}
124
125/// Connection side packets histories and reinit date
126pub struct PeerState {
127    ordinary_history: PacketsHistory,
128    priority_history: PacketsHistory,
129    reinit_date: AtomicU32,
130}
131
132impl PeerState {
133    fn for_receive_with_reinit_date(reinit_date: u32) -> Self {
134        Self {
135            ordinary_history: PacketsHistory::for_recv(),
136            priority_history: PacketsHistory::for_recv(),
137            reinit_date: AtomicU32::new(reinit_date),
138        }
139    }
140
141    fn for_send() -> Self {
142        Self {
143            ordinary_history: PacketsHistory::for_send(),
144            priority_history: PacketsHistory::for_send(),
145            reinit_date: Default::default(),
146        }
147    }
148
149    #[inline(always)]
150    pub fn history(&self, priority: bool) -> &PacketsHistory {
151        if priority {
152            &self.priority_history
153        } else {
154            &self.ordinary_history
155        }
156    }
157
158    pub fn reinit_date(&self) -> u32 {
159        self.reinit_date.load(Ordering::Acquire)
160    }
161
162    pub fn set_reinit_date(&self, reinit_date: u32) {
163        self.reinit_date.store(reinit_date, Ordering::Release)
164    }
165}
166
167/// The context in which the new peer is added
168#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
169pub enum NewPeerContext {
170    AdnlPacket,
171    Dht,
172    PublicOverlay,
173}
174
175/// New peers filter
176pub trait PeerFilter: Send + Sync {
177    fn check(&self, ctx: NewPeerContext, addr: SocketAddrV4, peer_id: &NodeIdShort) -> bool;
178}
179
180#[cfg(test)]
181mod tests {
182    use super::*;
183
184    #[test]
185    fn correct_addr_pack() {
186        let test = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 23123);
187
188        let packed = pack_socket_addr(&test);
189
190        let unpacked = unpack_socket_addr(packed);
191        assert_eq!(unpacked, test);
192    }
193}