Kea 2.7.1
server_hooks.cc
Go to the documentation of this file.
1// Copyright (C) 2013-2024 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
10#include <hooks/hooks_log.h>
11#include <hooks/server_hooks.h>
12
13#include <algorithm>
14#include <utility>
15#include <vector>
16
17using namespace std;
18using namespace isc;
19
20namespace isc {
21namespace hooks {
22
23// Constructor - register the pre-defined hooks and check that the indexes
24// assigned to them are as expected.
25//
26// Note that there are no logging messages here or in registerHooks(). The
27// recommended way to initialize hook names is to use static initialization.
28// Here, a static object is declared in a file outside of any function or
29// method. As a result, it is instantiated and its constructor run before the
30// program starts. By putting calls to ServerHooks::registerHook() in there,
31// hooks names are already registered when the program runs. However, at that
32// point, the logging system is not initialized, so messages are unable to
33// be output.
34
35ServerHooks::ServerHooks() {
36 initialize();
37}
38
39// Register a hook. The index assigned to the hook is the current number
40// of entries in the collection, so ensuring that hook indexes are unique
41// and non-negative.
42
43int
44ServerHooks::registerHook(const string& name) {
45
46 // Determine index for the new element and insert.
47 int index = hooks_.size();
48 pair<HookCollection::iterator, bool> result =
49 hooks_.insert(make_pair(name, index));
50
55
56 if (!result.second) {
57
58 // There's a problem with hook libraries that need to be linked with
59 // libdhcpsrv. For example host_cmds hook library requires host
60 // parser, so it needs to be linked with libdhcpsrv. However, when
61 // unit-tests are started, the hook points are not registered.
62 // When the library is loaded new hook points are registered.
63 // This causes issues in the hooks framework, especially when
64 // LibraryManager::unloadLibrary() iterates through all hooks
65 // and then calls deregisterAllCallouts. This method gets
66 // hook_index that is greater than number of elements in
67 // hook_vector_ and then we have a read past the array boundary.
69 return (getIndex(name));
70
71 // New element was not inserted because an element with the same name
72 // already existed.
73 //isc_throw(DuplicateHook, "hook with name " << name <<
74 // " is already registered");
75 }
76
77 // Element was inserted, so add to the inverse hooks collection.
78 inverse_hooks_[index] = name;
79
80 // ... and return numeric index.
81 return (index);
82}
83
84// Set ServerHooks object to initial state.
85
86void
87ServerHooks::initialize() {
88
89 // Clear out the name->index and index->name maps.
90 hooks_.clear();
91 inverse_hooks_.clear();
92 parking_lots_.reset(new ParkingLots());
93
94 // Register the pre-defined hooks.
95 int create = registerHook("context_create");
96 int destroy = registerHook("context_destroy");
97
98 // Check registration went as expected.
99 if ((create != CONTEXT_CREATE) || (destroy != CONTEXT_DESTROY)) {
100 isc_throw(Unexpected, "pre-defined hook indexes are not as expected. "
101 "context_create: expected = " << CONTEXT_CREATE <<
102 ", actual = " << create <<
103 ". context_destroy: expected = " << CONTEXT_DESTROY <<
104 ", actual = " << destroy);
105 }
106}
107
108// Reset ServerHooks object to initial state.
109
110void
112
113 // Clear all hooks then initialize the pre-defined ones.
114 initialize();
115
116 // Log a warning - although this is done during testing, it should never be
117 // seen in a production system.
119}
120
121// Find the name associated with a hook index.
122
123std::string
124ServerHooks::getName(int index) const {
125
126 // Get iterator to matching element.
127 InverseHookCollection::const_iterator i = inverse_hooks_.find(index);
128 if (i == inverse_hooks_.end()) {
129 isc_throw(NoSuchHook, "hook index " << index << " is not recognized");
130 }
131
132 return (i->second);
133}
134
135// Find the index associated with a hook name.
136
137int
138ServerHooks::getIndex(const string& name) const {
139
140 // Get iterator to matching element.
141 HookCollection::const_iterator i = hooks_.find(name);
142 if (i == hooks_.end()) {
143 isc_throw(NoSuchHook, "hook name " << name << " is not recognized");
144 }
145
146 return (i->second);
147}
148
149int
150ServerHooks::findIndex(const std::string& name) const {
151 // Get iterator to matching element.
152 auto i = hooks_.find(name);
153 return ((i == hooks_.end()) ? -1 : i->second);
154}
155
156// Return vector of hook names. The names are not sorted - it is up to the
157// caller to perform sorting if required.
158
159vector<string>
161 vector<string> names;
162 for (auto const& i : hooks_) {
163 names.push_back(i.first);
164 }
165
166 return (names);
167}
168
169// Return global ServerHooks object
170
175
178 static ServerHooksPtr hooks(new ServerHooks());
179 return (hooks);
180}
181
184 return (parking_lots_);
185}
186
188ServerHooks::getParkingLotPtr(const int hook_index) {
189 return (parking_lots_->getParkingLotPtr(hook_index));
190}
191
193ServerHooks::getParkingLotPtr(const std::string& hook_name) {
194 return (parking_lots_->getParkingLotPtr(getServerHooks().getIndex(hook_name)));
195}
196
197std::string
198ServerHooks::commandToHookName(const std::string& command_name) {
199 // Prefix the command name with a dollar sign.
200 std::string hook_name = std::string("$") + command_name;
201 // Replace all hyphens with underscores.
202 std::replace(hook_name.begin(), hook_name.end(), '-', '_');
203 return (hook_name);
204}
205
206std::string
207ServerHooks::hookToCommandName(const std::string& hook_name) {
208 if (!hook_name.empty() && hook_name.front() == '$') {
209 std::string command_name = hook_name.substr(1);
210 std::replace(command_name.begin(), command_name.end(), '_', '-');
211 return (command_name);
212 }
213 return ("");
214}
215
216} // namespace hooks
217} // namespace isc
A generic exception that is thrown when an unexpected error condition occurs.
Collection of parking lots for various hook points.
Server hook collection.
static ServerHooksPtr getServerHooksPtr()
Returns pointer to ServerHooks object.
ParkingLotPtr getParkingLotPtr(const int hook_index)
Returns pointer to the ParkingLot for the specified hook index.
int getIndex(const std::string &name) const
Get hook index.
static ServerHooks & getServerHooks()
Return ServerHooks object.
static const int CONTEXT_DESTROY
ParkingLotsPtr getParkingLotsPtr() const
Returns pointer to all parking lots.
int findIndex(const std::string &name) const
Find hook index.
void reset()
Reset to Initial State.
static std::string hookToCommandName(const std::string &hook_name)
Returns command name for a specified hook name.
static std::string commandToHookName(const std::string &command_name)
Generates hook point name for the given control command name.
static const int CONTEXT_CREATE
Index numbers for pre-defined hooks.
int registerHook(const std::string &name)
Register a hook.
std::vector< std::string > getHookNames() const
Get hook names.
std::string getName(int index) const
Get hook name.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
boost::shared_ptr< ParkingLots > ParkingLotsPtr
Type of the pointer to the parking lots.
const isc::log::MessageID HOOKS_HOOK_LIST_RESET
boost::shared_ptr< ServerHooks > ServerHooksPtr
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
Definition hooks_log.h:37
boost::shared_ptr< ParkingLot > ParkingLotPtr
Type of the pointer to the parking lot.
Defines the logger used by the top-level component of kea-lfc.