• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tox-rs / tox / 7247588774

18 Dec 2023 11:45AM UTC coverage: 94.85% (-0.03%) from 94.876%
7247588774

Pull #477

github

web-flow
Merge 6a5a935cc into 5ab95a61f
Pull Request #477: Add functions for tox crate version information

0 of 10 new or added lines in 1 file covered. (0.0%)

13 existing lines in 7 files now uncovered.

16816 of 17729 relevant lines covered (94.85%)

1.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.47
/tox_core/src/net_crypto/mod.rs
1
/*! Net crypto module allows to send data between two friends and provides
2
encryption, ordered delivery, and perfect forward secrecy.
3

4
It can use both UDP and TCP (over relays) transport protocols to send data and
5
can switch between them without the peers needing to disconnect and reconnect.
6
For example two Tox friends might first connect over TCP and a few seconds later
7
switch to UDP when a direct UDP connection becomes possible. Direct UDP is
8
preferred over TCP because it is direct and isn't limited by possibly congested
9
TCP relays.
10

11
*/
12

13
mod crypto_connection;
14
pub mod errors;
15
mod packets_array;
16

17
pub use self::crypto_connection::*;
18
use self::errors::*;
19
use self::packets_array::*;
20

21
use std::collections::{HashMap, HashSet};
22
use std::net::{IpAddr, SocketAddr};
23
use std::sync::Arc;
24
use std::time::{Duration, Instant};
25
use std::u16;
26

27
use crypto_box::{aead::AeadCore, SalsaBox};
28
use futures::channel::mpsc;
29
use futures::future;
30
use futures::{SinkExt, TryFutureExt};
31
use rand::thread_rng;
32
use tokio::sync::RwLock;
33

34
use crate::dht::precomputed_cache::*;
35
use crate::io_tokio::*;
36
use crate::time::*;
37
use tox_binary_io::*;
38
use tox_crypto::*;
39
use tox_packet::dht::{Packet as DhtPacket, *};
40
use tox_packet::relay::DataPayload as TcpDataPayload;
41
use xsalsa20poly1305::{KeyInit, XSalsa20Poly1305};
42

43
/// Maximum size of `Packet` when we try to send it to UDP address even if
44
/// it's considered dead.
45
const DHT_ATTEMPT_MAX_PACKET_LENGTH: usize = 95;
46

47
/// If diff between `Nonce` from received data packet and connection `Nonce` is
48
/// bigger than 2 * `NONCE_DIFF_THRESHOLD` then increase connection `Nonce` by
49
/// `NONCE_DIFF_THRESHOLD`.
50
const NONCE_DIFF_THRESHOLD: u16 = u16::MAX / 3;
51

52
/// Packet with this ID contains indices of lossless packets that should be
53
/// resent.
54
const PACKET_ID_REQUEST: u8 = 1;
55

56
/// Packet with this ID means that this crypto connection should be killed.
57
const PACKET_ID_KILL: u8 = 2;
58

59
/// Packets with ID from 0 to `PACKET_ID_CRYPTO_RANGE_END` are reserved for
60
/// `net_crypto`.
61
const PACKET_ID_CRYPTO_RANGE_END: u8 = 15;
62

63
/// Packets with ID from `PACKET_ID_LOSSY_RANGE_START` to
64
/// `PACKET_ID_LOSSY_RANGE_END` are considered lossy packets.
65
const PACKET_ID_LOSSY_RANGE_START: u8 = 192;
66

67
/// Packets with ID from `PACKET_ID_LOSSY_RANGE_START` to
68
/// `PACKET_ID_LOSSY_RANGE_END` are considered lossy packets.
69
const PACKET_ID_LOSSY_RANGE_END: u8 = 254;
70

71
/// Shorthand for the transmit half of the message channel for sending DHT
72
/// packets.
73
type UdpTx = mpsc::Sender<(DhtPacket, SocketAddr)>;
74

75
/// Shorthand for the transmit half of the message channel for sending TCP
76
/// packets via relays.
77
type TcpTx = mpsc::Sender<(TcpDataPayload, PublicKey)>;
78

79
/// Shorthand for the transmit half of the message channel for sending DHT
80
/// `PublicKey` when it gets known. The first key is a long term key, the second
81
/// key is a DHT key.
82
type DhtPkTx = mpsc::UnboundedSender<(PublicKey, PublicKey)>;
83

84
/// Shorthand for the transmit half of the message channel for sending a
85
/// connection status when it becomes connected or disconnected. The key is a
86
/// long term key of the connection.
87
type ConnectionStatusTx = mpsc::UnboundedSender<(PublicKey, bool)>;
88

89
/// Shorthand for the transmit half of the message channel for sending lossless
90
/// packets. The key is a long term public key of the peer that sent this
91
/// packet.
92
type LosslessTx = mpsc::UnboundedSender<(PublicKey, Vec<u8>)>;
93

94
/// Shorthand for the transmit half of the message channel for sending lossy
95
/// packets. The key is a long term public key of the peer that sent this
96
/// packet.
97
type LossyTx = mpsc::UnboundedSender<(PublicKey, Vec<u8>)>;
98

99
/// Packet that can be sent as UDP packet or as TCP payload via TCP relay. The
100
/// way it should be sent is determined automatically. It doesn't contain
101
/// `CookieResponse` variant because `CookieResponse` is always sent via the
102
/// channel the request packet was received from.
103
#[derive(Clone, Debug, Eq, PartialEq)]
104
enum Packet {
105
    /// `CookieRequest` structure.
106
    CookieRequest(CookieRequest),
107
    /// `CryptoHandshake` structure.
108
    CryptoHandshake(CryptoHandshake),
109
    /// `CryptoData` structure.
110
    CryptoData(CryptoData),
111
}
112

113
impl From<StatusPacket> for Packet {
114
    fn from(packet: StatusPacket) -> Self {
1✔
115
        match packet {
1✔
116
            StatusPacket::CookieRequest(packet) => Packet::CookieRequest(packet),
1✔
117
            StatusPacket::CryptoHandshake(packet) => Packet::CryptoHandshake(packet),
1✔
118
        }
119
    }
120
}
121

122
impl From<Packet> for DhtPacket {
123
    fn from(packet: Packet) -> Self {
1✔
124
        match packet {
1✔
125
            Packet::CookieRequest(packet) => DhtPacket::CookieRequest(packet),
1✔
126
            Packet::CryptoHandshake(packet) => DhtPacket::CryptoHandshake(packet),
1✔
127
            Packet::CryptoData(packet) => DhtPacket::CryptoData(packet),
1✔
128
        }
129
    }
130
}
131

132
impl From<Packet> for TcpDataPayload {
133
    fn from(packet: Packet) -> Self {
1✔
134
        match packet {
1✔
135
            Packet::CookieRequest(packet) => TcpDataPayload::CookieRequest(packet),
×
136
            Packet::CryptoHandshake(packet) => TcpDataPayload::CryptoHandshake(packet),
1✔
137
            Packet::CryptoData(packet) => TcpDataPayload::CryptoData(packet),
1✔
138
        }
139
    }
140
}
141

142
/// Arguments for creating new `NetCrypto`.
143
#[derive(Clone)]
144
pub struct NetCryptoNewArgs {
145
    /// Sink to send packets to UDP socket.
146
    pub udp_tx: UdpTx,
147
    /// Sink to send lossless packets. The key is a long term public key of the
148
    /// peer that sent this packet.
149
    pub lossless_tx: LosslessTx,
150
    /// Sink to send lossy packets. The key is a long term public key of the
151
    /// peer that sent this packet.
152
    pub lossy_tx: LossyTx,
153
    /// Our DHT `PublicKey`
154
    pub dht_pk: PublicKey,
155
    /// Our DHT `SecretKey`
156
    pub dht_sk: SecretKey,
157
    /// Our real `PublicKey`
158
    pub real_pk: PublicKey,
159
    /// Our real `SecretKey`
160
    pub real_sk: SecretKey,
161
    /// Lru cache for precomputed keys. It stores precomputed keys to avoid
162
    /// redundant calculations.
163
    pub precomputed_keys: PrecomputedCache,
164
}
165

166
/// Struct that manages crypto connections to friends and handles net crypto
167
/// packets from both UDP and TCP connections.
168
#[derive(Clone)]
169
pub struct NetCrypto {
170
    /// Sink to send packets to UDP socket.
171
    udp_tx: UdpTx,
172
    /// Sink to send TCP packets via relays.
173
    tcp_tx: Arc<RwLock<Option<TcpTx>>>,
174
    /// Sink to send DHT `PublicKey` when it gets known. The first key is a long
175
    /// term key, the second key is a DHT key. `NetCrypto` module can learn DHT
176
    /// `PublicKey` of peer from `Cookie` obtained from `CryptoHandshake`
177
    /// packet. If key from `Cookie` is not equal to saved key inside
178
    /// `CryptoConnection` then `NetCrypto` module will send message to this
179
    /// sink.
180
    dht_pk_tx: Arc<RwLock<Option<DhtPkTx>>>,
181
    /// Sink to send a connection status when it becomes connected or
182
    /// disconnected. The key is a long term key of the connection.
183
    connection_status_tx: Arc<RwLock<Option<ConnectionStatusTx>>>,
184
    /// Sink to send lossless packets. The key is a long term public key of the
185
    /// peer that sent this packet.
186
    lossless_tx: LosslessTx,
187
    /// Sink to send lossy packets. The key is a long term public key of the
188
    /// peer that sent this packet.
189
    lossy_tx: LossyTx,
190
    /// Our DHT `PublicKey`
191
    dht_pk: PublicKey,
192
    /// Our DHT `SecretKey`
193
    dht_sk: SecretKey,
194
    /// Our real `PublicKey`
195
    real_pk: PublicKey,
196
    /// Our real `SecretKey`
197
    real_sk: SecretKey,
198
    /// Symmetric key used for cookies encryption
199
    symmetric_key: XSalsa20Poly1305,
200
    /// List of friends used to check whether should we accept an incoming
201
    /// `NetCrypto` connection.
202
    friends: Arc<RwLock<HashSet<PublicKey>>>,
203
    /// Connection by long term public key of DHT node map
204
    connections: Arc<RwLock<HashMap<PublicKey, Arc<RwLock<CryptoConnection>>>>>,
205
    /// Long term keys by IP address of DHT node map. `SocketAddr` can't be used
206
    /// as a key since it contains additional info for `IPv6` address.
207
    keys_by_addr: Arc<RwLock<HashMap<(IpAddr, /*port*/ u16), PublicKey>>>,
208
    /// Lru cache for precomputed keys. It stores precomputed keys to avoid
209
    /// redundant calculations.
210
    precomputed_keys: PrecomputedCache,
211
}
212

213
impl NetCrypto {
214
    /// Create new `NetCrypto` object
215
    pub fn new(args: NetCryptoNewArgs) -> NetCrypto {
1✔
216
        let symmetric_key = XSalsa20Poly1305::new(&XSalsa20Poly1305::generate_key(&mut thread_rng()));
2✔
217
        NetCrypto {
218
            udp_tx: args.udp_tx,
1✔
219
            tcp_tx: Default::default(),
2✔
220
            dht_pk_tx: Default::default(),
2✔
221
            connection_status_tx: Default::default(),
2✔
222
            lossless_tx: args.lossless_tx,
1✔
223
            lossy_tx: args.lossy_tx,
1✔
224
            dht_pk: args.dht_pk,
1✔
225
            dht_sk: args.dht_sk,
1✔
226
            real_pk: args.real_pk,
1✔
227
            real_sk: args.real_sk,
1✔
228
            symmetric_key,
229
            friends: Arc::new(RwLock::new(HashSet::new())),
2✔
230
            connections: Arc::new(RwLock::new(HashMap::new())),
2✔
231
            keys_by_addr: Arc::new(RwLock::new(HashMap::new())),
2✔
232
            precomputed_keys: args.precomputed_keys,
1✔
233
        }
234
    }
235

236
    /// Add a friend to accept incoming connections from him.
237
    pub async fn add_friend(&self, real_pk: PublicKey) {
5✔
238
        self.friends.write().await.insert(real_pk);
2✔
239
    }
240

241
    /// Remove a friend to stop accepting incoming connections from him.
242
    pub async fn remove_friend(&self, real_pk: PublicKey) {
5✔
243
        self.friends.write().await.remove(&real_pk);
2✔
244
    }
245

246
    /// Add connection to a friend when its DHT `PublicKey` is known.
247
    pub async fn add_connection(&self, peer_real_pk: PublicKey, peer_dht_pk: PublicKey) {
5✔
248
        let mut connections = self.connections.write().await;
2✔
249

250
        if connections.contains_key(&peer_real_pk) {
2✔
251
            return;
252
        }
253

254
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &self.dht_sk);
1✔
255
        let connection = CryptoConnection::new(
256
            &dht_precomputed_key,
257
            self.dht_pk.clone(),
1✔
258
            self.real_pk.clone(),
1✔
259
            peer_real_pk.clone(),
1✔
260
            peer_dht_pk,
1✔
261
        );
262
        let connection = Arc::new(RwLock::new(connection));
2✔
263
        connections.insert(peer_real_pk, connection);
2✔
264
    }
265

266
    /// Clear stored addresses from `keys_by_addr`.
267
    async fn clear_keys_by_addr(&self, connection: &CryptoConnection) {
5✔
268
        if connection.udp_addr_v4.is_some() || connection.udp_addr_v6.is_some() {
2✔
269
            let mut keys_by_addr = self.keys_by_addr.write().await;
2✔
270
            if let Some(addr) = connection.get_udp_addr_v4() {
2✔
271
                keys_by_addr.remove(&(addr.ip(), addr.port()));
2✔
272
            }
273
            if let Some(addr) = connection.get_udp_addr_v6() {
3✔
274
                keys_by_addr.remove(&(addr.ip(), addr.port()));
×
275
            }
276
        }
277
    }
278

279
    /// Send connection status to the appropriate sink when it becomes connected
280
    /// or disconnected.
281
    async fn send_connection_status(&self, connection: &CryptoConnection, status: bool) -> Result<(), mpsc::SendError> {
5✔
282
        if connection.is_established() != status {
3✔
283
            let tx = (*self.connection_status_tx.read().await).clone();
2✔
284
            maybe_send_unbounded(tx, (connection.peer_real_pk.clone(), status)).await
1✔
285
        } else {
286
            Ok(())
1✔
287
        }
288
    }
289

290
    /// Send kill packet to a connection if it's established or not confirmed.
291
    async fn send_kill_packet(&self, connection: &mut CryptoConnection) -> Result<(), SendDataError> {
5✔
292
        if connection.is_established() || connection.is_not_confirmed() {
3✔
293
            let packet_number = connection.send_array.buffer_end;
1✔
294
            self.send_data_packet(connection, vec![PACKET_ID_KILL], packet_number)
3✔
295
                .await
2✔
296
        } else {
297
            Ok(())
1✔
298
        }
299
    }
300

301
    /// Kill a connection sending `PACKET_ID_KILL` packet and removing it from
302
    /// the connections list.
303
    pub async fn kill_connection(&self, real_pk: PublicKey) -> Result<(), KillConnectionError> {
6✔
304
        if let Some(connection) = self.connections.write().await.remove(&real_pk) {
4✔
305
            let mut connection = connection.write().await;
2✔
306
            self.clear_keys_by_addr(&connection).await;
2✔
307

308
            self.send_connection_status(&connection, false)
3✔
309
                .await
2✔
310
                .map_err(KillConnectionError::SendToConnectionStatus)?;
×
311
            self.send_kill_packet(&mut connection)
4✔
312
                .await
2✔
313
                .map_err(KillConnectionError::SendTo)
314
        } else {
315
            Err(KillConnectionError::NoConnection)
1✔
316
        }
317
    }
318

319
    /// Set friend's UDP IP address when it gets known.
320
    pub async fn set_friend_udp_addr(&self, real_pk: PublicKey, saddr: SocketAddr) {
5✔
321
        let connections = self.connections.read().await;
2✔
322
        let mut connection = if let Some(connection) = connections.get(&real_pk) {
2✔
323
            connection.write().await
2✔
324
        } else {
325
            return;
326
        };
327

328
        if connection.get_udp_addr_v4() == Some(saddr) || connection.get_udp_addr_v6() == Some(saddr) {
3✔
329
            return;
330
        }
331

332
        let mut keys_by_addr = self.keys_by_addr.write().await;
1✔
333
        let current_addr = if saddr.is_ipv4() {
2✔
334
            connection.get_udp_addr_v4()
2✔
335
        } else {
336
            connection.get_udp_addr_v6()
2✔
337
        };
338
        if let Some(saddr) = current_addr {
2✔
339
            keys_by_addr.remove(&(saddr.ip(), saddr.port()));
2✔
340
        }
341
        connection.set_udp_addr(saddr);
2✔
342
        keys_by_addr.insert((saddr.ip(), saddr.port()), real_pk);
1✔
343
    }
344

345
    /// Send lossless packet to a friend via established connection.
346
    pub async fn send_lossless(&self, real_pk: PublicKey, packet: Vec<u8>) -> Result<(), SendLosslessPacketError> {
7✔
347
        if packet.first().map_or(true, |&packet_id| {
4✔
348
            packet_id <= PACKET_ID_CRYPTO_RANGE_END || packet_id >= PACKET_ID_LOSSY_RANGE_START
1✔
349
        }) {
350
            return Err(SendLosslessPacketError::InvalidPacketId);
1✔
351
        }
352

353
        if let Some(connection) = self.connections.read().await.get(&real_pk) {
4✔
354
            let mut connection = connection.write().await;
2✔
355
            let packet_number = connection.send_array.buffer_end;
2✔
356
            if let Err(e) = connection.send_array.push_back(SentPacket::new(packet.clone())) {
2✔
357
                Err(SendLosslessPacketError::FullSendArray(e))
×
358
            } else {
359
                connection.packets_sent += 1;
2✔
360
                self.send_data_packet(&mut connection, packet, packet_number)
4✔
361
                    .await
2✔
362
                    .map_err(SendLosslessPacketError::SendTo)
363
            }
364
        } else {
365
            Err(SendLosslessPacketError::NoConnection)
1✔
366
        }
367
    }
368

369
    /// Send `Packet` packet to UDP socket
370
    async fn send_to_udp(&self, addr: SocketAddr, packet: DhtPacket) -> Result<(), mpsc::SendError> {
6✔
371
        self.udp_tx.clone().send((packet, addr)).await
3✔
372
    }
373

374
    /// Get long term `PublicKey` of the peer by its UDP address
375
    async fn key_by_addr(&self, addr: SocketAddr) -> Option<PublicKey> {
5✔
376
        self.keys_by_addr.read().await.get(&(addr.ip(), addr.port())).cloned()
3✔
377
    }
378

379
    /// Get crypto connection by long term `PublicKey`
380
    async fn connection_by_key(&self, pk: PublicKey) -> Option<Arc<RwLock<CryptoConnection>>> {
5✔
381
        self.connections.read().await.get(&pk).cloned()
3✔
382
    }
383

384
    /// Get crypto connection by its UDP address
385
    async fn connection_by_addr(&self, addr: SocketAddr) -> Option<Arc<RwLock<CryptoConnection>>> {
5✔
386
        if let Some(pk) = self.key_by_addr(addr).await {
3✔
387
            self.connection_by_key(pk).await
2✔
388
        } else {
389
            None
1✔
390
        }
391
    }
392

393
    /// Get crypto connection by long term `PublicKey`
394
    async fn connection_by_dht_key(&self, pk: PublicKey) -> Option<Arc<RwLock<CryptoConnection>>> {
5✔
395
        // TODO: should it be optimized?
396
        for connection in self.connections.read().await.values() {
4✔
397
            if connection.read().await.peer_dht_pk == pk {
3✔
398
                return Some(connection.clone());
1✔
399
            }
400
        }
401
        None
×
402
    }
403

404
    /// Create `CookieResponse` packet with `Cookie` requested by `CookieRequest` packet
405
    async fn handle_cookie_request(&self, packet: &CookieRequest) -> Result<CookieResponse, HandlePacketError> {
5✔
406
        let payload = packet
4✔
407
            .get_payload(&self.precomputed_keys.get(packet.pk.clone()).await)
2✔
408
            .map_err(HandlePacketError::GetPayload)?;
2✔
409

410
        let cookie = Cookie::new(payload.pk, packet.pk.clone());
1✔
411
        let encrypted_cookie = EncryptedCookie::new(&mut thread_rng(), &self.symmetric_key, &cookie);
2✔
412

413
        let response_payload = CookieResponsePayload {
414
            cookie: encrypted_cookie,
415
            id: payload.id,
1✔
416
        };
417
        let precomputed_key = SalsaBox::new(&packet.pk, &self.dht_sk);
1✔
418
        let response = CookieResponse::new(&precomputed_key, &response_payload);
1✔
419

420
        Ok(response)
1✔
421
    }
422

423
    /// Handle `CookieRequest` packet received from UDP socket
424
    pub async fn handle_udp_cookie_request(
1✔
425
        &self,
426
        packet: &CookieRequest,
427
        addr: SocketAddr,
428
    ) -> Result<(), HandlePacketError> {
429
        match self.handle_cookie_request(packet).await {
2✔
430
            Ok(response) => self
4✔
431
                .send_to_udp(addr, DhtPacket::CookieResponse(response))
1✔
432
                .await
2✔
433
                .map_err(|e| HandlePacketError::SendTo(SendPacketError::Udp(e))),
×
434
            Err(e) => Err(e),
1✔
435
        }
436
    }
437

438
    /// Handle `CookieRequest` packet received from TCP socket
439
    pub async fn handle_tcp_cookie_request(
1✔
440
        &self,
441
        packet: &CookieRequest,
442
        sender_pk: PublicKey,
443
    ) -> Result<(), HandlePacketError> {
444
        match self.handle_cookie_request(packet).await {
2✔
445
            Ok(response) => {
1✔
446
                let msg = (TcpDataPayload::CookieResponse(response), sender_pk);
1✔
447
                maybe_send_bounded(self.tcp_tx.read().await.clone(), msg)
6✔
448
                    .await
2✔
449
                    .map_err(|e| HandlePacketError::SendTo(SendPacketError::Tcp(e)))
×
450
            }
451
            Err(e) => Err(e),
×
452
        }
453
    }
454

455
    /// Handle `CookieResponse` and if it's correct change connection status to `HandshakeSending`.
456
    pub async fn handle_cookie_response(
1✔
457
        &self,
458
        connection: &mut CryptoConnection,
459
        packet: &CookieResponse,
460
    ) -> Result<(), HandlePacketError> {
461
        let cookie_request_id = if let ConnectionStatus::CookieRequesting { cookie_request_id, .. } = connection.status
2✔
462
        {
463
            cookie_request_id
1✔
464
        } else {
465
            return Err(HandlePacketError::InvalidState);
1✔
466
        };
467

468
        let payload = match packet.get_payload(&self.precomputed_keys.get(connection.peer_dht_pk.clone()).await) {
3✔
469
            Ok(payload) => payload,
1✔
470
            Err(e) => return Err(HandlePacketError::GetPayload(e)),
×
471
        };
472

473
        if payload.id != cookie_request_id {
1✔
474
            return Err(HandlePacketError::invalid_request_id(cookie_request_id, payload.id));
2✔
475
        }
476

477
        let mut rng = rand::thread_rng();
2✔
478
        let sent_nonce = SalsaBox::generate_nonce(&mut rng);
1✔
479
        let our_cookie = Cookie::new(connection.peer_real_pk.clone(), connection.peer_dht_pk.clone());
1✔
480
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &self.symmetric_key, &our_cookie);
2✔
481
        let handshake_payload = CryptoHandshakePayload {
482
            base_nonce: sent_nonce.into(),
1✔
483
            session_pk: connection.session_pk.clone(),
1✔
484
            cookie_hash: payload.cookie.hash(),
1✔
485
            cookie: our_encrypted_cookie,
486
        };
487
        let handshake = CryptoHandshake::new(
488
            &SalsaBox::new(&connection.peer_real_pk, &self.real_sk),
1✔
489
            &handshake_payload,
1✔
490
            payload.cookie,
1✔
491
        );
492

493
        connection.status = ConnectionStatus::HandshakeSending {
1✔
494
            sent_nonce: sent_nonce.into(),
1✔
495
            packet: StatusPacketWithTime::new_crypto_handshake(handshake),
1✔
496
        };
497

498
        self.send_status_packet(connection)
3✔
499
            .map_err(HandlePacketError::SendTo)
500
            .await
2✔
501
    }
502

503
    /// Handle `CookieResponse` packet received from UDP socket
504
    pub async fn handle_udp_cookie_response(
1✔
505
        &self,
506
        packet: &CookieResponse,
507
        addr: SocketAddr,
508
    ) -> Result<(), HandlePacketError> {
509
        if let Some(connection) = self.connection_by_addr(addr).await {
2✔
510
            let mut connection = connection.write().await;
2✔
511
            connection.set_udp_addr(addr);
2✔
512
            self.handle_cookie_response(&mut connection, packet).await
2✔
513
        } else {
514
            Err(HandlePacketError::no_udp_connection(addr))
2✔
515
        }
516
    }
517

518
    /// Handle `CookieResponse` packet received from TCP socket
