mirror of
https://github.com/MedzikUser/servers
synced 2024-08-14 23:57:48 +00:00
add event manager
This commit is contained in:
parent
01f6ed8ad8
commit
f0fd1b1d2a
5 changed files with 120 additions and 21 deletions
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
mod help;
|
||||
|
||||
pub use help::*;
|
||||
|
||||
use crate::plugins::Command;
|
||||
|
||||
/// Register default commands
|
||||
pub fn register_commands() -> Vec<Box<dyn Command>> {
|
||||
// create Vector with Commands
|
||||
vec![Box::new(CommandHelp)]
|
||||
vec![Box::new(help::CommandHelp)]
|
||||
}
|
||||
|
|
|
@ -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<dyn Plugin>);
|
||||
fn register(&mut self, plugin: Box<dyn Plugin>);
|
||||
}
|
||||
|
||||
impl PluginRegistrar for PluginManager {
|
||||
fn register_plugin(&mut self, plugin: Box<dyn Plugin>) {
|
||||
fn register(&mut self, plugin: Box<dyn Plugin>) {
|
||||
self.plugins.push(plugin)
|
||||
}
|
||||
}
|
||||
|
@ -91,17 +91,56 @@ pub type CommandManagerType = Arc<CommandManager>;
|
|||
|
||||
pub trait CommandRegistrar {
|
||||
/// Function to register the plugin and the commands in the plugin
|
||||
fn register_command(&mut self, command: Box<dyn Command>);
|
||||
fn register(&mut self, command: Box<dyn Command>);
|
||||
}
|
||||
|
||||
impl CommandRegistrar for CommandManager {
|
||||
fn register_command(&mut self, command: Box<dyn Command>) {
|
||||
fn register(&mut self, command: Box<dyn Command>) {
|
||||
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<Box<dyn Event>>,
|
||||
}
|
||||
|
||||
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<EventManager>;
|
||||
|
||||
pub trait EventRegistrar {
|
||||
/// Function to register the plugin and the commands in the plugin
|
||||
fn register(&mut self, command: Box<dyn Event>);
|
||||
}
|
||||
|
||||
impl EventRegistrar for EventManager {
|
||||
fn register(&mut self, command: Box<dyn Event>) {
|
||||
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),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
|
|
Loading…
Reference in a new issue