summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-04-04 13:21:59 +0200
committerRoland Reichwein <mail@reichwein.it>2020-04-04 13:21:59 +0200
commit95d5acc8c7e60255b19e7084e374eb26cc5d0ba3 (patch)
treed2ebf474c5076341a30cdeb8035f1843db240d16
parent2be63668af1cadf846ae2d44a0fd5c909ceaf47e (diff)
Versioned plugins
-rw-r--r--plugin.cpp48
-rw-r--r--plugin.h18
-rw-r--r--plugin_interface.h3
-rw-r--r--webserver.cpp8
4 files changed, 67 insertions, 10 deletions
diff --git a/plugin.cpp b/plugin.cpp
index 9c47ed2..c0a01fc 100644
--- a/plugin.cpp
+++ b/plugin.cpp
@@ -1,21 +1,22 @@
#include "plugin.h"
#include <boost/dll/import.hpp>
-#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include <iostream>
#include <filesystem>
-#include "plugin_interface.h"
-
namespace dll = boost::dll;
namespace fs = std::filesystem;
using namespace std::string_literals;
-void load_plugins(Config& config)
+PluginLoader::PluginLoader(Config& config): m_config{config}
+{
+}
+
+void PluginLoader::load_plugins()
{
- const auto& plugin_directories{config.PluginDirectories()};
+ const auto& plugin_directories{m_config.PluginDirectories()};
for (const auto& dir: plugin_directories) {
for (auto& path: fs::recursive_directory_iterator(dir)) {
@@ -23,14 +24,45 @@ void load_plugins(Config& config)
dll::fs::path lib_path{path.path()};
+ try {
boost::shared_ptr<webserver_plugin_interface> plugin = dll::import<webserver_plugin_interface>(lib_path, "webserver_plugin", dll::load_mode::append_decorations);
- if (!plugin)
- throw std::runtime_error("Can't load plugin");
+ if (plugin) {
+ if (plugin->version() != webserver_plugin_interface::interface_version)
+ throw std::runtime_error("Bad interface version for "s + path.path().generic_string() + ": "s + std::to_string(plugin->version()) + " vs. "s + std::to_string(webserver_plugin_interface::interface_version));
- std::cout << "Plugin: " << plugin->generate_page("a") << std::endl;
+ if (m_plugins.contains(plugin->name()))
+ throw std::runtime_error("Plugin already exists: "s + plugin->name());
+
+ m_plugins.emplace(plugin->name(), plugin);
+
+ std::cout << "Found plugin: " << plugin->name() << std::endl;
+ } else
+ std::cout << "Can't load plugin from " << path.path().generic_string() << std::endl;
+ } catch (const std::exception& ex) {
+ std::cout << "Can't load plugin from " << path.path().generic_string() << ": " << ex.what() << std::endl;
+ }
}
}
}
}
+bool PluginLoader::validate_config()
+{
+ const auto& sites{m_config.Sites()};
+
+ for (const auto& site: sites) {
+ for (const auto& path: site.paths) {
+ if (path.type == Plugin) {
+ std::string plugin {path.params.at("plugin")};
+
+ if (!m_plugins.contains(plugin)) {
+ std::cout << "Configured plugin " << plugin << " not found" << std::endl;
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
diff --git a/plugin.h b/plugin.h
index 1c88ff9..cc68524 100644
--- a/plugin.h
+++ b/plugin.h
@@ -1,5 +1,21 @@
#pragma once
#include "config.h"
+#include "plugin_interface.h"
-void load_plugins(Config& config);
+#include <boost/shared_ptr.hpp>
+
+#include <memory>
+#include <unordered_map>
+
+class PluginLoader
+{
+ Config& m_config;
+ std::unordered_map<std::string, boost::shared_ptr<webserver_plugin_interface>> m_plugins;
+
+public:
+ PluginLoader(Config& config);
+
+ void load_plugins(); // Load all plugins from configured paths
+ bool validate_config(); // Check if all configured plugins exist
+};
diff --git a/plugin_interface.h b/plugin_interface.h
index 72da0b9..e67d20a 100644
--- a/plugin_interface.h
+++ b/plugin_interface.h
@@ -6,6 +6,9 @@
class BOOST_SYMBOL_VISIBLE webserver_plugin_interface {
public:
+ static const int interface_version {1};
+ virtual int version() { return interface_version; }
+ virtual std::string name() = 0;
virtual std::string generate_page(std::string path) = 0;
virtual ~webserver_plugin_interface(){}
};
diff --git a/webserver.cpp b/webserver.cpp
index 2574272..3f7a2a3 100644
--- a/webserver.cpp
+++ b/webserver.cpp
@@ -33,7 +33,13 @@ int main(int argc, char* argv[])
try {
Config config{config_filename};
- load_plugins(config);
+
+ PluginLoader plugin_loader(config);
+ plugin_loader.load_plugins();
+
+ if (!plugin_loader.validate_config())
+ throw std::runtime_error("Couldn't find all configured plugins.");
+
return http_server(argc, argv);
} catch (const std::exception& ex) {
std::cout << "Error: " << ex.what() << std::endl;