519
    pub async fn handle_tcp_cookie_response(
1✔
520
        &self,
521
        packet: &CookieResponse,
522
        sender_pk: PublicKey,
523
    ) -> Result<(), HandlePacketError> {
524
        let connection = self.connection_by_dht_key(sender_pk.clone()).await;
2✔
525
        if let Some(connection) = connection {
1✔
526
            let mut connection = connection.write().await;
2✔
527
            self.handle_cookie_response(&mut connection, packet).await
2✔
528
        } else {
529
            Err(HandlePacketError::no_tcp_connection(sender_pk))
×
530
        }
531
    }
532

533
    /// Check that incoming `CryptoHandshake` request is valid:
534
    /// - cookie is not timed out
535
    /// - hash for the cookie inside the payload is correct
536
    fn validate_crypto_handshake(
1✔
537
        &self,
538
        packet: &CryptoHandshake,
539
    ) -> Result<(Cookie, CryptoHandshakePayload, SalsaBox), HandlePacketError> {
540
        let cookie = match packet.cookie.get_payload(&self.symmetric_key) {
1✔
541
            Ok(cookie) => cookie,
1✔
542
            Err(e) => return Err(HandlePacketError::GetPayload(e)),
×
543
        };
544

545
        if cookie.is_timed_out() {
1✔
546
            return Err(HandlePacketError::CookieTimedOut);
1✔
547
        }
548

549
        let real_precomputed_key = SalsaBox::new(&cookie.real_pk, &self.real_sk);
1✔
550

551
        let payload = match packet.get_payload(&real_precomputed_key) {
2✔
552
            Ok(payload) => payload,
1✔
553
            Err(e) => return Err(HandlePacketError::GetPayload(e)),
×
554
        };
555

556
        if packet.cookie.hash() != payload.cookie_hash {
2✔
557
            return Err(HandlePacketError::BadSha512);
1✔
558
        }
559

560
        Ok((cookie, payload, real_precomputed_key))
1✔
561
    }
562

563
    /// Handle `CryptoHandshake` and if it's correct change connection status to `NotConfirmed`.
564
    pub async fn handle_crypto_handshake(
1✔
565
        &self,
566
        connection: &mut CryptoConnection,
567
        packet: &CryptoHandshake,
568
    ) -> Result<(), HandlePacketError> {
569
        if let ConnectionStatus::Established { .. } = connection.status {
1✔
570
            return Err(HandlePacketError::InvalidState);
1✔
571
        }
572

573
        let (cookie, payload, real_precomputed_key) = match self.validate_crypto_handshake(packet) {
3✔
574
            Ok(result) => result,
1✔
575
            Err(e) => return Err(e),
1✔
576
        };
577

578
        if cookie.real_pk != connection.peer_real_pk {
2✔
579
            return Err(HandlePacketError::InvalidRealPk);
1✔
580
        }
581
        if cookie.dht_pk != connection.peer_dht_pk {
2✔
582
            let msg = (connection.peer_real_pk.clone(), cookie.dht_pk);
2✔
583

584
            let dht_pk_future =
2✔
585
                maybe_send_unbounded(self.dht_pk_tx.read().await.clone(), msg).map_err(HandlePacketError::SendToDhtpk);
586

587
            return dht_pk_future
2✔
588
                .and_then(|()| future::err(HandlePacketError::InvalidDhtPk))
2✔
589
                .await;
2✔
590
        }
591

592
        connection.status = match connection.status {
4✔
593
            ConnectionStatus::CookieRequesting { .. } => {
594
                let mut rng = rand::thread_rng();
2✔
595
                let sent_nonce = SalsaBox::generate_nonce(&mut rng);
1✔
596
                let our_cookie = Cookie::new(connection.peer_real_pk.clone(), connection.peer_dht_pk.clone());
1✔
597
                let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &self.symmetric_key, &our_cookie);
2✔
598
                let handshake_payload = CryptoHandshakePayload {
1✔
599
                    base_nonce: sent_nonce.into(),
1✔
600
                    session_pk: connection.session_pk.clone(),
1✔
601
                    cookie_hash: payload.cookie.hash(),
1✔
602
                    cookie: our_encrypted_cookie,
1✔
603
                };
604
                let handshake = CryptoHandshake::new(&real_precomputed_key, &handshake_payload, payload.cookie);
2✔
605
                ConnectionStatus::NotConfirmed {
1✔
606
                    sent_nonce: sent_nonce.into(),
1✔
607
                    received_nonce: payload.base_nonce,
1✔
608
                    session_precomputed_key: SalsaBox::new(&payload.session_pk, &connection.session_sk),
1✔
609
                    packet: StatusPacketWithTime::new_crypto_handshake(handshake),
1✔
610
                }
611
            }
612
            ConnectionStatus::HandshakeSending {
613
                sent_nonce, ref packet, ..
×
614
            }
615
            | ConnectionStatus::NotConfirmed {
616
                sent_nonce, ref packet, ..
1✔
617
            } => ConnectionStatus::NotConfirmed {
1✔
618
                sent_nonce,
1✔
619
                received_nonce: payload.base_nonce,
1✔
620
                session_precomputed_key: SalsaBox::new(&payload.session_pk, &connection.session_sk),
1✔
621
                packet: packet.clone(),
1✔
622
            },
623
            ConnectionStatus::Established { .. } => unreachable!("Checked for Established status above"),
×
624
        };
625

626
        self.send_status_packet(connection)
3✔
627
            .await
2✔
628
            .map_err(HandlePacketError::SendTo)
629
    }
630

631
    /// Handle incoming `CryptoHandshake` in case when we don't have associated
632
    /// with sender connection.
633
    async fn handle_crypto_handshake_new_connection(
1✔
634
        &self,
635
        packet: &CryptoHandshake,
636
        addr: Option<SocketAddr>,
637
    ) -> Result<(), HandlePacketError> {
638
        let (cookie, payload, _real_precomputed_key) = match self.validate_crypto_handshake(packet) {
3✔
639
            Ok(result) => result,
1✔
640
            Err(e) => return Err(e),
×
641
        };
642

643
        if !self.friends.read().await.contains(&cookie.real_pk) {
2✔
644
            return Err(HandlePacketError::UnexpectedCryptoHandshake);
1✔
645
        }
646

647
        let mut connections = self.connections.write().await;
1✔
648

649
        if let Some(connection) = connections.get(&cookie.real_pk) {
2✔
650
            let mut connection = connection.write().await;
2✔
651
            if connection.peer_dht_pk != cookie.dht_pk {
3✔
652
                // We received a handshake packet for an existent connection
653
                // from a new address and this packet contains a different DHT
654
                // PublicKey. In this case we kill the old connection and create
655
                // a new one.
656

657
                self.clear_keys_by_addr(&connection).await;
2✔
658
                self.send_connection_status(&connection, false)
3✔
659
                    .await
2✔
660
                    .map_err(HandlePacketError::SendToConnectionStatus)?;
×
661
                self.send_kill_packet(&mut connection)
4✔
662
                    .await
2✔
663
                    .map_err(HandlePacketError::SendDataTo)?;
×
664
            } else {
665
                // We received a handshake packet for an existent connection
666
                // from a new address and this packet contains the same DHT
667
                // PublicKey. In this case we reject this packet if we already
668
                // received a handshake from the old connection and accept it
669
                // otherwise.
670

671
                if connection.is_established() || connection.is_not_confirmed() {
3✔
672
                    return Err(HandlePacketError::UnexpectedCryptoHandshake);
1✔
673
                }
674

675
                self.clear_keys_by_addr(&connection).await;
1✔
676
            }
677
        };
678

679
        let mut connection = CryptoConnection::new_not_confirmed(
680
            &self.real_sk,
1✔
681
            cookie.real_pk.clone(),
1✔
682
            cookie.dht_pk.clone(),
1✔
683
            payload.base_nonce,
1✔
684
            payload.session_pk,
1✔
685
            payload.cookie,
1✔
686
            &self.symmetric_key,
1✔
687
        );
688
        if let Some(addr) = addr {
1✔
689
            connection.set_udp_addr(addr);
1✔
690
            self.keys_by_addr
4✔
691
                .write()
692
                .await
2✔
693
                .insert((addr.ip(), addr.port()), cookie.real_pk.clone());
1✔
694
        }
695
        let connection = Arc::new(RwLock::new(connection));
2✔
696
        connections.insert(cookie.real_pk.clone(), connection);
2✔
697

698
        let msg = (cookie.real_pk, cookie.dht_pk);
1✔
699
        maybe_send_unbounded(self.dht_pk_tx.read().await.clone(), msg)
6✔
700
            .await
2✔
701
            .map_err(HandlePacketError::SendToDhtpk)
702
    }
703

704
    /// Handle `CryptoHandshake` packet received from UDP socket
705
    pub async fn handle_udp_crypto_handshake(
1✔
706
        &self,
707
        packet: &CryptoHandshake,
708
        addr: SocketAddr,
709
    ) -> Result<(), HandlePacketError> {
710
        if let Some(connection) = self.connection_by_addr(addr).await {
2✔
711
            let mut connection = connection.write().await;
2✔
712
            connection.set_udp_addr(addr);
2✔
713
            self.handle_crypto_handshake(&mut connection, packet).await
2✔
714
        } else {
715
            self.handle_crypto_handshake_new_connection(packet, Some(addr)).await
2✔
716
        }
717
    }
718

719
    /// Handle `CryptoHandshake` packet received from TCP socket
720
    pub async fn handle_tcp_crypto_handshake(
1✔
721
        &self,
722
        packet: &CryptoHandshake,
723
        sender_pk: PublicKey,
724
    ) -> Result<(), HandlePacketError> {
725
        let connection = self.connection_by_dht_key(sender_pk).await;
2✔
726
        if let Some(connection) = connection {
1✔
727
            let mut connection = connection.write().await;
2✔
728
            self.handle_crypto_handshake(&mut connection, packet).await
2✔
729
        } else {
730
            self.handle_crypto_handshake_new_connection(packet, None).await
×
731
        }
732
    }
733

734
    /** Handle request packet marking requested packets if rtt is elapsed since
735
    they were sent and removing delivered packets.
736

737
    Request array consists of bytes where every byte means offset of the
738
    requested packet starting from 1. Each 0 means adding 255 to the offset
739
    until non 0 byte is reached. For example, array of bytes [3 3 0 0 0 253]
740
    means that packets 2, 5 and 1023 were requested (if the first index is 0).
741

742
    */
743
    fn handle_request_packet(
1✔
744
        send_array: &mut PacketsArray<SentPacket>,
745
        mut data: &[u8],
746
        rtt: Duration,
747
        last_sent_time: &mut Option<Instant>,
748
    ) {
749
        // n is a packet number corresponding to numbers from the request
750
        let mut n = 1;
1✔
751

752
        // Cycle over sent packets to mark them requested or to delete them if
753
        // they are not requested which means they are delivered
754
        for i in send_array.buffer_start..send_array.buffer_end {
2✔
755
            // Stop if there is no more request numbers to handle
756
            if data.is_empty() {
1✔
757
                break;
758
            }
759

760
            if n == data[0] {
3✔
761
                // packet is requested
762
                if let Some(packet) = send_array.get_mut(i) {
2✔
763
                    if clock_elapsed(packet.sent_time) > rtt {
2✔
764
                        // mark it if it wasn't delivered in time
765
                        packet.requested = true;
1✔
766
                    }
767
                }
768
                n = 0;
1✔
769
                data = &data[1..];
1✔
770
            } else if let Some(packet) = send_array.remove(i) {
2✔
771
                // packet is not requested, delete it
772
                if last_sent_time.map(|time| time < packet.sent_time).unwrap_or(true) {
5✔
773
                    *last_sent_time = Some(packet.sent_time);
1✔
774
                }
775
            }
776

777
            if n == 255 {
3✔
778
                // n went through all the values except 0
779
                // which means that request byte is 0
780
                // which means that requested packet number is greater than 255
781
                // so just reset n and go farther
782
                n = 1;
1✔
783
                data = &data[1..];
1✔
784
            } else {
785
                n += 1;
1✔
786
            }
787
        }
788
    }
789

790
    /// Build request packet that will contain numbers of missing packets that
791
    /// we should receive.
792
    fn generate_request_packet(recv_array: &PacketsArray<RecvPacket>) -> Vec<u8> {
1✔
793
        let mut data = Vec::with_capacity(MAX_CRYPTO_DATA_SIZE);
1✔
794
        data.push(PACKET_ID_REQUEST);
1✔
795

796
        // n is a packet number relative to the last missing packet
797
        let mut n = 1;
1✔
798

799
        // go through all received packets and put numbers of missing packets to the request
800
        for i in recv_array.buffer_start..recv_array.buffer_end {
3✔
801
            if !recv_array.contains(i) {
2✔
802
                data.push(n);
1✔
803
                n = 0;
1✔
804
            } else if n == 255 {
2✔
805
                data.push(0);
1✔
806
                n = 0;
1✔
807
            }
808

809
            if data.len() == MAX_CRYPTO_DATA_SIZE {
2✔
810
                return data;
1✔
811
            }
812

813
            n += 1;
2✔
814
        }
815

816
        data
1✔
817
    }
818

819
    /// Send received lossless packets from the beginning of the receiving
820
    /// buffer to lossless sink and delete them
821
    async fn process_ready_lossless_packets(
1✔
822
        &self,
823
        recv_array: &mut PacketsArray<RecvPacket>,
824
        pk: PublicKey,
825
    ) -> Result<(), mpsc::SendError> {
826
        let mut tx = self.lossless_tx.clone();
2✔
827

828
        while let Some(packet) = recv_array.pop_front() {
4✔
829
            tx.send((pk.clone(), packet.data)).await?;
4✔
830
        }
831

832
        Ok(())
1✔
833
    }
834

835
    /// Find the time when the last acknowledged packet was sent. This time is
836
    /// used to update rtt
837
    fn last_sent_time(send_array: &PacketsArray<SentPacket>, index: u32) -> Option<Instant> {
1✔
838
        let mut last_sent_time = None;
1✔
839
        for i in send_array.buffer_start..index {
2✔
840
            if let Some(packet) = send_array.get(i) {
1✔
841
                if last_sent_time.map(|time| time < packet.sent_time).unwrap_or(true) {
2✔
842
                    last_sent_time = Some(packet.sent_time);
1✔
843
                }
844
            }
845
        }
846
        last_sent_time
1✔
847
    }
848

849
    /** Handle `CryptoData` packet
850

851
    Every data packet contains `buffer_start` index. All packets with index
852
    lower than `buffer_start` index were received by other side. So we can
853
    delete all these packets from sent packets array.
854

855
    Then depending on type of the data packet we can do:
856
    - kill type: kill the connection
857
    - request type: mark packets from the sent packets buffer that they should
858
      be sent and delete delivered packets
859
    - lossless type: add packet to the received packets buffer and process
860
      packets from the beginning of this buffer
861
    - lossy type: just process the packet
862
    */
863
    async fn handle_crypto_data(
1✔
864
        &self,
865
        connection: &mut CryptoConnection,
866
        packet: &CryptoData,
867
        udp: bool,
868
    ) -> Result<(), HandlePacketError> {
869
        let (sent_nonce, mut received_nonce, session_precomputed_key) = match connection.status {
3✔
870
            ConnectionStatus::NotConfirmed {
1✔
871
                sent_nonce,
872
                received_nonce,
873
                ref session_precomputed_key,
874
                ..
875
            }
876
            | ConnectionStatus::Established {
877
                sent_nonce,
878
                received_nonce,
879
                ref session_precomputed_key,
880
            } => (sent_nonce, received_nonce, session_precomputed_key.clone()),
881
            _ => return Err(HandlePacketError::CannotHandleCryptoData),
1✔
882
        };
883

884
        let cur_last_bytes = CryptoData::nonce_last_bytes(received_nonce);
2✔
885
        let (diff, _) = packet.nonce_last_bytes.overflowing_sub(cur_last_bytes);
2✔
886
        let mut packet_nonce = received_nonce;
1✔
887
        increment_nonce_number(&mut packet_nonce, diff);
1✔
888

889
        let payload = match packet.get_payload(&session_precomputed_key, &packet_nonce) {
2✔
890
            Ok(payload) => payload,
1✔
891
            Err(e) => return Err(HandlePacketError::GetPayload(e)),
×
892
        };
893

894
        // Find the time when the last acknowledged packet was sent
895
        let mut last_sent_time = NetCrypto::last_sent_time(&connection.send_array, payload.buffer_start);
2✔
896

897
        // Remove all acknowledged packets and set new start index to the send buffer
898
        if let Err(e) = connection.send_array.set_buffer_start(payload.buffer_start) {
1✔
899
            return Err(HandlePacketError::PacketsArrayError(e));
1✔
900
        }
901

902
        // And get the ID of the packet
903
        let packet_id = match payload.data.first() {
2✔
904
            Some(&packet_id) => packet_id,
1✔
905
            None => return Err(HandlePacketError::DataEmpty),
1✔
906
        };
907

908
        if packet_id == PACKET_ID_KILL {
1✔
909
            // Kill the connection
910
            self.connections.write().await.remove(&connection.peer_real_pk);
2✔
911
            self.clear_keys_by_addr(connection).await;
1✔
912
            return self
3✔
913
                .send_connection_status(connection, false)
1✔
914
                .map_err(HandlePacketError::SendToConnectionStatus)
915
                .await;
2✔
916
        }
917

918
        // Update nonce if diff is big enough
919
        if diff > NONCE_DIFF_THRESHOLD * 2 {
2✔
920
            increment_nonce_number(&mut received_nonce, NONCE_DIFF_THRESHOLD);
1✔
921
        }
922

923
        self.send_connection_status(connection, true)
3✔
924
            .await
2✔
925
            .map_err(HandlePacketError::SendToConnectionStatus)?;
×
926

927
        connection.status = ConnectionStatus::Established {
2✔
928
            sent_nonce,
1✔
929
            received_nonce,
1✔
930
            session_precomputed_key,
1✔
931
        };
932

933
        if packet_id == PACKET_ID_REQUEST {
1✔
934
            // Use const RTT in case of TCP connection
935
            let rtt = if udp { connection.rtt } else { TCP_RTT };
1✔
936
            NetCrypto::handle_request_packet(&mut connection.send_array, &payload.data[1..], rtt, &mut last_sent_time);
1✔
937
            // Update end index of received buffer ignoring the error - we still
938
            // want to handle this packet even if connection is too slow
939
            connection.recv_array.set_buffer_end(payload.packet_number).ok();
1✔
940
        } else if packet_id > PACKET_ID_CRYPTO_RANGE_END && packet_id < PACKET_ID_LOSSY_RANGE_START {
3✔
941
            if let Err(e) = connection
2✔
942
                .recv_array
943
                .insert(payload.packet_number, RecvPacket::new(payload.data))
1✔
944
            {
945
                return Err(HandlePacketError::PacketsArrayError(e));
1✔
946
            }
947
            connection.packets_received += 1;
1✔
948
            self.process_ready_lossless_packets(&mut connection.recv_array, connection.peer_real_pk.clone())
4✔
949
                .await
2✔
950
                .map_err(HandlePacketError::SendToLossless)?;
×
951
        } else if (PACKET_ID_LOSSY_RANGE_START..=PACKET_ID_LOSSY_RANGE_END).contains(&packet_id) {
2✔
952
            // Update end index of received buffer ignoring the error - we still
953
            // want to handle this packet even if connection is too slow
954
            connection.recv_array.set_buffer_end(payload.packet_number).ok();
2✔
955
            let mut tx = self.lossy_tx.clone();
1✔
956
            let peer_real_pk = connection.peer_real_pk.clone();
1✔
957
            let data = payload.data.clone();
1✔
958

959
            tx.send((peer_real_pk, data))
3✔
960
                .await
2✔
961
                .map_err(HandlePacketError::SendToLossy)?;
×
962
        } else {
963
            return Err(HandlePacketError::packet_id(packet_id));
2✔
964
        };
965

966
        // TODO: update rtt only when udp is true?
967
        if let Some(last_sent_time) = last_sent_time {
2✔
968
            // Update rtt if it's become lower
969
            let elapsed = clock_elapsed(last_sent_time);
2✔
970
            if elapsed < connection.rtt {
2✔
971
                connection.rtt = elapsed;
1✔
972
            }
973
        }
974

975
        Ok(())
1✔
976
    }
977

978
    /// Handle `CryptoData` packet received from UDP socket
979
    pub async fn handle_udp_crypto_data(&self, packet: &CryptoData, addr: SocketAddr) -> Result<(), HandlePacketError> {
5✔
980
        if let Some(connection) = self.connection_by_addr(addr).await {
2✔
981
            let mut connection = connection.write().await;
2✔
982
            connection.set_udp_addr(addr);
2✔
983
            self.handle_crypto_data(&mut connection, packet, /* udp */ true).await
2✔
984
        } else {
985
            Err(HandlePacketError::no_udp_connection(addr))
×
986
        }
987
    }
988

989
    /// Handle `CryptoData` packet received from TCP socket
990
    pub async fn handle_tcp_crypto_data(
1✔
991
        &self,
992
        packet: &CryptoData,
993
        sender_pk: PublicKey,
994
    ) -> Result<(), HandlePacketError> {
995
        if let Some(connection) = self.connection_by_dht_key(sender_pk.clone()).await {
2✔
996
            let mut connection = connection.write().await;
2✔
997
            self.handle_crypto_data(&mut connection, packet, /* udp */ false).await
2✔
998
        } else {
999
            Err(HandlePacketError::no_tcp_connection(sender_pk))
×
1000
        }
1001
    }
1002

1003
    /// Send packet to crypto connection choosing TCP or UDP protocol
1004
    async fn send_packet(&self, packet: Packet, connection: &mut CryptoConnection) -> Result<(), SendPacketError> {
8✔
1005
        // TODO: can backpressure be used instead of congestion control? It
1006
        // seems it's possible to implement wrapper for bounded sender with
1007
        // priority queue and just send packets there
1008
        if let Some(addr) = connection.get_udp_addr() {
3✔
1009
            if connection.is_udp_alive() {
2✔
1010
                return self
4✔
1011
                    .send_to_udp(addr, packet.into())
1✔
1012
                    .await
2✔
1013
                    .map_err(SendPacketError::Udp);
1014
            }
1015

1016
            let dht_packet: DhtPacket = packet.clone().into();
2✔
1017
            let udp_attempt_should_be_made = connection.udp_attempt_should_be_made() && {
2✔
1018
                // check if the packet is not too big
1019
                let mut buf = [0; DHT_ATTEMPT_MAX_PACKET_LENGTH];
1✔
1020
                dht_packet.to_bytes((&mut buf, 0)).is_ok()
3✔
1021
            };
1022

1023
            if udp_attempt_should_be_made {
2✔
1024
                connection.update_udp_send_attempt_time();
1✔
1025
                self.send_to_udp(addr, dht_packet).await.map_err(SendPacketError::Udp)?;
1✔
1026
            }
1027
        };
1028

1029
        let tcp_tx = self.tcp_tx.read().await.clone();
2✔
1030
        maybe_send_bounded(tcp_tx, (packet.into(), connection.peer_dht_pk.clone()))
3✔
1031
            .await
2✔
1032
            .map_err(SendPacketError::Tcp)
1033
    }
1034

1035
    /// Send `CookieRequest` or `CryptoHandshake` packet if needed depending on
1036
    /// connection status and update sent counter
1037
    async fn send_status_packet(&self, connection: &mut CryptoConnection) -> Result<(), SendPacketError> {
5✔
1038
        match connection.packet_to_send() {
2✔
1039
            Some(packet) => self.send_packet(packet.into(), connection).await,
2✔
1040
            None => Ok(()),
1✔
1041
        }
1042
    }
1043

1044
    /// Send `CryptoData` packet if the connection is established.
1045
    async fn send_data_packet(
1✔
1046
        &self,
1047
        connection: &mut CryptoConnection,
1048
        data: Vec<u8>,
1049
        packet_number: u32,
1050
    ) -> Result<(), SendDataError> {
1051
        let packet = match connection.status {
1✔
1052
            ConnectionStatus::NotConfirmed {
×
1053
                ref mut sent_nonce,
1054
                ref session_precomputed_key,
1055
                ..
1056
            }
1057
            | ConnectionStatus::Established {
1058
                ref mut sent_nonce,
1059
                ref session_precomputed_key,
1060
                ..
1061
            } => {
1062
                let payload = CryptoDataPayload {
1063
                    buffer_start: connection.recv_array.buffer_start,
1✔
1064
                    packet_number,
1065
                    data,
1066
                };
1067
                let packet = CryptoData::new(session_precomputed_key, *sent_nonce, &payload);
1✔
1068
                increment_nonce(sent_nonce);
1✔
1069
                packet
1✔
1070
            }
1071
            _ => return Err(SendDataError::NoConnection),
×
1072
        };
1073
        self.send_packet(Packet::CryptoData(packet), connection)
3✔
1074
            .await
2✔
1075
            .map_err(SendDataError::SendTo)
1076
    }
1077

1078
    /// Send request packet with indices of not received packets.
1079
    async fn send_request_packet(&self, connection: &mut CryptoConnection) -> Result<(), SendDataError> {
5✔
1080
        let data = NetCrypto::generate_request_packet(&connection.recv_array);
1✔
1081
        let packet_number = connection.send_array.buffer_end;
1✔
1082
        // TODO: set only if packet was sent successfully?
1083
        connection.request_packet_sent_time = Some(clock_now());
2✔
1084
        self.send_data_packet(connection, data, packet_number).await
1✔
1085
    }
1086

1087
    /// Send packets that were requested.
