blob: 28fdb62121f13d4f6a9941f8c6992738462b1c26 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include "plugin.h"
#include <boost/beast/version.hpp>
// Support both boost in Debian unstable (BOOST_LATEST) and in stable (boost 1.67)
#if BOOST_VERSION >= 107100
#define BOOST_LATEST
#endif
#include <boost/dll/import.hpp>
#include <boost/filesystem.hpp>
#include <iostream>
#include <filesystem>
namespace dll = boost::dll;
namespace fs = std::filesystem;
using namespace std::string_literals;
PluginLoader::PluginLoader(Config& config): m_config{config}
{
}
void PluginLoader::load_plugins()
{
const auto& plugin_directories{m_config.PluginDirectories()};
for (const auto& dir: plugin_directories) {
for (auto& path: fs::recursive_directory_iterator(dir)) {
if (path.is_regular_file() && path.path().extension() == ".so"s) {
#ifdef BOOST_LATEST
dll::fs::path lib_path{path.path()};
#else
boost::filesystem::path lib_path{path.path().generic_string()};
#endif
try {
boost::shared_ptr<webserver_plugin_interface> plugin = dll::import<webserver_plugin_interface>(lib_path, "webserver_plugin", dll::load_mode::append_decorations);
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::string name{plugin->name()};
if (m_plugins.find(name) != m_plugins.end())
throw std::runtime_error("Plugin already exists: "s + name);
std::cout << "Found plugin: " << name << " (" << path.path().string() << "), ";
if (m_config.PluginIsConfigured(name)) {
std::cout << "loading.";
m_plugins.emplace(plugin->name(), plugin);
} else {
std::cout << "ignored (not configured).";
}
std::cout << 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) {
// path must contain target and plugin
auto it {path.params.find("target")};
if (it == path.params.end()) {
std::cout << "Path " << path.requested << " for site " << site.name << " is missing target specification." << std::endl;
return false;
}
it = path.params.find("plugin");
if (it == path.params.end()) {
std::cout << "Path " << path.requested << " for site " << site.name << " is missing plugin specification." << std::endl;
return false;
}
std::string plugin {it->second};
// check if plugin exists
if (m_plugins.find(plugin) == m_plugins.end()) {
std::cout << "Configured plugin " << plugin << " not found" << std::endl;
return false;
}
}
}
return true;
}
plugins_container_type& PluginLoader::get_plugins()
{
return m_plugins;
}
|