mirror of https://github.com/MedzikUser/servers
chore: some changes (more in the commit description)
- added `/disconnect` commands - moved logger init function to other file - updated command description - the `/help` command has been accelerated - re-export `async_trait` so that it doesn't have to be added to dependencies in plugins
This commit is contained in:
parent
6ad4afb146
commit
3fb0a1132a
|
@ -474,7 +474,6 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
name = "plugin_test"
|
name = "plugin_test"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
|
||||||
"servers",
|
"servers",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,4 @@ edition = "2021"
|
||||||
crate-type = ["dylib"]
|
crate-type = ["dylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait = "0.1.56"
|
|
||||||
servers = { path = ".." }
|
servers = { path = ".." }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use async_trait::async_trait;
|
|
||||||
use servers::{
|
use servers::{
|
||||||
plugins::{Command, Event, Plugin, PluginManagerType, Registrar, Result},
|
plugins::{Command, Event, Plugin, PluginManagerType, Registrar, Result},
|
||||||
tcp::Client,
|
tcp::Client, async_trait,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PluginTest;
|
struct PluginTest;
|
||||||
|
@ -29,7 +28,7 @@ impl Command for PluginTest {
|
||||||
|
|
||||||
/// Help message of the command
|
/// Help message of the command
|
||||||
fn help(&self) -> &'static str {
|
fn help(&self) -> &'static str {
|
||||||
"test command"
|
"Test command from plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Command function
|
/// Command function
|
||||||
|
@ -55,7 +54,9 @@ impl Event for PluginTest {
|
||||||
|
|
||||||
/// Event function
|
/// Event function
|
||||||
async fn execute(&self, client: &mut Client) -> Result<()> {
|
async fn execute(&self, client: &mut Client) -> Result<()> {
|
||||||
client.send(&format!("Welcome {}", client.stream.peer_addr().unwrap())).await?;
|
client
|
||||||
|
.send(&format!("Welcome {}", client.stream.peer_addr().unwrap()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
plugins::{Command, PluginManagerType, Result},
|
||||||
|
tcp::Client,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct CommandDisconnect;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Command for CommandDisconnect {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"/disconnect"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn help(&self) -> &'static str {
|
||||||
|
"Disconnect from the server"
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn execute(
|
||||||
|
&self,
|
||||||
|
client: &mut Client,
|
||||||
|
_args: Vec<&str>,
|
||||||
|
_plugin_manager: &PluginManagerType,
|
||||||
|
) -> Result<()> {
|
||||||
|
// close the connection
|
||||||
|
client.stream.shutdown().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ impl Command for CommandHelp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help(&self) -> &'static str {
|
fn help(&self) -> &'static str {
|
||||||
"show help"
|
"Display all available commands"
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execute(
|
async fn execute(
|
||||||
|
@ -23,10 +23,17 @@ impl Command for CommandHelp {
|
||||||
_args: Vec<&str>,
|
_args: Vec<&str>,
|
||||||
plugin_manager: &PluginManagerType,
|
plugin_manager: &PluginManagerType,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
// Vector which will contain help messages of the commands
|
||||||
|
let mut help = Vec::new();
|
||||||
|
|
||||||
for command in plugin_manager.commands.iter() {
|
for command in plugin_manager.commands.iter() {
|
||||||
client.send(&format!("{} - {}", command.name(), command.help())).await?;
|
// add a help message for the command
|
||||||
|
help.push(format!("{} - {}", command.name(), command.help()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send help message to the client
|
||||||
|
client.send(help.join("\n\r")).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Build-in commands
|
//! Build-in commands
|
||||||
|
|
||||||
|
mod disconnect;
|
||||||
mod help;
|
mod help;
|
||||||
|
|
||||||
use crate::plugins::Command;
|
use crate::plugins::Command;
|
||||||
|
@ -7,5 +8,8 @@ use crate::plugins::Command;
|
||||||
/// Register build-in commands
|
/// Register build-in commands
|
||||||
pub fn register_commands() -> Vec<Box<dyn Command>> {
|
pub fn register_commands() -> Vec<Box<dyn Command>> {
|
||||||
// create array with build-in commands
|
// create array with build-in commands
|
||||||
vec![Box::new(help::CommandHelp)]
|
vec![
|
||||||
|
Box::new(help::CommandHelp),
|
||||||
|
Box::new(disconnect::CommandDisconnect),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,11 @@
|
||||||
//! Go to [plugins](plugins) module
|
//! Go to [plugins](plugins) module
|
||||||
|
|
||||||
#![doc(html_root_url = "https://servers.medzik.xyz")]
|
#![doc(html_root_url = "https://servers.medzik.xyz")]
|
||||||
#![warn(missing_docs)]
|
|
||||||
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod logger;
|
||||||
|
mod macros;
|
||||||
pub mod plugins;
|
pub mod plugins;
|
||||||
pub mod tcp;
|
pub mod tcp;
|
||||||
mod macros;
|
|
||||||
|
pub use async_trait::async_trait;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
use tracing::metadata::LevelFilter;
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
better_panic::install();
|
||||||
|
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_max_level(LevelFilter::TRACE)
|
||||||
|
.init();
|
||||||
|
}
|
29
src/main.rs
29
src/main.rs
|
@ -1,6 +1,7 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cli::Cli;
|
use cli::Cli;
|
||||||
use servers::{
|
use servers::{
|
||||||
|
logger,
|
||||||
plugins::loader,
|
plugins::loader,
|
||||||
tcp::{handle_connection, handle_websocket, Client},
|
tcp::{handle_connection, handle_websocket, Client},
|
||||||
};
|
};
|
||||||
|
@ -11,10 +12,7 @@ mod cli;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
// init better panic
|
logger::init();
|
||||||
better_panic::install();
|
|
||||||
// init logger
|
|
||||||
tracing_subscriber::fmt().init();
|
|
||||||
|
|
||||||
// parse cli args
|
// parse cli args
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
|
@ -29,13 +27,13 @@ async fn main() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// start tcp server
|
// start tcp server
|
||||||
start_tcp_server(&args.host, &args.port).await?;
|
start_tcp_server(args.host, args.port).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start tcp server
|
/// Start tcp server
|
||||||
async fn start_tcp_server(host: &str, port: &str) -> anyhow::Result<()> {
|
async fn start_tcp_server(host: String, port: String) -> anyhow::Result<()> {
|
||||||
// listen Tcp server
|
// listen Tcp server
|
||||||
let listener = TcpListener::bind(format!("{host}:{port}")).await?;
|
let listener = TcpListener::bind(format!("{host}:{port}")).await?;
|
||||||
|
|
||||||
|
@ -51,11 +49,14 @@ async fn start_tcp_server(host: &str, port: &str) -> anyhow::Result<()> {
|
||||||
|
|
||||||
// handle client connection in new thread
|
// handle client connection in new thread
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let ip = client.stream.peer_addr().unwrap();
|
// get ip address of the client
|
||||||
|
let ip = client
|
||||||
|
.stream
|
||||||
|
.peer_addr()
|
||||||
|
.expect("failed to get peer address");
|
||||||
|
|
||||||
match handle_connection(client, plugin_manager).await {
|
if let Err(e) = handle_connection(client, plugin_manager).await {
|
||||||
Ok(_) => (),
|
error!("Client {ip}: {e}")
|
||||||
Err(err) => error!("Client {}, {}", ip, err),
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -75,11 +76,11 @@ async fn start_ws_server(host: String, port: String, tcp_port: String) -> anyhow
|
||||||
while let Ok((stream, _address)) = listener.accept().await {
|
while let Ok((stream, _address)) = listener.accept().await {
|
||||||
let tcp_port = tcp_port.clone();
|
let tcp_port = tcp_port.clone();
|
||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
let ip = stream.peer_addr().unwrap();
|
// get ip address of the client
|
||||||
|
let ip = stream.peer_addr().expect("failed to get peer address");
|
||||||
|
|
||||||
match handle_websocket(stream, tcp_port).await {
|
if let Err(e) = handle_websocket(stream, tcp_port).await {
|
||||||
Ok(_) => (),
|
error!("Client {ip}: {e}")
|
||||||
Err(err) => error!("Client {}, {}", ip, err),
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{fs, sync::Arc, path::Path};
|
use std::{fs, path::Path, sync::Arc};
|
||||||
|
|
||||||
use libloading::{Library, Symbol};
|
use libloading::{Library, Symbol};
|
||||||
use tracing::{debug, trace};
|
use tracing::{info, trace};
|
||||||
|
|
||||||
use crate::{commands, plugins::Registrar};
|
use crate::{commands, plugins::Registrar};
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ pub fn loader() -> anyhow::Result<PluginManagerType> {
|
||||||
let path = path?.path();
|
let path = path?.path();
|
||||||
let plugin_path = path.to_str().unwrap();
|
let plugin_path = path.to_str().unwrap();
|
||||||
|
|
||||||
debug!("Loading plugin `{}`", plugin_path);
|
info!("Loading plugin `{}`", plugin_path);
|
||||||
|
|
||||||
// loading library from .so is unsafe
|
// loading library from .so is unsafe
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -41,13 +41,16 @@ pub fn loader() -> anyhow::Result<PluginManagerType> {
|
||||||
// Box::new and Box::leak must be there because if it isn't there it throws a segmentation fault
|
// Box::new and Box::leak must be there because if it isn't there it throws a segmentation fault
|
||||||
let lib = Box::leak(Box::new(Library::new(&path)?));
|
let lib = Box::leak(Box::new(Library::new(&path)?));
|
||||||
|
|
||||||
// get `plugin_entry` from library
|
// get function `plugin_entry` from library
|
||||||
trace!("Finding symbol `plugin_entry` in `{}`", plugin_path);
|
trace!("Finding symbol `plugin_entry` in `{}`", plugin_path);
|
||||||
let func: Symbol<unsafe extern "C" fn(&mut dyn Registrar) -> ()> =
|
let func: Symbol<unsafe extern "C" fn(&mut dyn Registrar) -> ()> =
|
||||||
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 function `plugin_entry` from plugin `{}`",
|
||||||
|
plugin_path
|
||||||
|
);
|
||||||
func(&mut plugin_manager);
|
func(&mut plugin_manager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,13 @@
|
||||||
//!
|
//!
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! [dependencies]
|
//! [dependencies]
|
||||||
//! async-trait = "0.1.56"
|
//! servers = { git = "https://github.com/MedzikUser/servers" }
|
||||||
//! servers = "0.1.0"
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! In file `src/lib.rs`
|
//! In file `src/lib.rs`
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use async_trait::async_trait;
|
//! use servers::{plugins::{Plugin, Registrar}, tcp::Client, async_trait};
|
||||||
//! use servers::{plugins::{Plugin, Registrar}, tcp::Client};
|
|
||||||
//!
|
//!
|
||||||
//! struct PluginTest;
|
//! struct PluginTest;
|
||||||
//!
|
//!
|
||||||
|
@ -50,9 +48,8 @@
|
||||||
//! ## Add command
|
//! ## Add command
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use async_trait::async_trait;
|
|
||||||
//! use servers::{
|
//! use servers::{
|
||||||
//! plugins::{Command, PluginManagerType, Registrar, Result},
|
//! plugins::{Command, PluginManagerType, Registrar, Result, async_trait},
|
||||||
//! tcp::Client,
|
//! tcp::Client,
|
||||||
//! };
|
//! };
|
||||||
//! #
|
//! #
|
||||||
|
@ -104,9 +101,8 @@
|
||||||
//! In file `src/lib.rs`
|
//! In file `src/lib.rs`
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use async_trait::async_trait;
|
|
||||||
//! use servers::{
|
//! use servers::{
|
||||||
//! plugins::{Event, Registrar, Result},
|
//! plugins::{Event, Registrar, Result, async_trait},
|
||||||
//! tcp::Client,
|
//! tcp::Client,
|
||||||
//! };
|
//! };
|
||||||
//! #
|
//! #
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
use tokio::{net::TcpStream, io::{self, AsyncWriteExt, AsyncReadExt}};
|
use core::fmt;
|
||||||
|
|
||||||
|
use tokio::{
|
||||||
|
io::{self, AsyncReadExt, AsyncWriteExt},
|
||||||
|
net::TcpStream,
|
||||||
|
};
|
||||||
|
|
||||||
/// Max size of a TCP packet
|
/// Max size of a TCP packet
|
||||||
pub const MAX_PACKET_LEN: usize = 65536;
|
pub const MAX_PACKET_LEN: usize = 65536;
|
||||||
|
@ -33,7 +38,10 @@ impl Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send message to the client
|
/// Send message to the client
|
||||||
pub async fn send(&mut self, content: &str) -> io::Result<()> {
|
pub async fn send<S>(&mut self, content: S) -> io::Result<()>
|
||||||
|
where
|
||||||
|
S: ToString + fmt::Debug + fmt::Display,
|
||||||
|
{
|
||||||
// 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");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use tracing::{error, info, trace};
|
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
|
use tracing::{error, info, trace};
|
||||||
|
|
||||||
use crate::plugins::PluginManagerType;
|
use crate::plugins::PluginManagerType;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ use futures_util::{
|
||||||
stream::{SplitSink, SplitStream},
|
stream::{SplitSink, SplitStream},
|
||||||
SinkExt, StreamExt,
|
SinkExt, StreamExt,
|
||||||
};
|
};
|
||||||
use tracing::info;
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
io::{AsyncReadExt, AsyncWriteExt},
|
||||||
net::{
|
net::{
|
||||||
|
@ -13,6 +12,7 @@ use tokio::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tokio_tungstenite::WebSocketStream;
|
use tokio_tungstenite::WebSocketStream;
|
||||||
|
use tracing::info;
|
||||||
use tungstenite::Message;
|
use tungstenite::Message;
|
||||||
|
|
||||||
use super::MAX_PACKET_LEN;
|
use super::MAX_PACKET_LEN;
|
||||||
|
|
Loading…
Reference in New Issue