[svn] commit: r2601 - in /branches/trac191: ./ doc/ src/bin/auth/ src/bin/auth/tests/ src/bin/bindctl/ src/bin/cmdctl/ src/bin/cmdctl/tests/ src/bin/host/ src/bin/xfrin/ src/bin/xfrin/tests/ src/bin/xfrout/ src/lib/cc/ src/lib/config/ src/lib/config/testdata/ src/lib/config/tests/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/datasrc/tests/testdata/ src/lib/dns/ src/lib/dns/python/ src/lib/dns/rdata/generic/ src/lib/dns/tests/ src/lib/dns/util/ src/lib/exceptions/ src/lib/python/isc/cc/ src/lib/python/isc/cc/tests/ src/lib/python/isc/config/ src/lib/python/isc/config/tests/ src/lib/xfr/

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jul 23 09:45:18 UTC 2010


Author: naokikambe
Date: Fri Jul 23 09:45:17 2010
New Revision: 2601

Log:
merge from trunk head

Added:
    branches/trac191/src/bin/auth/tests/asio_link_unittest.cc
      - copied unchanged from r2600, trunk/src/bin/auth/tests/asio_link_unittest.cc
    branches/trac191/src/lib/config/testdata/spec28.spec
      - copied unchanged from r2600, trunk/src/lib/config/testdata/spec28.spec
    branches/trac191/src/lib/dns/tests/base32hex_unittest.cc
      - copied unchanged from r2600, trunk/src/lib/dns/tests/base32hex_unittest.cc
    branches/trac191/src/lib/dns/util/
      - copied from r2600, trunk/src/lib/dns/util/
Removed:
    branches/trac191/src/lib/datasrc/tests/testdata/q_cname
    branches/trac191/src/lib/datasrc/tests/testdata/q_cname_ext
    branches/trac191/src/lib/datasrc/tests/testdata/q_cname_int
    branches/trac191/src/lib/datasrc/tests/testdata/q_dname
    branches/trac191/src/lib/datasrc/tests/testdata/q_example_dnskey
    branches/trac191/src/lib/datasrc/tests/testdata/q_example_ns
    branches/trac191/src/lib/datasrc/tests/testdata/q_example_ptr
    branches/trac191/src/lib/datasrc/tests/testdata/q_glork
    branches/trac191/src/lib/datasrc/tests/testdata/q_spork
    branches/trac191/src/lib/datasrc/tests/testdata/q_sql1
    branches/trac191/src/lib/datasrc/tests/testdata/q_subzone
    branches/trac191/src/lib/datasrc/tests/testdata/q_subzone_any
    branches/trac191/src/lib/datasrc/tests/testdata/q_subzone_dname
    branches/trac191/src/lib/datasrc/tests/testdata/q_subzone_ds
    branches/trac191/src/lib/datasrc/tests/testdata/q_subzone_ns
    branches/trac191/src/lib/datasrc/tests/testdata/q_subzone_nsec
    branches/trac191/src/lib/datasrc/tests/testdata/q_wild2_a
    branches/trac191/src/lib/datasrc/tests/testdata/q_wild2_aaaa
    branches/trac191/src/lib/datasrc/tests/testdata/q_wild3_a
    branches/trac191/src/lib/datasrc/tests/testdata/q_wild_a
    branches/trac191/src/lib/datasrc/tests/testdata/q_wild_aaaa
    branches/trac191/src/lib/dns/base32.cc
    branches/trac191/src/lib/dns/base32.h
    branches/trac191/src/lib/dns/base64.cc
    branches/trac191/src/lib/dns/base64.h
    branches/trac191/src/lib/dns/hex.cc
    branches/trac191/src/lib/dns/hex.h
    branches/trac191/src/lib/dns/sha1.cc
    branches/trac191/src/lib/dns/sha1.h
    branches/trac191/src/lib/dns/tests/base32_unittest.cc
Modified:
    branches/trac191/   (props changed)
    branches/trac191/ChangeLog
    branches/trac191/doc/Doxyfile
    branches/trac191/src/bin/auth/Makefile.am
    branches/trac191/src/bin/auth/asio_link.cc
    branches/trac191/src/bin/auth/asio_link.h
    branches/trac191/src/bin/auth/auth.spec.pre.in
    branches/trac191/src/bin/auth/auth_srv.cc
    branches/trac191/src/bin/auth/auth_srv.h
    branches/trac191/src/bin/auth/main.cc
    branches/trac191/src/bin/auth/tests/Makefile.am
    branches/trac191/src/bin/auth/tests/auth_srv_unittest.cc
    branches/trac191/src/bin/bindctl/bindcmd.py
    branches/trac191/src/bin/cmdctl/TODO
    branches/trac191/src/bin/cmdctl/cmdctl.py.in
    branches/trac191/src/bin/cmdctl/cmdctl.spec.pre.in
    branches/trac191/src/bin/cmdctl/tests/cmdctl_test.py
    branches/trac191/src/bin/host/host.cc
    branches/trac191/src/bin/xfrin/   (props changed)
    branches/trac191/src/bin/xfrin/tests/xfrin_test.py
    branches/trac191/src/bin/xfrin/xfrin.py.in
    branches/trac191/src/bin/xfrin/xfrin.spec.pre.in
    branches/trac191/src/bin/xfrout/xfrout.spec.pre.in
    branches/trac191/src/lib/cc/   (props changed)
    branches/trac191/src/lib/cc/data.cc
    branches/trac191/src/lib/cc/session.cc
    branches/trac191/src/lib/cc/session.h
    branches/trac191/src/lib/cc/session_unittests.cc
    branches/trac191/src/lib/config/Makefile.am
    branches/trac191/src/lib/config/ccsession.cc
    branches/trac191/src/lib/config/ccsession.h
    branches/trac191/src/lib/config/config_data.cc
    branches/trac191/src/lib/config/module_spec.cc
    branches/trac191/src/lib/config/testdata/b10-config.db
    branches/trac191/src/lib/config/testdata/data22_1.data
    branches/trac191/src/lib/config/testdata/data22_2.data
    branches/trac191/src/lib/config/testdata/data22_3.data
    branches/trac191/src/lib/config/testdata/data22_4.data
    branches/trac191/src/lib/config/testdata/data22_5.data
    branches/trac191/src/lib/config/testdata/data22_6.data
    branches/trac191/src/lib/config/testdata/data22_7.data
    branches/trac191/src/lib/config/testdata/data22_8.data
    branches/trac191/src/lib/config/testdata/spec10.spec
    branches/trac191/src/lib/config/testdata/spec11.spec
    branches/trac191/src/lib/config/testdata/spec12.spec
    branches/trac191/src/lib/config/testdata/spec13.spec
    branches/trac191/src/lib/config/testdata/spec14.spec
    branches/trac191/src/lib/config/testdata/spec15.spec
    branches/trac191/src/lib/config/testdata/spec17.spec
    branches/trac191/src/lib/config/testdata/spec2.spec
    branches/trac191/src/lib/config/testdata/spec20.spec
    branches/trac191/src/lib/config/testdata/spec22.spec
    branches/trac191/src/lib/config/testdata/spec23.spec
    branches/trac191/src/lib/config/testdata/spec24.spec
    branches/trac191/src/lib/config/testdata/spec27.spec
    branches/trac191/src/lib/config/testdata/spec3.spec
    branches/trac191/src/lib/config/testdata/spec4.spec
    branches/trac191/src/lib/config/testdata/spec6.spec
    branches/trac191/src/lib/config/testdata/spec9.spec
    branches/trac191/src/lib/config/tests/Makefile.am
    branches/trac191/src/lib/config/tests/ccsession_unittests.cc
    branches/trac191/src/lib/config/tests/config_data_unittests.cc
    branches/trac191/src/lib/config/tests/fake_session.cc
    branches/trac191/src/lib/config/tests/fake_session.h
    branches/trac191/src/lib/config/tests/module_spec_unittests.cc
    branches/trac191/src/lib/datasrc/   (props changed)
    branches/trac191/src/lib/datasrc/cache.cc
    branches/trac191/src/lib/datasrc/data_source.cc
    branches/trac191/src/lib/datasrc/query.cc
    branches/trac191/src/lib/datasrc/query.h
    branches/trac191/src/lib/datasrc/sqlite3_datasrc.cc
    branches/trac191/src/lib/datasrc/sqlite3_datasrc.h
    branches/trac191/src/lib/datasrc/static_datasrc.cc
    branches/trac191/src/lib/datasrc/static_datasrc.h
    branches/trac191/src/lib/datasrc/tests/Makefile.am
    branches/trac191/src/lib/datasrc/tests/datasrc_unittest.cc
    branches/trac191/src/lib/datasrc/tests/query_unittest.cc
    branches/trac191/src/lib/datasrc/tests/static_unittest.cc
    branches/trac191/src/lib/datasrc/tests/test_datasrc.cc
    branches/trac191/src/lib/dns/   (props changed)
    branches/trac191/src/lib/dns/Makefile.am
    branches/trac191/src/lib/dns/python/libdns_python.cc
    branches/trac191/src/lib/dns/rdata/generic/dnskey_48.cc
    branches/trac191/src/lib/dns/rdata/generic/ds_43.cc
    branches/trac191/src/lib/dns/rdata/generic/nsec3_50.cc
    branches/trac191/src/lib/dns/rdata/generic/nsec3param_51.cc
    branches/trac191/src/lib/dns/rdata/generic/nsec_47.cc
    branches/trac191/src/lib/dns/rdata/generic/rrsig_46.cc   (contents, props changed)
    branches/trac191/src/lib/dns/tests/   (props changed)
    branches/trac191/src/lib/dns/tests/Makefile.am
    branches/trac191/src/lib/dns/tests/base64_unittest.cc
    branches/trac191/src/lib/dns/tests/hex_unittest.cc
    branches/trac191/src/lib/dns/tests/message_unittest.cc
    branches/trac191/src/lib/dns/tests/messagerenderer_unittest.cc
    branches/trac191/src/lib/dns/tests/name_unittest.cc
    branches/trac191/src/lib/dns/tests/question_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_cname_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_dname_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_dnskey_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_ds_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_in_a_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_mx_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_ns_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_nsec3_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_nsec3param_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_nsec_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_opt_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_ptr_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_rrsig_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_soa_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_txt_unittest.cc
    branches/trac191/src/lib/dns/tests/rdata_unittest.cc
    branches/trac191/src/lib/dns/tests/rrclass_unittest.cc
    branches/trac191/src/lib/dns/tests/rrset_unittest.cc
    branches/trac191/src/lib/dns/tests/rrttl_unittest.cc
    branches/trac191/src/lib/dns/tests/rrtype_unittest.cc
    branches/trac191/src/lib/dns/tests/run_unittests.cc
    branches/trac191/src/lib/dns/tests/sha1_unittest.cc
    branches/trac191/src/lib/dns/tests/tsig_unittest.cc
    branches/trac191/src/lib/dns/tests/unittest_util.cc
    branches/trac191/src/lib/exceptions/Makefile.am
    branches/trac191/src/lib/exceptions/exceptions.cc
    branches/trac191/src/lib/exceptions/exceptions.h
    branches/trac191/src/lib/exceptions/exceptions_unittest.cc
    branches/trac191/src/lib/python/isc/cc/data.py
    branches/trac191/src/lib/python/isc/cc/tests/data_test.py
    branches/trac191/src/lib/python/isc/config/ccsession.py
    branches/trac191/src/lib/python/isc/config/cfgmgr.py
    branches/trac191/src/lib/python/isc/config/module_spec.py
    branches/trac191/src/lib/python/isc/config/tests/ccsession_test.py
    branches/trac191/src/lib/python/isc/config/tests/module_spec_test.py
    branches/trac191/src/lib/xfr/fd_share.cc
    branches/trac191/src/lib/xfr/fdshare_python.cc
    branches/trac191/src/lib/xfr/python_xfr.cc
    branches/trac191/src/lib/xfr/xfrout_client.cc
    branches/trac191/src/lib/xfr/xfrout_client.h

Modified: branches/trac191/ChangeLog
==============================================================================
--- branches/trac191/ChangeLog (original)
+++ branches/trac191/ChangeLog Fri Jul 23 09:45:17 2010
@@ -1,3 +1,48 @@
+  79.	[func]		feng, jinmei
+	Refactored the ASIO link interfaces to move incoming XFR and
+	NOTIFY processing to the auth server class.  Wrapper classes for
+	ASIO specific concepts were also provided, so that other BIND 10
+	modules can (eventually) use the interface without including the
+	ASIO header file directly.  On top of these changes, AXFR and
+	NOTIFY processing was massively improved in terms of message
+	validation and protocol conformance.  Detailed tests were provided
+	to confirm the behavior.
+	Note: Right now, NOTIFY doesn't actually trigger subsequent zone
+	transfer due to security reasons. (Trac #221, r2565)
+
+  78.	[bug]		jinmei
+	lib/dns: Fixed miscellaneous bugs in the base32 (hex) and hex
+	(base16) implementation, including incorrect padding handling,
+	parser failure in decoding with a SunStudio build, missing
+	validation on the length of encoded hex string.  Test cases were
+	more detailed to identify these bugs and confirm the fix.  Also
+	renamed the incorrect term of "base32" to "base32hex".  This
+	changed the API, but they are not intended to be used outside
+	libdns++, so we don't consider it a backward incompatible change.
+	(Trac #256, r2549)
+
+  77.	[func]		zhanglikun
+	Make error message be more friendly when running cmdctl and it's 
+	already running(listening on same port)(Trac #277, r2540)
+
+  76.	[bug]		jelte
+	Fixed a bug in the handling of 'remote' config modules (i.e.
+	modules that peek at the configuration of other modules), where
+	they answered 'unknown command' to commands for those other
+	modules. (Trac #278, r2506)
+
+  75.	[bug]		jinmei
+	Fixed a bug in the sqlite3 data source where temporary strings
+	could be referenced after destruction.  It caused various lookup
+	failures with SunStudio build. (Trac #288, r2494)
+
+  74.	[func]*		jinmei
+	Refactored the cc::Session class by introducing an abstract base
+	class.  Test code can use their own derived mock class so that
+	tests can be done without establishing a real CC session.  This
+	change also modified some public APIs, mainly in the config
+	module. (Trac #275, r2459)
+
   73.	[bug]		jelte
   	Fixed a bug where in bindctl, locally changed settings were
 	reset when the list of running modules is updated. (Trac #285,

Modified: branches/trac191/doc/Doxyfile
==============================================================================
--- branches/trac191/doc/Doxyfile (original)
+++ branches/trac191/doc/Doxyfile Fri Jul 23 09:45:17 2010
@@ -568,7 +568,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc
+INPUT                  = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

Modified: branches/trac191/src/bin/auth/Makefile.am
==============================================================================
--- branches/trac191/src/bin/auth/Makefile.am (original)
+++ branches/trac191/src/bin/auth/Makefile.am Fri Jul 23 09:45:17 2010
@@ -1,8 +1,10 @@
 SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
+AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
@@ -53,8 +55,8 @@
 b10_auth_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a
 b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
 b10_auth_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a
+b10_auth_LDADD += $(top_builddir)/src/lib/xfr/.libs/libxfr.a
 b10_auth_LDADD += $(SQLITE_LIBS)
-b10_auth_LDADD += $(top_builddir)/src/lib/xfr/.libs/libxfr.a
 
 # TODO: config.h.in is wrong because doesn't honor pkgdatadir
 # and can't use @datadir@ because doesn't expand default ${prefix}

Modified: branches/trac191/src/bin/auth/asio_link.cc
==============================================================================
--- branches/trac191/src/bin/auth/asio_link.cc (original)
+++ branches/trac191/src/bin/auth/asio_link.cc Fri Jul 23 09:45:17 2010
@@ -17,83 +17,167 @@
 #include <config.h>
 
 #include <unistd.h>             // for some IPC/network system calls
+#include <sys/socket.h>
+#include <netinet/in.h>
+
 #include <asio.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/bind.hpp>
 
+#include <boost/shared_ptr.hpp>
+
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
 
-#include <xfr/xfrout_client.h>
-
 #include <asio_link.h>
 
-#include "spec_config.h"        // for XFROUT.  should not be here.
-#include "auth_srv.h"
-#include "common.h"
+#include <auth/auth_srv.h>
+#include <auth/common.h>
 
 using namespace asio;
-using ip::udp;
-using ip::tcp;
+using asio::ip::udp;
+using asio::ip::tcp;
 
 using namespace std;
 using namespace isc::dns;
-using namespace isc::xfr;
-
-namespace {
-// As a short term workaround, we have XFROUT specific code.  We should soon
-// refactor the code with some abstraction so that we can separate this level
-// details from the (AS)IO module.
-
-// This was contained in an ifdef USE_XFROUT, but we should really check
-// live if we do xfrout
-//TODO. The sample way for checking axfr query, the code should be merged to auth server class
-bool
-check_axfr_query(char* const msg_data, const uint16_t msg_len) {
-    if (msg_len < 15) {
-        return false;
-    }
-
-    const uint16_t query_type = *(uint16_t *)(msg_data + (msg_len - 4));
-    if ( query_type == 0xFC00) {
-        return true;
-    }
-    
-    return false;
-}
-
-//TODO. Send the xfr query to xfrout module, the code should be merged to auth server class
-//BIGGERTODO: stop using hardcoded install-path locations! 
-void
-dispatch_axfr_query(const int tcp_sock, char const axfr_query[],
-                    const uint16_t query_len)
+
+namespace asio_link {
+IOAddress::IOAddress(const string& address_str)
+    // XXX: we cannot simply construct the address in the initialization list
+    // because we'd like to throw our own exception on failure.
 {
-    string path;
-    if (getenv("B10_FROM_BUILD")) {
-        path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
-    } else {
-        path = UNIX_SOCKET_FILE;
-    }
-    
-    if (getenv("B10_FROM_BUILD")) {
-        path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
-    }
-    XfroutClient xfr_client(path);
-    try {
-        xfr_client.connect();
-        xfr_client.sendXfroutRequestInfo(tcp_sock, (uint8_t *)axfr_query,
-                                         query_len);
-        xfr_client.disconnect();
-    }
-    catch (const exception & err) {
-        //if (verbose_mode)
-        cerr << "error handle xfr query " << UNIX_SOCKET_FILE << ":" << err.what() << endl;
-    }
-}
-}
-
-namespace asio_link {
+    error_code err;
+    asio_address_ = ip::address::from_string(address_str, err);
+    if (err) {
+        isc_throw(IOError, "Failed to convert string to address '"
+                  << address_str << "': " << err.message());
+    }
+}
+
+IOAddress::IOAddress(const ip::address& asio_address) :
+    asio_address_(asio_address)
+{}
+
+string
+IOAddress::toText() const {
+    return (asio_address_.to_string());
+}
+
+// Note: this implementation is optimized for the case where this object
+// is created from an ASIO endpoint object in a receiving code path
+// by avoiding to make a copy of the base endpoint.  For TCP it may not be
+// a bug deal, but when we receive UDP packets at a high rate, the copy
+// overhead might be significant.
+class TCPEndpoint : public IOEndpoint {
+public:
+    TCPEndpoint(const IOAddress& address, const unsigned short port) :
+        asio_endpoint_placeholder_(
+            new tcp::endpoint(ip::address::from_string(address.toText()),
+                              port)),
+        asio_endpoint_(*asio_endpoint_placeholder_)
+    {}
+    TCPEndpoint(const tcp::endpoint& asio_endpoint) :
+        asio_endpoint_placeholder_(NULL), asio_endpoint_(asio_endpoint)
+    {}
+        
+    ~TCPEndpoint() { delete asio_endpoint_placeholder_; }
+    virtual IOAddress getAddress() const {
+        return (asio_endpoint_.address());
+    }
+private:
+    const tcp::endpoint* asio_endpoint_placeholder_;
+    const tcp::endpoint& asio_endpoint_;
+};
+
+class UDPEndpoint : public IOEndpoint {
+public:
+    UDPEndpoint(const IOAddress& address, const unsigned short port) :
+        asio_endpoint_placeholder_(
+            new udp::endpoint(ip::address::from_string(address.toText()),
+                              port)),
+        asio_endpoint_(*asio_endpoint_placeholder_)
+    {}
+    UDPEndpoint(const udp::endpoint& asio_endpoint) :
+        asio_endpoint_placeholder_(NULL), asio_endpoint_(asio_endpoint)
+    {}
+    ~UDPEndpoint() { delete asio_endpoint_placeholder_; }
+    virtual IOAddress getAddress() const {
+        return (asio_endpoint_.address());
+    }
+private:
+    const udp::endpoint* asio_endpoint_placeholder_;
+    const udp::endpoint& asio_endpoint_;
+};
+
+const IOEndpoint*
+IOEndpoint::create(const int protocol, const IOAddress& address,
+                   const unsigned short port)
+{
+    if (protocol == IPPROTO_UDP) {
+        return (new UDPEndpoint(address, port));
+    } else if (protocol == IPPROTO_TCP) {
+        return (new TCPEndpoint(address, port));
+    }
+    isc_throw(IOError,
+              "IOEndpoint creation attempt for unsupported protocol: " <<
+              protocol);
+}
+
+class TCPSocket : public IOSocket {
+private:
+    TCPSocket(const TCPSocket& source);
+    TCPSocket& operator=(const TCPSocket& source);
+public:
+    TCPSocket(tcp::socket& socket) : socket_(socket) {}
+    virtual int getNative() const { return (socket_.native()); }
+    virtual int getProtocol() const { return (IPPROTO_TCP); }
+private:
+    tcp::socket& socket_;
+};
+
+class UDPSocket : public IOSocket {
+private:
+    UDPSocket(const UDPSocket& source);
+    UDPSocket& operator=(const UDPSocket& source);
+public:
+    UDPSocket(udp::socket& socket) : socket_(socket) {}
+    virtual int getNative() const { return (socket_.native()); }
+    virtual int getProtocol() const { return (IPPROTO_UDP); }
+private:
+    udp::socket& socket_;
+};
+
+class DummySocket : public IOSocket {
+private:
+    DummySocket(const DummySocket& source);
+    DummySocket& operator=(const DummySocket& source);
+public:
+    DummySocket(const int protocol) : protocol_(protocol) {}
+    virtual int getNative() const { return (-1); }
+    virtual int getProtocol() const { return (protocol_); }
+private:
+    const int protocol_;
+};
+
+IOSocket&
+IOSocket::getDummyUDPSocket() {
+    static DummySocket socket(IPPROTO_UDP);
+    return (socket);
+}
+
+IOSocket&
+IOSocket::getDummyTCPSocket() {
+    static DummySocket socket(IPPROTO_TCP);
+    return (socket);
+}
+
+IOMessage::IOMessage(const void* data, const size_t data_size,
+                     IOSocket& io_socket, const IOEndpoint& remote_endpoint) :
+    data_(data), data_size_(data_size), io_socket_(io_socket),
+    remote_endpoint_(remote_endpoint)
+{}
+
 //
 // Helper classes for asynchronous I/O using asio
 //
@@ -102,15 +186,18 @@
     TCPClient(AuthSrv* auth_server, io_service& io_service) :
         auth_server_(auth_server),
         socket_(io_service),
+        io_socket_(socket_),
         response_buffer_(0),
         responselen_buffer_(TCP_MESSAGE_LENGTHSIZE),
         response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE)
+        dns_message_(Message::PARSE),
+        custom_callback_(NULL)
     {}
 
     void start() {
         // Check for queued configuration commands
-        if (auth_server_->configSession()->hasQueuedMsgs()) {
+        if (auth_server_ != NULL &&
+            auth_server_->configSession()->hasQueuedMsgs()) {
             auth_server_->configSession()->checkCommand();
         }
         async_read(socket_, asio::buffer(data_, TCP_MESSAGE_LENGTHSIZE),
@@ -129,7 +216,6 @@
 
             uint16_t msglen = dnsbuffer.readUint16();
             async_read(socket_, asio::buffer(data_, msglen),
-
                        boost::bind(&TCPClient::requestRead, this,
                                    placeholders::error,
                                    placeholders::bytes_transferred));
@@ -142,25 +228,28 @@
                      size_t bytes_transferred)
     {
         if (!error) {
-            InputBuffer dnsbuffer(data_, bytes_transferred);
-            if (check_axfr_query(data_, bytes_transferred)) {
-                dispatch_axfr_query(socket_.native(), data_, bytes_transferred); 
-                // start to get new query ?
+            const TCPEndpoint remote_endpoint(socket_.remote_endpoint());
+            const IOMessage io_message(data_, bytes_transferred, io_socket_,
+                                       remote_endpoint);
+            // currently, for testing purpose only
+            if (custom_callback_ != NULL) {
+                (*custom_callback_)(io_message);
                 start();
+                return;
+            }
+
+            if (auth_server_->processMessage(io_message, dns_message_,
+                                             response_renderer_)) {
+                responselen_buffer_.writeUint16(
+                    response_buffer_.getLength());
+                async_write(socket_,
+                            asio::buffer(
+                                responselen_buffer_.getData(),
+                                responselen_buffer_.getLength()),
+                            boost::bind(&TCPClient::responseWrite, this,
+                                        placeholders::error));
             } else {
-                if (auth_server_->processMessage(dnsbuffer, dns_message_,
-                                                response_renderer_, false)) {
-                    responselen_buffer_.writeUint16(
-                        response_buffer_.getLength());
-                    async_write(socket_,
-                                asio::buffer(
-                                    responselen_buffer_.getData(),
-                                    responselen_buffer_.getLength()),
-                                boost::bind(&TCPClient::responseWrite, this,
-                                            placeholders::error));
-                } else {
-                    delete this;
-                }
+                delete this;
             }
         } else {
             delete this;
@@ -171,9 +260,9 @@
         if (!error) {
                 async_write(socket_,
                             asio::buffer(response_buffer_.getData(),
-                                                response_buffer_.getLength()),
-                        boost::bind(&TCPClient::handleWrite, this,
-                                    placeholders::error));
+                                         response_buffer_.getLength()),
+                            boost::bind(&TCPClient::handleWrite, this,
+                                        placeholders::error));
         } else {
             delete this;
         }
@@ -187,9 +276,15 @@
       }
     }
 
+    // Currently this is for tests only
+    void setCallBack(const IOService::IOCallBack* callback) {
+        custom_callback_ = callback;
+    }
+
 private:
     AuthSrv* auth_server_;
     tcp::socket socket_;
+    TCPSocket io_socket_;
     OutputBuffer response_buffer_;
     OutputBuffer responselen_buffer_;
     MessageRenderer response_renderer_;
@@ -197,21 +292,25 @@
     enum { MAX_LENGTH = 65535 };
     static const size_t TCP_MESSAGE_LENGTHSIZE = 2;
     char data_[MAX_LENGTH];
+
+    // currently, for testing purpose only.
+    const IOService::IOCallBack* custom_callback_;
 };
 
 class TCPServer {
 public:
     TCPServer(AuthSrv* auth_server, io_service& io_service,
-              int af, uint16_t port) :
+              const ip::address& addr, const uint16_t port) :
         auth_server_(auth_server), io_service_(io_service),
         acceptor_(io_service_), listening_(new TCPClient(auth_server_,
-                                                         io_service_))
-    {
-        tcp::endpoint endpoint(af == AF_INET6 ? tcp::v6() : tcp::v4(), port);
+                                                         io_service_)),
+        custom_callback_(NULL)
+    {
+        tcp::endpoint endpoint(addr, port);
         acceptor_.open(endpoint.protocol());
         // Set v6-only (we use a different instantiation for v4,
         // otherwise asio will bind to both v4 and v6
-        if (af == AF_INET6) {
+        if (addr.is_v6()) {
             acceptor_.set_option(ip::v6_only(true));
         }
         acceptor_.set_option(tcp::acceptor::reuse_address(true));
@@ -222,23 +321,6 @@
                                            listening_, placeholders::error));
     }
 
-    TCPServer(AuthSrv* auth_server, io_service& io_service,
-              asio::ip::address addr, uint16_t port) :
-        auth_server_(auth_server),
-        io_service_(io_service), acceptor_(io_service_),
-        listening_(new TCPClient(auth_server, io_service_))
-    {
-        tcp::endpoint endpoint(addr, port);
-        acceptor_.open(endpoint.protocol());
-
-        acceptor_.set_option(tcp::acceptor::reuse_address(true));
-        acceptor_.bind(endpoint);
-        acceptor_.listen();
-        acceptor_.async_accept(listening_->getSocket(),
-                               boost::bind(&TCPServer::handleAccept, this,
-                                           listening_, placeholders::error));
-    }
-
     ~TCPServer() { delete listening_; }
 
     void handleAccept(TCPClient* new_client,
@@ -246,6 +328,7 @@
     {
         if (!error) {
             assert(new_client == listening_);
+            new_client->setCallBack(custom_callback_);
             new_client->start();
             listening_ = new TCPClient(auth_server_, io_service_);
             acceptor_.async_accept(listening_->getSocket(),
@@ -257,44 +340,42 @@
         }
     }
 
+    // Currently this is for tests only
+    void setCallBack(const IOService::IOCallBack* callback) {
+        custom_callback_ = callback;
+    }
+
 private:
     AuthSrv* auth_server_;
     io_service& io_service_;
     tcp::acceptor acceptor_;
     TCPClient* listening_;
+
+    // currently, for testing purpose only.
+    const IOService::IOCallBack* custom_callback_;
 };
 
 class UDPServer {
 public:
     UDPServer(AuthSrv* auth_server, io_service& io_service,
-              int af, uint16_t port) :
+              const ip::address& addr, const uint16_t port) :
         auth_server_(auth_server),
         io_service_(io_service),
-        socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
+        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
+        io_socket_(socket_),
         response_buffer_(0),
         response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE)
+        dns_message_(Message::PARSE),
+        custom_callback_(NULL)
     {
         // Set v6-only (we use a different instantiation for v4,
         // otherwise asio will bind to both v4 and v6
-        if (af == AF_INET6) {
+        if (addr.is_v6()) {
             socket_.set_option(asio::ip::v6_only(true));
-            socket_.bind(udp::endpoint(udp::v6(), port));
+            socket_.bind(udp::endpoint(addr, port));
         } else {
-            socket_.bind(udp::endpoint(udp::v4(), port));
-        }
-        startReceive();
-    }
-
-    UDPServer(AuthSrv* auth_server, io_service& io_service,
-              asio::ip::address addr, uint16_t port) :
-        auth_server_(auth_server), io_service_(io_service),
-        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
-        response_buffer_(0),
-        response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE)
-    {
-        socket_.bind(udp::endpoint(addr, port));
+            socket_.bind(udp::endpoint(addr, port));
+        }
         startReceive();
     }
 
@@ -302,16 +383,25 @@
                        size_t bytes_recvd)
     {
         // Check for queued configuration commands
-        if (auth_server_->configSession()->hasQueuedMsgs()) {
+        if (auth_server_ != NULL &&
+            auth_server_->configSession()->hasQueuedMsgs()) {
             auth_server_->configSession()->checkCommand();
         }
         if (!error && bytes_recvd > 0) {
-            InputBuffer request_buffer(data_, bytes_recvd);
+            const UDPEndpoint remote_endpoint(sender_endpoint_);
+            const IOMessage io_message(data_, bytes_recvd, io_socket_,
+                                       remote_endpoint);
+            // currently, for testing purpose only
+            if (custom_callback_ != NULL) {
+                (*custom_callback_)(io_message);
+                startReceive();
+                return;
+            }
 
             dns_message_.clear(Message::PARSE);
             response_renderer_.clear();
-            if (auth_server_->processMessage(request_buffer, dns_message_,
-                                            response_renderer_, true)) {
+            if (auth_server_->processMessage(io_message, dns_message_,
+                                             response_renderer_)) {
                 socket_.async_send_to(
                     asio::buffer(response_buffer_.getData(),
                                         response_buffer_.getLength()),
@@ -335,6 +425,11 @@
         // the next request.
         startReceive();
     }
+
+    // Currently this is for tests only
+    void setCallBack(const IOService::IOCallBack* callback) {
+        custom_callback_ = callback;
+    }
 private:
     void startReceive() {
         socket_.async_receive_from(
@@ -348,121 +443,107 @@
     AuthSrv* auth_server_;
     io_service& io_service_;
     udp::socket socket_;
+    UDPSocket io_socket_;
     OutputBuffer response_buffer_;
     MessageRenderer response_renderer_;
     Message dns_message_;
     udp::endpoint sender_endpoint_;
     enum { MAX_LENGTH = 4096 };
     char data_[MAX_LENGTH];
-};
-
-// This is a helper structure just to make the construction of IOServiceImpl
-// exception safe.  If the constructor of {UDP/TCP}Server throws an exception,
-// the destructor of this class will automatically perform the necessary
-// cleanup.
-struct ServerSet {
-    ServerSet() : udp4_server(NULL), udp6_server(NULL),
-                  tcp4_server(NULL), tcp6_server(NULL)
-    {}
-    ~ServerSet() {
-        delete udp4_server;
-        delete udp6_server;
-        delete tcp4_server;
-        delete tcp6_server;
-    }
-    UDPServer* udp4_server;
-    UDPServer* udp6_server;
-    TCPServer* tcp4_server;
-    TCPServer* tcp6_server;
+
+    // currently, for testing purpose only.
+    const IOService::IOCallBack* custom_callback_;
 };
 
 class IOServiceImpl {
 public:
-    IOServiceImpl(AuthSrv* auth_server, const char* address, const char* port,
-                  const bool use_ipv4, const bool use_ipv6);
-    ~IOServiceImpl();
+    IOServiceImpl(AuthSrv* auth_server, const char& port,
+                  const ip::address* v4addr, const ip::address* v6addr);
     asio::io_service io_service_;
     AuthSrv* auth_server_;
-    UDPServer* udp4_server_;
-    UDPServer* udp6_server_;
-    TCPServer* tcp4_server_;
-    TCPServer* tcp6_server_;
-};
-
-IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char* const address,
-                             const char* const port, const bool use_ipv4,
-                             const bool use_ipv6) :
-    auth_server_(auth_server), udp4_server_(NULL), udp6_server_(NULL),
-    tcp4_server_(NULL), tcp6_server_(NULL)
+
+    typedef boost::shared_ptr<UDPServer> UDPServerPtr;
+    typedef boost::shared_ptr<TCPServer> TCPServerPtr;
+    UDPServerPtr udp4_server_;
+    UDPServerPtr udp6_server_;
+    TCPServerPtr tcp4_server_;
+    TCPServerPtr tcp6_server_;
+
+    // This member is used only for testing at the moment.
+    IOService::IOCallBack callback_;
+};
+
+IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char& port,
+                             const ip::address* const v4addr,
+                             const ip::address* const v6addr) :
+    auth_server_(auth_server),
+    udp4_server_(UDPServerPtr()), udp6_server_(UDPServerPtr()),
+    tcp4_server_(TCPServerPtr()), tcp6_server_(TCPServerPtr())
 {
-    ServerSet servers;
-    uint16_t portnum = atoi(port);
+    uint16_t portnum;
 
     try {
-        portnum = boost::lexical_cast<uint16_t>(port);
-    } catch (const std::exception& ex) {
-        isc_throw(FatalError, "[b10-auth] Invalid port number '"
-                              << port << "'");
-    }
-
-    if (address != NULL) {
-        asio::ip::address addr = asio::ip::address::from_string(address);
-
-        if ((addr.is_v6() && !use_ipv6)) {
-            isc_throw(FatalError,
-                      "[b10-auth] Error: -4 conflicts with " << addr);
-        }
-
-        if ((addr.is_v4() && !use_ipv4)) {
-            isc_throw(FatalError,
-                      "[b10-auth] Error: -6 conflicts with " << addr);
-        }
-
-        if (addr.is_v4()) {
-            servers.udp4_server = new UDPServer(auth_server, io_service_,
-                                                addr, portnum);
-            servers.tcp4_server = new TCPServer(auth_server, io_service_,
-                                                addr, portnum);
-         } else {
-            servers.udp6_server = new UDPServer(auth_server, io_service_,
-                                                addr, portnum);
-            servers.tcp6_server = new TCPServer(auth_server, io_service_,
-                                                addr, portnum);
-        }
-    } else {
-        if (use_ipv4) {
-            servers.udp4_server = new UDPServer(auth_server, io_service_,
-                                                AF_INET, portnum);
-            servers.tcp4_server = new TCPServer(auth_server, io_service_,
-                                                AF_INET, portnum);
-        }
-        if (use_ipv6) {
-            servers.udp6_server = new UDPServer(auth_server, io_service_,
-                                                AF_INET6, portnum);
-            servers.tcp6_server = new TCPServer(auth_server, io_service_,
-                                                AF_INET6, portnum);
-        }
-    }
-
-    // Now we don't have to worry about exception, and need to make sure that
-    // the server objects won't be accidentally cleaned up.
-    servers.udp4_server = NULL;
-    servers.udp6_server = NULL;
-    servers.tcp4_server = NULL;
-    servers.tcp6_server = NULL;
-}
-
-IOServiceImpl::~IOServiceImpl() {
-    delete udp4_server_;
-    delete udp6_server_;
-    delete tcp4_server_;
-    delete tcp6_server_;
-}
-
-IOService::IOService(AuthSrv* auth_server, const char* const address,
-                     const char* const port, const bool use_ipv4,
-                     const bool use_ipv6) {
-    impl_ = new IOServiceImpl(auth_server, address, port, use_ipv4, use_ipv6);
+        // XXX: SunStudio with stlport4 doesn't reject some invalid
+        // representation such as "-1" by lexical_cast<uint16_t>, so
+        // we convert it into a signed integer of a larger size and perform
+        // range check ourselves.
+        const int32_t portnum32 = boost::lexical_cast<int32_t>(&port);
+        if (portnum32 < 0 || portnum32 > 65535) {
+            isc_throw(IOError, "Invalid port number '" << &port);
+        }
+        portnum = portnum32;
+    } catch (const boost::bad_lexical_cast& ex) {
+        isc_throw(IOError, "Invalid port number '" << &port << "': " <<
+                  ex.what());
+    }
+
+    try {
+        if (v4addr != NULL) {
+            udp4_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
+                                                      *v4addr, portnum));
+            tcp4_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
+                                                      *v4addr, portnum));
+        }
+        if (v6addr != NULL) {
+            udp6_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
+                                                      *v6addr, portnum));
+            tcp6_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
+                                                      *v6addr, portnum));
+        }
+    } catch (const asio::system_error& err) {
+        // We need to catch and convert any ASIO level exceptions.
+        // This can happen for unavailable address, binding a privilege port
+        // without the privilege, etc.
+        isc_throw(IOError, "Failed to initialize network servers: " <<
+                  err.what());
+    }
+}
+
+IOService::IOService(AuthSrv* auth_server, const char& port,
+                     const char& address) :
+    impl_(NULL)
+{
+    error_code err;
+    const ip::address addr = ip::address::from_string(&address, err);
+    if (err) {
+        isc_throw(IOError, "Invalid IP address '" << &address << "': "
+                  << err.message());
+    }
+
+    impl_ = new IOServiceImpl(auth_server, port,
+                              addr.is_v4() ? &addr : NULL,
+                              addr.is_v6() ? &addr : NULL);
+}
+
+IOService::IOService(AuthSrv* auth_server, const char& port,
+                     const bool use_ipv4, const bool use_ipv6) :
+    impl_(NULL)
+{
+    const ip::address v4addr_any = ip::address(ip::address_v4::any());
+    const ip::address* const v4addrp = use_ipv4 ? &v4addr_any : NULL; 
+    const ip::address v6addr_any = ip::address(ip::address_v6::any());
+    const ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
+    impl_ = new IOServiceImpl(auth_server, port, v4addrp, v6addrp);
 }
 
 IOService::~IOService() {
@@ -483,4 +564,21 @@
 IOService::get_io_service() {
     return impl_->io_service_;
 }
-}
+
+void
+IOService::setCallBack(const IOCallBack callback) {
+    impl_->callback_ = callback;
+    if (impl_->udp4_server_ != NULL) {
+        impl_->udp4_server_->setCallBack(&impl_->callback_);
+    }
+    if (impl_->udp6_server_ != NULL) {
+        impl_->udp6_server_->setCallBack(&impl_->callback_);
+    }
+    if (impl_->tcp4_server_ != NULL) {
+        impl_->tcp4_server_->setCallBack(&impl_->callback_);
+    }
+    if (impl_->tcp6_server_ != NULL) {
+        impl_->tcp6_server_->setCallBack(&impl_->callback_);
+    }
+}
+}