1088
    async fn send_requested_packets(&self, connection: &mut CryptoConnection) -> Result<(), SendDataError> {
5✔
1089
        let now = clock_now();
2✔
1090
        let packets = connection
2✔
1091
            .send_array
1092
            .iter_mut()
1093
            .filter(|(_, packet)| packet.requested)
2✔
1094
            .map(|(i, packet)| {
3✔
1095
                packet.requested = false;
1✔
1096
                packet.sent_time = now;
1✔
1097
                (i, packet.data.clone())
1✔
1098
            })
1099
            .collect::<Vec<_>>();
1100

1101
        for (i, data) in packets {
3✔
1102
            self.send_data_packet(connection, data, i).await?;
4✔
1103
        }
1104

1105
        Ok(())
1✔
1106
    }
1107

1108
    /// The main loop that should be run at least 20 times per second
1109
    async fn main_loop(&self) -> Result<(), SendDataError> {
5✔
1110
        let mut connections = self.connections.write().await;
2✔
1111
        let mut keys_by_addr = self.keys_by_addr.write().await;
2✔
1112
        let mut to_remove = Vec::new();
1✔
1113

1114
        // Only one cycle over all connections to prevent many lock acquirements
1115
        for (pk, connection) in connections.iter() {
4✔
1116
            let mut connection = connection.write().await;
3✔
1117

1118
            if connection.is_timed_out() {
1✔
1119
                if let Some(addr) = connection.get_udp_addr_v4() {
1✔
1120
                    keys_by_addr.remove(&(addr.ip(), addr.port()));
2✔
1121
                }
1122
                if let Some(addr) = connection.get_udp_addr_v6() {
2✔
1123
                    keys_by_addr.remove(&(addr.ip(), addr.port()));
×
1124
                }
1125

1126
                if connection.is_established() {
2✔
1127
                    self.send_connection_status(&connection, false)
×
1128
                        .await
×
1129
                        .map_err(SendDataError::SendToConnectionStatus)?;
×
1130
                }
1131

1132
                if connection.is_established() || connection.is_not_confirmed() {
3✔
1133
                    self.send_kill_packet(&mut connection).await?;
×
1134
                }
1135

1136
                to_remove.push(pk.clone());
2✔
1137
            }
1138

1139
            self.send_status_packet(&mut connection)
4✔
1140
                .await
3✔
1141
                .map_err(SendDataError::SendTo)?;
×
1142

1143
            if connection.is_not_confirmed() || connection.is_established() {
3✔
1144
                let should_send = connection
2✔
1145
                    .request_packet_sent_time
1146
                    .map_or(true, |time| clock_elapsed(time) > CRYPTO_SEND_PACKET_INTERVAL);
2✔
1147
                if should_send {
2✔
1148
                    self.send_request_packet(&mut connection).await?;
2✔
1149
                }
1150
            }
1151

1152
            if connection.is_established() {
3✔
1153
                if connection.packet_recv_rate > CRYPTO_PACKET_MIN_RATE {
1✔
1154
                    let request_packet_interval = connection.request_packet_interval();
×
1155
                    let should_send = connection
×
1156
                        .request_packet_sent_time
1157
                        .map_or(true, |time| clock_elapsed(time) > request_packet_interval);
×
1158
                    if should_send {
×
1159
                        self.send_request_packet(&mut connection).await?;
×
1160
                    }
1161
                }
1162

1163
                // TODO: either use send_rate or remove it
1164
                connection.update_congestion_stats();
2✔
1165

1166
                self.send_requested_packets(&mut connection).await?;
3✔
1167
            }
1168
        }
1169

1170
        for pk in to_remove {
2✔
1171
            connections.remove(&pk);
2✔
1172
        }
1173

1174
        Ok(())
1✔
1175
    }
1176

1177
    /// Run `net_crypto` periodical tasks. Result future will never be completed
1178
    /// successfully.
1179
    pub async fn run(&self) -> Result<(), RunError> {
×
1180
        let mut wakeups = tokio::time::interval(PACKET_COUNTER_AVERAGE_INTERVAL);
1181

1182
        loop {
1183
            wakeups.tick().await;
1184

1185
            let fut = tokio::time::timeout(PACKET_COUNTER_AVERAGE_INTERVAL, self.main_loop());
1186

1187
            let res = match fut.await {
1188
                Err(e) => Err(RunError::Timeout(e)),
1189
                Ok(Err(e)) => Err(RunError::SendData(e)),
1190
                Ok(Ok(_)) => Ok(()),
1191
            };
1192

1193
            if let Err(ref e) = res {
1194
                warn!("Failed to send net crypto packets: {}", e);
1195
                return res;
1196
            }
1197
        }
1198
    }
1199

1200
    /// Set sink to send DHT `PublicKey` when it gets known.
1201
    pub async fn set_dht_pk_sink(&self, dht_pk_tx: DhtPkTx) {
5✔
1202
        *self.dht_pk_tx.write().await = Some(dht_pk_tx);
1✔
1203
    }
1204

1205
    /// Set sink to send a connection status when it becomes connected or
1206
    /// disconnected.
1207
    pub async fn set_connection_status_sink(&self, connection_status_tx: ConnectionStatusTx) {
5✔
1208
        *self.connection_status_tx.write().await = Some(connection_status_tx);
1✔
1209
    }
1210

1211
    /// Set sink for sending TCP packets via relays.
1212
    pub async fn set_tcp_sink(&self, tcp_tx: TcpTx) {
5✔
1213
        *self.tcp_tx.write().await = Some(tcp_tx);
1✔
1214
    }
1215
}
1216

1217
#[cfg(test)]
1218
mod tests {
1219
    // https://github.com/rust-lang/rust/issues/61520
1220
    use super::{Packet, *};
1221
    use crypto_box::{
1222
        aead::{generic_array::typenum::marker_traits::Unsigned, AeadCore},
1223
        SalsaBox,
1224
    };
1225
    use futures::{Future, StreamExt};
1226
    use rand::{CryptoRng, Rng};
1227

1228
    impl NetCrypto {
1229
        pub fn real_pk(&self) -> &PublicKey {
1✔
1230
            &self.real_pk
1✔
1231
        }
1232

1233
        pub async fn has_friend(&self, pk: &PublicKey) -> bool {
5✔
1234
            self.friends.read().await.contains(pk)
3✔
1235
        }
1236

1237
        pub async fn connection_dht_pk(&self, pk: &PublicKey) -> Option<PublicKey> {
5✔
1238
            if let Some(connection) = self.connections.read().await.get(pk) {
3✔
1239
                Some(connection.read().await.peer_dht_pk.clone())
3✔
1240
            } else {
1241
                None
×
1242
            }
1243
        }
1244

1245
        pub async fn connection_saddr(&self, pk: &PublicKey) -> Option<SocketAddr> {
5✔
1246
            if let Some(connection) = self.connections.read().await.get(pk) {
3✔
1247
                connection.read().await.get_udp_addr()
3✔
1248
            } else {
1249
                None
×
1250
            }
1251
        }
1252

1253
        pub async fn add_established_connection(
1✔
1254
            &self,
1255
            peer_dht_pk: PublicKey,
1256
            peer_real_pk: PublicKey,
1257
            sent_nonce: Nonce,
1258
            received_nonce: Nonce,
1259
            session_precomputed_key: SalsaBox,
1260
        ) {
1261
            let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &self.dht_sk);
1✔
1262
            let mut connection = CryptoConnection::new(
1263
                &dht_precomputed_key,
1✔
1264
                self.dht_pk.clone(),
1✔
1265
                self.real_pk.clone(),
1✔
1266
                peer_real_pk.clone(),
1✔
1267
                peer_dht_pk,
1✔
1268
            );
1269
            connection.status = ConnectionStatus::Established {
2✔
1270
                sent_nonce,
1271
                received_nonce,
1272
                session_precomputed_key,
1✔
1273
            };
1274
            self.connections
5✔
1275
                .write()
1276
                .await
2✔
1277
                .insert(peer_real_pk, Arc::new(RwLock::new(connection)));
1✔
1278
        }
1279

1280
        pub fn get_cookie<R: Rng + CryptoRng>(
1✔
1281
            &self,
1282
            rng: &mut R,
1283
            real_pk: PublicKey,
1284
            dht_pk: PublicKey,
1285
        ) -> EncryptedCookie {
1286
            let cookie = Cookie::new(real_pk, dht_pk);
1✔
1287
            EncryptedCookie::new(rng, &self.symmetric_key, &cookie)
1✔
1288
        }
1289

1290
        pub async fn get_session_pk(&self, friend_pk: &PublicKey) -> Option<PublicKey> {
5✔
1291
            if let Some(connection) = self.connections.read().await.get(friend_pk) {
3✔
1292
                Some(connection.read().await.session_pk.clone())
3✔
1293
            } else {
1294
                None
×
1295
            }
1296
        }
1297
    }
1298

1299
    #[tokio::test]
6✔
1300
    async fn add_remove_friend() {
3✔
1301
        let mut rng = thread_rng();
2✔
1302
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1303
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1304
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1305
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1306
        let dht_pk = dht_sk.public_key();
1✔
1307
        let real_sk = SecretKey::generate(&mut rng);
2✔
1308
        let real_pk = real_sk.public_key();
1✔
1309
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
1310
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1311
            udp_tx,
1✔
1312
            lossless_tx,
1✔
1313
            lossy_tx,
1✔
1314
            dht_pk,
1✔
1315
            dht_sk,
1✔
1316
            real_pk,
1✔
1317
            real_sk,
1✔
1318
            precomputed_keys,
1✔
1319
        });
1320

1321
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
1322

1323
        net_crypto.add_friend(peer_real_pk.clone()).await;
1✔
1324
        assert!(net_crypto.friends.read().await.contains(&peer_real_pk));
1✔
1325
        net_crypto.remove_friend(peer_real_pk.clone()).await;
1✔
1326
        assert!(!net_crypto.friends.read().await.contains(&peer_real_pk));
2✔
1327
    }
1328

1329
    #[tokio::test]
6✔
1330
    async fn handle_cookie_request() {
3✔
1331
        let mut rng = thread_rng();
2✔
1332
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1333
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1334
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1335
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1336
        let dht_pk = dht_sk.public_key();
1✔
1337
        let real_sk = SecretKey::generate(&mut rng);
2✔
1338
        let real_pk = real_sk.public_key();
1✔
1339
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
1340
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
1341
        let precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1342
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1343
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1344
            udp_tx,
1✔
1345
            lossless_tx,
1✔
1346
            lossy_tx,
1✔
1347
            dht_pk,
1✔
1348
            dht_sk,
1✔
1349
            real_pk,
1✔
1350
            real_sk,
1✔
1351
            precomputed_keys,
1✔
1352
        });
1353

1354
        let cookie_request_id = 12345;
1✔
1355

1356
        let cookie_request_payload = CookieRequestPayload {
1357
            pk: peer_real_pk.clone(),
1✔
1358
            id: cookie_request_id,
1359
        };
1360
        let cookie_request = CookieRequest::new(&precomputed_key, peer_dht_pk.clone(), &cookie_request_payload);
1✔
1361

1362
        let cookie_response = net_crypto.handle_cookie_request(&cookie_request).await.unwrap();
2✔
1363
        let cookie_response_payload = cookie_response.get_payload(&precomputed_key).unwrap();
2✔
1364

1365
        assert_eq!(cookie_response_payload.id, cookie_request_id);
1✔
1366

1367
        let cookie = cookie_response_payload
2✔
1368
            .cookie
1369
            .get_payload(&net_crypto.symmetric_key)
1✔
1370
            .unwrap();
1371
        assert_eq!(cookie.dht_pk, peer_dht_pk);
1✔
1372
        assert_eq!(cookie.real_pk, peer_real_pk);
2✔
1373
    }
1374

1375
    #[tokio::test]
6✔
1376
    async fn handle_cookie_request_invalid() {
3✔
1377
        let mut rng = thread_rng();
2✔
1378
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1379
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1380
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1381
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1382
        let dht_pk = dht_sk.public_key();
1✔
1383
        let real_sk = SecretKey::generate(&mut rng);
2✔
1384
        let real_pk = real_sk.public_key();
1✔
1385
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
1386
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1387
            udp_tx,
1✔
1388
            lossless_tx,
1✔
1389
            lossy_tx,
1✔
1390
            dht_pk,
1✔
1391
            dht_sk,
1✔
1392
            real_pk,
1✔
1393
            real_sk,
1✔
1394
            precomputed_keys,
1✔
1395
        });
1396

1397
        let cookie_request = CookieRequest {
1398
            pk: SecretKey::generate(&mut rng).public_key(),
2✔
1399
            nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
1400
            payload: vec![42; 88],
1✔
1401
        };
1402

1403
        let res = net_crypto.handle_cookie_request(&cookie_request).await;
2✔
1404
        assert!(res.is_err());
2✔
1405
        assert_eq!(
3✔
1406
            res.err().unwrap(),
1✔
1407
            HandlePacketError::GetPayload(GetPayloadError::Decrypt)
1408
        );
1409
    }
1410

1411
    #[tokio::test]
6✔
1412
    async fn handle_udp_cookie_request() {
3✔
1413
        let mut rng = thread_rng();
2✔
1414
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
1415
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1416
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1417
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1418
        let dht_pk = dht_sk.public_key();
1✔
1419
        let real_sk = SecretKey::generate(&mut rng);
2✔
1420
        let real_pk = real_sk.public_key();
1✔
1421
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
1422
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
1423
        let precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1424
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1425
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1426
            udp_tx,
1✔
1427
            lossless_tx,
1✔
1428
            lossy_tx,
1✔
1429
            dht_pk,
1✔
1430
            dht_sk,
1✔
1431
            real_pk,
1✔
1432
            real_sk,
1✔
1433
            precomputed_keys,
1✔
1434
        });
1435

1436
        let cookie_request_id = 12345;
1✔
1437

1438
        let cookie_request_payload = CookieRequestPayload {
1439
            pk: peer_real_pk.clone(),
1✔
1440
            id: cookie_request_id,
1441
        };
1442
        let cookie_request = CookieRequest::new(&precomputed_key, peer_dht_pk.clone(), &cookie_request_payload);
1✔
1443

1444
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
1445

1446
        net_crypto
4✔
1447
            .handle_udp_cookie_request(&cookie_request, addr)
1✔
1448
            .await
2✔
1449
            .unwrap();
1450

1451
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
1452
        let (packet, addr_to_send) = received.unwrap();
2✔
1453
        let cookie_response = unpack!(packet, DhtPacket::CookieResponse);
1✔
1454

1455
        assert_eq!(addr_to_send, addr);
2✔
1456

1457
        let cookie_response_payload = cookie_response.get_payload(&precomputed_key).unwrap();
1✔
1458

1459
        assert_eq!(cookie_response_payload.id, cookie_request_id);
1✔
1460

1461
        let cookie = cookie_response_payload
2✔
1462
            .cookie
1463
            .get_payload(&net_crypto.symmetric_key)
1✔
1464
            .unwrap();
1465
        assert_eq!(cookie.dht_pk, peer_dht_pk);
1✔
1466
        assert_eq!(cookie.real_pk, peer_real_pk);
2✔
1467
    }
1468

1469
    #[tokio::test]
6✔
1470
    async fn handle_tcp_cookie_request() {
3✔
1471
        let mut rng = thread_rng();
2✔
1472
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1473
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1474
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1475
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1476
        let dht_pk = dht_sk.public_key();
1✔
1477
        let real_sk = SecretKey::generate(&mut rng);
2✔
1478
        let real_pk = real_sk.public_key();
1✔
1479
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
1480
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
1481
        let precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1482
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1483
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1484
            udp_tx,
1✔
1485
            lossless_tx,
1✔
1486
            lossy_tx,
1✔
1487
            dht_pk,
1✔
1488
            dht_sk,
1✔
1489
            real_pk,
1✔
1490
            real_sk,
1✔
1491
            precomputed_keys,
1✔
1492
        });
1493

1494
        let (net_crypto_tcp_tx, net_crypto_tcp_rx) = mpsc::channel(1);
2✔
1495
        net_crypto.set_tcp_sink(net_crypto_tcp_tx).await;
2✔
1496

1497
        let cookie_request_id = 12345;
1✔
1498

1499
        let cookie_request_payload = CookieRequestPayload {
1500
            pk: peer_real_pk.clone(),
1✔
1501
            id: cookie_request_id,
1502
        };
1503
        let cookie_request = CookieRequest::new(&precomputed_key, peer_dht_pk.clone(), &cookie_request_payload);
1✔
1504

1505
        net_crypto
4✔
1506
            .handle_tcp_cookie_request(&cookie_request, peer_dht_pk.clone())
1✔
1507
            .await
2✔
1508
            .unwrap();
1509

1510
        let (received, _net_crypto_tcp_rx) = net_crypto_tcp_rx.into_future().await;
1✔
1511
        let (packet, pk_to_send) = received.unwrap();
2✔
1512
        let cookie_response = unpack!(packet, TcpDataPayload::CookieResponse);
1✔
1513

1514
        assert_eq!(pk_to_send, peer_dht_pk);
2✔
1515

1516
        let cookie_response_payload = cookie_response.get_payload(&precomputed_key).unwrap();
1✔
1517

1518
        assert_eq!(cookie_response_payload.id, cookie_request_id);
1✔
1519

1520
        let cookie = cookie_response_payload
2✔
1521
            .cookie
1522
            .get_payload(&net_crypto.symmetric_key)
1✔
1523
            .unwrap();
1524
        assert_eq!(cookie.dht_pk, peer_dht_pk);
1✔
1525
        assert_eq!(cookie.real_pk, peer_real_pk);
2✔
1526
    }
1527

1528
    #[tokio::test]
6✔
1529
    async fn handle_udp_cookie_request_invalid() {
3✔
1530
        let mut rng = thread_rng();
2✔
1531
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1532
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1533
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1534
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1535
        let dht_pk = dht_sk.public_key();
1✔
1536
        let real_sk = SecretKey::generate(&mut rng);
2✔
1537
        let real_pk = real_sk.public_key();
1✔
1538
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
1539
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1540
            udp_tx,
1✔
1541
            lossless_tx,
1✔
1542
            lossy_tx,
1✔
1543
            dht_pk,
1✔
1544
            dht_sk,
1✔
1545
            real_pk,
1✔
1546
            real_sk,
1✔
1547
            precomputed_keys,
1✔
1548
        });
1549

1550
        let cookie_request = CookieRequest {
1551
            pk: SecretKey::generate(&mut rng).public_key(),
2✔
1552
            nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
1553
            payload: vec![42; 88],
1✔
1554
        };
1555

1556
        let addr = "127.0.0.1:12345".parse().unwrap();
1✔
1557

1558
        let res = net_crypto.handle_udp_cookie_request(&cookie_request, addr).await;
2✔
1559
        assert!(res.is_err());
2✔
1560
        assert_eq!(
3✔
1561
            res.err().unwrap(),
1✔
1562
            HandlePacketError::GetPayload(GetPayloadError::Decrypt)
1563
        );
1564
    }
1565

1566
    #[tokio::test]
6✔
1567
    async fn handle_cookie_response() {
3✔
1568
        let mut rng = thread_rng();
2✔
1569
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1570
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1571
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1572
        let dht_sk = SecretKey::generate(&mut rng);
1✔
1573
        let dht_pk = dht_sk.public_key();
1✔
1574
        let real_sk = SecretKey::generate(&mut rng);
2✔
1575
        let real_pk = real_sk.public_key();
1✔
1576
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1577
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1578
            udp_tx,
1✔
1579
            lossless_tx,
1✔
1580
            lossy_tx,
1✔
1581
            dht_pk: dht_pk.clone(),
1✔
1582
            dht_sk: dht_sk.clone(),
1✔
1583
            real_pk: real_pk.clone(),
1✔
1584
            real_sk,
1✔
1585
            precomputed_keys,
1✔
1586
        });
1587

1588
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
1589
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
1590
        let peer_real_pk = peer_real_sk.public_key();
1✔
1591
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1592
        let mut connection =
2✔
1593
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk.clone(), peer_real_pk, peer_dht_pk);
1594

1595
        let cookie_request_id = unpack!(connection.status, ConnectionStatus::CookieRequesting, cookie_request_id);
1✔
1596

1597
        let cookie = EncryptedCookie {
1598
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1599
            payload: vec![43; 88],
1✔
1600
        };
1601
        let cookie_response_payload = CookieResponsePayload {
1602
            cookie: cookie.clone(),
1✔
1603
            id: cookie_request_id,
1604
        };
1605
        let cookie_response = CookieResponse::new(&dht_precomputed_key, &cookie_response_payload);
1✔
1606

1607
        net_crypto
4✔
1608
            .handle_cookie_response(&mut connection, &cookie_response)
1✔
1609
            .await
2✔
1610
            .unwrap();
1611

1612
        let packet = unpack!(connection.status, ConnectionStatus::HandshakeSending, packet);
1✔
1613
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
2✔
1614
        assert_eq!(packet.cookie, cookie);
2✔
1615

1616
        let payload = packet.get_payload(&SalsaBox::new(&real_pk, &peer_real_sk)).unwrap();
1✔
1617
        assert_eq!(payload.cookie_hash, cookie.hash());
2✔
1618
    }
1619

1620
    #[tokio::test]
6✔
1621
    async fn handle_cookie_response_invalid_status() {
3✔
1622
        let mut rng = thread_rng();
2✔
1623
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1624
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1625
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1626
        let dht_sk = SecretKey::generate(&mut rng);
1✔
1627
        let dht_pk = dht_sk.public_key();
1✔
1628
        let real_sk = SecretKey::generate(&mut rng);
1✔
1629
        let real_pk = real_sk.public_key();
1✔
1630
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1631
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1632
            udp_tx,
1✔
1633
            lossless_tx,
1✔
1634
            lossy_tx,
1✔
1635
            dht_pk,
1✔
1636
            dht_sk: dht_sk.clone(),
1✔
1637
            real_pk,
1✔
1638
            real_sk: real_sk.clone(),
1✔
1639
            precomputed_keys,
1✔
1640
        });
1641

1642
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
1643
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
1644
        let mut connection = CryptoConnection::new_not_confirmed(
1645
            &real_sk,
1✔
1646
            peer_real_pk,
1✔
1647
            peer_dht_pk.clone(),
1✔
1648
            [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
1649
            SecretKey::generate(&mut rng).public_key(),
1✔
1650
            EncryptedCookie {
1✔
1651
                nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1652
                payload: vec![42; 88],
1✔
1653
            },
1654
            &net_crypto.symmetric_key,
1✔
1655
        );
1656

1657
        let cookie = EncryptedCookie {
1658
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1659
            payload: vec![43; 88],
1✔
1660
        };
1661
        let cookie_response_payload = CookieResponsePayload { cookie, id: 12345 };
1✔
1662
        let cookie_response = CookieResponse::new(&SalsaBox::new(&peer_dht_pk, &dht_sk), &cookie_response_payload);
2✔
1663

1664
        let res = net_crypto
3✔
1665
            .handle_cookie_response(&mut connection, &cookie_response)
1✔
1666
            .await;
2✔
1667
        assert!(res.is_err());
2✔
1668
        assert_eq!(res.err().unwrap(), HandlePacketError::InvalidState);
2✔
1669
    }
1670

1671
    #[tokio::test]
6✔
1672
    async fn handle_cookie_response_invalid_request_id() {
3✔
1673
        let mut rng = thread_rng();
2✔
1674
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1675
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1676
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1677
        let dht_sk = SecretKey::generate(&mut rng);
1✔
1678
        let dht_pk = dht_sk.public_key();
1✔
1679
        let real_sk = SecretKey::generate(&mut rng);
2✔
1680
        let real_pk = real_sk.public_key();
1✔
1681
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1682
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1683
            udp_tx,
1✔
1684
            lossless_tx,
1✔
1685
            lossy_tx,
1✔
1686
            dht_pk: dht_pk.clone(),
1✔
1687
            dht_sk: dht_sk.clone(),
1✔
1688
            real_pk: real_pk.clone(),
1✔
1689
            real_sk,
1✔
1690
            precomputed_keys,
1✔
1691
        });
1692

1693
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
1694
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
1695
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1696
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
1697

1698
        let cookie_request_id = unpack!(connection.status, ConnectionStatus::CookieRequesting, cookie_request_id);
1✔
1699

1700
        let cookie = EncryptedCookie {
1701
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1702
            payload: vec![43; 88],
1✔
1703
        };
1704
        let cookie_response_payload = CookieResponsePayload {
1705
            cookie,
1706
            id: cookie_request_id.overflowing_add(1).0,
1707
        };
1708
        let cookie_response = CookieResponse::new(&dht_precomputed_key, &cookie_response_payload);
1✔
1709

1710
        assert!(net_crypto
6✔
1711
            .handle_cookie_response(&mut connection, &cookie_response)
1✔
1712
            .await
2✔
UNCOV
1713
            .is_err());
×
1714
    }
1715

1716
    async fn handle_cookie_response_test<'a, R, F>(handle_function: F)
4✔
1717
    where
1718
        R: Future<Output = NetCrypto>,
1719
        F: Fn(NetCrypto, CookieResponse, SocketAddr, PublicKey) -> R,
