Work on runtime system

This commit is contained in:
Michael Mikovsky
2025-11-13 11:52:01 -07:00
parent 920a0f78e9
commit cc2b2960e8
18 changed files with 200 additions and 190 deletions
+19 -10
View File
@@ -2,31 +2,40 @@ use std::{
io::Read,
net::TcpStream,
sync::{
Arc, Mutex,
Arc,
atomic::{AtomicBool, Ordering},
},
thread::{self, JoinHandle},
};
use crate::*;
use crate::{config::RuntimeConfig, *};
// use unshell_modules::{Manager, ModuleRuntime};
use crate::{Announcement, ModuleRuntime, module::Manager};
use crate::{Announcement, ModuleRuntime};
pub struct RuntimeTest {
pub struct ClientRuntime {
thread_handle: JoinHandle<()>,
join_signal: Arc<AtomicBool>,
}
impl RuntimeTest {
pub fn new(_manager: Arc<Mutex<Manager>>) -> RuntimeTest {
impl ClientRuntime {
pub fn new(config: &'static RuntimeConfig) -> Result<ClientRuntime, ModuleError> {
let join_signal = Arc::new(AtomicBool::new(false));
let join_clone = join_signal.clone();
Self {
let host = match config.config.get("host") {
Some(host) => host,
None => {
return Err(ModuleError::Error(
"Could not find HOST in Client Runtime".into(),
));
}
};
Ok(Self {
thread_handle: thread::spawn(move || {
debug!("Connecting to server...");
let mut stream = match TcpStream::connect("localhost:1234") {
let mut stream = match TcpStream::connect(host) {
Ok(stream) => stream,
Err(e) => {
error!("Failed to connect to server: {}", e);
@@ -64,11 +73,11 @@ impl RuntimeTest {
}
}),
join_signal,
}
})
}
}
impl ModuleRuntime for RuntimeTest {
impl ModuleRuntime for ClientRuntime {
// fn init(&mut self) {}
fn is_running(&self) -> bool {
+30 -31
View File
@@ -6,12 +6,15 @@ pub const MODULE_NAME: &'static str = "client";
// use unshell_modules::{Manager, ModuleRuntime, module_interface};
use std::any::TypeId;
use crate::{
Component,
module::Interface,
ModuleError,
ModuleRuntime,
client::client_runtime::ClientRuntime,
config::{InterfaceWrapper, NamedComponent, RuntimeConfig},
module_interface,
warn,
// module_interface,
warn, // module_interface,
};
pub extern "C" fn test1() {
@@ -32,39 +35,35 @@ module_interface! {
}
}
// #[unsafe(no_mangle)]
// pub fn interface() -> Interface {
// Interface::from_raw(test1, test2, test3)
// }
pub struct ClientInterfaceWrapper;
// #[unsafe(no_mangle)]
// pub fn init(manager: Arc<Mutex<Manager>>) -> Box<dyn ModuleRuntime> {
// info!("Initializing client module");
// }
impl InterfaceWrapper for ClientInterfaceWrapper {
fn get_interface<T: 'static>(&self) -> Option<T>
where
Self: Sized,
{
if TypeId::of::<T>() == TypeId::of::<ClientInterface>() {
let my_struct = ClientInterface::from_raw(test1, test2, test3);
#[derive(Clone)]
pub struct ClientComponent;
impl ClientComponent {
pub fn new() -> Self {
ClientComponent
unsafe { Some(std::mem::transmute_copy(&my_struct)) }
} else {
None
}
}
}
impl Component for ClientComponent {
fn name(&self) -> &'static str {
MODULE_NAME
}
fn get_interface() -> Option<&'static (dyn InterfaceWrapper + Sync)> {
Some(&ClientInterfaceWrapper)
}
// fn start_runtime(&self, manager: Arc<Mutex<Manager>>) -> Option<Box<dyn ModuleRuntime>> {
// Some(Box::new(RuntimeTest::new(manager)))
// }
fn start_runtime(config: &'static RuntimeConfig) -> Result<Box<dyn ModuleRuntime>, ModuleError> {
Ok(Box::new(ClientRuntime::new(config)?))
}
fn clone_box(&self) -> Box<dyn Component> {
Box::new(self.clone())
}
fn get_interface(&self) -> Box<dyn Interface> {
Box::new(ClientInterface::from_raw(test1, test2, test3))
pub const fn get_named_component() -> NamedComponent {
NamedComponent {
name: MODULE_NAME,
get_interface: &get_interface,
start_runtime: &start_runtime,
}
}
+5 -4
View File
@@ -1,15 +1,16 @@
use unshell_obfuscate::obfuscated_symbol;
use crate::{Component, config::NamedComponent};
use std::collections::HashMap;
use crate::config::NamedComponent;
#[obfuscated_symbol]
pub fn get_components() -> Vec<NamedComponent> {
// let mut components: HashMap<&'static str, Box<dyn Component>> = HashMap::new();
// let a = crate::client::get_interface;
return vec![
NamedComponent {name:,crate::client::MODULE_NAME, get_interface: crate::client::get_interface, start_runtime: todo!() },
#[cfg(feature = "client")]
crate::client::get_named_component(),
];
// components
+13 -3
View File
@@ -23,23 +23,33 @@ pub struct PayloadConfig {
pub struct RuntimeConfig {
pub parent_component: &'static str,
pub name: &'static str,
pub config: HashMap<String, String>,
pub config: HashMap<&'static str, String>,
}
#[derive(Clone)]
pub struct NamedComponent {
pub name: &'static str,
// + Sync + Sync + Sync + Sync + Sync + Sync + Sync + Sync
pub get_interface: &'static (dyn Fn() -> Option<&'static (dyn InterfaceWrapper + Sync)> + Sync),
pub start_runtime: &'static (
dyn Fn(&'static RuntimeConfig) -> Result<&'static dyn ModuleRuntime, ModuleError>
dyn Fn(&'static RuntimeConfig) -> Result<Box<dyn ModuleRuntime>, ModuleError>
+ Sync
),
}
/// Trait that wraps the get_interface<T>() function inside of components
pub trait InterfaceWrapper: Send + Sync {
fn get_interface<T>() -> Option<T>
fn get_interface<T: 'static>(&self) -> Option<T>
where
Self: Sized;
}
// impl<T: 'static> InterfaceWrapper for T {
// default fn get_interface<T>() -> Option<T>
// where
// Self: Sized,
// {
// None
// }
// }
+13 -13
View File
@@ -12,12 +12,12 @@ pub use components::get_components;
mod announcement;
use std::{
fmt,
sync::{Arc, Mutex},
// sync::{Arc, Mutex},
};
pub use announcement::Announcement;
use crate::module::{Interface, Manager};
// use crate::module::{Interface, Manager};
///Generic error type for module-related operations.
#[derive(Debug)]
@@ -58,16 +58,16 @@ pub trait ModuleRuntime: Send + Sync {
fn kill(self: Box<Self>);
}
pub trait Component {
fn name(&self) -> &'static str;
// fn start_runtime(&self, manager: Arc<Mutex<Manager>>) -> Option<Box<dyn ModuleRuntime>>;
// pub trait Component {
// fn name(&self) -> &'static str;
// // fn start_runtime(&self, manager: Arc<Mutex<Manager>>) -> Option<Box<dyn ModuleRuntime>>;
fn get_interface(&self) -> Box<dyn Interface>;
fn clone_box(&self) -> Box<dyn Component>;
}
// fn get_interface(&self) -> Box<dyn Interface>;
// fn clone_box(&self) -> Box<dyn Component>;
// }
impl Clone for Box<dyn Component> {
fn clone(&self) -> Box<dyn Component> {
self.clone_box()
}
}
// impl Clone for Box<dyn Component> {
// fn clone(&self) -> Box<dyn Component> {
// self.clone_box()
// }
// }
+39 -44
View File
@@ -5,37 +5,35 @@ use std::{
time::Duration,
};
use unshell_obfuscate::symbol;
use crate::{
config::{NamedComponent, PayloadConfig, RuntimeConfig},
*,
};
use module::Module;
use unshell_obfuscate::symbol;
// #[derive(Debug)]
pub struct Manager<'a> {
pub struct Manager {
id: &'static str,
modules: Vec<Module>,
pub modules: Vec<Module>,
active_runtimes: Vec<&'a dyn ModuleRuntime>,
active_runtimes: Vec<Box<dyn ModuleRuntime>>,
// runtime_config: Vec<RuntimeConfig>,
components: HashMap<String, &'a NamedComponent>,
components: HashMap<String, NamedComponent>,
}
// static mut MANAGER_RUNTIME: Option<Arc<Mutex<Manager>>> = None;
impl<'a> Manager<'a> {
fn new(id: &'static str, config: &'a Vec<NamedComponent>, modules: Vec<Module>) -> Self {
impl Manager {
fn new(id: &'static str, config: Vec<NamedComponent>, modules: Vec<Module>) -> Self {
Self {
id,
// config,
modules,
components: config.iter().map(|c| (c.name.to_string(), c)).collect(),
components: config
.into_iter()
.map(|c| (c.name.to_string(), c))
.collect(),
active_runtimes: Vec::new(),
}
}
@@ -44,54 +42,49 @@ impl<'a> Manager<'a> {
#[allow(static_mut_refs)]
pub fn run(config: &'static PayloadConfig, modules: Vec<Module>) {
// Construct self
let this = Self::new(&config.id, &config.components, modules);
let mut this = Self::new(&config.id, config.components.clone(), modules);
// Load each of the pre-prepared modules
// this.load_components();
this.load_components();
let this = Arc::new(Mutex::new(this));
Self::start_runtimes(this.clone(), &config.runtime_config);
// let components = this.components.clone();
// let mut runtimes: Vec<Box<dyn ModuleRuntime>> = Vec::new();
// for (_name, component) in components {
// let module_runtime = component.start_runtime(this.clone());
// if let Some(module_runtime) = module_runtime {
// runtimes.push(module_runtime);
// }
// }
// drop(config);
Self::join(this);
}
// fn load_components(&mut self) {
// for i in 0..self.modules.len() {
// debug!("Importing module {}", i);
// // let this_lock = .unwrap();
// let component_func = if let Ok(component_func) = self.modules[i]
// .get_symbol::<fn() -> HashMap<&'static str, Box<dyn Component>>>(
// symbol!("get_components").as_bytes(),
// ) {
// component_func
// } else {
// warn!("get_components function not found");
// continue;
// };
fn load_components(&mut self) {
for module in &self.modules {
// Load get_components function from shared object library
let component_func = match module
.get_symbol::<fn() -> Vec<NamedComponent>>(symbol!(b"get_components"))
{
Ok(func) => func,
Err(_) => {
warn!("get_components function not found");
continue;
}
};
// let components = component_func();
let components = component_func();
let component_name = "TODO";
// let len = components.len();
// debug!("[{}] Loaded {} components", i, len);
debug!("{} - Retrieved payload metadata", component_name);
// self.components.extend(components);
// }
// }
// Add each component into self
for c in components {
debug!("{} - Found component '{}'", "TODO", c.name);
self.components.insert(c.name.to_owned(), c);
}
}
}
/// Start each runtime
fn start_runtimes(this: Arc<Mutex<Self>>, runtimes: &'static Vec<RuntimeConfig>) {
debug!("Starting runtimes...");
for runtime in runtimes {
let mut this_lock = this.lock().unwrap();
@@ -106,6 +99,8 @@ impl<'a> Manager<'a> {
}
};
debug!("Starting runtime: {}", runtime.name);
let runtime = match (*component.start_runtime)(runtime) {
Ok(runtime) => runtime,
Err(e) => {
+5 -9
View File
@@ -7,10 +7,6 @@ mod module;
pub use manager::Manager;
pub use module::Module;
pub trait Interface {
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any>;
}
/// "Module Interface" helper macro that creates a struct with function pointers
/// Useful for defining and requiring modules' functions accross FFI boundry.
#[macro_export]
@@ -58,10 +54,10 @@ macro_rules! module_interface {
}
}
impl crate::module::Interface for $interface_name {
fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}
}
// impl crate::module::Interface for $interface_name {
// fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> {
// self
// }
// }
};
}
+3 -1
View File
@@ -5,7 +5,6 @@ use crate::{ModuleError, logger::SetupLogger, logger::logger};
use crate::*;
pub struct Module {
// name: String,
lib: Library,
}
@@ -29,6 +28,9 @@ impl Module {
Ok(symbol)
}
// pub fn get_id(&self) -> &str {
// self.id
// }
// pub fn get_interface<T>(&self) -> Result<T, ModuleError> {
// if let Ok(interface_function) = self.get_symbol::<fn() -> T>(b"interface") {
// Ok(interface_function())
+1 -6
View File
@@ -17,7 +17,7 @@ pub struct ListenerRuntime {
impl ListenerRuntime {
pub fn new() -> ListenerRuntime {
info!("Starting listener runtime on 127.0.0.1:1234",);
// info!("Starting listener runtime on {}",);
let listener = TcpListener::bind("127.0.0.1:1234").unwrap();
let streams = Arc::new(Mutex::new(Vec::new()));
@@ -51,11 +51,6 @@ impl ListenerRuntime {
println!("Announcement {:?} sent", announcement);
Ok(())
// self.stream
// .write_all(&u32::to_be_bytes(bytes.len() as u32))?;
// self.stream.write_all(&bytes)?;
// self.stream.flush()?;
}
}