mirror of https://github.com/dswd/vpncloud.git
More tests
This commit is contained in:
parent
c750947ab0
commit
5be254db4a
95
src/cloud.rs
95
src/cloud.rs
|
@ -40,7 +40,7 @@ struct PeerData {
|
||||||
alt_addrs: Vec<SocketAddr>,
|
alt_addrs: Vec<SocketAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerList<TS: TimeSource> {
|
pub struct PeerList<TS: TimeSource> {
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
peers: HashMap<SocketAddr, PeerData, Hash>,
|
peers: HashMap<SocketAddr, PeerData, Hash>,
|
||||||
nodes: HashMap<NodeId, SocketAddr, Hash>,
|
nodes: HashMap<NodeId, SocketAddr, Hash>,
|
||||||
|
@ -81,12 +81,12 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn contains_addr(&self, addr: &SocketAddr) -> bool {
|
pub fn contains_addr(&self, addr: &SocketAddr) -> bool {
|
||||||
self.addresses.contains_key(addr)
|
self.addresses.contains_key(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_connected<Addr: ToSocketAddrs+fmt::Debug>(&self, addr: Addr) -> Result<bool, Error> {
|
pub fn is_connected<Addr: ToSocketAddrs+fmt::Debug>(&self, addr: Addr) -> Result<bool, Error> {
|
||||||
for addr in try!(resolve(&addr)) {
|
for addr in try!(resolve(&addr)) {
|
||||||
if self.contains_addr(&addr) {
|
if self.contains_addr(&addr) {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
|
@ -96,7 +96,7 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn contains_node(&self, node_id: &NodeId) -> bool {
|
pub fn contains_node(&self, node_id: &NodeId) -> bool {
|
||||||
self.nodes.contains_key(node_id)
|
self.nodes.contains_key(node_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,23 +142,23 @@ impl<TS: TimeSource> PeerList<TS> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_node_id(&self, addr: &SocketAddr) -> Option<NodeId> {
|
pub fn get_node_id(&self, addr: &SocketAddr) -> Option<NodeId> {
|
||||||
self.addresses.get(addr).map(|n| *n)
|
self.addresses.get(addr).map(|n| *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_vec(&self) -> Vec<SocketAddr> {
|
pub fn as_vec(&self) -> Vec<SocketAddr> {
|
||||||
self.addresses.keys().cloned().collect()
|
self.addresses.keys().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.peers.len()
|
self.peers.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.peers.is_empty()
|
self.peers.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,12 +687,13 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
}
|
}
|
||||||
// Reply with stage=1 if stage is 0
|
// Reply with stage=1 if stage is 0
|
||||||
if stage == 0 {
|
if stage == 0 {
|
||||||
let peers = self.peers.as_vec();
|
|
||||||
let own_addrs = self.addresses.clone();
|
let own_addrs = self.addresses.clone();
|
||||||
let own_node_id = self.node_id;
|
let own_node_id = self.node_id;
|
||||||
try!(self.send_msg(peer, &mut Message::Init(stage+1, own_node_id, own_addrs)));
|
try!(self.send_msg(peer, &mut Message::Init(stage+1, own_node_id, own_addrs)));
|
||||||
try!(self.send_msg(peer, &mut Message::Peers(peers)));
|
|
||||||
}
|
}
|
||||||
|
// Send peers in any case
|
||||||
|
let peers = self.peers.as_vec();
|
||||||
|
try!(self.send_msg(peer, &mut Message::Peers(peers)));
|
||||||
},
|
},
|
||||||
Message::Close => {
|
Message::Close => {
|
||||||
self.peers.remove(&peer);
|
self.peers.remove(&peer);
|
||||||
|
@ -712,10 +713,6 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_message<'a>(&self, msg: &'a mut [u8]) -> Result<Message<'a>, Error> {
|
|
||||||
decode(msg, self.magic, &self.crypto)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_socket_data(&mut self, src: SocketAddr, data: &mut [u8]) {
|
fn handle_socket_data(&mut self, src: SocketAddr, data: &mut [u8]) {
|
||||||
let size = data.len();
|
let size = data.len();
|
||||||
if let Err(e) = decode(data, self.magic, &mut self.crypto).and_then(|msg| {
|
if let Err(e) = decode(data, self.magic, &mut self.crypto).and_then(|msg| {
|
||||||
|
@ -788,42 +785,52 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)] use super::ethernet::{self, SwitchTable};
|
|
||||||
#[cfg(test)] use super::util::MockTimeSource;
|
|
||||||
#[cfg(test)] use super::net::MockSocket;
|
#[cfg(test)] use super::net::MockSocket;
|
||||||
|
#[cfg(test)] use super::util::MockTimeSource;
|
||||||
#[cfg(test)] use super::device::MockDevice;
|
#[cfg(test)] use super::device::MockDevice;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl<P: Protocol, T: Table, TS: TimeSource> GenericCloud<MockDevice, P, T, MockSocket, TS> {
|
impl<P: Protocol, T: Table> GenericCloud<MockDevice, P, T, MockSocket, MockTimeSource> {
|
||||||
fn is_empty(&self) -> bool {
|
pub fn socket4(&mut self) -> &mut MockSocket {
|
||||||
self.device.is_empty() && self.socket4.is_empty() && self.socket6.is_empty()
|
&mut self.socket4
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
pub fn socket6(&mut self) -> &mut MockSocket {
|
||||||
type TestNode = GenericCloud<MockDevice, ethernet::Frame, SwitchTable<MockTimeSource>, MockSocket, MockTimeSource>;
|
&mut self.socket6
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn create_node() -> TestNode {
|
|
||||||
TestNode::new(
|
|
||||||
&Config::default(),
|
|
||||||
MockDevice::new(),
|
|
||||||
SwitchTable::new(1800, 10),
|
|
||||||
true, true, vec![], Crypto::None, None
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn device(&mut self) -> &mut MockDevice {
|
||||||
fn connect() {
|
&mut self.device
|
||||||
let mut node = create_node();
|
}
|
||||||
assert!(node.is_empty());
|
|
||||||
node.connect("1.2.3.4:5678").unwrap();
|
pub fn trigger_socket_v4_event(&mut self) {
|
||||||
assert!(node.device.is_empty());
|
let mut buffer = [0; 64*1024];
|
||||||
assert!(node.socket6.is_empty());
|
self.handle_socket_v4_event(&mut buffer);
|
||||||
let (addr, mut message) = node.socket4.pop_outbound().unwrap();
|
}
|
||||||
assert_eq!("1.2.3.4:5678".to_socket_addrs().unwrap().next().unwrap(), addr);
|
|
||||||
let message = node.decode_message(&mut message).unwrap();
|
pub fn trigger_socket_v6_event(&mut self) {
|
||||||
assert_eq!(Message::Init(0, node.node_id, vec![]), message);
|
let mut buffer = [0; 64*1024];
|
||||||
|
self.handle_socket_v6_event(&mut buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trigger_device_event(&mut self) {
|
||||||
|
let mut buffer = [0; 64*1024];
|
||||||
|
self.handle_device_event(&mut buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn node_id(&self) -> NodeId {
|
||||||
|
self.node_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peers(&self) -> &PeerList<MockTimeSource> {
|
||||||
|
&self.peers
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn own_addresses(&self) -> &[SocketAddr] {
|
||||||
|
&self.own_addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_message<'a>(&self, msg: &'a mut [u8]) -> Result<Message<'a>, Error> {
|
||||||
|
decode(msg, self.magic, &self.crypto)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -259,8 +259,8 @@ impl MockDevice {
|
||||||
self.outbound.pop_front()
|
self.outbound.pop_front()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn has_inbound(&self) -> bool {
|
||||||
self.inbound.is_empty() && self.outbound.is_empty()
|
!self.inbound.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern crate base_62;
|
||||||
#[cfg(feature = "bench")] extern crate test;
|
#[cfg(feature = "bench")] extern crate test;
|
||||||
|
|
||||||
#[macro_use] pub mod util;
|
#[macro_use] pub mod util;
|
||||||
|
#[cfg(test)] #[macro_use] mod tests;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod udpmessage;
|
pub mod udpmessage;
|
||||||
|
|
|
@ -54,10 +54,6 @@ impl MockSocket {
|
||||||
pub fn pop_outbound(&mut self) -> Option<(SocketAddr, Vec<u8>)> {
|
pub fn pop_outbound(&mut self) -> Option<(SocketAddr, Vec<u8>)> {
|
||||||
self.outbound.pop_front()
|
self.outbound.pop_front()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.inbound.is_empty() && self.outbound.is_empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for MockSocket {
|
impl AsRawFd for MockSocket {
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn connect_v4() {
|
||||||
|
let mut node1 = create_tap_node();
|
||||||
|
let node1_addr = addr!("1.2.3.4:5678");
|
||||||
|
let mut node2 = create_tap_node();
|
||||||
|
let node2_addr = addr!("2.3.4.5:6789");
|
||||||
|
assert_clean!(node1, node2);
|
||||||
|
assert!(!node1.peers().contains_node(&node2.node_id()));
|
||||||
|
assert!(!node2.peers().contains_node(&node1.node_id()));
|
||||||
|
|
||||||
|
node1.connect("2.3.4.5:6789").unwrap();
|
||||||
|
|
||||||
|
// Node 1 -> Node 2: Init 0
|
||||||
|
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![]));
|
||||||
|
assert_clean!(node1);
|
||||||
|
assert!(node2.peers().contains_node(&node1.node_id()));
|
||||||
|
|
||||||
|
// Node 2 -> Node 1: Init 1 | Node 2 -> Node 1: Peers
|
||||||
|
assert_message4!(node2, node2_addr, node1, node1_addr, Message::Init(1, node2.node_id(), vec![]));
|
||||||
|
assert!(node1.peers().contains_node(&node2.node_id()));
|
||||||
|
assert_message4!(node2, node2_addr, node1, node1_addr, Message::Peers(vec![node1_addr]));
|
||||||
|
assert_clean!(node2);
|
||||||
|
|
||||||
|
// Node 1 -> Node 2: Peers | Node 1 -> Node 1: Init 0
|
||||||
|
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Peers(vec![node2_addr]));
|
||||||
|
assert_message4!(node1, node1_addr, node1, node1_addr, Message::Init(0, node1.node_id(), vec![]));
|
||||||
|
assert!(node1.own_addresses().contains(&node1_addr));
|
||||||
|
assert_clean!(node1);
|
||||||
|
|
||||||
|
// Node 2 -> Node 2: Init 0
|
||||||
|
assert_message4!(node2, node2_addr, node2, node2_addr, Message::Init(0, node2.node_id(), vec![]));
|
||||||
|
assert_clean!(node2);
|
||||||
|
assert!(node2.own_addresses().contains(&node2_addr));
|
||||||
|
|
||||||
|
assert_connected!(node1, node2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn connect_v6() {
|
||||||
|
let mut node1 = create_tap_node();
|
||||||
|
let node1_addr = addr!("[::1]:5678");
|
||||||
|
let mut node2 = create_tap_node();
|
||||||
|
let node2_addr = addr!("[::2]:6789");
|
||||||
|
|
||||||
|
node1.connect("[::2]:6789").unwrap();
|
||||||
|
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr);
|
||||||
|
|
||||||
|
assert_connected!(node1, node2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cross_connect() {
|
||||||
|
let mut node1 = create_tap_node();
|
||||||
|
let node1_addr = addr!("1.1.1.1:1111");
|
||||||
|
let mut node2 = create_tap_node();
|
||||||
|
let node2_addr = addr!("2.2.2.2:2222");
|
||||||
|
let mut node3 = create_tap_node();
|
||||||
|
let node3_addr = addr!("3.3.3.3:3333");
|
||||||
|
let mut node4 = create_tap_node();
|
||||||
|
let node4_addr = addr!("4.4.4.4:4444");
|
||||||
|
|
||||||
|
node1.connect("2.2.2.2:2222").unwrap();
|
||||||
|
node3.connect("4.4.4.4:4444").unwrap();
|
||||||
|
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr, node3 => node3_addr, node4 => node4_addr);
|
||||||
|
|
||||||
|
assert_connected!(node1, node2);
|
||||||
|
assert_connected!(node3, node4);
|
||||||
|
|
||||||
|
node1.connect("3.3.3.3:3333").unwrap();
|
||||||
|
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr, node3 => node3_addr, node4 => node4_addr);
|
||||||
|
|
||||||
|
// existing connections
|
||||||
|
assert_connected!(node1, node2);
|
||||||
|
assert_connected!(node3, node4);
|
||||||
|
|
||||||
|
// new connection
|
||||||
|
assert_connected!(node1, node3);
|
||||||
|
|
||||||
|
// transient connections 1st degree
|
||||||
|
assert_connected!(node1, node4);
|
||||||
|
assert_connected!(node3, node2);
|
||||||
|
|
||||||
|
// transient connections 2nd degree
|
||||||
|
assert_connected!(node1, node4);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
macro_rules! assert_clean {
|
||||||
|
($($node: expr),*) => {
|
||||||
|
$(
|
||||||
|
assert_eq!($node.socket4().pop_outbound().map(|(addr, mut msg)| (addr, $node.decode_message(&mut msg).unwrap().without_data())), None);
|
||||||
|
assert_eq!($node.socket6().pop_outbound().map(|(addr, mut msg)| (addr, $node.decode_message(&mut msg).unwrap().without_data())), None);
|
||||||
|
assert_eq!($node.device().pop_outbound(), None);
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! assert_message4 {
|
||||||
|
($from: expr, $from_addr: expr, $to: expr, $to_addr: expr, $message: expr) => {
|
||||||
|
let (addr, mut data) = msg4_get(&mut $from);
|
||||||
|
assert_eq!($to_addr, addr);
|
||||||
|
{
|
||||||
|
let message = $to.decode_message(&mut data).unwrap();
|
||||||
|
assert_eq!($message, message.without_data());
|
||||||
|
}
|
||||||
|
msg4_put(&mut $to, $from_addr, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! assert_message6 {
|
||||||
|
($from: expr, $from_addr: expr, $to: expr, $to_addr: expr, $message: expr) => {
|
||||||
|
let (addr, mut data) = msg6_get(&mut $from);
|
||||||
|
assert_eq!($to_addr, addr);
|
||||||
|
{
|
||||||
|
let message = $to.decode_message(&mut data).unwrap();
|
||||||
|
assert_eq!($message, message.without_data());
|
||||||
|
}
|
||||||
|
msg6_put(&mut $to, $from_addr, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! simulate {
|
||||||
|
($($node: expr => $addr: expr),*) => {
|
||||||
|
simulate(&mut [$((&mut $node, $addr)),*]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! assert_connected {
|
||||||
|
($($node:expr),*) => {
|
||||||
|
for node1 in [$(&$node),*].iter() {
|
||||||
|
for node2 in [$(&$node),*].iter() {
|
||||||
|
if node1.node_id() == node2.node_id() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
assert!(node1.peers().contains_node(&node2.node_id()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
|
#[macro_use] mod helper;
|
||||||
|
mod connect;
|
||||||
|
mod payload;
|
||||||
|
|
||||||
|
pub use std::net::SocketAddr;
|
||||||
|
|
||||||
|
pub use super::ethernet::{self, SwitchTable};
|
||||||
|
pub use super::util::MockTimeSource;
|
||||||
|
pub use super::net::MockSocket;
|
||||||
|
pub use super::device::MockDevice;
|
||||||
|
pub use super::udpmessage::Message;
|
||||||
|
pub use super::config::Config;
|
||||||
|
pub use super::crypto::Crypto;
|
||||||
|
pub use super::cloud::GenericCloud;
|
||||||
|
pub use super::types::{Protocol, Table, Range};
|
||||||
|
pub use super::ip::{self, RoutingTable};
|
||||||
|
|
||||||
|
|
||||||
|
type TestNode<P, T> = GenericCloud<MockDevice, P, T, MockSocket, MockTimeSource>;
|
||||||
|
|
||||||
|
type TapTestNode = TestNode<ethernet::Frame, SwitchTable<MockTimeSource>>;
|
||||||
|
type TunTestNode = TestNode<ip::Packet, RoutingTable>;
|
||||||
|
|
||||||
|
|
||||||
|
fn create_tap_node() -> TapTestNode {
|
||||||
|
TestNode::new(
|
||||||
|
&Config::default(),
|
||||||
|
MockDevice::new(),
|
||||||
|
SwitchTable::new(1800, 10),
|
||||||
|
true, true, vec![], Crypto::None, None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tun_node(addresses: Vec<Range>) -> TunTestNode {
|
||||||
|
TestNode::new(
|
||||||
|
&Config::default(),
|
||||||
|
MockDevice::new(),
|
||||||
|
RoutingTable::new(),
|
||||||
|
false, false, addresses, Crypto::None, None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn msg4_get<P: Protocol, T: Table>(node: &mut TestNode<P, T>) -> (SocketAddr, Vec<u8>) {
|
||||||
|
let msg = node.socket4().pop_outbound();
|
||||||
|
assert!(msg.is_some());
|
||||||
|
msg.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msg6_get<P: Protocol, T: Table>(node: &mut TestNode<P, T>) -> (SocketAddr, Vec<u8>) {
|
||||||
|
let msg = node.socket6().pop_outbound();
|
||||||
|
assert!(msg.is_some());
|
||||||
|
msg.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msg4_put<P: Protocol, T: Table>(node: &mut TestNode<P, T>, from: SocketAddr, msg: Vec<u8>) {
|
||||||
|
node.socket4().put_inbound(from, msg);
|
||||||
|
node.trigger_socket_v4_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msg6_put<P: Protocol, T: Table>(node: &mut TestNode<P, T>, from: SocketAddr, msg: Vec<u8>) {
|
||||||
|
node.socket6().put_inbound(from, msg);
|
||||||
|
node.trigger_socket_v6_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simulate<P: Protocol, T: Table>(nodes: &mut [(&mut TestNode<P, T>, SocketAddr)]) {
|
||||||
|
for (ref mut node, ref from_addr) in nodes.iter_mut() {
|
||||||
|
while node.device().has_inbound() {
|
||||||
|
node.trigger_device_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut clean = false;
|
||||||
|
while !clean {
|
||||||
|
clean = true;
|
||||||
|
let mut msgs = Vec::new();
|
||||||
|
for (ref mut node, ref from_addr) in nodes.iter_mut() {
|
||||||
|
while let Some((to_addr, msg)) = node.socket4().pop_outbound() {
|
||||||
|
msgs.push((msg, *from_addr, to_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clean &= msgs.is_empty();
|
||||||
|
for (msg, from_addr, to_addr) in msgs {
|
||||||
|
for (ref mut node, ref addr) in nodes.iter_mut() {
|
||||||
|
if *addr == to_addr {
|
||||||
|
msg4_put(node, from_addr, msg);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut msgs = Vec::new();
|
||||||
|
for (ref mut node, ref from_addr) in nodes.iter_mut() {
|
||||||
|
while let Some((to_addr, msg)) = node.socket6().pop_outbound() {
|
||||||
|
msgs.push((msg, *from_addr, to_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clean &= msgs.is_empty();
|
||||||
|
for (msg, from_addr, to_addr) in msgs {
|
||||||
|
for (ref mut node, ref addr) in nodes.iter_mut() {
|
||||||
|
if *addr == to_addr {
|
||||||
|
msg6_put(node, from_addr, msg);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ethernet_send() {
|
||||||
|
let mut node1 = create_tap_node();
|
||||||
|
let node1_addr = addr!("1.2.3.4:5678");
|
||||||
|
let mut node2 = create_tap_node();
|
||||||
|
let node2_addr = addr!("2.3.4.5:6789");
|
||||||
|
|
||||||
|
node1.connect("2.3.4.5:6789").unwrap();
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr);
|
||||||
|
assert_connected!(node1, node2);
|
||||||
|
|
||||||
|
let payload = vec![2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
node1.device().put_inbound(payload.clone());
|
||||||
|
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr);
|
||||||
|
|
||||||
|
assert_eq!(Some(payload), node2.device().pop_outbound());
|
||||||
|
|
||||||
|
assert_clean!(node1, node2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn learning_switch() {
|
||||||
|
let mut node1 = create_tap_node();
|
||||||
|
let node1_addr = addr!("1.2.3.4:5678");
|
||||||
|
let mut node2 = create_tap_node();
|
||||||
|
let node2_addr = addr!("2.3.4.5:6789");
|
||||||
|
let mut node3 = create_tap_node();
|
||||||
|
let node3_addr = addr!("3.4.5.6:7890");
|
||||||
|
|
||||||
|
node1.connect("2.3.4.5:6789").unwrap();
|
||||||
|
node1.connect("3.4.5.6:7890").unwrap();
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||||
|
assert_connected!(node1, node2, node3);
|
||||||
|
|
||||||
|
let payload = vec![2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
node1.device().put_inbound(payload.clone());
|
||||||
|
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||||
|
|
||||||
|
assert_eq!(Some(&payload), node2.device().pop_outbound().as_ref());
|
||||||
|
assert_eq!(Some(&payload), node3.device().pop_outbound().as_ref());
|
||||||
|
|
||||||
|
let payload = vec![1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 5, 4, 3, 2, 1];
|
||||||
|
|
||||||
|
node2.device().put_inbound(payload.clone());
|
||||||
|
|
||||||
|
simulate!(node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||||
|
|
||||||
|
assert_eq!(Some(&payload), node1.device().pop_outbound().as_ref());
|
||||||
|
assert_clean!(node3);
|
||||||
|
|
||||||
|
assert_clean!(node1, node2, node3);
|
||||||
|
}
|
|
@ -55,6 +55,17 @@ pub enum Message<'a> {
|
||||||
Close,
|
Close,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Message<'a> {
|
||||||
|
pub fn without_data(self) -> Message<'static> {
|
||||||
|
match self {
|
||||||
|
Message::Data(_, start, end) => Message::Data(&mut [], start, end),
|
||||||
|
Message::Peers(peers) => Message::Peers(peers),
|
||||||
|
Message::Init(step, node_id, ranges) => Message::Init(step, node_id, ranges),
|
||||||
|
Message::Close => Message::Close
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Debug for Message<'a> {
|
impl<'a> fmt::Debug for Message<'a> {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -129,6 +129,14 @@ pub fn resolve<Addr: ToSocketAddrs+fmt::Debug>(addr: Addr) -> Result<Vec<SocketA
|
||||||
Ok(addrs)
|
Ok(addrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! addr {
|
||||||
|
($addr: expr) => {
|
||||||
|
{
|
||||||
|
std::net::ToSocketAddrs::to_socket_addrs($addr).unwrap().next().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct Bytes(pub u64);
|
pub struct Bytes(pub u64);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue