diff options
author | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2019-10-09 15:08:26 +0200 |
---|---|---|
committer | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2019-10-09 15:08:26 +0200 |
commit | 761c46064d7510303f08cde27c9e13b07293f3af (patch) | |
tree | 7b914169725952e557223972b3f0b611c54e6829 /src/types | |
parent | Restructure dummy implementations (diff) | |
download | wireguard-rs-761c46064d7510303f08cde27c9e13b07293f3af.tar.xz wireguard-rs-761c46064d7510303f08cde27c9e13b07293f3af.zip |
Restructure IO traits.
Diffstat (limited to '')
-rw-r--r-- | src/types/bind.rs | 79 | ||||
-rw-r--r-- | src/types/dummy.rs | 172 | ||||
-rw-r--r-- | src/types/endpoint.rs | 2 | ||||
-rw-r--r-- | src/types/mod.rs | 8 | ||||
-rw-r--r-- | src/types/tun.rs | 43 | ||||
-rw-r--r-- | src/types/udp.rs | 29 |
6 files changed, 162 insertions, 171 deletions
diff --git a/src/types/bind.rs b/src/types/bind.rs index 62adbbb..fcc38c8 100644 --- a/src/types/bind.rs +++ b/src/types/bind.rs @@ -1,73 +1,28 @@ use super::Endpoint; -use std::error; +use std::error::Error; -/// Traits representing the "internet facing" end of the VPN. -/// -/// In practice this is a UDP socket (but the router interface is agnostic). -/// Often these traits will be implemented on the same type. +pub trait Reader<E: Endpoint>: Send + Sync { + type Error: Error; -/// Bind interface provided to the router code -pub trait RouterBind: Send + Sync { - type Error: error::Error; - type Endpoint: Endpoint; + fn read(&self, buf: &mut [u8]) -> Result<(usize, E), Self::Error>; +} - /// Receive a buffer on the bind - /// - /// # Arguments - /// - /// - `buf`, buffer for storing the packet. If the buffer is too short, the packet should just be truncated. - /// - /// # Note - /// - /// The size of the buffer is derieved from the MTU of the Tun device. - fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error>; +pub trait Writer<E: Endpoint>: Send + Sync + Clone + 'static { + type Error: Error; - /// Send a buffer to the endpoint - /// - /// # Arguments - /// - /// - `buf`, packet src buffer (in practice the body of a UDP datagram) - /// - `dst`, destination endpoint (in practice, src: (ip, port) + dst: (ip, port) for sticky sockets) - /// - /// # Returns - /// - /// The unit type or an error if transmission failed - fn send(&self, buf: &[u8], dst: &Self::Endpoint) -> Result<(), Self::Error>; + fn write(&self, buf: &[u8], dst: &E) -> Result<(), Self::Error>; } -/// Bind interface provided for configuration (setting / getting the port) -pub trait ConfigBind { - type Error: error::Error; - - /// Return a new (unbound) instance of a configuration bind - fn new() -> Self; +pub trait Bind: Send + Sync + 'static { + type Error: Error; + type Endpoint: Endpoint; - /// Updates the port of the bind - /// - /// # Arguments - /// - /// - `port`, the new port to bind to. 0 means any available port. - /// - /// # Returns - /// - /// The unit type or an error, if binding fails - fn set_port(&self, port: u16) -> Result<(), Self::Error>; + /* Until Rust gets type equality constraints these have to be generic */ + type Writer: Writer<Self::Endpoint>; + type Reader: Reader<Self::Endpoint>; - /// Returns the current port of the bind - fn get_port(&self) -> Option<u16>; + /* Used to close the reader/writer when binding to a new port */ + type Closer; - /// Set the mark (e.g. on Linus this is the fwmark) on the bind - /// - /// # Arguments - /// - /// - `mark`, the mark to set - /// - /// # Note - /// - /// The mark should be retained accross calls to `set_port`. - /// - /// # Returns - /// - /// The unit type or an error, if the operation fails due to permission errors - fn set_mark(&self, mark: u16) -> Result<(), Self::Error>; + fn bind(port: u16) -> Result<(Self::Reader, Self::Writer, Self::Closer, u16), Self::Error>; } diff --git a/src/types/dummy.rs b/src/types/dummy.rs index e15abb0..40a3bdd 100644 --- a/src/types/dummy.rs +++ b/src/types/dummy.rs @@ -5,8 +5,9 @@ use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use std::sync::Arc; use std::sync::Mutex; use std::time::Instant; +use std::marker; -use super::{Bind, Endpoint, Key, KeyPair, Tun}; +use super::*; /* This submodule provides pure/dummy implementations of the IO interfaces * for use in unit tests thoughout the project. @@ -72,104 +73,103 @@ impl Endpoint for UnitEndpoint { } } +impl UnitEndpoint { + pub fn new() -> UnitEndpoint { + UnitEndpoint{} + } +} + +/* */ + #[derive(Clone, Copy)] pub struct TunTest {} -impl Tun for TunTest { +impl tun::Reader for TunTest { type Error = TunError; + fn read(&self, _buf: &mut [u8], _offset: usize) -> Result<usize, Self::Error> { + Ok(0) + } +} + +impl tun::MTU for TunTest { fn mtu(&self) -> usize { 1500 } +} - fn read(&self, _buf: &mut [u8], _offset: usize) -> Result<usize, Self::Error> { - Ok(0) - } +impl tun::Writer for TunTest { + type Error = TunError; fn write(&self, _src: &[u8]) -> Result<(), Self::Error> { Ok(()) } } +impl tun::Tun for TunTest { + type Writer = TunTest; + type Reader = TunTest; + type MTU = TunTest; + type Error = TunError; +} + impl TunTest { - pub fn new() -> TunTest { - TunTest {} + pub fn create(_name: &str) -> Result<(TunTest, TunTest, TunTest), TunError> { + Ok((TunTest {},TunTest {}, TunTest{})) } } -/* Bind implemenentations */ +/* Void Bind */ #[derive(Clone, Copy)] pub struct VoidBind {} -impl Bind for VoidBind { +impl bind::Reader<UnitEndpoint> for VoidBind { type Error = BindError; - type Endpoint = UnitEndpoint; - fn new() -> VoidBind { - VoidBind {} - } - - fn set_port(&self, _port: u16) -> Result<(), Self::Error> { - Ok(()) - } - - fn get_port(&self) -> Option<u16> { - None - } - - fn recv(&self, _buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error> { + fn read(&self, _buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> { Ok((0, UnitEndpoint {})) } - - fn send(&self, _buf: &[u8], _dst: &Self::Endpoint) -> Result<(), Self::Error> { - Ok(()) - } } -#[derive(Clone)] -pub struct PairBind { - send: Arc<Mutex<SyncSender<Vec<u8>>>>, - recv: Arc<Mutex<Receiver<Vec<u8>>>>, -} +impl bind::Writer<UnitEndpoint> for VoidBind { + type Error = BindError; -impl PairBind { - pub fn pair() -> (PairBind, PairBind) { - let (tx1, rx1) = sync_channel(128); - let (tx2, rx2) = sync_channel(128); - ( - PairBind { - send: Arc::new(Mutex::new(tx1)), - recv: Arc::new(Mutex::new(rx2)), - }, - PairBind { - send: Arc::new(Mutex::new(tx2)), - recv: Arc::new(Mutex::new(rx1)), - }, - ) + fn write(&self, _buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> { + Ok(()) } } -impl Bind for PairBind { +impl bind::Bind for VoidBind { type Error = BindError; type Endpoint = UnitEndpoint; - fn new() -> PairBind { - PairBind { - send: Arc::new(Mutex::new(sync_channel(0).0)), - recv: Arc::new(Mutex::new(sync_channel(0).1)), - } - } + type Reader = VoidBind; + type Writer = VoidBind; + type Closer = (); - fn set_port(&self, _port: u16) -> Result<(), Self::Error> { - Ok(()) + fn bind(_ : u16) -> Result<(Self::Reader, Self::Writer, Self::Closer, u16), Self::Error> { + Ok((VoidBind{}, VoidBind{}, (), 2600)) } +} - fn get_port(&self) -> Option<u16> { - None +impl VoidBind { + pub fn new() -> VoidBind { + VoidBind{} } +} - fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error> { +/* Pair Bind */ + +#[derive(Clone)] +pub struct PairReader<E> { + recv: Arc<Mutex<Receiver<Vec<u8>>>>, + _marker: marker::PhantomData<E>, +} + +impl bind::Reader<UnitEndpoint> for PairReader<UnitEndpoint> { + type Error = BindError; + fn read(&self, buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> { let vec = self .recv .lock() @@ -180,8 +180,11 @@ impl Bind for PairBind { buf[..len].copy_from_slice(&vec[..]); Ok((vec.len(), UnitEndpoint {})) } +} - fn send(&self, buf: &[u8], _dst: &Self::Endpoint) -> Result<(), Self::Error> { +impl bind::Writer<UnitEndpoint> for PairWriter<UnitEndpoint> { + type Error = BindError; + fn write(&self, buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> { let owned = buf.to_owned(); match self.send.lock().unwrap().send(owned) { Err(_) => Err(BindError::Disconnected), @@ -190,6 +193,57 @@ impl Bind for PairBind { } } +#[derive(Clone)] +pub struct PairWriter<E> { + send: Arc<Mutex<SyncSender<Vec<u8>>>>, + _marker: marker::PhantomData<E>, +} + +#[derive(Clone)] +pub struct PairBind {} + +impl PairBind { + pub fn pair<E>() -> ((PairReader<E>, PairWriter<E>), (PairReader<E>, PairWriter<E>)) { + let (tx1, rx1) = sync_channel(128); + let (tx2, rx2) = sync_channel(128); + ( + ( + PairReader{ + + recv: Arc::new(Mutex::new(rx1)), + _marker: marker::PhantomData + }, + PairWriter{ + send: Arc::new(Mutex::new(tx2)), + _marker: marker::PhantomData + } + ), + ( + PairReader{ + recv: Arc::new(Mutex::new(rx2)), + _marker: marker::PhantomData + }, + PairWriter{ + send: Arc::new(Mutex::new(tx1)), + _marker: marker::PhantomData + } + ), + ) + } +} + +impl bind::Bind for PairBind { + type Closer = (); + type Error = BindError; + type Endpoint = UnitEndpoint; + type Reader = PairReader<Self::Endpoint>; + type Writer = PairWriter<Self::Endpoint>; + + fn bind(_port: u16) -> Result<(Self::Reader, Self::Writer, Self::Closer, u16), Self::Error> { + Err(BindError::Disconnected) + } +} + pub fn keypair(initiator: bool) -> KeyPair { let k1 = Key { key: [0x53u8; 32], diff --git a/src/types/endpoint.rs b/src/types/endpoint.rs index 261203f..74796aa 100644 --- a/src/types/endpoint.rs +++ b/src/types/endpoint.rs @@ -1,6 +1,6 @@ use std::net::SocketAddr; -pub trait Endpoint: Send { +pub trait Endpoint: Send + 'static { fn from_address(addr: SocketAddr) -> Self; fn into_address(&self) -> SocketAddr; } diff --git a/src/types/mod.rs b/src/types/mod.rs index 07ca44d..e0725f3 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,12 +1,10 @@ mod endpoint; mod keys; -mod tun; -mod udp; +pub mod tun; +pub mod bind; #[cfg(test)] pub mod dummy; pub use endpoint::Endpoint; -pub use keys::{Key, KeyPair}; -pub use tun::Tun; -pub use udp::Bind; +pub use keys::{Key, KeyPair};
\ No newline at end of file diff --git a/src/types/tun.rs b/src/types/tun.rs index fc8044a..2ba16ff 100644 --- a/src/types/tun.rs +++ b/src/types/tun.rs @@ -1,18 +1,22 @@ -use std::error; +use std::error::Error; -pub trait Tun: Send + Sync + Clone + 'static { - type Error: error::Error; +pub trait Writer: Send + Sync + 'static { + type Error: Error; - /// Returns the MTU of the device + /// Receive a cryptkey routed IP packet /// - /// This function needs to be efficient (called for every read). - /// The goto implementation strategy is to .load an atomic variable, - /// then use e.g. netlink to update the variable in a separate thread. + /// # Arguments + /// + /// - src: Buffer containing the IP packet to be written /// /// # Returns /// - /// The MTU of the interface in bytes - fn mtu(&self) -> usize; + /// Unit type or an error + fn write(&self, src: &[u8]) -> Result<(), Self::Error>; +} + +pub trait Reader: Send + 'static { + type Error: Error; /// Reads an IP packet into dst[offset:] from the tunnel device /// @@ -29,15 +33,24 @@ pub trait Tun: Send + Sync + Clone + 'static { /// /// The size of the IP packet (ignoring the header) or an std::error::Error instance: fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, Self::Error>; +} - /// Writes an IP packet to the tunnel device - /// - /// # Arguments +pub trait MTU: Send + Sync + Clone + 'static { + /// Returns the MTU of the device /// - /// - src: Buffer containing the IP packet to be written + /// This function needs to be efficient (called for every read). + /// The goto implementation strategy is to .load an atomic variable, + /// then use e.g. netlink to update the variable in a separate thread. /// /// # Returns /// - /// Unit type or an error - fn write(&self, src: &[u8]) -> Result<(), Self::Error>; + /// The MTU of the interface in bytes + fn mtu(&self) -> usize; +} + +pub trait Tun: Send + Sync + 'static { + type Writer: Writer; + type Reader: Reader; + type MTU: MTU; + type Error: Error; } diff --git a/src/types/udp.rs b/src/types/udp.rs deleted file mode 100644 index 943bf94..0000000 --- a/src/types/udp.rs +++ /dev/null @@ -1,29 +0,0 @@ -use super::Endpoint; -use std::error; - -/* Often times an a file descriptor in an atomic might suffice. - */ -pub trait Bind: Send + Sync + Clone + 'static { - type Error: error::Error + Send; - type Endpoint: Endpoint; - - fn new() -> Self; - - /// Updates the port of the Bind - /// - /// # Arguments - /// - /// - port, The new port to bind to. 0 means any available port. - /// - /// # Returns - /// - /// The unit type or an error, if binding fails - fn set_port(&self, port: u16) -> Result<(), Self::Error>; - - /// Returns the current port of the bind - fn get_port(&self) -> Option<u16>; - - fn recv(&self, buf: &mut [u8]) -> Result<(usize, Self::Endpoint), Self::Error>; - - fn send(&self, buf: &[u8], dst: &Self::Endpoint) -> Result<(), Self::Error>; -} |