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"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"servers",
|
||||
]
|
||||
|
||||
|
|
|
@ -7,5 +7,4 @@ edition = "2021"
|
|||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.56"
|
||||
servers = { path = ".." }
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use async_trait::async_trait;
|
||||
use servers::{
|
||||
plugins::{Command, Event, Plugin, PluginManagerType, Registrar, Result},
|
||||
tcp::Client,
|
||||
tcp::Client, async_trait,
|
||||
};
|
||||
|
||||
struct PluginTest;
|
||||
|
@ -29,7 +28,7 @@ impl Command for PluginTest {
|
|||
|
||||
/// Help message of the command
|
||||
fn help(&self) -> &'static str {
|
||||
"test command"
|
||||
"Test command from plugin"
|
||||
}
|
||||
|
||||
/// Command function
|
||||
|
@ -55,7 +54,9 @@ impl Event for PluginTest {
|
|||
|
||||
/// Event function
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
"show help"
|
||||
"Display all available commands"
|
||||
}
|
||||
|
||||
async fn execute(
|
||||
|
@ -23,10 +23,17 @@ impl Command for CommandHelp {
|
|||
_args: Vec<&str>,
|
||||
plugin_manager: &PluginManagerType,
|
||||
) -> Result<()> {
|
||||
// Vector which will contain help messages of the commands
|
||||
let mut help = Vec::new();
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Build-in commands
|
||||
|
||||
mod disconnect;
|
||||
mod help;
|
||||
|
||||
use crate::plugins::Command;
|
||||
|
@ -7,5 +8,8 @@ use crate::plugins::Command;
|
|||
/// Register build-in commands
|
||||
pub fn register_commands() -> Vec<Box<dyn Command>> {
|
||||
// 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
|
||||
|
||||
#![doc(html_root_url = "https://servers.medzik.xyz")]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
pub mod commands;
|
||||
pub mod logger;
|
||||
mod macros;
|
||||
pub mod plugins;
|
||||
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 cli::Cli;
|
||||
use servers::{
|
||||
logger,
|
||||
plugins::loader,
|
||||
tcp::{handle_connection, handle_websocket, Client},
|
||||
};
|
||||
|
@ -11,10 +12,7 @@ mod cli;
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// init better panic
|
||||
better_panic::install();
|
||||
// init logger
|
||||
tracing_subscriber::fmt().init();
|
||||
logger::init();
|
||||
|
||||
// parse cli args
|
||||
let args = Cli::parse();
|
||||
|
@ -29,13 +27,13 @@ async fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
// start tcp server
|
||||
start_tcp_server(&args.host, &args.port).await?;
|
||||
start_tcp_server(args.host, args.port).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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
|
||||
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
|
||||
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 {
|
||||
Ok(_) => (),
|
||||
Err(err) => error!("Client {}, {}", ip, err),
|
||||
if let Err(e) = handle_connection(client, plugin_manager).await {
|
||||
error!("Client {ip}: {e}")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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 {
|
||||
let tcp_port = tcp_port.clone();
|
||||
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 {
|
||||
Ok(_) => (),
|
||||
Err(err) => error!("Client {}, {}", ip, err),
|
||||
if let Err(e) = handle_websocket(stream, tcp_port).await {
|
||||
error!("Client {ip}: {e}")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{fs, sync::Arc, path::Path};
|
||||
use std::{fs, path::Path, sync::Arc};
|
||||
|
||||
use libloading::{Library, Symbol};
|
||||
use tracing::{debug, trace};
|
||||
use tracing::{info, trace};
|
||||
|
||||
use crate::{commands, plugins::Registrar};
|
||||
|
||||
|
@ -33,7 +33,7 @@ pub fn loader() -> anyhow::Result<PluginManagerType> {
|
|||
let path = path?.path();
|
||||
let plugin_path = path.to_str().unwrap();
|
||||
|
||||
debug!("Loading plugin `{}`", plugin_path);
|
||||
info!("Loading plugin `{}`", plugin_path);
|
||||
|
||||
// loading library from .so is 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
|
||||
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);
|
||||
let func: Symbol<unsafe extern "C" fn(&mut dyn Registrar) -> ()> =
|
||||
lib.get(b"plugin_entry")?;
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,15 +15,13 @@
|
|||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! async-trait = "0.1.56"
|
||||
//! servers = "0.1.0"
|
||||
//! servers = { git = "https://github.com/MedzikUser/servers" }
|
||||
//! ```
|
||||
//!
|
||||
//! In file `src/lib.rs`
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use async_trait::async_trait;
|
||||
//! use servers::{plugins::{Plugin, Registrar}, tcp::Client};
|
||||
//! use servers::{plugins::{Plugin, Registrar}, tcp::Client, async_trait};
|
||||
//!
|
||||
//! struct PluginTest;
|
||||
//!
|
||||
|
@ -50,9 +48,8 @@
|
|||
//! ## Add command
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use async_trait::async_trait;
|
||||
//! use servers::{
|
||||
//! plugins::{Command, PluginManagerType, Registrar, Result},
|
||||
//! plugins::{Command, PluginManagerType, Registrar, Result, async_trait},
|
||||
//! tcp::Client,
|
||||
//! };
|
||||
//! #
|
||||
|
@ -104,9 +101,8 @@
|
|||
//! In file `src/lib.rs`
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use async_trait::async_trait;
|
||||
//! use servers::{
|
||||
//! plugins::{Event, Registrar, Result},
|
||||
//! plugins::{Event, Registrar, Result, async_trait},
|
||||
//! 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
|
||||
pub const MAX_PACKET_LEN: usize = 65536;
|
||||
|
@ -33,7 +38,10 @@ impl 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
|
||||
let content = format!("{content}\n\r");
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use tracing::{error, info, trace};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tracing::{error, info, trace};
|
||||
|
||||
use crate::plugins::PluginManagerType;
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ use futures_util::{
|
|||
stream::{SplitSink, SplitStream},
|
||||
SinkExt, StreamExt,
|
||||
};
|
||||
use tracing::info;
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
net::{
|
||||
|
@ -13,6 +12,7 @@ use tokio::{
|
|||
},
|
||||
};
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
use tracing::info;
|
||||
use tungstenite::Message;
|
||||
|
||||
use super::MAX_PACKET_LEN;
|
||||
|
|
Loading…
Reference in New Issue