[svn] commit: r2586 - in /branches/trac191: ./ doc/ src/bin/ src/bin/auth/ src/bin/auth/tests/ src/bin/bind10/ src/bin/bindctl/ src/bin/cmdctl/ src/bin/cmdctl/tests/ src/bin/host/ src/bin/stats/ src/bin/stats/tests/ 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
Thu Jul 22 10:38:11 UTC 2010
Author: naokikambe
Date: Thu Jul 22 10:38:10 2010
New Revision: 2586
Log:
merge from trunk head
Added:
branches/trac191/src/bin/auth/tests/asio_link_unittest.cc
- copied unchanged from r2585, trunk/src/bin/auth/tests/asio_link_unittest.cc
branches/trac191/src/lib/config/testdata/spec28.spec
- copied unchanged from r2585, trunk/src/lib/config/testdata/spec28.spec
branches/trac191/src/lib/dns/tests/base32hex_unittest.cc
- copied unchanged from r2585, trunk/src/lib/dns/tests/base32hex_unittest.cc
branches/trac191/src/lib/dns/util/
- copied from r2585, trunk/src/lib/dns/util/
Removed:
branches/trac191/src/bin/stats/Makefile.am
branches/trac191/src/bin/stats/b10-stats.8
branches/trac191/src/bin/stats/b10-stats.xml
branches/trac191/src/bin/stats/run_b10-stats.sh.in
branches/trac191/src/bin/stats/run_b10-stats_stub.sh.in
branches/trac191/src/bin/stats/stats.py.in
branches/trac191/src/bin/stats/stats.spec.pre.in
branches/trac191/src/bin/stats/stats_stub.py.in
branches/trac191/src/bin/stats/tests/
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/configure.ac
branches/trac191/doc/Doxyfile
branches/trac191/src/bin/Makefile.am
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/bind10/bind10.py.in
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 Thu Jul 22 10:38:10 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/configure.ac
==============================================================================
--- branches/trac191/configure.ac (original)
+++ branches/trac191/configure.ac Thu Jul 22 10:38:10 2010
@@ -411,8 +411,6 @@
src/bin/xfrin/tests/Makefile
src/bin/xfrout/Makefile
src/bin/xfrout/tests/Makefile
- src/bin/stats/Makefile
- src/bin/stats/tests/Makefile
src/bin/usermgr/Makefile
src/lib/Makefile
src/lib/cc/Makefile
@@ -450,12 +448,6 @@
src/bin/xfrout/xfrout.spec.pre
src/bin/xfrout/tests/xfrout_test
src/bin/xfrout/run_b10-xfrout.sh
- src/bin/stats/stats.py
- src/bin/stats/stats_stub.py
- src/bin/stats/stats.spec.pre
- src/bin/stats/run_b10-stats.sh
- src/bin/stats/run_b10-stats_stub.sh
- src/bin/stats/tests/stats_test
src/bin/bind10/bind10.py
src/bin/bind10/tests/bind10_test
src/bin/bind10/run_bind10.sh
@@ -485,9 +477,6 @@
chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
chmod +x src/bin/xfrin/run_b10-xfrin.sh
chmod +x src/bin/xfrout/run_b10-xfrout.sh
- chmod +x src/bin/stats/tests/stats_test
- chmod +x src/bin/stats/run_b10-stats.sh
- chmod +x src/bin/stats/run_b10-stats_stub.sh
chmod +x src/bin/bind10/run_bind10.sh
chmod +x src/bin/cmdctl/tests/cmdctl_test
chmod +x src/bin/xfrin/tests/xfrin_test
Modified: branches/trac191/doc/Doxyfile
==============================================================================
--- branches/trac191/doc/Doxyfile (original)
+++ branches/trac191/doc/Doxyfile Thu Jul 22 10:38:10 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/Makefile.am
==============================================================================
--- branches/trac191/src/bin/Makefile.am (original)
+++ branches/trac191/src/bin/Makefile.am Thu Jul 22 10:38:10 2010
@@ -1,1 +1,1 @@
-SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr stats
+SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr
Modified: branches/trac191/src/bin/auth/Makefile.am
==============================================================================
--- branches/trac191/src/bin/auth/Makefile.am (original)
+++ branches/trac191/src/bin/auth/Makefile.am Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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(¬ify_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/bind10/bind10.py.in
==============================================================================
--- branches/trac191/src/bin/bind10/bind10.py.in (original)
+++ branches/trac191/src/bin/bind10/bind10.py.in Thu Jul 22 10:38:10 2010
@@ -396,26 +396,6 @@
sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" %
xfrind.pid)
- # start b10-stats
- stats_args = ['b10-stats']
- if self.verbose:
- sys.stdout.write("[bind10] Starting b10-stats\n")
- stats_args += ['-v']
- try:
- statsd = ProcessInfo("b10-stats", stats_args,
- c_channel_env)
- except Exception as e:
- c_channel.process.kill()
- bind_cfgd.process.kill()
- xfrout.process.kill()
- auth.process.kill()
- xfrind.process.kill()
- return "Unable to start b10-stats; " + str(e)
-
- self.processes[statsd.pid] = statsd
- if self.verbose:
- sys.stdout.write("[bind10] Started b10-stats (PID %d)\n" % statsd.pid)
-
# start the b10-cmdctl
# XXX: we hardcode port 8080
cmdctl_args = ['b10-cmdctl']
@@ -431,7 +411,6 @@
xfrout.process.kill()
auth.process.kill()
xfrind.process.kill()
- statsd.process.kill()
return "Unable to start b10-cmdctl; " + str(e)
self.processes[cmd_ctrld.pid] = cmd_ctrld
if self.verbose:
@@ -450,7 +429,6 @@
self.cc_session.group_sendmsg(cmd, "Boss", "Auth")
self.cc_session.group_sendmsg(cmd, "Boss", "Xfrout")
self.cc_session.group_sendmsg(cmd, "Boss", "Xfrin")
- self.cc_session.group_sendmsg(cmd, "Boss", "Stats")
def stop_process(self, process):
"""Stop the given process, friendly-like."""
Modified: branches/trac191/src/bin/bindctl/bindcmd.py
==============================================================================
--- branches/trac191/src/bin/bindctl/bindcmd.py (original)
+++ branches/trac191/src/bin/bindctl/bindcmd.py Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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 Thu Jul 22 10:38:10 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