1720
    {
1721
        let mut rng = thread_rng();
4✔
1722
        let (udp_tx, _udp_rx) = mpsc::channel(1);
4✔
1723
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
4✔
1724
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
4✔
1725
        let dht_sk = SecretKey::generate(&mut rng);
2✔
1726
        let dht_pk = dht_sk.public_key();
2✔
1727
        let real_sk = SecretKey::generate(&mut rng);
4✔
1728
        let real_pk = real_sk.public_key();
2✔
1729
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
4✔
1730
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
2✔
1731
            udp_tx,
2✔
1732
            lossless_tx,
2✔
1733
            lossy_tx,
2✔
1734
            dht_pk: dht_pk.clone(),
2✔
1735
            dht_sk: dht_sk.clone(),
2✔
1736
            real_pk: real_pk.clone(),
2✔
1737
            real_sk,
2✔
1738
            precomputed_keys,
2✔
1739
        });
1740

1741
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
4✔
1742
        let peer_real_sk = SecretKey::generate(&mut rng);
2✔
1743
        let peer_real_pk = peer_real_sk.public_key();
2✔
1744
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
2✔
1745
        let mut connection = CryptoConnection::new(
1746
            &dht_precomputed_key,
2✔
1747
            dht_pk,
2✔
1748
            real_pk.clone(),
2✔
1749
            peer_real_pk.clone(),
2✔
1750
            peer_dht_pk.clone(),
2✔
1751
        );
1752

1753
        let cookie_request_id = unpack!(connection.status, ConnectionStatus::CookieRequesting, cookie_request_id);
2✔
1754

1755
        let addr = "127.0.0.1:12345".parse().unwrap();
4✔
1756
        connection.set_udp_addr(addr);
2✔
1757

1758
        net_crypto
8✔
1759
            .connections
×
1760
            .write()
1761
            .await
4✔
1762
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
2✔
1763
        net_crypto
8✔
1764
            .keys_by_addr
×
1765
            .write()
1766
            .await
4✔
1767
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
2✔
1768

1769
        let cookie = EncryptedCookie {
1770
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
2✔
1771
            payload: vec![43; 88],
2✔
1772
        };
1773
        let cookie_response_payload = CookieResponsePayload {
1774
            cookie: cookie.clone(),
2✔
1775
            id: cookie_request_id,
1776
        };
1777
        let cookie_response = CookieResponse::new(&dht_precomputed_key, &cookie_response_payload);
2✔
1778

1779
        let net_crypto = handle_function(net_crypto, cookie_response, addr, peer_dht_pk).await;
2✔
1780

1781
        let connections = net_crypto.connections.read().await;
4✔
1782
        let connection = connections.get(&peer_real_pk).unwrap().read().await.clone();
4✔
1783

1784
        let packet = unpack!(connection.status, ConnectionStatus::HandshakeSending, packet);
2✔
1785
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
4✔
1786
        assert_eq!(packet.cookie, cookie);
4✔
1787

1788
        let payload = packet.get_payload(&SalsaBox::new(&real_pk, &peer_real_sk)).unwrap();
2✔
1789
        assert_eq!(payload.cookie_hash, cookie.hash());
2✔
1790
    }
1791

1792
    #[tokio::test]
6✔
1793
    async fn handle_udp_cookie_response() {
3✔
1794
        async fn test_me(
3✔
1795
            net_crypto: NetCrypto,
1796
            packet: CookieResponse,
1797
            saddr: SocketAddr,
1798
            _pk: PublicKey,
1799
        ) -> NetCrypto {
1800
            net_crypto.handle_udp_cookie_response(&packet, saddr).await.unwrap();
2✔
1801
            net_crypto
1✔
1802
        }
1803

1804
        handle_cookie_response_test(test_me).await;
2✔
1805
    }
1806

1807
    #[tokio::test]
6✔
1808
    async fn handle_tcp_cookie_response() {
3✔
1809
        async fn test_me(
3✔
1810
            net_crypto: NetCrypto,
1811
            packet: CookieResponse,
1812
            _saddr: SocketAddr,
1813
            pk: PublicKey,
1814
        ) -> NetCrypto {
1815
            net_crypto.handle_tcp_cookie_response(&packet, pk).await.unwrap();
2✔
1816
            net_crypto
1✔
1817
        }
1818

1819
        handle_cookie_response_test(test_me).await;
2✔
1820
    }
1821

1822
    #[tokio::test]
6✔
1823
    async fn handle_udp_cookie_response_no_connection() {
3✔
1824
        let mut rng = thread_rng();
2✔
1825
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1826
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1827
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1828
        let dht_sk = SecretKey::generate(&mut rng);
1✔
1829
        let dht_pk = dht_sk.public_key();
1✔
1830
        let real_sk = SecretKey::generate(&mut rng);
2✔
1831
        let real_pk = real_sk.public_key();
1✔
1832
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1833
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1834
            udp_tx,
1✔
1835
            lossless_tx,
1✔
1836
            lossy_tx,
1✔
1837
            dht_pk,
1✔
1838
            dht_sk: dht_sk.clone(),
1✔
1839
            real_pk,
1✔
1840
            real_sk,
1✔
1841
            precomputed_keys,
1✔
1842
        });
1843

1844
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
1845
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1846

1847
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
1848

1849
        let cookie = EncryptedCookie {
1850
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1851
            payload: vec![43; 88],
1✔
1852
        };
1853
        let cookie_response_payload = CookieResponsePayload {
1854
            cookie: cookie.clone(),
1✔
1855
            id: 12345,
1856
        };
1857
        let cookie_response = CookieResponse::new(&dht_precomputed_key, &cookie_response_payload);
1✔
1858

1859
        let res = net_crypto.handle_udp_cookie_response(&cookie_response, addr).await;
2✔
1860
        assert!(res.is_err());
2✔
1861
        assert_eq!(
3✔
1862
            res.err().unwrap(),
1✔
1863
            HandlePacketError::NoUdpConnection {
1✔
1864
                addr: "127.0.0.1:12345".parse().unwrap()
2✔
1865
            }
1866
        );
1867
    }
1868

1869
    #[tokio::test]
6✔
1870
    async fn handle_crypto_handshake_in_cookie_requesting_status() {
3✔
1871
        let mut rng = thread_rng();
2✔
1872
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1873
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1874
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1875
        let dht_sk = SecretKey::generate(&mut rng);
1✔
1876
        let dht_pk = dht_sk.public_key();
1✔
1877
        let real_sk = SecretKey::generate(&mut rng);
2✔
1878
        let real_pk = real_sk.public_key();
1✔
1879
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1880
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1881
            udp_tx,
1✔
1882
            lossless_tx,
1✔
1883
            lossy_tx,
1✔
1884
            dht_pk: dht_pk.clone(),
1✔
1885
            dht_sk: dht_sk.clone(),
1✔
1886
            real_pk: real_pk.clone(),
1✔
1887
            real_sk,
1✔
1888
            precomputed_keys,
1✔
1889
        });
1890

1891
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
1892
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
1893
        let peer_real_pk = peer_real_sk.public_key();
1✔
1894
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
1895
        let mut connection = CryptoConnection::new(
1896
            &dht_precomputed_key,
1✔
1897
            dht_pk,
1✔
1898
            real_pk.clone(),
1✔
1899
            peer_real_pk.clone(),
1✔
1900
            peer_dht_pk.clone(),
1✔
1901
        );
1902

1903
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
1904
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
1905
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
1906
        let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
1907
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
1908
        let cookie = EncryptedCookie {
1909
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1910
            payload: vec![43; 88],
1✔
1911
        };
1912
        let crypto_handshake_payload = CryptoHandshakePayload {
1913
            base_nonce,
1914
            session_pk,
1915
            cookie_hash: our_encrypted_cookie.hash(),
1✔
1916
            cookie: cookie.clone(),
1✔
1917
        };
1918
        let crypto_handshake =
1✔
1919
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
1920

1921
        net_crypto
4✔
1922
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
1923
            .await
2✔
1924
            .unwrap();
1925

1926
        let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
1✔
1927
        assert_eq!(received_nonce, base_nonce);
2✔
1928

1929
        let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
1✔
1930
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
2✔
1931
        assert_eq!(packet.cookie, cookie);
2✔
1932

1933
        let payload = packet.get_payload(&real_precomputed_key).unwrap();
1✔
1934
        assert_eq!(payload.cookie_hash, cookie.hash());
3✔
1935
    }
1936

1937
    #[tokio::test]
6✔
1938
    async fn handle_crypto_handshake_in_not_confirmed_status() {
3✔
1939
        let mut rng = thread_rng();
2✔
1940
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
1941
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
1942
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
1943
        let dht_sk = SecretKey::generate(&mut rng);
1✔
1944
        let dht_pk = dht_sk.public_key();
1✔
1945
        let real_sk = SecretKey::generate(&mut rng);
1✔
1946
        let real_pk = real_sk.public_key();
1✔
1947
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
1948
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
1949
            udp_tx,
1✔
1950
            lossless_tx,
1✔
1951
            lossy_tx,
1✔
1952
            dht_pk,
1✔
1953
            dht_sk: dht_sk.clone(),
1✔
1954
            real_pk: real_pk.clone(),
1✔
1955
            real_sk: real_sk.clone(),
1✔
1956
            precomputed_keys,
1✔
1957
        });
1958

1959
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
1960
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
1961
        let peer_real_pk = peer_real_sk.public_key();
1✔
1962
        let cookie = EncryptedCookie {
1963
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1964
            payload: vec![42; 88],
1✔
1965
        };
1966
        let mut connection = CryptoConnection::new_not_confirmed(
1967
            &real_sk,
1✔
1968
            peer_real_pk.clone(),
1✔
1969
            peer_dht_pk.clone(),
1✔
1970
            [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
1971
            SecretKey::generate(&mut rng).public_key(),
1✔
1972
            cookie.clone(),
1✔
1973
            &net_crypto.symmetric_key,
1✔
1974
        );
1975

1976
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
1977
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
1978
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
1979
        let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
1980
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
1981
        let other_cookie = EncryptedCookie {
1982
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
1983
            payload: vec![43; 88],
1✔
1984
        };
1985
        let crypto_handshake_payload = CryptoHandshakePayload {
1986
            base_nonce,
1987
            session_pk,
1988
            cookie_hash: our_encrypted_cookie.hash(),
1✔
1989
            cookie: other_cookie,
1990
        };
1991
        let crypto_handshake =
1✔
1992
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
1993

1994
        net_crypto
4✔
1995
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
1996
            .await
2✔
1997
            .unwrap();
1998

1999
        // Nonce should be taken from the packet
2000
        let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
1✔
2001
        assert_eq!(received_nonce, base_nonce);
2✔
2002

2003
        // cookie should not be updated
2004
        let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
1✔
2005
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
2✔
2006
        assert_eq!(packet.cookie, cookie);
2✔
2007

2008
        let payload = packet.get_payload(&real_precomputed_key).unwrap();
1✔
2009
        assert_eq!(payload.cookie_hash, cookie.hash());
3✔
2010
    }
2011

2012
    #[tokio::test]
6✔
2013
    async fn handle_crypto_handshake_invalid_status() {
3✔
2014
        let mut rng = thread_rng();
2✔
2015
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2016
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2017
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2018
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2019
        let dht_pk = dht_sk.public_key();
1✔
2020
        let real_sk = SecretKey::generate(&mut rng);
2✔
2021
        let real_pk = real_sk.public_key();
1✔
2022
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2023
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2024
            udp_tx,
1✔
2025
            lossless_tx,
1✔
2026
            lossy_tx,
1✔
2027
            dht_pk: dht_pk.clone(),
1✔
2028
            dht_sk: dht_sk.clone(),
1✔
2029
            real_pk: real_pk.clone(),
1✔
2030
            real_sk,
1✔
2031
            precomputed_keys,
1✔
2032
        });
2033

2034
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2035
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
2036
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2037
        let mut connection = CryptoConnection::new(
2038
            &dht_precomputed_key,
1✔
2039
            dht_pk,
1✔
2040
            real_pk,
1✔
2041
            peer_real_pk.clone(),
1✔
2042
            peer_dht_pk.clone(),
1✔
2043
        );
2044

2045
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
2✔
2046
        let session_sk = SecretKey::generate(&mut rng);
1✔
2047
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
2048
        connection.status = ConnectionStatus::Established {
2✔
2049
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
2050
            received_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
2051
            session_precomputed_key,
1✔
2052
        };
2053

2054
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
2055
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2056
        let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
2057
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2058
        let cookie = EncryptedCookie {
2059
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2060
            payload: vec![43; 88],
1✔
2061
        };
2062
        let crypto_handshake_payload = CryptoHandshakePayload {
2063
            base_nonce,
2064
            session_pk,
2065
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2066
            cookie,
2067
        };
2068
        let crypto_handshake =
1✔
2069
            CryptoHandshake::new(&dht_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2070

2071
        let res = net_crypto
3✔
2072
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
2073
            .await;
2✔
2074
        assert!(res.is_err());
2✔
2075
        assert_eq!(res.err().unwrap(), HandlePacketError::InvalidState);
2✔
2076
    }
2077

2078
    #[tokio::test]
6✔
2079
    async fn handle_crypto_handshake_invalid_hash() {
3✔
2080
        let mut rng = thread_rng();
2✔
2081
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2082
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2083
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2084
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2085
        let dht_pk = dht_sk.public_key();
1✔
2086
        let real_sk = SecretKey::generate(&mut rng);
2✔
2087
        let real_pk = real_sk.public_key();
1✔
2088
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2089
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2090
            udp_tx,
1✔
2091
            lossless_tx,
1✔
2092
            lossy_tx,
1✔
2093
            dht_pk: dht_pk.clone(),
1✔
2094
            dht_sk: dht_sk.clone(),
1✔
2095
            real_pk: real_pk.clone(),
1✔
2096
            real_sk,
1✔
2097
            precomputed_keys,
1✔
2098
        });
2099

2100
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2101
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2102
        let peer_real_pk = peer_real_sk.public_key();
1✔
2103
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2104
        let mut connection = CryptoConnection::new(
2105
            &dht_precomputed_key,
1✔
2106
            dht_pk,
1✔
2107
            real_pk.clone(),
1✔
2108
            peer_real_pk.clone(),
1✔
2109
            peer_dht_pk.clone(),
1✔
2110
        );
2111

2112
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2113
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2114
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2115
        let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
2116
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2117
        let cookie = EncryptedCookie {
2118
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2119
            payload: vec![43; 88],
1✔
2120
        };
2121
        let crypto_handshake_payload = CryptoHandshakePayload {
2122
            base_nonce,
2123
            session_pk,
2124
            cookie_hash: cookie.hash(),
1✔
2125
            cookie,
2126
        };
2127
        let crypto_handshake =
1✔
2128
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2129

2130
        let res = net_crypto
3✔
2131
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
2132
            .await;
2✔
2133
        assert!(res.is_err());
2✔
2134
        assert_eq!(res.err().unwrap(), HandlePacketError::BadSha512);
2✔
2135
    }
2136

2137
    #[tokio::test]
6✔
2138
    async fn handle_crypto_handshake_timed_out_cookie() {
3✔
2139
        let mut rng = thread_rng();
2✔
2140
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2141
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2142
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2143
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2144
        let dht_pk = dht_sk.public_key();
1✔
2145
        let real_sk = SecretKey::generate(&mut rng);
2✔
2146
        let real_pk = real_sk.public_key();
1✔
2147
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2148
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2149
            udp_tx,
1✔
2150
            lossless_tx,
1✔
2151
            lossy_tx,
1✔
2152
            dht_pk: dht_pk.clone(),
1✔
2153
            dht_sk: dht_sk.clone(),
1✔
2154
            real_pk: real_pk.clone(),
1✔
2155
            real_sk,
1✔
2156
            precomputed_keys,
1✔
2157
        });
2158

2159
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2160
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2161
        let peer_real_pk = peer_real_sk.public_key();
1✔
2162
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2163
        let mut connection = CryptoConnection::new(
2164
            &dht_precomputed_key,
1✔
2165
            dht_pk,
1✔
2166
            real_pk.clone(),
1✔
2167
            peer_real_pk.clone(),
1✔
2168
            peer_dht_pk.clone(),
1✔
2169
        );
2170

2171
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2172
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2173
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2174
        let mut our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
2175
        our_cookie.time -= COOKIE_TIMEOUT + 1;
1✔
2176
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2177
        let cookie = EncryptedCookie {
2178
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2179
            payload: vec![43; 88],
1✔
2180
        };
2181
        let crypto_handshake_payload = CryptoHandshakePayload {
2182
            base_nonce,
2183
            session_pk,
2184
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2185
            cookie,
2186
        };
2187
        let crypto_handshake =
1✔
2188
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2189

2190
        let res = net_crypto
3✔
2191
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
2192
            .await;
2✔
2193
        assert!(res.is_err());
2✔
2194
        assert_eq!(res.err().unwrap(), HandlePacketError::CookieTimedOut);
2✔
2195
    }
2196

2197
    #[tokio::test]
6✔
2198
    async fn handle_crypto_handshake_invalid_peer_real_pk() {
3✔
2199
        let mut rng = thread_rng();
2✔
2200
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2201
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2202
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2203
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2204
        let dht_pk = dht_sk.public_key();
1✔
2205
        let real_sk = SecretKey::generate(&mut rng);
2✔
2206
        let real_pk = real_sk.public_key();
1✔
2207
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2208
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2209
            udp_tx,
1✔
2210
            lossless_tx,
1✔
2211
            lossy_tx,
1✔
2212
            dht_pk: dht_pk.clone(),
1✔
2213
            dht_sk: dht_sk.clone(),
1✔
2214
            real_pk: real_pk.clone(),
1✔
2215
            real_sk,
1✔
2216
            precomputed_keys,
1✔
2217
        });
2218

2219
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2220
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
2221
        let another_peer_real_sk = SecretKey::generate(&mut rng);
1✔
2222
        let another_peer_real_pk = another_peer_real_sk.public_key();
1✔
2223
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2224
        let mut connection = CryptoConnection::new(
2225
            &dht_precomputed_key,
1✔
2226
            dht_pk,
1✔
2227
            real_pk.clone(),
1✔
2228
            peer_real_pk,
1✔
2229
            peer_dht_pk.clone(),
1✔
2230
        );
2231

2232
        let real_precomputed_key = SalsaBox::new(&real_pk, &another_peer_real_sk);
1✔
2233
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2234
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2235
        let our_cookie = Cookie::new(another_peer_real_pk, peer_dht_pk);
1✔
2236
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2237
        let cookie = EncryptedCookie {
2238
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2239
            payload: vec![43; 88],
1✔
2240
        };
2241
        let crypto_handshake_payload = CryptoHandshakePayload {
2242
            base_nonce,
2243
            session_pk,
2244
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2245
            cookie,
2246
        };
2247
        let crypto_handshake =
1✔
2248
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2249

2250
        let res = net_crypto
3✔
2251
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
2252
            .await;
2✔
2253
        assert!(res.is_err());
2✔
2254
        assert_eq!(res.err().unwrap(), HandlePacketError::InvalidRealPk);
2✔
2255
    }
2256

2257
    #[tokio::test]
6✔
2258
    async fn handle_crypto_handshake_invalid_peer_dht_pk() {
3✔
2259
        let mut rng = thread_rng();
2✔
2260
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2261
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2262
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2263
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2264
        let dht_pk = dht_sk.public_key();
1✔
2265
        let real_sk = SecretKey::generate(&mut rng);
2✔
2266
        let real_pk = real_sk.public_key();
1✔
2267
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2268
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2269
            udp_tx,
1✔
2270
            lossless_tx,
1✔
2271
            lossy_tx,
1✔
2272
            dht_pk: dht_pk.clone(),
1✔
2273
            dht_sk: dht_sk.clone(),
1✔
2274
            real_pk: real_pk.clone(),
1✔
2275
            real_sk,
1✔
2276
            precomputed_keys,
1✔
2277
        });
2278

2279
        let (dht_pk_tx, dht_pk_rx) = mpsc::unbounded();
2✔
2280
        net_crypto.set_dht_pk_sink(dht_pk_tx).await;
2✔
2281

2282
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
2283
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2284
        let peer_real_pk = peer_real_sk.public_key();
1✔
2285
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2286
        let mut connection = CryptoConnection::new(
2287
            &dht_precomputed_key,
1✔
2288
            dht_pk.clone(),
1✔
2289
            real_pk.clone(),
1✔
2290
            peer_real_pk.clone(),
1✔
2291
            peer_dht_pk,
1✔
2292
        );
2293

2294
        let new_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2295

2296
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2297
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2298
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2299
        let our_cookie = Cookie::new(peer_real_pk.clone(), new_dht_pk.clone());
1✔
2300
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2301
        let cookie = EncryptedCookie {
2302
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2303
            payload: vec![43; 88],
1✔
2304
        };
2305
        let crypto_handshake_payload = CryptoHandshakePayload {
2306
            base_nonce,
2307
            session_pk,
2308
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2309
            cookie,
2310
        };
2311
        let crypto_handshake =
1✔
2312
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2313

2314
        let res = net_crypto
3✔
2315
            .handle_crypto_handshake(&mut connection, &crypto_handshake)
1✔
2316
            .await;
2✔
2317
        assert!(res.is_err());
2✔
2318
        assert_eq!(res.err().unwrap(), HandlePacketError::InvalidDhtPk);
1✔
2319

2320
        let (keys, _dht_pk_rx) = dht_pk_rx.into_future().await;
1✔
2321
        let (received_real_pk, received_dht_pk) = keys.unwrap();
2✔
2322

2323
        assert_eq!(received_real_pk, peer_real_pk);
1✔
2324
        assert_eq!(received_dht_pk, new_dht_pk);
2✔
2325
    }
2326

2327
    async fn handle_crypto_handshake_test<'a, R, F>(handle_function: F)
4✔
2328
    where
2329
        R: Future<Output = NetCrypto>,
2330
        F: FnOnce(NetCrypto, CryptoHandshake, SocketAddr, PublicKey) -> R,
2331
    {
2332
        let mut rng = thread_rng();
4✔
2333
        let (udp_tx, _udp_rx) = mpsc::channel(1);
4✔
2334
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
4✔
2335
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
4✔
2336
        let dht_sk = SecretKey::generate(&mut rng);
2✔
2337
        let dht_pk = dht_sk.public_key();
2✔
2338
        let real_sk = SecretKey::generate(&mut rng);
4✔
2339
        let real_pk = real_sk.public_key();
2✔
2340
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
4✔
2341
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
2✔
2342
            udp_tx,
2✔
2343
            lossless_tx,
2✔
2344
            lossy_tx,
2✔
2345
            dht_pk: dht_pk.clone(),
2✔
2346
            dht_sk: dht_sk.clone(),
2✔
2347
            real_pk: real_pk.clone(),
2✔
2348
            real_sk,
2✔
2349
            precomputed_keys,
2✔
2350
        });
2351

2352
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
4✔
2353
        let peer_real_sk = SecretKey::generate(&mut rng);
2✔
2354
        let peer_real_pk = peer_real_sk.public_key();
2✔
2355
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
2✔
2356
        let mut connection = CryptoConnection::new(
2357
            &dht_precomputed_key,
2✔
2358
            dht_pk,
2✔
2359
            real_pk.clone(),
2✔
2360
            peer_real_pk.clone(),
2✔
2361
            peer_dht_pk.clone(),
2✔
2362
        );
2363

2364
        let addr = "127.0.0.1:12345".parse().unwrap();
4✔
2365
        connection.set_udp_addr(addr);
2✔
2366

2367
        net_crypto
8✔
2368
            .connections
×
2369
            .write()
2370
            .await
4✔
2371
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
2✔
2372
        net_crypto
8✔
2373
            .keys_by_addr
×
2374
            .write()
2375
            .await
4✔
2376
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
2✔
2377

2378
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
2✔
2379
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
4✔
2380
        let session_pk = SecretKey::generate(&mut rng).public_key();
2✔
2381
        let our_cookie = Cookie::new(peer_real_pk.clone(), peer_dht_pk.clone());
2✔
2382
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
4✔
2383
        let cookie = EncryptedCookie {
2384
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
2✔
2385
            payload: vec![43; 88],
2✔
2386
        };
2387
        let crypto_handshake_payload = CryptoHandshakePayload {
2388
            base_nonce,
2389
            session_pk,
2390
            cookie_hash: our_encrypted_cookie.hash(),
2✔
2391
            cookie: cookie.clone(),
2✔
2392
        };
2393
        let crypto_handshake =
2✔
2394
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
×
2395

2396
        let net_crypto = handle_function(net_crypto, crypto_handshake, addr, peer_dht_pk).await;
2✔
2397

2398
        let connections = net_crypto.connections.read().await;
4✔
2399
        let connection = connections.get(&peer_real_pk).unwrap().read().await.clone();
4✔
2400

2401
        let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
2✔
2402
        assert_eq!(received_nonce, base_nonce);
4✔
2403

2404
        let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
2✔
2405
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
4✔
2406
        assert_eq!(packet.cookie, cookie);
4✔
2407

2408
        let payload = packet.get_payload(&real_precomputed_key).unwrap();
2✔
2409
        assert_eq!(payload.cookie_hash, cookie.hash());
4✔
2410
    }
2411

2412
    #[tokio::test]
6✔
2413
    async fn handle_udp_crypto_handshake() {
3✔
2414
        async fn test_me(
3✔
2415
            net_crypto: NetCrypto,
2416
            packet: CryptoHandshake,
2417
            saddr: SocketAddr,
2418
            _pk: PublicKey,
2419
        ) -> NetCrypto {
2420
            net_crypto.handle_udp_crypto_handshake(&packet, saddr).await.unwrap();
2✔
2421
            net_crypto
1✔
2422
        }
2423

2424
        handle_crypto_handshake_test(test_me).await;
2✔
2425
    }
