servers/src/plugins/loader.rs

61 lines
1.8 KiB
Rust
Raw Normal View History

use std::{fs, path::Path, sync::Arc};
2022-06-04 11:58:21 +00:00
use libloading::{Library, Symbol};
use tracing::{info, trace};
2022-06-04 11:58:21 +00:00
use crate::{commands, plugins::Registrar};
2022-06-04 11:58:21 +00:00
use super::{PluginManager, PluginManagerType};
2022-06-16 17:31:09 +00:00
2022-06-05 20:10:23 +00:00
/// Plugins and Commands loader
pub fn loader() -> anyhow::Result<PluginManagerType> {
2022-06-04 11:58:21 +00:00
let config_dir = "./plugins";
// if config directory doesn't exists, create it
if !Path::new(config_dir).exists() {
fs::create_dir_all(config_dir)?;
}
// get path to .so lib from command argument
2022-06-04 11:58:21 +00:00
let paths = fs::read_dir(config_dir)?;
// create a plugin manager
2022-06-04 11:58:21 +00:00
let mut plugin_manager = PluginManager::new();
2022-06-04 18:10:21 +00:00
// register default commands
for command in commands::register_commands() {
plugin_manager.commands.push(command)
2022-06-04 18:10:21 +00:00
}
2022-06-04 11:58:21 +00:00
// for all plugin in directory
for path in paths {
// get library file path
let path = path?.path();
let plugin_path = path.to_str().unwrap();
2022-06-04 11:58:21 +00:00
info!("Loading plugin `{}`", plugin_path);
// loading library from .so is unsafe
2022-06-04 11:58:21 +00:00
unsafe {
// load library
// 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)?));
2022-06-04 11:58:21 +00:00
// 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")?;
2022-06-04 11:58:21 +00:00
// execute initial plugin function
trace!(
"Running function `plugin_entry` from plugin `{}`",
plugin_path
);
func(&mut plugin_manager);
2022-06-04 11:58:21 +00:00
}
}
// return a `PluginManager`
Ok(Arc::new(plugin_manager))
2022-06-04 11:58:21 +00:00
}