mod crypto_connection;
mod packets_array;
pub use self::crypto_connection::*;
use self::packets_array::*;
use std::collections::HashMap;
use std::io::{ErrorKind, Error};
use std::net::{SocketAddr, IpAddr};
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::u16;
use futures::Future;
use futures::future;
use futures::sync::mpsc;
use parking_lot::RwLock;
use toxcore::binary_io::*;
use toxcore::crypto_core::*;
use toxcore::dht::packet::*;
use toxcore::io_tokio::*;
use toxcore::time::*;
const DHT_ATTEMPT_MAX_PACKET_LENGTH: usize = 95;
const NONCE_DIFF_THRESHOLD: u16 = u16::MAX / 3;
const PACKET_ID_REQUEST: u8 = 1;
const PACKET_ID_KILL: u8 = 2;
const PACKET_ID_CRYPTO_RANGE_END: u8 = 15;
const PACKET_ID_LOSSY_RANGE_START: u8 = 192;
const PACKET_ID_LOSSY_RANGE_END: u8 = 254;
type UdpTx = mpsc::UnboundedSender<(DhtPacket, SocketAddr)>;
type DhtPkTx = mpsc::UnboundedSender<(PublicKey, PublicKey)>;
type LosslessTx = mpsc::UnboundedSender<(PublicKey, Vec<u8>)>;
type LossyTx = mpsc::UnboundedSender<(PublicKey, Vec<u8>)>;
#[derive(Clone)]
pub struct NetCryptoNewArgs {
pub udp_tx: UdpTx,
pub dht_pk_tx: DhtPkTx,
pub lossless_tx: LosslessTx,
pub lossy_tx: LossyTx,
pub dht_pk: PublicKey,
pub dht_sk: SecretKey,
pub real_pk: PublicKey,
}
#[derive(Clone)]
pub struct NetCrypto {
udp_tx: UdpTx,
dht_pk_tx: DhtPkTx,
lossless_tx: LosslessTx,
lossy_tx: LossyTx,
dht_pk: PublicKey,
dht_sk: SecretKey,
real_pk: PublicKey,
symmetric_key: secretbox::Key,
connections: Arc<RwLock<HashMap<PublicKey, Arc<RwLock<CryptoConnection>>>>>,
keys_by_addr: Arc<RwLock<HashMap<(IpAddr, /*port*/ u16), PublicKey>>>,
}
impl NetCrypto {
pub fn new(args: NetCryptoNewArgs) -> NetCrypto {
NetCrypto {
udp_tx: args.udp_tx,
dht_pk_tx: args.dht_pk_tx,
lossless_tx: args.lossless_tx,
lossy_tx: args.lossy_tx,
dht_pk: args.dht_pk,
dht_sk: args.dht_sk,
real_pk: args.real_pk,
symmetric_key: secretbox::gen_key(),
connections: Arc::new(RwLock::new(HashMap::new())),
keys_by_addr: Arc::new(RwLock::new(HashMap::new()))
}
}
fn send_to_udp(&self, addr: SocketAddr, packet: DhtPacket) -> IoFuture<()> {
send_to(&self.udp_tx, (packet, addr))
}
fn key_by_addr(&self, addr: SocketAddr) -> Option<PublicKey> {
self.keys_by_addr.read().get(&(addr.ip(), addr.port())).cloned()
}
fn connection_by_key(&self, pk: PublicKey) -> Option<Arc<RwLock<CryptoConnection>>> {
self.connections.read().get(&pk).cloned()
}
fn handle_cookie_request(&self, packet: CookieRequest) -> Result<CookieResponse, Error> {
let payload = packet.get_payload(&self.dht_sk)?;
let cookie = Cookie::new(payload.pk, packet.pk);
let encrypted_cookie = EncryptedCookie::new(&self.symmetric_key, cookie);
let response_payload = CookieResponsePayload {
cookie: encrypted_cookie,
id: payload.id,
};
let precomputed_key = precompute(&packet.pk, &self.dht_sk);
let response = CookieResponse::new(&precomputed_key, response_payload);
Ok(response)
}
pub fn handle_udp_cookie_request(&self, packet: CookieRequest, addr: SocketAddr) -> IoFuture<()> {
match self.handle_cookie_request(packet) {
Ok(response) => self.send_to_udp(addr, DhtPacket::CookieResponse(response)),
Err(e) => Box::new(future::err(e))
}
}
pub fn handle_cookie_response(&self, connection: &mut CryptoConnection, packet: CookieResponse) -> IoFuture<()> {
let cookie_request_id = if let ConnectionStatus::CookieRequesting { cookie_request_id, .. } = connection.status {
cookie_request_id
} else {
return Box::new(future::err(Error::new(
ErrorKind::Other,
"Can't handle CookieResponse in current connection state"
)))
};
let payload = match packet.get_payload(&connection.dht_precomputed_key) {
Ok(payload) => payload,
Err(e) => return Box::new(future::err(e)),
};
if payload.id != cookie_request_id {
return Box::new(future::err(Error::new(
ErrorKind::Other,
format!("Invalid cookie request id: expected {} but got {}", cookie_request_id, payload.id)
)))
}
let sent_nonce = gen_nonce();
let our_cookie = Cookie::new(connection.peer_real_pk, connection.peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&self.symmetric_key, our_cookie);
let handshake_payload = CryptoHandshakePayload {
base_nonce: sent_nonce,
session_pk: connection.session_pk,
cookie_hash: payload.cookie.hash(),
cookie: our_encrypted_cookie,
};
let handshake = CryptoHandshake::new(&connection.dht_precomputed_key, handshake_payload, payload.cookie);
connection.status = ConnectionStatus::HandshakeSending {
sent_nonce,
packet: StatusPacket::new_crypto_handshake(handshake)
};
self.send_status_packet(connection)
}
pub fn handle_udp_cookie_response(&self, packet: CookieResponse, addr: SocketAddr) -> IoFuture<()> {
let connection = self.key_by_addr(addr).and_then(|pk| self.connection_by_key(pk));
if let Some(connection) = connection {
let mut connection = connection.write();
connection.update_udp_received_time();
self.handle_cookie_response(&mut connection, packet)
} else {
Box::new(future::err(
Error::new(
ErrorKind::Other,
format!("No crypto connection for address {}", addr)
)
))
}
}
pub fn handle_crypto_handshake(&self, connection: &mut CryptoConnection, packet: CryptoHandshake) -> IoFuture<()> {
if let ConnectionStatus::Established { .. } = connection.status {
return Box::new(future::err(Error::new(
ErrorKind::Other,
"Can't handle CryptoHandshake in current connection state"
)))
}
let payload = match packet.get_payload(&connection.dht_precomputed_key) {
Ok(payload) => payload,
Err(e) => return Box::new(future::err(e)),
};
if packet.cookie.hash() != payload.cookie_hash {
return Box::new(future::err(Error::new(
ErrorKind::Other,
"Invalid SHA512 hash of cookie"
)))
}
let cookie = match packet.cookie.get_payload(&self.symmetric_key) {
Ok(cookie) => cookie,
Err(e) => return Box::new(future::err(e)),
};
if cookie.is_timed_out() {
return Box::new(future::err(Error::new(
ErrorKind::Other,
"Cookie is timed out"
)))
}
if cookie.real_pk != connection.peer_real_pk {
return Box::new(future::err(Error::new(
ErrorKind::Other,
"Cookie contains invalid real pk"
)))
}
if cookie.dht_pk != connection.peer_dht_pk {
return Box::new(
send_to(&self.dht_pk_tx, (connection.peer_real_pk, cookie.dht_pk))
.and_then(|()| future::err(Error::new(
ErrorKind::Other,
"Cookie contains invalid dht pk"
)))
)
}
connection.status = match connection.status {
ConnectionStatus::CookieRequesting { .. } => {
let sent_nonce = gen_nonce();
let our_cookie = Cookie::new(connection.peer_real_pk, connection.peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&self.symmetric_key, our_cookie);
let handshake_payload = CryptoHandshakePayload {
base_nonce: sent_nonce,
session_pk: connection.session_pk,
cookie_hash: payload.cookie.hash(),
cookie: our_encrypted_cookie,
};
let handshake = CryptoHandshake::new(&connection.dht_precomputed_key, handshake_payload, payload.cookie);
ConnectionStatus::NotConfirmed {
sent_nonce,
received_nonce: payload.base_nonce,
peer_session_pk: payload.session_pk,
session_precomputed_key: precompute(&payload.session_pk, &connection.session_sk),
packet: StatusPacket::new_crypto_handshake(handshake)
}
},
ConnectionStatus::HandshakeSending { sent_nonce, ref packet, .. }
| ConnectionStatus::NotConfirmed { sent_nonce, ref packet, .. } => ConnectionStatus::NotConfirmed {
sent_nonce,
received_nonce: payload.base_nonce,
peer_session_pk: payload.session_pk,
session_precomputed_key: precompute(&payload.session_pk, &connection.session_sk),
packet: packet.clone()
},
ConnectionStatus::Established { .. } => unreachable!("Checked for Established status above"),
};
self.send_status_packet(connection)
}
pub fn handle_udp_crypto_handshake(&self, packet: CryptoHandshake, addr: SocketAddr) -> IoFuture<()> {
let connection = self.key_by_addr(addr).and_then(|pk| self.connection_by_key(pk));
if let Some(connection) = connection {
let mut connection = connection.write();
connection.update_udp_received_time();
self.handle_crypto_handshake(&mut connection, packet)
} else {
Box::new(future::err( Error::new(
ErrorKind::Other,
format!("No crypto connection for address {}", addr)
)
))
}
}
fn handle_request_packet(send_array: &mut PacketsArray<SentPacket>, mut data: &[u8], rtt: Duration, last_sent_time: &mut Option<Instant>) {
let mut n = 1;
for i in send_array.buffer_start .. send_array.buffer_end {
if data.is_empty() {
break
}
if n == data[0] { if let Some(packet) = send_array.get_mut(i) {
if clock_elapsed(packet.sent_time) > rtt { packet.requested = true;
}
}
n = 0;
data = &data[1..];
} else if let Some(packet) = send_array.remove(i) { if last_sent_time.map(|time| time < packet.sent_time).unwrap_or(true) {
*last_sent_time = Some(packet.sent_time);
}
}
if n == 255 {
n = 1;
data = &data[1..];
} else {
n += 1;
}
}
}
fn process_ready_lossless_packets(&self, recv_array: &mut PacketsArray<RecvPacket>, pk: PublicKey) -> IoFuture<()> {
let mut futures = Vec::new();
while let Some(packet) = recv_array.pop_front() {
let future = send_to(&self.lossless_tx, (pk, packet.data));
futures.push(future);
}
Box::new(future::join_all(futures).map(|_| ()))
}
fn last_sent_time(send_array: &PacketsArray<SentPacket>, index: u32) -> Option<Instant> {
let mut last_sent_time = None;
for i in send_array.buffer_start .. index {
if let Some(packet) = send_array.get(i) {
if last_sent_time.map(|time| time < packet.sent_time).unwrap_or(true) {
last_sent_time = Some(packet.sent_time);
}
}
}
last_sent_time
}
fn handle_crypto_data(&self, connection: &mut CryptoConnection, packet: CryptoData, udp: bool) -> IoFuture<()> {
let (sent_nonce, mut received_nonce, peer_session_pk, session_precomputed_key) = match connection.status {
ConnectionStatus::NotConfirmed { sent_nonce, received_nonce, peer_session_pk, ref session_precomputed_key, .. }
| ConnectionStatus::Established { sent_nonce, received_nonce, peer_session_pk, ref session_precomputed_key } => {
(sent_nonce, received_nonce, peer_session_pk, session_precomputed_key.clone())
},
_ => {
return Box::new(future::err(Error::new(
ErrorKind::Other,
"Can't handle CryptoData in current connection state"
)))
}
};
let cur_last_bytes = CryptoData::nonce_last_bytes(received_nonce);
let (diff, _) = packet.nonce_last_bytes.overflowing_sub(cur_last_bytes);
let mut packet_nonce = received_nonce;
increment_nonce_number(&mut packet_nonce, diff as usize);
let payload = match packet.get_payload(&session_precomputed_key, &packet_nonce) {
Ok(payload) => payload,
Err(e) => return Box::new(future::err(e))
};
let mut last_sent_time = NetCrypto::last_sent_time(&connection.send_array, payload.buffer_start);
if let Err(e) = connection.send_array.set_buffer_start(payload.buffer_start) {
return Box::new(future::err(e))
}
let packet_id = match payload.data.first() {
Some(&packet_id) => packet_id,
None => return Box::new(future::err(Error::new(
ErrorKind::Other,
"Real data is empty"
)))
};
if packet_id == PACKET_ID_KILL {
self.connections.write().remove(&connection.peer_real_pk);
if let Some(addr) = connection.udp_addr {
self.keys_by_addr.write().remove(&(addr.ip(), addr.port()));
}
return Box::new(future::ok(()));
}
if diff > NONCE_DIFF_THRESHOLD * 2 {
increment_nonce_number(&mut received_nonce, NONCE_DIFF_THRESHOLD as usize);
}
connection.status = ConnectionStatus::Established {
sent_nonce,
received_nonce,
peer_session_pk,
session_precomputed_key
};
let result = if packet_id == PACKET_ID_REQUEST {
let rtt = if udp { connection.rtt } else { Duration::from_millis(TCP_RTT) };
NetCrypto::handle_request_packet(&mut connection.send_array, &payload.data[1..], rtt, &mut last_sent_time);
connection.recv_array.set_buffer_end(payload.packet_number).ok();
Box::new(future::ok(()))
} else if packet_id > PACKET_ID_CRYPTO_RANGE_END && packet_id < PACKET_ID_LOSSY_RANGE_START {
if let Err(e) = connection.recv_array.insert(payload.packet_number, RecvPacket::new(payload.data)) {
return Box::new(future::err(e))
}
self.process_ready_lossless_packets(&mut connection.recv_array, connection.peer_real_pk)
} else if packet_id >= PACKET_ID_LOSSY_RANGE_START && packet_id <= PACKET_ID_LOSSY_RANGE_END {
connection.recv_array.set_buffer_end(payload.packet_number).ok();
send_to(&self.lossy_tx, (connection.peer_real_pk, payload.data))
} else {
return Box::new(future::err(Error::new(
ErrorKind::Other,
format!("Invalid packet id: {}", packet_id)
)))
};
if let Some(last_sent_time) = last_sent_time {
let elapsed = clock_elapsed(last_sent_time);
if elapsed < connection.rtt {
connection.rtt = elapsed;
}
}
result
}
pub fn handle_udp_crypto_data(&self, packet: CryptoData, addr: SocketAddr) -> IoFuture<()> {
let connection = self.key_by_addr(addr).and_then(|pk| self.connection_by_key(pk));
if let Some(connection) = connection {
let mut connection = connection.write();
connection.update_udp_received_time();
self.handle_crypto_data(&mut connection, packet, true)
} else {
Box::new(future::err(
Error::new(
ErrorKind::Other,
format!("No crypto connection for address {}", addr)
)
))
}
}
fn send_packet(&self, packet: DhtPacket, connection: &mut CryptoConnection) -> IoFuture<()> {
if let Some(addr) = connection.udp_addr {
if connection.is_udp_alive() {
return self.send_to_udp(addr, packet)
}
let udp_attempt_should_be_made = connection.udp_attempt_should_be_made() && {
let mut buf = [0; DHT_ATTEMPT_MAX_PACKET_LENGTH];
packet.to_bytes((&mut buf, 0)).is_ok()
};
if udp_attempt_should_be_made {
connection.update_udp_send_attempt_time();
self.send_to_udp(addr, packet)
} else {
Box::new(future::ok(()))
}
} else {
Box::new(future::ok(()))
}
}
fn send_status_packet(&self, connection: &mut CryptoConnection) -> IoFuture<()> {
match connection.packet_to_send() {
Some(packet) => self.send_packet(packet, connection),
None => Box::new(future::ok(())),
}
}
pub fn main_loop(&self) -> IoFuture<()> {
let connections = self.connections.read();
let len = connections.len();
let mut send_futures = Vec::with_capacity(len);
let mut timed_out = Vec::with_capacity(len);
for (&pk, connection) in connections.iter() {
let mut connection = connection.write();
if connection.is_timed_out() {
timed_out.push((pk, connection.udp_addr));
continue;
}
let send_future = self.send_status_packet(&mut connection);
send_futures.push(send_future);
}
drop(connections);
if !timed_out.is_empty() {
let mut connections = self.connections.write();
let mut keys_by_addr = self.keys_by_addr.write();
for (pk, addr) in timed_out {
connections.remove(&pk);
if let Some(addr) = addr {
keys_by_addr.remove(&(addr.ip(), addr.port()));
}
}
}
Box::new(future::join_all(send_futures).map(|_| ()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use futures::Stream;
use tokio_executor;
use tokio_timer::clock::*;
use toxcore::time::ConstNow;
#[test]
fn net_crypto_clone() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk,
real_pk
});
let _net_crypto_c = net_crypto.clone();
}
#[test]
fn handle_cookie_request() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let precomputed_key = precompute(&peer_dht_pk, &dht_sk);
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk,
real_pk
});
let cookie_request_id = 12345;
let cookie_request_payload = CookieRequestPayload {
pk: peer_real_pk,
id: cookie_request_id,
};
let cookie_request = CookieRequest::new(&precomputed_key, &peer_dht_pk, cookie_request_payload);
let cookie_response = net_crypto.handle_cookie_request(cookie_request).unwrap();
let cookie_response_payload = cookie_response.get_payload(&precomputed_key).unwrap();
assert_eq!(cookie_response_payload.id, cookie_request_id);
let cookie = cookie_response_payload.cookie.get_payload(&net_crypto.symmetric_key).unwrap();
assert_eq!(cookie.dht_pk, peer_dht_pk);
assert_eq!(cookie.real_pk, peer_real_pk);
}
#[test]
fn handle_cookie_request_invalid() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk,
real_pk
});
let cookie_request = CookieRequest {
pk: gen_keypair().0,
nonce: gen_nonce(),
payload: vec![42; 88]
};
assert!(net_crypto.handle_cookie_request(cookie_request).is_err());
}
#[test]
fn handle_udp_cookie_request() {
let (udp_tx, udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let precomputed_key = precompute(&peer_dht_pk, &dht_sk);
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk,
real_pk
});
let cookie_request_id = 12345;
let cookie_request_payload = CookieRequestPayload {
pk: peer_real_pk,
id: cookie_request_id,
};
let cookie_request = CookieRequest::new(&precomputed_key, &peer_dht_pk, cookie_request_payload);
let addr = "127.0.0.1:12345".parse().unwrap();
assert!(net_crypto.handle_udp_cookie_request(cookie_request, addr).wait().is_ok());
let (received, _udp_rx) = udp_rx.into_future().wait().unwrap();
let (packet, addr_to_send) = received.unwrap();
let cookie_response = unpack!(packet, DhtPacket::CookieResponse);
assert_eq!(addr_to_send, addr);
let cookie_response_payload = cookie_response.get_payload(&precomputed_key).unwrap();
assert_eq!(cookie_response_payload.id, cookie_request_id);
let cookie = cookie_response_payload.cookie.get_payload(&net_crypto.symmetric_key).unwrap();
assert_eq!(cookie.dht_pk, peer_dht_pk);
assert_eq!(cookie.real_pk, peer_real_pk);
}
#[test]
fn handle_udp_cookie_request_invalid() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk,
real_pk
});
let cookie_request = CookieRequest {
pk: gen_keypair().0,
nonce: gen_nonce(),
payload: vec![42; 88]
};
let addr = "127.0.0.1:12345".parse().unwrap();
assert!(net_crypto.handle_udp_cookie_request(cookie_request, addr).wait().is_err());
}
#[test]
fn handle_cookie_response() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let cookie_request_id = unpack!(connection.status, ConnectionStatus::CookieRequesting, cookie_request_id);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let cookie_response_payload = CookieResponsePayload {
cookie: cookie.clone(),
id: cookie_request_id
};
let cookie_response = CookieResponse::new(&connection.dht_precomputed_key, cookie_response_payload);
assert!(net_crypto.handle_cookie_response(&mut connection, cookie_response).wait().is_ok());
let packet = unpack!(connection.status, ConnectionStatus::HandshakeSending, packet);
let packet = unpack!(packet.dht_packet(), DhtPacket::CryptoHandshake);
assert_eq!(packet.cookie, cookie);
let payload = packet.get_payload(&connection.dht_precomputed_key).unwrap();
assert_eq!(payload.cookie_hash, cookie.hash());
}
#[test]
fn handle_cookie_response_invalid_status() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new_not_confirmed(
dht_sk,
peer_real_pk,
peer_dht_pk,
gen_nonce(),
gen_keypair().0,
EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![42; 88]
},
&net_crypto.symmetric_key
);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let cookie_response_payload = CookieResponsePayload {
cookie,
id: 12345
};
let cookie_response = CookieResponse::new(&connection.dht_precomputed_key, cookie_response_payload);
assert!(net_crypto.handle_cookie_response(&mut connection, cookie_response).wait().is_err());
}
#[test]
fn handle_cookie_response_invalid_request_id() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let cookie_request_id = unpack!(connection.status, ConnectionStatus::CookieRequesting, cookie_request_id);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let cookie_response_payload = CookieResponsePayload {
cookie,
id: cookie_request_id.overflowing_add(1).0
};
let cookie_response = CookieResponse::new(&connection.dht_precomputed_key, cookie_response_payload);
assert!(net_crypto.handle_cookie_response(&mut connection, cookie_response).wait().is_err());
}
#[test]
fn handle_udp_cookie_response() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let dht_precomputed_key = connection.dht_precomputed_key.clone();
let cookie_request_id = unpack!(connection.status, ConnectionStatus::CookieRequesting, cookie_request_id);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let cookie_response_payload = CookieResponsePayload {
cookie: cookie.clone(),
id: cookie_request_id
};
let cookie_response = CookieResponse::new(&dht_precomputed_key, cookie_response_payload);
assert!(net_crypto.handle_udp_cookie_response(cookie_response, addr).wait().is_ok());
let connections = net_crypto.connections.read();
let connection = connections.get(&peer_real_pk).unwrap().read().clone();
let packet = unpack!(connection.status, ConnectionStatus::HandshakeSending, packet);
let packet = unpack!(packet.dht_packet(), DhtPacket::CryptoHandshake);
assert_eq!(packet.cookie, cookie);
let payload = packet.get_payload(&dht_precomputed_key).unwrap();
assert_eq!(payload.cookie_hash, cookie.hash());
}
#[test]
fn handle_udp_cookie_response_no_connection() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let dht_precomputed_key = precompute(&peer_dht_pk, &dht_sk);
let addr = "127.0.0.1:12345".parse().unwrap();
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let cookie_response_payload = CookieResponsePayload {
cookie: cookie.clone(),
id: 12345
};
let cookie_response = CookieResponse::new(&dht_precomputed_key, cookie_response_payload);
assert!(net_crypto.handle_udp_cookie_response(cookie_response, addr).wait().is_err());
}
#[test]
fn handle_crypto_handshake_in_cookie_requesting_status() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie: cookie.clone()
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_ok());
let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
let peer_session_pk = unpack!(connection.status, ConnectionStatus::NotConfirmed, peer_session_pk);
assert_eq!(received_nonce, base_nonce);
assert_eq!(peer_session_pk, session_pk);
let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
let packet = unpack!(packet.dht_packet(), DhtPacket::CryptoHandshake);
assert_eq!(packet.cookie, cookie);
let payload = packet.get_payload(&connection.dht_precomputed_key).unwrap();
assert_eq!(payload.cookie_hash, cookie.hash());
}
#[test]
fn handle_crypto_handshake_in_not_confirmed_status() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![42; 88]
};
let mut connection = CryptoConnection::new_not_confirmed(
dht_sk,
peer_real_pk,
peer_dht_pk,
gen_nonce(),
gen_keypair().0,
cookie.clone(),
&net_crypto.symmetric_key
);
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let other_cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie: other_cookie
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_ok());
let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
let peer_session_pk = unpack!(connection.status, ConnectionStatus::NotConfirmed, peer_session_pk);
assert_eq!(received_nonce, base_nonce);
assert_eq!(peer_session_pk, session_pk);
let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
let packet = unpack!(packet.dht_packet(), DhtPacket::CryptoHandshake);
assert_eq!(packet.cookie, cookie);
let payload = packet.get_payload(&connection.dht_precomputed_key).unwrap();
assert_eq!(payload.cookie_hash, cookie.hash());
}
#[test]
fn handle_crypto_handshake_invalid_status() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce: gen_nonce(),
peer_session_pk,
session_precomputed_key,
};
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_err());
}
#[test]
fn handle_crypto_handshake_invalid_hash() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: cookie.hash(),
cookie
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_err());
}
#[test]
fn handle_crypto_handshake_timed_out_cookie() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let mut our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
our_cookie.time -= COOKIE_TIMEOUT + 1;
let our_encrypted_cookie = EncryptedCookie::new(&&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_err());
}
#[test]
fn handle_crypto_handshake_invalid_peer_real_pk() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_dht_pk, peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_err());
}
#[test]
fn handle_crypto_handshake_invalid_peer_dht_pk() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let (new_dht_pk, _new_dht_sk) = gen_keypair();
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_real_pk, new_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie
};
let crypto_handshake = CryptoHandshake::new(&connection.dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_crypto_handshake(&mut connection, crypto_handshake).wait().is_err());
let (keys, _dht_pk_rx) = dht_pk_rx.into_future().wait().unwrap();
let (received_real_pk, received_dht_pk) = keys.unwrap();
assert_eq!(received_real_pk, peer_real_pk);
assert_eq!(received_dht_pk, new_dht_pk);
}
#[test]
fn handle_udp_crypto_handshake() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let dht_precomputed_key = connection.dht_precomputed_key.clone();
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
let base_nonce = gen_nonce();
let session_pk = gen_keypair().0;
let our_cookie = Cookie::new(peer_real_pk, peer_dht_pk);
let our_encrypted_cookie = EncryptedCookie::new(&net_crypto.symmetric_key, our_cookie);
let cookie = EncryptedCookie {
nonce: secretbox::gen_nonce(),
payload: vec![43; 88]
};
let crypto_handshake_payload = CryptoHandshakePayload {
base_nonce,
session_pk,
cookie_hash: our_encrypted_cookie.hash(),
cookie: cookie.clone()
};
let crypto_handshake = CryptoHandshake::new(&dht_precomputed_key, crypto_handshake_payload, our_encrypted_cookie);
assert!(net_crypto.handle_udp_crypto_handshake(crypto_handshake, addr).wait().is_ok());
let connections = net_crypto.connections.read();
let connection = connections.get(&peer_real_pk).unwrap().read().clone();
let received_nonce = unpack!(connection.status, ConnectionStatus::NotConfirmed, received_nonce);
let peer_session_pk = unpack!(connection.status, ConnectionStatus::NotConfirmed, peer_session_pk);
assert_eq!(received_nonce, base_nonce);
assert_eq!(peer_session_pk, session_pk);
let packet = unpack!(connection.status, ConnectionStatus::NotConfirmed, packet);
let packet = unpack!(packet.dht_packet(), DhtPacket::CryptoHandshake);
assert_eq!(packet.cookie, cookie);
let payload = packet.get_payload(&dht_precomputed_key).unwrap();
assert_eq!(payload.cookie_hash, cookie.hash());
}
#[test]
fn handle_crypto_data_lossy() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_ok());
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
let (received, _lossy_rx) = lossy_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
}
#[test]
fn handle_crypto_data_lossy_increment_nonce() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let mut packet_nonce = received_nonce;
increment_nonce_number(&mut packet_nonce, (2 * NONCE_DIFF_THRESHOLD + 1) as usize);
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, packet_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_ok());
let mut expected_nonce = received_nonce;
increment_nonce_number(&mut expected_nonce, NONCE_DIFF_THRESHOLD as usize);
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), expected_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
let (received, _lossy_rx) = lossy_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
}
#[test]
fn handle_crypto_data_lossy_update_rtt() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let now = Instant::now();
let sent_packet = SentPacket {
data: vec![42; 123],
sent_time: now,
requested: false,
};
assert!(connection.send_array.insert(0, sent_packet).is_ok());
connection.rtt = Duration::from_millis(500);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 1,
packet_number: 0,
data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
let mut enter = tokio_executor::enter().unwrap();
let clock = Clock::new_with_now(ConstNow(now + Duration::from_millis(250)));
with_default(&clock, &mut enter, |_| {
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_ok());
});
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 1);
assert_eq!(connection.send_array.buffer_end, 1);
let (received, _lossy_rx) = lossy_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
assert_eq!(connection.rtt, Duration::from_millis(250));
}
#[test]
fn handle_crypto_data_lossy_invalid_buffer_start() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 7, packet_number: 0,
data: vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_err());
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
}
#[test]
fn handle_crypto_data_lossless() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload_1 = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 1, 2, 3]
};
let crypto_data_1 = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload_1);
let crypto_data_payload_2 = CryptoDataPayload {
buffer_start: 0,
packet_number: 1,
data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 4, 5, 6]
};
let crypto_data_2 = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload_2);
let crypto_data_payload_3 = CryptoDataPayload {
buffer_start: 0,
packet_number: 2,
data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 7, 8, 9]
};
let crypto_data_3 = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload_3);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data_2, true).wait().is_ok());
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data_3, true).wait().is_ok());
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data_1, true).wait().is_ok());
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 3);
assert_eq!(connection.recv_array.buffer_end, 3);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
let (received, lossless_rx) = lossless_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START - 1, 1, 2, 3]);
let (received, lossless_rx) = lossless_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START - 1, 4, 5, 6]);
let (received, _lossless_rx) = lossless_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START - 1, 7, 8, 9]);
}
#[test]
fn handle_crypto_data_lossless_too_big_index() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: CRYPTO_PACKET_BUFFER_SIZE,
data: vec![PACKET_ID_LOSSY_RANGE_START - 1, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_err());
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
}
#[test]
fn handle_crypto_data_kill() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let connection = Arc::new(RwLock::new(connection));
net_crypto.connections.write().insert(peer_real_pk, connection.clone());
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![PACKET_ID_KILL]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection.write(), crypto_data, true).wait().is_ok());
assert!(net_crypto.connections.read().is_empty());
assert!(net_crypto.keys_by_addr.read().is_empty());
}
#[test]
fn handle_crypto_data_request() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let now = Instant::now();
assert!(connection.send_array.insert(0, SentPacket::new(vec![42; 123])).is_ok());
let packet_1 = SentPacket {
data: vec![43; 123],
sent_time: now + Duration::from_millis(750),
requested: false,
};
assert!(connection.send_array.insert(1, packet_1).is_ok());
let packet_5 = SentPacket {
data: vec![44; 123],
sent_time: now + Duration::from_millis(750),
requested: false,
};
assert!(connection.send_array.insert(5, packet_5).is_ok());
assert!(connection.send_array.insert(7, SentPacket::new(vec![45; 123])).is_ok());
assert!(connection.send_array.insert(1024, SentPacket::new(vec![46; 123])).is_ok());
connection.rtt = Duration::from_millis(500);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![PACKET_ID_REQUEST, 1, 5, 0, 0, 0, 254] };
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
let mut enter = tokio_executor::enter().unwrap();
let clock = Clock::new_with_now(ConstNow(now + Duration::from_secs(1)));
with_default(&clock, &mut enter, |_| {
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_ok());
});
assert!(connection.send_array.get(0).unwrap().requested);
assert!(connection.send_array.get(1).is_none());
assert!(!connection.send_array.get(5).unwrap().requested);
assert!(connection.send_array.get(7).is_none());
assert!(connection.send_array.get(1024).unwrap().requested);
assert_eq!(connection.rtt, Duration::from_millis(250));
}
#[test]
fn handle_crypto_data_empty_request() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
assert!(connection.send_array.insert(0, SentPacket::new(vec![42; 123])).is_ok());
assert!(connection.send_array.insert(1, SentPacket::new(vec![43; 123])).is_ok());
assert!(connection.send_array.insert(5, SentPacket::new(vec![44; 123])).is_ok());
assert!(connection.send_array.insert(7, SentPacket::new(vec![45; 123])).is_ok());
assert!(connection.send_array.insert(1024, SentPacket::new(vec![46; 123])).is_ok());
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![PACKET_ID_REQUEST]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_ok());
assert!(!connection.send_array.get(0).unwrap().requested);
assert!(!connection.send_array.get(1).unwrap().requested);
assert!(!connection.send_array.get(5).unwrap().requested);
assert!(!connection.send_array.get(7).unwrap().requested);
assert!(!connection.send_array.get(1024).unwrap().requested);
}
#[test]
fn handle_crypto_data_invalid_packet_id() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![255, 1, 2, 3] };
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_err());
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
}
#[test]
fn handle_crypto_data_empty_data() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: Vec::new()
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_err());
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
}
#[test]
fn handle_crypto_data_invalid_status() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![0, 0, PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_crypto_data(&mut connection, crypto_data, true).wait().is_err());
}
#[test]
fn handle_udp_crypto_data_lossy() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let received_nonce = gen_nonce();
let (peer_session_pk, _peer_session_sk) = gen_keypair();
let (_session_pk, session_sk) = gen_keypair();
let session_precomputed_key = precompute(&peer_session_pk, &session_sk);
connection.status = ConnectionStatus::Established {
sent_nonce: gen_nonce(),
received_nonce,
peer_session_pk,
session_precomputed_key: session_precomputed_key.clone(),
};
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
let crypto_data_payload = CryptoDataPayload {
buffer_start: 0,
packet_number: 0,
data: vec![0, 0, PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]
};
let crypto_data = CryptoData::new(&session_precomputed_key, received_nonce, crypto_data_payload);
assert!(net_crypto.handle_udp_crypto_data(crypto_data, addr).wait().is_ok());
let connections = net_crypto.connections.read();
let connection = connections.get(&peer_real_pk).unwrap().read().clone();
assert_eq!(unpack!(connection.status, ConnectionStatus::Established, received_nonce), received_nonce);
assert_eq!(connection.recv_array.buffer_start, 0);
assert_eq!(connection.recv_array.buffer_end, 0);
assert_eq!(connection.send_array.buffer_start, 0);
assert_eq!(connection.send_array.buffer_end, 0);
let (received, _lossy_rx) = lossy_rx.into_future().wait().unwrap();
let (received_peer_real_pk, received_data) = received.unwrap();
assert_eq!(received_peer_real_pk, peer_real_pk);
assert_eq!(received_data, vec![PACKET_ID_LOSSY_RANGE_START, 1, 2, 3]);
}
#[test]
fn send_status_packet() {
let (udp_tx, udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
connection.update_udp_received_time();
assert!(net_crypto.send_status_packet(&mut connection).wait().is_ok());
let packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet);
assert_eq!(packet.num_sent, 1);
let (received, _udp_rx) = udp_rx.into_future().wait().unwrap();
let (received, addr_to_send) = received.unwrap();
assert_eq!(received, packet.dht_packet());
assert_eq!(addr_to_send, addr);
assert!(net_crypto.send_status_packet(&mut connection).wait().is_ok());
let packet = unpack!(connection.status, ConnectionStatus::CookieRequesting, packet);
assert_eq!(packet.num_sent, 1);
}
#[test]
fn send_packet_udp() {
let (udp_tx, udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
connection.update_udp_received_time();
let packet = DhtPacket::CryptoData(CryptoData {
nonce_last_bytes: 123,
payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH]
});
assert!(net_crypto.send_packet(packet.clone(), &mut connection).wait().is_ok());
let (received, _udp_rx) = udp_rx.into_future().wait().unwrap();
let (received, addr_to_send) = received.unwrap();
assert_eq!(addr_to_send, addr);
assert_eq!(received, packet);
}
#[test]
fn send_packet_udp_attempt() {
let (udp_tx, udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
let packet = DhtPacket::CryptoData(CryptoData {
nonce_last_bytes: 123,
payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH - 3] });
assert!(net_crypto.send_packet(packet.clone(), &mut connection).wait().is_ok());
let (received, _udp_rx) = udp_rx.into_future().wait().unwrap();
let (received, addr_to_send) = received.unwrap();
assert_eq!(addr_to_send, addr);
assert_eq!(received, packet);
}
#[test]
fn send_packet_no_udp_attempt() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
let packet = DhtPacket::CryptoData(CryptoData {
nonce_last_bytes: 123,
payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH]
});
assert!(net_crypto.send_packet(packet.clone(), &mut connection).wait().is_ok());
}
#[test]
fn send_packet_tcp() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let packet = DhtPacket::CryptoData(CryptoData {
nonce_last_bytes: 123,
payload: vec![42; DHT_ATTEMPT_MAX_PACKET_LENGTH]
});
assert!(net_crypto.send_packet(packet.clone(), &mut connection).wait().is_ok());
}
#[test]
fn main_loop_sends_status_packets() {
let (udp_tx, udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet).dht_packet();
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
connection.update_udp_received_time();
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
assert!(net_crypto.main_loop().wait().is_ok());
let (received, _udp_rx) = udp_rx.into_future().wait().unwrap();
let (received, addr_to_send) = received.unwrap();
assert_eq!(addr_to_send, addr);
assert_eq!(received, packet);
}
#[test]
fn main_loop_removes_timed_out_connections() {
let (udp_tx, _udp_rx) = mpsc::unbounded();
let (dht_pk_tx, _dht_pk_rx) = mpsc::unbounded();
let (lossless_tx, _lossless_rx) = mpsc::unbounded();
let (lossy_tx, _lossy_rx) = mpsc::unbounded();
let (dht_pk, dht_sk) = gen_keypair();
let (real_pk, _real_sk) = gen_keypair();
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
udp_tx,
dht_pk_tx,
lossless_tx,
lossy_tx,
dht_pk,
dht_sk: dht_sk.clone(),
real_pk
});
let (peer_dht_pk, _peer_dht_sk) = gen_keypair();
let (peer_real_pk, _peer_real_sk) = gen_keypair();
let mut connection = CryptoConnection::new(dht_sk, dht_pk, real_pk, peer_real_pk, peer_dht_pk);
let addr = "127.0.0.1:12345".parse().unwrap();
connection.udp_addr = Some(addr);
let cookie_request_id = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, cookie_request_id);
let mut packet = unpack!(connection.status.clone(), ConnectionStatus::CookieRequesting, packet);
packet.num_sent = MAX_NUM_SENDPACKET_TRIES;
packet.sent_time -= Duration::from_secs(CRYPTO_SEND_PACKET_INTERVAL + 1);
connection.status = ConnectionStatus::CookieRequesting {
cookie_request_id,
packet
};
assert!(connection.is_timed_out());
net_crypto.connections.write().insert(peer_real_pk, Arc::new(RwLock::new(connection)));
net_crypto.keys_by_addr.write().insert((addr.ip(), addr.port()), peer_real_pk);
assert!(net_crypto.main_loop().wait().is_ok());
assert!(net_crypto.connections.read().is_empty());
assert!(net_crypto.keys_by_addr.read().is_empty());
}
}