2426

2427
    #[tokio::test]
6✔
2428
    async fn handle_tcp_crypto_handshake() {
3✔
2429
        async fn test_me(
3✔
2430
            net_crypto: NetCrypto,
2431
            packet: CryptoHandshake,
2432
            _saddr: SocketAddr,
2433
            pk: PublicKey,
2434
        ) -> NetCrypto {
2435
            net_crypto.handle_tcp_crypto_handshake(&packet, pk).await.unwrap();
2✔
2436
            net_crypto
1✔
2437
        }
2438

2439
        handle_crypto_handshake_test(test_me).await;
2✔
2440
    }
2441

2442
    #[tokio::test]
6✔
2443
    async fn handle_udp_crypto_handshake_new_connection() {
3✔
2444
        let mut rng = thread_rng();
2✔
2445
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2446
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2447
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2448
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2449
        let dht_pk = dht_sk.public_key();
1✔
2450
        let real_sk = SecretKey::generate(&mut rng);
2✔
2451
        let real_pk = real_sk.public_key();
1✔
2452
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2453
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2454
            udp_tx,
1✔
2455
            lossless_tx,
1✔
2456
            lossy_tx,
1✔
2457
            dht_pk,
1✔
2458
            dht_sk: dht_sk.clone(),
1✔
2459
            real_pk: real_pk.clone(),
1✔
2460
            real_sk,
1✔
2461
            precomputed_keys,
1✔
2462
        });
2463

2464
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2465
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2466
        let peer_real_pk = peer_real_sk.public_key();
1✔
2467

2468
        net_crypto.add_friend(peer_real_pk.clone()).await;
1✔
2469

2470
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2471
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2472
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2473
        let our_cookie = Cookie::new(peer_real_pk.clone(), peer_dht_pk);
1✔
2474
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2475
        let cookie = EncryptedCookie {
2476
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2477
            payload: vec![43; 88],
1✔
2478
        };
2479
        let crypto_handshake_payload = CryptoHandshakePayload {
2480
            base_nonce,
2481
            session_pk,
2482
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2483
            cookie: cookie.clone(),
1✔
2484
        };
2485
        let crypto_handshake =
1✔
2486
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2487

2488
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
2489

2490
        net_crypto
4✔
2491
            .handle_udp_crypto_handshake(&crypto_handshake, addr)
1✔
2492
            .await
2✔
2493
            .unwrap();
2494

2495
        let connections = net_crypto.connections.read().await;
1✔
2496
        let connection = connections.get(&peer_real_pk).unwrap().read().await.clone();
2✔
2497

2498
        assert_eq!(connection.get_udp_addr_v4(), Some(addr));
1✔
2499

2500
        let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
1✔
2501
        assert_eq!(received_nonce, base_nonce);
2✔
2502

2503
        let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
1✔
2504
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
2✔
2505
        assert_eq!(packet.cookie, cookie);
2✔
2506

2507
        let payload = packet.get_payload(&real_precomputed_key).unwrap();
1✔
2508
        assert_eq!(payload.cookie_hash, cookie.hash());
3✔
2509
    }
2510

2511
    #[tokio::test]
6✔
2512
    async fn handle_udp_crypto_handshake_new_address_new_dht_pk() {
3✔
2513
        let mut rng = thread_rng();
2✔
2514
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
2515
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2516
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2517
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2518
        let dht_pk = dht_sk.public_key();
1✔
2519
        let real_sk = SecretKey::generate(&mut rng);
2✔
2520
        let real_pk = real_sk.public_key();
1✔
2521
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2522
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2523
            udp_tx,
1✔
2524
            lossless_tx,
1✔
2525
            lossy_tx,
1✔
2526
            dht_pk: dht_pk.clone(),
1✔
2527
            dht_sk: dht_sk.clone(),
1✔
2528
            real_pk: real_pk.clone(),
1✔
2529
            real_sk,
1✔
2530
            precomputed_keys,
1✔
2531
        });
2532

2533
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2534
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2535
        let peer_real_pk = peer_real_sk.public_key();
1✔
2536

2537
        net_crypto.add_friend(peer_real_pk.clone()).await;
1✔
2538

2539
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2540
        let mut connection = CryptoConnection::new(
2541
            &dht_precomputed_key,
1✔
2542
            dht_pk,
1✔
2543
            real_pk.clone(),
1✔
2544
            peer_real_pk.clone(),
1✔
2545
            peer_dht_pk,
1✔
2546
        );
2547

2548
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2549
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
2550
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2551
        let session_sk = SecretKey::generate(&mut rng);
1✔
2552
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
2553
        connection.status = ConnectionStatus::Established {
1✔
2554
            sent_nonce,
1✔
2555
            received_nonce,
1✔
2556
            session_precomputed_key: session_precomputed_key.clone(),
1✔
2557
        };
2558

2559
        let addr = "127.0.0.1:12345".parse().unwrap();
1✔
2560
        connection.set_udp_addr(addr);
1✔
2561

2562
        net_crypto
4✔
2563
            .connections
2564
            .write()
2565
            .await
2✔
2566
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
2567
        net_crypto
4✔
2568
            .keys_by_addr
2569
            .write()
2570
            .await
2✔
2571
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
1✔
2572

2573
        let new_peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
2574
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2575
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2576
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2577
        let our_cookie = Cookie::new(peer_real_pk.clone(), new_peer_dht_pk.clone());
1✔
2578
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2579
        let cookie = EncryptedCookie {
2580
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2581
            payload: vec![43; 88],
1✔
2582
        };
2583
        let crypto_handshake_payload = CryptoHandshakePayload {
2584
            base_nonce,
2585
            session_pk,
2586
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2587
            cookie: cookie.clone(),
1✔
2588
        };
2589
        let crypto_handshake =
1✔
2590
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2591

2592
        let new_addr = "127.0.0.2:12345".parse().unwrap();
2✔
2593
        net_crypto
4✔
2594
            .handle_udp_crypto_handshake(&crypto_handshake, new_addr)
1✔
2595
            .await
2✔
2596
            .unwrap();
2597

2598
        // the old connection should be replaced with the new one
2599

2600
        let connections = net_crypto.connections.read().await;
1✔
2601
        let connection = connections.get(&peer_real_pk).unwrap().read().await.clone();
2✔
2602

2603
        assert_eq!(connection.peer_dht_pk, new_peer_dht_pk);
1✔
2604
        assert_eq!(connection.get_udp_addr_v4(), Some(new_addr));
1✔
2605

2606
        let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
1✔
2607
        assert_eq!(received_nonce, base_nonce);
2✔
2608

2609
        let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
1✔
2610
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
2✔
2611
        assert_eq!(packet.cookie, cookie);
2✔
2612

2613
        let payload = packet.get_payload(&real_precomputed_key).unwrap();
1✔
2614
        assert_eq!(payload.cookie_hash, cookie.hash());
2✔
2615

2616
        assert!(!net_crypto
4✔
2617
            .keys_by_addr
2618
            .read()
2619
            .await
2✔
2620
            .contains_key(&(addr.ip(), addr.port())));
1✔
2621
        assert!(net_crypto
4✔
2622
            .keys_by_addr
2623
            .read()
2624
            .await
2✔
2625
            .contains_key(&(new_addr.ip(), new_addr.port())));
1✔
2626

2627
        // the old connection should be killed
2628

2629
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
2630
        let (received, addr_to_send) = received.unwrap();
2✔
2631

2632
        assert_eq!(addr_to_send, addr);
2✔
2633

2634
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
2635
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
2636
        assert_eq!(payload.buffer_start, 0);
1✔
2637
        assert_eq!(payload.packet_number, 0);
1✔
2638
        assert_eq!(payload.data, vec![PACKET_ID_KILL]);
2✔
2639
    }
2640

2641
    #[tokio::test]
6✔
2642
    async fn handle_udp_crypto_handshake_new_address_old_dht_pk() {
3✔
2643
        let mut rng = thread_rng();
2✔
2644
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2645
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2646
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2647
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2648
        let dht_pk = dht_sk.public_key();
1✔
2649
        let real_sk = SecretKey::generate(&mut rng);
2✔
2650
        let real_pk = real_sk.public_key();
1✔
2651
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2652
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2653
            udp_tx,
1✔
2654
            lossless_tx,
1✔
2655
            lossy_tx,
1✔
2656
            dht_pk: dht_pk.clone(),
1✔
2657
            dht_sk: dht_sk.clone(),
1✔
2658
            real_pk: real_pk.clone(),
1✔
2659
            real_sk,
1✔
2660
            precomputed_keys,
1✔
2661
        });
2662

2663
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2664
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2665
        let peer_real_pk = peer_real_sk.public_key();
1✔
2666

2667
        net_crypto.add_friend(peer_real_pk.clone()).await;
1✔
2668

2669
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2670
        let mut connection = CryptoConnection::new(
2671
            &dht_precomputed_key,
1✔
2672
            dht_pk,
1✔
2673
            real_pk.clone(),
1✔
2674
            peer_real_pk.clone(),
1✔
2675
            peer_dht_pk.clone(),
1✔
2676
        );
2677

2678
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
2679
        connection.set_udp_addr(addr);
1✔
2680

2681
        net_crypto
4✔
2682
            .connections
2683
            .write()
2684
            .await
2✔
2685
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
2686
        net_crypto
4✔
2687
            .keys_by_addr
2688
            .write()
2689
            .await
2✔
2690
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
1✔
2691

2692
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2693
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2694
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2695
        let our_cookie = Cookie::new(peer_real_pk.clone(), peer_dht_pk);
1✔
2696
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2697
        let cookie = EncryptedCookie {
2698
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2699
            payload: vec![43; 88],
1✔
2700
        };
2701
        let crypto_handshake_payload = CryptoHandshakePayload {
2702
            base_nonce,
2703
            session_pk,
2704
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2705
            cookie: cookie.clone(),
1✔
2706
        };
2707
        let crypto_handshake =
1✔
2708
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2709

2710
        let new_addr = "127.0.0.2:12345".parse().unwrap();
2✔
2711
        net_crypto
4✔
2712
            .handle_udp_crypto_handshake(&crypto_handshake, new_addr)
1✔
2713
            .await
2✔
2714
            .unwrap();
2715

2716
        // the old connection should be updated with a new address
2717

2718
        let connections = net_crypto.connections.read().await;
1✔
2719
        let connection = connections.get(&peer_real_pk).unwrap().read().await.clone();
2✔
2720

2721
        assert_eq!(connection.get_udp_addr_v4(), Some(new_addr));
1✔
2722

2723
        let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
1✔
2724
        assert_eq!(received_nonce, base_nonce);
2✔
2725

2726
        let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
1✔
2727
        let packet = unpack!(packet.packet, StatusPacket::CryptoHandshake);
2✔
2728
        assert_eq!(packet.cookie, cookie);
2✔
2729

2730
        let payload = packet.get_payload(&real_precomputed_key).unwrap();
1✔
2731
        assert_eq!(payload.cookie_hash, cookie.hash());
2✔
2732

2733
        assert!(!net_crypto
4✔
2734
            .keys_by_addr
2735
            .read()
2736
            .await
2✔
2737
            .contains_key(&(addr.ip(), addr.port())));
1✔
2738
        assert!(net_crypto
6✔
2739
            .keys_by_addr
2740
            .read()
2741
            .await
2✔
2742
            .contains_key(&(new_addr.ip(), new_addr.port())));
1✔
2743
    }
2744

2745
    #[tokio::test]
6✔
2746
    async fn handle_udp_crypto_handshake_new_address_old_dht_pk_established() {
3✔
2747
        let mut rng = thread_rng();
2✔
2748
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2749
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2750
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2751
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2752
        let dht_pk = dht_sk.public_key();
1✔
2753
        let real_sk = SecretKey::generate(&mut rng);
2✔
2754
        let real_pk = real_sk.public_key();
1✔
2755
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2756
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2757
            udp_tx,
1✔
2758
            lossless_tx,
1✔
2759
            lossy_tx,
1✔
2760
            dht_pk: dht_pk.clone(),
1✔
2761
            dht_sk: dht_sk.clone(),
1✔
2762
            real_pk: real_pk.clone(),
1✔
2763
            real_sk,
1✔
2764
            precomputed_keys,
1✔
2765
        });
2766

2767
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2768
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2769
        let peer_real_pk = peer_real_sk.public_key();
1✔
2770

2771
        net_crypto.add_friend(peer_real_pk.clone()).await;
1✔
2772

2773
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2774
        let mut connection = CryptoConnection::new(
2775
            &dht_precomputed_key,
1✔
2776
            dht_pk,
1✔
2777
            real_pk.clone(),
1✔
2778
            peer_real_pk.clone(),
1✔
2779
            peer_dht_pk.clone(),
1✔
2780
        );
2781

2782
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2783
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
2784
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2785
        let session_sk = SecretKey::generate(&mut rng);
1✔
2786
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
2787
        connection.status = ConnectionStatus::Established {
1✔
2788
            sent_nonce,
1✔
2789
            received_nonce,
1✔
2790
            session_precomputed_key: session_precomputed_key.clone(),
1✔
2791
        };
2792

2793
        let addr = "127.0.0.1:12345".parse().unwrap();
1✔
2794
        connection.set_udp_addr(addr);
1✔
2795

2796
        net_crypto
4✔
2797
            .connections
2798
            .write()
2799
            .await
2✔
2800
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
2801
        net_crypto
4✔
2802
            .keys_by_addr
2803
            .write()
2804
            .await
2✔
2805
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
1✔
2806

2807
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2808
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2809
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2810
        let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
2811
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2812
        let cookie = EncryptedCookie {
2813
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2814
            payload: vec![43; 88],
1✔
2815
        };
2816
        let crypto_handshake_payload = CryptoHandshakePayload {
2817
            base_nonce,
2818
            session_pk,
2819
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2820
            cookie: cookie.clone(),
1✔
2821
        };
2822
        let crypto_handshake =
1✔
2823
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2824

2825
        let new_addr = "127.0.0.2:12345".parse().unwrap();
2✔
2826
        let error = net_crypto
4✔
2827
            .handle_udp_crypto_handshake(&crypto_handshake, new_addr)
1✔
2828
            .await
2✔
2829
            .err()
2830
            .unwrap();
2831
        assert_eq!(error, HandlePacketError::UnexpectedCryptoHandshake);
3✔
2832
    }
2833

2834
    #[tokio::test]
6✔
2835
    async fn handle_udp_crypto_handshake_unexpected() {
3✔
2836
        let mut rng = thread_rng();
2✔
2837
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2838
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2839
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
2840
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2841
        let dht_pk = dht_sk.public_key();
1✔
2842
        let real_sk = SecretKey::generate(&mut rng);
2✔
2843
        let real_pk = real_sk.public_key();
1✔
2844
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2845
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2846
            udp_tx,
1✔
2847
            lossless_tx,
1✔
2848
            lossy_tx,
1✔
2849
            dht_pk,
1✔
2850
            dht_sk: dht_sk.clone(),
1✔
2851
            real_pk: real_pk.clone(),
1✔
2852
            real_sk,
1✔
2853
            precomputed_keys,
1✔
2854
        });
2855

2856
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2857
        let peer_real_sk = SecretKey::generate(&mut rng);
1✔
2858
        let peer_real_pk = peer_real_sk.public_key();
1✔
2859

2860
        let real_precomputed_key = SalsaBox::new(&real_pk, &peer_real_sk);
1✔
2861
        let base_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2862
        let session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2863
        let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
1✔
2864
        let our_encrypted_cookie = EncryptedCookie::new(&mut rng, &net_crypto.symmetric_key, &our_cookie);
2✔
2865
        let cookie = EncryptedCookie {
2866
            nonce: [42; xsalsa20poly1305::NONCE_SIZE],
1✔
2867
            payload: vec![43; 88],
1✔
2868
        };
2869
        let crypto_handshake_payload = CryptoHandshakePayload {
2870
            base_nonce,
2871
            session_pk,
2872
            cookie_hash: our_encrypted_cookie.hash(),
1✔
2873
            cookie: cookie.clone(),
1✔
2874
        };
2875
        let crypto_handshake =
1✔
2876
            CryptoHandshake::new(&real_precomputed_key, &crypto_handshake_payload, our_encrypted_cookie);
2877

2878
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
2879

2880
        let error = net_crypto
4✔
2881
            .handle_udp_crypto_handshake(&crypto_handshake, addr)
1✔
2882
            .await
2✔
2883
            .err()
2884
            .unwrap();
2885

2886
        assert_eq!(error, HandlePacketError::UnexpectedCryptoHandshake);
3✔
2887
    }
2888

2889
    #[tokio::test]
6✔
2890
    async fn handle_crypto_data_lossy() {
3✔
2891
        let mut rng = thread_rng();
2✔
2892
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2893
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2894
        let (lossy_tx, lossy_rx) = mpsc::unbounded();
2✔
2895
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2896
        let dht_pk = dht_sk.public_key();
1✔
2897
        let real_sk = SecretKey::generate(&mut rng);
2✔
2898
        let real_pk = real_sk.public_key();
1✔
2899
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2900
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2901
            udp_tx,
1✔
2902
            lossless_tx,
1✔
2903
            lossy_tx,
1✔
2904
            dht_pk: dht_pk.clone(),
1✔
2905
            dht_sk: dht_sk.clone(),
1✔
2906
            real_pk: real_pk.clone(),
1✔
2907
            real_sk,
1✔
2908
            precomputed_keys,
1✔
2909
        });
2910

2911
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2912
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
2913
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2914
        let mut connection =
2✔
2915
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
2916

2917
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2918
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2919
        let session_sk = SecretKey::generate(&mut rng);
1✔
2920
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
2921
        connection.status = ConnectionStatus::Established {
1✔
2922
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
2923
            received_nonce,
1✔
2924
            session_precomputed_key: session_precomputed_key.clone(),
1✔
2925
        };
2926

2927
        let crypto_data_payload = CryptoDataPayload {
2928
            buffer_start: 0,
2929
            packet_number: 0,
2930
            data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3],
1✔
2931
        };
2932
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
2933

2934
        net_crypto
4✔
2935
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
2936
            .await
2✔
2937
            .unwrap();
2938

2939
        // The diff between nonces is not bigger than the threshold so received
2940
        // nonce shouldn't be changed
2941
        assert_eq!(
2✔
2942
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
2943
            received_nonce
2944
        );
2945

2946
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
2947
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
2948
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
2949
        assert_eq!(connection.send_array.buffer_end, 0);
1✔
2950

2951
        let (received, _lossy_rx) = lossy_rx.into_future().await;
1✔
2952
        let (received_peer_real_pk, received_data) = received.unwrap();
2✔
2953
        assert_eq!(received_peer_real_pk, peer_real_pk);
2✔
2954
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
2✔
2955
    }
2956

2957
    #[tokio::test]
6✔
2958
    async fn handle_crypto_data_lossy_increment_nonce() {
3✔
2959
        let mut rng = thread_rng();
2✔
2960
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
2961
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
2962
        let (lossy_tx, lossy_rx) = mpsc::unbounded();
2✔
2963
        let dht_sk = SecretKey::generate(&mut rng);
1✔
2964
        let dht_pk = dht_sk.public_key();
1✔
2965
        let real_sk = SecretKey::generate(&mut rng);
2✔
2966
        let real_pk = real_sk.public_key();
1✔
2967
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
2968
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
2969
            udp_tx,
1✔
2970
            lossless_tx,
1✔
2971
            lossy_tx,
1✔
2972
            dht_pk: dht_pk.clone(),
1✔
2973
            dht_sk: dht_sk.clone(),
1✔
2974
            real_pk: real_pk.clone(),
1✔
2975
            real_sk,
1✔
2976
            precomputed_keys,
1✔
2977
        });
2978

2979
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
2980
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
2981
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
2982
        let mut connection =
2✔
2983
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
2984

2985
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
2986
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
2987
        let session_sk = SecretKey::generate(&mut rng);
1✔
2988
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
2989
        connection.status = ConnectionStatus::Established {
1✔
2990
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
2991
            received_nonce,
1✔
2992
            session_precomputed_key: session_precomputed_key.clone(),
1✔
2993
        };
2994

2995
        // Make the diff between nonces is bigger than the threshold
2996
        let mut packet_nonce = received_nonce;
1✔
2997
        increment_nonce_number(&mut packet_nonce, 2 * NONCE_DIFF_THRESHOLD + 1);
1✔
2998

2999
        let crypto_data_payload = CryptoDataPayload {
3000
            buffer_start: 0,
3001
            packet_number: 0,
3002
            data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3],
1✔
3003
        };
3004
        let crypto_data = CryptoData::new(&session_precomputed_key, packet_nonce, &crypto_data_payload);
1✔
3005

3006
        net_crypto
4✔
3007
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3008
            .await
2✔
3009
            .unwrap();
3010

3011
        // The diff between nonces is bigger than the threshold so received
3012
        // nonce should be changed increased
3013
        let mut expected_nonce = received_nonce;
1✔
3014
        increment_nonce_number(&mut expected_nonce, NONCE_DIFF_THRESHOLD);
1✔
3015
        assert_eq!(
2✔
3016
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3017
            expected_nonce
3018
        );
3019

3020
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
3021
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
3022
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
3023
        assert_eq!(connection.send_array.buffer_end, 0);
1✔
3024

3025
        let (received, _lossy_rx) = lossy_rx.into_future().await;
1✔
3026
        let (received_peer_real_pk, received_data) = received.unwrap();
2✔
3027
        assert_eq!(received_peer_real_pk, peer_real_pk);
2✔
3028
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
2✔
3029
    }
3030

3031
    #[tokio::test]
6✔
3032
    async fn handle_crypto_data_lossy_update_rtt() {
3✔
3033
        let mut rng = thread_rng();
2✔
3034
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3035
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3036
        let (lossy_tx, lossy_rx) = mpsc::unbounded();
2✔
3037
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3038
        let dht_pk = dht_sk.public_key();
1✔
3039
        let real_sk = SecretKey::generate(&mut rng);
2✔
3040
        let real_pk = real_sk.public_key();
1✔
3041
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3042
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3043
            udp_tx,
1✔
3044
            lossless_tx,
1✔
3045
            lossy_tx,
1✔
3046
            dht_pk: dht_pk.clone(),
1✔
3047
            dht_sk: dht_sk.clone(),
1✔
3048
            real_pk: real_pk.clone(),
1✔
3049
            real_sk,
1✔
3050
            precomputed_keys,
1✔
3051
        });
3052

3053
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3054
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3055
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3056
        let mut connection =
2✔
3057
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
3058

3059
        tokio::time::pause();
1✔
3060
        let now = clock_now();
1✔
3061

3062
        let sent_packet = SentPacket {
3063
            data: vec![42; 123],
1✔
3064
            sent_time: now,
3065
            requested: false,
3066
        };
3067
        assert!(connection.send_array.insert(0, sent_packet).is_ok());
1✔
3068

3069
        connection.rtt = Duration::from_millis(500);
1✔
3070

3071
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
3072
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3073
        let session_sk = SecretKey::generate(&mut rng);
1✔
3074
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3075
        connection.status = ConnectionStatus::Established {
1✔
3076
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3077
            received_nonce,
1✔
3078
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3079
        };
3080

3081
        let crypto_data_payload = CryptoDataPayload {
3082
            buffer_start: 1,
3083
            packet_number: 0,
3084
            data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3],
1✔
3085
        };
3086
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3087

3088
        tokio::time::advance(Duration::from_millis(250)).await;
3✔
3089

3090
        net_crypto
4✔
3091
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3092
            .await
2✔
3093
            .unwrap();
3094

3095
        // The diff between nonces is not bigger than the threshold so received
3096
        // nonce shouldn't be changed
3097
        assert_eq!(
2✔
3098
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3099
            received_nonce
3100
        );
3101

3102
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
3103
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
3104
        assert_eq!(connection.send_array.buffer_start, 1);
1✔
3105
        assert_eq!(connection.send_array.buffer_end, 1);
1✔
3106

3107
        let (received, _lossy_rx) = lossy_rx.into_future().await;
1✔
3108
        let (received_peer_real_pk, received_data) = received.unwrap();
2✔
3109
        assert_eq!(received_peer_real_pk, peer_real_pk);
2✔
3110
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
1✔
3111

3112
        // avoid problems with floating point arithmetic
3113
        assert!(connection.rtt > Duration::from_millis(249) && connection.rtt < Duration::from_millis(251));
2✔
3114
    }
3115

3116
    #[tokio::test]
6✔
3117
    async fn handle_crypto_data_lossy_invalid_buffer_start() {
3✔
3118
        let mut rng = thread_rng();
2✔
3119
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3120
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3121
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3122
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3123
        let dht_pk = dht_sk.public_key();
1✔
3124
        let real_sk = SecretKey::generate(&mut rng);
2✔
3125
        let real_pk = real_sk.public_key();
1✔
3126
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3127
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3128
            udp_tx,
1✔
3129
            lossless_tx,
1✔
3130
            lossy_tx,
1✔
3131
            dht_pk: dht_pk.clone(),
1✔
3132
            dht_sk: dht_sk.clone(),
1✔
3133
            real_pk: real_pk.clone(),
1✔
3134
            real_sk,
1✔
3135
            precomputed_keys,
1✔
3136
        });
3137

3138
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3139
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3140
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3141
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
3142

