server_hooks.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (C) 2013-2017 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. #include <exceptions/exceptions.h>
  7. #include <hooks/hooks_log.h>
  8. #include <hooks/server_hooks.h>
  9. #include <utility>
  10. #include <vector>
  11. using namespace std;
  12. using namespace isc;
  13. namespace isc {
  14. namespace hooks {
  15. // Constructor - register the pre-defined hooks and check that the indexes
  16. // assigned to them are as expected.
  17. //
  18. // Note that there are no logging messages here or in registerHooks(). The
  19. // recommended way to initialize hook names is to use static initialization.
  20. // Here, a static object is declared in a file outside of any function or
  21. // method. As a result, it is instantiated and its constructor run before the
  22. // program starts. By putting calls to ServerHooks::registerHook() in there,
  23. // hooks names are already registered when the program runs. However, at that
  24. // point, the logging system is not initialized, so messages are unable to
  25. // be output.
  26. ServerHooks::ServerHooks() {
  27. initialize();
  28. }
  29. // Register a hook. The index assigned to the hook is the current number
  30. // of entries in the collection, so ensuring that hook indexes are unique
  31. // and non-negative.
  32. int
  33. ServerHooks::registerHook(const string& name) {
  34. // Determine index for the new element and insert.
  35. int index = hooks_.size();
  36. pair<HookCollection::iterator, bool> result =
  37. hooks_.insert(make_pair(name, index));
  38. if (!result.second) {
  39. // There's a problem with hook libraries that need to be linked with
  40. // libdhcpsrv. For example host_cmds hook library requires host
  41. // parser, so it needs to be linked with libdhcpsrv. However, when
  42. // unit-tests are started, the hook points are not registered.
  43. // When the library is loaded new hook points are registered.
  44. // This causes issues in the hooks framework, especially when
  45. // LibraryManager::unloadLibrary() iterates through all hooks
  46. // and then calls deregisterAllCallouts. This method gets
  47. // hook_index that is greater than number of elements in
  48. // hook_vector_ and then we have a read past the array boundary.
  49. /// @todo: See ticket 5251 and 5208 for details.
  50. return (getIndex(name));
  51. // New element was not inserted because an element with the same name
  52. // already existed.
  53. //isc_throw(DuplicateHook, "hook with name " << name <<
  54. // " is already registered");
  55. }
  56. // Element was inserted, so add to the inverse hooks collection.
  57. inverse_hooks_[index] = name;
  58. // ... and return numeric index.
  59. return (index);
  60. }
  61. // Set ServerHooks object to initial state.
  62. void
  63. ServerHooks::initialize() {
  64. // Clear out the name->index and index->name maps.
  65. hooks_.clear();
  66. inverse_hooks_.clear();
  67. // Register the pre-defined hooks.
  68. int create = registerHook("context_create");
  69. int destroy = registerHook("context_destroy");
  70. // Check registration went as expected.
  71. if ((create != CONTEXT_CREATE) || (destroy != CONTEXT_DESTROY)) {
  72. isc_throw(Unexpected, "pre-defined hook indexes are not as expected. "
  73. "context_create: expected = " << CONTEXT_CREATE <<
  74. ", actual = " << create <<
  75. ". context_destroy: expected = " << CONTEXT_DESTROY <<
  76. ", actual = " << destroy);
  77. }
  78. }
  79. // Reset ServerHooks object to initial state.
  80. void
  81. ServerHooks::reset() {
  82. // Clear all hooks then initialize the pre-defined ones.
  83. initialize();
  84. // Log a warning - although this is done during testing, it should never be
  85. // seen in a production system.
  86. LOG_WARN(hooks_logger, HOOKS_HOOK_LIST_RESET);
  87. }
  88. // Find the name associated with a hook index.
  89. std::string
  90. ServerHooks::getName(int index) const {
  91. // Get iterator to matching element.
  92. InverseHookCollection::const_iterator i = inverse_hooks_.find(index);
  93. if (i == inverse_hooks_.end()) {
  94. isc_throw(NoSuchHook, "hook index " << index << " is not recognized");
  95. }
  96. return (i->second);
  97. }
  98. // Find the index associated with a hook name.
  99. int
  100. ServerHooks::getIndex(const string& name) const {
  101. // Get iterator to matching element.
  102. HookCollection::const_iterator i = hooks_.find(name);
  103. if (i == hooks_.end()) {
  104. isc_throw(NoSuchHook, "hook name " << name << " is not recognized");
  105. }
  106. return (i->second);
  107. }
  108. // Return vector of hook names. The names are not sorted - it is up to the
  109. // caller to perform sorting if required.
  110. vector<string>
  111. ServerHooks::getHookNames() const {
  112. vector<string> names;
  113. HookCollection::const_iterator i;
  114. for (i = hooks_.begin(); i != hooks_.end(); ++i) {
  115. names.push_back(i->first);
  116. }
  117. return (names);
  118. }
  119. // Return global ServerHooks object
  120. ServerHooks&
  121. ServerHooks::getServerHooks() {
  122. return (*getServerHooksPtr());
  123. }
  124. ServerHooksPtr
  125. ServerHooks::getServerHooksPtr() {
  126. static ServerHooksPtr hooks(new ServerHooks());
  127. return (hooks);
  128. }
  129. } // namespace util
  130. } // namespace isc