callout_handle.cc 5.58 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

15
16
17
18
#include <hooks/callout_handle.h>
#include <hooks/callout_manager.h>
#include <hooks/library_handle.h>
#include <hooks/server_hooks.h>
19
20

#include <string>
21
#include <utility>
22
23
24
25
26
#include <vector>

using namespace std;

namespace isc {
27
namespace hooks {
28

29
// Constructor.
30
31
32
33
CalloutHandle::CalloutHandle(const boost::shared_ptr<CalloutManager>& manager,
                    const boost::shared_ptr<LibraryManagerCollection>& lmcoll)
    : lm_collection_(lmcoll), arguments_(), context_collection_(),
      manager_(manager), skip_(false) {
34
35
36
37

    // Call the "context_create" hook.  We should be OK doing this - although
    // the constructor has not finished running, all the member variables
    // have been created.
38
    manager_->callCallouts(ServerHooks::CONTEXT_CREATE, *this);
39
40
41
42
43
44
45
46
}

// Destructor
CalloutHandle::~CalloutHandle() {

    // Call the "context_destroy" hook.  We should be OK doing this - although
    // the destructor is being called, all the member variables are still in
    // existence.
47
    manager_->callCallouts(ServerHooks::CONTEXT_DESTROY, *this);
48
49
50
51
52
53
54

    // Explicitly clear the argument and context objects.  This should free up
    // all memory that could have been allocated by libraries that were loaded.
    arguments_.clear();
    context_collection_.clear();

    // Normal destruction of the remaining variables will include the
55
56
57
58
59
60
    // destruction of lm_collection_, an action that decrements the reference
    // count on the library manager collection (which holds the libraries that
    // could have allocated memory in the argument and context members.)  When
    // that goes to zero, the libraries will be unloaded: at that point nothing
    // in the hooks framework will be pointing to memory in the libraries'
    // address space.
61
62
63
64
65
    //
    // It is possible that some other data structure in the server (the program
    // using the hooks library) still references the address space and attempts
    // to access it causing a segmentation fault. That issue is outside the
    // scope of this framework and is not addressed by it.
66
67
}

68
// Return the name of all argument items.
69
70
71
72
73

vector<string>
CalloutHandle::getArgumentNames() const {

    vector<string> names;
74
75
76
77
78
79
80
81
    for (ElementCollection::const_iterator i = arguments_.begin();
         i != arguments_.end(); ++i) {
        names.push_back(i->first);
    }

    return (names);
}

82
83
// Return the library handle allowing the callout to access the CalloutManager
// registration/deregistration functions.
84
85
86

LibraryHandle&
CalloutHandle::getLibraryHandle() const {
87
    return (manager_->getLibraryHandle());
88
89
90
91
92
93
94
95
}

// Return the context for the currently pointed-to library.  This version is
// used by the "setContext()" method and creates a context for the current
// library if it does not exist.

CalloutHandle::ElementCollection&
CalloutHandle::getContextForLibrary() {
96
    int libindex = manager_->getLibraryIndex();
97
98
99
100
101
102
103

    // Access a reference to the element collection for the given index,
    // creating a new element collection if necessary, and return it.
    return (context_collection_[libindex]);
}

// The "const" version of the above, used by the "getContext()" method.  If
104
// the context for the current library doesn't exist, throw an exception.
105
106
107

const CalloutHandle::ElementCollection&
CalloutHandle::getContextForLibrary() const {
108
    int libindex = manager_->getLibraryIndex();
109

110
111
112
113
    ContextCollection::const_iterator libcontext =
        context_collection_.find(libindex);
    if (libcontext == context_collection_.end()) {
        isc_throw(NoSuchCalloutContext, "unable to find callout context "
114
115
                  "associated with the current library index (" << libindex <<
                  ")");
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    }

    // Return a reference to the context's element collection.
    return (libcontext->second);
}

// Return the name of all items in the context associated with the current]
// library.

vector<string>
CalloutHandle::getContextNames() const {

    vector<string> names;

    const ElementCollection& elements = getContextForLibrary();
    for (ElementCollection::const_iterator i = elements.begin();
         i != elements.end(); ++i) {
133
134
135
136
137
138
        names.push_back(i->first);
    }

    return (names);
}

Stephen Morris's avatar
Stephen Morris committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Return name of current hook (the hook to which the current callout is
// attached) or the empty string if not called within the context of a
// callout.

string
CalloutHandle::getHookName() const {
    // Get the current hook index.
    int index = manager_->getHookIndex();

    // ... and look up the hook.
    string hook = "";
    try {
        hook = ServerHooks::getServerHooks().getName(index);
    } catch (const NoSuchHook&) {
Stephen Morris's avatar
Stephen Morris committed
153
154
155
        // Hook index is invalid, so this methods probably called from outside
        // a callout being executed via a call to CalloutManager::callCallouts.
        // In this case, the empty string is returned.
Stephen Morris's avatar
Stephen Morris committed
156
157
158
159
160
    }

    return (hook);
}

161
162
} // namespace util
} // namespace isc