3143
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
3144
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3145
        let session_sk = SecretKey::generate(&mut rng);
1✔
3146
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3147
        connection.status = ConnectionStatus::Established {
1✔
3148
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3149
            received_nonce,
1✔
3150
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3151
        };
3152

3153
        let crypto_data_payload = CryptoDataPayload {
3154
            buffer_start: 7, // bigger than end index of sent packets buffer
3155
            packet_number: 0,
3156
            data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3],
1✔
3157
        };
3158
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3159

3160
        let res = net_crypto
3✔
3161
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3162
            .await;
2✔
3163
        assert!(res.is_err());
2✔
3164
        assert_eq!(
1✔
3165
            res.err().unwrap(),
1✔
3166
            HandlePacketError::PacketsArrayError(PacketsArrayError::OutsideIndex { index: 7 })
3167
        );
3168

3169
        assert_eq!(
2✔
3170
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3171
            received_nonce
3172
        );
3173

3174
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
3175
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
3176
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
3177
        assert_eq!(connection.send_array.buffer_end, 0);
2✔
3178
    }
3179

3180
    #[tokio::test]
6✔
3181
    async fn handle_crypto_data_lossless() {
3✔
3182
        let mut rng = thread_rng();
2✔
3183
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3184
        let (lossless_tx, lossless_rx) = mpsc::unbounded();
2✔
3185
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3186
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3187
        let dht_pk = dht_sk.public_key();
1✔
3188
        let real_sk = SecretKey::generate(&mut rng);
2✔
3189
        let real_pk = real_sk.public_key();
1✔
3190
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3191
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3192
            udp_tx,
1✔
3193
            lossless_tx,
1✔
3194
            lossy_tx,
1✔
3195
            dht_pk: dht_pk.clone(),
1✔
3196
            dht_sk: dht_sk.clone(),
1✔
3197
            real_pk: real_pk.clone(),
1✔
3198
            real_sk,
1✔
3199
            precomputed_keys,
1✔
3200
        });
3201

3202
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3203
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3204
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3205
        let mut connection =
2✔
3206
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
3207

3208
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
3209
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3210
        let session_sk = SecretKey::generate(&mut rng);
1✔
3211
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3212
        connection.status = ConnectionStatus::Established {
1✔
3213
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3214
            received_nonce,
1✔
3215
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3216
        };
3217

3218
        let crypto_data_payload_1 = CryptoDataPayload {
3219
            buffer_start: 0,
3220
            packet_number: 0,
3221
            data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 1, 2, 3],
1✔
3222
        };
3223
        let crypto_data_1 = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload_1);
1✔
3224

3225
        let crypto_data_payload_2 = CryptoDataPayload {
3226
            buffer_start: 0,
3227
            packet_number: 1,
3228
            data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 4, 5, 6],
2✔
3229
        };
3230
        let crypto_data_2 = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload_2);
1✔
3231

3232
        let crypto_data_payload_3 = CryptoDataPayload {
3233
            buffer_start: 0,
3234
            packet_number: 2,
3235
            data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 7, 8, 9],
2✔
3236
        };
3237
        let crypto_data_3 = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload_3);
1✔
3238

3239
        // Send packets in random order
3240
        net_crypto
4✔
3241
            .handle_crypto_data(&mut connection, &crypto_data_2, /* udp */ true)
1✔
3242
            .await
2✔
3243
            .unwrap();
3244
        net_crypto
4✔
3245
            .handle_crypto_data(&mut connection, &crypto_data_3, /* udp */ true)
1✔
3246
            .await
2✔
3247
            .unwrap();
3248
        net_crypto
4✔
3249
            .handle_crypto_data(&mut connection, &crypto_data_1, /* udp */ true)
1✔
3250
            .await
2✔
3251
            .unwrap();
3252

3253
        // The diff between nonces is not bigger than the threshold so received
3254
        // nonce shouldn't be changed
3255
        assert_eq!(
2✔
3256
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3257
            received_nonce
3258
        );
3259

3260
        assert_eq!(connection.recv_array.buffer_start, 3);
1✔
3261
        assert_eq!(connection.recv_array.buffer_end, 3);
1✔
3262
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
3263
        assert_eq!(connection.send_array.buffer_end, 0);
1✔
3264

3265
        // We should receive lossless packets according to their numbers
3266

3267
        let (received, lossless_rx) = lossless_rx.into_future().await;
1✔
3268
        let (received_peer_real_pk, received_data) = received.unwrap();
2✔
3269
        assert_eq!(received_peer_real_pk, peer_real_pk);
2✔
3270
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START - 1, 1, 2, 3]);
1✔
3271

3272
        let (received, lossless_rx) = lossless_rx.into_future().await;
1✔
3273
        let (received_peer_real_pk, received_data) = received.unwrap();
2✔
3274
        assert_eq!(received_peer_real_pk, peer_real_pk);
2✔
3275
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START - 1, 4, 5, 6]);
1✔
3276

3277
        let (received, _lossless_rx) = lossless_rx.into_future().await;
1✔
3278
        let (received_peer_real_pk, received_data) = received.unwrap();
2✔
3279
        assert_eq!(received_peer_real_pk, peer_real_pk);
2✔
3280
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START - 1, 7, 8, 9]);
2✔
3281
    }
3282

3283
    #[tokio::test]
6✔
3284
    async fn handle_crypto_data_lossless_too_big_index() {
3✔
3285
        let mut rng = thread_rng();
2✔
3286
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3287
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3288
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3289
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3290
        let dht_pk = dht_sk.public_key();
1✔
3291
        let real_sk = SecretKey::generate(&mut rng);
2✔
3292
        let real_pk = real_sk.public_key();
1✔
3293
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3294
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3295
            udp_tx,
1✔
3296
            lossless_tx,
1✔
3297
            lossy_tx,
1✔
3298
            dht_pk: dht_pk.clone(),
1✔
3299
            dht_sk: dht_sk.clone(),
1✔
3300
            real_pk: real_pk.clone(),
1✔
3301
            real_sk,
1✔
3302
            precomputed_keys,
1✔
3303
        });
3304

3305
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3306
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3307
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3308
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
3309

3310
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
3311
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3312
        let session_sk = SecretKey::generate(&mut rng);
1✔
3313
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3314
        connection.status = ConnectionStatus::Established {
1✔
3315
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3316
            received_nonce,
1✔
3317
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3318
        };
3319

3320
        let crypto_data_payload = CryptoDataPayload {
3321
            buffer_start: 0,
3322
            packet_number: CRYPTO_PACKET_BUFFER_SIZE,
3323
            data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 1, 2, 3],
1✔
3324
        };
3325
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3326

3327
        let res = net_crypto
3✔
3328
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3329
            .await;
2✔
3330
        assert!(res.is_err());
2✔
3331
        assert_eq!(
1✔
3332
            res.err().unwrap(),
1✔
3333
            HandlePacketError::PacketsArrayError(PacketsArrayError::TooBig { index: 32768 })
3334
        );
3335

3336
        assert_eq!(
2✔
3337
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3338
            received_nonce
3339
        );
3340

3341
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
3342
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
3343
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
3344
        assert_eq!(connection.send_array.buffer_end, 0);
2✔
3345
    }
3346

3347
    #[tokio::test]
6✔
3348
    async fn handle_crypto_data_kill() {
3✔
3349
        let mut rng = thread_rng();
2✔
3350
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3351
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3352
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3353
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3354
        let dht_pk = dht_sk.public_key();
1✔
3355
        let real_sk = SecretKey::generate(&mut rng);
2✔
3356
        let real_pk = real_sk.public_key();
1✔
3357
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3358
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3359
            udp_tx,
1✔
3360
            lossless_tx,
1✔
3361
            lossy_tx,
1✔
3362
            dht_pk: dht_pk.clone(),
1✔
3363
            dht_sk: dht_sk.clone(),
1✔
3364
            real_pk: real_pk.clone(),
1✔
3365
            real_sk,
1✔
3366
            precomputed_keys,
1✔
3367
        });
3368

3369
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3370
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3371
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3372
        let mut connection =
2✔
3373
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
3374

3375
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
3376
        connection.set_udp_addr(addr);
1✔
3377

3378
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
3379
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3380
        let session_sk = SecretKey::generate(&mut rng);
1✔
3381
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3382
        connection.status = ConnectionStatus::Established {
1✔
3383
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3384
            received_nonce,
1✔
3385
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3386
        };
3387

3388
        let connection = Arc::new(RwLock::new(connection));
1✔
3389
        net_crypto
5✔
3390
            .connections
3391
            .write()
3392
            .await
2✔
3393
            .insert(peer_real_pk.clone(), connection.clone());
1✔
3394
        net_crypto
4✔
3395
            .keys_by_addr
3396
            .write()
3397
            .await
2✔
3398
            .insert((addr.ip(), addr.port()), peer_real_pk);
1✔
3399

3400
        let crypto_data_payload = CryptoDataPayload {
3401
            buffer_start: 0,
3402
            packet_number: 0,
3403
            data: vec![PACKET_ID_KILL],
1✔
3404
        };
3405
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3406

3407
        net_crypto
4✔
3408
            .handle_crypto_data(&mut *connection.write().await, &crypto_data, /* udp */ true)
3✔
3409
            .await
2✔
3410
            .unwrap();
3411

3412
        assert!(net_crypto.connections.read().await.is_empty());
1✔
3413
        assert!(net_crypto.keys_by_addr.read().await.is_empty());
2✔
3414
    }
3415

3416
    #[tokio::test]
6✔
3417
    async fn handle_crypto_data_request() {
3✔
3418
        let mut rng = thread_rng();
2✔
3419
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3420
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3421
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3422
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3423
        let dht_pk = dht_sk.public_key();
1✔
3424
        let real_sk = SecretKey::generate(&mut rng);
2✔
3425
        let real_pk = real_sk.public_key();
1✔
3426
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3427
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3428
            udp_tx,
1✔
3429
            lossless_tx,
1✔
3430
            lossy_tx,
1✔
3431
            dht_pk: dht_pk.clone(),
1✔
3432
            dht_sk: dht_sk.clone(),
1✔
3433
            real_pk: real_pk.clone(),
1✔
3434
            real_sk,
1✔
3435
            precomputed_keys,
1✔
3436
        });
3437

3438
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3439
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3440
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3441
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
3442

3443
        tokio::time::pause();
1✔
3444
        let now = clock_now();
1✔
3445

3446
        assert!(connection.send_array.insert(0, SentPacket::new(vec![42; 123])).is_ok());
1✔
3447
        // this time will be used to update rtt
3448
        let packet_1 = SentPacket {
3449
            data: vec![43; 123],
1✔
3450
            sent_time: now + Duration::from_millis(750),
2✔
3451
            requested: false,
3452
        };
3453
        assert!(connection.send_array.insert(1, packet_1).is_ok());
1✔
3454
        // this packet will be requested but elapsed time will be less then rtt
3455
        // so it shouldn't be marked
3456
        let packet_5 = SentPacket {
3457
            data: vec![44; 123],
1✔
3458
            sent_time: now + Duration::from_millis(750),
2✔
3459
            requested: false,
3460
        };
3461
        assert!(connection.send_array.insert(5, packet_5).is_ok());
1✔
3462
        assert!(connection.send_array.insert(7, SentPacket::new(vec![45; 123])).is_ok());
1✔
3463
        assert!(connection
2✔
3464
            .send_array
3465
            .insert(1024, SentPacket::new(vec![46; 123]))
1✔
3466
            .is_ok());
3467

3468
        connection.rtt = Duration::from_millis(500);
1✔
3469

3470
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
3471
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3472
        let session_sk = SecretKey::generate(&mut rng);
1✔
3473
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3474
        connection.status = ConnectionStatus::Established {
1✔
3475
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3476
            received_nonce,
1✔
3477
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3478
        };
3479

3480
        let crypto_data_payload = CryptoDataPayload {
3481
            buffer_start: 0,
3482
            packet_number: 0,
3483
            data: vec![PACKET_ID_REQUEST, 1, 5, 0, 0, 0, 254], // request 0, 5 and 1024 packets
1✔
3484
        };
3485
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3486

3487
        tokio::time::advance(Duration::from_secs(1)).await;
3✔
3488

3489
        net_crypto
4✔
3490
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3491
            .await
2✔
3492
            .unwrap();
3493

3494
        assert!(connection.send_array.get(0).unwrap().requested);
1✔
3495
        assert!(connection.send_array.get(1).is_none());
1✔
3496
        assert!(!connection.send_array.get(5).unwrap().requested);
1✔
3497
        assert!(connection.send_array.get(7).is_none());
2✔
3498
        assert!(connection.send_array.get(1024).unwrap().requested);
1✔
3499

3500
        // avoid problems with floating point arithmetic
3501
        assert!(connection.rtt > Duration::from_millis(249) && connection.rtt < Duration::from_millis(251));
2✔
3502
    }
3503

3504
    #[tokio::test]
6✔
3505
    async fn handle_crypto_data_empty_request() {
3✔
3506
        let mut rng = thread_rng();
2✔
3507
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3508
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3509
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3510
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3511
        let dht_pk = dht_sk.public_key();
1✔
3512
        let real_sk = SecretKey::generate(&mut rng);
2✔
3513
        let real_pk = real_sk.public_key();
1✔
3514
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3515
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3516
            udp_tx,
1✔
3517
            lossless_tx,
1✔
3518
            lossy_tx,
1✔
3519
            dht_pk: dht_pk.clone(),
1✔
3520
            dht_sk: dht_sk.clone(),
1✔
3521
            real_pk: real_pk.clone(),
1✔
3522
            real_sk,
1✔
3523
            precomputed_keys,
1✔
3524
        });
3525

3526
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3527
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3528
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3529
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
3530

3531
        assert!(connection.send_array.insert(0, SentPacket::new(vec![42; 123])).is_ok());
2✔
3532
        assert!(connection.send_array.insert(1, SentPacket::new(vec![43; 123])).is_ok());
1✔
3533
        assert!(connection.send_array.insert(5, SentPacket::new(vec![44; 123])).is_ok());
1✔
3534
        assert!(connection.send_array.insert(7, SentPacket::new(vec![45; 123])).is_ok());
1✔
3535
        assert!(connection
2✔
3536
            .send_array
3537
            .insert(1024, SentPacket::new(vec![46; 123]))
1✔
3538
            .is_ok());
3539

3540
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
3541
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3542
        let session_sk = SecretKey::generate(&mut rng);
1✔
3543
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3544
        connection.status = ConnectionStatus::Established {
1✔
3545
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3546
            received_nonce,
1✔
3547
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3548
        };
3549

3550
        let crypto_data_payload = CryptoDataPayload {
3551
            buffer_start: 0,
3552
            packet_number: 0,
3553
            data: vec![PACKET_ID_REQUEST],
1✔
3554
        };
3555
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3556

3557
        net_crypto
4✔
3558
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3559
            .await
2✔
3560
            .unwrap();
3561

3562
        assert!(!connection.send_array.get(0).unwrap().requested);
1✔
3563
        assert!(!connection.send_array.get(1).unwrap().requested);
2✔
3564
        assert!(!connection.send_array.get(5).unwrap().requested);
2✔
3565
        assert!(!connection.send_array.get(7).unwrap().requested);
2✔
3566
        assert!(!connection.send_array.get(1024).unwrap().requested);
3✔
3567
    }
3568

3569
    #[tokio::test]
6✔
3570
    async fn handle_crypto_data_invalid_packet_id() {
3✔
3571
        let mut rng = thread_rng();
2✔
3572
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3573
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3574
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3575
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3576
        let dht_pk = dht_sk.public_key();
1✔
3577
        let real_sk = SecretKey::generate(&mut rng);
2✔
3578
        let real_pk = real_sk.public_key();
1✔
3579
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3580
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3581
            udp_tx,
1✔
3582
            lossless_tx,
1✔
3583
            lossy_tx,
1✔
3584
            dht_pk: dht_pk.clone(),
1✔
3585
            dht_sk: dht_sk.clone(),
1✔
3586
            real_pk: real_pk.clone(),
1✔
3587
            real_sk,
1✔
3588
            precomputed_keys,
1✔
3589
        });
3590

3591
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3592
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3593
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3594
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
3595

3596
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
3597
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3598
        let session_sk = SecretKey::generate(&mut rng);
1✔
3599
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3600
        connection.status = ConnectionStatus::Established {
1✔
3601
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3602
            received_nonce,
1✔
3603
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3604
        };
3605

3606
        let crypto_data_payload = CryptoDataPayload {
3607
            buffer_start: 0,
3608
            packet_number: 0,
3609
            data: vec![255, 1, 2, 3], // only 255 is invalid id
1✔
3610
        };
3611
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3612

3613
        let res = net_crypto
3✔
3614
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3615
            .await;
2✔
3616
        assert!(res.is_err());
2✔
3617
        assert_eq!(res.err().unwrap(), HandlePacketError::PacketId { id: 255 });
1✔
3618

3619
        assert_eq!(
2✔
3620
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3621
            received_nonce
3622
        );
3623

3624
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
3625
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
3626
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
3627
        assert_eq!(connection.send_array.buffer_end, 0);
2✔
3628
    }
3629

3630
    #[tokio::test]
6✔
3631
    async fn handle_crypto_data_empty_data() {
3✔
3632
        let mut rng = thread_rng();
2✔
3633
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3634
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3635
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3636
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3637
        let dht_pk = dht_sk.public_key();
1✔
3638
        let real_sk = SecretKey::generate(&mut rng);
2✔
3639
        let real_pk = real_sk.public_key();
1✔
3640
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3641
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3642
            udp_tx,
1✔
3643
            lossless_tx,
1✔
3644
            lossy_tx,
1✔
3645
            dht_pk: dht_pk.clone(),
1✔
3646
            dht_sk: dht_sk.clone(),
1✔
3647
            real_pk: real_pk.clone(),
1✔
3648
            real_sk,
1✔
3649
            precomputed_keys,
1✔
3650
        });
3651

3652
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3653
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3654
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3655
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
3656

3657
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
3658
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3659
        let session_sk = SecretKey::generate(&mut rng);
1✔
3660
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3661
        connection.status = ConnectionStatus::Established {
1✔
3662
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
3663
            received_nonce,
1✔
3664
            session_precomputed_key: session_precomputed_key.clone(),
1✔
3665
        };
3666

3667
        let crypto_data_payload = CryptoDataPayload {
3668
            buffer_start: 0,
3669
            packet_number: 0,
3670
            data: Vec::new(),
1✔
3671
        };
3672
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3673

3674
        let res = net_crypto
3✔
3675
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3676
            .await;
2✔
3677
        assert!(res.is_err());
2✔
3678
        assert_eq!(res.err().unwrap(), HandlePacketError::DataEmpty);
1✔
3679

3680
        assert_eq!(
2✔
3681
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
3682
            received_nonce
3683
        );
3684

3685
        assert_eq!(connection.recv_array.buffer_start, 0);
1✔
3686
        assert_eq!(connection.recv_array.buffer_end, 0);
1✔
3687
        assert_eq!(connection.send_array.buffer_start, 0);
1✔
3688
        assert_eq!(connection.send_array.buffer_end, 0);
2✔
3689
    }
3690

3691
    #[tokio::test]
6✔
3692
    async fn handle_crypto_data_invalid_status() {
3✔
3693
        let mut rng = thread_rng();
2✔
3694
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
3695
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3696
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3697
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3698
        let dht_pk = dht_sk.public_key();
1✔
3699
        let real_sk = SecretKey::generate(&mut rng);
2✔
3700
        let real_pk = real_sk.public_key();
1✔
3701
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3702
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3703
            udp_tx,
1✔
3704
            lossless_tx,
1✔
3705
            lossy_tx,
1✔
3706
            dht_pk: dht_pk.clone(),
1✔
3707
            dht_sk: dht_sk.clone(),
1✔
3708
            real_pk: real_pk.clone(),
1✔
3709
            real_sk,
1✔
3710
            precomputed_keys,
1✔
3711
        });
3712

3713
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3714
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3715
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3716
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
3717

3718
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
3719
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
3720
        let session_sk = SecretKey::generate(&mut rng);
1✔
3721
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
3722
        let crypto_data_payload = CryptoDataPayload {
3723
            buffer_start: 0,
3724
            packet_number: 0,
3725
            data: vec![0, 0, PACKET_ID_LOSSY_RANGE_START, 1, 2, 3],
2✔
3726
        };
3727
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
1✔
3728

3729
        let res = net_crypto
3✔
3730
            .handle_crypto_data(&mut connection, &crypto_data, /* udp */ true)
1✔
3731
            .await;
2✔
3732
        assert!(res.is_err());
2✔
3733
        assert_eq!(res.err().unwrap(), HandlePacketError::CannotHandleCryptoData);
2✔
3734
    }
3735

3736
    async fn handle_crypto_data_lossy_test<'a, R, F>(handle_function: F)
4✔
3737
    where
3738
        R: Future<Output = NetCrypto>,
3739
        F: Fn(NetCrypto, CryptoData, SocketAddr, PublicKey) -> R,
3740
    {
3741
        let mut rng = thread_rng();
4✔
3742
        let (udp_tx, _udp_rx) = mpsc::channel(1);
4✔
3743
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
4✔
3744
        let (lossy_tx, lossy_rx) = mpsc::unbounded();
4✔
3745
        let dht_sk = SecretKey::generate(&mut rng);
2✔
3746
        let dht_pk = dht_sk.public_key();
2✔
3747
        let real_sk = SecretKey::generate(&mut rng);
4✔
3748
        let real_pk = real_sk.public_key();
2✔
3749
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
4✔
3750
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
2✔
3751
            udp_tx,
2✔
3752
            lossless_tx,
2✔
3753
            lossy_tx,
2✔
3754
            dht_pk: dht_pk.clone(),
2✔
3755
            dht_sk: dht_sk.clone(),
2✔
3756
            real_pk: real_pk.clone(),
2✔
3757
            real_sk,
2✔
3758
            precomputed_keys,
2✔
3759
        });
3760

3761
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
4✔
3762
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
3763
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
2✔
3764
        let mut connection = CryptoConnection::new(
3765
            &dht_precomputed_key,
2✔
3766
            dht_pk.clone(),
2✔
3767
            real_pk.clone(),
2✔
3768
            peer_real_pk.clone(),
2✔
3769
            peer_dht_pk.clone(),
2✔
3770
        );
3771

3772
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
4✔
3773
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
2✔
3774
        let session_sk = SecretKey::generate(&mut rng);
2✔
3775
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
2✔
3776
        connection.status = ConnectionStatus::Established {
2✔
3777
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
2✔
3778
            received_nonce,
2✔
3779
            session_precomputed_key: session_precomputed_key.clone(),
2✔
3780
        };
3781

3782
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
3783
        connection.set_udp_addr(addr);
2✔
3784

3785
        net_crypto
8✔
3786
            .connections
×
3787
            .write()
3788
            .await
4✔
3789
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
2✔
3790
        net_crypto
8✔
3791
            .keys_by_addr
×
3792
            .write()
3793
            .await
4✔
3794
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
2✔
3795

3796
        let crypto_data_payload = CryptoDataPayload {
3797
            buffer_start: 0,
3798
            packet_number: 0,
3799
            data: vec![0, 0, PACKET_ID_LOSSY_RANGE_START, 1, 2, 3],
2✔
3800
        };
3801
        let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, &crypto_data_payload);
2✔
3802

3803
        let net_crypto = handle_function(net_crypto, crypto_data, addr, peer_dht_pk).await;
2✔
3804

3805
        let connections = net_crypto.connections.read().await;
4✔
3806
        let connection = connections.get(&peer_real_pk).unwrap().read().await.clone();
4✔
3807

3808
        // The diff between nonces is not bigger than the threshold so received
3809
        // nonce shouldn't be changed
3810
        assert_eq!(
4✔
3811
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
2✔
3812
            received_nonce
×
3813
        );
3814

3815
        assert_eq!(connection.recv_array.buffer_start, 0);
2✔
3816
        assert_eq!(connection.recv_array.buffer_end, 0);
2✔
3817
        assert_eq!(connection.send_array.buffer_start, 0);
2✔
3818
        assert_eq!(connection.send_array.buffer_end, 0);
2✔
3819

3820
        let (received, _lossy_rx) = lossy_rx.into_future().await;
2✔
3821
        let (received_peer_real_pk, received_data) = received.unwrap();
4✔
3822
        assert_eq!(received_peer_real_pk, peer_real_pk);
4✔
3823
        assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
2✔
3824
    }
3825

3826
    #[tokio::test]
6✔
3827
    async fn handle_udp_crypto_data_lossy() {
3✔
3828
        async fn test_me(net_crypto: NetCrypto, packet: CryptoData, saddr: SocketAddr, _pk: PublicKey) -> NetCrypto {
8✔
3829
            net_crypto.handle_udp_crypto_data(&packet, saddr).await.unwrap();
2✔
3830
            net_crypto
1✔
3831
        }
3832

3833
        handle_crypto_data_lossy_test(test_me).await;
2✔
3834
    }
3835

3836
    #[tokio::test]
6✔
3837
    async fn handle_tcp_crypto_data_lossy() {
3✔
3838
        async fn test_me(net_crypto: NetCrypto, packet: CryptoData, _saddr: SocketAddr, pk: PublicKey) -> NetCrypto {
8✔
3839
            net_crypto.handle_tcp_crypto_data(&packet, pk).await.unwrap();
2✔
3840
            net_crypto
1✔
3841
        }
3842

3843
        handle_crypto_data_lossy_test(test_me).await;
2✔
3844
    }