Modified: branches/trac191/src/bin/auth/asio_link.h
==============================================================================
--- branches/trac191/src/bin/auth/asio_link.h (original)
+++ branches/trac191/src/bin/auth/asio_link.h Fri Jul 23 09:45:17 2010
@@ -17,20 +17,430 @@
 #ifndef __ASIO_LINK_H
 #define __ASIO_LINK_H 1
 
+// IMPORTANT NOTE: only very few ASIO headers files can be included in
+// this file.  In particular, asio.hpp should never be included here.
+// See the description of the namespace below.
+#include <unistd.h>             // for some network system calls
+#include <asio/ip/address.hpp>
+
+#include <functional>
+#include <string>
+
+#include <boost/function.hpp>
+
+#include <exceptions/exceptions.h>
+
+namespace asio {
+// forward declaration for IOService::get_io_service() below
+class io_service;
+}
+
 class AuthSrv;
+
+/// \namespace asio_link
+/// \brief A wrapper interface for the ASIO library.
+///
+/// The \c asio_link namespace is used to define a set of wrapper interfaces
+/// for the ASIO library.
+///
+/// BIND 10 uses the non-Boost version of ASIO because it's header-only,
+/// i.e., does not require a separate library object to be linked, and thus
+/// lowers the bar for introduction.
+///
+/// But the advantage comes with its own costs: since the header-only version
+/// includes more definitions in public header files, it tends to trigger
+/// more compiler warnings for our own sources, and, depending on the
+/// compiler options, may make the build fail.
+///
+/// We also found it may be tricky to use ASIO and standard C++ libraries
+/// in a single translation unit, i.e., a .cc file: depending on the order
+/// of including header files, ASIO may or may not work on some platforms.
+///
+/// This wrapper interface is intended to centralize these
+/// problematic issues in a single sub module.  Other BIND 10 modules should
+/// simply include \c asio_link.h and use the wrapper API instead of
+/// including ASIO header files and using ASIO-specific classes directly.
+///
+/// This wrapper may be used for other IO libraries if and when we want to
+/// switch, but generality for that purpose is not the primary goal of
+/// this module.  The resulting interfaces are thus straightforward mapping
+/// to the ASIO counterparts.
+///
+/// Notes to developers:
+/// Currently the wrapper interface is specific to the authoritative
+/// server implementation.  But the plan is to generalize it and have
+/// other modules use it.
+///
+/// One obvious drawback of this approach is performance overhead
+/// due to the additional layer.  We should eventually evaluate the cost
+/// of the wrapper abstraction in benchmark tests. Another drawback is
+/// that the wrapper interfaces don't provide all features of ASIO
+/// (at least for the moment).  We should also re-evaluate the
+/// maintenance overhead of providing necessary wrappers as we develop
+/// more.
+///
+/// On the other hand, we may be able to exploit the wrapper approach to
+/// simplify the interfaces (by limiting the usage) and unify performance
+/// optimization points.
+///
+/// As for optimization, we may want to provide a custom allocator for
+/// the placeholder of callback handlers:
+/// http://think-async.com/Asio/asio-1.3.1/doc/asio/reference/asio_handler_allocate.html
 
 namespace asio_link {
 struct IOServiceImpl;
 
+/// \brief An exception that is thrown if an error occurs within the IO
+/// module.  This is mainly intended to be a wrapper exception class for
+/// ASIO specific exceptions.
+class IOError : public isc::Exception {
+public:
+    IOError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+/// \brief The \c IOAddress class represents an IP addresses (version
+/// agnostic)
+///
+/// This class is a wrapper for the ASIO \c ip::address class.
+class IOAddress {
+public:
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// This class is copyable.  We use default versions of copy constructor
+    /// and the assignment operator.
+    /// We use the default destructor.
+    //@{
+    /// \brief Constructor from string.
+    ///
+    /// This constructor converts a textual representation of IPv4 and IPv6
+    /// addresses into an IOAddress object.
+    /// If \c address_str is not a valid representation of any type of
+    /// address, an exception of class \c IOError will be thrown.
+    /// This constructor allocates memory for the object, and if that fails
+    /// a corresponding standard exception will be thrown.
+    ///
+    /// \param address_str Textual representation of address.
+    IOAddress(const std::string& address_str);
+
+    /// \brief Constructor from an ASIO \c ip::address object.
+    ///
+    /// This constructor is intended to be used within the wrapper
+    /// implementation; user applications of the wrapper API won't use it.
+    ///
+    /// This constructor never throws an exception.
+    ///
+    /// \param asio_address The ASIO \c ip::address to be converted.
+    IOAddress(const asio::ip::address& asio_adress);
+    //@}
+
+    /// \brief Convert the address to a string.
+    ///
+    /// This method is basically expected to be exception free, but
+    /// generating the string will involve resource allocation,
+    /// and if it fails the corresponding standard exception will be thrown.
+    ///
+    /// \return A string representation of the address.
+    std::string toText() const;
+private:
+    asio::ip::address asio_address_;
+};
+
+/// \brief The \c IOEndpoint class is an abstract base class to represent
+/// a communication endpoint.
+///
+/// This class is a wrapper for the ASIO endpoint classes such as
+/// \c ip::tcp::endpoint and \c ip::udp::endpoint.
+///
+/// Derived class implementations are completely hidden within the
+/// implementation.  User applications only get access to concrete
+/// \c IOEndpoint objects via the abstract interfaces.
+class IOEndpoint {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOEndpoint(const IOEndpoint& source);
+    IOEndpoint& operator=(const IOEndpoint& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class
+    /// should never be instantiated (except as part of a derived class).
+    IOEndpoint() {}
+public:
+    /// The destructor.
+    virtual ~IOEndpoint() {}
+    //@}
+
+    /// \brief Returns the address of the endpoint.
+    ///
+    /// This method returns an IOAddress object corresponding to \c this
+    /// endpoint.
+    /// Note that the return value is a real object, not a reference or
+    /// a pointer.
+    /// This is aligned with the interface of the ASIO counterpart:
+    /// the \c address() method of \c ip::xxx::endpoint classes returns
+    /// an \c ip::address object.
+    /// This also means handling the address of an endpoint using this method
+    /// can be expensive.  If the address information is necessary in a
+    /// performance sensitive context and there's a more efficient interface
+    /// for that purpose, it's probably better to avoid using this method.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return A copy of \c IOAddress object corresponding to the endpoint.
+    virtual IOAddress getAddress() const = 0;
+
+    /// \brief A polymorphic factory of endpoint from address and port.
+    ///
+    /// This method creates a new instance of (a derived class of)
+    /// \c IOEndpoint object that identifies the pair of given address
+    /// and port.
+    /// The appropriate derived class is chosen based on the specified
+    /// transport protocol.  If the \c protocol doesn't specify a protocol
+    /// supported in this implementation, an exception of class \c IOError
+    /// will be thrown.
+    ///
+    /// Memory for the created object will be dynamically allocated.  It's
+    /// caller's responsibility to \c delete it later.
+    /// If resource allocation for the new object fails, a corresponding
+    /// standard exception will be thrown.
+    ///
+    /// \param protocol The transport protocol used for the endpoint.
+    /// Currently, only \c IPPROTO_UDP and \c IPPROTO_TCP can be specified.
+    /// \param address The (IP) address of the endpoint.
+    /// \param port The transport port number of the endpoint
+    /// \return A pointer to a newly created \c IOEndpoint object.
+    static const IOEndpoint* create(const int protocol,
+                                    const IOAddress& address,
+                                    const unsigned short port);
+};
+
+/// \brief The \c IOSocket class is an abstract base class to represent
+/// various types of network sockets.
+///
+/// This class is a wrapper for the ASIO socket classes such as
+/// \c ip::tcp::socket and \c ip::udp::socket.
+///
+/// Derived class implementations are completely hidden within the
+/// implementation.  User applications only get access to concrete
+/// \c IOSocket objects via the abstract interfaces.
+/// We may revisit this decision when we generalize the wrapper and more
+/// modules use it.  Also, at that point we may define a separate (visible)
+/// derived class for testing purposes rather than providing factory methods
+/// (i.e., getDummy variants below).
+class IOSocket {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOSocket(const IOSocket& source);
+    IOSocket& operator=(const IOSocket& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class
+    /// should never be instantiated (except as part of a derived class).
+    IOSocket() {}
+public:
+    /// The destructor.
+    virtual ~IOSocket() {}
+    //@}
+
+    /// \brief Return the "native" representation of the socket.
+    ///
+    /// In practice, this is the file descriptor of the socket for
+    /// UNIX-like systems so the current implementation simply uses
+    /// \c int as the type of the return value.
+    /// We may have to need revisit this decision later.
+    ///
+    /// In general, the application should avoid using this method;
+    /// it essentially discloses an implementation specific "handle" that
+    /// can change the internal state of the socket (consider the
+    /// application closes it, for example).
+    /// But we sometimes need to perform very low-level operations that
+    /// requires the native representation.  Passing the file descriptor
+    /// to a different process is one example.
+    /// This method is provided as a necessary evil for such limited purposes.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return The native representation of the socket.  This is the socket
+    /// file descriptor for UNIX-like systems.
+    virtual int getNative() const = 0;
+
+    /// \brief Return the transport protocol of the socket.
+    ///
+    /// Currently, it returns \c IPPROTO_UDP for UDP sockets, and
+    /// \c IPPROTO_TCP for TCP sockets.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return IPPROTO_UDP for UDP sockets
+    /// \return IPPROTO_TCP for TCP sockets
+    virtual int getProtocol() const = 0;
+
+    /// \brief Return a non-usable "dummy" UDP socket for testing.
+    ///
+    /// This is a class method that returns a "mock" of UDP socket.
+    /// This is not associated with any actual socket, and its only
+    /// responsibility is to return \c IPPROTO_UDP from \c getProtocol().
+    /// The only feasible usage of this socket is for testing so that
+    /// the test code can prepare some "UDP data" even without opening any
+    /// actual socket.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \return A reference to an \c IOSocket object whose \c getProtocol()
+    /// returns \c IPPROTO_UDP.
+    static IOSocket& getDummyUDPSocket();
+
+    /// \brief Return a non-usable "dummy" TCP socket for testing.
+    ///
+    /// See \c getDummyUDPSocket().  This method is its TCP version.
+    ///
+    /// \return A reference to an \c IOSocket object whose \c getProtocol()
+    /// returns \c IPPROTO_TCP.
+    static IOSocket& getDummyTCPSocket();
+};
+
+/// \brief The \c IOMessage class encapsulates an incoming message received
+/// on a socket.
+///
+/// An \c IOMessage object represents a tuple of a chunk of data
+/// (a UDP packet or some segment of TCP stream), the socket over which the
+/// data is passed, the information about the other end point of the
+/// communication, and perhaps more.
+///
+/// The current design and interfaces of this class is tentative.
+/// It only provides a minimal level of support that is necessary for
+/// the current implementation of the authoritative server.
+/// A future version of this class will definitely support more.
+class IOMessage {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOMessage(const IOMessage& source);
+    IOMessage& operator=(const IOMessage& source);
+public:
+    /// \brief Constructor from message information.
+    ///
+    /// This constructor needs to handle the ASIO \c ip::address class,
+    /// and is intended to be used within this wrapper implementation.
+    /// Once the \c IOMessage object is created, the application can
+    /// get access to the information via the wrapper interface such as
+    /// \c getRemoteAddress().
+    ///
+    /// This constructor never throws an exception.
+    ///
+    /// \param data A pointer to the message data.
+    /// \param data_size The size of the message data in bytes.
+    /// \param io_socket The socket over which the data is given.
+    /// \param remote_endpoint The other endpoint of the socket, that is,
+    /// the sender of the message.
+    IOMessage(const void* data, const size_t data_size, IOSocket& io_socket,
+              const IOEndpoint& remote_endpoint);
+    //@}
+
+    /// \brief Returns a pointer to the received data.
+    const void* getData() const { return (data_); }
+
+    /// \brief Returns the size of the received data in bytes.
+    size_t getDataSize() const { return (data_size_); }
+
+    /// \brief Returns the socket on which the message arrives.
+    const IOSocket& getSocket() const { return (io_socket_); }
+
+    /// \brief Returns the endpoint that sends the message.
+    const IOEndpoint& getRemoteEndpoint() const { return (remote_endpoint_); }
+private:
+    const void* data_;
+    const size_t data_size_;
+    IOSocket& io_socket_;
+    const IOEndpoint& remote_endpoint_;
+};
+
+/// \brief The \c IOService class is a wrapper for the ASIO \c io_service
+/// class.
+///
+/// Currently, the interface of this class is very specific to the
+/// authoritative server implementation as indicated in the signature of
+/// the constructor, but the plan is to generalize it so that other BIND 10
+/// modules can use this interface, too.
 class IOService {
-public:
-    IOService(AuthSrv* auth_server,
-              const char* const address, const char* const port,
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// These are currently very specific to the authoritative server
+    /// implementation.
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private, making this class non-copyable.
+    //@{
+private:
+    IOService(const IOService& source);
+    IOService& operator=(const IOService& source);
+public:
+    /// \brief The constructor with a specific IP address and port on which
+    /// the services listen on.
+    IOService(AuthSrv* auth_server, const char& port, const char& address);
+    /// \brief The constructor with a specific port on which the services
+    /// listen on.
+    ///
+    /// It effectively listens on "any" IPv4 and/or IPv6 addresses.
+    /// IPv4/IPv6 services will be available if and only if \c use_ipv4
+    /// or \c use_ipv6 is \c true, respectively.
+    IOService(AuthSrv* auth_server, const char& port,
               const bool use_ipv4, const bool use_ipv6);
+    /// \brief The destructor.
     ~IOService();
+    //@}
+
+    /// \brief Start the underlying event loop.
+    ///
+    /// This method does not return control to the caller until
+    /// the \c stop() method is called via some handler.
     void run();
+
+    /// \brief Stop the underlying event loop.
+    ///
+    /// This will return the control to the caller of the \c run() method.
     void stop();
+
+    /// \brief Return the native \c io_service object used in this wrapper.
+    ///
+    /// This is a short term work around to support other BIND 10 modules
+    /// that share the same \c io_service with the authoritative server.
+    /// It will eventually be removed once the wrapper interface is
+    /// generalized.
     asio::io_service& get_io_service();
+
+    /// \brief A functor(-like) class that specifies a custom call back
+    /// invoked from the event loop instead of the embedded authoritative
+    /// server callbacks.
+    ///
+    /// Currently, the callback is intended to be used only for testing
+    /// purposes.  But we'll need a generic callback type like this to
+    /// generalize the wrapper interface.
+    typedef boost::function<void(const IOMessage& io_message)> IOCallBack;
+
+    /// \brief Set the custom call back invoked from the event loop.
+    ///
+    /// Right now this method is only for testing, but will eventually be
+    /// generalized.
+    void setCallBack(IOCallBack callback);
 private:
     IOServiceImpl* impl_;
 };

Modified: branches/trac191/src/bin/auth/auth.spec.pre.in
==============================================================================
--- branches/trac191/src/bin/auth/auth.spec.pre.in (original)
+++ branches/trac191/src/bin/auth/auth.spec.pre.in Fri Jul 23 09:45:17 2010
@@ -5,7 +5,7 @@
     "config_data": [
       { "item_name": "database_file",
         "item_type": "string",
-        "item_optional": True,
+        "item_optional": true,
         "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
       }
     ],

Modified: branches/trac191/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/trac191/src/bin/auth/auth_srv.cc (original)
+++ branches/trac191/src/bin/auth/auth_srv.cc Fri Jul 23 09:45:17 2010
@@ -14,6 +14,8 @@
 
 // $Id$
 
+#include <netinet/in.h>
+
 #include <algorithm>
 #include <cassert>
 #include <iostream>
@@ -40,19 +42,23 @@
 
 #include <cc/data.h>
 
-#include "common.h"
-#include "auth_srv.h"
-
-#include <boost/lexical_cast.hpp>
+#include <xfr/xfrout_client.h>
+
+#include <auth/common.h>
+#include <auth/auth_srv.h>
+#include <auth/asio_link.h>
 
 using namespace std;
 
 using namespace isc;
+using namespace isc::cc;
 using namespace isc::datasrc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 using namespace isc::data;
 using namespace isc::config;
+using namespace isc::xfr;
+using namespace asio_link;
 
 class AuthSrvImpl {
 private:
@@ -60,12 +66,18 @@
     AuthSrvImpl(const AuthSrvImpl& source);
     AuthSrvImpl& operator=(const AuthSrvImpl& source);
 public:
-    AuthSrvImpl(const bool use_cache);
-
+    AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
+    ~AuthSrvImpl();
     isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
 
+    bool processNormalQuery(const IOMessage& io_message, Message& message,
+                            MessageRenderer& response_renderer);
+    bool processAxfrQuery(const IOMessage& io_message, Message& message,
+                            MessageRenderer& response_renderer);
+    bool processNotify(const IOMessage& io_message, Message& message, 
+                            MessageRenderer& response_renderer);
     std::string db_file_;
-    ModuleCCSession* cs_;
+    ModuleCCSession* config_session_;
     MetaDataSrc data_sources_;
     /// We keep a pointer to the currently running sqlite datasource
     /// so that we can specifically remove that one should the database
@@ -74,6 +86,11 @@
 
     bool verbose_mode_;
 
+    AbstractSession* xfrin_session_;
+
+    bool xfrout_connected_;
+    AbstractXfroutClient& xfrout_client_;
+
     /// Currently non-configurable, but will be.
     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
 
@@ -81,8 +98,12 @@
     isc::datasrc::HotCache cache_;
 };
 
-AuthSrvImpl::AuthSrvImpl(const bool use_cache) :
-    cs_(NULL), verbose_mode_(false)
+AuthSrvImpl::AuthSrvImpl(const bool use_cache,
+                         AbstractXfroutClient& xfrout_client) :
+    config_session_(NULL), verbose_mode_(false),
+    xfrin_session_(NULL),
+    xfrout_connected_(false),
+    xfrout_client_(xfrout_client)
 {
     // cur_datasrc_ is automatically initialized by the default constructor,
     // effectively being an empty (sqlite) data source.  once ccsession is up
@@ -95,8 +116,16 @@
     cache_.setEnabled(use_cache);
 }
 
-AuthSrv::AuthSrv(const bool use_cache) : impl_(new AuthSrvImpl(use_cache)) {
-}
+AuthSrvImpl::~AuthSrvImpl() {
+    if (xfrout_connected_) {
+        xfrout_client_.disconnect();
+        xfrout_connected_ = false;
+    }
+}
+
+AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client) :
+    impl_(new AuthSrvImpl(use_cache, xfrout_client))
+{}
 
 AuthSrv::~AuthSrv() {
     delete impl_;
@@ -125,8 +154,9 @@
     const Opcode& opcode = message.getOpcode();
     vector<QuestionPtr> questions;
 
-    // If this is an error to a query, we should also copy the question section.
-    if (opcode == Opcode::QUERY()) {
+    // If this is an error to a query or notify, we should also copy the
+    // question section.
+    if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
         questions.assign(message.beginQuestion(), message.endQuestion());
     }
 
@@ -147,8 +177,7 @@
 
     if (verbose_mode) {
         cerr << "[b10-auth] sending an error response (" <<
-            boost::lexical_cast<string>(renderer.getLength())
-             << " bytes):\n" << message.toText() << endl;
+            renderer.getLength() << " bytes):\n" << message.toText() << endl;
     }
 }
 }
@@ -164,20 +193,26 @@
 }
 
 void
-AuthSrv::setConfigSession(ModuleCCSession* cs) {
-    impl_->cs_ = cs;
+AuthSrv::setXfrinSession(AbstractSession* xfrin_session) {
+    impl_->xfrin_session_ = xfrin_session;
+}
+
+void
+AuthSrv::setConfigSession(ModuleCCSession* config_session) {
+    impl_->config_session_ = config_session;
 }
 
 ModuleCCSession*
 AuthSrv::configSession() const {
-    return (impl_->cs_);
+    return (impl_->config_session_);
 }
 
 bool
-AuthSrv::processMessage(InputBuffer& request_buffer, Message& message,
-                        MessageRenderer& response_renderer,
-                        const bool udp_buffer)
+AuthSrv::processMessage(const IOMessage& io_message, Message& message,
+                        MessageRenderer& response_renderer)
 {
+    InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
+
     // First, check the header part.  If we fail even for the base header,
     // just drop the message.
     try {
@@ -186,7 +221,8 @@
         // Ignore all responses.
         if (message.getHeaderFlag(MessageFlag::QR())) {
             if (impl_->verbose_mode_) {
-                cerr << "[b10-auth] received unexpected response, ignoring" << endl;
+                cerr << "[b10-auth] received unexpected response, ignoring"
+                     << endl;
             }
             return (false);
         }
@@ -199,8 +235,8 @@
         message.fromWire(request_buffer);
     } catch (const DNSProtocolError& error) {
         if (impl_->verbose_mode_) {
-            cerr << "[b10-auth] returning " <<  error.getRcode().toText() << ": "
-                 << error.what() << endl;
+            cerr << "[b10-auth] returning " <<  error.getRcode().toText()
+                 << ": " << error.what() << endl;
         }
         makeErrorMessage(message, response_renderer, error.getRcode(),
                          impl_->verbose_mode_);
@@ -220,8 +256,9 @@
 
     // Perform further protocol-level validation.
 
-    // In this implementation, we only support normal queries
-    if (message.getOpcode() != Opcode::QUERY()) {
+    if (message.getOpcode() == Opcode::NOTIFY()) {
+        return (impl_->processNotify(io_message, message, response_renderer));
+    } else if (message.getOpcode() != Opcode::QUERY()) {
         if (impl_->verbose_mode_) {
             cerr << "[b10-auth] unsupported opcode" << endl;
         }
@@ -236,6 +273,25 @@
         return (true);
     }
 
+    ConstQuestionPtr question = *message.beginQuestion();
+    const RRType &qtype = question->getType();
+    if (qtype == RRType::AXFR()) {
+        return (impl_->processAxfrQuery(io_message, message,
+                                        response_renderer));
+    } else if (qtype == RRType::IXFR()) {
+        makeErrorMessage(message, response_renderer, Rcode::NOTIMP(),
+                         impl_->verbose_mode_);
+        return (true);
+    } else {
+        return (impl_->processNormalQuery(io_message, message,
+                                          response_renderer));
+    }
+}
+
+bool
+AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
+                                MessageRenderer& response_renderer)
+{
     const bool dnssec_ok = message.isDNSSECSupported();
     const uint16_t remote_bufsize = message.getUDPSize();
 
@@ -246,26 +302,159 @@
     message.setUDPSize(AuthSrvImpl::DEFAULT_LOCAL_UDPSIZE);
 
     try {
-        Query query(message, impl_->cache_, dnssec_ok);
-        impl_->data_sources_.doQuery(query);
+        Query query(message, cache_, dnssec_ok);
+        data_sources_.doQuery(query);
     } catch (const Exception& ex) {
-        if (impl_->verbose_mode_) {
+        if (verbose_mode_) {
             cerr << "[b10-auth] Internal error, returning SERVFAIL: " <<
                 ex.what() << endl;
         }
         makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
-                         impl_->verbose_mode_);
-        return (true);
-    }
-
+                         verbose_mode_);
+        return (true);
+    }
+
+    const bool udp_buffer =
+        (io_message.getSocket().getProtocol() == IPPROTO_UDP);
     response_renderer.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
     message.toWire(response_renderer);
-    if (impl_->verbose_mode_) {
-        cerr << "[b10-auth] sending a response (" <<
-            boost::lexical_cast<string>(response_renderer.getLength())
+    if (verbose_mode_) {
+        cerr << "[b10-auth] sending a response ("
+             << response_renderer.getLength()
              << " bytes):\n" << message.toText() << endl;
     }
 
+    return (true);
+}
+
+
+bool
+AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
+                            MessageRenderer& response_renderer)
+{
+    if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
+        if (verbose_mode_) {
+            cerr << "[b10-auth] AXFR query over UDP isn't allowed" << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
+                         verbose_mode_);
+        return (true);
+    }
+
+    try {
+        if (!xfrout_connected_) {
+            xfrout_client_.connect();
+            xfrout_connected_ = true;
+        }
+        xfrout_client_.sendXfroutRequestInfo(
+            io_message.getSocket().getNative(),
+            io_message.getData(),
+            io_message.getDataSize());
+    } catch (const XfroutError& err) {
+        if (xfrout_connected_) {
+            // disconnect() may trigger an exception, but since we try it
+            // only if we've successfully opened it, it shouldn't happen in
+            // normal condition.  Should this occur, we'll propagate it to the
+            // upper layer.
+            xfrout_client_.disconnect();
+            xfrout_connected_ = false;
+        }
+        
+        if (verbose_mode_) {
+            cerr << "[b10-auth] Error in handling XFR request: " << err.what()
+                 << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(),
+                         verbose_mode_);
+        return (true);
+    }
+    return (false);
+}
+
+bool
+AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message, 
+                           MessageRenderer& response_renderer) 
+{
+    // The incoming notify must contain exactly one question for SOA of the
+    // zone name.
+    if (message.getRRCount(Section::QUESTION()) != 1) {
+        if (verbose_mode_) {
+                cerr << "[b10-auth] invalid number of questions in notify: "
+                     << message.getRRCount(Section::QUESTION()) << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
+                         verbose_mode_);
+        return (true);
+    }
+    ConstQuestionPtr question = *message.beginQuestion();
+    if (question->getType() != RRType::SOA()) {
+        if (verbose_mode_) {
+                cerr << "[b10-auth] invalid question RR type in notify: "
+                     << question->getType() << endl;
+        }
+        makeErrorMessage(message, response_renderer, Rcode::FORMERR(),
+                         verbose_mode_);
+        return (true);
+    }
+
+    // According to RFC 1996, rcode should be "no error" and AA bit should be
+    // on, but we don't check these conditions.  This behavior is compatible
+    // with BIND 9.
+
+    // TODO check with the conf-mgr whether current server is the auth of the
+    // zone
+
+    // In the code that follows, we simply ignore the notify if any internal
+    // error happens rather than returning (e.g.) SERVFAIL.  RFC 1996 is
+    // silent about such cases, but there doesn't seem to be anything we can
+    // improve at the primary server side by sending an error anyway.
+    if (xfrin_session_ == NULL) {
+        if (verbose_mode_) {
+            cerr << "[b10-auth] "
+                "session interface for xfrin is not available" << endl;
+        }
+        return (false);
+    }
+    
+    const string remote_ip_address =
+        io_message.getRemoteEndpoint().getAddress().toText();
+    static const string command_template_start =
+        "{\"command\": [\"notify\", {\"zone_name\" : \"";
+    static const string command_template_master = "\", \"master\" : \"";
+    static const string command_template_rrclass = "\", \"rrclass\" : \"";
+    static const string command_template_end = "\"}]}";
+
+    try {
+        ElementPtr notify_command = Element::fromJSON(
+                command_template_start + question->getName().toText() + 
+                command_template_master + remote_ip_address +
+                command_template_rrclass + question->getClass().toText() +
+                command_template_end);
+        const unsigned int seq =
+            xfrin_session_->group_sendmsg(notify_command, "Xfrin",
+                                          "*", "*");
+        ElementPtr env, answer, parsed_answer;
+        xfrin_session_->group_recvmsg(env, answer, false, seq);
+        int rcode;
+        parsed_answer = parseAnswer(rcode, answer);
+        if (rcode != 0) {
+            if (verbose_mode_) {
+                cerr << "[b10-auth] failed to notify Xfrin: "
+                     << parsed_answer->str() << endl; 
+            }
+            return (false);
+        }
+    } catch (const Exception& ex) {
+        if (verbose_mode_) {
+            cerr << "[b10-auth] failed to notify Xfrin: " << ex.what() << endl;
+        }
+        return (false);
+    }
+
+    message.makeResponse();
+    message.setHeaderFlag(MessageFlag::AA());
+    message.setRcode(Rcode::NOERROR());
+    message.toWire(response_renderer);
     return (true);
 }
 
