From f0fd1b1d2a552bbd4d4159811cf0d09089323c13 Mon Sep 17 00:00:00 2001 From: MedzikUser Date: Thu, 16 Jun 2022 19:31:09 +0200 Subject: [PATCH] add event manager --- plugin_test/src/lib.rs | 34 ++++++++++++++--- src/commands/mod.rs | 4 +- src/plugins/loader.rs | 72 +++++++++++++++++++++++++++++++----- src/tcp/handle_connection.rs | 24 +++++++++++- src/tcp/start.rs | 7 +++- 5 files changed, 120 insertions(+), 21 deletions(-) diff --git a/plugin_test/src/lib.rs b/plugin_test/src/lib.rs index f3c9d9c..2fe9488 100644 --- a/plugin_test/src/lib.rs +++ b/plugin_test/src/lib.rs @@ -1,6 +1,9 @@ use async_trait::async_trait; use servers::{ - plugins::{Command, CommandManagerType, CommandRegistrar, Plugin, PluginRegistrar}, + plugins::{ + Command, CommandManagerType, CommandRegistrar, Event, EventRegistrar, Plugin, + PluginRegistrar, + }, tcp::Client, }; @@ -32,8 +35,29 @@ impl Command for PluginTest { } } -#[no_mangle] -pub fn plugin_entry(registrar: &mut dyn PluginRegistrar, command: &mut dyn CommandRegistrar) { - registrar.register_plugin(Box::new(PluginTest)); - command.register_command(Box::new(PluginTest)); +#[async_trait] +impl Event for PluginTest { + fn name(&self) -> &'static str { + "onConnect" + } + + async fn execute(&self, client: &mut Client) { + client + .send(&format!("Welcome {}", client.stream.peer_addr().unwrap())) + .expect("send message") + } +} + +#[no_mangle] +pub fn plugin_entry( + plugin: &mut dyn PluginRegistrar, + command: &mut dyn CommandRegistrar, + event: &mut dyn EventRegistrar, +) { + // register plugin + plugin.register(Box::new(PluginTest)); + // register command + command.register(Box::new(PluginTest)); + // register plugin + event.register(Box::new(PluginTest)); } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index b5c4349..d25f27a 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,11 +1,9 @@ mod help; -pub use help::*; - use crate::plugins::Command; /// Register default commands pub fn register_commands() -> Vec> { // create Vector with Commands - vec![Box::new(CommandHelp)] + vec![Box::new(help::CommandHelp)] } diff --git a/src/plugins/loader.rs b/src/plugins/loader.rs index 76cbe8f..038da42 100644 --- a/src/plugins/loader.rs +++ b/src/plugins/loader.rs @@ -21,11 +21,11 @@ pub trait Plugin: Any + Send + Sync { pub trait PluginRegistrar { /// Function to register the plugin - fn register_plugin(&mut self, plugin: Box); + fn register(&mut self, plugin: Box); } impl PluginRegistrar for PluginManager { - fn register_plugin(&mut self, plugin: Box) { + fn register(&mut self, plugin: Box) { self.plugins.push(plugin) } } @@ -91,17 +91,56 @@ pub type CommandManagerType = Arc; pub trait CommandRegistrar { /// Function to register the plugin and the commands in the plugin - fn register_command(&mut self, command: Box); + fn register(&mut self, command: Box); } impl CommandRegistrar for CommandManager { - fn register_command(&mut self, command: Box) { + fn register(&mut self, command: Box) { self.commands.push(command) } } +#[async_trait] +pub trait Event: Any + Send + Sync { + /// Event name (onConnect, onSend) + fn name(&self) -> &'static str; + /// Event function + async fn execute(&self, client: &mut Client); +} + +/// Event Manager +pub struct EventManager { + pub events: Vec>, +} + +impl EventManager { + /// Create empty `EventManager` + pub fn new() -> Self { + Self { events: Vec::new() } + } +} + +impl Default for EventManager { + fn default() -> Self { + Self::new() + } +} + +pub type EventManagerType = Arc; + +pub trait EventRegistrar { + /// Function to register the plugin and the commands in the plugin + fn register(&mut self, command: Box); +} + +impl EventRegistrar for EventManager { + fn register(&mut self, command: Box) { + self.events.push(command) + } +} + /// Plugins and Commands loader -pub fn loader() -> anyhow::Result<(CommandManagerType, PluginManagerType)> { +pub fn loader() -> anyhow::Result<(CommandManagerType, PluginManagerType, EventManagerType)> { // get path to .so lib from command argument let config_dir = "./plugins"; let paths = fs::read_dir(config_dir)?; @@ -112,6 +151,9 @@ pub fn loader() -> anyhow::Result<(CommandManagerType, PluginManagerType)> { // create a command manager where located all commands let mut command_manager = CommandManager::new(); + // create a command manager where located all events from plugins + let mut event_manager = EventManager::new(); + // register default commands for command in commands::register_commands() { command_manager.commands.push(command) @@ -136,15 +178,27 @@ pub fn loader() -> anyhow::Result<(CommandManagerType, PluginManagerType)> { // get `plugin_entry` from library trace!("Finding symbol `plugin_entry` in `{}`", plugin_path); let func: Symbol< - unsafe extern "C" fn(&mut dyn PluginRegistrar, &mut dyn CommandRegistrar) -> (), + unsafe extern "C" fn( + &mut dyn PluginRegistrar, + &mut dyn CommandRegistrar, + &mut dyn EventRegistrar, + ) -> (), > = lib.get(b"plugin_entry")?; // execute initial plugin function trace!("Running `plugin_entry(...)` in plugin `{}`", plugin_path); - func(&mut plugin_manager, &mut command_manager); + func( + &mut plugin_manager, + &mut command_manager, + &mut event_manager, + ); } } - // return CommandManager and PluginManager - Ok((Arc::new(command_manager), Arc::new(plugin_manager))) + // return CommandManager, PluginManager and EventManager + Ok(( + Arc::new(command_manager), + Arc::new(plugin_manager), + Arc::new(event_manager), + )) } diff --git a/src/tcp/handle_connection.rs b/src/tcp/handle_connection.rs index e1847fb..8d0ddb2 100644 --- a/src/tcp/handle_connection.rs +++ b/src/tcp/handle_connection.rs @@ -2,7 +2,7 @@ use std::io::Write; use log::trace; -use crate::plugins::CommandManagerType; +use crate::plugins::{CommandManagerType, EventManagerType}; use super::Client; @@ -10,13 +10,20 @@ use super::Client; pub async fn handle_connection( mut client: Client, commands: CommandManagerType, + events: EventManagerType, ) -> anyhow::Result<()> { println!("New Client: {:?}", client.stream.peer_addr()?); + // run `onConnect` events from plugins + check_event(&mut client, &events, "onConnect").await; + loop { // read client message/buffer let buf = client.read()?; + // run `onSend` events from plugins + check_event(&mut client, &events, "onSend").await; + // split message by whitespace let args: &Vec<&str> = &buf.split_ascii_whitespace().collect(); @@ -27,8 +34,9 @@ pub async fn handle_connection( for command in commands.commands.iter() { // if this is the entered command if cmd == command.name() { - // execute command trace!("Executing a command `{}`", command.name()); + + // execute command command .execute(&mut client, args[1..args.len()].to_vec(), &commands) .await; @@ -47,3 +55,15 @@ pub async fn handle_connection( Ok(()) } + +async fn check_event(client: &mut Client, events: &EventManagerType, event_name: &str) { + for event in events.events.iter() { + // check if this event should be started + if event.name() == event_name { + trace!("Executing a event `{}`", event.name()); + + // execute event + event.execute(client).await; + } + } +} diff --git a/src/tcp/start.rs b/src/tcp/start.rs index 49e8817..e9d781e 100644 --- a/src/tcp/start.rs +++ b/src/tcp/start.rs @@ -13,16 +13,19 @@ pub async fn start_server(host: &str, port: &str) -> anyhow::Result<()> { println!("Tcp server started at: {}", listener.local_addr()?); // load plugins and commands - let (command_manager, _plugin_manager) = loader()?; + let (command_manager, _plugin_manager, event_manager) = loader()?; // Accepts a new incoming connection from this listener. while let Ok((stream, _address)) = listener.accept() { let client = Client::new(stream); + // clone `CommandManager` let command_manager = command_manager.clone(); + // clone `EventManager` + let event_manager = event_manager.clone(); // handle client connection in new thread - tokio::spawn(handle_connection(client, command_manager)); + tokio::spawn(handle_connection(client, command_manager, event_manager)); } Ok(())