3845

3846
    #[tokio::test]
6✔
3847
    async fn send_status_packet() {
3✔
3848
        let mut rng = thread_rng();
2✔
3849
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
3850
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3851
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3852
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3853
        let dht_pk = dht_sk.public_key();
1✔
3854
        let real_sk = SecretKey::generate(&mut rng);
2✔
3855
        let real_pk = real_sk.public_key();
1✔
3856
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3857
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3858
            udp_tx,
1✔
3859
            lossless_tx,
1✔
3860
            lossy_tx,
1✔
3861
            dht_pk: dht_pk.clone(),
1✔
3862
            dht_sk: dht_sk.clone(),
1✔
3863
            real_pk: real_pk.clone(),
1✔
3864
            real_sk,
1✔
3865
            precomputed_keys,
1✔
3866
        });
3867

3868
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3869
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3870
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3871
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
3872

3873
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
3874
        connection.set_udp_addr(addr);
1✔
3875

3876
        // send status packet first time - it should be sent
3877
        net_crypto.send_status_packet(&mut connection).await.unwrap();
1✔
3878

3879
        let packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet);
1✔
3880
        assert_eq!(packet.num_sent, 1);
1✔
3881

3882
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
3883
        let (received, addr_to_send) = received.unwrap();
2✔
3884

3885
        assert_eq!(
1✔
3886
            unpack!(received, DhtPacket::CookieRequest),
1✔
3887
            unpack!(packet.packet.clone(), StatusPacket::CookieRequest)
2✔
3888
        );
3889
        assert_eq!(addr_to_send, addr);
1✔
3890

3891
        // send status packet again - it shouldn't be sent
3892
        net_crypto.send_status_packet(&mut connection).await.unwrap();
1✔
3893

3894
        let packet = unpack!(connection.status, ConnectionStatus::CookieRequesting, packet);
1✔
3895
        assert_eq!(packet.num_sent, 1);
2✔
3896
    }
3897

3898
    #[tokio::test]
6✔
3899
    async fn send_packet_udp() {
3✔
3900
        let mut rng = thread_rng();
2✔
3901
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
3902
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3903
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3904
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3905
        let dht_pk = dht_sk.public_key();
1✔
3906
        let real_sk = SecretKey::generate(&mut rng);
2✔
3907
        let real_pk = real_sk.public_key();
1✔
3908
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3909
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3910
            udp_tx,
1✔
3911
            lossless_tx,
1✔
3912
            lossy_tx,
1✔
3913
            dht_pk: dht_pk.clone(),
1✔
3914
            dht_sk: dht_sk.clone(),
1✔
3915
            real_pk: real_pk.clone(),
1✔
3916
            real_sk,
1✔
3917
            precomputed_keys,
1✔
3918
        });
3919

3920
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
3921
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3922
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3923
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
3924

3925
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
3926
        connection.set_udp_addr(addr);
1✔
3927

3928
        let packet = CryptoData {
3929
            nonce_last_bytes: 123,
3930
            payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH],
1✔
3931
        };
3932

3933
        net_crypto
4✔
3934
            .send_packet(Packet::CryptoData(packet.clone()), &mut connection)
2✔
3935
            .await
2✔
3936
            .unwrap();
3937

3938
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
3939
        let (received, addr_to_send) = received.unwrap();
2✔
3940

3941
        assert_eq!(addr_to_send, addr);
2✔
3942
        assert_eq!(received, DhtPacket::CryptoData(packet));
2✔
3943
    }
3944

3945
    #[tokio::test]
6✔
3946
    async fn send_packet_udp_attempt() {
3✔
3947
        let mut rng = thread_rng();
2✔
3948
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
3949
        let (tcp_tx, tcp_rx) = mpsc::channel(1);
2✔
3950
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
3951
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
3952
        let dht_sk = SecretKey::generate(&mut rng);
1✔
3953
        let dht_pk = dht_sk.public_key();
1✔
3954
        let real_sk = SecretKey::generate(&mut rng);
2✔
3955
        let real_pk = real_sk.public_key();
1✔
3956
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
3957
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
3958
            udp_tx,
1✔
3959
            lossless_tx,
1✔
3960
            lossy_tx,
1✔
3961
            dht_pk: dht_pk.clone(),
1✔
3962
            dht_sk: dht_sk.clone(),
1✔
3963
            real_pk: real_pk.clone(),
1✔
3964
            real_sk,
1✔
3965
            precomputed_keys,
1✔
3966
        });
3967

3968
        net_crypto.set_tcp_sink(tcp_tx).await;
2✔
3969

3970
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
3971
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
3972
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
3973
        let mut connection =
2✔
3974
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk.clone());
3975

3976
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
3977
        connection.set_udp_addr(addr);
1✔
3978

3979
        let packet = CryptoData {
3980
            nonce_last_bytes: 123,
3981
            payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH - 3], // 1 byte of packet kind and 2 bytes of nonce
1✔
3982
        };
3983

3984
        tokio::time::pause();
1✔
3985
        tokio::time::advance(UDP_DIRECT_TIMEOUT + Duration::from_secs(1)).await;
2✔
3986

3987
        net_crypto
4✔
3988
            .send_packet(Packet::CryptoData(packet.clone()), &mut connection)
1✔
3989
            .await
2✔
3990
            .unwrap();
3991

3992
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
3993
        let (received, addr_to_send) = received.unwrap();
2✔
3994

3995
        assert_eq!(addr_to_send, addr);
2✔
3996
        assert_eq!(received, DhtPacket::CryptoData(packet.clone()));
1✔
3997

3998
        let (received, _tcp_rx) = tcp_rx.into_future().await;
1✔
3999
        let (received, key_to_send) = received.unwrap();
2✔
4000

4001
        assert_eq!(key_to_send, peer_dht_pk);
2✔
4002
        assert_eq!(received, TcpDataPayload::CryptoData(packet));
2✔
4003
    }
4004

4005
    #[tokio::test]
6✔
4006
    async fn send_packet_no_udp_attempt() {
3✔
4007
        let mut rng = thread_rng();
2✔
4008
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
4009
        let (tcp_tx, tcp_rx) = mpsc::channel(1);
2✔
4010
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4011
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4012
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4013
        let dht_pk = dht_sk.public_key();
1✔
4014
        let real_sk = SecretKey::generate(&mut rng);
2✔
4015
        let real_pk = real_sk.public_key();
1✔
4016
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4017
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4018
            udp_tx,
1✔
4019
            lossless_tx,
1✔
4020
            lossy_tx,
1✔
4021
            dht_pk: dht_pk.clone(),
1✔
4022
            dht_sk: dht_sk.clone(),
1✔
4023
            real_pk: real_pk.clone(),
1✔
4024
            real_sk,
1✔
4025
            precomputed_keys,
1✔
4026
        });
4027

4028
        net_crypto.set_tcp_sink(tcp_tx).await;
2✔
4029

4030
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
4031
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4032
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4033
        let mut connection =
2✔
4034
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk.clone());
4035

4036
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4037
        connection.set_udp_addr(addr);
1✔
4038

4039
        let packet = CryptoData {
4040
            nonce_last_bytes: 123,
4041
            payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH],
1✔
4042
        };
4043

4044
        tokio::time::pause();
1✔
4045
        tokio::time::advance(UDP_DIRECT_TIMEOUT + Duration::from_secs(1)).await;
2✔
4046

4047
        net_crypto
4✔
4048
            .send_packet(Packet::CryptoData(packet.clone()), &mut connection)
1✔
4049
            .await
2✔
4050
            .unwrap();
4051

4052
        let (received, _tcp_rx) = tcp_rx.into_future().await;
1✔
4053
        let (received, key_to_send) = received.unwrap();
2✔
4054

4055
        assert_eq!(key_to_send, peer_dht_pk);
2✔
4056
        assert_eq!(received, TcpDataPayload::CryptoData(packet));
2✔
4057
    }
4058

4059
    #[tokio::test]
6✔
4060
    async fn send_packet_tcp() {
3✔
4061
        let mut rng = thread_rng();
2✔
4062
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
4063
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4064
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4065
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4066
        let dht_pk = dht_sk.public_key();
1✔
4067
        let real_sk = SecretKey::generate(&mut rng);
2✔
4068
        let real_pk = real_sk.public_key();
1✔
4069
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4070
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4071
            udp_tx,
1✔
4072
            lossless_tx,
1✔
4073
            lossy_tx,
1✔
4074
            dht_pk: dht_pk.clone(),
1✔
4075
            dht_sk: dht_sk.clone(),
1✔
4076
            real_pk: real_pk.clone(),
1✔
4077
            real_sk,
1✔
4078
            precomputed_keys,
1✔
4079
        });
4080

4081
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4082
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4083
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4084
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
4085

4086
        let packet = Packet::CryptoData(CryptoData {
1✔
4087
            nonce_last_bytes: 123,
4088
            payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH],
1✔
4089
        });
4090

4091
        net_crypto.send_packet(packet.clone(), &mut connection).await.unwrap();
3✔
4092

4093
        // TODO: check that TCP received the packet
4094
    }
4095

4096
    #[tokio::test]
6✔
4097
    async fn main_loop_sends_status_packets() {
3✔
4098
        let mut rng = thread_rng();
2✔
4099
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4100
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4101
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4102
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4103
        let dht_pk = dht_sk.public_key();
1✔
4104
        let real_sk = SecretKey::generate(&mut rng);
2✔
4105
        let real_pk = real_sk.public_key();
1✔
4106
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4107
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4108
            udp_tx,
1✔
4109
            lossless_tx,
1✔
4110
            lossy_tx,
1✔
4111
            dht_pk: dht_pk.clone(),
1✔
4112
            dht_sk: dht_sk.clone(),
1✔
4113
            real_pk: real_pk.clone(),
1✔
4114
            real_sk,
1✔
4115
            precomputed_keys,
1✔
4116
        });
4117

4118
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4119
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4120
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4121
        let mut connection =
2✔
4122
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
4123

4124
        let packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet);
2✔
4125

4126
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4127
        connection.set_udp_addr(addr);
1✔
4128

4129
        net_crypto
4✔
4130
            .connections
4131
            .write()
4132
            .await
2✔
4133
            .insert(peer_real_pk, Arc::new(RwLock::new(connection)));
1✔
4134

4135
        net_crypto.main_loop().await.unwrap();
1✔
4136

4137
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4138
        let (received, addr_to_send) = received.unwrap();
2✔
4139

4140
        assert_eq!(addr_to_send, addr);
2✔
4141
        assert_eq!(
3✔
4142
            unpack!(received, DhtPacket::CookieRequest),
1✔
4143
            unpack!(packet.packet, StatusPacket::CookieRequest)
2✔
4144
        );
4145
    }
4146

4147
    #[tokio::test]
6✔
4148
    async fn main_loop_removes_timed_out_connections() {
3✔
4149
        let mut rng = thread_rng();
2✔
4150
        let (udp_tx, _udp_rx) = mpsc::channel(1);
2✔
4151
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4152
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4153
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4154
        let dht_pk = dht_sk.public_key();
1✔
4155
        let real_sk = SecretKey::generate(&mut rng);
2✔
4156
        let real_pk = real_sk.public_key();
1✔
4157
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4158
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4159
            udp_tx,
1✔
4160
            lossless_tx,
1✔
4161
            lossy_tx,
1✔
4162
            dht_pk: dht_pk.clone(),
1✔
4163
            dht_sk: dht_sk.clone(),
1✔
4164
            real_pk: real_pk.clone(),
1✔
4165
            real_sk,
1✔
4166
            precomputed_keys,
1✔
4167
        });
4168

4169
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4170
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4171
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4172
        let mut connection =
2✔
4173
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
4174

4175
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4176
        connection.set_udp_addr(addr);
1✔
4177

4178
        // make the connection timed out
4179
        let cookie_request_id = unpack!(
1✔
4180
            connection.status.clone(),
1✔
4181
            ConnectionStatus::CookieRequesting,
4182
            cookie_request_id
4183
        );
4184
        let mut packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet);
2✔
4185
        packet.num_sent = MAX_NUM_SENDPACKET_TRIES;
1✔
4186
        packet.sent_time -= CRYPTO_SEND_PACKET_INTERVAL + Duration::from_secs(1);
2✔
4187
        connection.status = ConnectionStatus::CookieRequesting {
2✔
4188
            cookie_request_id,
4189
            packet,
1✔
4190
        };
4191

4192
        assert!(connection.is_timed_out());
1✔
4193

4194
        net_crypto
4✔
4195
            .connections
4196
            .write()
4197
            .await
2✔
4198
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
4199
        net_crypto
4✔
4200
            .keys_by_addr
4201
            .write()
4202
            .await
2✔
4203
            .insert((addr.ip(), addr.port()), peer_real_pk);
1✔
4204

4205
        net_crypto.main_loop().await.unwrap();
1✔
4206

4207
        assert!(net_crypto.connections.read().await.is_empty());
1✔
4208
        assert!(net_crypto.keys_by_addr.read().await.is_empty());
2✔
4209
    }
4210

4211
    #[tokio::test]
6✔
4212
    async fn main_loop_sends_request_packets() {
3✔
4213
        let mut rng = thread_rng();
2✔
4214
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4215
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4216
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4217
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4218
        let dht_pk = dht_sk.public_key();
1✔
4219
        let real_sk = SecretKey::generate(&mut rng);
2✔
4220
        let real_pk = real_sk.public_key();
1✔
4221
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4222
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4223
            udp_tx,
1✔
4224
            lossless_tx,
1✔
4225
            lossy_tx,
1✔
4226
            dht_pk: dht_pk.clone(),
1✔
4227
            dht_sk: dht_sk.clone(),
1✔
4228
            real_pk: real_pk.clone(),
1✔
4229
            real_sk,
1✔
4230
            precomputed_keys,
1✔
4231
        });
4232

4233
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4234
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4235
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4236
        let mut connection =
2✔
4237
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
4238

4239
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4240
        connection.set_udp_addr(addr);
1✔
4241

4242
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4243
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4244
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4245
        let session_sk = SecretKey::generate(&mut rng);
1✔
4246
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4247
        connection.status = ConnectionStatus::Established {
1✔
4248
            sent_nonce,
1✔
4249
            received_nonce,
1✔
4250
            session_precomputed_key: session_precomputed_key.clone(),
1✔
4251
        };
4252

4253
        net_crypto
4✔
4254
            .connections
4255
            .write()
4256
            .await
2✔
4257
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
4258
        net_crypto
4✔
4259
            .keys_by_addr
4260
            .write()
4261
            .await
2✔
4262
            .insert((addr.ip(), addr.port()), peer_real_pk);
1✔
4263

4264
        net_crypto.main_loop().await.unwrap();
1✔
4265

4266
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4267
        let (received, addr_to_send) = received.unwrap();
2✔
4268

4269
        assert_eq!(addr_to_send, addr);
2✔
4270

4271
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
4272
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
4273
        assert_eq!(payload.buffer_start, 0);
1✔
4274
        assert_eq!(payload.packet_number, 0);
1✔
4275
        assert_eq!(payload.data, vec![PACKET_ID_REQUEST]);
2✔
4276
    }
4277

4278
    #[tokio::test]
6✔
4279
    async fn main_loop_sends_requested_packets() {
3✔
4280
        let mut rng = thread_rng();
2✔
4281
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4282
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4283
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4284
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4285
        let dht_pk = dht_sk.public_key();
1✔
4286
        let real_sk = SecretKey::generate(&mut rng);
2✔
4287
        let real_pk = real_sk.public_key();
1✔
4288
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4289
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4290
            udp_tx,
1✔
4291
            lossless_tx,
1✔
4292
            lossy_tx,
1✔
4293
            dht_pk: dht_pk.clone(),
1✔
4294
            dht_sk: dht_sk.clone(),
1✔
4295
            real_pk: real_pk.clone(),
1✔
4296
            real_sk,
1✔
4297
            precomputed_keys,
1✔
4298
        });
4299

4300
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4301
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4302
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4303
        let mut connection =
2✔
4304
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
4305

4306
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4307
        connection.set_udp_addr(addr);
1✔
4308

4309
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4310
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4311
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4312
        let session_sk = SecretKey::generate(&mut rng);
1✔
4313
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4314
        connection.status = ConnectionStatus::Established {
1✔
4315
            sent_nonce,
1✔
4316
            received_nonce,
1✔
4317
            session_precomputed_key: session_precomputed_key.clone(),
1✔
4318
        };
4319

4320
        let now = Instant::now();
1✔
4321

4322
        connection.request_packet_sent_time = Some(now);
1✔
4323

4324
        let data = vec![42; 123];
1✔
4325
        connection.packets_sent = 1;
1✔
4326
        connection.send_array.buffer_end = 1;
1✔
4327
        assert!(connection
2✔
4328
            .send_array
4329
            .insert(
4330
                0,
4331
                SentPacket {
1✔
4332
                    data: data.clone(),
1✔
4333
                    sent_time: now,
4334
                    requested: true,
4335
                }
4336
            )
4337
            .is_ok());
4338

4339
        net_crypto
4✔
4340
            .connections
4341
            .write()
4342
            .await
2✔
4343
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
4344
        net_crypto
4✔
4345
            .keys_by_addr
4346
            .write()
4347
            .await
2✔
4348
            .insert((addr.ip(), addr.port()), peer_real_pk);
1✔
4349

4350
        net_crypto.main_loop().await.unwrap();
1✔
4351

4352
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4353
        let (received, addr_to_send) = received.unwrap();
2✔
4354

4355
        assert_eq!(addr_to_send, addr);
2✔
4356

4357
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
4358
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
4359
        assert_eq!(payload.buffer_start, 0);
1✔
4360
        assert_eq!(payload.packet_number, 0);
1✔
4361
        assert_eq!(payload.data, data);
2✔
4362
    }
4363

4364
    #[tokio::test]
6✔
4365
    async fn send_status_packet_established() {
3✔
4366
        let mut rng = thread_rng();
2✔
4367
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4368
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4369
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4370
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4371
        let dht_pk = dht_sk.public_key();
1✔
4372
        let real_sk = SecretKey::generate(&mut rng);
2✔
4373
        let real_pk = real_sk.public_key();
1✔
4374
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4375
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4376
            udp_tx,
1✔
4377
            lossless_tx,
1✔
4378
            lossy_tx,
1✔
4379
            dht_pk: dht_pk.clone(),
1✔
4380
            dht_sk: dht_sk.clone(),
1✔
4381
            real_pk: real_pk.clone(),
1✔
4382
            real_sk,
1✔
4383
            precomputed_keys,
1✔
4384
        });
4385

4386
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4387
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4388
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4389
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
4390

4391
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
4392
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4393
        let session_sk = SecretKey::generate(&mut rng);
1✔
4394
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4395
        connection.status = ConnectionStatus::Established {
2✔
4396
            sent_nonce: [42; <SalsaBox as AeadCore>::NonceSize::USIZE],
1✔
4397
            received_nonce,
1✔
4398
            session_precomputed_key,
1✔
4399
        };
4400

4401
        // send status packet with connection.status is Established
4402
        net_crypto.send_status_packet(&mut connection).await.unwrap();
1✔
4403

4404
        // Necessary to drop udp_tx so that udp_rx.collect() can be finished
4405
        drop(net_crypto.udp_tx);
1✔
4406

4407
        assert!(udp_rx.collect::<Vec<_>>().await.is_empty());
2✔
4408
    }
4409

4410
    #[tokio::test]
6✔
4411
    async fn send_data_packet() {
3✔
4412
        let mut rng = thread_rng();
2✔
4413
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4414
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4415
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4416
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4417
        let dht_pk = dht_sk.public_key();
1✔
4418
        let real_sk = SecretKey::generate(&mut rng);
2✔
4419
        let real_pk = real_sk.public_key();
1✔
4420
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4421
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4422
            udp_tx,
1✔
4423
            lossless_tx,
1✔
4424
            lossy_tx,
1✔
4425
            dht_pk: dht_pk.clone(),
1✔
4426
            dht_sk: dht_sk.clone(),
1✔
4427
            real_pk: real_pk.clone(),
1✔
4428
            real_sk,
1✔
4429
            precomputed_keys,
1✔
4430
        });
4431

4432
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4433
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4434
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4435
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
2✔
4436

4437
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4438
        connection.set_udp_addr(addr);
1✔
4439

4440
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4441
        let mut sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4442
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4443
        let session_sk = SecretKey::generate(&mut rng);
1✔
4444
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4445
        connection.status = ConnectionStatus::Established {
1✔
4446
            sent_nonce,
1✔
4447
            received_nonce,
1✔
4448
            session_precomputed_key: session_precomputed_key.clone(),
1✔
4449
        };
4450

4451
        connection.recv_array.buffer_start = 23;
1✔
4452
        connection.recv_array.buffer_end = 25;
1✔
4453

4454
        let data = vec![42; 123];
1✔
4455
        net_crypto
4✔
4456
            .send_data_packet(&mut connection, data.clone(), 7)
1✔
4457
            .await
2✔
4458
            .unwrap();
4459

4460
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4461
        let (received, addr_to_send) = received.unwrap();
2✔
4462

4463
        assert_eq!(addr_to_send, addr);
2✔
4464

4465
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
4466
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
4467
        assert_eq!(payload.buffer_start, 23);
1✔
4468
        assert_eq!(payload.packet_number, 7);
1✔
4469
        assert_eq!(payload.data, data);
1✔
4470

4471
        increment_nonce(&mut sent_nonce);
1✔
4472
        assert_eq!(
2✔
4473
            unpack!(connection.status, ConnectionStatus::Established, sent_nonce),
1✔
4474
            sent_nonce
4475
        );
4476
        assert_eq!(
4✔
4477
            unpack!(connection.status, ConnectionStatus::Established, received_nonce),
1✔
4478
            received_nonce
4479
        );
4480
    }
4481

4482
    #[tokio::test]
6✔
4483
    async fn send_request_packet() {
3✔
4484
        let mut rng = thread_rng();
2✔
4485
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4486
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4487
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4488
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4489
        let dht_pk = dht_sk.public_key();
1✔
4490
        let real_sk = SecretKey::generate(&mut rng);
2✔
4491
        let real_pk = real_sk.public_key();
1✔
4492
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4493
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4494
            udp_tx,
1✔
4495
            lossless_tx,
1✔
4496
            lossy_tx,
1✔
4497
            dht_pk: dht_pk.clone(),
1✔
4498
            dht_sk: dht_sk.clone(),
1✔
4499
            real_pk: real_pk.clone(),
1✔
4500
            real_sk,
1✔
4501
            precomputed_keys,
1✔
4502
        });
4503

4504
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4505
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4506
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4507
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
4508

4509
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4510
        connection.set_udp_addr(addr);
1✔
4511

4512
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4513
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4514
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4515
        let session_sk = SecretKey::generate(&mut rng);
1✔
4516
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4517
        connection.status = ConnectionStatus::Established {
1✔
4518
            sent_nonce,
1✔
4519
            received_nonce,
1✔
4520
            session_precomputed_key: session_precomputed_key.clone(),
1✔
4521
        };
4522

4523
        connection.recv_array.buffer_end = 270;
1✔
4524
        assert!(connection
2✔
4525
            .recv_array
4526
            .insert(2, RecvPacket { data: vec![42; 123] })
1✔
4527
            .is_ok());
4528
        for i in 5..269 {
2✔
4529
            assert!(connection
2✔
4530
                .recv_array
4531
                .insert(i, RecvPacket { data: vec![42; 123] })
2✔
4532
                .is_ok());
4533
        }
4534

4535
        tokio::time::pause();
1✔
4536
        let now = clock_now();
1✔
4537
        let delay = Duration::from_secs(1);
1✔
4538
        tokio::time::advance(delay).await;
2✔
4539

4540
        net_crypto.send_request_packet(&mut connection).await.unwrap();
1✔
4541

4542
        assert_eq!(connection.request_packet_sent_time, Some(now + delay));
1✔
4543

4544
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4545
        let (received, addr_to_send) = received.unwrap();
2✔
4546

4547
        assert_eq!(addr_to_send, addr);
2✔
4548

4549
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
4550
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
4551
        assert_eq!(payload.buffer_start, 0);
1✔
4552
        assert_eq!(payload.packet_number, 0);
1✔
4553
        assert_eq!(payload.data, vec![PACKET_ID_REQUEST, 1, 1, 2, 1, 0, 10]);
2✔
4554
    }
4555

4556
    #[tokio::test]
6✔
4557
    async fn send_request_packet_too_many_missing_packets() {
3✔
4558
        let mut rng = thread_rng();
2✔
4559
        let (udp_tx, udp_rx) = mpsc::channel(1);
2✔
4560
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4561
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4562
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4563
        let dht_pk = dht_sk.public_key();
1✔
4564
        let real_sk = SecretKey::generate(&mut rng);
2✔
4565
        let real_pk = real_sk.public_key();
1✔
4566
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4567
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4568
            udp_tx,
1✔
4569
            lossless_tx,
1✔
4570
            lossy_tx,
1✔
4571
            dht_pk: dht_pk.clone(),
1✔
4572
            dht_sk: dht_sk.clone(),
1✔
4573
            real_pk: real_pk.clone(),
1✔
4574
            real_sk,
1✔
4575
            precomputed_keys,
1✔
4576
        });
4577

4578
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4579
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4580
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4581
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
4582

