Commit 80d16e0d authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

Merge branch 'master' into trac2956. 2956 was created before 2955, but

needs 2955 (which is now complete) to finish.
parents fd911f47 dbe47722
621. [func] team
libdns++: All Rdata classes now use the generic lexer in
constructors from text. This means that the name fields in such
RRs in a zone file can now be non-absolute (the origin name in that
context will be used), e.g., when loaded by b10-loadzone. Note
that the existing string constructors for these Rdata classes also
use the generic lexer, and they now expect an absolute name (with
the trailing '.') in the name fields.
(Trac #2522, git ea97070cf6b41299351fc29af66fa39c6465d56a)
(Trac #2521, git c6603decaadcd33ccf9aee4a7b22447acec4b7f6)
(See also ChangeLog 594, 564, 545)
620. [bug] jinmei
b10-auth now returns SERVFAIL to queries for a zone that is
configured to be loaded in-memory but isn't due to load time
errors (missing zone file or errors in the zone file, etc).
Such zones were previously treated as non existent and would
result in REFUSED or unintentional match against less specific
zones. The revised behavior is also compatible with BIND 9.
(Trac #2905, git 56ee9810fdfb5f86bd6948e6bf26545ac714edd8)
619. [bug] jinmei
b10-xfrout now uses blocking send for xfr response messages
to prevent abrupt termination of the stream due to a slower
client or narrower network bandwidth.
(Trac #2934, git bde0e94518469557c8b455ccbecc079a38382afd)
618. [func]* marcin
b10-dhcp4: Added the ability for the server to respond to a
directly connected client which does not yet have an IP address.
On Linux, the server will unicast the response to the client's
hardware address and the 'yiaddr' (the client's new IP
address). Sending a response to the unicast address prevents other
(not interested) hosts from receiving the server response. This
capability is not yet implemented on non-Linux Operating Systems
where, in all cases, the server responds to the broadcast
address. The logic conforms to section 4.1 of RFC 2131.
(Trac #2902, git c2d40e3d425f1e51647be6a717c4a97d7ca3c29c)
617. [bug] marcin
b10-dhcp4: Fixed a bug whereby the domain-name option was encoded
as FQDN (using technique described in RFC1035) instead of a string.
Also, created new class which represents an option carrying a single
string value. This class is now used for all standard options of
this kind.
(Trac #2786, git 96b1a7eb31b16bf9b270ad3d82873c0bd86a3530)
616. [doc] stephen
Added description to the DHCP "Database Back-Ends" section of the
BIND 10 Developer's Guide about how to set up a MySQL database for
testing the DHCP MySQL backend.
(Trac #2653, git da3579feea036aa2b7d094b1c260a80a69d2f9aa)
615. [bug] jinmei
b10-auth: Avoid referencing to a freed object when authoritative
server addresses are reconfigured. It caused a crash on a busy
server during initial startup time, and the same crash could also
happen if listen_on parameters are reconfigured at run time.
(Trac #2946, git d5f2a0d0954acd8bc33aabb220fab31652394fcd)
614. [func] tmark
b10-d2: Initial DHCP-DDNS (a.k.a. D2) module implemented. Currently it does
nothing useful, except for providing the skeleton implementation
to be expanded in the future.
b10-d2: Initial DHCP-DDNS (a.k.a. D2) module implemented.
Currently it does nothing useful, except for providing the
skeleton implementation to be expanded in the future.
(Trac #2954, git 392c5ec5d15cd8c809bc9c6096b9f2bfe7b8c66a)
613. [func] jinmei
......@@ -25,7 +85,7 @@
while Xfrin is running.
(Trac #2252, git e1a0ea8ef5c51b9b25afa111fbfe9347afbe5413)
bind10-1.0.0beta2 released on May 10, 2013
bind10-1.1.0beta2 released on May 10, 2013
610. [bug] muks
When the sqlite3 program is not available on the system (in
......@@ -128,7 +188,7 @@ bind10-1.0.0beta2 released on May 10, 2013
messages.
(Trac #2827, git 29c3f7f4e82d7e85f0f5fb692345fd55092796b4)
bind10-1.0.0beta1 released on April 4, 2013
bind10-1.1.0beta1 released on April 4, 2013
598. [func]* jinmei
The separate "static" data source is now deprecated as it can be
......
......@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.59])
AC_INIT(bind10, 20130510, bind10-dev@isc.org)
AC_INIT(bind10, 20130529, bind10-dev@isc.org)
AC_CONFIG_SRCDIR(README)
# serial-tests is not available in automake version before 1.13. In
# automake 1.13 and higher, AM_PROG_INSTALL is undefined, so we'll check
......@@ -1332,6 +1332,7 @@ AC_CONFIG_FILES([Makefile
tests/tools/perfdhcp/Makefile
tests/tools/perfdhcp/tests/Makefile
tests/tools/perfdhcp/tests/testdata/Makefile
tests/lettuce/Makefile
m4macros/Makefile
dns++.pc
])
......
......@@ -210,7 +210,7 @@ about changes to zone data, they'd subscribe to the
`Notifications/ZoneUpdates` group. Then, other client (let's say
`XfrIn`, with session ID `s12345`) would send something like:
s12345 -> Notifications/ZoneUpdates
s12345 -> notifications/ZoneUpdates
{"notification": ["zone-update", {
"class": "IN",
"origin": "example.org.",
......@@ -221,7 +221,7 @@ Both receivers would receive the message and know that the
`example.org` zone is now at version 123456. Note that multiple users
may produce the same kind of notification. Also, single group may be
used to send multiple notification names (but they should be related;
in our example, the `Notifications/ZoneUpdates` could be used for
in our example, the `notifications/ZoneUpdates` could be used for
`zone-update`, `zone-available` and `zone-unavailable` notifications
for change in zone data, configuration of new zone in the system and
removal of a zone from configuration).
......
......@@ -386,6 +386,12 @@ Query::process(datasrc::ClientList& client_list,
response_->setHeaderFlag(Message::HEADERFLAG_AA, false);
response_->setRcode(Rcode::REFUSED());
return;
} else if (!result.finder_) {
// We found a matching zone in a data source but its data are not
// available.
response_->setHeaderFlag(Message::HEADERFLAG_AA, false);
response_->setRcode(Rcode::SERVFAIL());
return;
}
ZoneFinder& zfinder = *result.finder_;
......
......@@ -1210,6 +1210,38 @@ TEST_F(AuthSrvTest, updateWithInMemoryClient) {
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
}
TEST_F(AuthSrvTest, emptyZone) {
// Similar to the previous setup, but the configuration has an error
// (zone file doesn't exist) and the query should result in SERVFAIL.
// Here we check the rcode other header parameters, and statistics.
const ConstElementPtr config(Element::fromJSON("{"
"\"IN\": [{"
" \"type\": \"MasterFiles\","
" \"params\": {\"example.com\": \"nosuchfile.zone\"},"
" \"cache-enable\": true"
"}]}"));
installDataSrcClientLists(server, configureDataSource(config));
createDataFromFile("examplequery_fromWire.wire");
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
checkAllRcodeCountersZeroExcept(Rcode::SERVFAIL(), 1);
ConstElementPtr stats = server.getStatistics()->get("zones")->
get("_SERVER_");
std::map<std::string, int> expect;
expect["request.v4"] = 1;
expect["request.udp"] = 1;
expect["opcode.query"] = 1;
expect["responses"] = 1;
expect["qrynoauthans"] = 1;
expect["rcode.servfail"] = 1;
checkStatisticsCounters(stats, expect);
}
TEST_F(AuthSrvTest, queryWithInMemoryClientNoDNSSEC) {
// In this example, we do simple check that query is handled from the
// query handler class, and confirm it returns no error and a non empty
......
......@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <util/unittests/check_valgrind.h>
#include <dns/name.h>
......
......@@ -133,6 +133,12 @@ const char* const unsigned_delegation_nsec3_txt =
"q81r598950igr1eqvc60aedlq66425b5.example.com. 3600 IN NSEC3 1 1 12 "
"aabbccdd 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom NS RRSIG\n";
// Name of an "empty" zone: used to simulate the case of
// configured-but-available zone (due to load errors, etc).
// Each tested data source client is expected to have this zone (SQLite3
// currently doesn't have this concept so it's skipped)
const char* const EMPTY_ZONE_NAME = "empty.example.org";
// A helper function that generates a textual representation of RRSIG RDATA
// for the given covered type. The resulting RRSIG may not necessarily make
// sense in terms of the DNSSEC protocol, but for our testing purposes it's
......@@ -799,11 +805,14 @@ createDataSrcClientList(DataSrcType type, DataSourceClient& client) {
return (boost::shared_ptr<ClientList>(new SingletonList(client)));
case INMEMORY:
list.reset(new ConfigurableClientList(RRClass::IN()));
// Configure one normal zone and one "empty" zone.
list->configure(isc::data::Element::fromJSON(
"[{\"type\": \"MasterFiles\","
" \"cache-enable\": true, "
" \"params\": {\"example.com\": \"" +
string(TEST_OWN_DATA_BUILDDIR "/example.zone") +
string(TEST_OWN_DATA_BUILDDIR "/example.zone\",") +
+ "\"" + EMPTY_ZONE_NAME + "\": \"" +
string(TEST_OWN_DATA_BUILDDIR "/nosuchfile.zone") +
"\"}}]"), true);
return (list);
case SQLITE3:
......@@ -834,39 +843,38 @@ createDataSrcClientList(DataSrcType type, DataSourceClient& client) {
class MockClient : public DataSourceClient {
public:
virtual FindResult findZone(const isc::dns::Name& origin) const {
const Name r_origin(origin.reverse());
std::map<Name, ZoneFinderPtr>::const_iterator it =
zone_finders_.lower_bound(r_origin);
if (it != zone_finders_.end()) {
const NameComparisonResult result =
origin.compare((it->first).reverse());
if (result.getRelation() == NameComparisonResult::EQUAL) {
return (FindResult(result::SUCCESS, it->second));
} else if (result.getRelation() == NameComparisonResult::SUBDOMAIN) {
return (FindResult(result::PARTIALMATCH, it->second));
}
}
// Identify the next (strictly) larger name than the given 'origin' in
// the map. Its predecessor (if any) is the longest matching name
// if it's either an exact match or a super domain; otherwise there's
// no match in the map. See also datasrc/tests/mock_client.cc.
// If it is at the beginning of the map, then the name was not
// found (we have already handled the element the iterator
// points to).
if (it == zone_finders_.begin()) {
// Eliminate the case of empty map to simply the rest of the code
if (zone_finders_.empty()) {
return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
}
// Check if the previous element is a partial match.
--it;
const NameComparisonResult result =
origin.compare((it->first).reverse());
if (result.getRelation() == NameComparisonResult::SUBDOMAIN) {
return (FindResult(result::PARTIALMATCH, it->second));
std::map<Name, ZoneFinderPtr>::const_iterator it =
zone_finders_.upper_bound(origin);
if (it == zone_finders_.begin()) { // no predecessor
return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
}
return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
--it; // get the predecessor
const result::ResultFlags flags =
it->second ? result::FLAGS_DEFAULT : result::ZONE_EMPTY;
const NameComparisonResult compar(it->first.compare(origin));
switch (compar.getRelation()) {
case NameComparisonResult::EQUAL:
return (FindResult(result::SUCCESS, it->second, flags));
case NameComparisonResult::SUPERDOMAIN:
return (FindResult(result::PARTIALMATCH, it->second, flags));
default:
return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
}
}
virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name&, bool, bool) const {
virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name&, bool, bool) const
{
isc_throw(isc::NotImplemented,
"Updater isn't supported in the MockClient");
}
......@@ -878,18 +886,21 @@ public:
}
result::Result addZone(ZoneFinderPtr finder) {
// Use the reverse of the name as the key, so we can quickly
// find partial matches in the map.
zone_finders_[finder->getOrigin().reverse()] = finder;
zone_finders_[finder->getOrigin()] = finder;
return (result::SUCCESS);
}
// "configure" a zone with no data. This will cause the ZONE_EMPTY flag
// on in finZone().
result::Result addEmptyZone(const Name& zone_name) {
zone_finders_[zone_name] = ZoneFinderPtr();
return (result::SUCCESS);
}
private:
// Note that because we no longer have the old RBTree, and the new
// in-memory DomainTree is not useful as it returns const nodes, we
// use a std::map instead. In this map, the key is a name stored in
// reverse order of labels to aid in finding partial matches
// quickly.
// use a std::map instead.
std::map<Name, ZoneFinderPtr> zone_finders_;
};
......@@ -916,9 +927,10 @@ protected:
response.setRcode(Rcode::NOERROR());
response.setOpcode(Opcode::QUERY());
// create and add a matching zone.
// create and add a matching zone. One is a "broken, empty" zone.
mock_finder = new MockZoneFinder();
mock_client.addZone(ZoneFinderPtr(mock_finder));
mock_client.addEmptyZone(Name(EMPTY_ZONE_NAME));
}
virtual void SetUp() {
......@@ -949,6 +961,12 @@ protected:
setNSEC3HashCreator(NULL);
}
bool isEmptyZoneSupported() const {
// Not all data sources support the concept of empty zones.
// Specifically for this test, SQLite3-based data source doesn't.
return (GetParam() != SQLITE3);
}
void enableNSEC3(const vector<string>& rrsets_to_add) {
boost::shared_ptr<ConfigurableClientList> new_list;
switch (GetParam()) {
......@@ -1144,11 +1162,29 @@ TEST_P(QueryTest, noZone) {
// REFUSED.
MockClient empty_mock_client;
SingletonList empty_list(empty_mock_client);
EXPECT_NO_THROW(query.process(empty_list, qname, qtype,
response));
EXPECT_NO_THROW(query.process(empty_list, qname, qtype, response));
EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
}
TEST_P(QueryTest, emptyZone) {
// Query for an "empty (broken)" zone. If the concept is supported by
// the underlying data source, the result should be SERVFAIL; otherwise
// it would be handled as a nonexistent zone, resulting in REFUSED.
const Rcode expected_rcode =
isEmptyZoneSupported() ? Rcode::SERVFAIL() : Rcode::REFUSED();
query.process(*list_, Name(EMPTY_ZONE_NAME), qtype, response);
responseCheck(response, expected_rcode, 0, 0, 0, 0, NULL, NULL, NULL);
// Same for the partial match case
response.clear(isc::dns::Message::RENDER);
response.setRcode(Rcode::NOERROR());
response.setOpcode(Opcode::QUERY());
query.process(*list_, Name(string("www.") + EMPTY_ZONE_NAME), qtype,
response);
responseCheck(response, expected_rcode, 0, 0, 0, 0, NULL, NULL, NULL);
}
TEST_P(QueryTest, exactMatch) {
EXPECT_NO_THROW(query.process(*list_, qname, qtype, response));
// find match rrset
......@@ -1400,7 +1436,6 @@ TEST_F(QueryTestForMockOnly, badSecureDelegation) {
qtype, response));
}
TEST_P(QueryTest, nxdomain) {
EXPECT_NO_THROW(query.process(*list_,
Name("nxdomain.example.com"), qtype,
......
......@@ -100,4 +100,3 @@ the process when it is not running.
% D2CTL_CONFIG_UPDATE updated configuration received: %1
A debug message indicating that the controller has received an
updated configuration from the BIND 10 configuration system.
// 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 <config/ccsession.h>
#include <d2/d2_log.h>
#include <d2/d2_process.h>
using namespace asio;
namespace isc {
namespace d2 {
D2Process::D2Process(const char* name, IOServicePtr io_service)
: DProcessBase(name, io_service) {
};
void
D2Process::init() {
};
int
D2Process::run() {
// Until shut down or an fatal error occurs, wait for and
// execute a single callback. This is a preliminary implementation
// that is likely to evolve as development progresses.
// To use run(), the "managing" layer must issue an io_service::stop
// or the call to run will continue to block, and shutdown will not
// occur.
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_ENTER);
IOServicePtr& io_service = getIoService();
while (!shouldShutdown()) {
try {
io_service->run_one();
} catch (const std::exception& ex) {
LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what());
return (EXIT_FAILURE);
}
}
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_EXIT);
return (EXIT_SUCCESS);
};
int
D2Process::shutdown() {
LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_SHUTDOWN);
setShutdownFlag(true);
return (0);
}
isc::data::ConstElementPtr
D2Process::configure(isc::data::ConstElementPtr config_set) {
// @TODO This is the initial implementation which simply accepts
// any content in config_set as valid. This is sufficient to
// allow participation as a BIND10 module, while D2 configuration support
// is being developed.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
D2PRC_CONFIGURE).arg(config_set->str());
return (isc::config::createAnswer(0, "Configuration accepted."));
}
isc::data::ConstElementPtr
D2Process::command(const std::string& command, isc::data::ConstElementPtr args){
// @TODO This is the initial implementation. If and when D2 is extended
// to support its own commands, this implementation must change. Otherwise
// it should reject all commands as it does now.
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
D2PRC_COMMAND).arg(command).arg(args->str());
return (isc::config::createAnswer(COMMAND_INVALID, "Unrecognized command:"
+ command));
}
D2Process::~D2Process() {
};
}; // namespace isc::d2
}; // namespace isc
// 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 D2_PROCESS_H
#define D2_PROCESS_H
#include <d2/d_process.h>
namespace isc {
namespace d2 {
/// @brief @TODO DHCP-DDNS Application Process
///
/// D2Process provides the top level application logic for DHCP-driven DDNS
/// update processing. It provides the asynchronous event processing required
/// to receive DNS mapping change requests and carry them out.
/// It implements the DProcessBase interface, which structures it such that it
/// is a managed "application", controlled by a management layer.
class D2Process : public DProcessBase {
public:
/// @brief Constructor
///
/// @param name name is a text label for the process. Generally used
/// in log statements, but otherwise arbitrary.
/// @param io_service is the io_service used by the caller for
/// asynchronous event handling.
///
/// @throw DProcessBaseError is io_service is NULL.
D2Process(const char* name, IOServicePtr io_service);
/// @brief Will be used after instantiation to perform initialization
/// unique to D2. This will likely include interactions with QueueMgr and
/// UpdateMgr, to prepare for request receipt and processing.
virtual void init();
/// @brief Implements the process's event loop.
/// The initial implementation is quite basic, surrounding calls to
/// io_service->runOne() with a test of the shutdown flag.
/// Once invoked, the method will continue until the process itself is
/// exiting due to a request to shutdown or some anomaly forces an exit.
/// @return returns 0 upon a successful, "normal" termination, non
/// zero to indicate an abnormal termination.
virtual int run();
// @TODO need brief
virtual int shutdown();
// @TODO need brief
/// @brief Processes the given configuration.
///
/// This method may be called multiple times during the process lifetime.
/// Certainly once during process startup, and possibly later if the user
/// alters configuration. This method must not throw, it should catch any
/// processing errors and return a success or failure answer as described
/// below.
///
/// @param config_set a new configuration (JSON) for the process
/// @return an Element that contains the results of configuration composed
/// of an integer status value (0 means successful, non-zero means failure),
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
config_set);
// @TODO need brief
/// @brief Processes the given command.
///
/// This method is called to execute any custom commands supported by the
/// process. This method must not throw, it should catch any processing
/// errors and return a success or failure answer as described below.
///
/// @param command is a string label representing the command to execute.
/// @param args is a set of arguments (if any) required for the given
/// command.
/// @return an Element that contains the results of command composed
/// of an integer status value (0 means successful, non-zero means failure),
/// and a string explanation of the outcome.
virtual isc::data::ConstElementPtr command(const std::string& command,
isc::data::ConstElementPtr args);
// @TODO need brief
virtual ~D2Process();
};
}; // namespace isc::d2
}; // namespace isc
#endif
// 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 D_PROCESS_H
#define D_PROCESS_H
#include <asiolink/asiolink.h>
#include <cc/data.h>
#include <boost/shared_ptr.hpp>
#include <exceptions/exceptions.h>
typedef boost::shared_ptr<isc::asiolink::IOService> IOServicePtr;
namespace isc {
namespace d2 {
/// @brief Exception thrown if the process encountered an operational error.
class DProcessBaseError : public isc::Exception {
public:
DProcessBaseError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) { };
};
static const int COMMAND_SUCCESS = 0;
static const int COMMAND_ERROR = 1;
static const int COMMAND_INVALID = 2;
static const std::string SHUT_DOWN_COMMAND("shutdown");
/// @brief Application Process Interface
///
/// DProcessBase is an abstract class represents the primary "application"
/// level object in a "managed" asynchronous application. It provides a uniform
/// interface such that a managing layer can construct, intialize, and start
/// the application's event loop. The event processing is centered around the
/// use of isc::asiolink::io_service. The io_service is shared between the
/// the managing layer and the DProcessBase. This allows management layer IO
/// such as directives to be sensed and handled, as well as processing IO
/// activity specific to the application. In terms of management layer IO,
/// there are methods shutdown, configuration updates, and commands unique
/// to the application.
class DProcessBase {