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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
|
// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef HOOKS_MANAGER_H
#define HOOKS_MANAGER_H
#include <hooks/server_hooks.h>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>
namespace isc {
namespace hooks {
// Forward declarations
class CalloutHandle;
class CalloutManager;
class LibraryHandle;
class LibraryManagerCollection;
/// @brief Hooks Manager
///
/// This is the overall manager of the hooks framework and is the main class
/// used by a Kea module when handling hooks. It is responsible for the
/// loading and unloading of user libraries, and for calling the callouts on
/// each hook point.
///
/// The class is a singleton, the single instance of the object being accessed
/// through the static getHooksManager() method.
class HooksManager : boost::noncopyable {
public:
/// @brief Get singleton hooks manager
///
/// @return Reference to the singleton hooks manager.
static HooksManager& getHooksManager();
/// @brief Load and reload libraries
///
/// Loads the list of libraries into the server address space. For each
/// library, the "standard" functions (ones with the same names as the
/// hook points) are configured and the libraries' "load" function
/// called.
///
/// If libraries are already loaded, they are unloaded and the new
/// libraries loaded.
///
/// If any library fails to load, an error message will be logged. The
/// remaining libraries will be loaded if possible.
///
/// @param libraries List of libraries to be loaded. The order is
/// important, as it determines the order that callouts on the same
/// hook will be called.
///
/// @return true if all libraries loaded without a problem, false if one or
/// more libraries failed to load. In the latter case, message will
/// be logged that give the reason.
static bool loadLibraries(const std::vector<std::string>& libraries);
/// @brief Unload libraries
///
/// Unloads the loaded libraries and leaves the hooks subsystem in the
/// state it was after construction but before loadLibraries() is called.
///
/// @note: This method should be used with caution - see the notes for
/// the class LibraryManager for pitfalls. In general, a server
/// should not call this method: library unloading will automatically
/// take place when new libraries are loaded, and when appropriate
/// objects are destroyed.
///
/// @return true if all libraries unloaded successfully, false on an error.
/// In the latter case, an error message will have been output.
static void unloadLibraries();
/// @brief Are callouts present?
///
/// Checks loaded libraries and returns true if at lease one callout
/// has been registered by them for the given hook.
///
/// @param index Hooks index for which callouts are checked.
///
/// @return true if callouts are present, false if not.
/// @throw NoSuchHook Given index does not correspond to a valid hook.
static bool calloutsPresent(int index);
/// @brief Calls the callouts for a given hook
///
/// Iterates through the library handles and calls the callouts associated
/// with the given hook index.
///
/// @note This method invalidates the current library index set with
/// setLibraryIndex().
///
/// @param index Index of the hook to call.
/// @param handle Reference to the CalloutHandle object for the current
/// object being processed.
static void callCallouts(int index, CalloutHandle& handle);
/// @brief Return pre-callouts library handle
///
/// Returns a library handle that can be used by the server to register
/// callouts on a hook that are called _before_ any callouts belonging
/// to a library.
///
/// @note Both the reference returned and the callouts registered with
/// this handle only remain valid until the next loadLibraries() or
/// unloadLibraries() call. If the callouts are to remain registered
/// after this time, a new handle will need to be obtained and the
/// callouts re-registered.
///
/// @return Reference to library handle associated with pre-library callout
/// registration.
static LibraryHandle& preCalloutsLibraryHandle();
/// @brief Return post-callouts library handle
///
/// Returns a library handle that can be used by the server to register
/// callouts on a hook that are called _after any callouts belonging
/// to a library.
///
/// @note Both the reference returned and the callouts registered with
/// this handle only remain valid until the next loadLibraries() or
/// unloadLibraries() call. If the callouts are to remain registered
/// after this time, a new handle will need to be obtained and the
/// callouts re-registered.
///
/// @return Reference to library handle associated with post-library callout
/// registration.
static LibraryHandle& postCalloutsLibraryHandle();
/// @brief Return callout handle
///
/// Returns a callout handle to be associated with a request passed round
/// the system.
///
/// @note This handle is valid only after a loadLibraries() call and then
/// only up to the next loadLibraries() call.
///
/// @return Shared pointer to a CalloutHandle object.
static boost::shared_ptr<CalloutHandle> createCalloutHandle();
/// @brief Register Hook
///
/// This is just a convenience shell around the ServerHooks::registerHook()
/// method. It - along with the definitions of the two hook indexes for
/// the context_create and context_destroy methods - means that server
/// authors only need to deal with HooksManager and CalloutHandle, and not
/// include any other hooks framework classes.
///
/// @param name Name of the hook
///
/// @return Index of the hook, to be used in subsequent hook-related calls.
/// This will be greater than or equal to zero (so allowing a
/// negative value to indicate an invalid index).
///
/// @throws DuplicateHook A hook with the same name has already been
/// registered.
static int registerHook(const std::string& name);
/// @brief Return list of loaded libraries
///
/// Returns the names of the loaded libraries.
///
/// @return List of loaded library names.
static std::vector<std::string> getLibraryNames();
/// @brief Validate library list
///
/// For each library passed to it, checks that the library can be opened
/// and that the "version" function is present and gives the right answer.
/// Each library is closed afterwards.
///
/// This is used during the configuration parsing - when the list of hooks
/// libraries is changed, each of the new libraries is checked before the
/// change is committed.
///
/// @param libraries List of libraries to be validated.
///
/// @return An empty vector if all libraries validated. Otherwise it
/// holds the names of the libraries that failed validation.
static std::vector<std::string> validateLibraries(
const std::vector<std::string>& libraries);
/// Index numbers for pre-defined hooks.
static const int CONTEXT_CREATE = ServerHooks::CONTEXT_CREATE;
static const int CONTEXT_DESTROY = ServerHooks::CONTEXT_DESTROY;
private:
/// @brief Constructor
///
/// This is private as the object is a singleton and can only be addressed
/// through the getHooksManager() static method.
HooksManager();
//@{
/// The following methods correspond to similarly-named static methods,
/// but actually do the work on the singleton instance of the HooksManager.
/// See the descriptions of the static methods for more details.
/// @brief Validate library list
///
/// @param List of libraries to be validated.
///
/// @return An empty string if all libraries validated. Otherwise it is
/// the name of the first library that failed validation. The
/// configuration code can return this to bindctl as an indication
/// of the problem.
std::string validateLibrariesInternal(
const std::vector<std::string>& libraries) const;
/// @brief Load and reload libraries
///
/// @param libraries List of libraries to be loaded. The order is
/// important, as it determines the order that callouts on the same
/// hook will be called.
///
/// @return true if all libraries loaded without a problem, false if one or
/// more libraries failed to load. In the latter case, message will
/// be logged that give the reason.
bool loadLibrariesInternal(const std::vector<std::string>& libraries);
/// @brief Unload libraries
void unloadLibrariesInternal();
/// @brief Are callouts present?
///
/// @param index Hooks index for which callouts are checked.
///
/// @return true if callouts are present, false if not.
/// @throw NoSuchHook Given index does not correspond to a valid hook.
bool calloutsPresentInternal(int index);
/// @brief Calls the callouts for a given hook
///
/// @param index Index of the hook to call.
/// @param handle Reference to the CalloutHandle object for the current
/// object being processed.
void callCalloutsInternal(int index, CalloutHandle& handle);
/// @brief Return callout handle
///
/// @return Shared pointer to a CalloutHandle object.
boost::shared_ptr<CalloutHandle> createCalloutHandleInternal();
/// @brief Return pre-callouts library handle
///
/// @return Reference to library handle associated with pre-library callout
/// registration.
LibraryHandle& preCalloutsLibraryHandleInternal();
/// @brief Return post-callouts library handle
///
/// @return Reference to library handle associated with post-library callout
/// registration.
LibraryHandle& postCalloutsLibraryHandleInternal();
/// @brief Return list of loaded libraries
///
/// @return List of loaded library names.
std::vector<std::string> getLibraryNamesInternal() const;
//@}
/// @brief Initialization to No Libraries
///
/// Initializes the hooks manager with an "empty set" of libraries. This
/// method is called if conditionallyInitialize() determines that such
/// initialization is needed.
void performConditionalInitialization();
/// @brief Conditional initialization of the hooks manager
///
/// loadLibraries() performs the initialization of the HooksManager,
/// setting up the internal structures and loading libraries. However,
/// in some cases, server authors may not do that. This method is called
/// whenever any hooks execution function is invoked (checking callouts,
/// calling callouts or returning a callout handle). If the HooksManager
/// is uninitialized, it will initialize it with an "empty set"
/// of libraries.
///
/// For speed, the test of whether initialization is required is done
/// in-line here. The actual initialization is performed in
/// performConditionalInitialization().
void conditionallyInitialize() {
if (!lm_collection_) {
performConditionalInitialization();
}
}
// Members
/// Set of library managers.
boost::shared_ptr<LibraryManagerCollection> lm_collection_;
/// Callout manager for the set of library managers.
boost::shared_ptr<CalloutManager> callout_manager_;
};
} // namespace util
} // namespace hooks
#endif // HOOKS_MANAGER_H
|