// VpnCloud - Peer-to-Peer VPN // Copyright (C) 2015-2021 Dennis Schwerdel // This software is licensed under GPL-3 or newer (see LICENSE.md) mod nat; mod payload; mod peers; use std::{ collections::{HashMap, VecDeque}, io::Write, net::SocketAddr, sync::{ atomic::{AtomicUsize, Ordering}, Once } }; pub use super::{ cloud::GenericCloud, config::{Config, CryptoConfig}, device::{MockDevice, Type}, net::MockSocket, payload::{Frame, Packet, Protocol}, types::Range, util::{MockTimeSource, Time, TimeSource} }; static INIT_LOGGER: Once = Once::new(); pub fn init_debug_logger() { INIT_LOGGER.call_once(|| { log::set_boxed_logger(Box::new(DebugLogger)).unwrap(); log::set_max_level(log::LevelFilter::Debug); }) } static CURRENT_NODE: AtomicUsize = AtomicUsize::new(0); struct DebugLogger; impl DebugLogger { pub fn set_node(node: usize) { CURRENT_NODE.store(node, Ordering::SeqCst); } } impl log::Log for DebugLogger { #[inline] fn enabled(&self, _metadata: &log::Metadata) -> bool { true } #[inline] fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) { eprintln!("Node {} - {} - {}", CURRENT_NODE.load(Ordering::SeqCst), record.level(), record.args()); } } #[inline] fn flush(&self) { std::io::stderr().flush().expect("Failed to flush") } } type TestNode
= GenericCloud {
pub fn new() -> Self {
init_debug_logger();
MockTimeSource::set_time(0);
Self { next_port: 1, nodes: HashMap::default(), messages: VecDeque::default() }
}
pub fn add_node(&mut self, nat: bool, config: &Config) -> SocketAddr {
let mut config = config.clone();
MockSocket::set_nat(nat);
config.listen = format!("[::]:{}", self.next_port);
let addr = config.listen.parse:: {
let node = self.nodes.get_mut(&addr).unwrap();
DebugLogger::set_node(node.get_num());
node
}
pub fn simulate_next_message(&mut self) {
if let Some((src, dst, data)) = self.messages.pop_front() {
if let Some(node) = self.nodes.get_mut(&dst) {
if node.socket().put_inbound(src, data) {
DebugLogger::set_node(node.get_num());
node.trigger_socket_event();
DebugLogger::set_node(0);
let sock = node.socket();
let src = dst;
while let Some((dst, data)) = sock.pop_outbound() {
self.messages.push_back((src, dst, data));
}
}
} else {
warn!("Message to unknown node {}", dst);
}
}
}
pub fn simulate_all_messages(&mut self) {
while !self.messages.is_empty() {
self.simulate_next_message()
}
}
pub fn trigger_node_housekeep(&mut self, addr: SocketAddr) {
let node = self.nodes.get_mut(&addr).unwrap();
DebugLogger::set_node(node.get_num());
node.trigger_housekeep();
DebugLogger::set_node(0);
let sock = node.socket();
while let Some((dst, data)) = sock.pop_outbound() {
self.messages.push_back((addr, dst, data));
}
}
pub fn trigger_housekeep(&mut self) {
for (src, node) in &mut self.nodes {
DebugLogger::set_node(node.get_num());
node.trigger_housekeep();
DebugLogger::set_node(0);
let sock = node.socket();
while let Some((dst, data)) = sock.pop_outbound() {
self.messages.push_back((*src, dst, data));
}
}
}
pub fn set_time(&mut self, time: Time) {
MockTimeSource::set_time(time);
}
pub fn simulate_time(&mut self, time: Time) {
let mut t = MockTimeSource::now();
while t < time {
t += 1;
self.set_time(t);
self.trigger_housekeep();
self.simulate_all_messages();
}
}
pub fn connect(&mut self, src: SocketAddr, dst: SocketAddr) {
let node = self.nodes.get_mut(&src).unwrap();
DebugLogger::set_node(node.get_num());
node.connect(dst).unwrap();
DebugLogger::set_node(0);
let sock = node.socket();
while let Some((dst, data)) = sock.pop_outbound() {
self.messages.push_back((src, dst, data));
}
}
pub fn is_connected(&self, src: SocketAddr, dst: SocketAddr) -> bool {
self.nodes.get(&src).unwrap().is_connected(&dst)
}
#[allow(dead_code)]
pub fn node_addresses(&self) -> Vec