Simple plugin server example
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
#[macro_export]
|
||||
macro_rules! logger {
|
||||
(const $i:ident $name:expr) => {
|
||||
#[allow(unused)]
|
||||
pub const $i: $crate::once_cell::sync::Lazy<$crate::utils::logger::Logger> =
|
||||
$crate::once_cell::sync::Lazy::new(|| $crate::utils::logger::Logger::new($name));
|
||||
};
|
||||
|
||||
($i:ident $name:expr) => {
|
||||
#[allow(unused)]
|
||||
pub const $i: $crate::once_cell::sync::Lazy<$crate::utils::logger::Logger> =
|
||||
$crate::once_cell::sync::Lazy::new(|| $crate::utils::logger::Logger::new($name));
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod macros;
|
||||
mod plugin;
|
||||
mod requests;
|
||||
mod server;
|
||||
mod types;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
use crate::{logger, plugin::Plugin};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
io::Read,
|
||||
net::{TcpListener, TcpStream},
|
||||
path::Path,
|
||||
process::Command,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
logger!(LOGGER "Plugin Loader");
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PluginJson {
|
||||
pub id: String,
|
||||
pub version: String,
|
||||
pub supported_versions: Vec<String>,
|
||||
pub file: String,
|
||||
pub args: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PluginHandshake {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
pub struct PluginLoader {
|
||||
plugins: Vec<Plugin>,
|
||||
plugin_clients: Arc<Mutex<HashMap<String, TcpStream>>>,
|
||||
}
|
||||
|
||||
impl PluginLoader {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
plugins: Vec::new(),
|
||||
plugin_clients: Arc::new(Mutex::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(&self, json_path: &Path) -> Plugin {
|
||||
let json_string = fs::read_to_string(json_path).unwrap();
|
||||
let plugin_json: PluginJson = serde_json::from_str(&json_string).unwrap();
|
||||
LOGGER.info(format!("Loading {}", plugin_json.id));
|
||||
|
||||
Command::new(plugin_json.file)
|
||||
.args(plugin_json.args)
|
||||
.current_dir("plugins")
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
while self
|
||||
.plugin_clients
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&plugin_json.id)
|
||||
.is_none()
|
||||
{}
|
||||
Plugin(
|
||||
self.plugin_clients
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&plugin_json.id)
|
||||
.unwrap()
|
||||
.try_clone()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn start_server(&self) {
|
||||
let plugin_clients = self.plugin_clients.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let listener = TcpListener::bind("0.0.0.0:7243").unwrap();
|
||||
LOGGER.info("Server listening at 0.0.0.0:7243");
|
||||
|
||||
for stream in listener.incoming() {
|
||||
let mut stream = stream.unwrap();
|
||||
let mut s = String::new();
|
||||
stream.read_to_string(&mut s).unwrap();
|
||||
let plugin_handshake: PluginHandshake = serde_json::from_str(&s).unwrap();
|
||||
plugin_clients
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(plugin_handshake.id, stream);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
use std::net::TcpStream;
|
||||
|
||||
pub mod loader;
|
||||
|
||||
pub struct Plugin(TcpStream);
|
||||
|
||||
impl Plugin {}
|
||||
+19
-3
@@ -1,12 +1,15 @@
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fs,
|
||||
net::{TcpListener, TcpStream},
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
logger, types,
|
||||
logger,
|
||||
plugin::loader::PluginLoader,
|
||||
types,
|
||||
utils::{self, client::Client},
|
||||
};
|
||||
|
||||
@@ -25,6 +28,7 @@ pub struct Server {
|
||||
pub config: ServerConfig,
|
||||
pub clients: Mutex<HashSet<Client>>,
|
||||
pub db: utils::database::Database,
|
||||
pub plugin_loader: PluginLoader,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
@@ -32,8 +36,8 @@ impl Default for ServerConfig {
|
||||
Self {
|
||||
port: 7080,
|
||||
server_name: format!("Server Name"),
|
||||
server_id: format!("offline-server"),
|
||||
server_key: format!(""),
|
||||
server_id: format!("important"),
|
||||
server_key: format!("important"),
|
||||
channels: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -58,13 +62,25 @@ impl Server {
|
||||
root: root.to_path_buf(),
|
||||
config,
|
||||
clients: Mutex::new(HashSet::new()),
|
||||
plugin_loader: PluginLoader::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run(self: &Arc<Self>) -> crate::Result<()> {
|
||||
// Load plugins
|
||||
Self::LOGGER.info("Loading plugins");
|
||||
for entry in fs::read_dir(self.root.join("plugins"))? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
if path.extension().and_then(|s| s.to_str()) == Some("json") {
|
||||
self.plugin_loader.load(&path);
|
||||
}
|
||||
}
|
||||
Self::LOGGER.info("Plugins loaded");
|
||||
|
||||
// Initialize plugins
|
||||
Self::LOGGER.info("Initializing plugins");
|
||||
|
||||
// Start server
|
||||
let listener = TcpListener::bind(format!("0.0.0.0:{}", self.config.port))?;
|
||||
|
||||
Reference in New Issue
Block a user