diff --git a/.gitignore b/.gitignore index 1efde2b..2ed6481 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ # build **/target/ **/*.log -# random testing -domo_proto/src/main.rs \ No newline at end of file +# testing +domo_test/ \ No newline at end of file diff --git a/domo_lib/Cargo.lock b/domo_lib/Cargo.lock index 5b43fa7..8bd1973 100644 --- a/domo_lib/Cargo.lock +++ b/domo_lib/Cargo.lock @@ -19,14 +19,14 @@ dependencies = [ [[package]] name = "domo_lib" -version = "0.1.0" +version = "0.2.0" dependencies = [ "domo_proto", ] [[package]] name = "domo_proto" -version = "0.2.0" +version = "1.0.0" dependencies = [ "crc32fast", "rand", diff --git a/domo_lib/Cargo.toml b/domo_lib/Cargo.toml index fc126d2..a6274f4 100644 --- a/domo_lib/Cargo.toml +++ b/domo_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "domo_lib" -version = "0.1.0" +version = "0.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/domo_lib/src/filter/filters/packet.rs b/domo_lib/src/filter/filters/packet.rs index 27f8778..882fd74 100644 --- a/domo_lib/src/filter/filters/packet.rs +++ b/domo_lib/src/filter/filters/packet.rs @@ -4,13 +4,6 @@ use crate::filter::{Filter, FilterState}; use super::function_filter::FunctionFilter; -pub trait PacketFilter: Filter { - fn filter_packet(&self, filter_packet: Packet) -> FilterState { - self.filter(FilterState::Pass(filter_packet)) - } -} - -impl PacketFilter for FunctionFilter {} impl Filter for FunctionFilter { fn filter(&self, f: FilterState) -> FilterState { (self.0)(f) @@ -20,9 +13,21 @@ impl Filter for FunctionFilter { impl Filter for Packet { fn filter(&self, f: FilterState) -> FilterState { match f { - FilterState::Pass(p) => if &p != self { FilterState::Drop } else { FilterState::Pass(p) }, - FilterState::Skip(p) => if &p != self { FilterState::Drop } else { FilterState::Pass(p) }, + FilterState::Pass(p) => { + if &p != self { + FilterState::Drop + } else { + FilterState::Pass(p) + } + } + FilterState::Skip(p) => { + if &p != self { + FilterState::Drop + } else { + FilterState::Pass(p) + } + } FilterState::Drop => FilterState::Drop, } } -} \ No newline at end of file +} diff --git a/domo_lib/src/filter/mod.rs b/domo_lib/src/filter/mod.rs index 01273e9..e6de447 100644 --- a/domo_lib/src/filter/mod.rs +++ b/domo_lib/src/filter/mod.rs @@ -1,12 +1,46 @@ pub mod filters; +#[derive(Clone)] pub enum FilterState { /// T passed filter Pass(T), /// T was not subject to filter. Skip(T), /// T did not pass filter - Drop + Drop, +} + +impl FilterState { + pub fn to_type(self) -> Option { + match self { + FilterState::Pass(v) | FilterState::Skip(v) => Some(v), + FilterState::Drop => None + } + } + + pub fn is_pass(&self) -> bool { + if let FilterState::Pass(_) = self { + true + } else { + false + } + } + + pub fn is_skip(&self) -> bool { + if let FilterState::Skip(_) = self { + true + } else { + false + } + } + + pub fn is_drop(&self) -> bool { + if let FilterState::Drop = self { + true + } else { + false + } + } } pub trait Filter { @@ -14,4 +48,3 @@ pub trait Filter { f } } - diff --git a/domo_lib/src/node/mod.rs b/domo_lib/src/node/mod.rs index 596f14f..c40ed61 100644 --- a/domo_lib/src/node/mod.rs +++ b/domo_lib/src/node/mod.rs @@ -1,5 +1,7 @@ +use crate::filter::Filter; + use self::property::Property; -use domo_proto::identifier::Identifier; +use domo_proto::{identifier::Identifier, packet::Packet}; use std::collections::HashMap; pub mod property; @@ -18,6 +20,7 @@ pub struct Node { } impl Node { + /// Create a new node pub fn new(node_id: Identifier) -> Self { Node { parent: None, @@ -27,25 +30,69 @@ impl Node { } } - pub fn add_child(&mut self, node: Node) -> bool { + /// Attempts to add child node to self. + /// Returns a mutable reference to the added node. + pub fn add_child<'a>(&'a mut self, mut node: Node) -> Option<&'a mut Node> { if self.children.contains_key(&node.identifier) { - return false; + return None; } - self.children.insert(node.identifier, node); - true + node.parent = Some(self.identifier.clone()); + self.children.insert(node.identifier, node.clone()); + self.children.get_mut(&node.identifier) } + /// Attempts to remove child from self. + /// Returns removed node. + pub fn remove_child(&mut self, identifier: &Identifier) -> Option { + self.children.remove(&identifier).map(|mut n| { + n.parent = None; + n + }) + } + + /// Returns if this node has the identifier. + pub fn has(&self, identifier: &Identifier) -> bool { + self.children.contains_key(identifier) + } + + /// Attempts to find given identifier and returns mutable reference to it. pub fn find<'a>(&'a mut self, identifier: &Identifier) -> Option<&'a mut Node> { - if self.identifier == *identifier { - return Some(self); - } - for (_, child) in self.children.iter_mut() { if let Some(found) = child.find(identifier) { return Some(found); } } - None } -} \ No newline at end of file +} + +impl Filter for Node { + fn filter( + &self, + f: crate::filter::FilterState, + ) -> crate::filter::FilterState { + if let Some(i) = f.to_type() { + if self.has(&i) || i == self.identifier { + crate::filter::FilterState::Pass(i) + } else { + crate::filter::FilterState::Skip(i) + } + } else { + crate::filter::FilterState::Drop + } + } +} + +impl Filter for Node { + fn filter(&self, f: crate::filter::FilterState) -> crate::filter::FilterState { + if let Some(p) = f.to_type() { + if self.has(&p.dest) || self.identifier == p.dest { + crate::filter::FilterState::Pass(p) + } else { + crate::filter::FilterState::Skip(p) + } + } else { + crate::filter::FilterState::Drop + } + } +} diff --git a/domo_lib/src/routing/endpoint.rs b/domo_lib/src/routing/endpoint.rs index 1e622c0..8b25a05 100644 --- a/domo_lib/src/routing/endpoint.rs +++ b/domo_lib/src/routing/endpoint.rs @@ -1,5 +1,7 @@ use crate::filter::Filter; +/// Endpoints are a non-returning trait. +/// Because endpoints *should* be the last thing in the chain, you *should* manage errors in there! pub trait Endpoint: Filter { fn handle(&mut self, item: T); } diff --git a/domo_lib/src/routing/mod.rs b/domo_lib/src/routing/mod.rs index 742b3b1..1b020e3 100644 --- a/domo_lib/src/routing/mod.rs +++ b/domo_lib/src/routing/mod.rs @@ -1,10 +1,7 @@ use domo_proto::packet::Packet; use crate::filter::{ - filters::{ - function_filter::{FunctionFilter, FunctionFilterFunction}, - packet::PacketFilter, - }, + filters::function_filter::{FunctionFilter, FunctionFilterFunction}, Filter, FilterState, }; @@ -15,7 +12,7 @@ pub mod endpoint; /// The Router will first filter the packet through the filter chain. /// Then it will filter past all endpoints and send the packet if the endpoint filter passed. pub struct Router<'a> { - filters: Vec>, + filters: Vec + 'a>>, endpoints: Vec + 'a>>, } @@ -27,7 +24,7 @@ impl<'a> Router<'a> { } } - pub fn add_filter(&mut self, filter: impl PacketFilter + 'a) { + pub fn add_filter(&mut self, filter: impl Filter + 'a) { self.filters.push(Box::new(filter)); } @@ -40,7 +37,6 @@ impl<'a> Router<'a> { } } -impl PacketFilter for Router<'_> {} impl Filter for Router<'_> { fn filter(&self, f: FilterState) -> FilterState { let mut f = f; @@ -49,4 +45,18 @@ impl Filter for Router<'_> { } f } -} \ No newline at end of file +} + +impl Endpoint for Router<'_> { + fn handle(&mut self, item: Packet) { + let item = self.filter(FilterState::Pass(item)); + for endpoint in &mut self.endpoints { + match endpoint.filter(item.clone()) { + FilterState::Pass(p) | FilterState::Skip(p) => { + let _ = &endpoint.handle(p); + } + FilterState::Drop => {} + } + } + } +}