@@ -277,10 +466,10 @@
     if (config && config->contains("database_file")) {
         db_file_ = config->get("database_file")->stringValue();
         final = config;
-    } else if (cs_ != NULL) {
+    } else if (config_session_ != NULL) {
         bool is_default;
         string item("database_file");
-        ElementPtr value = cs_->getValue(is_default, item);
+        ElementPtr value = config_session_->getValue(is_default, item);
         final = Element::createMap();
 
         // If the value is the default, and we are running from

Modified: branches/trac191/src/bin/auth/auth_srv.h
==============================================================================
--- branches/trac191/src/bin/auth/auth_srv.h (original)
+++ branches/trac191/src/bin/auth/auth_srv.h Fri Jul 23 09:45:17 2010
@@ -28,6 +28,14 @@
 class Message;
 class MessageRenderer;
 }
+
+namespace xfr {
+class AbstractXfroutClient;
+};
+}
+
+namespace asio_link {
+class IOMessage;
 }
 
 class AuthSrvImpl;
@@ -36,28 +44,49 @@
     ///
     /// \name Constructors, Assignment Operator and Destructor.
     ///
-    /// Note: The copy constructor and the assignment operator are intentionally
-    /// defined as private.
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private.
     //@{
 private:
     AuthSrv(const AuthSrv& source);
     AuthSrv& operator=(const AuthSrv& source);
 public:
-    explicit AuthSrv(const bool use_cache);
+    /// The constructor.
+    ///
+    /// \param use_cache Whether to enable hot spot cache for lookup results.
+    /// \param xfrout_client Communication interface with a separate xfrout
+    /// process.  It's normally a reference to an xfr::XfroutClient object,
+    /// but can refer to a local mock object for testing (or other
+    /// experimental) purposes.
+    AuthSrv(const bool use_cache,
+            isc::xfr::AbstractXfroutClient& xfrout_client);
     ~AuthSrv();
     //@}
     /// \return \c true if the \message contains a response to be returned;
     /// otherwise \c false.
-    bool processMessage(isc::dns::InputBuffer& request_buffer,
+    bool processMessage(const asio_link::IOMessage& io_message,
                         isc::dns::Message& message,
-                        isc::dns::MessageRenderer& response_renderer,
-                        bool udp_buffer);
+                        isc::dns::MessageRenderer& response_renderer);
     void setVerbose(bool on);
     bool getVerbose() const;
-    void serve(std::string zone_name);
     isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
     isc::config::ModuleCCSession* configSession() const;
-    void setConfigSession(isc::config::ModuleCCSession* cs);
+    void setConfigSession(isc::config::ModuleCCSession* config_session);
+
+    ///
+    /// Note: this interface is tentative.  We'll revisit the ASIO and session
+    /// frameworks, at which point the session will probably be passed on
+    /// construction of the server.
+    ///
+    /// \param xfrin_session A Session object over which NOTIFY message
+    /// information is exchanged with a XFRIN handler.
+    /// The session must be established before setting in the server
+    /// object.
+    /// Ownership isn't transferred: the caller is responsible for keeping
+    /// this object to be valid while the server object is working and for
+    /// disconnecting the session and destroying the object when the server
+    ///
+    void setXfrinSession(isc::cc::AbstractSession* xfrin_session);
 private:
     AuthSrvImpl* impl_;
 };

Modified: branches/trac191/src/bin/auth/main.cc
==============================================================================
--- branches/trac191/src/bin/auth/main.cc (original)
+++ branches/trac191/src/bin/auth/main.cc Fri Jul 23 09:45:17 2010
@@ -14,8 +14,6 @@
 
 // $Id$
 
-#include "config.h"
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -39,16 +37,19 @@
 #include <cc/data.h>
 #include <config/ccsession.h>
 
-#include "spec_config.h"
-#include "common.h"
-#include "auth_srv.h"
-#include "asio_link.h"
+#include <xfr/xfrout_client.h>
+
+#include <auth/spec_config.h>
+#include <auth/common.h>
+#include <auth/auth_srv.h>
+#include <auth/asio_link.h>
 
 using namespace std;
 using namespace isc::data;
 using namespace isc::cc;
 using namespace isc::config;
 using namespace isc::dns;
+using namespace isc::xfr;
 
 namespace {
 
@@ -86,7 +87,7 @@
 
 void
 usage() {
-    cerr << "Usage: b10-auth [-p port] [-4|-6] [-nv]" << endl;
+    cerr << "Usage: b10-auth [-a address] [-p port] [-4|-6] [-nv]" << endl;
     exit(1);
 }
 } // end of anonymous namespace
@@ -98,7 +99,7 @@
     const char* address = NULL;
     bool use_ipv4 = true, use_ipv6 = true, cache = true;
 
-    while ((ch = getopt(argc, argv, "46np:v")) != -1) {
+    while ((ch = getopt(argc, argv, "46a:np:v")) != -1) {
         switch (ch) {
         case '4':
             // Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
@@ -138,8 +139,19 @@
         usage();
     }
 
-    // initialize command channel
+    if ((!use_ipv4 || !use_ipv6) && address != NULL) {
+        cerr << "[b10-auth] Error: -4|-6 and -a can't coexist" << endl;
+        usage();
+    }
+
     int ret = 0;
+
+    // XXX: we should eventually pass io_service here.
+    Session* cc_session = NULL;
+    Session* xfrin_session = NULL;
+    bool xfrin_session_established = false; // XXX (see Trac #287)
+    ModuleCCSession* config_session = NULL;
+    XfroutClient xfrout_client(UNIX_SOCKET_FILE);
     try {
         string specfile;
         if (getenv("B10_FROM_BUILD")) {
@@ -149,26 +161,64 @@
             specfile = string(AUTH_SPECFILE_LOCATION);
         }
 
-        auth_server = new AuthSrv(cache);
+        auth_server = new AuthSrv(cache, xfrout_client);
         auth_server->setVerbose(verbose_mode);
-
-        io_service = new asio_link::IOService(auth_server, address, port,
-                                              use_ipv4, use_ipv6);
-
-        ModuleCCSession cs(specfile, io_service->get_io_service(),
-                           my_config_handler, my_command_handler);
-
-        auth_server->setConfigSession(&cs);
+        cout << "[b10-auth] Server created." << endl;
+
+        if (address != NULL) {
+            // XXX: we can only specify at most one explicit address.
+            // This also means the server cannot run in the dual address
+            // family mode if explicit addresses need to be specified.
+            // We don't bother to fix this problem, however.  The -a option
+            // is a short term workaround until we support dynamic listening
+            // port allocation.
+            io_service = new asio_link::IOService(auth_server, *port,
+                                                  *address);
+        } else {
+            io_service = new asio_link::IOService(auth_server, *port,
+                                                  use_ipv4, use_ipv6);
+        }
+        cout << "[b10-auth] IOService created." << endl;
+
+        cc_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Configuration session channel created." << endl;
+
+        config_session = new ModuleCCSession(specfile, *cc_session,
+                                             my_config_handler,
+                                             my_command_handler);
+        cout << "[b10-auth] Configuration channel established." << endl;
+
+        xfrin_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Xfrin session channel created." << endl;
+        xfrin_session->establish(NULL);
+        xfrin_session_established = true;
+        cout << "[b10-auth] Xfrin session channel established." << endl;
+
+        // XXX: with the current interface to asio_link we have to create
+        // auth_server before io_service while Session needs io_service.
+        // In a next step of refactoring we should make asio_link independent
+        // from auth_server, and create io_service, auth_server, and
+        // sessions in that order.
+        auth_server->setXfrinSession(xfrin_session);
+        auth_server->setConfigSession(config_session);
         auth_server->updateConfig(ElementPtr());
 
         cout << "[b10-auth] Server started." << endl;
         io_service->run();
     } catch (const std::exception& ex) {
-        cerr << "[b10-auth] " << ex.what() << endl;
+        cerr << "[b10-auth] Initialization failed: " << ex.what() << endl;
         ret = 1;
     }
 
+    if (xfrin_session_established) {
+        xfrin_session->disconnect();
+    }
+
+    delete xfrin_session;
+    delete config_session;
+    delete cc_session;
     delete io_service;
     delete auth_server;
+
     return (ret);
 }

Modified: branches/trac191/src/bin/auth/tests/Makefile.am
==============================================================================
--- branches/trac191/src/bin/auth/tests/Makefile.am (original)
+++ branches/trac191/src/bin/auth/tests/Makefile.am Fri Jul 23 09:45:17 2010
@@ -14,6 +14,7 @@
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
 run_unittests_SOURCES += auth_srv_unittest.cc
+run_unittests_SOURCES += asio_link_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
@@ -24,6 +25,8 @@
 run_unittests_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a
 run_unittests_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
+run_unittests_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a
+run_unittests_LDADD += $(top_builddir)/src/lib/xfr/.libs/libxfr.a
 endif
 
 noinst_PROGRAMS = $(TESTS)

Modified: branches/trac191/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/trac191/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/trac191/src/bin/auth/tests/auth_srv_unittest.cc Fri Jul 23 09:45:17 2010
@@ -14,6 +14,8 @@
 
 // $Id$
 
+#include <config.h>
+
 #include <gtest/gtest.h>
 
 #include <dns/buffer.h>
@@ -24,33 +26,105 @@
 #include <dns/rrtype.h>
 
 #include <cc/data.h>
+#include <cc/session.h>
+
+#include <xfr/xfrout_client.h>
 
 #include <auth/auth_srv.h>
+#include <auth/asio_link.h>
 
 #include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc::cc;
 using namespace isc::dns;
 using namespace isc::data;
+using namespace isc::xfr;
+using namespace asio_link;
 
 namespace {
-const char* CONFIG_TESTDB =
+const char* const CONFIG_TESTDB =
     "{\"database_file\": \"" TEST_DATA_DIR "/example.sqlite3\"}";
 // The following file must be non existent and must be non"creatable" (see
 // the sqlite3 test).
-const char* BADCONFIG_TESTDB =
+const char* const BADCONFIG_TESTDB =
     "{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}";
+const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
 
 class AuthSrvTest : public ::testing::Test {
+private:
+    class MockXfroutClient : public AbstractXfroutClient {
+    public:
+        MockXfroutClient() :
+            is_connected_(false), connect_ok_(true), send_ok_(true),
+            disconnect_ok_(true)
+        {}
+        virtual void connect();
+        virtual void disconnect();
+        virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+                                          uint16_t msg_len);
+        bool isConnected() const { return (is_connected_); }
+        void disableConnect() { connect_ok_ = false; }
+        void disableDisconnect() { disconnect_ok_ = false; }
+        void enableDisconnect() { disconnect_ok_ = true; }
+        void disableSend() { send_ok_ = false; }
+    private:
+        bool is_connected_;
+        bool connect_ok_;
+        bool send_ok_;
+        bool disconnect_ok_;
+    };
+
+    class MockSession : public AbstractSession {
+    public:
+        MockSession() :
+            // by default we return a simple "success" message.
+            msg_(Element::fromJSON("{\"result\": [0, \"SUCCESS\"]}")),
+            send_ok_(true), receive_ok_(true)
+        {}
+        virtual void establish(const char* socket_file);
+        virtual void disconnect();
+        virtual int group_sendmsg(ElementPtr msg, string group,
+                                  string instance, string to);
+        virtual bool group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+                                   bool nonblock, int seq);
+        virtual void subscribe(string group, string instance);
+        virtual void unsubscribe(string group, string instance);
+        virtual void startRead(boost::function<void()> read_callback);
+        virtual int reply(ElementPtr& envelope, ElementPtr& newmsg);
+        virtual bool hasQueuedMsgs();
+
+        void setMessage(ElementPtr msg) { msg_ = msg; }
+        void disableSend() { send_ok_ = false; }
+        void disableReceive() { receive_ok_ = false; }
+
+        ElementPtr sent_msg;
+        string msg_destination;
+    private:
+        ElementPtr msg_;
+        bool send_ok_;
+        bool receive_ok_;
+    };
+
 protected:
-    AuthSrvTest() : server(true), request_message(Message::RENDER),
+    AuthSrvTest() : server(true, xfrout),
+                    request_message(Message::RENDER),
                     parse_message(Message::PARSE), default_qid(0x1035),
                     opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
-                    qclass(RRClass::IN()), qtype(RRType::A()), ibuffer(NULL),
-                    request_obuffer(0), request_renderer(request_obuffer),
+                    qclass(RRClass::IN()), qtype(RRType::A()),
+                    io_message(NULL), endpoint(NULL), request_obuffer(0),
+                    request_renderer(request_obuffer),
                     response_obuffer(0), response_renderer(response_obuffer)
-    {}
+    {
+        server.setXfrinSession(&notify_session);
+    }
+    ~AuthSrvTest() {
+        delete io_message;
+        delete endpoint;
+    }
+    MockSession notify_session;
+    MockXfroutClient xfrout;
     AuthSrv server;
     Message request_message;
     Message parse_message;
@@ -59,15 +133,113 @@
     const Name qname;
     const RRClass qclass;
     const RRType qtype;
-    InputBuffer* ibuffer;
+    IOMessage* io_message;
+    const IOEndpoint* endpoint;
     OutputBuffer request_obuffer;
     MessageRenderer request_renderer;
     OutputBuffer response_obuffer;
     MessageRenderer response_renderer;
     vector<uint8_t> data;
 
-    void createDataFromFile(const char* const datafile);
+    void createDataFromFile(const char* const datafile, int protocol);
+    void createRequestMessage(const Opcode& opcode, const Name& request_name,
+                              const RRClass& rrclass, const RRType& rrtype);
+    void createRequestPacket(const Opcode& opcode, const Name& request_name,
+                             const RRClass& rrclass, const RRType& rrtype,
+                             int protocol);
+    void createRequestPacket(int protocol);
 };
+
+void
+AuthSrvTest::MockSession::establish(const char* socket_file UNUSED_PARAM) {}
+
+void
+AuthSrvTest::MockSession::disconnect() {}
+
+void
+AuthSrvTest::MockSession::subscribe(string group UNUSED_PARAM,
+                                    string instance UNUSED_PARAM)
+{}
+
+void
+AuthSrvTest::MockSession::unsubscribe(string group UNUSED_PARAM,
+                                      string instance UNUSED_PARAM)
+{}
+
+void
+AuthSrvTest::MockSession::startRead(
+    boost::function<void()> read_callback UNUSED_PARAM)
+{}
+
+int
+AuthSrvTest::MockSession::reply(ElementPtr& envelope UNUSED_PARAM,
+                                ElementPtr& newmsg UNUSED_PARAM)
+{
+    return (-1);
+}
+
+bool
+AuthSrvTest::MockSession::hasQueuedMsgs() {
+    return (false);
+}
+
+int
+AuthSrvTest::MockSession::group_sendmsg(ElementPtr msg, string group,
+                                        string instance UNUSED_PARAM,
+                                        string to UNUSED_PARAM)
+{
+    if (!send_ok_) {
+        isc_throw(XfroutError, "mock session send is disabled for test");
+    }
+
+    sent_msg = msg;
+    msg_destination = group;
+    return (0);
+}
+
+bool
+AuthSrvTest::MockSession::group_recvmsg(ElementPtr& envelope UNUSED_PARAM,
+                                        ElementPtr& msg,
+                                        bool nonblock UNUSED_PARAM,
+                                        int seq UNUSED_PARAM)
+{
+    if (!receive_ok_) {
+        isc_throw(XfroutError, "mock session receive is disabled for test");
+    }
+
+    msg = msg_;
+    return (true);
+}
+
+void
+AuthSrvTest::MockXfroutClient::connect() {
+    if (!connect_ok_) {
+        isc_throw(XfroutError, "xfrout connection disabled for test");
+    }
+    is_connected_ = true;
+}
+
+void
+AuthSrvTest::MockXfroutClient::disconnect() {
+    if (!disconnect_ok_) {
+        isc_throw(XfroutError,
+                  "closing xfrout connection is disabled for test");
+    }
+    is_connected_ = false;
+}
+
+int
+AuthSrvTest::MockXfroutClient::sendXfroutRequestInfo(
+    const int tcp_sock UNUSED_PARAM,
+    const void* msg_data UNUSED_PARAM,
+    const uint16_t msg_len UNUSED_PARAM)
+{
+    if (!send_ok_) {
+        isc_throw(XfroutError, "xfrout connection send is disabled for test");
+    }
+    return (0);
+}
+
 
 // These are flags to indicate whether the corresponding flag bit of the
 // DNS header is to be set in the test cases.  (Note that the flag values
@@ -81,12 +253,56 @@
 const unsigned int CD_FLAG = 0x40;
 
 void
