mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Work on remaking routing
This commit is contained in:
Generated
+16
@@ -216,6 +216,21 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -839,6 +854,7 @@ dependencies = [
|
|||||||
name = "unshell-protocol"
|
name = "unshell-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
"rkyv",
|
"rkyv",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ unshell-protocol = { workspace = true }
|
|||||||
# unshell-runtime = { workspace = true }
|
# unshell-runtime = { workspace = true }
|
||||||
# unshell-leaves = { workspace = true }
|
# unshell-leaves = { workspace = true }
|
||||||
|
|
||||||
|
|
||||||
[profile.minimize]
|
[profile.minimize]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
strip = true # Strip symbols from the binary
|
strip = true # Strip symbols from the binary
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ doctest = false
|
|||||||
rkyv = { workspace = true }
|
rkyv = { workspace = true }
|
||||||
# unshell-macros = { path = "../unshell-macros" }
|
# unshell-macros = { path = "../unshell-macros" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
crossbeam-channel.workspace = true
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
elided_lifetimes_in_paths = "warn"
|
elided_lifetimes_in_paths = "warn"
|
||||||
future_incompatible = { level = "warn", priority = -1 }
|
future_incompatible = { level = "warn", priority = -1 }
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
use alloc::{format, string::ToString};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
endpoint::error::EndpointError,
|
||||||
|
packet::Packet,
|
||||||
|
types::{ConnectionSet, HookMap, Path, RouteMap},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EndpointRef<'a> {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub path: &'a Path,
|
||||||
|
|
||||||
|
pub hooks: &'a mut HookMap,
|
||||||
|
|
||||||
|
pub connections: &'a mut ConnectionSet,
|
||||||
|
|
||||||
|
pub inbound: &'a mut RouteMap,
|
||||||
|
pub outbound: &'a mut RouteMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EndpointRef<'a> {
|
||||||
|
pub fn add_inbound(&mut self, packet: Packet) -> Result<(), EndpointError> {
|
||||||
|
// If the packet is routed towards this endpoint
|
||||||
|
if packet.path.ends_with(self.name) {
|
||||||
|
if packet.is_upwards_call {
|
||||||
|
self.hooks.insert(packet.hook_id, packet.path.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.outbound
|
||||||
|
.entry(packet.path.clone())
|
||||||
|
.or_default()
|
||||||
|
.push_back(packet);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
// If the absolute path of this endpoint hasn't been set yet
|
||||||
|
if self.path.is_empty() {
|
||||||
|
return Err(EndpointError::NoAbsoultePathYet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if *self.path == packet.path {
|
||||||
|
return Err(EndpointError::IncorrectAbsolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For routing
|
||||||
|
let connection = if packet.is_upwards_call && self.path.starts_with(&packet.path) {
|
||||||
|
(
|
||||||
|
packet
|
||||||
|
.path
|
||||||
|
.rsplit_once('/')
|
||||||
|
.map_or(packet.path.clone(), |(_, after)| after.to_string()),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
} else if packet
|
||||||
|
.path
|
||||||
|
.starts_with(&format!("{}/{}", self.path, self.name))
|
||||||
|
{
|
||||||
|
let concat_len = self.path.len() + self.name.len();
|
||||||
|
|
||||||
|
let after_self = &packet.path[concat_len..];
|
||||||
|
|
||||||
|
(
|
||||||
|
after_self
|
||||||
|
.split_once('/')
|
||||||
|
.map_or(after_self.to_string(), |(before, _)| before.to_string()),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return Err(EndpointError::IncorrectAbsolutePath);
|
||||||
|
};
|
||||||
|
|
||||||
|
if !self.connections.contains(&connection) {
|
||||||
|
return Err(EndpointError::RouteNotExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.add_outbound(packet);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_outbound_upwards(&mut self, packet: Packet) -> Result<(), EndpointError> {
|
||||||
|
let next_hop = self
|
||||||
|
.hooks
|
||||||
|
.get(&packet.hook_id)
|
||||||
|
.ok_or(EndpointError::RouteNotExist)?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
if packet.end_hook {
|
||||||
|
let _ = self.hooks.remove(&packet.hook_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.outbound
|
||||||
|
.entry(next_hop.clone())
|
||||||
|
.or_default()
|
||||||
|
.push_back(packet);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_outbound_downwards(&mut self, packet: Packet) -> Result<(), EndpointError> {
|
||||||
|
let next_hop = self
|
||||||
|
.hooks
|
||||||
|
.get(&packet.hook_id)
|
||||||
|
.ok_or(EndpointError::RouteNotExist)?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
if packet.end_hook {
|
||||||
|
let _ = self.hooks.remove(&packet.hook_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.outbound
|
||||||
|
.entry(next_hop.clone())
|
||||||
|
.or_default()
|
||||||
|
.push_back(packet);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_intbound<F>(&mut self, path: &str, f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&Packet),
|
||||||
|
{
|
||||||
|
if let Some(queue) = self.inbound.get_mut(path) {
|
||||||
|
let _ = queue.iter().map(f);
|
||||||
|
|
||||||
|
queue.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_outbound<F>(&mut self, path: &str, f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&Packet),
|
||||||
|
{
|
||||||
|
if let Some(queue) = self.inbound.get_mut(path) {
|
||||||
|
let _ = queue.iter().map(f);
|
||||||
|
|
||||||
|
queue.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn get_last_term_in_path(path: &Path) -> &str {}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#[derive(Debug)]
|
||||||
|
pub enum EndpointError {
|
||||||
|
NoAbsoultePathYet,
|
||||||
|
IncorrectAbsolutePath,
|
||||||
|
|
||||||
|
RouteNotExist,
|
||||||
|
HookDuplicate,
|
||||||
|
HookNotExist,
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
mod endpoint_ref;
|
||||||
|
pub mod error;
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
leaf::Leaf,
|
||||||
|
types::{ConnectionSet, HookMap, Path, RouteMap},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub use endpoint_ref::EndpointRef;
|
||||||
|
|
||||||
|
pub struct Endpoint {
|
||||||
|
pub name: &'static str,
|
||||||
|
|
||||||
|
// Absolute path for this node.
|
||||||
|
pub path: Path,
|
||||||
|
pub leaves: Vec<Box<dyn Leaf>>,
|
||||||
|
|
||||||
|
pub connections: ConnectionSet,
|
||||||
|
|
||||||
|
pub hooks: HookMap,
|
||||||
|
pub inbound: RouteMap,
|
||||||
|
pub outbound: RouteMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Endpoint {
|
||||||
|
pub fn new(name: &'static str, leaves: Vec<Box<dyn Leaf>>) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
path: String::new(),
|
||||||
|
leaves,
|
||||||
|
hooks: HookMap::new(),
|
||||||
|
connections: ConnectionSet::new(),
|
||||||
|
inbound: RouteMap::new(),
|
||||||
|
outbound: RouteMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self) {
|
||||||
|
let mut self_ref = EndpointRef {
|
||||||
|
name: self.name,
|
||||||
|
path: &mut self.path,
|
||||||
|
hooks: &mut self.hooks,
|
||||||
|
connections: &mut self.connections,
|
||||||
|
inbound: &mut self.inbound,
|
||||||
|
outbound: &mut self.outbound,
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = self.leaves.iter_mut().map(|leaf| {
|
||||||
|
leaf.update(&mut self_ref);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
use crate::endpoint::EndpointRef;
|
||||||
|
|
||||||
|
pub trait Leaf {
|
||||||
|
fn get_name(&self) -> &'static str;
|
||||||
|
fn update<'a>(&mut self, _: &mut EndpointRef<'a>);
|
||||||
|
}
|
||||||
@@ -2,5 +2,10 @@
|
|||||||
|
|
||||||
pub extern crate alloc;
|
pub extern crate alloc;
|
||||||
|
|
||||||
|
pub mod endpoint;
|
||||||
|
pub mod leaf;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod utils;
|
mod types;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
use crate::{endpoint::EndpointRef, leaf::Leaf, packet::Packet};
|
||||||
|
|
||||||
|
use alloc::{
|
||||||
|
collections::vec_deque::VecDeque,
|
||||||
|
format,
|
||||||
|
string::{String, ToString},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
|
|
||||||
|
struct ControllerLeaf {
|
||||||
|
responder_id: String,
|
||||||
|
has_run: bool,
|
||||||
|
}
|
||||||
|
struct CommsLeaf {
|
||||||
|
tx: Sender<Vec<u8>>,
|
||||||
|
rx: Receiver<Vec<u8>>,
|
||||||
|
|
||||||
|
remote_id: String,
|
||||||
|
is_authority: bool,
|
||||||
|
started: bool,
|
||||||
|
}
|
||||||
|
struct ResponderLeaf;
|
||||||
|
|
||||||
|
impl Leaf for ControllerLeaf {
|
||||||
|
fn get_name(&self) -> &'static str {
|
||||||
|
"ControllerLeaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update<'a>(&mut self, endpoint: &mut EndpointRef<'a>) {
|
||||||
|
if !self.has_run {
|
||||||
|
endpoint.add_outbound(
|
||||||
|
self.responder_id.clone(),
|
||||||
|
Packet {
|
||||||
|
hook_id: 0,
|
||||||
|
is_upwards_call: false,
|
||||||
|
end_hook: false,
|
||||||
|
path: format!("/{}", self.responder_id),
|
||||||
|
procedure_id: "echo".to_string(),
|
||||||
|
data: "ABC123".as_bytes().to_vec(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.has_run = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Leaf for CommsLeaf {
|
||||||
|
fn get_name(&self) -> &'static str {
|
||||||
|
"CommsLeaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update<'a>(&mut self, endpoint: &mut EndpointRef<'a>) {
|
||||||
|
if !self.started {
|
||||||
|
endpoint
|
||||||
|
.connections
|
||||||
|
.insert((self.remote_id.clone(), self.is_authority));
|
||||||
|
}
|
||||||
|
|
||||||
|
while !self.rx.is_empty() {
|
||||||
|
let packet = Packet::deserialize(&self.rx.recv().unwrap()).unwrap();
|
||||||
|
|
||||||
|
endpoint.add_inbound(packet).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint.take_outbound(self.get_name(), |packet| {
|
||||||
|
let data = packet.serialize().unwrap();
|
||||||
|
self.tx.send(data).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Leaf for ResponderLeaf {
|
||||||
|
fn get_name(&self) -> &'static str {
|
||||||
|
"ResponderLeaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update<'a>(&mut self, endpoint: &mut EndpointRef<'a>) {
|
||||||
|
let packets = endpoint
|
||||||
|
.inbound
|
||||||
|
.get(self.get_name())
|
||||||
|
.unwrap_or(&VecDeque::new())
|
||||||
|
.iter()
|
||||||
|
.map(|packet| {
|
||||||
|
// let data = ;
|
||||||
|
|
||||||
|
Packet {
|
||||||
|
hook_id: 0,
|
||||||
|
is_upwards_call: false,
|
||||||
|
end_hook: false,
|
||||||
|
path: String::new(),
|
||||||
|
// path: packet.path.clone(),
|
||||||
|
procedure_id: "echo".to_string(),
|
||||||
|
data: packet.data.clone(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<Packet>>();
|
||||||
|
|
||||||
|
for packet in packets {
|
||||||
|
endpoint.add_outbound(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_comms() {}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
use alloc::{
|
||||||
|
collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque},
|
||||||
|
string::String,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::packet::Packet;
|
||||||
|
|
||||||
|
pub type Path = String;
|
||||||
|
pub type EndpointName = String;
|
||||||
|
pub type HookID = u16;
|
||||||
|
pub type ConnectionSet = BTreeSet<(EndpointName, bool)>;
|
||||||
|
pub type HookMap = BTreeMap<HookID, EndpointName>;
|
||||||
|
pub type PacketQueue = VecDeque<Packet>;
|
||||||
|
pub type RouteMap = BTreeMap<EndpointName, PacketQueue>;
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
Reference in New Issue
Block a user