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
// Copyright (C) 2013-2024 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/.

#include <config.h>

#include <hooks/callout_manager.h>
#include <hooks/hooks_manager.h>
#include <hooks/library_manager.h>
#include <hooks/library_manager_collection.h>
#include <boost/range/adaptor/reversed.hpp><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace isc {
namespace hooks {

// Return callout manager for the loaded libraries.  This call is only valid
// after one has been created for the loaded libraries (which includes the
// case of no loaded libraries).
//
// Note that there is no real connection between the callout manager and the
// libraries, other than it knows the number of libraries so can do sanity
// checks on values passed to it.  However, this may change in the future,
// so the hooks framework is written such that a callout manager is used only
// with the LibraryManagerCollection that created it.  It is also the reason
// why each LibraryManager contains a pointer to this CalloutManager.

boost::shared_ptr<CalloutManager>
LibraryManagerCollection::getCalloutManager() const {

    // Only return a pointer if we have a CalloutManager created.
    if (!callout_manager_) {
        isc_throw(LoadLibrariesNotCalled, "must load hooks libraries before "
                  "attempting to retrieve a CalloutManager for them");
    }

    return (callout_manager_);
}

LibraryManagerCollection::LibraryManagerCollection(const HookLibsCollection& libraries)
    : library_info_(libraries) {

    // We need to split hook libs into library names and library parameters.
    for (auto const& it : libraries) {
        library_names_.push_back(it.first);<--- Consider using std::transform algorithm instead of a raw loop.
    }
}

// Load a set of libraries

bool
LibraryManagerCollection::loadLibraries(bool multi_threading_enabled) {

    // There must be no libraries still in memory.
    if (!lib_managers_.empty()) {
        isc_throw(LibrariesStillOpened, "some libraries are still opened");
    }

    // Access the callout manager, (re)creating it if required.
    //
    // A pointer to the callout manager is maintained by each as well as by
    // the HooksManager itself.  Note that the callout manager does not hold any
    // memory allocated by a library: although a library registers a callout
    // (and so causes the creation of an entry in the CalloutManager's callout
    // list), that creation is done by the CalloutManager itself.  The
    // CalloutManager is created within the server. The upshot of this is that
    // it is therefore safe for the CalloutManager to be deleted after all
    // associated libraries are deleted, hence this link (LibraryManager ->
    // CalloutManager) is safe.
    //
    // The call of this function will result in re-creating the callout manager.
    // This deletes all callouts (including the pre-library and post-
    // library) ones.  It is up to the libraries to re-register their callouts.
    // The pre-library and post-library callouts will also need to be
    // re-registered.
    callout_manager_.reset(new CalloutManager(library_names_.size()));

    // Now iterate through the libraries are load them one by one.  We'll
    for (size_t i = 0; i < library_names_.size(); ++i) {
        // Create a pointer to the new library manager.  The index of this
        // library is determined by the number of library managers currently
        // loaded: note that the library indexes run from 1 to (number of loaded
        // libraries).
        boost::shared_ptr<LibraryManager> manager(
                new LibraryManager(library_names_[i], lib_managers_.size() + 1,
                                   callout_manager_));

        // Load the library.  On success, add it to the list of loaded
        // libraries.  On failure, unload all currently loaded libraries,
        // leaving the object in the state it was in before loadLibraries was
        // called.
        if (manager->loadLibrary(multi_threading_enabled)) {
            lib_managers_.push_back(manager);
        } else {
            static_cast<void>(unloadLibraries());
            return (false);
        }
    }

    return (true);
}

// Unload the libraries.

void
LibraryManagerCollection::unloadLibraries() {

    // Delete the library managers in the reverse order to which they were
    // created, then clear the library manager vector.
    while (!lib_managers_.empty()) {
        lib_managers_.pop_back();
    }

    // Get rid of the callout manager. (The other member, the list of library
    // names, was cleared when the libraries were loaded.)
    callout_manager_.reset();
}

// Prepare the unloading of libraries.
bool
LibraryManagerCollection::prepareUnloadLibraries() {
    bool result = true;
    // Iterate on library managers in reverse order.
    for (auto const& lm : boost::adaptors::reverse(lib_managers_)) {
        result = lm->prepareUnloadLibrary() && result;
    }
    return (result);
}

// Return number of loaded libraries.
int
LibraryManagerCollection::getLoadedLibraryCount() const {
    return (lib_managers_.size());
}

// Validate the libraries.
std::vector<std::string>
LibraryManagerCollection::validateLibraries(const std::vector<std::string>& libraries,
                                            bool multi_threading_enabled) {

    std::vector<std::string> failures;
    for (size_t i = 0; i < libraries.size(); ++i) {
        if (!LibraryManager::validateLibrary(libraries[i], multi_threading_enabled)) {
            failures.push_back(libraries[i]);
        }
    }

    return (failures);
}

} // namespace hooks
} // namespace isc