Kea  2.1.6-git
server_hooks.cc
Go to the documentation of this file.
1 // Copyright (C) 2013-2018 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 
17 using namespace std;
18 using namespace isc;
19 
20 namespace isc {
21 namespace 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 
35 ServerHooks::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 
43 int
44 ServerHooks::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 
86 void
87 ServerHooks::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 
110 void
111 ServerHooks::reset() {
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 
123 std::string
124 ServerHooks::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 
137 int
138 ServerHooks::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 
149 int
150 ServerHooks::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 
159 vector<string>
160 ServerHooks::getHookNames() const {
161 
162  vector<string> names;
163  HookCollection::const_iterator i;
164  for (i = hooks_.begin(); i != hooks_.end(); ++i) {
165  names.push_back(i->first);
166  }
167 
168  return (names);
169 }
170 
171 // Return global ServerHooks object
172 
174 ServerHooks::getServerHooks() {
175  return (*getServerHooksPtr());
176 }
177 
179 ServerHooks::getServerHooksPtr() {
180  static ServerHooksPtr hooks(new ServerHooks());
181  return (hooks);
182 }
183 
185 ServerHooks::getParkingLotsPtr() const {
186  return (parking_lots_);
187 }
188 
190 ServerHooks::getParkingLotPtr(const int hook_index) {
191  return (parking_lots_->getParkingLotPtr(hook_index));
192 }
193 
195 ServerHooks::getParkingLotPtr(const std::string& hook_name) {
196  return (parking_lots_->getParkingLotPtr(getServerHooks().getIndex(hook_name)));
197 }
198 
199 std::string
200 ServerHooks::commandToHookName(const std::string& command_name) {
201  // Prefix the command name with a dollar sign.
202  std::string hook_name = std::string("$") + command_name;
203  // Replace all hyphens with underscores.
204  std::replace(hook_name.begin(), hook_name.end(), '-', '_');
205  return (hook_name);
206 }
207 
208 std::string
209 ServerHooks::hookToCommandName(const std::string& hook_name) {
210  if (!hook_name.empty() && hook_name.front() == '$') {
211  std::string command_name = hook_name.substr(1);
212  std::replace(command_name.begin(), command_name.end(), '_', '-');
213  return (command_name);
214  }
215  return ("");
216 }
217 
218 
219 
220 } // namespace hooks
221 } // namespace isc
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
boost::shared_ptr< ParkingLot > ParkingLotPtr
Type of the pointer to the parking lot.
Definition: parking_lots.h:294
STL namespace.
boost::shared_ptr< ServerHooks > ServerHooksPtr
Definition: server_hooks.h:42
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Collection of parking lots for various hook points.
Definition: parking_lots.h:384
const isc::log::MessageID HOOKS_HOOK_LIST_RESET
A generic exception that is thrown when an unexpected error condition occurs.
boost::shared_ptr< ParkingLots > ParkingLotsPtr
Type of the pointer to the parking lots.
Definition: parking_lots.h:421
Defines the logger used by the top-level component of kea-lfc.
Invalid hook.
Definition: server_hooks.h:36
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
Definition: hooks_log.h:37
Server hook collection.
Definition: server_hooks.h:62