From 12a7b371d4fed75f3934cf7d3788a6cf51c33c22 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Sun, 29 Mar 2020 18:21:48 +0200 Subject: Restructuring and dependency version bump. --- src/platform/dummy/tun/dummy.rs | 200 ++++++++++++++++++++++++++++++++++++++++ src/platform/dummy/tun/mod.rs | 12 +++ src/platform/dummy/tun/void.rs | 43 +++++++++ 3 files changed, 255 insertions(+) create mode 100644 src/platform/dummy/tun/dummy.rs create mode 100644 src/platform/dummy/tun/mod.rs create mode 100644 src/platform/dummy/tun/void.rs (limited to 'src/platform/dummy/tun') diff --git a/src/platform/dummy/tun/dummy.rs b/src/platform/dummy/tun/dummy.rs new file mode 100644 index 0000000..0f3479a --- /dev/null +++ b/src/platform/dummy/tun/dummy.rs @@ -0,0 +1,200 @@ +// This provides a mock tunnel interface. +// Which enables unit tests where WireGuard interfaces +// are configured to match each other and a full test of: +// +// - Handshake +// - Transport encryption/decryption +// +// Can be executed. + +use super::*; + +use std::cmp::min; +use std::error::Error; +use std::fmt; +use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; +use std::sync::Mutex; +use std::thread; +use std::time::Duration; + +use hex; +use log::debug; +use rand::rngs::OsRng; +use rand::Rng; + +pub struct TunTest {} + +// Represents the "other end" (kernel/OS end) of the TUN connection: +// +// Used to send/receive packets to the mock WireGuard interface. +pub struct TunFakeIO { + id: u32, + store: bool, + tx: SyncSender>, + rx: Receiver>, +} + +pub struct TunReader { + id: u32, + rx: Receiver>, +} + +pub struct TunWriter { + id: u32, + store: bool, + tx: Mutex>>, +} + +impl fmt::Display for TunFakeIO { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "FakeIO({})", self.id) + } +} + +impl fmt::Display for TunReader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TunReader({})", self.id) + } +} + +impl fmt::Display for TunWriter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TunWriter({})", self.id) + } +} + +pub struct TunStatus { + first: bool, +} + +impl Error for TunError { + fn description(&self) -> &str { + "Generic Tun Error" + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } +} + +impl fmt::Display for TunError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Not Possible") + } +} + +impl Reader for TunReader { + type Error = TunError; + + fn read(&self, buf: &mut [u8], offset: usize) -> Result { + match self.rx.recv() { + Ok(msg) => { + let n = min(buf.len() - offset, msg.len()); + buf[offset..offset + n].copy_from_slice(&msg[..n]); + debug!( + "dummy::TUN({}) : read ({}, {})", + self.id, + n, + hex::encode(&buf[offset..offset + n]) + ); + Ok(n) + } + Err(_) => Err(TunError::Disconnected), + } + } +} + +impl Writer for TunWriter { + type Error = TunError; + + fn write(&self, src: &[u8]) -> Result<(), Self::Error> { + debug!( + "dummy::TUN({}) : write ({}, {})", + self.id, + src.len(), + hex::encode(src) + ); + if self.store { + let m = src.to_owned(); + match self.tx.lock().unwrap().send(m) { + Ok(_) => Ok(()), + Err(_) => Err(TunError::Disconnected), + } + } else { + Ok(()) + } + } +} + +impl Status for TunStatus { + type Error = TunError; + + fn event(&mut self) -> Result { + if self.first { + self.first = false; + return Ok(TunEvent::Up(1420)); + } + + loop { + thread::sleep(Duration::from_secs(60 * 60)); + } + } +} + +impl Tun for TunTest { + type Writer = TunWriter; + type Reader = TunReader; + type Error = TunError; +} + +impl TunFakeIO { + pub fn write(&self, msg: Vec) { + if self.store { + self.tx.send(msg).unwrap(); + } + } + + pub fn read(&self) -> Vec { + self.rx.recv().unwrap() + } +} + +impl TunTest { + pub fn create(store: bool) -> (TunFakeIO, TunReader, TunWriter, TunStatus) { + let (tx1, rx1) = if store { + sync_channel(32) + } else { + sync_channel(1) + }; + let (tx2, rx2) = if store { + sync_channel(32) + } else { + sync_channel(1) + }; + + let id: u32 = OsRng.gen(); + + let fake = TunFakeIO { + id, + tx: tx1, + rx: rx2, + store, + }; + let reader = TunReader { id, rx: rx1 }; + let writer = TunWriter { + id, + tx: Mutex::new(tx2), + store, + }; + let status = TunStatus { first: true }; + (fake, reader, writer, status) + } +} + +impl PlatformTun for TunTest { + type Status = TunStatus; + + fn create(_name: &str) -> Result<(Vec, Self::Writer, Self::Status), Self::Error> { + Err(TunError::Disconnected) + } +} diff --git a/src/platform/dummy/tun/mod.rs b/src/platform/dummy/tun/mod.rs new file mode 100644 index 0000000..da03c7a --- /dev/null +++ b/src/platform/dummy/tun/mod.rs @@ -0,0 +1,12 @@ +use super::super::tun::*; + +mod dummy; +mod void; + +#[derive(Debug)] +pub enum TunError { + Disconnected, +} + +pub use dummy::*; +pub use void::*; diff --git a/src/platform/dummy/tun/void.rs b/src/platform/dummy/tun/void.rs new file mode 100644 index 0000000..0777541 --- /dev/null +++ b/src/platform/dummy/tun/void.rs @@ -0,0 +1,43 @@ +/* +// This code provides a "void" implementation of the tunnel interface: +// The implementation never reads and immediately discards any write without error +// +// This is used during benchmarking and profiling of the inbound path. + +use super::*; + +pub struct VoidTun {} + +pub struct VoidReader {} + +pub struct VoidWriter {} + +impl Tun for VoidTun { + type Writer = VoidWriter; + type Reader = VoidReader; + type Error = TunError; +} + + +impl Reader for VodReader { + type Error = TunError; + + fn write(&self, src: &[u8]) -> Result<(), Self::Error> { + debug!( + "dummy::TUN({}) : write ({}, {})", + self.id, + src.len(), + hex::encode(src) + ); + if self.store { + let m = src.to_owned(); + match self.tx.lock().unwrap().send(m) { + Ok(_) => Ok(()), + Err(_) => Err(TunError::Disconnected), + } + } else { + Ok(()) + } + } +} +*/ -- cgit v1.2.3-59-g8ed1b