source: nscp/service/NSCPlugin.cpp @ 9b9be81

0.4.00.4.10.4.2
Last change on this file since 9b9be81 was 9b9be81, checked in by Michael Medin <michael@…>, 20 months ago
  • Fixed many many issues all over the place as I tried to make things working for my pressention at nwc.
  • Property mode set to 100644
File size: 16.2 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#include "StdAfx.h"
22#include "NSCPlugin.h"
23#include "core_api.h"
24
25/**
26 * Default c-tor
27 * Initializes the plug in name but does not load the actual plug in.<br>
28 * To load the plug in use function load() that loads an initializes the plug in.
29 *
30 * @param file The file (DLL) to load as a NSC plug in.
31 */
32NSCPlugin::NSCPlugin(const unsigned int id, const boost::filesystem::wpath file, std::wstring alias)
33        : module_(file.string())
34        ,fLoadModule(NULL)
35        ,fGetName(NULL)
36        ,fHasCommandHandler(NULL)
37        ,fUnLoadModule(NULL)
38        ,fHasMessageHandler(NULL)
39        ,fHandleMessage(NULL)
40        ,fDeleteBuffer(NULL)
41        ,fGetDescription(NULL)
42        ,fGetVersion(NULL)
43        ,fCommandLineExec(NULL)
44        ,fHasNotificationHandler(NULL)
45        ,fHandleNotification(NULL)
46        ,fHasRoutingHandler(NULL)
47        ,fRouteMessage(NULL)
48        ,loaded_(false)
49        ,lastIsMsgPlugin_(false)
50        ,broken_(false)
51        ,plugin_id_(id)
52        ,alias_(alias)
53{
54
55}
56/**
57 * Default d-tor
58 */
59NSCPlugin::~NSCPlugin() {
60        if (isLoaded()) {
61                try {
62                        unload_plugin();
63                        unload_dll();
64                } catch (NSPluginException &e) {
65                        // ...
66                }
67        }
68}
69/**
70 * Returns the name of the plug in.
71 *
72 * @return Name of the plug in.
73 *
74 * @throws NSPluginException if the module is not loaded.
75 */
76std::wstring NSCPlugin::getName() {
77        wchar_t *buffer = new wchar_t[1024];
78        if (!getName_(buffer, 1023)) {
79                return _T("Could not get name");
80        }
81        std::wstring ret = buffer;
82        delete [] buffer;
83        return ret;
84}
85std::wstring NSCPlugin::getDescription() {
86        wchar_t *buffer = new wchar_t[4096];
87        if (!getDescription_(buffer, 4095)) {
88                throw NSPluginException(module_, _T("Could not get description"));
89        }
90        std::wstring ret = buffer;
91        delete [] buffer;
92        return ret;
93}
94
95/**
96 * Loads the plug in (DLL) and initializes the plug in by calling NSLoadModule
97 *
98 * @throws NSPluginException when exceptions occur.
99 * Exceptions include but are not limited to: DLL fails to load, DLL is not a correct plug in.
100 */
101void NSCPlugin::load_dll() {
102        if (module_.is_loaded())
103                throw NSPluginException(module_, _T("Module already loaded"));
104        try {
105                module_.load_library();
106        } catch (dll::dll_exception &e) {
107                throw NSPluginException(module_, e.what());
108        }
109        loadRemoteProcs_();
110}
111
112bool NSCPlugin::load_plugin(NSCAPI::moduleLoadMode mode) {
113        if (loaded_)
114                return true;
115        if (!fLoadModule)
116                throw NSPluginException(module_, _T("Critical error (fLoadModule)"));
117        if (fLoadModule(plugin_id_, alias_.c_str(), mode)) {
118                loaded_ = true;
119                return true;
120        }
121        return false;
122}
123
124void NSCPlugin::setBroken(bool broken) {
125        broken_ = broken;
126}
127bool NSCPlugin::isBroken() {
128        return broken_;
129}
130
131
132/**
133 * Get the plug in version.
134 *
135 * @bug Not implemented as of yet
136 *
137 * @param *major
138 * @param *minor
139 * @param *revision
140 * @return False
141 */
142bool NSCPlugin::getVersion(int *major, int *minor, int *revision) {
143        if (!isLoaded())
144                throw NSPluginException(module_, _T("Library is not loaded"));
145        if (!fGetVersion)
146                throw NSPluginException(module_, _T("Critical error (fGetVersion)"));
147        try {
148                return fGetVersion(major, minor, revision)?true:false;
149        } catch (...) {
150                throw NSPluginException(module_, _T("Unhandled exception in getVersion."));
151        }
152}
153/**
154 * Returns true if the plug in has a command handler.
155 * @return true if the plug in has a command handler.
156 * @throws NSPluginException if the module is not loaded.
157 */
158bool NSCPlugin::hasCommandHandler() {
159        if (!isLoaded())
160                throw NSPluginException(module_, _T("Module not loaded"));
161        try {
162                if (fHasCommandHandler(plugin_id_))
163                        return true;
164                return false;
165        } catch (...) {
166                throw NSPluginException(module_, _T("Unhandled exception in hasCommandHandler."));
167        }
168}
169/**
170* Returns true if the plug in has a message (log) handler.
171* @return true if the plug in has a message (log) handler.
172* @throws NSPluginException if the module is not loaded.
173*/
174bool NSCPlugin::hasMessageHandler() {
175        if (!isLoaded())
176                throw NSPluginException(module_, _T("Module not loaded"));
177        try {
178                if (fHasMessageHandler(plugin_id_)) {
179                        lastIsMsgPlugin_ = true;
180                        return true;
181                }
182                return false;
183        } catch (...) {
184                throw NSPluginException(module_, _T("Unhandled exception in hasMessageHandler."));
185        }
186}
187bool NSCPlugin::hasNotificationHandler() {
188        if (!isLoaded())
189                throw NSPluginException(module_, _T("Module not loaded"));
190        if (!fHasNotificationHandler)
191                return false;
192        try {
193                if (fHasNotificationHandler(plugin_id_)) {
194                        return true;
195                }
196                return false;
197        } catch (...) {
198                throw NSPluginException(module_, _T("Unhandled exception in hasMessageHandler."));
199        }
200}
201bool NSCPlugin::has_routing_handler() {
202        if (!isLoaded())
203                throw NSPluginException(module_, _T("Module not loaded"));
204        if (!fHasRoutingHandler)
205                return false;
206        try {
207                if (fHasRoutingHandler(plugin_id_)) {
208                        return true;
209                }
210                return false;
211        } catch (...) {
212                throw NSPluginException(module_, _T("Unhandled exception in hasMessageHandler."));
213        }
214}
215/**
216 * Allow for the plug in to handle a command from the input core.
217 *
218 * Plug ins may refuse to handle the plug in (if not applicable) by returning an empty string.
219 *
220 * @param command The command name (is a string encoded number for legacy commands)
221 * @param argLen The length of the argument buffer.
222 * @param **arguments The arguments for this command
223 * @param returnMessageBuffer Return buffer for plug in to store the result of the executed command.
224 * @param returnMessageBufferLen Size of returnMessageBuffer
225 * @param returnPerfBuffer Return buffer for performance data
226 * @param returnPerfBufferLen Size of returnPerfBuffer
227 * @return Status of execution. Could be error codes, buffer length messages etc.
228 * @throws NSPluginException if the module is not loaded.
229 */
230NSCAPI::nagiosReturn NSCPlugin::handleCommand(const wchar_t* command, const char* dataBuffer, unsigned int dataBuffer_len, char** returnBuffer, unsigned int *returnBuffer_len) {
231        if (!isLoaded())
232                throw NSPluginException(module_, _T("Library is not loaded"));
233        try {
234                return fHandleCommand(plugin_id_, command, dataBuffer, dataBuffer_len, returnBuffer, returnBuffer_len);
235        } catch (...) {
236                throw NSPluginException(module_, _T("Unhandled exception in handleCommand."));
237        }
238}
239NSCAPI::nagiosReturn NSCPlugin::handleCommand(const wchar_t *command, std::string &request, std::string &reply) {
240        char *buffer = NULL;
241        unsigned int len = 0;
242        NSCAPI::nagiosReturn ret = handleCommand(command, request.c_str(), request.size(), &buffer, &len);
243        if (buffer != NULL) {
244                reply = std::string(buffer, len);
245                deleteBuffer(&buffer);
246        }
247        return ret;
248}
249
250NSCAPI::nagiosReturn NSCPlugin::handleNotification(const wchar_t *channel, std::string &request, std::string &reply) {
251        char *buffer = NULL;
252        unsigned int len = 0;
253        NSCAPI::nagiosReturn ret = handleNotification(channel, request.c_str(), request.size(), &buffer, &len);
254        if (buffer != NULL) {
255                reply = std::string(buffer, len);
256                deleteBuffer(&buffer);
257        }
258        return ret;
259}
260
261NSCAPI::nagiosReturn NSCPlugin::handleNotification(const wchar_t *channel, const char* dataBuffer, const unsigned int dataBuffer_len, char** returnBuffer, unsigned int *returnBuffer_len) {
262        if (!isLoaded() || fHandleNotification == NULL)
263                throw NSPluginException(module_, _T("Library is not loaded"));
264        try {
265                return fHandleNotification(plugin_id_, channel, dataBuffer, dataBuffer_len, returnBuffer, returnBuffer_len);
266        } catch (...) {
267                throw NSPluginException(module_, _T("Unhandled exception in handleNotification."));
268        }
269}
270
271bool NSCPlugin::route_message(const wchar_t *channel, const char* buffer, unsigned int buffer_len, wchar_t **new_channel_buffer, char **new_buffer, unsigned int *new_buffer_len) {
272        if (!isLoaded() || fRouteMessage == NULL)
273                throw NSPluginException(module_, _T("Library is not loaded"));
274        try {
275                return fRouteMessage(plugin_id_, channel, buffer, buffer_len, new_channel_buffer, new_buffer, new_buffer_len);
276        } catch (...) {
277                throw NSPluginException(module_, _T("Unhandled exception in route_message."));
278        }
279}
280
281
282void NSCPlugin::deleteBuffer(char** buffer) {
283        if (!isLoaded())
284                throw NSPluginException(module_, _T("Library is not loaded"));
285        try {
286                fDeleteBuffer(buffer);
287        } catch (...) {
288                throw NSPluginException(module_, _T("Unhandled exception in deleteBuffer."));
289        }
290}
291
292/**
293 * Handle a message from the core (or any other (or even potentially self) plug in).
294 * A message may be anything really errors, log messages etc.
295 *
296 * @param msgType Type of message (error, warning, debug, etc.)
297 * @param file The file that generated this message generally __FILE__.
298 * @param line The line in the file that generated the message generally __LINE__
299 * @throws NSPluginException if the module is not loaded.
300 */
301void NSCPlugin::handleMessage(const char* data, unsigned int len) {
302        if (!fHandleMessage)
303                throw NSPluginException(module_, _T("Library is not loaded"));
304        try {
305                fHandleMessage(plugin_id_, data, len);
306        } catch (...) {
307                throw NSPluginException(module_, _T("Unhandled exception in handleMessage."));
308        }
309}
310/**
311 * Unload the plug in
312 * @throws NSPluginException if the module is not loaded and/or cannot be unloaded (plug in remains loaded if so).
313 */
314void NSCPlugin::unload_plugin() {
315        if (!isLoaded())
316                return;
317        loaded_ = false;
318        if (!fUnLoadModule)
319                throw NSPluginException(module_, _T("Critical error (fUnLoadModule)"));
320        try {
321                fUnLoadModule(plugin_id_);
322        } catch (...) {
323                throw NSPluginException(module_, _T("Unhandled exception in fUnLoadModule."));
324        }
325}
326void NSCPlugin::unload_dll() {
327        if (isLoaded())
328                return;
329        module_.unload_library();
330}
331bool NSCPlugin::getName_(wchar_t* buf, unsigned int buflen) {
332        if (fGetName == NULL)
333                return false;//throw NSPluginException(module_, _T("Critical error (fGetName)"));
334        try {
335                return fGetName(buf, buflen)?true:false;
336        } catch (...) {
337                return false; //throw NSPluginException(module_, _T("Unhandled exception in getName."));
338        }
339}
340bool NSCPlugin::getDescription_(wchar_t* buf, unsigned int buflen) {
341        if (fGetDescription == NULL)
342                throw NSPluginException(module_, _T("Critical error (fGetDescription)"));
343        try {
344                return fGetDescription(buf, buflen)?true:false;
345        } catch (...) {
346                throw NSPluginException(module_, _T("Unhandled exception in getDescription."));
347        }
348}
349
350/**
351 * Load all remote function pointers from the loaded module.
352 * These pointers are cached for "speed" which might (?) be dangerous if something changes.
353 * @throws NSPluginException if any of the function pointers fail to load.
354 * If NSPluginException  is thrown the loaded might remain partially loaded and crashes might occur if plug in is used in this state.
355 */
356void NSCPlugin::loadRemoteProcs_(void) {
357
358        try {
359                fLoadModule = (nscapi::plugin_api::lpLoadModule)module_.load_proc("NSLoadModuleEx");
360                if (!fLoadModule)
361                        throw NSPluginException(module_, _T("Could not load NSLoadModuleEx"));
362
363                fModuleHelperInit = (nscapi::plugin_api::lpModuleHelperInit)module_.load_proc("NSModuleHelperInit");
364                if (!fModuleHelperInit)
365                        throw NSPluginException(module_, _T("Could not load NSModuleHelperInit"));
366
367                try {
368                        fModuleHelperInit(get_id(), NSAPILoader);
369                } catch (...) {
370                        throw NSPluginException(module_, _T("Unhandled exception in getDescription."));
371                }
372
373                fGetName = (nscapi::plugin_api::lpGetName)module_.load_proc("NSGetModuleName");
374                if (!fGetName)
375                        throw NSPluginException(module_, _T("Could not load NSGetModuleName"));
376
377                fGetVersion = (nscapi::plugin_api::lpGetVersion)module_.load_proc("NSGetModuleVersion");
378                if (!fGetVersion)
379                        throw NSPluginException(module_, _T("Could not load NSGetModuleVersion"));
380
381                fGetDescription = (nscapi::plugin_api::lpGetDescription)module_.load_proc("NSGetModuleDescription");
382                if (!fGetDescription)
383                        throw NSPluginException(module_, _T("Could not load NSGetModuleDescription"));
384
385                fHasCommandHandler = (nscapi::plugin_api::lpHasCommandHandler)module_.load_proc("NSHasCommandHandler");
386                if (!fHasCommandHandler)
387                        throw NSPluginException(module_, _T("Could not load NSHasCommandHandler"));
388
389                fHasMessageHandler = (nscapi::plugin_api::lpHasMessageHandler)module_.load_proc("NSHasMessageHandler");
390                if (!fHasMessageHandler)
391                        throw NSPluginException(module_, _T("Could not load NSHasMessageHandler"));
392
393                fHandleCommand = (nscapi::plugin_api::lpHandleCommand)module_.load_proc("NSHandleCommand");
394                //if (!fHandleCommand)
395                //      throw NSPluginException(module_, _T("Could not load NSHandleCommand"));
396
397                fDeleteBuffer = (nscapi::plugin_api::lpDeleteBuffer)module_.load_proc("NSDeleteBuffer");
398                if (!fDeleteBuffer)
399                        throw NSPluginException(module_, _T("Could not load NSDeleteBuffer"));
400
401                fHandleMessage = (nscapi::plugin_api::lpHandleMessage)module_.load_proc("NSHandleMessage");
402                if (!fHandleMessage)
403                        throw NSPluginException(module_, _T("Could not load NSHandleMessage"));
404
405                fUnLoadModule = (nscapi::plugin_api::lpUnLoadModule)module_.load_proc("NSUnloadModule");
406                if (!fUnLoadModule)
407                        throw NSPluginException(module_, _T("Could not load NSUnloadModule"));
408
409                fCommandLineExec = (nscapi::plugin_api::lpCommandLineExec)module_.load_proc("NSCommandLineExec");
410                fHandleNotification = (nscapi::plugin_api::lpHandleNotification)module_.load_proc("NSHandleNotification");
411                fHasNotificationHandler = (nscapi::plugin_api::lpHasNotificationHandler)module_.load_proc("NSHasNotificationHandler");
412
413                fHasRoutingHandler = (nscapi::plugin_api::lpHasRoutingHandler)module_.load_proc("NSHasRoutingHandler");
414                fRouteMessage = (nscapi::plugin_api::lpRouteMessage)module_.load_proc("NSRouteMessage");
415
416        } catch (NSPluginException &e) {
417                throw e;
418        } catch (dll::dll_exception &e) {
419                throw NSPluginException(module_, _T("Unhandled exception when loading proces: ") + e.what());
420        } catch (...) {
421                throw NSPluginException(module_, _T("Unhandled exception when loading proces: <UNKNOWN>"));
422        }
423
424}
425
426
427int NSCPlugin::commandLineExec(const wchar_t* command, std::string &request, std::string &reply) {
428        char *buffer = NULL;
429        unsigned int len = 0;
430        NSCAPI::nagiosReturn ret = commandLineExec(command, request.c_str(), request.size(), &buffer, &len);
431        if (buffer != NULL) {
432                reply = std::string(buffer, len);
433                deleteBuffer(&buffer);
434        }
435        return ret;
436}
437
438bool NSCPlugin::has_command_line_exec() {
439        return isLoaded() && fCommandLineExec != NULL;
440}
441
442int NSCPlugin::commandLineExec(const wchar_t* command, const char* request, const unsigned int request_len, char** reply, unsigned int *reply_len) {
443        if (!has_command_line_exec())
444                throw NSPluginException(module_, _T("Library is not loaded or modules does not support command line"));
445        try {
446                return fCommandLineExec(plugin_id_, command, request, request_len, reply, reply_len);
447        } catch (...) {
448                throw NSPluginException(module_, _T("Unhandled exception in handleCommand."));
449        }
450
451}
452boost::filesystem::wpath NSCPlugin::get_filename(boost::filesystem::wpath folder, std::wstring module) {
453        return dll::dll::fix_module_name(folder / module);
454}
455bool NSCPlugin::is_duplicate(boost::filesystem::wpath file, std::wstring alias) {
456        if (alias.empty() && alias_.empty())
457                return module_.get_file() == dll::dll::fix_module_name(file);
458        if (alias.empty() || alias_.empty())
459                return false;
460        return module_.get_file() == dll::dll::fix_module_name(file) && alias == alias_;
461}
Note: See TracBrowser for help on using the repository browser.