1 // Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <hooks/callout_handle.h>
10 #include <hooks/callout_manager.h>
11 #include <hooks/library_handle.h>
12 #include <hooks/library_manager_collection.h>
13 #include <hooks/hooks_manager.h>
14 #include <hooks/server_hooks.h>
15
16 #include <boost/shared_ptr.hpp>
17 #include <boost/weak_ptr.hpp>
18
19 #include <string>
20 #include <vector>
21
22 using namespace std;
23
24 namespace isc {
25 namespace hooks {
26
27 // Constructor
28
HooksManager()29 HooksManager::HooksManager() : test_mode_(false) {
30 // Nothing present, so create the collection with any empty set of
31 // libraries, and get the CalloutManager.
32 HookLibsCollection libraries;
33 lm_collection_.reset(new LibraryManagerCollection(libraries));
34 lm_collection_->loadLibraries();
35 callout_manager_ = lm_collection_->getCalloutManager();
36 }
37
38 // Return reference to singleton hooks manager.
39
40 HooksManager&
getHooksManager()41 HooksManager::getHooksManager() {
42 static HooksManager manager;
43 return (manager);
44 }
45
46 // Are callouts present?
47
48 bool
calloutsPresentInternal(int index)49 HooksManager::calloutsPresentInternal(int index) {
50 return (callout_manager_->calloutsPresent(index));
51 }
52
53 bool
calloutsPresent(int index)54 HooksManager::calloutsPresent(int index) {
55 return (getHooksManager().calloutsPresentInternal(index));
56 }
57
58 bool
commandHandlersPresentInternal(const std::string & command_name)59 HooksManager::commandHandlersPresentInternal(const std::string& command_name) {
60 return (callout_manager_->commandHandlersPresent(command_name));
61 }
62
63 bool
commandHandlersPresent(const std::string & command_name)64 HooksManager::commandHandlersPresent(const std::string& command_name) {
65 return (getHooksManager().commandHandlersPresentInternal(command_name));
66 }
67
68 // Call the callouts
69
70 void
callCalloutsInternal(int index,CalloutHandle & handle)71 HooksManager::callCalloutsInternal(int index, CalloutHandle& handle) {
72 callout_manager_->callCallouts(index, handle);
73 }
74
75 void
callCallouts(int index,CalloutHandle & handle)76 HooksManager::callCallouts(int index, CalloutHandle& handle) {
77 getHooksManager().callCalloutsInternal(index, handle);
78 }
79
80 void
callCommandHandlersInternal(const std::string & command_name,CalloutHandle & handle)81 HooksManager::callCommandHandlersInternal(const std::string& command_name,
82 CalloutHandle& handle) {
83 callout_manager_->callCommandHandlers(command_name, handle);
84 }
85
86 void
callCommandHandlers(const std::string & command_name,CalloutHandle & handle)87 HooksManager::callCommandHandlers(const std::string& command_name,
88 CalloutHandle& handle) {
89 getHooksManager().callCommandHandlersInternal(command_name, handle);
90 }
91
92 // Load the libraries. This will delete the previously-loaded libraries
93 // (if present) and load new ones. If loading libraries fails, initialize with
94 // empty list.
95
96 bool
loadLibrariesInternal(const HookLibsCollection & libraries)97 HooksManager::loadLibrariesInternal(const HookLibsCollection& libraries) {
98 if (test_mode_) {
99 return (true);
100 }
101
102 ServerHooks::getServerHooks().getParkingLotsPtr()->clear();
103
104 // Keep a weak pointer on the existing library manager collection.
105 boost::weak_ptr<LibraryManagerCollection> weak_lmc(lm_collection_);
106
107 // Create the library manager collection.
108 lm_collection_.reset(new LibraryManagerCollection(libraries));
109
110 // If there was another owner the previous library manager collection
111 // was not destroyed and libraries not closed.
112 if (!weak_lmc.expired()) {
113 isc_throw(LibrariesStillOpened, "some libraries are still opened");
114 }
115
116 // Load the libraries.
117 bool status = lm_collection_->loadLibraries();
118
119 if (status) {
120 // ... and obtain the callout manager for them if successful.
121 callout_manager_ = lm_collection_->getCalloutManager();
122 } else {
123 // Unable to load libraries, reset to state before this function was
124 // called.
125 static_cast<void>(unloadLibrariesInternal());
126 }
127
128 return (status);
129 }
130
131 bool
loadLibraries(const HookLibsCollection & libraries)132 HooksManager::loadLibraries(const HookLibsCollection& libraries) {
133 return (getHooksManager().loadLibrariesInternal(libraries));
134 }
135
136 // Unload the libraries. This just deletes all internal objects (which will
137 // cause the libraries to be unloaded) and initializes them with empty list if
138 // requested.
139
140 bool
unloadLibrariesInternal()141 HooksManager::unloadLibrariesInternal() {
142 if (test_mode_) {
143 return (true);
144 }
145
146 ServerHooks::getServerHooks().getParkingLotsPtr()->clear();
147
148 // Keep a weak pointer on the existing library manager collection.
149 boost::weak_ptr<LibraryManagerCollection> weak_lmc(lm_collection_);
150
151 // Create the collection with any empty set of libraries.
152 HookLibsCollection libraries;
153 lm_collection_.reset(new LibraryManagerCollection(libraries));
154
155 // If there was another owner the previous library manager collection
156 // was not destroyed and libraries not closed.
157 boost::shared_ptr<LibraryManagerCollection> still_here = weak_lmc.lock();
158 if (still_here) {
159 // Restore the library manager collection.
160 lm_collection_ = still_here;
161 return (false);
162 }
163
164 // Load the empty set of libraries.
165 lm_collection_->loadLibraries();
166
167 // Get the CalloutManager.
168 callout_manager_ = lm_collection_->getCalloutManager();
169
170 return (true);
171 }
172
173 bool
unloadLibraries()174 HooksManager::unloadLibraries() {
175 return (getHooksManager().unloadLibrariesInternal());
176 }
177
178 void
prepareUnloadLibrariesInternal()179 HooksManager::prepareUnloadLibrariesInternal() {
180 if (test_mode_) {
181 return;
182 }
183
184 static_cast<void>(lm_collection_->prepareUnloadLibraries());
185 }
186
187 void
prepareUnloadLibraries()188 HooksManager::prepareUnloadLibraries() {
189 getHooksManager().prepareUnloadLibrariesInternal();
190 }
191
192 // Create a callout handle
193
194 boost::shared_ptr<CalloutHandle>
createCalloutHandleInternal()195 HooksManager::createCalloutHandleInternal() {
196 return (boost::make_shared<CalloutHandle>(callout_manager_, lm_collection_));
197 }
198
199 boost::shared_ptr<CalloutHandle>
createCalloutHandle()200 HooksManager::createCalloutHandle() {
201 return (getHooksManager().createCalloutHandleInternal());
202 }
203
204 // Get the list of the names of loaded libraries.
205
206 std::vector<std::string>
getLibraryNamesInternal() const207 HooksManager::getLibraryNamesInternal() const {
208 return (lm_collection_->getLibraryNames());
209 }
210
211 HookLibsCollection
getLibraryInfoInternal() const212 HooksManager::getLibraryInfoInternal() const {
213 return (lm_collection_->getLibraryInfo());
214 }
215
216 std::vector<std::string>
getLibraryNames()217 HooksManager::getLibraryNames() {
218 return (getHooksManager().getLibraryNamesInternal());
219 }
220
221 HookLibsCollection
getLibraryInfo()222 HooksManager::getLibraryInfo() {
223 return (getHooksManager().getLibraryInfoInternal());
224 }
225
226 // Shell around ServerHooks::registerHook()
227
228 int
registerHook(const std::string & name)229 HooksManager::registerHook(const std::string& name) {
230 return (ServerHooks::getServerHooks().registerHook(name));
231 }
232
233 // Return pre- and post- library handles.
234
235 isc::hooks::LibraryHandle&
preCalloutsLibraryHandleInternal()236 HooksManager::preCalloutsLibraryHandleInternal() {
237 return (callout_manager_->getPreLibraryHandle());
238 }
239
240 isc::hooks::LibraryHandle&
preCalloutsLibraryHandle()241 HooksManager::preCalloutsLibraryHandle() {
242 return (getHooksManager().preCalloutsLibraryHandleInternal());
243 }
244
245 isc::hooks::LibraryHandle&
postCalloutsLibraryHandleInternal()246 HooksManager::postCalloutsLibraryHandleInternal() {
247 return (callout_manager_->getPostLibraryHandle());
248 }
249
250 isc::hooks::LibraryHandle&
postCalloutsLibraryHandle()251 HooksManager::postCalloutsLibraryHandle() {
252 return (getHooksManager().postCalloutsLibraryHandleInternal());
253 }
254
255 // Validate libraries
256
257 std::vector<std::string>
validateLibraries(const std::vector<std::string> & libraries)258 HooksManager::validateLibraries(const std::vector<std::string>& libraries) {
259 return (LibraryManagerCollection::validateLibraries(libraries));
260 }
261
262 // Test mode
263
264 void
setTestMode(bool mode)265 HooksManager::setTestMode(bool mode) {
266 getHooksManager().test_mode_ = mode;
267 }
268
269 bool
getTestMode()270 HooksManager::getTestMode() {
271 return (getHooksManager().test_mode_);
272 }
273
274 } // namespace util
275 } // namespace isc
276