Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
d2b10758
Commit
d2b10758
authored
Jun 17, 2013
by
Stephen Morris
Browse files
[master] Merge branch 'trac2974'
parents
a2a6bcce
3c7a0170
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
src/lib/util/Makefile.am
View file @
d2b10758
...
...
@@ -37,6 +37,10 @@ libb10_util_la_SOURCES += encode/base32hex_from_binary.h
libb10_util_la_SOURCES
+=
encode/base_n.cc encode/hex.h
libb10_util_la_SOURCES
+=
encode/binary_from_base32hex.h
libb10_util_la_SOURCES
+=
encode/binary_from_base16.h
libb10_util_la_SOURCES
+=
hooks/callout_manager.h hooks/callout_manager.cc
libb10_util_la_SOURCES
+=
hooks/callout_handle.h hooks/callout_handle.cc
libb10_util_la_SOURCES
+=
hooks/library_handle.h hooks/library_handle.cc
libb10_util_la_SOURCES
+=
hooks/server_hooks.h hooks/server_hooks.cc
libb10_util_la_SOURCES
+=
random/qid_gen.h random/qid_gen.cc
libb10_util_la_SOURCES
+=
random/random_number_generator.h
...
...
src/lib/util/hooks/callout_handle.cc
0 → 100644
View file @
d2b10758
// 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.
#include
<util/hooks/callout_handle.h>
#include
<util/hooks/callout_manager.h>
#include
<util/hooks/library_handle.h>
#include
<util/hooks/server_hooks.h>
#include
<string>
#include
<utility>
#include
<vector>
using
namespace
std
;
using
namespace
isc
::
util
;
namespace
isc
{
namespace
util
{
// Constructor.
CalloutHandle
::
CalloutHandle
(
const
boost
::
shared_ptr
<
CalloutManager
>&
manager
)
:
arguments_
(),
context_collection_
(),
manager_
(
manager
),
skip_
(
false
)
{
// 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.
manager_
->
callCallouts
(
ServerHooks
::
CONTEXT_CREATE
,
*
this
);
}
// 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.
manager_
->
callCallouts
(
ServerHooks
::
CONTEXT_DESTROY
,
*
this
);
}
// Return the name of all argument items.
vector
<
string
>
CalloutHandle
::
getArgumentNames
()
const
{
vector
<
string
>
names
;
for
(
ElementCollection
::
const_iterator
i
=
arguments_
.
begin
();
i
!=
arguments_
.
end
();
++
i
)
{
names
.
push_back
(
i
->
first
);
}
return
(
names
);
}
// Return the library handle allowing the callout to access the CalloutManager
// registration/deregistration functions.
LibraryHandle
&
CalloutHandle
::
getLibraryHandle
()
const
{
return
(
manager_
->
getLibraryHandle
());
}
// 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
()
{
int
libindex
=
manager_
->
getLibraryIndex
();
// 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
// the context for the current library doesn't exist, throw an exception.
const
CalloutHandle
::
ElementCollection
&
CalloutHandle
::
getContextForLibrary
()
const
{
int
libindex
=
manager_
->
getLibraryIndex
();
ContextCollection
::
const_iterator
libcontext
=
context_collection_
.
find
(
libindex
);
if
(
libcontext
==
context_collection_
.
end
())
{
isc_throw
(
NoSuchCalloutContext
,
"unable to find callout context "
"associated with the current library index ("
<<
libindex
<<
")"
);
}
// 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
)
{
names
.
push_back
(
i
->
first
);
}
return
(
names
);
}
}
// namespace util
}
// namespace isc
src/lib/util/hooks/callout_handle.h
0 → 100644
View file @
d2b10758
// 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.
#ifndef CALLOUT_HANDLE_H
#define CALLOUT_HANDLE_H
#include
<exceptions/exceptions.h>
#include
<util/hooks/library_handle.h>
#include
<boost/any.hpp>
#include
<boost/shared_ptr.hpp>
#include
<map>
#include
<string>
#include
<vector>
namespace
isc
{
namespace
util
{
/// @brief No such argument
///
/// Thrown if an attempt is made access an argument that does not exist.
class
NoSuchArgument
:
public
Exception
{
public:
NoSuchArgument
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
/// @brief No such callout context item
///
/// Thrown if an attempt is made to get an item of data from this callout's
/// context and either the context or an item in the context with that name
/// does not exist.
class
NoSuchCalloutContext
:
public
Exception
{
public:
NoSuchCalloutContext
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
// Forward declaration of the library handle and related collection classes.
class
CalloutManager
;
class
LibraryHandle
;
/// @brief Per-packet callout handle
///
/// An object of this class is associated with every packet (or request)
/// processed by the server. It forms the principle means of passing data
/// between the server and the user-library callouts.
///
/// The class allows access to the following information:
///
/// - Arguments. When the callouts associated with a hook are called, they
/// are passed information by the server (and can return information to it)
/// through name/value pairs. Each of these pairs is an argument and the
/// information is accessed through the {get,set}Argument() methods.
///
/// - Per-packet context. Each packet has a context associated with it, this
/// context being on a per-library basis. In other words, As a packet passes
/// through the callouts associated with a given library, the callouts can
/// associate and retrieve information with the packet. The per-library
/// nature of the context means that the callouts within a given library can
/// pass packet-specific information between one another, but they cannot pass
/// information to callous within another library. Typically such context
/// is created in the "context_create" callout and destroyed in the
/// "context_destroy" callout. The information is accessed through the
/// {get,set}Context() methods.
///
/// - Per-library handle. Allows the callout to dynamically register and
/// deregister callouts. (In the latter case, only functions registered by
/// functions in the same library as the callout doing the deregistration
/// can be removed: callouts registered by other libraries cannot be
/// modified.)
class
CalloutHandle
{
public:
/// Typedef to allow abbreviation of iterator specification in methods.
/// The std::string is the argument name and the "boost::any" is the
/// corresponding value associated with it.
typedef
std
::
map
<
std
::
string
,
boost
::
any
>
ElementCollection
;
/// Typedef to allow abbreviations in specifications when accessing
/// context. The ElementCollection is the name/value collection for
/// a particular context. The "int" corresponds to the index of an
/// associated library - there is a 1:1 correspondence between libraries
/// and a name.value collection.
///
/// The collection of contexts is stored in a map, as not every library
/// will require creation of a context associated with each packet. In
/// addition, the structure is more flexible in that the size does not
/// need to be set when the CalloutHandle is constructed.
typedef
std
::
map
<
int
,
ElementCollection
>
ContextCollection
;
/// @brief Constructor
///
/// Creates the object and calls the callouts on the "context_create"
/// hook.
///
/// @param manager Pointer to the callout manager object.
CalloutHandle
(
const
boost
::
shared_ptr
<
CalloutManager
>&
manager
);
/// @brief Destructor
///
/// Calls the context_destroy callback to release any per-packet context.
~
CalloutHandle
();
/// @brief Set argument
///
/// Sets the value of an argument. The argument is created if it does not
/// already exist.
///
/// @param name Name of the argument.
/// @param value Value to set. That can be of any data type.
template
<
typename
T
>
void
setArgument
(
const
std
::
string
&
name
,
T
value
)
{
arguments_
[
name
]
=
value
;
}
/// @brief Get argument
///
/// Gets the value of an argument.
///
/// @param name Name of the element in the argument list to get.
/// @param value [out] Value to set. The type of "value" is important:
/// it must match the type of the value set.
///
/// @throw NoSuchArgument No argument with the given name is present.
/// @throw boost::bad_any_cast An argument with the given name is present,
/// but the data type of the value is not the same as the type of
/// the variable provided to receive the value.
template
<
typename
T
>
void
getArgument
(
const
std
::
string
&
name
,
T
&
value
)
const
{
ElementCollection
::
const_iterator
element_ptr
=
arguments_
.
find
(
name
);
if
(
element_ptr
==
arguments_
.
end
())
{
isc_throw
(
NoSuchArgument
,
"unable to find argument with name "
<<
name
);
}
value
=
boost
::
any_cast
<
T
>
(
element_ptr
->
second
);
}
/// @brief Get argument names
///
/// Returns a vector holding the names of arguments in the argument
/// vector.
///
/// @return Vector of strings reflecting argument names.
std
::
vector
<
std
::
string
>
getArgumentNames
()
const
;
/// @brief Delete argument
///
/// Deletes an argument of the given name. If an argument of that name
/// does not exist, the method is a no-op.
///
/// N.B. If the element is a raw pointer, the pointed-to data is NOT deleted
/// by this method.
///
/// @param name Name of the element in the argument list to set.
void
deleteArgument
(
const
std
::
string
&
name
)
{
static_cast
<
void
>
(
arguments_
.
erase
(
name
));
}
/// @brief Delete all arguments
///
/// Deletes all arguments associated with this context.
///
/// N.B. If any elements are raw pointers, the pointed-to data is NOT
/// deleted by this method.
void
deleteAllArguments
()
{
arguments_
.
clear
();
}
/// @brief Set skip flag
///
/// Sets the "skip" variable in the callout handle. This variable is
/// interrogated by the server to see if the remaining callouts associated
/// with the current hook should be bypassed.
///
/// @param skip New value of the "skip" flag.
void
setSkip
(
bool
skip
)
{
skip_
=
skip
;
}
/// @brief Get skip flag
///
/// Gets the current value of the "skip" flag.
///
/// @return Current value of the skip flag.
bool
getSkip
()
const
{
return
(
skip_
);
}
/// @brief Access current library handle
///
/// Returns a reference to the current library handle. This function is
/// only available when called by a callout (which in turn is called
/// through the "callCallouts" method), as it is only then that the current
/// library index is valid. A callout uses the library handle to
/// dynamically register or deregister callouts.
///
/// @return Reference to the library handle.
///
/// @throw InvalidIndex thrown if this method is called when the current
/// library index is invalid (typically if it is called outside of
/// the active callout).
LibraryHandle
&
getLibraryHandle
()
const
;
/// @brief Set context
///
/// Sets an element in the context associated with the current library. If
/// an element of the name is already present, it is replaced.
///
/// @param name Name of the element in the context to set.
/// @param value Value to set.
template
<
typename
T
>
void
setContext
(
const
std
::
string
&
name
,
T
value
)
{
getContextForLibrary
()[
name
]
=
value
;
}
/// @brief Get context
///
/// Gets an element from the context associated with the current library.
///
/// @param name Name of the element in the context to get.
/// @param value [out] Value to set. The type of "value" is important:
/// it must match the type of the value set.
///
/// @throw NoSuchCalloutContext Thrown if no context element with the name
/// "name" is present.
/// @throw boost::bad_any_cast Thrown if the context element is present
/// but the type of the data is not the same as the type of the
/// variable provided to receive its value.
template
<
typename
T
>
void
getContext
(
const
std
::
string
&
name
,
T
&
value
)
const
{
const
ElementCollection
&
lib_context
=
getContextForLibrary
();
ElementCollection
::
const_iterator
element_ptr
=
lib_context
.
find
(
name
);
if
(
element_ptr
==
lib_context
.
end
())
{
isc_throw
(
NoSuchCalloutContext
,
"unable to find callout context "
"item "
<<
name
<<
" in the context associated with "
"current library"
);
}
value
=
boost
::
any_cast
<
T
>
(
element_ptr
->
second
);
}
/// @brief Get context names
///
/// Returns a vector holding the names of items in the context associated
/// with the current library.
///
/// @return Vector of strings reflecting the names of items in the callout
/// context associated with the current library.
std
::
vector
<
std
::
string
>
getContextNames
()
const
;
/// @brief Delete context element
///
/// Deletes an item of the given name from the context associated with the
/// current library. If an item of that name does not exist, the method is
/// a no-op.
///
/// N.B. If the element is a raw pointer, the pointed-to data is NOT deleted
/// by this.
///
/// @param name Name of the context item to delete.
void
deleteContext
(
const
std
::
string
&
name
)
{
static_cast
<
void
>
(
getContextForLibrary
().
erase
(
name
));
}
/// @brief Delete all context items
///
/// Deletes all items from the context associated with the current library.
///
/// N.B. If any elements are raw pointers, the pointed-to data is NOT
/// deleted by this.
void
deleteAllContext
()
{
getContextForLibrary
().
clear
();
}
private:
/// @brief Check index
///
/// Gets the current library index, throwing an exception if it is not set
/// or is invalid for the current library collection.
///
/// @return Current library index, valid for this library collection.
///
/// @throw InvalidIndex current library index is not valid for the library
/// handle collection.
int
getLibraryIndex
()
const
;
/// @brief Return reference to context for current library
///
/// Called by all context-setting functions, this returns a reference to
/// the callout context for the current library, creating a context if it
/// does not exist.
///
/// @return Reference to the collection of name/value pairs associated
/// with the current library.
///
/// @throw InvalidIndex current library index is not valid for the library
/// handle collection.
ElementCollection
&
getContextForLibrary
();
/// @brief Return reference to context for current library (const version)
///
/// Called by all context-accessing functions, this a reference to the
/// callout context for the current library. An exception is thrown if
/// it does not exist.
///
/// @return Reference to the collection of name/value pairs associated
/// with the current library.
///
/// @throw NoSuchCalloutContext Thrown if there is no ElementCollection
/// associated with the current library.
const
ElementCollection
&
getContextForLibrary
()
const
;
// Member variables
/// Collection of arguments passed to the callouts
ElementCollection
arguments_
;
/// Context collection - there is one entry per library context.
ContextCollection
context_collection_
;
/// Callout manager.
boost
::
shared_ptr
<
CalloutManager
>
manager_
;
/// "Skip" flag, indicating if the caller should bypass remaining callouts.
bool
skip_
;
};
}
// namespace util
}
// namespace isc
#endif // CALLOUT_HANDLE_H
src/lib/util/hooks/callout_manager.cc
0 → 100644
View file @
d2b10758
// 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.
#include
<util/hooks/callout_handle.h>
#include
<util/hooks/callout_manager.h>
#include
<boost/static_assert.hpp>
#include
<algorithm>
#include
<functional>
#include
<utility>
using
namespace
std
;
using
namespace
isc
::
util
;
namespace
isc
{
namespace
util
{
// Register a callout for the current library.
void
CalloutManager
::
registerCallout
(
const
std
::
string
&
name
,
CalloutPtr
callout
)
{
// Sanity check that the current library index is set to a valid value.
checkLibraryIndex
(
current_library_
);
// Get the index associated with this hook (validating the name in the
// process).
int
hook_index
=
hooks_
->
getIndex
(
name
);
// Iterate through the callout vector for the hook from start to end,
// looking for the first entry where the library index is greater than
// the present index.
for
(
CalloutVector
::
iterator
i
=
hook_vector_
[
hook_index
].
begin
();
i
!=
hook_vector_
[
hook_index
].
end
();
++
i
)
{
if
(
i
->
first
>
current_library_
)
{
// Found an element whose library index number is greater than the
// current index, so insert the new element ahead of this one.
hook_vector_
[
hook_index
].
insert
(
i
,
make_pair
(
current_library_
,
callout
));
return
;
}
}
// Reached the end of the vector, so there is no element in the (possibly
// empty) set of callouts with a library index greater than the current
// library index. Inset the callout at the end of the list.
hook_vector_
[
hook_index
].
push_back
(
make_pair
(
current_library_
,
callout
));
}
// Check if callouts are present for a given hook index.
bool
CalloutManager
::
calloutsPresent
(
int
hook_index
)
const
{
// Validate the hook index.
if
((
hook_index
<
0
)
||
(
hook_index
>=
hook_vector_
.
size
()))
{
isc_throw
(
NoSuchHook
,
"hook index "
<<
hook_index
<<
" is not valid for the list of registered hooks"
);
}
// Valid, so are there any callouts associated with that hook?
return
(
!
hook_vector_
[
hook_index
].
empty
());
}
// Call all the callouts for a given hook.
void
CalloutManager
::
callCallouts
(
int
hook_index
,
CalloutHandle
&
callout_handle
)
{
// Only initialize and iterate if there are callouts present. This check
// also catches the case of an invalid index.
if
(
calloutsPresent
(
hook_index
))
{
// Clear the "skip" flag so we don't carry state from a previous call.
callout_handle
.
setSkip
(
false
);
// Duplicate the callout vector for this hook and work through that.
// This step is needed because we allow dynamic registration and
// deregistration of callouts. If a callout attached to a hook modified
// the list of callouts on that hook, the underlying CalloutVector would
// change and potentially affect the iteration through that vector.
CalloutVector
callouts
(
hook_vector_
[
hook_index
]);
// Call all the callouts.
for
(
CalloutVector
::
const_iterator
i
=
callouts
.
begin
();
i
!=
callouts
.
end
();
++
i
)
{
// In case the callout tries to register or deregister a callout,
// set the current library index to the index associated with the
// library that registered the callout being called.
current_library_
=
i
->
first
;
// Call the callout
// @todo Log the return status if non-zero
static_cast
<
void
>
((
*
i
->
second
)(
callout_handle
));
}
// Reset the current library index to an invalid value to catch any
// programming errors.
current_library_
=
-
1
;
}
}
// Deregister a callout registered by the current library on a particular hook.
bool
CalloutManager
::
deregisterCallout
(
const
std
::
string
&
name
,
CalloutPtr
callout
)
{
// Sanity check that the current library index is set to a valid value.
checkLibraryIndex
(
current_library_
);
// Get the index associated with this hook (validating the name in the
// process).
int
hook_index
=
hooks_
->
getIndex
(
name
);
/// Construct a CalloutEntry matching the current library and the callout
/// we want to remove.
CalloutEntry
target
(
current_library_
,
callout
);
/// To decide if any entries were removed, we'll record the initial size
/// of the callout vector for the hook, and compare it with the size after
/// the removal.
size_t
initial_size
=
hook_vector_
[
hook_index
].
size
();
// The next bit is standard STL (see "Item 33" in "Effective STL" by
// Scott Meyers).