Work on remaking routing

This commit is contained in:
Michael Mikovsky
2026-05-27 11:04:22 -06:00
parent 129720145a
commit fa8cb6269c
11 changed files with 360 additions and 2 deletions
Generated
+16
View File
@@ -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",
] ]
+1
View File
@@ -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
+3
View File
@@ -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 {}
+9
View File
@@ -0,0 +1,9 @@
#[derive(Debug)]
pub enum EndpointError {
NoAbsoultePathYet,
IncorrectAbsolutePath,
RouteNotExist,
HookDuplicate,
HookNotExist,
}
+54
View File
@@ -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);
});
}
}
+6
View File
@@ -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>);
}
+6 -1
View File
@@ -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;
+107
View File
@@ -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() {}
+14
View File
@@ -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
View File
@@ -1 +0,0 @@