-AuthSrvTest::createDataFromFile(const char* const datafile) {
-    delete ibuffer;
+AuthSrvTest::createDataFromFile(const char* const datafile,
+                                const int protocol = IPPROTO_UDP)
+{
+    delete io_message;
     data.clear();
 
+    delete endpoint;
+    endpoint = IOEndpoint::create(protocol,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
     UnitTestUtil::readWireData(datafile, data);
-    ibuffer = new InputBuffer(&data[0], data.size());
+    io_message = new IOMessage(&data[0], data.size(),
+                               protocol == IPPROTO_UDP ?
+                               IOSocket::getDummyUDPSocket() :
+                               IOSocket::getDummyTCPSocket(), *endpoint);
+}
+
+void
+AuthSrvTest::createRequestMessage(const Opcode& opcode,
+                                  const Name& request_name,
+                                  const RRClass& rrclass,
+                                  const RRType& rrtype)
+{
+    request_message.clear(Message::RENDER);
+    request_message.setOpcode(opcode);
+    request_message.setQid(default_qid);
+    request_message.addQuestion(Question(request_name, rrclass, rrtype));
+}
+
+void
+AuthSrvTest::createRequestPacket(const Opcode& opcode,
+                                 const Name& request_name,
+                                 const RRClass& rrclass, const RRType& rrtype,
+                                 const int protocol = IPPROTO_UDP)
+{
+    createRequestMessage(opcode, request_name, rrclass, rrtype);
+    createRequestPacket(protocol);
+}
+
+void
+AuthSrvTest::createRequestPacket(const int protocol = IPPROTO_UDP) {
+    request_message.toWire(request_renderer);
+
+    delete io_message;
+    endpoint = IOEndpoint::create(protocol,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
+    io_message = new IOMessage(request_renderer.getData(),
+                               request_renderer.getLength(),
+                               protocol == IPPROTO_UDP ?
+                               IOSocket::getDummyUDPSocket() :
+                               IOSocket::getDummyTCPSocket(), *endpoint);
 }
 
 void
@@ -115,15 +331,19 @@
 
 // Unsupported requests.  Should result in NOTIMP.
 TEST_F(AuthSrvTest, unsupportedRequest) {
-    for (unsigned int i = 1; i < 16; ++i) {
+    for (unsigned int i = 0; i < 16; ++i) {
         // set Opcode to 'i', which iterators over all possible codes except
-        // the standard query (0)
+        // the standard query and notify
+        if (i == Opcode::QUERY().getCode() ||
+            i == Opcode::NOTIFY().getCode()) {
+            continue;
+        }
         createDataFromFile("simplequery_fromWire");
         data[2] = ((i << 3) & 0xff);
 
         parse_message.clear(Message::PARSE);
-        EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                              response_renderer, true));
+        EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                              response_renderer));
         headerCheck(parse_message, default_qid, Rcode::NOTIMP(), i, QR_FLAG,
                     0, 0, 0, 0);
     }
@@ -141,8 +361,8 @@
 // Multiple questions.  Should result in FORMERR.
 TEST_F(AuthSrvTest, multiQuestion) {
     createDataFromFile("multiquestion_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
                 QR_FLAG, 2, 0, 0, 0);
 
@@ -162,8 +382,8 @@
 // dropped.
 TEST_F(AuthSrvTest, shortMessage) {
     createDataFromFile("shortmessage_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 }
 
 // Response messages.  Must be silently dropped, whether it's a valid response
@@ -171,26 +391,26 @@
 TEST_F(AuthSrvTest, response) {
     // A valid (although unusual) response
     createDataFromFile("simpleresponse_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 
     // A response with a broken question section.  must be dropped rather than
     // returning FORMERR.
     createDataFromFile("shortresponse_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 
     // A response to iquery.  must be dropped rather than returning NOTIMP.
     createDataFromFile("iqueryresponse_fromWire");
-    EXPECT_EQ(false, server.processMessage(*ibuffer, parse_message,
-                                           response_renderer, true));
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
 }
 
 // Query with a broken question
 TEST_F(AuthSrvTest, shortQuestion) {
     createDataFromFile("shortquestion_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     // Since the query's question is broken, the question section of the
     // response should be empty.
     headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
@@ -200,8 +420,8 @@
 // Query with a broken answer section
 TEST_F(AuthSrvTest, shortAnswer) {
     createDataFromFile("shortanswer_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
 
     // This is a bogus query, but question section is valid.  So the response
     // should copy the question section.
@@ -219,8 +439,8 @@
 // Query with unsupported version of EDNS.
 TEST_F(AuthSrvTest, ednsBadVers) {
     createDataFromFile("queryBadEDNS_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
 
     // The response must have an EDNS OPT RR in the additional section.
     // Note that the DNSSEC DO bit is cleared even if this bit in the query
@@ -231,6 +451,242 @@
     EXPECT_FALSE(parse_message.isDNSSECSupported());
 }
 
+TEST_F(AuthSrvTest, AXFROverUDP) {
+    // AXFR over UDP is invalid and should result in FORMERR.
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(),
+                QR_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, AXFRSuccess) {
+    EXPECT_FALSE(xfrout.isConnected());
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    // On success, the AXFR query has been passed to a separate process,
+    // so we shouldn't have to respond.
+    EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
+                                           response_renderer));
+    EXPECT_TRUE(xfrout.isConnected());
+}
+
+TEST_F(AuthSrvTest, AXFRConnectFail) {
+    EXPECT_FALSE(xfrout.isConnected()); // check prerequisite
+    xfrout.disableConnect();
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    EXPECT_TRUE(server.processMessage(*io_message, parse_message,
+                                      response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+    EXPECT_FALSE(xfrout.isConnected());
+}
+
+TEST_F(AuthSrvTest, AXFRSendFail) {
+    // first send a valid query, making the connection with the xfr process
+    // open.
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    server.processMessage(*io_message, parse_message, response_renderer);
+    EXPECT_TRUE(xfrout.isConnected());
+
+    xfrout.disableSend();
+    parse_message.clear(Message::PARSE);
+    response_renderer.clear();
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    EXPECT_TRUE(server.processMessage(*io_message, parse_message,
+                                      response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+
+    // The connection should have been closed due to the send failure.
+    EXPECT_FALSE(xfrout.isConnected());
+}
+
+TEST_F(AuthSrvTest, AXFRDisconnectFail) {
+    // In our usage disconnect() shouldn't fail.  So we'll see the exception
+    // should it be thrown.
+    xfrout.disableSend();
+    xfrout.disableDisconnect();
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    EXPECT_THROW(server.processMessage(*io_message, parse_message,
+                                       response_renderer),
+                 XfroutError);
+    EXPECT_TRUE(xfrout.isConnected());
+    // XXX: we need to re-enable disconnect.  otherwise an exception would be
+    // thrown via the destructor of the server.
+    xfrout.enableDisconnect();
+}
+
+TEST_F(AuthSrvTest, notify) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+
+    // An internal command message should have been created and sent to an
+    // external module.  Check them.
+    EXPECT_EQ("Xfrin", notify_session.msg_destination);
+    EXPECT_EQ("notify",
+              notify_session.sent_msg->get("command")->get(0)->stringValue());
+    ElementPtr notify_args = notify_session.sent_msg->get("command")->get(1);
+    EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
+    EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
+              notify_args->get("master")->stringValue());
+    EXPECT_EQ("IN", notify_args->get("rrclass")->stringValue());
+
+    // On success, the server should return a response to the notify.
+    headerCheck(parse_message, default_qid, Rcode::NOERROR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
+
+    // The question must be identical to that of the received notify
+    ConstQuestionPtr question = *parse_message.beginQuestion();
+    EXPECT_EQ(Name("example.com"), question->getName());
+    EXPECT_EQ(RRClass::IN(), question->getClass());
+    EXPECT_EQ(RRType::SOA(), question->getType());
+}
+
+TEST_F(AuthSrvTest, notifyForCHClass) {
+    // Same as the previous test, but for the CH RRClass.
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::CH(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+
+    // Other conditions should be the same, so simply confirm the RR class is
+    // set correctly.
+    ElementPtr notify_args = notify_session.sent_msg->get("command")->get(1);
+    EXPECT_EQ("CH", notify_args->get("rrclass")->stringValue());
+}
+
+TEST_F(AuthSrvTest, notifyEmptyQuestion) {
+    request_message.clear(Message::RENDER);
+    request_message.setOpcode(Opcode::NOTIFY());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    request_message.setQid(default_qid);
+    request_message.toWire(request_renderer);
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG, 0, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyMultiQuestions) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    // add one more SOA question
+    request_message.addQuestion(Question(Name("example.com"), RRClass::IN(),
+                                         RRType::SOA()));
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG, 2, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyNonSOAQuestion) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::NS());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::FORMERR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyWithoutAA) {
+    // implicitly leave the AA bit off.  our implementation will accept it.
+    createRequestPacket(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::NOERROR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyWithErrorRcode) {
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    request_message.setRcode(Rcode::SERVFAIL());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::NOERROR(),
+                Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, notifyWithoutSession) {
+    server.setXfrinSession(NULL);
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+
+    // we simply ignore the notify and let it be resent if an internal error
+    // happens.
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifySendFail) {
+    notify_session.disableSend();
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifyReceiveFail) {
+    notify_session.disableReceive();
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
+    notify_session.setMessage(Element::fromJSON("{\"foo\": 1}"));
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
+TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
+    notify_session.setMessage(
+        Element::fromJSON("{\"result\": [1, \"FAIL\"]}"));
+
+    createRequestMessage(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
+                        RRType::SOA());
+    request_message.setHeaderFlag(MessageFlag::AA());
+    createRequestPacket(IPPROTO_UDP);
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                       response_renderer));
+}
+
 void
 updateConfig(AuthSrv* server, const char* const dbfile,
              const bool expect_success)
@@ -253,8 +709,8 @@
     // response should have the AA flag on, and have an RR in each answer
     // and authority section.
     createDataFromFile("examplequery_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
                 QR_FLAG | AA_FLAG, 1, 1, 1, 0);
 }
@@ -267,10 +723,10 @@
     // in a SERVFAIL response, and the answer and authority sections should
     // be empty.
     createDataFromFile("badExampleQuery_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
-    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(), opcode.getCode(),
-                QR_FLAG, 1, 0, 0, 0);
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
+    headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
 }
 
 TEST_F(AuthSrvTest, updateConfigFail) {
@@ -282,8 +738,8 @@
 
     // The original data source should still exist.
     createDataFromFile("examplequery_fromWire");
-    EXPECT_EQ(true, server.processMessage(*ibuffer, parse_message,
-                                          response_renderer, true));
+    EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
+                                          response_renderer));
     headerCheck(parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
                 QR_FLAG | AA_FLAG, 1, 1, 1, 0);
 }

Modified: branches/trac191/src/bin/bindctl/bindcmd.py
==============================================================================
--- branches/trac191/src/bin/bindctl/bindcmd.py (original)
+++ branches/trac191/src/bin/bindctl/bindcmd.py Fri Jul 23 09:45:17 2010
@@ -35,7 +35,7 @@
 import getpass
 from hashlib import sha1
 import csv
-import ast
+import json
 import pwd
 import getpass
 import traceback
@@ -568,7 +568,7 @@
                 else:
                     parsed_value = None
                     try:
-                        parsed_value = ast.literal_eval(cmd.params['value'])
+                        parsed_value = json.loads(cmd.params['value'])
                     except Exception as exc:
                         # ok could be an unquoted string, interpret as such
                         parsed_value = cmd.params['value']

Modified: branches/trac191/src/bin/cmdctl/TODO
==============================================================================
--- branches/trac191/src/bin/cmdctl/TODO (original)
+++ branches/trac191/src/bin/cmdctl/TODO Fri Jul 23 09:45:17 2010
@@ -3,4 +3,5 @@
 . Add check for the content of key/certificate file
   (when cmdctl starts or is configured by bindctl).
 . Use only one msgq/session to communicate with other modules?
-
+. Add more test cases, especially about the cases where CmdctlException
+  is raised

Modified: branches/trac191/src/bin/cmdctl/cmdctl.py.in
==============================================================================
--- branches/trac191/src/bin/cmdctl/cmdctl.py.in (original)
+++ branches/trac191/src/bin/cmdctl/cmdctl.py.in Fri Jul 23 09:45:17 2010
@@ -441,7 +441,11 @@
                  CommandControlClass,
                  idle_timeout = 1200, verbose = False):
         '''idle_timeout: the max idle time for login'''
-        http.server.HTTPServer.__init__(self, server_address, RequestHandlerClass)
+        try:
+            http.server.HTTPServer.__init__(self, server_address, RequestHandlerClass)
+        except socket.error as err:
+            raise CmdctlException("Error creating server, because: %s \n" % str(err))
+
         self.user_sessions = {}
         self.idle_timeout = idle_timeout
         self.cmdctl = CommandControlClass(self, verbose)
@@ -587,20 +591,23 @@
             help="display more about what is going on")
 
 if __name__ == '__main__':
+    set_signal_handler()
+    parser = OptionParser(version = __version__)
+    set_cmd_options(parser)
+    (options, args) = parser.parse_args()
+    result = 1                  # in case of failure
     try:
-        set_signal_handler()
-        parser = OptionParser(version = __version__)
-        set_cmd_options(parser)
-        (options, args) = parser.parse_args()
         run(options.addr, options.port, options.idle_timeout, options.verbose)
-    except isc.cc.SessionError as se:
+        result = 0
+    except isc.cc.SessionError as err:
         sys.stderr.write("[b10-cmdctl] Error creating b10-cmdctl, "
-                "is the command channel daemon running?\n")        
+                         "is the command channel daemon running?\n")        
     except KeyboardInterrupt:
-        sys.stderr.write("[b10-cmdctl] exit http server\n")
+        sys.stderr.write("[b10-cmdctl] exit from Cmdctl\n")
+    except CmdctlException as err:
+        sys.stderr.write("[b10-cmdctl] " + str(err) + "\n")
 
     if httpd:
         httpd.shutdown()
 
-
-
+    sys.exit(result)

Modified: branches/trac191/src/bin/cmdctl/cmdctl.spec.pre.in
==============================================================================
--- branches/trac191/src/bin/cmdctl/cmdctl.spec.pre.in (original)
+++ branches/trac191/src/bin/cmdctl/cmdctl.spec.pre.in Fri Jul 23 09:45:17 2010
@@ -6,20 +6,20 @@
       {
         "item_name": "key_file",
         "item_type": "string",
-        "item_optional": False,
-        "item_default": '@@SYSCONFDIR@@/@PACKAGE@/cmdctl-keyfile.pem'
+        "item_optional": false,
+        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-keyfile.pem"
       },
       {
         "item_name": "cert_file",
         "item_type": "string",
-        "item_optional": False,
-        "item_default": '@@SYSCONFDIR@@/@PACKAGE@/cmdctl-certfile.pem'
+        "item_optional": false,
+        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-certfile.pem"
       },
       {
         "item_name": "accounts_file",
         "item_type": "string",
-        "item_optional": False,
-        "item_default": '@@SYSCONFDIR@@/@PACKAGE@/cmdctl-accounts.csv'
+        "item_optional": false,
+        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-accounts.csv"
       }
     ],
     "commands": [
@@ -32,7 +32,7 @@
         "command_name": "shutdown",
         "command_description": "shutdown cmdctl",
         "command_args": []
-      },
+      }
     ]
   }
 }

Modified: branches/trac191/src/bin/cmdctl/tests/cmdctl_test.py
==============================================================================
--- branches/trac191/src/bin/cmdctl/tests/cmdctl_test.py (original)
+++ branches/trac191/src/bin/cmdctl/tests/cmdctl_test.py Fri Jul 23 09:45:17 2010
@@ -17,6 +17,7 @@
 import unittest
 import socket
 import tempfile
+import sys
 from cmdctl import *
 
 SPEC_FILE_PATH = '..' + os.sep
@@ -383,13 +384,31 @@
 class TestSecureHTTPServer(unittest.TestCase):
     def setUp(self):
         self.old_stdout = sys.stdout
+        self.old_stderr = sys.stderr
         sys.stdout = open(os.devnull, 'w')
+        sys.stderr = sys.stdout
         self.server = MySecureHTTPServer(('localhost', 8080), 
                                          MySecureHTTPRequestHandler,
                                          MyCommandControl, verbose=True)
 
     def tearDown(self):
         sys.stdout = self.old_stdout
+        sys.stderr = self.old_stderr
+
+    def test_addr_in_use(self):
+        server_one = None
+        try:
+            server_one = SecureHTTPServer(('localhost', 53531),
+                                        MySecureHTTPRequestHandler,
+                                        MyCommandControl)
+        except CmdctlException:
+            pass
+        else:
+            self.assertRaises(CmdctlException, SecureHTTPServer,
+                              ('localhost', 53531),
+                              MySecureHTTPRequestHandler, MyCommandControl)
+        if server_one:
+            server_one.server_close()
 
     def test_create_user_info(self):
         self.server._create_user_info('/local/not-exist')

Modified: branches/trac191/src/bin/host/host.cc
==============================================================================
--- branches/trac191/src/bin/host/host.cc (original)
+++ branches/trac191/src/bin/host/host.cc Fri Jul 23 09:45:17 2010
@@ -24,14 +24,14 @@
 #include <string>
 #include <iostream>
 
-#include "dns/buffer.h"
-#include "dns/name.h"
-#include "dns/message.h"
-#include "dns/messagerenderer.h"
-#include "dns/rrclass.h"
-#include "dns/rrtype.h"
-#include "dns/rrset.h"
-#include "dns/message.h"
+#include <dns/buffer.h>
+#include <dns/name.h>
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/rrset.h>
+#include <dns/message.h>
 
 using namespace std;
 using namespace isc::dns;

Modified: branches/trac191/src/bin/xfrin/tests/xfrin_test.py
==============================================================================
--- branches/trac191/src/bin/xfrin/tests/xfrin_test.py (original)
+++ branches/trac191/src/bin/xfrin/tests/xfrin_test.py Fri Jul 23 09:45:17 2010
@@ -412,21 +412,30 @@
         return self.xfr._parse_cmd_params(self.args)
 
     def test_parse_cmd_params(self):
-        name, master_addrinfo, db_file = self._do_parse()
+        name, rrclass, master_addrinfo, db_file = self._do_parse()
         self.assertEqual(master_addrinfo[4][1], int(TEST_MASTER_PORT))
         self.assertEqual(name, TEST_ZONE_NAME)
+        self.assertEqual(rrclass, TEST_RRCLASS)
         self.assertEqual(master_addrinfo[4][0], TEST_MASTER_IPV4_ADDRESS)
         self.assertEqual(db_file, TEST_DB_FILE)
 
     def test_parse_cmd_params_default_port(self):
         del self.args['port']
-        master_addrinfo = self._do_parse()[1]
+        master_addrinfo = self._do_parse()[2]
         self.assertEqual(master_addrinfo[4][1], 53)
 
     def test_parse_cmd_params_ip6master(self):
         self.args['master'] = TEST_MASTER_IPV6_ADDRESS
-        master_addrinfo = self._do_parse()[1]
+        master_addrinfo = self._do_parse()[2]
         self.assertEqual(master_addrinfo[4][0], TEST_MASTER_IPV6_ADDRESS)
+
+    def test_parse_cmd_params_chclass(self):
+        self.args['rrclass'] = 'CH'
+        self.assertEqual(self._do_parse()[1], RRClass.CH())
+
+    def test_parse_cmd_params_bogusclass(self):
+        self.args['rrclass'] = 'XXX'
+        self.assertRaises(XfrinException, self._do_parse)
 
     def test_parse_cmd_params_nozone(self):
         # zone name is mandatory.
@@ -504,6 +513,13 @@
         self.assertEqual(self.xfr.command_handler("refresh",
                                                   self.args)['result'][0], 0)
 
+    def test_command_handler_notify(self):
+        # at this level, refresh is no different than retransfer.
+        self.args['master'] = TEST_MASTER_IPV6_ADDRESS
+        # ...but right now we disable the feature due to security concerns.
+        self.assertEqual(self.xfr.command_handler("notify",
+                                                  self.args)['result'][0], 1)
+
     def test_command_handler_unknown(self):
         self.assertEqual(self.xfr.command_handler("xxx", None)['result'][0], 1)
 

Modified: branches/trac191/src/bin/xfrin/xfrin.py.in
==============================================================================
--- branches/trac191/src/bin/xfrin/xfrin.py.in (original)
+++ branches/trac191/src/bin/xfrin/xfrin.py.in Fri Jul 23 09:45:17 2010
@@ -404,13 +404,36 @@
             if command == 'shutdown':
                 self._shutdown_event.set()
             elif command == 'retransfer' or command == 'refresh':
-                # The default RR class is IN.  We should fix this so that
-                # the class is passed in the command arg (where we specify
-                # the default)
-                rrclass = RRClass.IN()
-                zone_name, master_addr, db_file = self._parse_cmd_params(args)
-                ret = self.xfrin_start(zone_name, rrclass, db_file, master_addr,
+                (zone_name, rrclass,
+                 master_addr, db_file) = self._parse_cmd_params(args)
+                ret = self.xfrin_start(zone_name, rrclass, db_file,
+                                       master_addr,
                                    False if command == 'retransfer' else True)
+                answer = create_answer(ret[0], ret[1])
+            elif command == 'notify':
+                # This is the temporary implementation for notify.
+                # actually the notfiy command should be sent to the
+                # Zone Manager module.  Being temporary, we separate this case
+                # from refresh/retransfer while we could (and should otherwise)
+                # share the code.
+                (zone_name, rrclass,
+                 master_addr, db_file) = self._parse_cmd_params(args)
+
+                # XXX: master_addr is the sender of the notify message.
+                # It's very dangerous to naively trust it as the source of
+                # subsequent zone transfer; any remote node can easily exploit
+                # it to mount zone poisoning or DoS attacks.  We should
+                # locally identify the appropriate set of master servers.
+                # For now, we disable the code below.
+                master_is_valid = False
+
+                if master_is_valid:
+                    ret = self.xfrin_start(zone_name, rrclass, db_file,
+                                           master_addr, True)
+                else:
+                    errmsg = 'Failed to validate the master address ('
+                    errmsg += args['master'] + '), ignoring notify'
+                    ret = [1, errmsg]
                 answer = create_answer(ret[0], ret[1])
             else:
                 answer = create_answer(1, 'unknown command: ' + command)
@@ -424,6 +447,18 @@
         zone_name = args.get('zone_name')
         if not zone_name:
             raise XfrinException('zone name should be provided')
+
+        rrclass = args.get('rrclass')
+        if not rrclass:
+            # The default RR class is IN.  We should fix this so that
+            # the class is always passed in the command arg (where we specify
+            # the default)
+            rrclass = RRClass.IN()
+        else:
+            try:
+                rrclass = RRClass(rrclass)
+            except InvalidRRClass as e:
+                raise XfrinException('invalid RRClass: ' + rrclass)
 
         master = args.get('master')
         if not master:
@@ -450,7 +485,7 @@
                 db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3"
             self._cc.remove_remote_config(AUTH_SPECFILE_LOCATION)
 
-        return (zone_name, master_addrinfo, db_file)
+        return (zone_name, rrclass, master_addrinfo, db_file)
 
     def startup(self):
         while not self._shutdown_event.is_set():

Modified: branches/trac191/src/bin/xfrin/xfrin.spec.pre.in
==============================================================================
--- branches/trac191/src/bin/xfrin/xfrin.spec.pre.in (original)
+++ branches/trac191/src/bin/xfrin/xfrin.spec.pre.in Fri Jul 23 09:45:17 2010
@@ -6,37 +6,37 @@
       {
         "item_name": "transfers_in",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 10
       }
     ],
     "commands": [
      {
-        'command_name': 'retransfer',
-        "command_description": 'retransfer a single zone without checking zone serial number',
-        'command_args': [ {
+        "command_name": "retransfer",
+        "command_description": "retransfer a single zone without checking zone serial number",
+        "command_args": [ {
             "item_name": "zone_name",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           {
             "item_name": "master",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": ""
           },
           {
             "item_name": "port",
             "item_type": "integer",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": 53
           },
           {
             "item_name": "db_file",
             "item_type": "string",
-            "item_optional": True,
-            "item_default": '@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3'
+            "item_optional": true,
+            "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
           }
         ]
       },

Modified: branches/trac191/src/bin/xfrout/xfrout.spec.pre.in
==============================================================================
--- branches/trac191/src/bin/xfrout/xfrout.spec.pre.in (original)
+++ branches/trac191/src/bin/xfrout/xfrout.spec.pre.in Fri Jul 23 09:45:17 2010
@@ -5,43 +5,43 @@
        {
          "item_name": "transfers_out",
          "item_type": "integer",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": 10
        },
        {
          "item_name": "db_file",
          "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
        },
        {
          "item_name": "log_name",
          "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": "Xfrout"
        },
        {
          "item_name": "log_file",
     	 "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
          "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/log/Xfrout.log"
        },
        {
          "item_name": "log_severity",
     	 "item_type": "string",
-         "item_optional": False,
+         "item_optional": false,
     	 "item_default": "debug"
        },
        {
          "item_name": "log_versions",
     	 "item_type": "integer",
-         "item_optional": False,
+         "item_optional": false,
     	 "item_default": 5
        },
        {
          "item_name": "log_max_bytes",
     	 "item_type": "integer",
-         "item_optional": False,
+         "item_optional": false,
     	 "item_default": 1048576
        }
       ],

Modified: branches/trac191/src/lib/cc/data.cc
==============================================================================
--- branches/trac191/src/lib/cc/data.cc (original)
+++ branches/trac191/src/lib/cc/data.cc Fri Jul 23 09:45:17 2010
@@ -14,9 +14,9 @@
 
 // $Id$
 
-#include "config.h"
-
-#include "data.h"
+#include <config.h>
+
+#include <cc/data.h>
 
 #include <cassert>
 #include <climits>

Modified: branches/trac191/src/lib/cc/session.cc
==============================================================================
--- branches/trac191/src/lib/cc/session.cc (original)
+++ branches/trac191/src/lib/cc/session.cc Fri Jul 23 09:45:17 2010
@@ -15,7 +15,7 @@
 // $Id$
 
 #include <config.h>
-#include "session_config.h"
+#include <cc/session_config.h>
 
 #include <stdint.h>
 
@@ -42,8 +42,8 @@
 
 #include <exceptions/exceptions.h>
 
-#include "data.h"
-#include "session.h"
+#include <cc/data.h>
+#include <cc/session.h>
 
 using namespace std;
 using namespace isc::cc;
@@ -52,44 +52,26 @@
 // some of the asio names conflict with socket API system calls
 // (e.g. write(2)) so we don't import the entire asio namespace.
 using asio::io_service;
-using asio::ip::tcp;
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 
 namespace isc {
 namespace cc {
-
 class SessionImpl {
 public:
-    SessionImpl() : sequence_(-1) { queue_ = Element::createList(); }
-    virtual ~SessionImpl() {}
-    virtual void establish(const char& socket_file) = 0;
-    virtual int getSocket() = 0;
-    virtual void disconnect() = 0;
-    virtual void writeData(const void* data, size_t datalen) = 0;
-    virtual size_t readDataLength() = 0;
-    virtual void readData(void* data, size_t datalen) = 0;
-    virtual void startRead(boost::function<void()> user_handler) = 0;
-    
+    SessionImpl(io_service& io_service) :
+        sequence_(-1), queue_(Element::createList()),
+        io_service_(io_service), socket_(io_service_), data_length_(0)
+    {}
+    void establish(const char& socket_file);
+    void disconnect();
+    void writeData(const void* data, size_t datalen);
+    size_t readDataLength();
+    void readData(void* data, size_t datalen);
+    void startRead(boost::function<void()> user_handler);
+
     long int sequence_; // the next sequence number to use
     std::string lname_;
     ElementPtr queue_;
-};
-
-class ASIOSession : public SessionImpl {
-public:
-    ASIOSession(io_service& io_service) :
-        io_service_(io_service), socket_(io_service_), data_length_(0)
-    {}
-    virtual void establish(const char& socket_file);
-    virtual void disconnect();
-    virtual int getSocket() { return (socket_.native()); }
-    virtual void writeData(const void* data, size_t datalen);
-    virtual size_t readDataLength();
-    virtual void readData(void* data, size_t datalen);
-    virtual void startRead(boost::function<void()> user_handler);
+
 private:
     void internalRead(const asio::error_code& error,
                       size_t bytes_transferred);
@@ -102,28 +84,28 @@
     asio::error_code error_;
 };
 
-
-
-void
-ASIOSession::establish(const char& socket_file) {
+void
+SessionImpl::establish(const char& socket_file) {
     try {
-        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file), error_);
-    } catch (asio::system_error& se) {
+        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file),
+                        error_);
+    } catch(const asio::system_error& se) {
         isc_throw(SessionError, se.what());
     }
     if (error_) {
-        isc_throw(SessionError, "Unable to connect to message queue.");
-    }
-}
-
-void
-ASIOSession::disconnect() {
+        isc_throw(SessionError, "Unable to connect to message queue: " <<
+                  error_.message());
+    }
+}
+
+void
+SessionImpl::disconnect() {
     socket_.close();
     data_length_ = 0;
 }
 
 void
-ASIOSession::writeData(const void* data, size_t datalen) {
+SessionImpl::writeData(const void* data, size_t datalen) {
     try {
         asio::write(socket_, asio::buffer(data, datalen));
     } catch (const asio::system_error& asio_ex) {
@@ -132,7 +114,7 @@
 }
 
 size_t
-ASIOSession::readDataLength() {
+SessionImpl::readDataLength() {
     size_t ret_len = data_length_;
     
     if (ret_len == 0) {
@@ -148,7 +130,7 @@
 }
 
 void
-ASIOSession::readData(void* data, size_t datalen) {
+SessionImpl::readData(void* data, size_t datalen) {
     try {
         asio::read(socket_, asio::buffer(data, datalen));
     } catch (const asio::system_error& asio_ex) {
@@ -159,18 +141,18 @@
 }
 
 void
-ASIOSession::startRead(boost::function<void()> user_handler) {
+SessionImpl::startRead(boost::function<void()> user_handler) {
     data_length_ = 0;
     user_handler_ = user_handler;
     async_read(socket_, asio::buffer(&data_length_,
                                             sizeof(data_length_)),
-               boost::bind(&ASIOSession::internalRead, this,
+               boost::bind(&SessionImpl::internalRead, this,
                            asio::placeholders::error,
                            asio::placeholders::bytes_transferred));
 }
 
 void
-ASIOSession::internalRead(const asio::error_code& error,
+SessionImpl::internalRead(const asio::error_code& error,
                           size_t bytes_transferred)
 {
     if (!error) {
@@ -185,27 +167,22 @@
     }
 }
 
-class SocketSession : public SessionImpl {
-public:
-    SocketSession() : sock_(-1) {}
-    virtual ~SocketSession() { disconnect(); }
-    virtual int getSocket() { return (sock_); }
-    void establish(const char& socket_file);
-    virtual void disconnect()
-    {
-        if (sock_ >= 0) {
-            close(sock_);
-        }
-        sock_ = -1;
-    }
-    virtual void writeData(const void* data, size_t datalen);
-    virtual void readData(void* data, size_t datalen);
-    virtual size_t readDataLength();
-    virtual void startRead(boost::function<void()> user_handler UNUSED_PARAM)
-    {} // nothing to do for this class
-private:
-    int sock_;
-};
+Session::Session(io_service& io_service) : impl_(new SessionImpl(io_service))
+{}
+
+Session::~Session() {
+    delete impl_;
+}
+
+void
+Session::disconnect() {
+    impl_->disconnect();
+}
+
+void
+Session::startRead(boost::function<void()> read_callback) {
+    impl_->startRead(read_callback);
+}
 
 namespace {                     // maybe unnecessary.
 // This is a helper class to make the establish() method (below) exception-safe
@@ -225,83 +202,6 @@
 }
 
 void
-SocketSession::establish(const char& socket_file) {
-    struct sockaddr_un s_un;
-#ifdef HAVE_SA_LEN
-    s_un.sun_len = sizeof(struct sockaddr_un);
-#endif
-
-    if (strlen(&socket_file) >= sizeof(s_un.sun_path)) {
-        isc_throw(SessionError, "Unable to connect to message queue; "
-                  "socket file path too long: " << socket_file);
-    }
-    s_un.sun_family = AF_UNIX;
-    strncpy(s_un.sun_path, &socket_file, sizeof(s_un.sun_path) - 1);
-
-    int s = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (s < 0) {
-        isc_throw(SessionError, "socket() failed");
-    }
-
-    if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
-        close(s);
-        isc_throw(SessionError, "Unable to connect to message queue");
-    }
-
-    sock_ = s;
-}
-
-void
-SocketSession::writeData(const void* data, const size_t datalen) {
-    int cc = write(sock_, data, datalen);
-    if (cc != datalen) {
-        isc_throw(SessionError, "Write failed: expect " << datalen <<
-                  ", actual " << cc);
-    }
-}
-
-size_t
-SocketSession::readDataLength() {
-    uint32_t length;
-    readData(&length, sizeof(length));
-    return (ntohl(length));
-}
-
-void
-SocketSession::readData(void* data, const size_t datalen) {
-    int cc = read(sock_, data, datalen);
-    if (cc != datalen) {
-        isc_throw(SessionError, "Read failed: expect " << datalen <<
-                  ", actual " << cc);
-    }
-}
-
-Session::Session() : impl_(new SocketSession)
-{}
-
-Session::Session(io_service& io_service) : impl_(new ASIOSession(io_service))
-{}
-
-Session::~Session() {
-    delete impl_;
-}
-
-void
-Session::disconnect() {
-    impl_->disconnect();
-}
-
-int
-Session::getSocket() const {
-    return (impl_->getSocket());
-}
-
-void
-Session::startRead(boost::function<void()> read_callback) {
-    impl_->startRead(read_callback);
-}
-
-void
 Session::establish(const char* socket_file) {
     if (socket_file == NULL) {
         socket_file = getenv("BIND10_MSGQ_SOCKET_FILE");
@@ -334,7 +234,8 @@
 }
 
 //
-// Convert to wire format and send this on the TCP stream with its length prefix
+// Convert to wire format and send this via the stream socket with its length
+// prefix.
 //
 void
 Session::sendmsg(ElementPtr& msg) {

Modified: branches/trac191/src/lib/cc/session.h
==============================================================================
--- branches/trac191/src/lib/cc/session.h (original)
+++ branches/trac191/src/lib/cc/session.h Fri Jul 23 09:45:17 2010
@@ -23,8 +23,8 @@
 
 #include <exceptions/exceptions.h>
 
-#include "data.h"
-#include "session_config.h"
+#include <cc/data.h>
+#include <cc/session_config.h>
 
 namespace asio {
 class io_service;
@@ -40,7 +40,57 @@
                 isc::Exception(file, line, what) {}
         };
 
-        class Session {
+        /// \brief The AbstractSession class is an abstract base class that
+        /// defines the interfaces of Session.
+        /// The intended primary usage of abstraction is to allow tests for the
+        /// user class of Session without requiring actual communication
+        /// channels.
+        /// For simplicity we only define the methods that are necessary for
+        /// existing test cases that use this base class.  Eventually we'll
+        /// probably have to extend them.
+        class AbstractSession {
+            ///
+            /// \name Constructors, Assignment Operator and Destructor.
+            ///
+            /// Note: The copy constructor and the assignment operator are
+            /// intentionally defined as private to make it explicit that
+            /// this is a pure base class.
+            //@{
+        private:
+            AbstractSession(const AbstractSession& source);
+            AbstractSession& operator=(const AbstractSession& source);
+        protected:
+            /// \brief The default constructor.
+            ///
+            /// This is intentionally defined as \c protected as this base
+            /// class should never be instantiated (except as part of a
+            /// derived class).
+            AbstractSession() {}
+        public:
+            /// \brief The destructor.
+            virtual ~AbstractSession() {}
+            //@}
+            virtual void establish(const char* socket_file) = 0;
+            virtual void disconnect() = 0;
+            virtual int group_sendmsg(isc::data::ElementPtr msg,
+                                      std::string group,
+                                      std::string instance = "*",
+                                      std::string to = "*") = 0;
+            virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
+                                       isc::data::ElementPtr& msg,
+                                       bool nonblock = true,
+                                       int seq = -1) = 0;
+            virtual void subscribe(std::string group,
+                                   std::string instance = "*") = 0;
+            virtual void unsubscribe(std::string group,
+                             std::string instance = "*") = 0;
+            virtual void startRead(boost::function<void()> read_callback) = 0;
+            virtual int reply(isc::data::ElementPtr& envelope,
+                               isc::data::ElementPtr& newmsg) = 0;
+            virtual bool hasQueuedMsgs() = 0;
+        };
+
+    class Session : public AbstractSession {
         private:
             SessionImpl* impl_;
 
@@ -49,17 +99,29 @@
             Session& operator=(const Session& source);
 
         public:
-            Session();
             Session(asio::io_service& ioservice);
-            ~Session();
+            virtual ~Session();
 
-            // XXX: quick hack to allow the user to watch the socket directly.
-            int getSocket() const;
+            virtual void startRead(boost::function<void()> read_callback);
 
-            void startRead(boost::function<void()> read_callback);
-
-            void establish(const char* socket_file = NULL);
-            void disconnect();
+            virtual void establish(const char* socket_file = NULL);
+            virtual void disconnect();
+            virtual void subscribe(std::string group,
+                                   std::string instance = "*");
+            virtual void unsubscribe(std::string group,
+                             std::string instance = "*");
+            virtual int group_sendmsg(isc::data::ElementPtr msg,
+                                      std::string group,
+                                      std::string instance = "*",
+                                      std::string to = "*");
+            virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
+                                       isc::data::ElementPtr& msg,
+                                       bool nonblock = true,
+                                       int seq = -1);
+            virtual int reply(isc::data::ElementPtr& envelope,
+                              isc::data::ElementPtr& newmsg);
+            virtual bool hasQueuedMsgs();
+    private:
             void sendmsg(isc::data::ElementPtr& msg);
             void sendmsg(isc::data::ElementPtr& env,
                          isc::data::ElementPtr& msg);
@@ -70,21 +132,6 @@
                          isc::data::ElementPtr& msg,
                          bool nonblock = true,
                          int seq = -1);
-            void subscribe(std::string group,
-                           std::string instance = "*");
-            void unsubscribe(std::string group,
-                             std::string instance = "*");
-            int group_sendmsg(isc::data::ElementPtr msg,
-                                       std::string group,
-                                       std::string instance = "*",
-                                       std::string to = "*");
-            bool group_recvmsg(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& msg,
-                               bool nonblock = true,
-                               int seq = -1);
-            int reply(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& newmsg);
-            bool hasQueuedMsgs();
         };
     } // namespace cc
 } // namespace isc

Modified: branches/trac191/src/lib/cc/session_unittests.cc
==============================================================================
--- branches/trac191/src/lib/cc/session_unittests.cc (original)
+++ branches/trac191/src/lib/cc/session_unittests.cc Fri Jul 23 09:45:17 2010
@@ -14,7 +14,7 @@
 
 // $Id: data_unittests.cc 1899 2010-05-21 12:03:59Z jelte $
 
-#include "config.h"
+#include <config.h>
 
 // for some IPC/network system calls in asio/detail/pipe_select_interrupter.hpp 
 #include <unistd.h>
@@ -47,22 +47,3 @@
     );
                   
 }
-
-TEST(Session, establish) {
-    Session sess;
-
-    EXPECT_THROW(
-        sess.establish("/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                  ), isc::cc::SessionError
-    );
-                  
-}

Modified: branches/trac191/src/lib/config/Makefile.am
==============================================================================
--- branches/trac191/src/lib/config/Makefile.am (original)
+++ branches/trac191/src/lib/config/Makefile.am Fri Jul 23 09:45:17 2010
@@ -51,3 +51,4 @@
 EXTRA_DIST += testdata/spec25.spec
 EXTRA_DIST += testdata/spec26.spec
 EXTRA_DIST += testdata/spec27.spec
+EXTRA_DIST += testdata/spec28.spec

Modified: branches/trac191/src/lib/config/ccsession.cc
==============================================================================
--- branches/trac191/src/lib/config/ccsession.cc (original)
+++ branches/trac191/src/lib/config/ccsession.cc Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 //               react on config change announcements)
 //
 
-#include "config.h"
+#include <config.h>
 
 #include <stdexcept>
 #include <stdlib.h>
@@ -40,8 +40,7 @@
 #include <cc/session.h>
 #include <exceptions/exceptions.h>
 
-#include "ccsession.h"
-#include "config.h"
+#include <config/ccsession.h>
 
 using namespace std;
 
@@ -197,37 +196,13 @@
 }
 
 ModuleCCSession::ModuleCCSession(
-    std::string spec_file_name,
-    asio::io_service& io_service,
+    const std::string& spec_file_name,
+    isc::cc::AbstractSession& session,
     isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
     isc::data::ElementPtr(*command_handler)(
         const std::string& command, const isc::data::ElementPtr args)
     ) throw (isc::cc::SessionError) :
-    session_(io_service)
-{
-    init(spec_file_name, config_handler, command_handler);
-
-    // register callback for asynchronous read
-    session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
-}
-
-ModuleCCSession::ModuleCCSession(
-    std::string spec_file_name,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
-    ) throw (isc::cc::SessionError)
-{
-    init(spec_file_name, config_handler, command_handler);
-}
-
-void
-ModuleCCSession::init(
-    std::string spec_file_name,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
-    ) throw (isc::cc::SessionError)
+    session_(session)
 {
     module_specification_ = readModuleSpecification(spec_file_name);
     setModuleSpec(module_specification_);
@@ -238,7 +213,7 @@
 
     ElementPtr answer, env;
 
-    session_.establish();
+    session_.establish(NULL);
     session_.subscribe(module_name_, "*");
     //session_.subscribe("Boss", "*");
     //session_.subscribe("statistics", "*");
@@ -265,6 +240,9 @@
             std::cerr << "[" << module_name_ << "] Error getting config: " << new_config << std::endl;
         }
     }
+
+    // register callback for asynchronous read
+    session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
 }
 
 /// Validates the new config values, if they are correct,
@@ -300,12 +278,6 @@
     return answer;
 }
 
-int
-ModuleCCSession::getSocket()
-{
-    return (session_.getSocket());
-}
-
 bool
 ModuleCCSession::hasQueuedMsgs()
 {
@@ -327,8 +299,8 @@
         ElementPtr answer;
         try {
             std::string cmd_str = parseCommand(arg, data);
+            std::string target_module = routing->get("group")->stringValue();
             if (cmd_str == "config_update") {
-                std::string target_module = routing->get("group")->stringValue();
                 if (target_module == module_name_) {
                     answer = handleConfigUpdate(arg);
                 } else {
@@ -339,16 +311,22 @@
                     return 0;
                 }
             } else {
-                if (command_handler_) {
-                    answer = command_handler_(cmd_str, arg);
-                } else {
-                    answer = createAnswer(1, "Command given but no command handler for module");
+                if (target_module == module_name_) {
+                    if (command_handler_) {
+                        answer = command_handler_(cmd_str, arg);
+                    } else {
+                        answer = createAnswer(1, "Command given but no command handler for module");
+                    }
                 }
             }
         } catch (CCSessionError re) {
+            // TODO: Once we have logging and timeouts, we should not
+            // answer here (potential interference)
             answer = createAnswer(1, re.what());
         }
-        session_.reply(routing, answer);
+        if (!isNull(answer)) {
+            session_.reply(routing, answer);
+        }
     }
     
     return 0;

Modified: branches/trac191/src/lib/config/ccsession.h
==============================================================================
--- branches/trac191/src/lib/config/ccsession.h (original)
+++ branches/trac191/src/lib/config/ccsession.h Fri Jul 23 09:45:17 2010
@@ -24,10 +24,6 @@
 #include <cc/session.h>
 #include <cc/data.h>
 
-namespace asio {
-class io_service;
-}
-
 namespace isc {
 namespace config {
 
@@ -112,7 +108,7 @@
 };
 
 ///
-/// \brief This modules keeps a connection to the command channel,
+/// \brief This module keeps a connection to the command channel,
 /// holds configuration information, and handles messages from
 /// the command channel
 ///
@@ -120,32 +116,29 @@
 public:
     /**
      * Initialize a config/command session
-     * @param module_name: The name of this module. This is not a
-     *                     reference because we expect static strings
-     *                     to be passed here.
-     * @param spec_file_name: The name of the file containing the
+     *
+     * @param spec_file_name The name of the file containing the
      *                        module specification.
-     */
-    ModuleCCSession(std::string spec_file_name,
-                    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
+     * @param session A Session object over which configuration and command
+     * data are exchanged.
+     * @param config_handler A callback function pointer to be called when
+     * configuration of the local module needs to be updated.
+     * This must refer to a valid object of a concrete derived class of
+     * AbstractSession without establishing the session.
+     * Note: the design decision on who is responsible for establishing the
+     * session is in flux, and may change in near future.
+     * @param command_handler A callback function pointer to be called when
+     * a control command from a remote agent needs to be performed on the
+     * local module.
+     */
+    ModuleCCSession(const std::string& spec_file_name,
+                    isc::cc::AbstractSession& session,
+                    isc::data::ElementPtr(*config_handler)(
+                        isc::data::ElementPtr new_config) = NULL,
+                    isc::data::ElementPtr(*command_handler)(
+                        const std::string& command,
+                        const isc::data::ElementPtr args) = NULL
                     ) throw (isc::cc::SessionError);
-    ModuleCCSession(std::string spec_file_name,
-                    asio::io_service& io_service,
-                    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
-                    ) throw (isc::cc::SessionError);
-
-    /**
-     * Returns the socket that is used to communicate with the msgq
-     * command channel. This socket should *only* be used to run a
-     * select() loop over it. And if not time-critical, it is strongly
-     * recommended to only use checkCommand() to check for messages
-     *
-     * @return The socket used to communicate with the msgq command
-     *         channel.
-     */
-    int getSocket();
 
     /**
      * Optional optimization for checkCommand loop; returns true
@@ -227,18 +220,11 @@
     ElementPtr getRemoteConfigValue(const std::string& module_name, const std::string& identifier);
     
 private:
-    void init(
-        std::string spec_file_name,
-        isc::data::ElementPtr(*config_handler)(
-            isc::data::ElementPtr new_config),
-        isc::data::ElementPtr(*command_handler)(
-            const std::string& command, const isc::data::ElementPtr args)
-        ) throw (isc::cc::SessionError);
     ModuleSpec readModuleSpecification(const std::string& filename);
     void startCheck();
     
     std::string module_name_;
-    isc::cc::Session session_;
+    isc::cc::AbstractSession& session_;
     ModuleSpec module_specification_;
     ElementPtr handleConfigUpdate(ElementPtr new_config);
 

Modified: branches/trac191/src/lib/config/config_data.cc
==============================================================================
--- branches/trac191/src/lib/config/config_data.cc (original)
+++ branches/trac191/src/lib/config/config_data.cc Fri Jul 23 09:45:17 2010
@@ -14,7 +14,7 @@
 
 // $Id$
 
-#include "config_data.h"
+#include <config/config_data.h>
 
 #include <boost/foreach.hpp>
 

Modified: branches/trac191/src/lib/config/module_spec.cc
==============================================================================
--- branches/trac191/src/lib/config/module_spec.cc (original)
+++ branches/trac191/src/lib/config/module_spec.cc Fri Jul 23 09:45:17 2010
@@ -13,7 +13,7 @@
 // NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 // WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-#include "module_spec.h"
+#include <config/module_spec.h>
 
 #include <sstream>
 #include <iostream>

Modified: branches/trac191/src/lib/config/testdata/b10-config.db
==============================================================================
--- branches/trac191/src/lib/config/testdata/b10-config.db (original)
+++ branches/trac191/src/lib/config/testdata/b10-config.db Fri Jul 23 09:45:17 2010
@@ -1,1 +1,1 @@
-{'TestModule': {'test': 125}, 'version': 1}
+{"version": 1, "TestModule": {"test": 125}}

Modified: branches/trac191/src/lib/config/testdata/data22_1.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_1.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_1.data Fri Jul 23 09:45:17 2010
@@ -1,9 +1,9 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
+    "value6": { "v61": "bar", "v62": true },
     "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
 }

Modified: branches/trac191/src/lib/config/testdata/data22_2.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_2.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_2.data Fri Jul 23 09:45:17 2010
@@ -1,8 +1,8 @@
 {
     "value1": "asdf",
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True }
+    "value6": { "v61": "bar", "v62": true }
 }

Modified: branches/trac191/src/lib/config/testdata/data22_3.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_3.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_3.data Fri Jul 23 09:45:17 2010
@@ -1,8 +1,8 @@
 {
     "value1": 1,
-    "value2": False,
-    "value3": True,
+    "value2": false,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True }
+    "value6": { "v61": "bar", "v62": true }
 }

Modified: branches/trac191/src/lib/config/testdata/data22_4.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_4.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_4.data Fri Jul 23 09:45:17 2010
@@ -1,8 +1,8 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, "a" ],
-    "value6": { "v61": "bar", "v62": True }
+    "value6": { "v61": "bar", "v62": true }
 }

Modified: branches/trac191/src/lib/config/testdata/data22_5.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_5.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_5.data Fri Jul 23 09:45:17 2010
@@ -1,7 +1,7 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
     "value6": { "v61": "bar", "v62": "Break" }

Modified: branches/trac191/src/lib/config/testdata/data22_6.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_6.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_6.data Fri Jul 23 09:45:17 2010
@@ -1,10 +1,10 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
-    "value7": [ 1, 2.2, "str", True ],
+    "value6": { "v61": "bar", "v62": true },
+    "value7": [ 1, 2.2, "str", true ],
     "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
 }

Modified: branches/trac191/src/lib/config/testdata/data22_7.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_7.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_7.data Fri Jul 23 09:45:17 2010
@@ -1,10 +1,10 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
+    "value6": { "v61": "bar", "v62": true },
     "value8": [ { "a": "d" }, { "a": "e" } ],
     "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
 }

Modified: branches/trac191/src/lib/config/testdata/data22_8.data
==============================================================================
--- branches/trac191/src/lib/config/testdata/data22_8.data (original)
+++ branches/trac191/src/lib/config/testdata/data22_8.data Fri Jul 23 09:45:17 2010
@@ -1,9 +1,9 @@
 {
     "value1": 1,
     "value2": 2.3,
-    "value3": True,
+    "value3": true,
     "value4": "foo",
     "value5": [ 1, 2, 3 ],
-    "value6": { "v61": "bar", "v62": True },
+    "value6": { "v61": "bar", "v62": true },
     "value8": [ { "a": "d" }, { "a": 1 } ]
 }

Modified: branches/trac191/src/lib/config/testdata/spec10.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec10.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec10.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "real",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec11.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec11.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec11.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "boolean",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec12.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec12.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec12.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "string",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec13.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec13.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec13.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "list",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec14.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec14.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec14.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec15.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec15.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec15.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "badname",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec17.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec17.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec17.spec Fri Jul 23 09:45:17 2010
@@ -7,7 +7,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       }

Modified: branches/trac191/src/lib/config/testdata/spec2.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec2.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec2.spec Fri Jul 23 09:45:17 2010
@@ -4,48 +4,48 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       },
       { "item_name": "item2",
         "item_type": "real",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1.1
       },
       { "item_name": "item3",
         "item_type": "boolean",
-        "item_optional": False,
-        "item_default": True
+        "item_optional": false,
+        "item_default": true
       },
       { "item_name": "item4",
         "item_type": "string",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": "test"
       },
       { "item_name": "item5",
         "item_type": "list",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": [ "a", "b" ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         }
       },
       { "item_name": "item6",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": {},
         "map_item_spec": [
           { "item_name": "value1",
             "item_type": "string",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": "default"
           },
           { "item_name": "value2",
             "item_type": "integer",
-            "item_optional": True
+            "item_optional": true
           }
         ]
       }
@@ -57,7 +57,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       },

Modified: branches/trac191/src/lib/config/testdata/spec20.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec20.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec20.spec Fri Jul 23 09:45:17 2010
@@ -8,7 +8,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "somethingbad",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       }

Modified: branches/trac191/src/lib/config/testdata/spec22.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec22.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec22.spec Fri Jul 23 09:45:17 2010
@@ -4,75 +4,75 @@
     "config_data": [
       { "item_name": "value1",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 9
       },
       { "item_name": "value2",
         "item_type": "real",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 9.9
       },
       { "item_name": "value3",
         "item_type": "boolean",
-        "item_optional": False,
-        "item_default": False
+        "item_optional": false,
+        "item_default": false
       },
       { "item_name": "value4",
         "item_type": "string",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": "default_string"
       },
       { "item_name": "value5",
         "item_type": "list",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": [ "a", "b" ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "integer",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": 8
         }
       },
       { "item_name": "value6",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": {},
         "map_item_spec": [
           { "item_name": "v61",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": "def"
           },
           { "item_name": "v62",
             "item_type": "boolean",
-            "item_optional": False,
-            "item_default": False
+            "item_optional": false,
+            "item_default": false
           }
         ]
       },
       { "item_name": "value7",
         "item_type": "list",
-        "item_optional": True,
+        "item_optional": true,
         "item_default": [ ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "any",
-          "item_optional": True
+          "item_optional": true
         }
       },
       { "item_name": "value8",
         "item_type": "list",
-        "item_optional": True,
+        "item_optional": true,
         "item_default": [ ],
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "map",
-          "item_optional": True,
+          "item_optional": true,
           "item_default": { "a": "b" },
           "map_item_spec": [
             { "item_name": "a",
               "item_type": "string",
-              "item_optional": True,
+              "item_optional": true,
               "item_default": "empty"
             }
           ]
@@ -80,28 +80,28 @@
       },
       { "item_name": "value9",
         "item_type": "map",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": {},
         "map_item_spec": [
           { "item_name": "v91",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": "def"
           },
           { "item_name": "v92",
             "item_type": "map",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": {},
             "map_item_spec": [
               { "item_name": "v92a",
                 "item_type": "string",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": "Hello"
               } ,
               {
                 "item_name": "v92b",
                 "item_type": "integer",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": 47806
               }
             ]

Modified: branches/trac191/src/lib/config/testdata/spec23.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec23.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec23.spec Fri Jul 23 09:45:17 2010
@@ -8,7 +8,7 @@
         "command_args": [ {
           "item_name": "message",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         } ]
       }

Modified: branches/trac191/src/lib/config/testdata/spec24.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec24.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec24.spec Fri Jul 23 09:45:17 2010
@@ -4,11 +4,11 @@
     "config_data": [
       { "item_name": "item",
         "item_type": "list",
-        "item_optional": True,
+        "item_optional": true,
         "list_item_spec": {
           "item_name": "list_element",
           "item_type": "string",
-          "item_optional": False,
+          "item_optional": false,
           "item_default": ""
         }
       }

Modified: branches/trac191/src/lib/config/testdata/spec27.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec27.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec27.spec Fri Jul 23 09:45:17 2010
@@ -3,81 +3,81 @@
     "module_name": "Spec27",
     "commands": [
     {
-        'command_name': 'cmd1',
+        "command_name": "cmd1",
         "command_description": "command_for_unittest",
-        'command_args': [ 
+        "command_args": [ 
           {
             "item_name": "value1",
             "item_type": "integer",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": 9
           },
           { "item_name": "value2",
             "item_type": "real",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": 9.9
           },
           { "item_name": "value3",
             "item_type": "boolean",
-            "item_optional": False,
-            "item_default": False
+            "item_optional": false,
+            "item_default": false
           },
           { "item_name": "value4",
             "item_type": "string",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": "default_string"
           },
           { "item_name": "value5",
             "item_type": "list",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": [ "a", "b" ],
             "list_item_spec": {
               "item_name": "list_element",
               "item_type": "integer",
-              "item_optional": False,
+              "item_optional": false,
               "item_default": 8
             }
           },
           { "item_name": "value6",
             "item_type": "map",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": {},
             "map_item_spec": [
               { "item_name": "v61",
                 "item_type": "string",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": "def"
               },
               { "item_name": "v62",
                 "item_type": "boolean",
-                "item_optional": False,
-                "item_default": False
+                "item_optional": false,
+                "item_default": false
               }
             ]
           },
           { "item_name": "value7",
             "item_type": "list",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": [ ],
             "list_item_spec": {
               "item_name": "list_element",
               "item_type": "any",
-              "item_optional": True
+              "item_optional": true
             }
           },
           { "item_name": "value8",
             "item_type": "list",
-            "item_optional": True,
+            "item_optional": true,
             "item_default": [ ],
             "list_item_spec": {
               "item_name": "list_element",
               "item_type": "map",
-              "item_optional": True,
+              "item_optional": true,
               "item_default": { "a": "b" },
               "map_item_spec": [
                 { "item_name": "a",
                   "item_type": "string",
-                  "item_optional": True,
+                  "item_optional": true,
                   "item_default": "empty"
                 }
               ]
@@ -85,28 +85,28 @@
           },
           { "item_name": "value9",
             "item_type": "map",
-            "item_optional": False,
+            "item_optional": false,
             "item_default": {},
             "map_item_spec": [
               { "item_name": "v91",
                 "item_type": "string",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": "def"
               },
               { "item_name": "v92",
                 "item_type": "map",
-                "item_optional": False,
+                "item_optional": false,
                 "item_default": {},
                 "map_item_spec": [
                   { "item_name": "v92a",
                     "item_type": "string",
-                    "item_optional": False,
+                    "item_optional": false,
                     "item_default": "Hello"
                   } ,
                   {
                     "item_name": "v92b",
                     "item_type": "integer",
-                    "item_optional": False,
+                    "item_optional": false,
                     "item_default": 47806
                   }
                 ]

Modified: branches/trac191/src/lib/config/testdata/spec3.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec3.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec3.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       {
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec4.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec4.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec4.spec Fri Jul 23 09:45:17 2010
@@ -3,7 +3,7 @@
     "module_name": "Spec2",
     "config_data": [
       { "item_name": "item1",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": 1
       }
     ]

Modified: branches/trac191/src/lib/config/testdata/spec6.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec6.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec6.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "integer",
-        "item_optional": False
+        "item_optional": false
       }
     ]
   }

Modified: branches/trac191/src/lib/config/testdata/spec9.spec
==============================================================================
--- branches/trac191/src/lib/config/testdata/spec9.spec (original)
+++ branches/trac191/src/lib/config/testdata/spec9.spec Fri Jul 23 09:45:17 2010
@@ -4,7 +4,7 @@
     "config_data": [
       { "item_name": "item1",
         "item_type": "integer",
-        "item_optional": False,
+        "item_optional": false,
         "item_default": "asdf"
       }
     ]

Modified: branches/trac191/src/lib/config/tests/Makefile.am
==============================================================================
--- branches/trac191/src/lib/config/tests/Makefile.am (original)
+++ branches/trac191/src/lib/config/tests/Makefile.am Fri Jul 23 09:45:17 2010
@@ -1,4 +1,4 @@
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 # see src/lib/cc/Makefile.am for -Wno-unused-parameter

Modified: branches/trac191/src/lib/config/tests/ccsession_unittests.cc
==============================================================================
--- branches/trac191/src/lib/config/tests/ccsession_unittests.cc (original)
+++ branches/trac191/src/lib/config/tests/ccsession_unittests.cc Fri Jul 23 09:45:17 2010
@@ -14,56 +14,49 @@
 
 // $Id: module_spec_unittests.cc 1321 2010-03-11 10:17:03Z jelte $
 
-#include "config.h"
+#include <config.h>
 
 #include <gtest/gtest.h>
 
-#include "fake_session.h"
+#include <config/tests/fake_session.h>
 
 #include <config/ccsession.h>
 
 #include <fstream>
 
-#include "data_def_unittests_config.h"
+#include <config/tests/data_def_unittests_config.h>
 
 using namespace isc::data;
 using namespace isc::config;
+using namespace isc::cc;
 using namespace std;
 
-std::string ccspecfile(const std::string name) {
+namespace {
+std::string
+ccspecfile(const std::string name) {
     return std::string(TEST_DATA_PATH) + "/" + name;
 }
 
-static ElementPtr
-el(const std::string& str)
-{
+ElementPtr
+el(const std::string& str) {
     return Element::fromJSON(str);
 }
 
-// upon creation of a ModuleCCSession, the class
-// sends its specification to the config manager
-// it expects an ok answer back, so everytime we
-// create a ModuleCCSession, we must set an initial
-// ok answer
-void
-initFakeSession()
-{
-    initial_messages = el("[]");
-    msg_queue = el("[]");
-    subscriptions = el("[]");
-    initial_messages->add(createAnswer());
-}
-
-void
-endFakeSession()
-{
-    initial_messages = ElementPtr();
-    msg_queue = ElementPtr();
-    subscriptions = ElementPtr();
-}
-
-TEST(CCSession, createAnswer)
-{
+class CCSessionTest : public ::testing::Test {
+protected:
+    CCSessionTest() : session(el("[]"), el("[]"), el("[]")) {
+        // upon creation of a ModuleCCSession, the class
+        // sends its specification to the config manager.
+        // it expects an ok answer back, so everytime we
+        // create a ModuleCCSession, we must set an initial
+        // ok answer.
+        session.getMessages()->add(createAnswer());
+    }
+    ~CCSessionTest() {}
+    FakeSession session;
+};
+
+TEST_F(CCSessionTest, createAnswer) {
     ElementPtr answer;
     answer = createAnswer();
     EXPECT_EQ("{ \"result\": [ 0 ] }", answer->str());
@@ -78,8 +71,7 @@
     EXPECT_EQ("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }", answer->str());
 }
 
-TEST(CCSession, parseAnswer)
-{
+TEST_F(CCSessionTest, parseAnswer) {
     ElementPtr answer;
     ElementPtr arg;
     int rcode;
@@ -110,8 +102,7 @@
     EXPECT_EQ("[ \"just\", \"some\", \"data\" ]", arg->str());
 }
 
-TEST(CCSession, createCommand)
-{
+TEST_F(CCSessionTest, createCommand) {
     ElementPtr command;
     ElementPtr arg;
 
@@ -131,8 +122,7 @@
     ASSERT_EQ("{ \"command\": [ \"foo\", { \"a\": \"map\" } ] }", command->str());
 }
 
-TEST(CCSession, parseCommand)
-{
+TEST_F(CCSessionTest, parseCommand) {
     ElementPtr arg;
     std::string cmd;
 
@@ -159,44 +149,38 @@
 
 }
 
-TEST(CCSession, session1)
-{
-    initFakeSession();
-    EXPECT_EQ(false, haveSubscription("Spec1", "*"));
-    ModuleCCSession mccs(ccspecfile("spec1.spec"), NULL, NULL);
-    EXPECT_EQ(true, haveSubscription("Spec1", "*"));
-
-    EXPECT_EQ(1, msg_queue->size());
+TEST_F(CCSessionTest, session1) {
+    EXPECT_EQ(false, session.haveSubscription("Spec1", "*"));
+    ModuleCCSession mccs(ccspecfile("spec1.spec"), session, NULL, NULL);
+    EXPECT_EQ(true, session.haveSubscription("Spec1", "*"));
+
+    EXPECT_EQ(1, session.getMsgQueue()->size());
     ElementPtr msg;
     std::string group, to;
-    msg = getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"module_name\": \"Spec1\" } ] }", msg->str());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(0, msg_queue->size());
-    endFakeSession();
-}
-
-TEST(CCSession, session2)
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+TEST_F(CCSessionTest, session2)
 {
-    initFakeSession();
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), NULL, NULL);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(1, msg_queue->size());
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, NULL, NULL);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(1, session.getMsgQueue()->size());
     ElementPtr msg;
     std::string group, to;
-    msg = getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"commands\": [ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [  ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ], \"config_data\": [ { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }, { \"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": false, \"item_type\": \"real\" }, { \"item_default\": true, \"item_name\": \"item3\", \"item_optional\": false, \"item_type\": \"boolean\" }, { \"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": false, \"item_type\": \"string\" }, { \"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": false, \"item_type\": \"list\", \"list_item_sp
 ec\": { \"item_default\": \"\", \"item_name\": \"list_element\", \"item_optional\": false, \"item_type\": \"string\" } }, { \"item_default\": {  }, \"item_name\": \"item6\", \"item_optional\": false, \"item_type\": \"map\", \"map_item_spec\": [ { \"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": true, \"item_type\": \"string\" }, { \"item_name\": \"value2\", \"item_optional\": true, \"item_type\": \"integer\" } ] } ], \"module_name\": \"Spec2\" } ] }", msg->str());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(0, msg_queue->size());
-    endFakeSession();
-}
-
-ElementPtr my_config_handler(ElementPtr new_config)
-{
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+ElementPtr my_config_handler(ElementPtr new_config) {
     if (new_config && new_config->contains("item1") &&
         new_config->get("item1")->intValue() == 5) {
         return createAnswer(6, "I do not like the number 5");
@@ -204,7 +188,8 @@
     return createAnswer();
 }
 
-ElementPtr my_command_handler(const std::string& command, ElementPtr arg UNUSED_PARAM)
+ElementPtr my_command_handler(const std::string& command,
+                              ElementPtr arg UNUSED_PARAM)
 {
     if (command == "good_command") {
         return createAnswer();
@@ -223,185 +208,215 @@
     }
 }
 
-TEST(CCSession, session3)
-{
-    initFakeSession();
+TEST_F(CCSessionTest, session3) {
     // client will ask for config
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(2, msg_queue->size());
+    session.getMessages()->add(createAnswer(0, el("{}")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, my_config_handler,
+                         my_command_handler);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(2, session.getMsgQueue()->size());
     ElementPtr msg;
     std::string group, to;
-    msg = getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"commands\": [ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [  ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ], \"config_data\": [ { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }, { \"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": false, \"item_type\": \"real\" }, { \"item_default\": true, \"item_name\": \"item3\", \"item_optional\": false, \"item_type\": \"boolean\" }, { \"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": false, \"item_type\": \"string\" }, { \"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": false, \"item_type\": \"list\", \"list_item_sp
 ec\": { \"item_default\": \"\", \"item_name\": \"list_element\", \"item_optional\": false, \"item_type\": \"string\" } }, { \"item_default\": {  }, \"item_name\": \"item6\", \"item_optional\": false, \"item_type\": \"map\", \"map_item_spec\": [ { \"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": true, \"item_type\": \"string\" }, { \"item_name\": \"value2\", \"item_optional\": true, \"item_type\": \"integer\" } ] } ], \"module_name\": \"Spec2\" } ] }", msg->str());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"command\": [ \"get_config\", { \"module_name\": \"Spec2\" } ] }", msg->str());
     EXPECT_EQ("ConfigManager", group);
     EXPECT_EQ("*", to);
-    EXPECT_EQ(0, msg_queue->size());
-    endFakeSession();
-}
-
-TEST(CCSession, checkCommand)
-{
-    initFakeSession();
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+TEST_F(CCSessionTest, checkCommand) {
     // client will ask for config
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
-    ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
-
-    EXPECT_EQ(2, msg_queue->size());
+    session.getMessages()->add(createAnswer(0, el("{}")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, my_config_handler,
+                         my_command_handler);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(2, session.getMsgQueue()->size());
     ElementPtr msg;
     std::string group, to;
     // checked above, drop em
-    msg = getFirstMessage(group, to);
-    msg = getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
+    msg = session.getFirstMessage(group, to);
 
     int result;
     result = mccs.checkCommand();
     EXPECT_EQ(0, result);
 
     // not a command, should be ignored
-    addMessage(el("1"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(0, result);
-
-    addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("1"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(0, result);
+
+    session.addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2",
+                       "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": \"bad_command\" }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": \"bad_command\" }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"Command part in command message missing, empty, or not a list\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"bad_command\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"bad_command\" ] }"),
+                       "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"bad command\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"command_with_arg\", 1 ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"command_with_arg\", 1 ] }"),
+                       "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0, 2 ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"command_with_arg\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"command_with_arg\" ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"arg missing\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
-    addMessage(el("{ \"command\": [ \"command_with_arg\", \"asdf\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"command_with_arg\", \"asdf\" ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"arg bad type\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
     mccs.setCommandHandler(NULL);
-    addMessage(el("{ \"command\": [ \"whatever\" ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"whatever\" ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 1, \"Command given but no command handler for module\" ] }", msg->str());
     EXPECT_EQ(0, result);
 
     EXPECT_EQ(1, mccs.getValue("item1")->intValue());
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 2 } ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 2 } ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
     EXPECT_EQ(0, result);
     EXPECT_EQ(2, mccs.getValue("item1")->intValue());
 
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": \"asdf\" } ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": \"asdf\" } ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 2, \"Error in config validation: Type mismatch\" ] }", msg->str());
     EXPECT_EQ(0, result);
     EXPECT_EQ(2, mccs.getValue("item1")->intValue());
 
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 5 } ] }"), "Spec2", "*");
-    result = mccs.checkCommand();
-    EXPECT_EQ(1, msg_queue->size());
-    msg = getFirstMessage(group, to);
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 5 } ] }"), "Spec2", "*");
+    result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
     EXPECT_EQ("{ \"result\": [ 6, \"I do not like the number 5\" ] }", msg->str());
     EXPECT_EQ(0, result);
     EXPECT_EQ(2, mccs.getValue("item1")->intValue());
-
-    endFakeSession();
-}
-
-TEST(CCSession, remoteConfig)
-{
+}
+
+TEST_F(CCSessionTest, remoteConfig) {
     std::string module_name;
     int item1;
     
-    initFakeSession();
-    ModuleCCSession mccs(ccspecfile("spec1.spec"), NULL, NULL);
-    EXPECT_EQ(true, haveSubscription("Spec1", "*"));
+    ModuleCCSession mccs(ccspecfile("spec1.spec"), session, NULL, NULL);
+    EXPECT_EQ(true, session.haveSubscription("Spec1", "*"));
     
     // first simply connect, with no config values, and see we get
     // the default
-    initial_messages->add(createAnswer(0, el("{  }")));
-
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
+    session.getMessages()->add(createAnswer(0, el("{}")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
     module_name = mccs.addRemoteConfig(ccspecfile("spec2.spec"));
     EXPECT_EQ("Spec2", module_name);
-    EXPECT_EQ(true, haveSubscription("Spec2", "*"));
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
 
     item1 = mccs.getRemoteConfigValue(module_name, "item1")->intValue();
     EXPECT_EQ(1, item1);
 
     // Remove it and see we get an error asking for a config value
     mccs.removeRemoteConfig(module_name);
-    EXPECT_EQ(false, haveSubscription("Spec2", "*"));
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
     EXPECT_THROW(mccs.getRemoteConfigValue(module_name, "item1"), CCSessionError);
 
     // Now re-add it, with a specific config value, and see we get that
-    initial_messages->add(createAnswer(0, el("{ \"item1\": 2 }")));
+    session.getMessages()->add(createAnswer(0, el("{ \"item1\": 2 }")));
     module_name = mccs.addRemoteConfig(ccspecfile("spec2.spec"));
     item1 = mccs.getRemoteConfigValue(module_name, "item1")->intValue();
     EXPECT_EQ(2, item1);
 
     // Try a config_update command
-    addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 3 } ] }"), module_name, "*");
+    session.addMessage(el("{ \"command\": [ \"config_update\", { \"item1\": 3 } ] }"), module_name, "*");
     mccs.checkCommand();
     item1 = mccs.getRemoteConfigValue(module_name, "item1")->intValue();
     EXPECT_EQ(3, item1);
 
     // remove, re-add, now with a *bad* config request answer
     mccs.removeRemoteConfig(module_name);
-    initial_messages->add(el("{  }"));
+    session.getMessages()->add(el("{}"));
     EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
     
-    initial_messages->add(createAnswer(1, "my_error"));
+    session.getMessages()->add(createAnswer(1, "my_error"));
     EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
     
-    initial_messages->add(createAnswer());
+    session.getMessages()->add(createAnswer());
     mccs.addRemoteConfig(ccspecfile("spec2.spec"));
-    
-    endFakeSession();
-}
-
+}
+
+TEST_F(CCSessionTest, ignoreRemoteConfigCommands) {
+    // client will ask for config
+    session.getMessages()->add(createAnswer(0, el("{  }")));
+
+    EXPECT_EQ(false, session.haveSubscription("Spec2", "*"));
+    ModuleCCSession mccs(ccspecfile("spec2.spec"), session, my_config_handler, my_command_handler);
+    EXPECT_EQ(true, session.haveSubscription("Spec2", "*"));
+
+    EXPECT_EQ(2, session.getMsgQueue()->size());
+    ElementPtr msg;
+    std::string group, to;
+    // drop the module_spec and config commands
+    session.getFirstMessage(group, to);
+    session.getFirstMessage(group, to);
+
+    session.getMessages()->add(createAnswer(0, el("{  }")));
+    mccs.addRemoteConfig(ccspecfile("spec1.spec"));
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
+
+    // Check if commands for the module are handled
+    session.addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec2", "*");
+    int result = mccs.checkCommand();
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    msg = session.getFirstMessage(group, to);
+    EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
+    EXPECT_EQ(0, result);
+
+    // Check if commands for the other module are ignored
+    session.addMessage(el("{ \"command\": [ \"good_command\" ] }"), "Spec1", "*");
+    EXPECT_EQ(1, session.getMsgQueue()->size());
+    result = mccs.checkCommand();
+    EXPECT_EQ(0, session.getMsgQueue()->size());
+}
+
+}

Modified: branches/trac191/src/lib/config/tests/config_data_unittests.cc
==============================================================================
--- branches/trac191/src/lib/config/tests/config_data_unittests.cc (original)
+++ branches/trac191/src/lib/config/tests/config_data_unittests.cc Fri Jul 23 09:45:17 2010
@@ -17,7 +17,7 @@
 
 #include <gtest/gtest.h>
 
-#include "data_def_unittests_config.h"
+#include <config/tests/data_def_unittests_config.h>
 #include <config/config_data.h>
 
 #include <iostream>

Modified: branches/trac191/src/lib/config/tests/fake_session.cc
==============================================================================
--- branches/trac191/src/lib/config/tests/fake_session.cc (original)
+++ branches/trac191/src/lib/config/tests/fake_session.cc Fri Jul 23 09:45:17 2010
@@ -14,7 +14,7 @@
 
 // $Id: session.cc 1250 2010-03-09 22:52:15Z jinmei $
 
-#include "config.h"
+#include <config.h>
 
 #include <stdint.h>
 
@@ -28,7 +28,7 @@
 #include <exceptions/exceptions.h>
 
 #include <cc/data.h>
-#include "fake_session.h"
+#include <config/tests/fake_session.h>
 
 using namespace std;
 using namespace isc::cc;
@@ -38,26 +38,21 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 
-isc::data::ElementPtr initial_messages;
-isc::data::ElementPtr subscriptions;
-isc::data::ElementPtr msg_queue;
-
 // ok i want these in cc/data 
-static bool
-listContains(ElementPtr list, ElementPtr el)
-{
+bool
+listContains(ElementPtr list, ElementPtr el) {
     if (!list) {
-        return false;
+        return (false);
     }
     BOOST_FOREACH(ElementPtr l_el, list->listValue()) {
         if (l_el == el) {
-            return true;
+            return (true);
         }
     }
-    return false;
-}
-
-static void
+    return (false);
+}
+
+void
 listRemove(ElementPtr list, ElementPtr el) {
     int i = -1;
     BOOST_FOREACH(ElementPtr s_el, list->listValue()) {
@@ -72,118 +67,65 @@
 }
 // endwant
 
-ElementPtr
-getFirstMessage(std::string& group, std::string& to)
-{
-    ElementPtr el;
-    if (msg_queue && msg_queue->size() > 0) {
-        el = msg_queue->get(0);
-        msg_queue->remove(0);
-        group = el->get(0)->stringValue();
-        to = el->get(1)->stringValue();
-        return el->get(2);
-    } else {
-        group = "";
-        to = "";
-        return ElementPtr();
-    }
-}
-
-void
-addMessage(ElementPtr msg, const std::string& group, const std::string& to) {
-    ElementPtr m_el = Element::createList();
-    m_el->add(Element::create(group));
-    m_el->add(Element::create(to));
-    m_el->add(msg);
-    if (!msg_queue) {
-        msg_queue = Element::createList();
-    }
-    msg_queue->add(m_el);
-}
-
-bool
-haveSubscription(const std::string& group, const std::string& instance)
-{
-    if (!subscriptions) {
-        return false;
-    }
-    ElementPtr s1 = Element::createList();
-    ElementPtr s2 = Element::createList();
-    s1->add(Element::create(group));
-    s1->add(Element::create(instance));
-    s2->add(Element::create(group));
-    s2->add(Element::create("*"));
-    bool result = (listContains(subscriptions, s1) || listContains(subscriptions, s2));
-    return result;
-}
-
-bool
-haveSubscription(const ElementPtr group, const ElementPtr instance)
-{
-    return haveSubscription(group->stringValue(), instance->stringValue());
-}
-
 namespace isc {
 namespace cc {
 
-Session::Session()
-{
-}
-
-Session::Session(asio::io_service& io_service UNUSED_PARAM)
-{
-}
-
-Session::~Session() {
-}
-
-bool
-Session::connect() {
-    return true;
-}
-
-void
-Session::disconnect() {
-}
-
-int
-Session::getSocket() const {
-    return 1;
-}
-
-void
-Session::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
-}
-
-void
-Session::establish(const char* socket_file) {
+FakeSession::FakeSession(isc::data::ElementPtr initial_messages,
+                         isc::data::ElementPtr subscriptions,
+                         isc::data::ElementPtr msg_queue) :
+    messages_(initial_messages),
+    subscriptions_(subscriptions),
+    msg_queue_(msg_queue)
+{
+}
+
+FakeSession::~FakeSession() {
+}
+
+bool
+FakeSession::connect() {
+    return (true);
+}
+
+void
+FakeSession::disconnect() {
+}
+
+void
+FakeSession::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
+}
+
+void
+FakeSession::establish(const char* socket_file) {
 }
 
 //
 // Convert to wire format and send this on the TCP stream with its length prefix
 //
 void
-Session::sendmsg(ElementPtr& msg) {
+FakeSession::sendmsg(ElementPtr& msg) {
     //cout << "[XX] client sends message: " << msg << endl;
     // err, to where?
     addMessage(msg, "*", "*");
 }
 
 void
-Session::sendmsg(ElementPtr& env, ElementPtr& msg) {
+FakeSession::sendmsg(ElementPtr& env, ElementPtr& msg) {
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] env: " << env << endl;
     addMessage(msg, env->get("group")->stringValue(), env->get("to")->stringValue());
 }
 
 bool
-Session::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PARAM) {
+FakeSession::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM,
+                     int seq UNUSED_PARAM)
+{
     //cout << "[XX] client asks for message " << endl;
-    if (initial_messages &&
-        initial_messages->getType() == Element::list &&
-        initial_messages->size() > 0) {
-        msg = initial_messages->get(0);
-        initial_messages->remove(0);
+    if (messages_ &&
+        messages_->getType() == Element::list &&
+        messages_->size() > 0) {
+        msg = messages_->get(0);
+        messages_->remove(0);
     } else {
         msg = ElementPtr();
     }
@@ -191,18 +133,21 @@
 }
 
 bool
-Session::recvmsg(ElementPtr& env, ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PARAM) {
+FakeSession::recvmsg(ElementPtr& env, ElementPtr& msg,
+                     bool nonblock UNUSED_PARAM,
+                     int seq UNUSED_PARAM)
+{
     //cout << "[XX] client asks for message and env" << endl;
     env = ElementPtr();
-    if (initial_messages &&
-        initial_messages->getType() == Element::list &&
-        initial_messages->size() > 0) {
+    if (messages_ &&
+        messages_->getType() == Element::list &&
+        messages_->size() > 0) {
         // do we need initial message to have env[group] and [to] too?
-        msg = initial_messages->get(0);
-        initial_messages->remove(0);
+        msg = messages_->get(0);
+        messages_->remove(0);
         return true;
-    } else if (msg_queue) {
-        BOOST_FOREACH(ElementPtr c_m, msg_queue->listValue()) {
+    } else if (msg_queue_) {
+        BOOST_FOREACH(ElementPtr c_m, msg_queue_->listValue()) {
             ElementPtr to_remove = ElementPtr();
             if (haveSubscription(c_m->get(0), c_m->get(1))) {
                 env = Element::createMap();
@@ -212,7 +157,7 @@
                 to_remove = c_m;
             }
             if (to_remove) {
-                listRemove(msg_queue, to_remove);
+                listRemove(msg_queue_, to_remove);
                 return true;
             }
         }
@@ -223,32 +168,32 @@
 }
 
 void
-Session::subscribe(std::string group, std::string instance) {
+FakeSession::subscribe(std::string group, std::string instance) {
     //cout << "[XX] client subscribes to " << group << " . " << instance << endl;
     ElementPtr s_el = Element::createList();
     s_el->add(Element::create(group));
     s_el->add(Element::create(instance));
-    if (!subscriptions) {
-        subscriptions = Element::createList();
-    }
-    subscriptions->add(s_el);
-}
-
-void
-Session::unsubscribe(std::string group, std::string instance) {
+    if (!subscriptions_) {
+        subscriptions_ = Element::createList();
+    }
+    subscriptions_->add(s_el);
+}
+
+void
+FakeSession::unsubscribe(std::string group, std::string instance) {
     //cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
     ElementPtr s_el = Element::createList();
     s_el->add(Element::create(group));
     s_el->add(Element::create(instance));
-    if (!subscriptions) {
+    if (!subscriptions_) {
         return;
     }
-    listRemove(subscriptions, s_el);
+    listRemove(subscriptions_, s_el);
 }
 
 int
-Session::group_sendmsg(ElementPtr msg, std::string group,
-                       std::string to, std::string instance UNUSED_PARAM)
+FakeSession::group_sendmsg(ElementPtr msg, std::string group,
+                           std::string to, std::string instance UNUSED_PARAM)
 {
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] to: " << group << " . " << instance << "." << to << endl;
@@ -257,14 +202,14 @@
 }
 
 bool
-Session::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
-                       bool nonblock, int seq)
+FakeSession::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+                           bool nonblock, int seq)
 {
     return (recvmsg(envelope, msg, nonblock, seq));
 }
 
 int
-Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
+FakeSession::reply(ElementPtr& envelope, ElementPtr& newmsg) {
     //cout << "[XX] client sends reply: " << newmsg << endl;
     //cout << "[XX] env: " << envelope << endl;
     addMessage(newmsg, envelope->get("group")->stringValue(), envelope->get("to")->stringValue());
@@ -272,9 +217,64 @@
 }
 
 bool
-Session::hasQueuedMsgs() {
+FakeSession::hasQueuedMsgs() {
     return false;
 }
 
-}
-}
+ElementPtr
+FakeSession::getFirstMessage(std::string& group, std::string& to) {
+    ElementPtr el;
+    if (msg_queue_ && msg_queue_->size() > 0) {
+        el = msg_queue_->get(0);
+        msg_queue_->remove(0);
+        group = el->get(0)->stringValue();
+        to = el->get(1)->stringValue();
+        return el->get(2);
+    } else {
+        group = "";
+        to = "";
+        return (ElementPtr());
+    }
+}
+
+void
+FakeSession::addMessage(ElementPtr msg, const std::string& group,
+                        const std::string& to)
+{
+    ElementPtr m_el = Element::createList();
+    m_el->add(Element::create(group));
+    m_el->add(Element::create(to));
+    m_el->add(msg);
+    if (!msg_queue_) {
+        msg_queue_ = Element::createList();
+    }
+    msg_queue_->add(m_el);
+}
+
+bool
+FakeSession::haveSubscription(const std::string& group,
+                              const std::string& instance)
+{
+    if (!subscriptions_) {
+        return (false);
+    }
+    ElementPtr s1 = Element::createList();
+    ElementPtr s2 = Element::createList();
+    s1->add(Element::create(group));
+    s1->add(Element::create(instance));
+    s2->add(Element::create(group));
+    s2->add(Element::create("*"));
+    bool result = (listContains(subscriptions_, s1) ||
+                   listContains(subscriptions_, s2));
+    return (result);
+}
+
+bool
+FakeSession::haveSubscription(const ElementPtr group,
+                              const ElementPtr instance)
+{
+    return (haveSubscription(group->stringValue(), instance->stringValue()));
+}
+
+}
+}

Modified: branches/trac191/src/lib/config/tests/fake_session.h
==============================================================================
--- branches/trac191/src/lib/config/tests/fake_session.h (original)
+++ branches/trac191/src/lib/config/tests/fake_session.h Fri Jul 23 09:45:17 2010
@@ -14,8 +14,8 @@
 
 // $Id: session.h 1250 2010-03-09 22:52:15Z jinmei $
 
-#ifndef _ISC_SESSION_H
-#define _ISC_SESSION_H 1
+#ifndef _ISC_FAKESESSION_H
+#define _ISC_FAKESESSION_H 1
 
 #include <string>
 
@@ -24,85 +24,78 @@
 #include <exceptions/exceptions.h>
 
 #include <cc/data.h>
-
-namespace asio {
-class io_service;
-}
-
-// global variables so tests can insert
-// update and check, before, during and after
-// the actual session object was created/destroyed
-
-// if initial_messages contains a list of messages,
-// these are sent when recv_msg or group_recvmsg is called
-// instead of whatever is in the msg queue
-extern isc::data::ElementPtr initial_messages;
-extern isc::data::ElementPtr subscriptions;
-extern isc::data::ElementPtr msg_queue;
-
-bool haveSubscription(const std::string& group, const std::string& instance);
-bool haveSubscription(const isc::data::ElementPtr group, const isc::data::ElementPtr instance);
-isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
-void addMessage(isc::data::ElementPtr, const std::string& group, const std::string& to);
+#include <cc/session.h>
 
 namespace isc {
-    namespace cc {
+namespace cc {
+class FakeSession : public AbstractSession {
+private:
+    FakeSession(const Session& source);
+    FakeSession& operator=(const Session& source);
 
-        class SessionError : public isc::Exception {
-        public:
-            SessionError(const char* file, size_t line, const char* what) :
-                isc::Exception(file, line, what) {}
-        };
+public:
+    // if initial_messages contains a list of messages,
+    // these are sent when recv_msg or group_recvmsg is called
+    // instead of whatever is in the msg queue.
+    // The test can also add data to a copy of the message later to tweak
+    // the group_recvmsg() behavior.  See getMessages() below.
+    FakeSession(isc::data::ElementPtr initial_messages,
+                isc::data::ElementPtr subscriptions,
+                isc::data::ElementPtr msg_queue);
+    virtual ~FakeSession();
 
-        class Session {
-        private:
-            Session(const Session& source);
-            Session& operator=(const Session& source);
+    virtual void startRead(boost::function<void()> read_callback);
 
-        public:
-            // public so tests can inspect them
-        
-            Session();
-            Session(asio::io_service& ioservice);
-            ~Session();
-
-            // XXX: quick hack to allow the user to watch the socket directly.
-            int getSocket() const;
-
-            void startRead(boost::function<void()> read_callback);
-
-            void establish(const char* socket_file = NULL);
-            bool connect();
-            void disconnect();
-            void sendmsg(isc::data::ElementPtr& msg);
-            void sendmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg);
-            bool recvmsg(isc::data::ElementPtr& msg,
-                         bool nonblock = true, int seq = -1);
-            bool recvmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg,
-                         bool nonblock = true, int seq = -1);
-            void subscribe(std::string group,
+    virtual void establish(const char* socket_file = NULL);
+    bool connect();
+    virtual void disconnect();
+    void sendmsg(isc::data::ElementPtr& msg);
+    void sendmsg(isc::data::ElementPtr& env,
+                 isc::data::ElementPtr& msg);
+    bool recvmsg(isc::data::ElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+    bool recvmsg(isc::data::ElementPtr& env,
+                 isc::data::ElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+    virtual void subscribe(std::string group,
                            std::string instance = "*");
-            void unsubscribe(std::string group,
+    virtual void unsubscribe(std::string group,
                              std::string instance = "*");
-            int group_sendmsg(isc::data::ElementPtr msg,
+    virtual int group_sendmsg(isc::data::ElementPtr msg,
                               std::string group,
                               std::string instance = "*",
                               std::string to = "*");
-            bool group_recvmsg(isc::data::ElementPtr& envelope,
+    virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
                                isc::data::ElementPtr& msg,
                                bool nonblock = true,
                                int seq = -1);
-            int reply(isc::data::ElementPtr& envelope,
+    virtual int reply(isc::data::ElementPtr& envelope,
                       isc::data::ElementPtr& newmsg);
-            bool hasQueuedMsgs();
+    virtual bool hasQueuedMsgs();
+    isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
+    void addMessage(isc::data::ElementPtr, const std::string& group,
+                    const std::string& to);
+    bool haveSubscription(const std::string& group,
+                          const std::string& instance);
+    bool haveSubscription(const isc::data::ElementPtr group,
+                          const isc::data::ElementPtr instance);
 
-        };
-    } // namespace cc
+    // For the convenience of tests, we share these internal members
+    // with the tester.  The test code may insert update and check,
+    // before (via the constructor parameters), during and after the actual
+    // session object was created/destroyed.
+    isc::data::ElementPtr getMessages() { return (messages_); }
+    isc::data::ElementPtr getMsgQueue() { return (msg_queue_); }
+
+private:
+    const isc::data::ElementPtr messages_;
+    isc::data::ElementPtr subscriptions_;
+    isc::data::ElementPtr msg_queue_;
+};
+} // namespace cc
 } // namespace isc
 
-#endif // _ISC_SESSION_H
+#endif // _ISC_FAKESESSION_H
 
 // Local Variables:
 // mode: c++

Modified: branches/trac191/src/lib/config/tests/module_spec_unittests.cc
==============================================================================
--- branches/trac191/src/lib/config/tests/module_spec_unittests.cc (original)
+++ branches/trac191/src/lib/config/tests/module_spec_unittests.cc Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 
 #include <fstream>
 
-#include "data_def_unittests_config.h"
+#include <config/tests/data_def_unittests_config.h>
 
 using namespace isc::data;
 using namespace isc::config;

Modified: branches/trac191/src/lib/datasrc/cache.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/cache.cc (original)
+++ branches/trac191/src/lib/datasrc/cache.cc Fri Jul 23 09:45:17 2010
@@ -240,8 +240,7 @@
     if (node->lru_entry_ == lru_.begin()) {
         return;
     }
-    lru_.erase(node->lru_entry_);
-    lru_.push_front(node);
+    lru_.splice(lru_.begin(), lru_, node->lru_entry_); // move node to front
     node->lru_entry_ = lru_.begin();
 }
 

Modified: branches/trac191/src/lib/datasrc/data_source.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/data_source.cc (original)
+++ branches/trac191/src/lib/datasrc/data_source.cc Fri Jul 23 09:45:17 2010
@@ -14,7 +14,7 @@
 
 // $Id$
 
-#include "config.h"
+#include <config.h>
 
 #include <cassert>
 #include <iomanip>
@@ -28,14 +28,14 @@
 #include <datasrc/data_source.h>
 #include <datasrc/query.h>
 
-#include <dns/base32.h>
+#include <dns/util/base32hex.h>
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/rdataclass.h>
 #include <dns/rrset.h>
 #include <dns/rrsetlist.h>
-#include <dns/sha1.h>
+#include <dns/util/sha1.h>
 
 #include <cc/data.h>
 
@@ -1234,7 +1234,7 @@
         inlength = SHA1_HASHSIZE;
     } while (n++ < iterations_);
 
-    return (encodeBase32(vector<uint8_t>(digest, digest + SHA1_HASHSIZE)));
+    return (encodeBase32Hex(vector<uint8_t>(digest, digest + SHA1_HASHSIZE)));
 }
 
 //

Modified: branches/trac191/src/lib/datasrc/query.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/query.cc (original)
+++ branches/trac191/src/lib/datasrc/query.cc Fri Jul 23 09:45:17 2010
@@ -21,7 +21,7 @@
 
 #include <cc/data.h>
 
-#include "query.h"
+#include <datasrc/query.h>
 
 using namespace isc::dns;
 

Modified: branches/trac191/src/lib/datasrc/query.h
==============================================================================
--- branches/trac191/src/lib/datasrc/query.h (original)
+++ branches/trac191/src/lib/datasrc/query.h Fri Jul 23 09:45:17 2010
@@ -88,7 +88,7 @@
         AUTH_QUERY,
         GLUE_QUERY,
         NOGLUE_QUERY,
-        REF_QUERY,
+        REF_QUERY
     } op;
 
     // The state field indicates the state of the query; it controls

Modified: branches/trac191/src/lib/datasrc/sqlite3_datasrc.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/sqlite3_datasrc.cc (original)
+++ branches/trac191/src/lib/datasrc/sqlite3_datasrc.cc Fri Jul 23 09:45:17 2010
@@ -19,7 +19,7 @@
 
 #include <sqlite3.h>
 
-#include "sqlite3_datasrc.h"
+#include <datasrc/sqlite3_datasrc.h>
 
 #include <dns/rrttl.h>
 #include <dns/rdata.h>
@@ -263,15 +263,16 @@
         isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
                   " to SQL statement (query)");
     }
-    const string s_name = name.toText();
-    rc = sqlite3_bind_text(query, 2, s_name.c_str(), -1, SQLITE_STATIC);
-    if (rc != SQLITE_OK) {
-        isc_throw(Sqlite3Error, "Could not bind name " << s_name <<
+    const string name_text = name.toText();
+    rc = sqlite3_bind_text(query, 2, name_text.c_str(), -1, SQLITE_STATIC);
+    if (rc != SQLITE_OK) {
+        isc_throw(Sqlite3Error, "Could not bind name " << name_text <<
                   " to SQL statement (query)");
     }
 
+    const string rdtype_text = rdtype.toText();
     if (query == dbparameters->q_record_) {
-        rc = sqlite3_bind_text(query, 3, rdtype.toText().c_str(), -1,
+        rc = sqlite3_bind_text(query, 3, rdtype_text.c_str(), -1,
                                SQLITE_STATIC);
         if (rc != SQLITE_OK) {
             isc_throw(Sqlite3Error, "Could not bind RR type " <<
@@ -300,8 +301,9 @@
                   " to SQL statement (qcount)");
     }
 
-    rc = sqlite3_bind_text(dbparameters->q_count_, 2,
-                           name.reverse().toText().c_str(), -1, SQLITE_STATIC);
+    const string revname_text = name.reverse().toText();
+    rc = sqlite3_bind_text(dbparameters->q_count_, 2, revname_text.c_str(),
+                           -1, SQLITE_STATIC);
     if (rc != SQLITE_OK) {
         isc_throw(Sqlite3Error, "Could not bind name " << name.reverse() <<
                   " to SQL statement (qcount)");
@@ -376,8 +378,9 @@
         isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
                   " to SQL statement (qprevious)");        
     }
+    const string revname_text = qname.reverse().toText();
     rc = sqlite3_bind_text(dbparameters->q_previous_, 2,
-                           qname.reverse().toText().c_str(), -1, SQLITE_STATIC);
+                           revname_text.c_str(), -1, SQLITE_STATIC);
     if (rc != SQLITE_OK) {
         isc_throw(Sqlite3Error, "Could not bind name " << qname <<
                   " to SQL statement (qprevious)");

Modified: branches/trac191/src/lib/datasrc/sqlite3_datasrc.h
==============================================================================
--- branches/trac191/src/lib/datasrc/sqlite3_datasrc.h (original)
+++ branches/trac191/src/lib/datasrc/sqlite3_datasrc.h Fri Jul 23 09:45:17 2010
@@ -21,7 +21,7 @@
 
 #include <exceptions/exceptions.h>
 
-#include "data_source.h"
+#include <datasrc/data_source.h>
 
 namespace isc {
 

Modified: branches/trac191/src/lib/datasrc/static_datasrc.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/static_datasrc.cc (original)
+++ branches/trac191/src/lib/datasrc/static_datasrc.cc Fri Jul 23 09:45:17 2010
@@ -14,7 +14,7 @@
 
 // $Id$
 
-#include "config.h"
+#include <config.h>
 
 #include <cassert>
 
@@ -26,8 +26,8 @@
 #include <dns/rrtype.h>
 #include <dns/rrttl.h>
 
-#include "data_source.h"
-#include "static_datasrc.h"
+#include <datasrc/data_source.h>
+#include <datasrc/static_datasrc.h>
 
 using namespace std;
 using namespace isc::dns;

Modified: branches/trac191/src/lib/datasrc/static_datasrc.h
==============================================================================
--- branches/trac191/src/lib/datasrc/static_datasrc.h (original)
+++ branches/trac191/src/lib/datasrc/static_datasrc.h Fri Jul 23 09:45:17 2010
@@ -25,7 +25,7 @@
 #ifndef __STATIC_DATA_SOURCE_H
 #define __STATIC_DATA_SOURCE_H
 
-#include "data_source.h"
+#include <datasrc/data_source.h>
 
 namespace isc {
 

Modified: branches/trac191/src/lib/datasrc/tests/Makefile.am
==============================================================================
--- branches/trac191/src/lib/datasrc/tests/Makefile.am (original)
+++ branches/trac191/src/lib/datasrc/tests/Makefile.am Fri Jul 23 09:45:17 2010
@@ -37,27 +37,6 @@
 EXTRA_DIST += testdata/example2.com
 EXTRA_DIST += testdata/example2.com.sqlite3
 EXTRA_DIST += testdata/mkbrokendb.c
-EXTRA_DIST += testdata/q_cname
-EXTRA_DIST += testdata/q_cname_ext
-EXTRA_DIST += testdata/q_cname_int
-EXTRA_DIST += testdata/q_dname
-EXTRA_DIST += testdata/q_example_dnskey
-EXTRA_DIST += testdata/q_example_ns
-EXTRA_DIST += testdata/q_example_ptr
-EXTRA_DIST += testdata/q_glork
-EXTRA_DIST += testdata/q_spork
-EXTRA_DIST += testdata/q_sql1
-EXTRA_DIST += testdata/q_subzone
-EXTRA_DIST += testdata/q_subzone_any
-EXTRA_DIST += testdata/q_subzone_dname
-EXTRA_DIST += testdata/q_subzone_ds
-EXTRA_DIST += testdata/q_subzone_ns
-EXTRA_DIST += testdata/q_subzone_nsec
-EXTRA_DIST += testdata/q_wild2_a
-EXTRA_DIST += testdata/q_wild2_aaaa
-EXTRA_DIST += testdata/q_wild3_a
-EXTRA_DIST += testdata/q_wild_a
-EXTRA_DIST += testdata/q_wild_aaaa
 EXTRA_DIST += testdata/root.zone
 EXTRA_DIST += testdata/sql1.example.com.signed
 EXTRA_DIST += testdata/sql2.example.com.signed

Modified: branches/trac191/src/lib/datasrc/tests/datasrc_unittest.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/tests/datasrc_unittest.cc (original)
+++ branches/trac191/src/lib/datasrc/tests/datasrc_unittest.cc Fri Jul 23 09:45:17 2010
@@ -39,7 +39,7 @@
 #include <datasrc/static_datasrc.h>
 
 #include <dns/tests/unittest_util.h>
-#include "test_datasrc.h"
+#include <datasrc/tests/test_datasrc.h>
 
 using isc::UnitTestUtil;
 using namespace std;
@@ -65,7 +65,6 @@
         meta_source.addDataSrc(static_source);
     }
     void QueryCommon(const RRClass& qclass);
-    void readAndProcessQuery(const char* datafile);
     void createAndProcessQuery(const Name& qname, const RRClass& qclass,
                                const RRType& qtype);
 
@@ -82,18 +81,6 @@
     message.setRcode(Rcode::NOERROR());
     Query q(message, cache, true);
     data_source.doQuery(q);
-}
-
-void
-DataSrcTest::readAndProcessQuery(const char* datafile) {
-    std::vector<unsigned char> data;
-    UnitTestUtil::readWireData(datafile, data);
-
-    InputBuffer buffer(&data[0], data.size());
-    msg.fromWire(buffer);
-
-    msg.makeResponse();
-    performQuery(meta_source, cache, msg);
 }
 
 void
@@ -193,8 +180,8 @@
 }
 
 TEST_F(DataSrcTest, NSQuery) {
-    readAndProcessQuery("q_example_ns");
-
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::NS());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -216,7 +203,8 @@
 
 // Make sure two successive queries have the same result
 TEST_F(DataSrcTest, DuplicateQuery) {
-    readAndProcessQuery("q_example_ns");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::NS());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -236,7 +224,8 @@
     EXPECT_TRUE(it->isLast());
 
     msg.clear(Message::PARSE);
-    readAndProcessQuery("q_example_ns");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::NS());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
 
     rit = msg.beginSection(Section::ANSWER());
@@ -257,7 +246,8 @@
 }
 
 TEST_F(DataSrcTest, DNSKEYQuery) {
-    readAndProcessQuery("q_example_dnskey");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::DNSKEY());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -271,7 +261,8 @@
 // We query for a record at a zone cut to ensure the REFERRAL flag doesn't
 // cause incorrect behavior.
 TEST_F(DataSrcTest, DNSKEYDuplicateQuery) {
-    readAndProcessQuery("q_example_dnskey");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::DNSKEY());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -281,9 +272,8 @@
     EXPECT_EQ(RRClass::IN(), rrset->getClass());
 
     msg.clear(Message::PARSE);
-    readAndProcessQuery("q_example_dnskey");
-    headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
-
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::DNSKEY());
     rit = msg.beginSection(Section::ANSWER());
     rrset = *rit;
     EXPECT_EQ(Name("example.com"), rrset->getName());
@@ -292,7 +282,8 @@
 }
 
 TEST_F(DataSrcTest, NxRRset) {
-    readAndProcessQuery("q_example_ptr");
+    createAndProcessQuery(Name("example.com"), RRClass::IN(),
+                          RRType::PTR());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 4, 0);
 
@@ -303,7 +294,8 @@
 }
 
 TEST_F(DataSrcTest, Nxdomain) {
-    readAndProcessQuery("q_glork");
+    createAndProcessQuery(Name("glork.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 6, 0);
 
@@ -316,7 +308,8 @@
 }
 
 TEST_F(DataSrcTest, NxZone) {
-    readAndProcessQuery("q_spork");
+    createAndProcessQuery(Name("spork.example"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
 
@@ -327,7 +320,8 @@
 }
 
 TEST_F(DataSrcTest, Wildcard) {
-    readAndProcessQuery("q_wild_a");
+    createAndProcessQuery(Name("www.wild.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 6, 6);
 
@@ -380,17 +374,26 @@
 }
 
 TEST_F(DataSrcTest, WildcardNodata) {
-
     // Check that a query for a data type not covered by the wildcard
     // returns NOERROR
-    readAndProcessQuery("q_wild_aaaa");
+    createAndProcessQuery(Name("www.wild.example.com"), RRClass::IN(),
+                          RRType::AAAA());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 2, 0);
+}
+
+TEST_F(DataSrcTest, DISABLED_WildcardAgainstMultiLabel) {
+    // this qname shouldn't match *.wild.com.com (because * can only match
+    // a single label), and it should result in NXDOMAIN.
+    createAndProcessQuery(Name("www.xxx.wild.example.com"), RRClass::IN(),
+                          RRType::A());
+    headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 1, 0);
 }
 
 TEST_F(DataSrcTest, WildcardCname) {
     // Check that wildcard answers containing CNAMES are followed
     // correctly
-    readAndProcessQuery("q_wild2_a");
+    createAndProcessQuery(Name("www.wild2.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 6, 6);
 
@@ -458,7 +461,8 @@
 TEST_F(DataSrcTest, WildcardCnameNodata) {
     // A wildcard containing a CNAME whose target does not include
     // data of this type.
-    readAndProcessQuery("q_wild2_aaaa");
+    createAndProcessQuery(Name("www.wild2.example.com"), RRClass::IN(),
+                          RRType::AAAA());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 0);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -489,7 +493,8 @@
 
 TEST_F(DataSrcTest, WildcardCnameNxdomain) {
     // A wildcard containing a CNAME whose target does not exist
-    readAndProcessQuery("q_wild3_a");
+    createAndProcessQuery(Name("www.wild3.example.com"), RRClass::IN(),
+                          RRType::A());
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 6, 0);
 
     RRsetIterator rit = msg.beginSection(Section::ANSWER());
@@ -525,7 +530,8 @@
     EXPECT_EQ(RRClass::IN(), rrset->getClass());
 }
 TEST_F(DataSrcTest, AuthDelegation) {
-    readAndProcessQuery("q_sql1");
+    createAndProcessQuery(Name("www.sql1.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
 
@@ -571,7 +577,8 @@
 }
 
 TEST_F(DataSrcTest, Dname) {
-    readAndProcessQuery("q_dname");
+    createAndProcessQuery(Name("www.dname.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 5, 4, 6);
 
@@ -628,7 +635,8 @@
 }
 
 TEST_F(DataSrcTest, Cname) {
-    readAndProcessQuery("q_cname");
+    createAndProcessQuery(Name("foo.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 0, 0);
 
@@ -646,7 +654,8 @@
 }
 
 TEST_F(DataSrcTest, CnameInt) {
-    readAndProcessQuery("q_cname_int");
+    createAndProcessQuery(Name("cname-int.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
@@ -672,7 +681,8 @@
 }
 
 TEST_F(DataSrcTest, CnameExt) {
-    readAndProcessQuery("q_cname_ext");
+    createAndProcessQuery(Name("cname-ext.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
 
@@ -696,7 +706,8 @@
 }
 
 TEST_F(DataSrcTest, Delegation) {
-    readAndProcessQuery("q_subzone");
+    createAndProcessQuery(Name("www.subzone.example.com"), RRClass::IN(),
+                          RRType::A());
 
     headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
 
@@ -726,7 +737,8 @@
 }
 
 TEST_F(DataSrcTest, NSDelegation) {
-    readAndProcessQuery("q_subzone_ns");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::NS());
 
     headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
 
@@ -758,12 +770,13 @@
 TEST_F(DataSrcTest, ANYZonecut) {
     // An ANY query at a zone cut should behave the same as any other
     // delegation
-    readAndProcessQuery("q_subzone_any");
-
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::ANY());
 }
 
 TEST_F(DataSrcTest, NSECZonecut) {
-    readAndProcessQuery("q_subzone_nsec");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::NSEC());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
 
@@ -791,7 +804,8 @@
 }
 
 TEST_F(DataSrcTest, DNAMEZonecut) {
-    readAndProcessQuery("q_subzone_dname");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::DNAME());
 
     headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
     RRsetIterator rit = msg.beginSection(Section::AUTHORITY());
@@ -820,7 +834,8 @@
 }
 
 TEST_F(DataSrcTest, DS) {
-    readAndProcessQuery("q_subzone_ds");
+    createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
+                          RRType::DS());
 
     headerCheck(msg, Rcode::NOERROR(), true, true, true, 3, 4, 6);
 

Modified: branches/trac191/src/lib/datasrc/tests/query_unittest.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/tests/query_unittest.cc (original)
+++ branches/trac191/src/lib/datasrc/tests/query_unittest.cc Fri Jul 23 09:45:17 2010
@@ -32,20 +32,13 @@
 
 namespace {
 
-class QueryTest : public ::testing::Test {
-protected:
-    void readQuery(Message& m, const char* datafile);
-
-    HotCache cache;
-};
-
 void
-QueryTest::readQuery(Message& m, const char* datafile) {
-    std::vector<unsigned char> data;
-    UnitTestUtil::readWireData(datafile, data);
-
-    InputBuffer buffer(&data[0], data.size());
-    m.fromWire(buffer);
+createQuery(Message& m, const Name& qname, const RRClass& qclass,
+            const RRType& qtype)
+{
+    m.setOpcode(Opcode::QUERY());
+    m.setHeaderFlag(MessageFlag::RD());
+    m.addQuestion(Question(qname, qclass, qtype));
 }
 
 QueryTaskPtr
@@ -58,15 +51,18 @@
 
 // Check the QueryTask created using a temporary RRType object will remain
 // valid.
-TEST_F(QueryTest, constructWithTemporary) {
-    Message m1(Message::PARSE);
-    readQuery(m1, "q_wild_a");
+TEST(QueryTest, constructWithTemporary) {
+    HotCache cache;
+
+    Message m1(Message::RENDER);
+    createQuery(m1, Name("www.wild.example.com"), RRClass::IN(), RRType::A()); 
     QueryTaskPtr task_a = createTask(m1, Name("www.wild.example.com"),
                                         RRType::A(), cache);
     EXPECT_EQ(RRType::A(), task_a->qtype);
 
-    Message m2(Message::PARSE);
-    readQuery(m2, "q_wild_aaaa");
+    Message m2(Message::RENDER);
+    createQuery(m2, Name("www.wild.example.com"), RRClass::IN(),
+                RRType::AAAA());
     QueryTaskPtr task_aaaa = createTask(m2, Name("www.wild.example.com"),
                                         RRType::AAAA(), cache);
     EXPECT_EQ(RRType::AAAA(), task_aaaa->qtype);

Modified: branches/trac191/src/lib/datasrc/tests/static_unittest.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/tests/static_unittest.cc (original)
+++ branches/trac191/src/lib/datasrc/tests/static_unittest.cc Fri Jul 23 09:45:17 2010
@@ -18,7 +18,7 @@
 #include <string>
 #include <vector>
 
-#include "config.h"
+#include <config.h>
 
 #include <gtest/gtest.h>
 

Modified: branches/trac191/src/lib/datasrc/tests/test_datasrc.cc
==============================================================================
--- branches/trac191/src/lib/datasrc/tests/test_datasrc.cc (original)
+++ branches/trac191/src/lib/datasrc/tests/test_datasrc.cc Fri Jul 23 09:45:17 2010
@@ -14,14 +14,14 @@
 
 // $Id$
 
-#include "config.h"
+#include <config.h>
 
 #include <cassert>
 
 #include <algorithm>
 
 #include <dns/tests/unittest_util.h>
-#include "test_datasrc.h"
+#include <datasrc/tests/test_datasrc.h>
 
 #include <datasrc/data_source.h>
 

Modified: branches/trac191/src/lib/dns/Makefile.am
==============================================================================
--- branches/trac191/src/lib/dns/Makefile.am (original)
+++ branches/trac191/src/lib/dns/Makefile.am Fri Jul 23 09:45:17 2010
@@ -57,12 +57,14 @@
 
 lib_LTLIBRARIES = libdns++.la
 
-libdns___la_SOURCES = base32.h base32.cc
-libdns___la_SOURCES += base64.h base64.cc
+libdns___la_SOURCES = util/base32hex.h util/base64.h util/base_n.cc
+libdns___la_SOURCES += util/base32hex_from_binary.h
+libdns___la_SOURCES += util/binary_from_base32hex.h
+libdns___la_SOURCES += util/base16_from_binary.h util/binary_from_base16.h
 libdns___la_SOURCES += buffer.h
 libdns___la_SOURCES += dnssectime.h dnssectime.cc
 libdns___la_SOURCES += exceptions.h exceptions.cc
-libdns___la_SOURCES += hex.h hex.cc
+libdns___la_SOURCES += util/hex.h
 libdns___la_SOURCES += message.h message.cc
 libdns___la_SOURCES += messagerenderer.h messagerenderer.cc
 libdns___la_SOURCES += name.h name.cc
@@ -74,7 +76,7 @@
 libdns___la_SOURCES += rrttl.h rrttl.cc
 libdns___la_SOURCES += rrtype.cc
 libdns___la_SOURCES += question.h question.cc
-libdns___la_SOURCES += sha1.h sha1.cc
+libdns___la_SOURCES += util/sha1.h util/sha1.cc
 libdns___la_SOURCES += tsig.h tsig.cc
 
 nodist_libdns___la_SOURCES = rdataclass.cc rrclass.h rrtype.h
@@ -105,9 +107,6 @@
 	rrtype.h \
 	tsig.h
 # Purposely not installing these headers:
-# base32.h # used only internally, and not actually DNS specific
-# base64.h # used only internally, and not actually DNS specific
-# hex.h # used only internally, and not actually DNS specific
-# sha1.h # used only internally, and not actually DNS specific
+# util/*.h: used only internally, and not actually DNS specific
 # rrclass-placeholder.h
 # rrtype-placeholder.h

Modified: branches/trac191/src/lib/dns/python/libdns_python.cc
==============================================================================
--- branches/trac191/src/lib/dns/python/libdns_python.cc (original)
+++ branches/trac191/src/lib/dns/python/libdns_python.cc Fri Jul 23 09:45:17 2010
@@ -27,7 +27,7 @@
 #include <Python.h>
 #include <structmember.h>
 
-#include "config.h"
+#include <config.h>
 
 #include <exceptions/exceptions.h>
 
@@ -36,22 +36,22 @@
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 
-#include "libdns_python_common.h"
+#include <dns/python/libdns_python_common.h>
 
 // For our 'general' isc::Exception
 static PyObject* po_IscException;
 
 // order is important here!
-#include "messagerenderer_python.cc"
-#include "name_python.cc"           // needs Messagerenderer
-#include "rrclass_python.cc"        // needs Messagerenderer
-#include "rrtype_python.cc"         // needs Messagerenderer
-#include "rrttl_python.cc"          // needs Messagerenderer
-#include "rdata_python.cc"          // needs Type, Class
-#include "rrset_python.cc"          // needs Rdata, RRTTL
-#include "question_python.cc"       // needs RRClass, RRType, RRTTL,
-                                    //       Name
-#include "message_python.cc"        // needs RRset, Question
+#include <dns/python/messagerenderer_python.cc>
+#include <dns/python/name_python.cc>           // needs Messagerenderer
+#include <dns/python/rrclass_python.cc>        // needs Messagerenderer
+#include <dns/python/rrtype_python.cc>         // needs Messagerenderer
+#include <dns/python/rrttl_python.cc>          // needs Messagerenderer
+#include <dns/python/rdata_python.cc>          // needs Type, Class
+#include <dns/python/rrset_python.cc>          // needs Rdata, RRTTL
+#include <dns/python/question_python.cc>       // needs RRClass, RRType, RRTTL,
+                                               // Name
+#include <dns/python/message_python.cc>        // needs RRset, Question
 
 //
 // Definition of the module

Modified: branches/trac191/src/lib/dns/rdata/generic/dnskey_48.cc
==============================================================================
--- branches/trac191/src/lib/dns/rdata/generic/dnskey_48.cc (original)
+++ branches/trac191/src/lib/dns/rdata/generic/dnskey_48.cc Fri Jul 23 09:45:17 2010
@@ -22,7 +22,7 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/foreach.hpp>
 
-#include <dns/base64.h>
+#include <dns/util/base64.h>
 #include <dns/buffer.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>

Modified: branches/trac191/src/lib/dns/rdata/generic/ds_43.cc
==============================================================================
--- branches/trac191/src/lib/dns/rdata/generic/ds_43.cc (original)
+++ branches/trac191/src/lib/dns/rdata/generic/ds_43.cc Fri Jul 23 09:45:17 2010
@@ -22,7 +22,7 @@
 #include <boost/lexical_cast.hpp>
 
 #include <dns/buffer.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
 #include <dns/rdata.h>

Modified: branches/trac191/src/lib/dns/rdata/generic/nsec3_50.cc
==============================================================================
--- branches/trac191/src/lib/dns/rdata/generic/nsec3_50.cc (original)
+++ branches/trac191/src/lib/dns/rdata/generic/nsec3_50.cc Fri Jul 23 09:45:17 2010
@@ -22,10 +22,10 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include <dns/base32.h>
+#include <dns/util/base32hex.h>
 #include <dns/buffer.h>
 #include <dns/exceptions.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
 #include <dns/rrtype.h>
@@ -88,7 +88,7 @@
     if (iss.bad() || iss.fail()) {
         isc_throw(InvalidRdataText, "Invalid NSEC3 hash algorithm");
     }
-    decodeBase32(nextstr, next);
+    decodeBase32Hex(nextstr, next);
 
     uint8_t bitmap[8 * 1024];       // 64k bits
     vector<uint8_t> typebits;
@@ -237,7 +237,7 @@
         " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) +
         " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) +
         " " + encodeHex(impl_->salt_) +
-        " " + encodeBase32(impl_->next_) + s.str());
+        " " + encodeBase32Hex(impl_->next_) + s.str());
 }
 
 void

Modified: branches/trac191/src/lib/dns/rdata/generic/nsec3param_51.cc
==============================================================================
--- branches/trac191/src/lib/dns/rdata/generic/nsec3param_51.cc (original)
+++ branches/trac191/src/lib/dns/rdata/generic/nsec3param_51.cc Fri Jul 23 09:45:17 2010
@@ -22,7 +22,7 @@
 #include <boost/lexical_cast.hpp>
 
 #include <dns/buffer.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
 #include <dns/rdata.h>

Modified: branches/trac191/src/lib/dns/rdata/generic/nsec_47.cc
==============================================================================
--- branches/trac191/src/lib/dns/rdata/generic/nsec_47.cc (original)
+++ branches/trac191/src/lib/dns/rdata/generic/nsec_47.cc Fri Jul 23 09:45:17 2010
@@ -19,7 +19,7 @@
 #include <sstream>
 #include <vector>
 
-#include <dns/base64.h>
+#include <dns/util/base64.h>
 #include <dns/buffer.h>
 #include <dns/exceptions.h>
 #include <dns/messagerenderer.h>

Modified: branches/trac191/src/lib/dns/rdata/generic/rrsig_46.cc
==============================================================================
--- branches/trac191/src/lib/dns/rdata/generic/rrsig_46.cc (original)
+++ branches/trac191/src/lib/dns/rdata/generic/rrsig_46.cc Fri Jul 23 09:45:17 2010
@@ -22,7 +22,7 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include <dns/base64.h>
+#include <dns/util/base64.h>
 #include <dns/buffer.h>
 #include <dns/dnssectime.h>
 #include <dns/messagerenderer.h>

Modified: branches/trac191/src/lib/dns/tests/Makefile.am
==============================================================================
--- branches/trac191/src/lib/dns/tests/Makefile.am (original)
+++ branches/trac191/src/lib/dns/tests/Makefile.am Fri Jul 23 09:45:17 2010
@@ -31,7 +31,7 @@
 run_unittests_SOURCES += question_unittest.cc
 run_unittests_SOURCES += rrparamregistry_unittest.cc
 run_unittests_SOURCES += message_unittest.cc
-run_unittests_SOURCES += base32_unittest.cc
+run_unittests_SOURCES += base32hex_unittest.cc
 run_unittests_SOURCES += base64_unittest.cc
 run_unittests_SOURCES += hex_unittest.cc
 run_unittests_SOURCES += sha1_unittest.cc

Modified: branches/trac191/src/lib/dns/tests/base64_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/base64_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/base64_unittest.cc Fri Jul 23 09:45:17 2010
@@ -18,11 +18,14 @@
 #include <utility>
 #include <vector>
 
-#include <dns/base64.h>
+#include <exceptions/exceptions.h>
+
+#include <dns/util/base64.h>
 
 #include <gtest/gtest.h>
 
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 
 namespace {
@@ -67,18 +70,18 @@
     decodeCheck("Zm9vYmE=\n", decoded_data, "fooba");
 
     // only up to 2 padding characters are allowed
-    EXPECT_THROW(decodeBase64("A===", decoded_data), BadBase64String);
-    EXPECT_THROW(decodeBase64("A= ==", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("A===", decoded_data), BadValue);
+    EXPECT_THROW(decodeBase64("A= ==", decoded_data), BadValue);
 
     // intermediate padding isn't allowed
-    EXPECT_THROW(decodeBase64("YmE=YmE=", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("YmE=YmE=", decoded_data), BadValue);
 
     // Non canonical form isn't allowed.
     // Z => 25(011001), m => 38(100110), 9 => 60(111101), so the padding
     // byte would be 0100 0000.
-    EXPECT_THROW(decodeBase64("Zm9=", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("Zm9=", decoded_data), BadValue);
     // Same for the 1st padding byte.  This would make it 01100000.
-    EXPECT_THROW(decodeBase64("Zm==", decoded_data), BadBase64String);
+    EXPECT_THROW(decodeBase64("Zm==", decoded_data), BadValue);
 }
 
 TEST_F(Base64Test, encode) {

Modified: branches/trac191/src/lib/dns/tests/hex_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/hex_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/hex_unittest.cc Fri Jul 23 09:45:17 2010
@@ -19,25 +19,27 @@
 #include <vector>
 #include <string>
 
-#include <dns/hex.h>
+#include <exceptions/exceptions.h>
+
+#include <dns/util/hex.h>
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-
-using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 
 namespace {
+const string hex_txt("DEADBEEFDECADE");
+const string hex_txt_space("DEAD BEEF DECADE");
+const string hex_txt_lower("deadbeefdecade");
+
 class HexTest : public ::testing::Test {
 protected:
-    HexTest() {}
+    HexTest() : encoding_chars("0123456789ABCDEF") {}
+    vector<uint8_t> decoded_data;
+    const string encoding_chars;
 };
-
-const std::string hex_txt("DEADBEEFDECADE");
-const std::string hex_txt_space("DEAD BEEF DECADE");
-const std::string hex_txt_lower("deadbeefdecade");
 
 TEST_F(HexTest, encodeHex) {
     std::vector<uint8_t> data;
@@ -53,8 +55,7 @@
 }
 
 void
-compareData(const std::vector<uint8_t>& data)
-{
+compareData(const std::vector<uint8_t>& data) {
     EXPECT_EQ(0xde, data[0]);
     EXPECT_EQ(0xad, data[1]);
     EXPECT_EQ(0xbe, data[2]);
@@ -82,7 +83,40 @@
 
     // Bogus input: should fail
     result.clear();
-    EXPECT_THROW(decodeHex("1x", result), BadHexString);
+    EXPECT_THROW(decodeHex("1x", result), BadValue);
+
+    // Bogus input: encoded string must have an even number of characters.
+    result.clear();
+    EXPECT_THROW(decodeHex("dea", result), BadValue);
+}
+
+// For Hex encode/decode we use handmade mappings, so it's prudent to test the
+// entire mapping table explicitly.
+TEST_F(HexTest, decodeMap) {
+    string input("00");       // input placeholder
+
+    // See Base32HexTest.decodeMap for details of the following tests.
+    for (int i = 0; i < 256; ++i) {
+        input[1] = i;
+
+        const char ch = toupper(i);
+        const size_t pos = encoding_chars.find(ch);
+        if (pos == string::npos) {
+            EXPECT_THROW(decodeHex(input, decoded_data), BadValue);
+        } else {
+            decodeHex(input, decoded_data);
+            EXPECT_EQ(1, decoded_data.size());
+            EXPECT_EQ(pos, decoded_data[0]);
+        }
+    }
+}
+
+TEST_F(HexTest, encodeMap) {
+    for (int i = 0; i < 16; ++i) {
+        decoded_data.clear();
+        decoded_data.push_back(i);
+        EXPECT_EQ(encoding_chars[i], encodeHex(decoded_data)[1]);
+    }
 }
 
 }

Modified: branches/trac191/src/lib/dns/tests/message_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/message_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/message_unittest.cc Fri Jul 23 09:45:17 2010
@@ -28,7 +28,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/messagerenderer_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/messagerenderer_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/messagerenderer_unittest.cc Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 #include <gtest/gtest.h>
 

Modified: branches/trac191/src/lib/dns/tests/name_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/name_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/name_unittest.cc Fri Jul 23 09:45:17 2010
@@ -26,7 +26,7 @@
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 #include <gtest/gtest.h>
 

Modified: branches/trac191/src/lib/dns/tests/question_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/question_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/question_unittest.cc Fri Jul 23 09:45:17 2010
@@ -29,7 +29,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_cname_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_cname_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_cname_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_dname_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_dname_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_dname_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_dnskey_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_dnskey_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_dnskey_unittest.cc Fri Jul 23 09:45:17 2010
@@ -16,7 +16,8 @@
 
 #include <string>
 
-#include <dns/base64.h>
+#include <exceptions/exceptions.h>
+
 #include <dns/buffer.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
@@ -26,11 +27,12 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
@@ -48,21 +50,18 @@
                   "7+ysyLKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA"
                   "8lVUgEf/rzeC/bByBNsO70aEFTd");
 
-TEST_F(Rdata_DNSKEY_Test, fromText)
-{
+TEST_F(Rdata_DNSKEY_Test, fromText) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(dnskey_txt, rdata_dnskey.toText());
 }
 
-TEST_F(Rdata_DNSKEY_Test, assign)
-{
+TEST_F(Rdata_DNSKEY_Test, assign) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     generic::DNSKEY rdata_dnskey2 = rdata_dnskey;
     EXPECT_EQ(0, rdata_dnskey.compare(rdata_dnskey2));
 }
 
-TEST_F(Rdata_DNSKEY_Test, badText)
-{
+TEST_F(Rdata_DNSKEY_Test, badText) {
     EXPECT_THROW(generic::DNSKEY("257 3 5"),
                  InvalidRdataText);
     EXPECT_THROW(generic::DNSKEY("99999 3 5 BAAAAAAAAAAAD"),
@@ -71,9 +70,10 @@
                  InvalidRdataText);
     EXPECT_THROW(generic::DNSKEY("257 3 500 BAAAAAAAAAAAD"),
                  InvalidRdataText);
-    EXPECT_THROW(generic::DNSKEY("257 3 5 BAAAAAAAAAAAD"),
-                 BadBase64String);
-#if 0
+    EXPECT_THROW(generic::DNSKEY("257 3 5 BAAAAAAAAAAAD"), BadValue);
+}
+
+TEST_F(Rdata_DNSKEY_Test, DISABLED_badText) {
     // Should this be allowed?  Probably not.  But the test currently fails.
     EXPECT_THROW(generic::DNSKEY("257 3 5BEAAEFTd"),
                  InvalidRdataText);
@@ -81,11 +81,9 @@
     // it could be ambiguous '51 EAAA' vs '5 1EAA..'
     EXPECT_THROW(generic::DNSKEY("257 3 51EAAEFTd"),
                  InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_DNSKEY_Test, toWireRenderer)
-{
+TEST_F(Rdata_DNSKEY_Test, toWireRenderer) {
     renderer.skip(2);
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     rdata_dnskey.toWire(renderer);
@@ -97,34 +95,29 @@
                         obuffer.getLength() - 2, &data[2], data.size() - 2);
 }
 
-TEST_F(Rdata_DNSKEY_Test, toWireBuffer)
-{
+TEST_F(Rdata_DNSKEY_Test, toWireBuffer) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     rdata_dnskey.toWire(obuffer);
 }
 
-TEST_F(Rdata_DNSKEY_Test, createFromWire)
-{
+TEST_F(Rdata_DNSKEY_Test, createFromWire) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(0, rdata_dnskey.compare(
                   *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"),
                                         "rdata_dnskey_fromWire")));
 }
 
-TEST_F(Rdata_DNSKEY_Test, getTag)
-{
+TEST_F(Rdata_DNSKEY_Test, getTag) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(12892, rdata_dnskey.getTag());
 }
 
-TEST_F(Rdata_DNSKEY_Test, getAlgorithm)
-{
+TEST_F(Rdata_DNSKEY_Test, getAlgorithm) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(5, rdata_dnskey.getAlgorithm());
 }
 
-TEST_F(Rdata_DNSKEY_Test, getFlags)
-{
+TEST_F(Rdata_DNSKEY_Test, getFlags) {
     generic::DNSKEY rdata_dnskey(dnskey_txt);
     EXPECT_EQ(257, rdata_dnskey.getFlags());
 }

Modified: branches/trac191/src/lib/dns/tests/rdata_ds_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_ds_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_ds_unittest.cc Fri Jul 23 09:45:17 2010
@@ -25,8 +25,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_in_a_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_in_a_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_in_a_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_in_aaaa_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_in_aaaa_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_mx_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_mx_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_mx_unittest.cc Fri Jul 23 09:45:17 2010
@@ -23,8 +23,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
@@ -38,14 +38,12 @@
 
 const generic::MX rdata_mx(10, Name("mx.example.com"));
 
-TEST_F(Rdata_MX_Test, createFromText)
-{
+TEST_F(Rdata_MX_Test, createFromText) {
     const generic::MX rdata_mx2("10 mx.example.com");
     EXPECT_EQ(0, rdata_mx2.compare(rdata_mx));
 }
 
-TEST_F(Rdata_MX_Test, badText)
-{
+TEST_F(Rdata_MX_Test, badText) {
     EXPECT_THROW(const generic::MX rdata_mx("99999999 mx."), InvalidRdataText);
     EXPECT_THROW(const generic::MX rdata_mx("10"), InvalidRdataText);
     EXPECT_THROW(const generic::MX rdata_mx("SPOON"), InvalidRdataText);
@@ -53,22 +51,19 @@
                  InvalidRdataText);
 }
 
-TEST_F(Rdata_MX_Test, copy)
-{
+TEST_F(Rdata_MX_Test, copy) {
     const generic::MX rdata_mx2(rdata_mx);
     EXPECT_EQ(0, rdata_mx.compare(rdata_mx2));
 }
 
-TEST_F(Rdata_MX_Test, createFromWire)
-{
+TEST_F(Rdata_MX_Test, createFromWire) {
     EXPECT_EQ(0, rdata_mx.compare(
                   *rdataFactoryFromFile(RRType("MX"), RRClass("IN"),
                                         "rdata_mx_fromWire")));
     // TBD: more tests
 }
 
-TEST_F(Rdata_MX_Test, toWireRenderer)
-{
+TEST_F(Rdata_MX_Test, toWireRenderer) {
     renderer.writeName(Name("example.com"));
     rdata_mx.toWire(renderer);
 
@@ -78,37 +73,32 @@
                         obuffer.getLength(), &data[0], data.size());
 }
 
-TEST_F(Rdata_MX_Test, toWireBuffer)
-{
+TEST_F(Rdata_MX_Test, toWireBuffer) {
     renderer.writeName(Name("example.com"));
     rdata_mx.toWire(obuffer);
+}
 
-#if 0
+TEST_F(Rdata_MX_Test, DISABLED_toWireBuffer) {
 // XXX: does not pass
     vector<unsigned char> data;
     UnitTestUtil::readWireData("rdata_mx_toWire1", data);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
                         obuffer.getLength(), &data[0], data.size());
-#endif
 }
 
-TEST_F(Rdata_MX_Test, toText)
-{
+TEST_F(Rdata_MX_Test, toText) {
     EXPECT_EQ("10 mx.example.com.", rdata_mx.toText());
 }
 
-TEST_F(Rdata_MX_Test, getMXName)
-{
+TEST_F(Rdata_MX_Test, getMXName) {
     EXPECT_EQ(Name("mx.example.com."), rdata_mx.getMXName());
 }
 
-TEST_F(Rdata_MX_Test, getMXPref)
-{
+TEST_F(Rdata_MX_Test, getMXPref) {
     EXPECT_EQ(10, rdata_mx.getMXPref());
 }
 
-TEST_F(Rdata_MX_Test, compare)
-{
+TEST_F(Rdata_MX_Test, compare) {
     generic::MX small1(1, Name("mx.example.com"));
     generic::MX small2(10, Name("mx.example.com"));
     generic::MX large1(65535, Name("mx.example.com"));

Modified: branches/trac191/src/lib/dns/tests/rdata_ns_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_ns_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_ns_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_nsec3_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_nsec3_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_nsec3_unittest.cc Fri Jul 23 09:45:17 2010
@@ -16,10 +16,11 @@
 
 #include <string>
 
-#include <dns/base32.h>
+#include <exceptions/exceptions.h>
+
 #include <dns/buffer.h>
 #include <dns/exceptions.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
@@ -28,60 +29,64 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
 namespace {
 class Rdata_NSEC3_Test : public RdataTest {
     // there's nothing to specialize
+public:
+    Rdata_NSEC3_Test() :
+        nsec3_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+                  "NS SOA RRSIG DNSKEY NSEC3PARAM") {}
+    string nsec3_txt;
 };
-string nsec3_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
-                 "NS SOA RRSIG DNSKEY NSEC3PARAM");
 
-
-TEST_F(Rdata_NSEC3_Test, toText)
-{
+TEST_F(Rdata_NSEC3_Test, toText) {
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     EXPECT_EQ(nsec3_txt, rdata_nsec3.toText());
 }
 
-TEST_F(Rdata_NSEC3_Test, badText)
-{
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEE "
+TEST_F(Rdata_NSEC3_Test, badText) {
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "BIFF POW SPOON"),
                  InvalidRdataText);
     EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEE "
                                             "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW "
                                             "A NS SOA"),
-                 BadBase32String);
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1000000 1 1 ADDAFEE "
+                 BadValue);     // bad hex
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEEE "
+                                            "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW "
+                                            "A NS SOA"),
+                 BadValue);     // bad base32hex
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1000000 1 1 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "A NS SOA"),
                  InvalidRdataText);
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1000000 1 ADDAFEE "
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1000000 1 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "A NS SOA"),
                  InvalidRdataText);
-    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1000000 ADDAFEE "
+    EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1000000 ADDAFEEE "
                                             "0123456789ABCDEFGHIJKLMNOPQRSTUV "
                                             "A NS SOA"),
                  InvalidRdataText);
+}
 
-#if 0 // this currently fails
+TEST_F(Rdata_NSEC3_Test, DISABLED_badText) { // this currently fails
     EXPECT_THROW(generic::NSEC3(
                      "1 1 1D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
                      "NS SOA RRSIG DNSKEY NSEC3PARAM"), InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_NSEC3_Test, createFromWire)
-{
+TEST_F(Rdata_NSEC3_Test, createFromWire) {
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     EXPECT_EQ(0, rdata_nsec3.compare(
                   *rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
@@ -98,8 +103,7 @@
                  DNSMessageFORMERR);
 }
 
-TEST_F(Rdata_NSEC3_Test, toWireRenderer)
-{
+TEST_F(Rdata_NSEC3_Test, toWireRenderer) {
     renderer.skip(2);
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     rdata_nsec3.toWire(renderer);
@@ -111,14 +115,12 @@
                         obuffer.getLength() - 2, &data[2], data.size() - 2);
 }
 
-TEST_F(Rdata_NSEC3_Test, toWireBuffer)
-{
+TEST_F(Rdata_NSEC3_Test, toWireBuffer) {
     const generic::NSEC3 rdata_nsec3(nsec3_txt);
     rdata_nsec3.toWire(obuffer);
 }
 
-TEST_F(Rdata_NSEC3_Test, assign)
-{
+TEST_F(Rdata_NSEC3_Test, assign) {
     generic::NSEC3 rdata_nsec3(nsec3_txt);
     generic::NSEC3 other_nsec3 = rdata_nsec3;
     EXPECT_EQ(0, rdata_nsec3.compare(other_nsec3));

Modified: branches/trac191/src/lib/dns/tests/rdata_nsec3param_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_nsec3param_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_nsec3param_unittest.cc Fri Jul 23 09:45:17 2010
@@ -16,9 +16,11 @@
 
 #include <string>
 
-#include <dns/base32.h>
+#include <exceptions/exceptions.h>
+
+#include <dns/util/base32hex.h>
 #include <dns/buffer.h>
-#include <dns/hex.h>
+#include <dns/util/hex.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
@@ -27,11 +29,12 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
@@ -41,35 +44,32 @@
 };
 string nsec3param_txt("1 0 1 D399EAAB");
 
-TEST_F(Rdata_NSEC3PARAM_Test, toText)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, toText) {
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     EXPECT_EQ(nsec3param_txt, rdata_nsec3param.toText());
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, badText)
-{
-    EXPECT_THROW(generic::NSEC3PARAM("1 1 1 SPORK"), BadHexString);
+TEST_F(Rdata_NSEC3PARAM_Test, badText) {
+    EXPECT_THROW(generic::NSEC3PARAM("1 1 1 SPORK"), BadValue); // bad hex
     EXPECT_THROW(generic::NSEC3PARAM("100000 1 1 ADDAFEE"), InvalidRdataText);
     EXPECT_THROW(generic::NSEC3PARAM("1 100000 1 ADDAFEE"), InvalidRdataText);
     EXPECT_THROW(generic::NSEC3PARAM("1 1 100000 ADDAFEE"), InvalidRdataText);
     EXPECT_THROW(generic::NSEC3PARAM("1"), InvalidRdataText);
-
-#if 0                           // this currently fails
-    EXPECT_THROW(generic::NSEC3PARAM("1 0 1D399EAAB"), InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, createFromWire)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, DISABLED_badText) {
+    // this currently fails
+    EXPECT_THROW(generic::NSEC3PARAM("1 0 1D399EAAB"), InvalidRdataText);
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, createFromWire) {
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     EXPECT_EQ(0, rdata_nsec3param.compare(
                   *rdataFactoryFromFile(RRType::NSEC3PARAM(), RRClass::IN(),
                                        "rdata_nsec3param_fromWire1")));
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer) {
     renderer.skip(2);
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     rdata_nsec3param.toWire(renderer);
@@ -81,14 +81,12 @@
                         obuffer.getLength() - 2, &data[2], data.size() - 2);
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) {
     const generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     rdata_nsec3param.toWire(obuffer);
 }
 
-TEST_F(Rdata_NSEC3PARAM_Test, assign)
-{
+TEST_F(Rdata_NSEC3PARAM_Test, assign) {
     generic::NSEC3PARAM rdata_nsec3param(nsec3param_txt);
     generic::NSEC3PARAM other_nsec3param = rdata_nsec3param;
     EXPECT_EQ(0, rdata_nsec3param.compare(other_nsec3param));

Modified: branches/trac191/src/lib/dns/tests/rdata_nsec_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_nsec_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_nsec_unittest.cc Fri Jul 23 09:45:17 2010
@@ -26,8 +26,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_opt_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_opt_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_opt_unittest.cc Fri Jul 23 09:45:17 2010
@@ -23,8 +23,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_ptr_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_ptr_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_ptr_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_rrsig_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_rrsig_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_rrsig_unittest.cc Fri Jul 23 09:45:17 2010
@@ -14,7 +14,8 @@
 
 // $Id$
 
-#include <dns/base64.h>
+#include <exceptions/exceptions.h>
+
 #include <dns/buffer.h>
 #include <dns/dnssectime.h>
 #include <dns/messagerenderer.h>
@@ -25,11 +26,12 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;
+using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 
@@ -38,8 +40,7 @@
     // there's nothing to specialize
 };
 
-TEST_F(Rdata_RRSIG_Test, fromText)
-{
+TEST_F(Rdata_RRSIG_Test, fromText) {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -50,8 +51,7 @@
 
 }
 
-TEST_F(Rdata_RRSIG_Test, badText)
-{
+TEST_F(Rdata_RRSIG_Test, badText) {
     EXPECT_THROW(const generic::RRSIG sig("SPORK"), InvalidRdataText);
     EXPECT_THROW(const generic::RRSIG sig("A 555 4 43200 "
                      "20100223214617 20100222214617 8496 isc.org. "
@@ -83,20 +83,21 @@
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
                      "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
                      "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidRdataText);
-    EXPECT_THROW(const generic::RRSIG sig("A 5 4 43200 "
+    EXPECT_THROW(const generic::RRSIG sig(
+                     "A 5 4 43200 "
                      "20100223214617 20100222214617 8496 isc.org. "
                      "EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="),
-                     BadBase64String);
+                 BadValue);     // bad base64 input
+}
 
-#if 0                           // this currently fails
+TEST_F(Rdata_RRSIG_Test, DISABLED_badText) {
+    // this currently fails
     // no space between the tag and signer
     EXPECT_THROW(generic::RRSIG("A 5 4 43200 20100223214617 20100222214617 "
                                 "8496isc.org. ofc="), InvalidRdataText);
-#endif
 }
 
-TEST_F(Rdata_RRSIG_Test, toWireRenderer)
-{
+TEST_F(Rdata_RRSIG_Test, toWireRenderer) {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -106,8 +107,7 @@
     rdata_rrsig.toWire(renderer);
 }
 
-TEST_F(Rdata_RRSIG_Test, toWireBuffer)
-{
+TEST_F(Rdata_RRSIG_Test, toWireBuffer) {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -117,8 +117,7 @@
     rdata_rrsig.toWire(obuffer);
 }
 
-TEST_F(Rdata_RRSIG_Test, createFromWire)
-{
+TEST_F(Rdata_RRSIG_Test, createFromWire) {
     string rrsig_txt("A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
                 "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
                 "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"

Modified: branches/trac191/src/lib/dns/tests/rdata_soa_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_soa_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_soa_unittest.cc Fri Jul 23 09:45:17 2010
@@ -23,8 +23,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_txt_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_txt_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_txt_unittest.cc Fri Jul 23 09:45:17 2010
@@ -24,8 +24,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rdata_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rdata_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rdata_unittest.cc Fri Jul 23 09:45:17 2010
@@ -27,8 +27,8 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
-#include "rdata_unittest.h"
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/rrclass_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rrclass_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rrclass_unittest.cc Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rrclass.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 using namespace isc;

Modified: branches/trac191/src/lib/dns/tests/rrset_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rrset_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rrset_unittest.cc Fri Jul 23 09:45:17 2010
@@ -28,7 +28,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 

Modified: branches/trac191/src/lib/dns/tests/rrttl_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rrttl_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rrttl_unittest.cc Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rrttl.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 using namespace isc;

Modified: branches/trac191/src/lib/dns/tests/rrtype_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/rrtype_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/rrtype_unittest.cc Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 #include <dns/messagerenderer.h>
 #include <dns/rrtype.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 using namespace isc;

Modified: branches/trac191/src/lib/dns/tests/run_unittests.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/run_unittests.cc (original)
+++ branches/trac191/src/lib/dns/tests/run_unittests.cc Fri Jul 23 09:45:17 2010
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 int
 main(int argc, char* argv[]) {

Modified: branches/trac191/src/lib/dns/tests/sha1_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/sha1_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/sha1_unittest.cc Fri Jul 23 09:45:17 2010
@@ -17,11 +17,11 @@
 #include <stdint.h>
 #include <string>
 
-#include <dns/sha1.h>
+#include <dns/util/sha1.h>
 
 #include <gtest/gtest.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/tsig_unittest.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/tsig_unittest.cc (original)
+++ branches/trac191/src/lib/dns/tests/tsig_unittest.cc Fri Jul 23 09:45:17 2010
@@ -18,7 +18,7 @@
 
 #include <dns/tsig.h>
 
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using isc::UnitTestUtil;
 using namespace std;

Modified: branches/trac191/src/lib/dns/tests/unittest_util.cc
==============================================================================
--- branches/trac191/src/lib/dns/tests/unittest_util.cc (original)
+++ branches/trac191/src/lib/dns/tests/unittest_util.cc Fri Jul 23 09:45:17 2010
@@ -26,7 +26,7 @@
 #include <gtest/gtest.h>
 
 #include <dns/name.h>
-#include "unittest_util.h"
+#include <dns/tests/unittest_util.h>
 
 using namespace std;
 

Modified: branches/trac191/src/lib/exceptions/Makefile.am
==============================================================================
--- branches/trac191/src/lib/exceptions/Makefile.am (original)
+++ branches/trac191/src/lib/exceptions/Makefile.am Fri Jul 23 09:45:17 2010
@@ -1,3 +1,4 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CXXFLAGS=$(B10_CXXFLAGS)
 
 lib_LTLIBRARIES = libexceptions.la
@@ -10,7 +11,7 @@
 TESTS += run_unittests
 run_unittests_SOURCES = run_unittests.cc
 run_unittests_SOURCES += exceptions_unittest.cc
-run_unittests_CPPFLAGS = $(GTEST_INCLUDES)
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(GTEST_LDFLAGS)
 run_unittests_LDADD = .libs/libexceptions.a $(GTEST_LDADD)
 endif

Modified: branches/trac191/src/lib/exceptions/exceptions.cc
==============================================================================
--- branches/trac191/src/lib/exceptions/exceptions.cc (original)
+++ branches/trac191/src/lib/exceptions/exceptions.cc Fri Jul 23 09:45:17 2010
@@ -16,7 +16,7 @@
 
 #include <string>
 
-#include "exceptions.h"
+#include <exceptions/exceptions.h>
 
 using isc::Exception;
 

Modified: branches/trac191/src/lib/exceptions/exceptions.h
==============================================================================
--- branches/trac191/src/lib/exceptions/exceptions.h (original)
+++ branches/trac191/src/lib/exceptions/exceptions.h Fri Jul 23 09:45:17 2010
@@ -104,7 +104,7 @@
 };
 
 ///
-/// \brief A standard DNS module exception that is thrown if a parameter give
+/// \brief A generic exception that is thrown if a parameter given
 /// to a method would refer to or modify out-of-range data.
 ///
 class OutOfRange : public Exception {
@@ -114,7 +114,17 @@
 };
 
 ///
-/// \brief A standard DNS module exception that is thrown when an unexpected
+/// \brief A generic exception that is thrown if a parameter given
+/// to a method is considered invalid in that context.
+///
+class BadValue : public Exception {
+public:
+    BadValue(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+///
+/// \brief A generic exception that is thrown when an unexpected
 /// error condition occurs.
 ///
 class Unexpected : public Exception {

Modified: branches/trac191/src/lib/exceptions/exceptions_unittest.cc
==============================================================================
--- branches/trac191/src/lib/exceptions/exceptions_unittest.cc (original)
+++ branches/trac191/src/lib/exceptions/exceptions_unittest.cc Fri Jul 23 09:45:17 2010
@@ -17,7 +17,7 @@
 #include <stdexcept>
 #include <string>
 
-#include "exceptions.h"
+#include <exceptions/exceptions.h>
 
 #include <gtest/gtest.h>
 

Modified: branches/trac191/src/lib/python/isc/cc/data.py
==============================================================================
--- branches/trac191/src/lib/python/isc/cc/data.py (original)
+++ branches/trac191/src/lib/python/isc/cc/data.py Fri Jul 23 09:45:17 2010
@@ -20,7 +20,7 @@
 # (int, real, bool, string, list and dict respectively)
 #
 
-import ast
+import json
 
 class DataNotFoundError(Exception): pass
 class DataTypeError(Exception): pass
@@ -134,7 +134,7 @@
     if type(value_str) != str:
         return None
     try:
-        return ast.literal_eval(value_str)
+        return json.loads(value_str)
     except ValueError as ve:
         # simply return the string itself
         return value_str

Modified: branches/trac191/src/lib/python/isc/cc/tests/data_test.py
==============================================================================
--- branches/trac191/src/lib/python/isc/cc/tests/data_test.py (original)
+++ branches/trac191/src/lib/python/isc/cc/tests/data_test.py Fri Jul 23 09:45:17 2010
@@ -137,13 +137,13 @@
         
     def test_parse_value_str(self):
         self.assertEqual(data.parse_value_str("1"), 1)
-        self.assertEqual(data.parse_value_str("True"), True)
-        self.assertEqual(data.parse_value_str("None"), None)
+        self.assertEqual(data.parse_value_str("true"), True)
+        self.assertEqual(data.parse_value_str("null"), None)
         self.assertEqual(data.parse_value_str("1.1"), 1.1)
         self.assertEqual(data.parse_value_str("[]"), [])
-        self.assertEqual(data.parse_value_str("[ 1, None, 'asdf' ]"), [ 1, None, "asdf" ])
+        self.assertEqual(data.parse_value_str("[ 1, null, \"asdf\" ]"), [ 1, None, "asdf" ])
         self.assertEqual(data.parse_value_str("{}"), {})
-        self.assertEqual(data.parse_value_str("{ 'a': 'b', 'c': 1 }"), { 'a': 'b', 'c': 1 })
+        self.assertEqual(data.parse_value_str("{ \"a\": \"b\", \"c\": 1 }"), { 'a': 'b', 'c': 1 })
         self.assertEqual(data.parse_value_str("[ a c"), "[ a c")
 
 if __name__ == '__main__':

Modified: branches/trac191/src/lib/python/isc/config/ccsession.py
==============================================================================
--- branches/trac191/src/lib/python/isc/config/ccsession.py (original)
+++ branches/trac191/src/lib/python/isc/config/ccsession.py Fri Jul 23 09:45:17 2010
@@ -183,10 +183,10 @@
         if msg and not 'result' in msg:
             answer = None
             try:
+                module_name = env['group']
                 cmd, arg = isc.config.ccsession.parse_command(msg)
                 if cmd == COMMAND_CONFIG_UPDATE:
                     new_config = arg
-                    module_name = env['group']
                     # If the target channel was not this module
                     # it might be in the remote_module_configs
                     if module_name != self._module_name:
@@ -213,10 +213,12 @@
                             isc.cc.data.merge(newc, new_config)
                             self.set_local_config(newc)
                 else:
-                    if self._command_handler:
-                        answer = self._command_handler(cmd, arg)
-                    else:
-                        answer = create_answer(2, self._module_name + " has no command handler")
+                    # ignore commands for 'remote' modules
+                    if module_name == self._module_name:
+                        if self._command_handler:
+                            answer = self._command_handler(cmd, arg)
+                        else:
+                            answer = create_answer(2, self._module_name + " has no command handler")
             except Exception as exc:
                 answer = create_answer(1, str(exc))
             if answer:

Modified: branches/trac191/src/lib/python/isc/config/cfgmgr.py
==============================================================================
--- branches/trac191/src/lib/python/isc/config/cfgmgr.py (original)
+++ branches/trac191/src/lib/python/isc/config/cfgmgr.py Fri Jul 23 09:45:17 2010
@@ -22,10 +22,10 @@
 import isc
 import signal
 import ast
-import pprint
 import os
 import copy
 import tempfile
+import json
 from isc.cc import data
 from isc.config import ccsession
 
@@ -67,7 +67,7 @@
         config = ConfigManagerData(data_path, file_name)
         try:
             file = open(config.db_filename, 'r')
-            file_config = ast.literal_eval(file.read())
+            file_config = json.loads(file.read())
             if 'version' in file_config and \
                 file_config['version'] == ConfigManagerData.CONFIG_VERSION:
                 config.data = file_config
@@ -93,9 +93,7 @@
                                                dir=self.data_path,
                                                delete=False)
             filename = file.name
-            pp = pprint.PrettyPrinter(indent=4)
-            s = pp.pformat(self.data)
-            file.write(s)
+            file.write(json.dumps(self.data))
             file.write("\n")
             file.close()
             if output_file_name:

Modified: branches/trac191/src/lib/python/isc/config/module_spec.py
==============================================================================
--- branches/trac191/src/lib/python/isc/config/module_spec.py (original)
+++ branches/trac191/src/lib/python/isc/config/module_spec.py Fri Jul 23 09:45:17 2010
@@ -21,7 +21,8 @@
    set of data against the specification
 """
 
-import ast
+import json
+import sys
 
 import isc.cc.data
 
@@ -37,19 +38,29 @@
 def module_spec_from_file(spec_file, check = True):
     """Returns a ModuleSpec object defined by the file at spec_file.
        If check is True, the contents are verified. If there is an error
-       in those contents, a ModuleSpecError is raised."""
+       in those contents, a ModuleSpecError is raised.
+       A ModuleSpecError is also raised if the file cannot be read, or
+       if it is not valid JSON."""
     module_spec = None
-    if hasattr(spec_file, 'read'):
-        module_spec = ast.literal_eval(spec_file.read(-1))
-    elif type(spec_file) == str:
-        file = open(spec_file)
-        module_spec = ast.literal_eval(file.read(-1))
-        file.close()
-    else:
-        raise ModuleSpecError("spec_file not a str or file-like object")
+    try:
+        if hasattr(spec_file, 'read'):
+            json_str = spec_file.read()
+            module_spec = json.loads(json_str)
+        elif type(spec_file) == str:
+            file = open(spec_file)
+            json_str = file.read()
+            module_spec = json.loads(json_str)
+            file.close()
+        else:
+            raise ModuleSpecError("spec_file not a str or file-like object")
+    except ValueError as ve:
+        raise ModuleSpecError("JSON parse error: " + str(ve))
+    except IOError as ioe:
+        raise ModuleSpecError("JSON read error: " + str(ioe))
+
     if 'module_spec' not in module_spec:
         raise ModuleSpecError("Data definition has no module_spec element")
-        
+
     result = ModuleSpec(module_spec['module_spec'], check)
     return result
 

Modified: branches/trac191/src/lib/python/isc/config/tests/ccsession_test.py
==============================================================================
--- branches/trac191/src/lib/python/isc/config/tests/ccsession_test.py (original)
+++ branches/trac191/src/lib/python/isc/config/tests/ccsession_test.py Fri Jul 23 09:45:17 2010
@@ -377,7 +377,34 @@
         mccs = None
         self.assertFalse("Spec2" in fake_session.subscriptions)
         
-    
+    def test_ignore_command_remote_module(self):
+        # Create a Spec1 module and subscribe to remote config for Spec2
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        mccs.set_command_handler(self.my_command_handler_ok)
+        rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
+
+        # remove the 'get config' from the queue
+        self.assertEqual(len(fake_session.message_queue), 1)
+        fake_session.get_message("ConfigManager")
+
+        # check if the command for the module itself is received
+        cmd = isc.config.ccsession.create_command("just_some_command", { 'foo': 'a' })
+        fake_session.group_sendmsg(cmd, 'Spec1')
+        self.assertEqual(len(fake_session.message_queue), 1)
+        mccs.check_command()
+        self.assertEqual(len(fake_session.message_queue), 1)
+        self.assertEqual({'result': [ 0 ]},
+                         fake_session.get_message('Spec1', None))
+
+        # check if the command for the other module is ignored
+        cmd = isc.config.ccsession.create_command("just_some_command", { 'foo': 'a' })
+        fake_session.group_sendmsg(cmd, 'Spec2')
+        self.assertEqual(len(fake_session.message_queue), 1)
+        mccs.check_command()
+        self.assertEqual(len(fake_session.message_queue), 0)
+        
+
 class fakeUIConn():
     def __init__(self):
         self.get_answers = {}

Modified: branches/trac191/src/lib/python/isc/config/tests/module_spec_test.py
==============================================================================
--- branches/trac191/src/lib/python/isc/config/tests/module_spec_test.py (original)
+++ branches/trac191/src/lib/python/isc/config/tests/module_spec_test.py Fri Jul 23 09:45:17 2010
@@ -54,6 +54,13 @@
 
     def test_open_bad_file_obj(self):
         self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, 1)
+        # contains single quotes which json parser does not accept
+        
+        self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, self.spec_file("spec28.spec"), False)
+        my_spec_file = open(self.spec_file("spec28.spec"))
+        self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, my_spec_file, False)
+
+        self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, self.spec_file("does_not_exist"), False)
 
     def test_bad_specfiles(self):
         self.assertRaises(ModuleSpecError, self.read_spec_file, "spec3.spec")

Modified: branches/trac191/src/lib/xfr/fd_share.cc
==============================================================================
--- branches/trac191/src/lib/xfr/fd_share.cc (original)
+++ branches/trac191/src/lib/xfr/fd_share.cc Fri Jul 23 09:45:17 2010
@@ -21,7 +21,7 @@
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <stdlib.h>             // for malloc and free
-#include "fd_share.h"
+#include <xfr/fd_share.h>
 
 namespace isc {
 namespace xfr {

Modified: branches/trac191/src/lib/xfr/fdshare_python.cc
==============================================================================
--- branches/trac191/src/lib/xfr/fdshare_python.cc (original)
+++ branches/trac191/src/lib/xfr/fdshare_python.cc Fri Jul 23 09:45:17 2010
@@ -18,9 +18,9 @@
 #include <Python.h>
 #include <structmember.h>
 
-#include "config.h"
+#include <config.h>
 
-#include "fd_share.h"
+#include <xfr/fd_share.h>
 
 static PyObject*
 fdshare_recv_fd(PyObject *self UNUSED_PARAM, PyObject *args)

Modified: branches/trac191/src/lib/xfr/python_xfr.cc
==============================================================================
--- branches/trac191/src/lib/xfr/python_xfr.cc (original)
+++ branches/trac191/src/lib/xfr/python_xfr.cc Fri Jul 23 09:45:17 2010
@@ -23,7 +23,7 @@
 #include <boost/python/copy_const_reference.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include "fd_share.h"
+#include <xfr/fd_share.h>
 
 using namespace isc::xfr;
 using namespace boost::python;

Modified: branches/trac191/src/lib/xfr/xfrout_client.cc
==============================================================================
--- branches/trac191/src/lib/xfr/xfrout_client.cc (original)
+++ branches/trac191/src/lib/xfr/xfrout_client.cc Fri Jul 23 09:45:17 2010
@@ -22,8 +22,8 @@
 #include <unistd.h>
 #include <asio.hpp>
 
-#include "fd_share.h"
-#include "xfrout_client.h"
+#include <xfr/fd_share.h>
+#include <xfr/xfrout_client.h>
 
 using namespace std;
 using asio::local::stream_protocol;
@@ -54,16 +54,25 @@
 
 void
 XfroutClient::connect() {
-    impl_->socket_.connect(stream_protocol::endpoint(impl_->file_path_));
+    asio::error_code err;
+    impl_->socket_.connect(stream_protocol::endpoint(impl_->file_path_), err);
+    if (err) {
+        isc_throw(XfroutError, "socket connect failed: " << err.message());
+    }
 }
 
 void
 XfroutClient::disconnect() {
-    impl_->socket_.close();
+    asio::error_code err;
+    impl_->socket_.close(err);
+    if (err) {
+        isc_throw(XfroutError, "close socket failed: " << err.message());
+    }
 }
 
 int 
-XfroutClient::sendXfroutRequestInfo(const int tcp_sock, uint8_t* msg_data,
+XfroutClient::sendXfroutRequestInfo(const int tcp_sock,
+                                    const void* const msg_data,
                                     const uint16_t msg_len)
 {
     if (-1 == send_fd(impl_->socket_.native(), tcp_sock)) {
@@ -71,7 +80,8 @@
                   "Fail to send the socket file descriptor to xfrout module");
     }
 
-    // XXX: this shouldn't be blocking send, even though it's unlikely to block.
+    // XXX: this shouldn't be blocking send, even though it's unlikely to
+    // block.
     const uint8_t lenbuf[2] = { msg_len >> 8, msg_len & 0xff };
     if (send(impl_->socket_.native(), lenbuf, sizeof(lenbuf), 0) !=
         sizeof(lenbuf)) {

Modified: branches/trac191/src/lib/xfr/xfrout_client.h
==============================================================================
--- branches/trac191/src/lib/xfr/xfrout_client.h (original)
+++ branches/trac191/src/lib/xfr/xfrout_client.h Fri Jul 23 09:45:17 2010
@@ -34,7 +34,39 @@
         isc::Exception(file, line, what) {}
 };
 
-class XfroutClient {
+/// \brief The AbstractXfroutClient class is an abstract base class that
+/// defines the interfaces of XfroutClient.
+///
+/// The intended primary usage of abstraction is to allow tests for the
+/// user class of XfroutClient without requiring actual communication.
+class AbstractXfroutClient {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are
+    /// intentionally defined as private to make it explicit that this is a
+    /// pure base class.
+    //@{
+private:
+    AbstractXfroutClient(const AbstractXfroutClient& source);
+    AbstractXfroutClient& operator=(const AbstractXfroutClient& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class should
+    /// never be instantiated (except as part of a derived class).
+    AbstractXfroutClient() {}
+public:
+    /// \brief The destructor.
+    virtual ~AbstractXfroutClient() {}
+    //@}
+    virtual void connect() = 0;
+    virtual void disconnect() = 0;
+    virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+                                      uint16_t msg_len) = 0;
+};
+
+class XfroutClient : public AbstractXfroutClient {
 public:
     XfroutClient(const std::string& file);
     ~XfroutClient();
@@ -43,10 +75,10 @@
     XfroutClient(const XfroutClient& source);
     XfroutClient& operator=(const XfroutClient& source);
 public:
-    void connect();
-    void disconnect();
-    int sendXfroutRequestInfo(int tcp_sock, uint8_t* msg_data,
-                              uint16_t msg_len);
+    virtual void connect();
+    virtual void disconnect();
+    virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+                                      uint16_t msg_len);
 private:
     XfroutClientImpl* impl_;
 };




More information about the bind10-changes mailing list