]> git.stg.codes - stg.git/blob - stargazer/plugin_runner.cpp
Public interfaces: part 1
[stg.git] / stargazer / plugin_runner.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
20  */
21
22 #include "plugin_runner.h"
23
24 #include "stg/common.h"
25
26 #include <dlfcn.h>
27 #include <unistd.h>
28
29 using STG::PluginRunner;
30 using STG::Plugin;
31
32 //-----------------------------------------------------------------------------
33 PluginRunner::PluginRunner(const std::string& fileName,
34                            const std::string& name,
35                            const ModuleSettings& ms,
36                            Admins& admins,
37                            Tariffs& tariffs,
38                            Users& users,
39                            Services& services,
40                            Corporations& corporations,
41                            TraffCounter& traffcounter,
42                            Store& store,
43                            const Settings& settings)
44     : pluginFileName(fileName),
45       pluginName(name),
46       libHandle(NULL),
47       m_plugin(load(ms, admins, tariffs, users, services, corporations,
48                     traffcounter, store, settings))
49 {
50 }
51 //-----------------------------------------------------------------------------
52 PluginRunner::~PluginRunner()
53 {
54     delete &m_plugin;
55     if (dlclose(libHandle))
56     {
57         errorStr = "Failed to unload plugin '" + pluginFileName + "': " + dlerror();
58         printfd(__FILE__, "PluginRunner::Unload() - %s", errorStr.c_str());
59     }
60 }
61 //-----------------------------------------------------------------------------
62 int PluginRunner::Start()
63 {
64     int res = m_plugin.Start();
65     errorStr = m_plugin.GetStrError();
66     return res;
67 }
68 //-----------------------------------------------------------------------------
69 int PluginRunner::Stop()
70 {
71     int res = m_plugin.Stop();
72     errorStr = m_plugin.GetStrError();
73     return res;
74 }
75 //-----------------------------------------------------------------------------
76 int PluginRunner::Reload(const ModuleSettings& ms)
77 {
78     int res = m_plugin.Reload(ms);
79     errorStr = m_plugin.GetStrError();
80     return res;
81 }
82 //-----------------------------------------------------------------------------
83 Plugin & PluginRunner::load(const ModuleSettings& ms,
84                             Admins& admins,
85                             Tariffs& tariffs,
86                             Users& users,
87                             Services& services,
88                             Corporations& corporations,
89                             TraffCounter& traffcounter,
90                             Store& store,
91                             const Settings& settings)
92 {
93     if (pluginFileName.empty())
94     {
95         const std::string msg = "Empty plugin file name.";
96         printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
97         throw Error(msg);
98     }
99
100     if (access(pluginFileName.c_str(), R_OK))
101     {
102         const std::string msg = "Plugin file '" + pluginFileName + "' is missing or inaccessible.";
103         printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
104         throw Error(msg);
105     }
106
107     libHandle = dlopen(pluginFileName.c_str(), RTLD_NOW);
108
109     if (!libHandle)
110     {
111         std::string msg = "Error loading plugin '" + pluginFileName + "'";
112         const char* error = dlerror();
113         if (error)
114             msg = msg + ": '" + error + "'";
115         printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
116         throw Error(msg);
117     }
118
119     using Getter = Plugin* (*)();
120     auto GetPlugin = reinterpret_cast<Getter>(dlsym(libHandle, "GetPlugin"));
121     if (!GetPlugin)
122     {
123         const std::string msg = "Plugin '" + pluginFileName + "' does not have GetPlugin() function. ";
124         printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
125         throw Error(msg);
126     }
127
128     Plugin* plugin = GetPlugin();
129
130     if (!plugin)
131     {
132         const std::string msg = "Failed to create an instance of plugin '" + pluginFileName + "'.";
133         printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
134         throw Error(msg);
135     }
136
137     plugin->SetSettings(ms);
138     plugin->SetTariffs(&tariffs);
139     plugin->SetAdmins(&admins);
140     plugin->SetUsers(&users);
141     plugin->SetServices(&services);
142     plugin->SetCorporations(&corporations);
143     plugin->SetTraffcounter(&traffcounter);
144     plugin->SetStore(&store);
145     plugin->SetStgSettings(&settings);
146
147     if (plugin->ParseSettings())
148     {
149         const std::string msg = "Plugin '" + pluginFileName + "' is unable to parse settings. " + plugin->GetStrError();
150         printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
151         throw Error(msg);
152     }
153
154     return *plugin;
155 }