4583
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4584
        connection.set_udp_addr(addr);
1✔
4585

4586
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4587
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4588
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4589
        let session_sk = SecretKey::generate(&mut rng);
1✔
4590
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4591
        connection.status = ConnectionStatus::Established {
1✔
4592
            sent_nonce,
1✔
4593
            received_nonce,
1✔
4594
            session_precomputed_key: session_precomputed_key.clone(),
1✔
4595
        };
4596

4597
        connection.recv_array.buffer_end = MAX_CRYPTO_DATA_SIZE as u32 + 42;
1✔
4598

4599
        net_crypto.send_request_packet(&mut connection).await.unwrap();
2✔
4600

4601
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4602
        let (received, addr_to_send) = received.unwrap();
2✔
4603

4604
        assert_eq!(addr_to_send, addr);
2✔
4605

4606
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
4607
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
4608
        assert_eq!(payload.buffer_start, 0);
1✔
4609
        assert_eq!(payload.packet_number, 0);
1✔
4610
        assert_eq!(payload.data.len(), MAX_CRYPTO_DATA_SIZE);
2✔
4611
    }
4612

4613
    #[tokio::test]
6✔
4614
    async fn send_requested_packets() {
3✔
4615
        tokio::time::pause();
1✔
4616
        let mut rng = thread_rng();
1✔
4617
        let now = clock_now();
2✔
4618

4619
        let (udp_tx, udp_rx) = mpsc::channel(2);
1✔
4620
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4621
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4622
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4623
        let dht_pk = dht_sk.public_key();
1✔
4624
        let real_sk = SecretKey::generate(&mut rng);
2✔
4625
        let real_pk = real_sk.public_key();
1✔
4626
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4627
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4628
            udp_tx,
1✔
4629
            lossless_tx,
1✔
4630
            lossy_tx,
1✔
4631
            dht_pk: dht_pk.clone(),
1✔
4632
            dht_sk: dht_sk.clone(),
1✔
4633
            real_pk: real_pk.clone(),
1✔
4634
            real_sk,
1✔
4635
            precomputed_keys,
1✔
4636
        });
4637

4638
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4639
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4640
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4641
        let mut connection = CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
1✔
4642

4643
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4644
        connection.set_udp_addr(addr);
1✔
4645

4646
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4647
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4648
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4649
        let session_sk = SecretKey::generate(&mut rng);
1✔
4650
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4651
        connection.status = ConnectionStatus::Established {
2✔
4652
            sent_nonce,
1✔
4653
            received_nonce,
1✔
4654
            session_precomputed_key,
1✔
4655
        };
4656

4657
        connection.send_array.buffer_end = 7;
1✔
4658
        assert!(connection
2✔
4659
            .send_array
4660
            .insert(
4661
                2,
4662
                SentPacket {
1✔
4663
                    data: vec![42; 123],
1✔
4664
                    sent_time: now,
1✔
4665
                    requested: true,
4666
                }
4667
            )
4668
            .is_ok());
4669
        assert!(connection
2✔
4670
            .send_array
4671
            .insert(
4672
                4,
4673
                SentPacket {
1✔
4674
                    data: vec![42; 123],
1✔
4675
                    sent_time: now,
1✔
4676
                    requested: false,
4677
                }
4678
            )
4679
            .is_ok());
4680
        assert!(connection
2✔
4681
            .send_array
4682
            .insert(
4683
                5,
4684
                SentPacket {
1✔
4685
                    data: vec![42; 123],
1✔
4686
                    sent_time: now,
1✔
4687
                    requested: true,
4688
                }
4689
            )
4690
            .is_ok());
4691

4692
        let delay = Duration::from_secs(1);
1✔
4693
        tokio::time::advance(delay).await;
2✔
4694

4695
        net_crypto.send_requested_packets(&mut connection).await.unwrap();
1✔
4696

4697
        assert!(!connection.send_array.get(2).unwrap().requested);
1✔
4698
        assert!(!connection.send_array.get(4).unwrap().requested);
2✔
4699
        assert!(!connection.send_array.get(5).unwrap().requested);
2✔
4700
        assert_eq!(connection.send_array.get(2).unwrap().sent_time, now + delay);
2✔
4701
        assert_eq!(connection.send_array.get(4).unwrap().sent_time, now);
1✔
4702
        assert_eq!(connection.send_array.get(5).unwrap().sent_time, now + delay);
1✔
4703

4704
        // Necessary to drop udp_tx so that udp_rx.collect() can be finished
4705
        drop(net_crypto.udp_tx);
1✔
4706

4707
        assert_eq!(udp_rx.collect::<Vec<_>>().await.len(), 2);
2✔
4708
    }
4709

4710
    #[tokio::test]
6✔
4711
    async fn send_lossless() {
3✔
4712
        let mut rng = thread_rng();
2✔
4713
        let (udp_tx, udp_rx) = mpsc::channel(2);
2✔
4714
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4715
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4716
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4717
        let dht_pk = dht_sk.public_key();
1✔
4718
        let real_sk = SecretKey::generate(&mut rng);
2✔
4719
        let real_pk = real_sk.public_key();
1✔
4720
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4721
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4722
            udp_tx,
1✔
4723
            lossless_tx,
1✔
4724
            lossy_tx,
1✔
4725
            dht_pk: dht_pk.clone(),
1✔
4726
            dht_sk: dht_sk.clone(),
1✔
4727
            real_pk: real_pk.clone(),
1✔
4728
            real_sk,
1✔
4729
            precomputed_keys,
1✔
4730
        });
4731

4732
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
4733
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
4734
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
4735
        let mut connection =
2✔
4736
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
4737

4738
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
4739
        connection.set_udp_addr(addr);
1✔
4740

4741
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4742
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
4743
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
4744
        let session_sk = SecretKey::generate(&mut rng);
1✔
4745
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
4746
        connection.status = ConnectionStatus::Established {
1✔
4747
            sent_nonce,
1✔
4748
            received_nonce,
1✔
4749
            session_precomputed_key: session_precomputed_key.clone(),
1✔
4750
        };
4751

4752
        let connection = Arc::new(RwLock::new(connection));
1✔
4753
        net_crypto
5✔
4754
            .connections
4755
            .write()
4756
            .await
2✔
4757
            .insert(peer_real_pk.clone(), connection.clone());
1✔
4758
        net_crypto
4✔
4759
            .keys_by_addr
4760
            .write()
4761
            .await
2✔
4762
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
1✔
4763

4764
        let data = vec![16, 42];
1✔
4765

4766
        net_crypto.send_lossless(peer_real_pk, data.clone()).await.unwrap();
2✔
4767

4768
        let connection = connection.read().await;
1✔
4769

4770
        assert_eq!(connection.packets_sent, 1);
2✔
4771

4772
        // the packet should be added to send_array
4773

4774
        assert_eq!(connection.send_array.buffer[0].clone().unwrap().data, data);
1✔
4775

4776
        // the packet should be sent to node
4777

4778
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
4779
        let (received, addr_to_send) = received.unwrap();
2✔
4780

4781
        assert_eq!(addr_to_send, addr);
2✔
4782

4783
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
4784
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
4785
        assert_eq!(payload.buffer_start, 0);
1✔
4786
        assert_eq!(payload.packet_number, 0);
1✔
4787
        assert_eq!(payload.data, data);
2✔
4788
    }
4789

4790
    #[tokio::test]
6✔
4791
    async fn send_lossless_no_connection() {
3✔
4792
        let mut rng = thread_rng();
2✔
4793
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
4794
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4795
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4796
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4797
        let dht_pk = dht_sk.public_key();
1✔
4798
        let real_sk = SecretKey::generate(&mut rng);
2✔
4799
        let real_pk = real_sk.public_key();
1✔
4800
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4801
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4802
            udp_tx,
1✔
4803
            lossless_tx,
1✔
4804
            lossy_tx,
1✔
4805
            dht_pk,
1✔
4806
            dht_sk: dht_sk.clone(),
1✔
4807
            real_pk,
1✔
4808
            real_sk,
1✔
4809
            precomputed_keys,
1✔
4810
        });
4811

4812
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
4813

4814
        let error = net_crypto
4✔
4815
            .send_lossless(peer_real_pk, vec![16, 42])
1✔
4816
            .await
2✔
4817
            .err()
4818
            .unwrap();
4819
        assert_eq!(error, SendLosslessPacketError::NoConnection);
2✔
4820
    }
4821

4822
    #[tokio::test]
6✔
4823
    async fn send_lossless_invalid_packet_id() {
3✔
4824
        let mut rng = thread_rng();
2✔
4825
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
4826
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4827
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4828
        let dht_sk = SecretKey::generate(&mut rng);
1✔
4829
        let dht_pk = dht_sk.public_key();
1✔
4830
        let real_sk = SecretKey::generate(&mut rng);
2✔
4831
        let real_pk = real_sk.public_key();
1✔
4832
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4833
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4834
            udp_tx,
1✔
4835
            lossless_tx,
1✔
4836
            lossy_tx,
1✔
4837
            dht_pk,
1✔
4838
            dht_sk: dht_sk.clone(),
1✔
4839
            real_pk,
1✔
4840
            real_sk,
1✔
4841
            precomputed_keys,
1✔
4842
        });
4843

4844
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
4845

4846
        let error = net_crypto
4✔
4847
            .send_lossless(peer_real_pk, vec![10, 42])
1✔
4848
            .await
2✔
4849
            .err()
4850
            .unwrap();
4851
        assert_eq!(error, SendLosslessPacketError::InvalidPacketId);
2✔
4852
    }
4853

4854
    #[tokio::test]
6✔
4855
    async fn add_connection() {
3✔
4856
        let mut rng = thread_rng();
2✔
4857
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
4858
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4859
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4860
        let dht_sk = SecretKey::generate(&mut rng);
2✔
4861
        let dht_pk = dht_sk.public_key();
1✔
4862
        let real_sk = SecretKey::generate(&mut rng);
2✔
4863
        let real_pk = real_sk.public_key();
1✔
4864
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
4865
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4866
            udp_tx,
1✔
4867
            lossless_tx,
1✔
4868
            lossy_tx,
1✔
4869
            dht_pk: dht_pk.clone(),
1✔
4870
            dht_sk,
1✔
4871
            real_pk: real_pk.clone(),
1✔
4872
            real_sk,
1✔
4873
            precomputed_keys,
1✔
4874
        });
4875

4876
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
4877
        let peer_dht_sk = SecretKey::generate(&mut rng);
1✔
4878
        let peer_dht_pk = peer_dht_sk.public_key();
1✔
4879
        net_crypto
2✔
4880
            .add_connection(peer_real_pk.clone(), peer_dht_pk.clone())
1✔
4881
            .await;
1✔
4882

4883
        let connections = net_crypto.connections.read().await;
1✔
4884
        let connection = connections[&peer_real_pk].read().await;
2✔
4885

4886
        assert_eq!(connection.peer_real_pk, peer_real_pk);
2✔
4887
        assert_eq!(connection.peer_dht_pk, peer_dht_pk);
1✔
4888

4889
        let status_packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet);
2✔
4890
        let cookie_request = unpack!(status_packet.packet, StatusPacket::CookieRequest);
2✔
4891
        let cookie_request_payload = cookie_request
2✔
4892
            .get_payload(&SalsaBox::new(&dht_pk, &peer_dht_sk))
1✔
4893
            .unwrap();
4894

4895
        assert_eq!(cookie_request_payload.pk, real_pk);
2✔
4896
    }
4897

4898
    #[tokio::test]
6✔
4899
    async fn add_connection_already_exists() {
3✔
4900
        let mut rng = thread_rng();
2✔
4901
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
4902
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4903
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4904
        let dht_sk = SecretKey::generate(&mut rng);
2✔
4905
        let dht_pk = dht_sk.public_key();
1✔
4906
        let real_sk = SecretKey::generate(&mut rng);
2✔
4907
        let real_pk = real_sk.public_key();
1✔
4908
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
4909
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4910
            udp_tx,
1✔
4911
            lossless_tx,
1✔
4912
            lossy_tx,
1✔
4913
            dht_pk,
1✔
4914
            dht_sk,
1✔
4915
            real_pk,
1✔
4916
            real_sk,
1✔
4917
            precomputed_keys,
1✔
4918
        });
4919

4920
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
4921
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
4922
        net_crypto
2✔
4923
            .add_connection(peer_real_pk.clone(), peer_dht_pk.clone())
1✔
4924
            .await;
1✔
4925

4926
        // adding a friend that already exists won't do anything
4927
        let another_peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
4928
        net_crypto
2✔
4929
            .add_connection(peer_real_pk.clone(), another_peer_dht_pk)
1✔
4930
            .await;
1✔
4931

4932
        let connections = net_crypto.connections.read().await;
1✔
4933
        let connection = connections[&peer_real_pk].read().await;
2✔
4934

4935
        assert_eq!(connection.peer_real_pk, peer_real_pk);
2✔
4936
        assert_eq!(connection.peer_dht_pk, peer_dht_pk);
2✔
4937
    }
4938

4939
    #[tokio::test]
6✔
4940
    async fn set_friend_udp_addr() {
3✔
4941
        let mut rng = thread_rng();
2✔
4942
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
4943
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4944
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4945
        let dht_sk = SecretKey::generate(&mut rng);
2✔
4946
        let dht_pk = dht_sk.public_key();
1✔
4947
        let real_sk = SecretKey::generate(&mut rng);
2✔
4948
        let real_pk = real_sk.public_key();
1✔
4949
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
4950
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4951
            udp_tx,
1✔
4952
            lossless_tx,
1✔
4953
            lossy_tx,
1✔
4954
            dht_pk,
1✔
4955
            dht_sk,
1✔
4956
            real_pk,
1✔
4957
            real_sk,
1✔
4958
            precomputed_keys,
1✔
4959
        });
4960

4961
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
4962
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
4963
        net_crypto.add_connection(peer_real_pk.clone(), peer_dht_pk).await;
1✔
4964

4965
        let addr_v4 = "127.0.0.1:12345".parse().unwrap();
1✔
4966
        net_crypto.set_friend_udp_addr(peer_real_pk.clone(), addr_v4).await;
1✔
4967
        let addr_v6 = "[::]:12345".parse().unwrap();
1✔
4968
        net_crypto.set_friend_udp_addr(peer_real_pk.clone(), addr_v6).await;
1✔
4969

4970
        let connections = net_crypto.connections.read().await;
1✔
4971
        let connection = connections[&peer_real_pk].read().await;
2✔
4972

4973
        assert_eq!(connection.get_udp_addr_v4(), Some(addr_v4));
2✔
4974
        assert_eq!(connection.get_udp_addr_v6(), Some(addr_v6));
1✔
4975
        assert_eq!(
1✔
4976
            net_crypto.keys_by_addr.read().await[&(addr_v4.ip(), addr_v4.port())],
2✔
4977
            peer_real_pk
4978
        );
4979
        assert_eq!(
3✔
4980
            net_crypto.keys_by_addr.read().await[&(addr_v6.ip(), addr_v6.port())],
2✔
4981
            peer_real_pk
4982
        );
4983
    }
4984

4985
    #[tokio::test]
6✔
4986
    async fn set_friend_udp_addr_update() {
3✔
4987
        let mut rng = thread_rng();
2✔
4988
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
4989
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
4990
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
4991
        let dht_sk = SecretKey::generate(&mut rng);
2✔
4992
        let dht_pk = dht_sk.public_key();
1✔
4993
        let real_sk = SecretKey::generate(&mut rng);
2✔
4994
        let real_pk = real_sk.public_key();
1✔
4995
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
4996
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
4997
            udp_tx,
1✔
4998
            lossless_tx,
1✔
4999
            lossy_tx,
1✔
5000
            dht_pk,
1✔
5001
            dht_sk,
1✔
5002
            real_pk,
1✔
5003
            real_sk,
1✔
5004
            precomputed_keys,
1✔
5005
        });
5006

5007
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
5008
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
1✔
5009
        net_crypto.add_connection(peer_real_pk.clone(), peer_dht_pk).await;
1✔
5010

5011
        let addr = "127.0.0.1:12345".parse().unwrap();
1✔
5012
        net_crypto.set_friend_udp_addr(peer_real_pk.clone(), addr).await;
1✔
5013
        // setting the same address won't do anything
5014
        net_crypto.set_friend_udp_addr(peer_real_pk.clone(), addr).await;
1✔
5015

5016
        let addr = "127.0.0.1:12346".parse().unwrap();
1✔
5017
        net_crypto.set_friend_udp_addr(peer_real_pk.clone(), addr).await;
1✔
5018

5019
        let connections = net_crypto.connections.read().await;
1✔
5020
        let connection = connections[&peer_real_pk].read().await;
2✔
5021

5022
        assert_eq!(connection.get_udp_addr_v4(), Some(addr));
2✔
5023

5024
        let keys_by_addr = net_crypto.keys_by_addr.read().await;
1✔
5025
        assert_eq!(keys_by_addr[&(addr.ip(), addr.port())], peer_real_pk);
2✔
5026
        assert_eq!(keys_by_addr.len(), 1);
2✔
5027
    }
5028

5029
    #[tokio::test]
6✔
5030
    async fn set_friend_udp_addr_no_connection() {
3✔
5031
        let mut rng = thread_rng();
2✔
5032
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
5033
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
5034
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
5035
        let dht_sk = SecretKey::generate(&mut rng);
2✔
5036
        let dht_pk = dht_sk.public_key();
1✔
5037
        let real_sk = SecretKey::generate(&mut rng);
2✔
5038
        let real_pk = real_sk.public_key();
1✔
5039
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
1✔
5040
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
5041
            udp_tx,
1✔
5042
            lossless_tx,
1✔
5043
            lossy_tx,
1✔
5044
            dht_pk,
1✔
5045
            dht_sk,
1✔
5046
            real_pk,
1✔
5047
            real_sk,
1✔
5048
            precomputed_keys,
1✔
5049
        });
5050

5051
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
5052
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
5053

5054
        // setting an address to nonexistent connection won't do anything
5055
        net_crypto.set_friend_udp_addr(peer_real_pk, addr).await;
1✔
5056

5057
        assert!(net_crypto.keys_by_addr.read().await.is_empty());
2✔
5058
    }
5059

5060
    #[tokio::test]
6✔
5061
    async fn kill_connection() {
3✔
5062
        let mut rng = thread_rng();
2✔
5063
        let (udp_tx, udp_rx) = mpsc::channel(2);
2✔
5064
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
5065
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
5066
        let dht_sk = SecretKey::generate(&mut rng);
1✔
5067
        let dht_pk = dht_sk.public_key();
1✔
5068
        let real_sk = SecretKey::generate(&mut rng);
2✔
5069
        let real_pk = real_sk.public_key();
1✔
5070
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
5071
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
5072
            udp_tx,
1✔
5073
            lossless_tx,
1✔
5074
            lossy_tx,
1✔
5075
            dht_pk: dht_pk.clone(),
1✔
5076
            dht_sk: dht_sk.clone(),
1✔
5077
            real_pk: real_pk.clone(),
1✔
5078
            real_sk,
1✔
5079
            precomputed_keys,
1✔
5080
        });
5081

5082
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
5083
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
5084
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
5085
        let mut connection =
2✔
5086
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
5087

5088
        let received_nonce = SalsaBox::generate_nonce(&mut rng).into();
2✔
5089
        let sent_nonce = SalsaBox::generate_nonce(&mut rng).into();
1✔
5090
        let peer_session_pk = SecretKey::generate(&mut rng).public_key();
1✔
5091
        let session_sk = SecretKey::generate(&mut rng);
1✔
5092
        let session_precomputed_key = SalsaBox::new(&peer_session_pk, &session_sk);
1✔
5093
        connection.status = ConnectionStatus::Established {
1✔
5094
            sent_nonce,
1✔
5095
            received_nonce,
1✔
5096
            session_precomputed_key: session_precomputed_key.clone(),
1✔
5097
        };
5098

5099
        let addr = "127.0.0.1:12345".parse().unwrap();
1✔
5100
        connection.set_udp_addr(addr);
1✔
5101

5102
        net_crypto
4✔
5103
            .connections
5104
            .write()
5105
            .await
2✔
5106
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
5107
        net_crypto
4✔
5108
            .keys_by_addr
5109
            .write()
5110
            .await
2✔
5111
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
1✔
5112

5113
        net_crypto.kill_connection(peer_real_pk.clone()).await.unwrap();
1✔
5114

5115
        assert!(!net_crypto.connections.read().await.contains_key(&peer_real_pk));
1✔
5116
        assert!(!net_crypto
4✔
5117
            .keys_by_addr
5118
            .read()
5119
            .await
2✔
5120
            .contains_key(&(addr.ip(), addr.port())));
1✔
5121

5122
        let (received, _udp_rx) = udp_rx.into_future().await;
1✔
5123
        let (received, addr_to_send) = received.unwrap();
2✔
5124

5125
        assert_eq!(addr_to_send, addr);
2✔
5126

5127
        let packet = unpack!(received, DhtPacket::CryptoData);
1✔
5128
        let payload = packet.get_payload(&session_precomputed_key, &sent_nonce).unwrap();
2✔
5129
        assert_eq!(payload.buffer_start, 0);
1✔
5130
        assert_eq!(payload.packet_number, 0);
1✔
5131
        assert_eq!(payload.data, vec![PACKET_ID_KILL]);
2✔
5132
    }
5133

5134
    #[tokio::test]
6✔
5135
    async fn kill_connection_no_connection() {
3✔
5136
        let mut rng = thread_rng();
2✔
5137
        let (udp_tx, _udp_rx) = mpsc::channel(2);
2✔
5138
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
5139
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
5140
        let dht_sk = SecretKey::generate(&mut rng);
1✔
5141
        let dht_pk = dht_sk.public_key();
1✔
5142
        let real_sk = SecretKey::generate(&mut rng);
2✔
5143
        let real_pk = real_sk.public_key();
1✔
5144
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
5145
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
5146
            udp_tx,
1✔
5147
            lossless_tx,
1✔
5148
            lossy_tx,
1✔
5149
            dht_pk,
1✔
5150
            dht_sk: dht_sk.clone(),
1✔
5151
            real_pk,
1✔
5152
            real_sk,
1✔
5153
            precomputed_keys,
1✔
5154
        });
5155

5156
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
2✔
5157

5158
        let error = net_crypto.kill_connection(peer_real_pk).await.err().unwrap();
1✔
5159
        assert_eq!(error, KillConnectionError::NoConnection);
2✔
5160
    }
5161

5162
    #[tokio::test]
6✔
5163
    async fn kill_connection_not_established() {
3✔
5164
        let mut rng = thread_rng();
2✔
5165
        let (udp_tx, udp_rx) = mpsc::channel(2);
2✔
5166
        let (lossless_tx, _lossless_rx) = mpsc::unbounded();
2✔
5167
        let (lossy_tx, _lossy_rx) = mpsc::unbounded();
2✔
5168
        let dht_sk = SecretKey::generate(&mut rng);
1✔
5169
        let dht_pk = dht_sk.public_key();
1✔
5170
        let real_sk = SecretKey::generate(&mut rng);
2✔
5171
        let real_pk = real_sk.public_key();
1✔
5172
        let precomputed_keys = PrecomputedCache::new(dht_sk.clone(), 1);
2✔
5173
        let net_crypto = NetCrypto::new(NetCryptoNewArgs {
1✔
5174
            udp_tx,
1✔
5175
            lossless_tx,
1✔
5176
            lossy_tx,
1✔
5177
            dht_pk: dht_pk.clone(),
1✔
5178
            dht_sk: dht_sk.clone(),
1✔
5179
            real_pk: real_pk.clone(),
1✔
5180
            real_sk,
1✔
5181
            precomputed_keys,
1✔
5182
        });
5183

5184
        let peer_dht_pk = SecretKey::generate(&mut rng).public_key();
2✔
5185
        let peer_real_pk = SecretKey::generate(&mut rng).public_key();
1✔
5186
        let dht_precomputed_key = SalsaBox::new(&peer_dht_pk, &dht_sk);
1✔
5187
        let mut connection =
2✔
5188
            CryptoConnection::new(&dht_precomputed_key, dht_pk, real_pk, peer_real_pk.clone(), peer_dht_pk);
5189

5190
        let addr = "127.0.0.1:12345".parse().unwrap();
2✔
5191
        connection.set_udp_addr(addr);
1✔
5192

5193
        net_crypto
4✔
5194
            .connections
5195
            .write()
5196
            .await
2✔
5197
            .insert(peer_real_pk.clone(), Arc::new(RwLock::new(connection)));
1✔
5198
        net_crypto
4✔
5199
            .keys_by_addr
5200
            .write()
5201
            .await
2✔
5202
            .insert((addr.ip(), addr.port()), peer_real_pk.clone());
1✔
5203

5204
        net_crypto.kill_connection(peer_real_pk.clone()).await.unwrap();
1✔
5205

5206
        assert!(!net_crypto.connections.read().await.contains_key(&peer_real_pk));
1✔
5207
        assert!(!net_crypto
4✔
5208
            .keys_by_addr
5209
            .read()
5210
            .await
2✔
5211
            .contains_key(&(addr.ip(), addr.port())));
1✔
5212

5213
        // Necessary to drop udp_tx so that udp_rx.collect() can be finished
5214
        drop(net_crypto.udp_tx);
1✔
5215

5216
        assert!(udp_rx.collect::<Vec<_>>().await.is_empty());
2✔
5217
    }
5218
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc