add missing doc and handle if client sent an empty buffer

This commit is contained in:
MedzikUser 2022-06-17 22:32:07 +02:00
parent b0c019525e
commit 2c144ae14a
No known key found for this signature in database
GPG Key ID: A5FAC1E185C112DB
5 changed files with 35 additions and 11 deletions

View File

@ -19,6 +19,8 @@
//! //!
//! Go to [plugins](plugins) module //! Go to [plugins](plugins) module
#![warn(missing_docs)]
pub mod commands; pub mod commands;
pub mod plugins; pub mod plugins;
pub mod tcp; pub mod tcp;

View File

@ -19,6 +19,7 @@ pub trait Plugin: Any + Send + Sync {
async fn on_plugin_unload(&self); async fn on_plugin_unload(&self);
} }
/// Trait with function to register plugin.
pub trait PluginRegistrar { pub trait PluginRegistrar {
/// Function to register the plugin /// Function to register the plugin
fn register(&mut self, plugin: Box<dyn Plugin>); fn register(&mut self, plugin: Box<dyn Plugin>);
@ -32,11 +33,12 @@ impl PluginRegistrar for PluginManager {
/// Plugin Manager /// Plugin Manager
pub struct PluginManager { pub struct PluginManager {
/// Vector with all loaded plugins.
pub plugins: Vec<Box<dyn Plugin>>, pub plugins: Vec<Box<dyn Plugin>>,
} }
impl PluginManager { impl PluginManager {
/// Create empty `PluginManager` /// Create empty `PluginManager`.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
plugins: Vec::new(), plugins: Vec::new(),
@ -50,8 +52,10 @@ impl Default for PluginManager {
} }
} }
/// Plugin Manager Type
pub type PluginManagerType = Arc<PluginManager>; pub type PluginManagerType = Arc<PluginManager>;
/// Trait with command functions to implement on struct.
#[async_trait] #[async_trait]
pub trait Command: Any + Send + Sync { pub trait Command: Any + Send + Sync {
/// Command name /// Command name
@ -69,11 +73,12 @@ pub trait Command: Any + Send + Sync {
/// Command Manager /// Command Manager
pub struct CommandManager { pub struct CommandManager {
/// Vector with all commands.
pub commands: Vec<Box<dyn Command>>, pub commands: Vec<Box<dyn Command>>,
} }
impl CommandManager { impl CommandManager {
/// Create empty `CommandManager` /// Create empty `CommandManager`.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
commands: Vec::new(), commands: Vec::new(),
@ -87,10 +92,12 @@ impl Default for CommandManager {
} }
} }
/// Command Manager Type
pub type CommandManagerType = Arc<CommandManager>; pub type CommandManagerType = Arc<CommandManager>;
/// Trait with function to register command.
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(&mut self, command: Box<dyn Command>); fn register(&mut self, command: Box<dyn Command>);
} }
@ -100,6 +107,7 @@ impl CommandRegistrar for CommandManager {
} }
} }
/// Trait with event functions to implement on struct.
#[async_trait] #[async_trait]
pub trait Event: Any + Send + Sync { pub trait Event: Any + Send + Sync {
/// Event name (onConnect, onSend) /// Event name (onConnect, onSend)
@ -110,6 +118,7 @@ pub trait Event: Any + Send + Sync {
/// Event Manager /// Event Manager
pub struct EventManager { pub struct EventManager {
/// Vector with all events loaded from plugins.
pub events: Vec<Box<dyn Event>>, pub events: Vec<Box<dyn Event>>,
} }
@ -126,10 +135,13 @@ impl Default for EventManager {
} }
} }
/// Event Manager Type
pub type EventManagerType = Arc<EventManager>; pub type EventManagerType = Arc<EventManager>;
/// Trait with function to register event.
pub trait EventRegistrar { pub trait EventRegistrar {
/// Function to register the plugin and the commands in the plugin /// Function to register the plugin and the commands in the plugin.
fn register(&mut self, command: Box<dyn Event>); fn register(&mut self, command: Box<dyn Event>);
} }

View File

@ -71,7 +71,7 @@
//! } //! }
//! } //! }
//! //!
//! /// Register plugin and command //! /// Register plugin and event
//! #[no_mangle] //! #[no_mangle]
//! pub fn plugin_entry( //! pub fn plugin_entry(
//! plugin: &mut dyn PluginRegistrar, //! plugin: &mut dyn PluginRegistrar,

View File

@ -1,5 +1,6 @@
#![allow(clippy::unused_io_amount)] #![allow(clippy::unused_io_amount)]
/// Max size of a TCP packet
pub const MAX_PACKET_LEN: usize = 65536; pub const MAX_PACKET_LEN: usize = 65536;
use std::{ use std::{
@ -7,8 +8,9 @@ use std::{
net::TcpStream, net::TcpStream,
}; };
/// TCP Client stream /// TCP Client
pub struct Client { pub struct Client {
/// TCP stream of this client
pub stream: TcpStream, pub stream: TcpStream,
} }
@ -18,7 +20,7 @@ impl Client {
Self { stream } Self { stream }
} }
/// Read message/buffer from Client /// Read message/buffer from client
pub fn read(&mut self) -> anyhow::Result<String> { pub fn read(&mut self) -> anyhow::Result<String> {
// allocate an empty buffer // allocate an empty buffer
let mut buf = [0; MAX_PACKET_LEN]; let mut buf = [0; MAX_PACKET_LEN];
@ -26,13 +28,13 @@ impl Client {
// read buffer from stream // read buffer from stream
self.stream.read(&mut buf)?; self.stream.read(&mut buf)?;
// encode &[u8] to a String and replace null spaces (empty `\0` bytes) // encode &[u8] to a String and delete null bytes (empty `\0` bytes)
let decoded = String::from_utf8(buf.to_vec())?.replace('\0', ""); let decoded = String::from_utf8(buf.to_vec())?.replace('\0', "");
Ok(decoded) Ok(decoded)
} }
/// Send message to Client /// Send message to client
pub fn send(&mut self, content: &str) -> io::Result<()> { pub fn send(&mut self, content: &str) -> io::Result<()> {
// add a new line at the end of the content // add a new line at the end of the content
let content = format!("{content}\n\r"); let content = format!("{content}\n\r");

View File

@ -24,8 +24,16 @@ pub async fn handle_connection(
// run `onSend` events from plugins // run `onSend` events from plugins
check_event(&mut client, &events, "onSend").await; check_event(&mut client, &events, "onSend").await;
// split message by whitespace // split message by whitespaces
let args: &Vec<&str> = &buf.split_ascii_whitespace().collect(); let args: Vec<&str> = buf.split_ascii_whitespace().collect();
// client sent an empty buffer
if args.is_empty() {
client.send("empty buffer").expect("send message");
// don't execute the following commands because it causes panic
continue
}
// get command from args // get command from args
let cmd = args[0]; let cmd = args[0];