mirror of https://github.com/MedzikUser/servers
add event manager
This commit is contained in:
parent
01f6ed8ad8
commit
f0fd1b1d2a
|
@ -1,6 +1,9 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use servers::{
|
use servers::{
|
||||||
plugins::{Command, CommandManagerType, CommandRegistrar, Plugin, PluginRegistrar},
|
plugins::{
|
||||||
|
Command, CommandManagerType, CommandRegistrar, Event, EventRegistrar, Plugin,
|
||||||
|
PluginRegistrar,
|
||||||
|
},
|
||||||
tcp::Client,
|
tcp::Client,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,8 +35,29 @@ impl Command for PluginTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[async_trait]
|
||||||
pub fn plugin_entry(registrar: &mut dyn PluginRegistrar, command: &mut dyn CommandRegistrar) {
|
impl Event for PluginTest {
|
||||||
registrar.register_plugin(Box::new(PluginTest));
|
fn name(&self) -> &'static str {
|
||||||
command.register_command(Box::new(PluginTest));
|
"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;
|
mod help;
|
||||||
|
|
||||||
pub use help::*;
|
|
||||||
|
|
||||||
use crate::plugins::Command;
|
use crate::plugins::Command;
|
||||||
|
|
||||||
/// Register default commands
|
/// Register default commands
|
||||||
pub fn register_commands() -> Vec<Box<dyn Command>> {
|
pub fn register_commands() -> Vec<Box<dyn Command>> {
|
||||||
// create Vector with Commands
|
// 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 {
|
pub trait PluginRegistrar {
|
||||||
/// Function to register the plugin
|
/// 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 {
|
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)
|
self.plugins.push(plugin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,17 +91,56 @@ pub type CommandManagerType = Arc<CommandManager>;
|
||||||
|
|
||||||
pub trait CommandRegistrar {
|
pub trait CommandRegistrar {
|
||||||
/// Function to register the plugin and the commands in the plugin
|
/// 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 {
|
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)
|
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
|
/// 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
|
// get path to .so lib from command argument
|
||||||
let config_dir = "./plugins";
|
let config_dir = "./plugins";
|
||||||
let paths = fs::read_dir(config_dir)?;
|
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
|
// create a command manager where located all commands
|
||||||
let mut command_manager = CommandManager::new();
|
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
|
// register default commands
|
||||||
for command in commands::register_commands() {
|
for command in commands::register_commands() {
|
||||||
command_manager.commands.push(command)
|
command_manager.commands.push(command)
|
||||||
|
@ -136,15 +178,27 @@ pub fn loader() -> anyhow::Result<(CommandManagerType, PluginManagerType)> {
|
||||||
// get `plugin_entry` from library
|
// get `plugin_entry` from library
|
||||||
trace!("Finding symbol `plugin_entry` in `{}`", plugin_path);
|
trace!("Finding symbol `plugin_entry` in `{}`", plugin_path);
|
||||||
let func: Symbol<
|
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")?;
|
> = lib.get(b"plugin_entry")?;
|
||||||
|
|
||||||
// execute initial plugin function
|
// execute initial plugin function
|
||||||
trace!("Running `plugin_entry(...)` in plugin `{}`", plugin_path);
|
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
|
// return CommandManager, PluginManager and EventManager
|
||||||
Ok((Arc::new(command_manager), Arc::new(plugin_manager)))
|
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 log::trace;
|
||||||
|
|
||||||
use crate::plugins::CommandManagerType;
|
use crate::plugins::{CommandManagerType, EventManagerType};
|
||||||
|
|
||||||
use super::Client;
|
use super::Client;
|
||||||
|
|
||||||
|
@ -10,13 +10,20 @@ use super::Client;
|
||||||
pub async fn handle_connection(
|
pub async fn handle_connection(
|
||||||
mut client: Client,
|
mut client: Client,
|
||||||
commands: CommandManagerType,
|
commands: CommandManagerType,
|
||||||
|
events: EventManagerType,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
println!("New Client: {:?}", client.stream.peer_addr()?);
|
println!("New Client: {:?}", client.stream.peer_addr()?);
|
||||||
|
|
||||||
|
// run `onConnect` events from plugins
|
||||||
|
check_event(&mut client, &events, "onConnect").await;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// read client message/buffer
|
// read client message/buffer
|
||||||
let buf = client.read()?;
|
let buf = client.read()?;
|
||||||
|
|
||||||
|
// run `onSend` events from plugins
|
||||||
|
check_event(&mut client, &events, "onSend").await;
|
||||||
|
|
||||||
// split message by whitespace
|
// split message by whitespace
|
||||||
let args: &Vec<&str> = &buf.split_ascii_whitespace().collect();
|
let args: &Vec<&str> = &buf.split_ascii_whitespace().collect();
|
||||||
|
|
||||||
|
@ -27,8 +34,9 @@ pub async fn handle_connection(
|
||||||
for command in commands.commands.iter() {
|
for command in commands.commands.iter() {
|
||||||
// if this is the entered command
|
// if this is the entered command
|
||||||
if cmd == command.name() {
|
if cmd == command.name() {
|
||||||
// execute command
|
|
||||||
trace!("Executing a command `{}`", command.name());
|
trace!("Executing a command `{}`", command.name());
|
||||||
|
|
||||||
|
// execute command
|
||||||
command
|
command
|
||||||
.execute(&mut client, args[1..args.len()].to_vec(), &commands)
|
.execute(&mut client, args[1..args.len()].to_vec(), &commands)
|
||||||
.await;
|
.await;
|
||||||
|
@ -47,3 +55,15 @@ pub async fn handle_connection(
|
||||||
|
|
||||||
Ok(())
|
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()?);
|
println!("Tcp server started at: {}", listener.local_addr()?);
|
||||||
|
|
||||||
// load plugins and commands
|
// 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.
|
// Accepts a new incoming connection from this listener.
|
||||||
while let Ok((stream, _address)) = listener.accept() {
|
while let Ok((stream, _address)) = listener.accept() {
|
||||||
let client = Client::new(stream);
|
let client = Client::new(stream);
|
||||||
|
|
||||||
|
// clone `CommandManager`
|
||||||
let command_manager = command_manager.clone();
|
let command_manager = command_manager.clone();
|
||||||
|
// clone `EventManager`
|
||||||
|
let event_manager = event_manager.clone();
|
||||||
|
|
||||||
// handle client connection in new thread
|
// handle client connection in new thread
|
||||||
tokio::spawn(handle_connection(client, command_manager));
|
tokio::spawn(handle_connection(client, command_manager, event_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue