mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-04 16:05:17 +00:00
[trac749] Merge 'master' into trac749
Conflicts: src/bin/auth/auth_srv.h src/bin/resolver/resolver.h src/lib/Makefile.am src/lib/asiodns/dns_lookup.h src/lib/asiodns/io_fetch.cc src/lib/asiodns/io_fetch.h src/lib/asiodns/qid_gen.cc src/lib/asiodns/qid_gen.h src/lib/asiodns/tcp_server.cc src/lib/asiodns/tests/qid_gen_unittest.cc src/lib/asiodns/udp_server.cc src/lib/asiolink/Makefile.am src/lib/asiolink/qid_gen.cc src/lib/asiolink/qid_gen.h src/lib/asiolink/tests/Makefile.am src/lib/asiolink/tests/qid_gen_unittest.cc src/lib/asiolink/tests/tcp_socket_unittest.cc src/lib/asiolink/tests/udp_socket_unittest.cc src/lib/dns/rdata.h src/lib/resolve/recursive_query.cc src/lib/resolve/recursive_query.h src/lib/resolve/tests/recursive_query_unittest_2.cc src/lib/testutils/srv_test.cc src/lib/util/Makefile.am src/lib/util/io_utilities.h src/lib/util/random/qid_gen.cc src/lib/util/random/qid_gen.h src/lib/util/tests/io_utilities_unittest.cc src/lib/util/tests/qid_gen_unittest.cc
This commit is contained in:
15
configure.ac
15
configure.ac
@@ -624,6 +624,8 @@ AC_CONFIG_FILES([Makefile
|
||||
src/bin/auth/benchmarks/Makefile
|
||||
src/bin/resolver/Makefile
|
||||
src/bin/resolver/tests/Makefile
|
||||
src/bin/sockcreator/Makefile
|
||||
src/bin/sockcreator/tests/Makefile
|
||||
src/bin/xfrin/Makefile
|
||||
src/bin/xfrin/tests/Makefile
|
||||
src/bin/xfrout/Makefile
|
||||
@@ -642,6 +644,8 @@ AC_CONFIG_FILES([Makefile
|
||||
src/lib/Makefile
|
||||
src/lib/asiolink/Makefile
|
||||
src/lib/asiolink/tests/Makefile
|
||||
src/lib/asiodns/Makefile
|
||||
src/lib/asiodns/tests/Makefile
|
||||
src/lib/bench/Makefile
|
||||
src/lib/bench/example/Makefile
|
||||
src/lib/bench/tests/Makefile
|
||||
@@ -667,6 +671,11 @@ AC_CONFIG_FILES([Makefile
|
||||
src/lib/config/Makefile
|
||||
src/lib/config/tests/Makefile
|
||||
src/lib/config/tests/testdata/Makefile
|
||||
src/lib/util/Makefile
|
||||
src/lib/util/io/Makefile
|
||||
src/lib/util/io/tests/Makefile
|
||||
src/lib/util/unittests/Makefile
|
||||
src/lib/util/tests/Makefile
|
||||
src/lib/dns/Makefile
|
||||
src/lib/dns/tests/Makefile
|
||||
src/lib/dns/tests/testdata/Makefile
|
||||
@@ -677,8 +686,6 @@ AC_CONFIG_FILES([Makefile
|
||||
src/lib/datasrc/Makefile
|
||||
src/lib/datasrc/tests/Makefile
|
||||
src/lib/xfr/Makefile
|
||||
src/lib/util/Makefile
|
||||
src/lib/util/tests/Makefile
|
||||
src/lib/log/Makefile
|
||||
src/lib/log/compiler/Makefile
|
||||
src/lib/log/tests/Makefile
|
||||
@@ -694,6 +701,9 @@ AC_CONFIG_FILES([Makefile
|
||||
src/lib/server_common/tests/Makefile
|
||||
tests/Makefile
|
||||
tests/system/Makefile
|
||||
tests/tools/Makefile
|
||||
tests/tools/badpacket/Makefile
|
||||
tests/tools/badpacket/tests/Makefile
|
||||
])
|
||||
AC_OUTPUT([doc/version.ent
|
||||
src/bin/cfgmgr/b10-cfgmgr.py
|
||||
@@ -708,6 +718,7 @@ AC_OUTPUT([doc/version.ent
|
||||
src/bin/xfrout/xfrout.py
|
||||
src/bin/xfrout/xfrout.spec.pre
|
||||
src/bin/xfrout/tests/xfrout_test
|
||||
src/bin/xfrout/tests/xfrout_test.py
|
||||
src/bin/xfrout/run_b10-xfrout.sh
|
||||
src/bin/resolver/resolver.spec.pre
|
||||
src/bin/resolver/spec_config.h.pre
|
||||
|
@@ -568,7 +568,11 @@ WARN_LOGFILE =
|
||||
# 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 ../src/bin/auth ../src/bin/resolver ../src/lib/bench ../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas ../src/lib/testutils ../src/lib/cache ../src/lib/server_common/
|
||||
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns \
|
||||
../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth \
|
||||
../src/bin/resolver ../src/lib/bench ../src/lib/log ../src/lib/asiolink/ \
|
||||
../src/lib/nsas ../src/lib/testutils ../src/lib/cache \
|
||||
../src/lib/server_common/ ../src/bin/sockcreator/ ../src/lib/util/
|
||||
|
||||
# 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
|
||||
|
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout \
|
||||
usermgr zonemgr stats tests resolver
|
||||
usermgr zonemgr stats tests resolver sockcreator
|
||||
|
||||
check-recursive: all-recursive
|
||||
|
@@ -39,9 +39,9 @@ pkglibexec_PROGRAMS = b10-auth
|
||||
b10_auth_SOURCES = query.cc query.h
|
||||
b10_auth_SOURCES += auth_srv.cc auth_srv.h
|
||||
b10_auth_SOURCES += change_user.cc change_user.h
|
||||
b10_auth_SOURCES += config.cc config.h
|
||||
b10_auth_SOURCES += auth_config.cc auth_config.h
|
||||
b10_auth_SOURCES += command.cc command.h
|
||||
b10_auth_SOURCES += common.h
|
||||
b10_auth_SOURCES += common.h common.cc
|
||||
b10_auth_SOURCES += statistics.cc statistics.h
|
||||
b10_auth_SOURCES += main.cc
|
||||
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
|
||||
@@ -49,6 +49,7 @@ b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
|
||||
b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include <datasrc/zonetable.h>
|
||||
|
||||
#include <auth/auth_srv.h>
|
||||
#include <auth/config.h>
|
||||
#include <auth/auth_config.h>
|
||||
#include <auth/common.h>
|
||||
|
||||
#include <server_common/portconfig.h>
|
@@ -53,7 +53,7 @@
|
||||
#include <xfr/xfrout_client.h>
|
||||
|
||||
#include <auth/common.h>
|
||||
#include <auth/config.h>
|
||||
#include <auth/auth_config.h>
|
||||
#include <auth/auth_srv.h>
|
||||
#include <auth/query.h>
|
||||
#include <auth/statistics.h>
|
||||
@@ -70,7 +70,8 @@ using namespace isc::dns::rdata;
|
||||
using namespace isc::data;
|
||||
using namespace isc::config;
|
||||
using namespace isc::xfr;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::server_common::portconfig;
|
||||
|
||||
class AuthSrvImpl {
|
||||
@@ -768,6 +769,6 @@ AuthSrv::setListenAddresses(const AddressList& addresses) {
|
||||
}
|
||||
|
||||
void
|
||||
AuthSrv::setDNSService(asiolink::DNSService& dnss) {
|
||||
AuthSrv::setDNSService(isc::asiodns::DNSService& dnss) {
|
||||
dnss_ = &dnss;
|
||||
}
|
||||
|
@@ -23,6 +23,15 @@
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <config/ccsession.h>
|
||||
#include <dns/message.h>
|
||||
#include <util/buffer.h>
|
||||
|
||||
#include <asiodns/dns_server.h>
|
||||
#include <asiodns/dns_lookup.h>
|
||||
#include <asiodns/dns_answer.h>
|
||||
#include <asiolink/io_message.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/simple_callback.h>
|
||||
|
||||
#include <asiolink/asiolink.h>
|
||||
#include <server_common/portconfig.h>
|
||||
@@ -107,10 +116,10 @@ public:
|
||||
/// \param server Pointer to the \c DNSServer
|
||||
///
|
||||
/// \throw isc::Unexpected Protocol type of \a message is unexpected
|
||||
void processMessage(const asiolink::IOMessage& io_message,
|
||||
void processMessage(const isc::asiolink::IOMessage& io_message,
|
||||
isc::dns::MessagePtr message,
|
||||
isc::util::OutputBufferPtr buffer,
|
||||
asiolink::DNSServer* server);
|
||||
isc::asiodns::DNSServer* server);
|
||||
|
||||
/// \brief Set verbose flag
|
||||
///
|
||||
@@ -193,16 +202,16 @@ public:
|
||||
void setConfigSession(isc::config::ModuleCCSession* config_session);
|
||||
|
||||
/// \brief Return this object's ASIO IO Service queue
|
||||
asiolink::IOService& getIOService();
|
||||
isc::asiolink::IOService& getIOService();
|
||||
|
||||
/// \brief Return pointer to the DNS Lookup callback function
|
||||
asiolink::DNSLookup* getDNSLookupProvider() const { return (dns_lookup_); }
|
||||
isc::asiodns::DNSLookup* getDNSLookupProvider() const { return (dns_lookup_); }
|
||||
|
||||
/// \brief Return pointer to the DNS Answer callback function
|
||||
asiolink::DNSAnswer* getDNSAnswerProvider() const { return (dns_answer_); }
|
||||
isc::asiodns::DNSAnswer* getDNSAnswerProvider() const { return (dns_answer_); }
|
||||
|
||||
/// \brief Return pointer to the Checkin callback function
|
||||
asiolink::SimpleCallback* getCheckinProvider() const { return (checkin_); }
|
||||
isc::asiolink::SimpleCallback* getCheckinProvider() const { return (checkin_); }
|
||||
|
||||
/// \brief Set or update the size (number of slots) of hot spot cache.
|
||||
///
|
||||
@@ -363,15 +372,15 @@ public:
|
||||
const;
|
||||
|
||||
/// \brief Assign an ASIO DNS Service queue to this Auth object
|
||||
void setDNSService(asiolink::DNSService& dnss);
|
||||
void setDNSService(isc::asiodns::DNSService& dnss);
|
||||
|
||||
|
||||
private:
|
||||
AuthSrvImpl* impl_;
|
||||
asiolink::SimpleCallback* checkin_;
|
||||
asiolink::DNSLookup* dns_lookup_;
|
||||
asiolink::DNSAnswer* dns_answer_;
|
||||
asiolink::DNSService* dnss_;
|
||||
isc::asiolink::SimpleCallback* checkin_;
|
||||
isc::asiodns::DNSLookup* dns_lookup_;
|
||||
isc::asiodns::DNSAnswer* dns_answer_;
|
||||
isc::asiodns::DNSService* dnss_;
|
||||
};
|
||||
|
||||
#endif // __AUTH_SRV_H
|
||||
|
@@ -10,7 +10,7 @@ noinst_PROGRAMS = query_bench
|
||||
query_bench_SOURCES = query_bench.cc
|
||||
query_bench_SOURCES += ../query.h ../query.cc
|
||||
query_bench_SOURCES += ../auth_srv.h ../auth_srv.cc
|
||||
query_bench_SOURCES += ../config.h ../config.cc
|
||||
query_bench_SOURCES += ../auth_config.h ../auth_config.cc
|
||||
query_bench_SOURCES += ../statistics.h ../statistics.cc
|
||||
|
||||
query_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
|
||||
@@ -22,6 +22,7 @@ query_bench_LDADD += $(top_builddir)/src/lib/cc/libcc.la
|
||||
query_bench_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
|
||||
query_bench_LDADD += $(top_builddir)/src/lib/log/liblog.la
|
||||
query_bench_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
|
||||
query_bench_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
|
||||
query_bench_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
|
||||
query_bench_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
|
||||
query_bench_LDADD += $(SQLITE_LIBS)
|
||||
|
@@ -12,6 +12,8 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
@@ -31,9 +33,10 @@
|
||||
#include <xfr/xfrout_client.h>
|
||||
|
||||
#include <auth/auth_srv.h>
|
||||
#include <auth/config.h>
|
||||
#include <auth/auth_config.h>
|
||||
#include <auth/query.h>
|
||||
|
||||
#include <asiodns/asiodns.h>
|
||||
#include <asiolink/asiolink.h>
|
||||
|
||||
using namespace std;
|
||||
@@ -44,7 +47,8 @@ using namespace isc::dns;
|
||||
using namespace isc::util;
|
||||
using namespace isc::xfr;
|
||||
using namespace isc::bench;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace {
|
||||
// Commonly used constant:
|
||||
|
36
src/bin/auth/common.cc
Normal file
36
src/bin/auth/common.cc
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2009-2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <auth/common.h>
|
||||
#include <auth/spec_config.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
string getXfroutSocketPath() {
|
||||
if (getenv("B10_FROM_BUILD") != NULL) {
|
||||
if (getenv("B10_FROM_SOURCE_LOCALSTATEDIR")) {
|
||||
return (string(getenv("B10_FROM_SOURCE_LOCALSTATEDIR")) +
|
||||
"/auth_xfrout_conn");
|
||||
} else {
|
||||
return (string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn");
|
||||
}
|
||||
} else {
|
||||
if (getenv("BIND10_XFROUT_SOCKET_FILE")) {
|
||||
return (getenv("BIND10_XFROUT_SOCKET_FILE"));
|
||||
} else {
|
||||
return (UNIX_SOCKET_FILE);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2009-2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -29,6 +29,15 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
/// \short Get the path of socket to talk to xfrout
|
||||
///
|
||||
/// It takes some environment variables into account (B10_FROM_BUILD,
|
||||
/// B10_FROM_SOURCE_LOCALSTATEDIR and BIND10_XFROUT_SOCKET_FILE). It
|
||||
/// also considers the installation prefix.
|
||||
///
|
||||
/// The logic should be the same as in b10-xfrout, so they find each other.
|
||||
std::string getXfroutSocketPath();
|
||||
|
||||
#endif // __COMMON_H
|
||||
|
||||
// Local Variables:
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2009-2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -12,6 +12,8 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
@@ -38,10 +40,11 @@
|
||||
|
||||
#include <auth/spec_config.h>
|
||||
#include <auth/common.h>
|
||||
#include <auth/config.h>
|
||||
#include <auth/auth_config.h>
|
||||
#include <auth/command.h>
|
||||
#include <auth/change_user.h>
|
||||
#include <auth/auth_srv.h>
|
||||
#include <asiodns/asiodns.h>
|
||||
#include <asiolink/asiolink.h>
|
||||
#include <log/dummylog.h>
|
||||
|
||||
@@ -52,7 +55,8 @@ using namespace isc::config;
|
||||
using namespace isc::dns;
|
||||
using namespace isc::util;
|
||||
using namespace isc::xfr;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::asiodns;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -122,19 +126,7 @@ main(int argc, char* argv[]) {
|
||||
bool xfrin_session_established = false; // XXX (see Trac #287)
|
||||
bool statistics_session_established = false; // XXX (see Trac #287)
|
||||
ModuleCCSession* config_session = NULL;
|
||||
string xfrout_socket_path;
|
||||
if (getenv("B10_FROM_BUILD") != NULL) {
|
||||
if (getenv("B10_FROM_SOURCE_LOCALSTATEDIR")) {
|
||||
xfrout_socket_path = string("B10_FROM_SOURCE_LOCALSTATEDIR") +
|
||||
"/auth_xfrout_conn";
|
||||
} else {
|
||||
xfrout_socket_path = string(getenv("B10_FROM_BUILD")) +
|
||||
"/auth_xfrout_conn";
|
||||
}
|
||||
} else {
|
||||
xfrout_socket_path = UNIX_SOCKET_FILE;
|
||||
}
|
||||
XfroutClient xfrout_client(xfrout_socket_path);
|
||||
XfroutClient xfrout_client(getXfroutSocketPath());
|
||||
try {
|
||||
string specfile;
|
||||
if (getenv("B10_FROM_BUILD")) {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/bin # for generated spec_config.h header
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/bin
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
|
||||
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
||||
@@ -16,18 +17,23 @@ CLEANFILES = *.gcno *.gcda
|
||||
|
||||
TESTS =
|
||||
if HAVE_GTEST
|
||||
|
||||
BUILT_SOURCES = ../spec_config.h
|
||||
TESTS += run_unittests
|
||||
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
|
||||
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
|
||||
run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
|
||||
run_unittests_SOURCES += ../query.h ../query.cc
|
||||
run_unittests_SOURCES += ../change_user.h ../change_user.cc
|
||||
run_unittests_SOURCES += ../config.h ../config.cc
|
||||
run_unittests_SOURCES += ../auth_config.h ../auth_config.cc
|
||||
run_unittests_SOURCES += ../command.h ../command.cc
|
||||
run_unittests_SOURCES += ../common.h ../common.cc
|
||||
run_unittests_SOURCES += ../spec_config.h
|
||||
run_unittests_SOURCES += ../statistics.h ../statistics.cc
|
||||
run_unittests_SOURCES += auth_srv_unittest.cc
|
||||
run_unittests_SOURCES += config_unittest.cc
|
||||
run_unittests_SOURCES += command_unittest.cc
|
||||
run_unittests_SOURCES += common_unittest.cc
|
||||
run_unittests_SOURCES += query_unittest.cc
|
||||
run_unittests_SOURCES += change_user_unittest.cc
|
||||
run_unittests_SOURCES += statistics_unittest.cc
|
||||
@@ -39,6 +45,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
|
||||
|
@@ -45,7 +45,8 @@ using namespace isc::util;
|
||||
using namespace isc::dns::rdata;
|
||||
using namespace isc::data;
|
||||
using namespace isc::xfr;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::testutils;
|
||||
using namespace isc::server_common::portconfig;
|
||||
using isc::UnitTestUtil;
|
||||
|
@@ -12,6 +12,8 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
@@ -32,7 +34,7 @@
|
||||
#include <datasrc/memory_datasrc.h>
|
||||
|
||||
#include <auth/auth_srv.h>
|
||||
#include <auth/config.h>
|
||||
#include <auth/auth_config.h>
|
||||
#include <auth/command.h>
|
||||
|
||||
#include <asiolink/asiolink.h>
|
||||
@@ -97,7 +99,7 @@ AuthConmmandTest::stopServer() {
|
||||
}
|
||||
|
||||
TEST_F(AuthConmmandTest, shutdown) {
|
||||
asiolink::IntervalTimer itimer(server.getIOService());
|
||||
isc::asiolink::IntervalTimer itimer(server.getIOService());
|
||||
itimer.setup(boost::bind(&AuthConmmandTest::stopServer, this), 1);
|
||||
server.getIOService().run();
|
||||
EXPECT_EQ(0, rcode);
|
||||
|
96
src/bin/auth/tests/common_unittest.cc
Normal file
96
src/bin/auth/tests/common_unittest.cc
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <auth/common.h>
|
||||
#include <auth/spec_config.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
|
||||
class Paths : public ::testing::Test {
|
||||
private:
|
||||
typedef pair<string, string*> Environ;
|
||||
vector<Environ> restoreEnviron;
|
||||
public:
|
||||
void TearDown() {
|
||||
// Restore the original environment
|
||||
BOOST_FOREACH(const Environ &env, restoreEnviron) {
|
||||
if (env.second == NULL) {
|
||||
EXPECT_EQ(0, unsetenv(env.first.c_str())) <<
|
||||
"Couldn't restore environment, results of other tests"
|
||||
"are uncertain";
|
||||
} else {
|
||||
EXPECT_EQ(0, setenv(env.first.c_str(), env.second->c_str(),
|
||||
1)) << "Couldn't restore environment, "
|
||||
"results of other tests are uncertain";
|
||||
}
|
||||
}
|
||||
}
|
||||
protected:
|
||||
// Sets a temporary value into environment. If value is empty, it deletes
|
||||
// the variable from environment (just for simplicity).
|
||||
void setEnv(const string& name, const string& value) {
|
||||
// Backup the original environment
|
||||
char* env(getenv(name.c_str()));
|
||||
restoreEnviron.push_back(Environ(name, env == NULL ? NULL :
|
||||
new string(env)));
|
||||
// Set the new value
|
||||
if (value.empty()) {
|
||||
EXPECT_EQ(0, unsetenv(name.c_str()));
|
||||
} else {
|
||||
EXPECT_EQ(0, setenv(name.c_str(), value.c_str(), 1));
|
||||
}
|
||||
}
|
||||
// Test getXfroutSocketPath under given environment
|
||||
void testXfrout(const string& fromBuild, const string& localStateDir,
|
||||
const string& socketFile, const string& expected)
|
||||
{
|
||||
setEnv("B10_FROM_BUILD", fromBuild);
|
||||
setEnv("B10_FROM_SOURCE_LOCALSTATEDIR", localStateDir);
|
||||
setEnv("BIND10_XFROUT_SOCKET_FILE", socketFile);
|
||||
EXPECT_EQ(expected, getXfroutSocketPath());
|
||||
}
|
||||
};
|
||||
|
||||
// Test that when we have no special environment, we get the default from prefix
|
||||
TEST_F(Paths, xfroutNoEnv) {
|
||||
testXfrout("", "", "", UNIX_SOCKET_FILE);
|
||||
}
|
||||
|
||||
// Override by B10_FROM_BUILD
|
||||
TEST_F(Paths, xfroutFromBuild) {
|
||||
testXfrout("/from/build", "", "/wrong/path",
|
||||
"/from/build/auth_xfrout_conn");
|
||||
}
|
||||
|
||||
// Override by B10_FROM_SOURCE_LOCALSTATEDIR
|
||||
TEST_F(Paths, xfroutLocalStatedir) {
|
||||
testXfrout("/wrong/path", "/state/dir", "/wrong/path",
|
||||
"/state/dir/auth_xfrout_conn");
|
||||
}
|
||||
|
||||
// Override by BIND10_XFROUT_SOCKET_FILE explicitly
|
||||
TEST_F(Paths, xfroutFromEnv) {
|
||||
testXfrout("", "", "/the/path/to/file", "/the/path/to/file");
|
||||
}
|
||||
|
||||
}
|
@@ -26,7 +26,7 @@
|
||||
#include <xfr/xfrout_client.h>
|
||||
|
||||
#include <auth/auth_srv.h>
|
||||
#include <auth/config.h>
|
||||
#include <auth/auth_config.h>
|
||||
#include <auth/common.h>
|
||||
|
||||
#include <testutils/mockups.h>
|
||||
@@ -35,7 +35,8 @@
|
||||
using namespace isc::dns;
|
||||
using namespace isc::data;
|
||||
using namespace isc::datasrc;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace {
|
||||
class AuthConfigTest : public ::testing::Test {
|
||||
|
@@ -2,12 +2,12 @@
|
||||
.\" Title: bind10
|
||||
.\" Author: [see the "AUTHORS" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||
.\" Date: February 22, 2011
|
||||
.\" Date: March 31, 2011
|
||||
.\" Manual: BIND10
|
||||
.\" Source: BIND10
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "BIND10" "8" "February 22, 2011" "BIND10" "BIND10"
|
||||
.TH "BIND10" "8" "March 31, 2011" "BIND10" "BIND10"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * set default formatting
|
||||
.\" -----------------------------------------------------------------
|
||||
@@ -22,7 +22,7 @@
|
||||
bind10 \- BIND 10 boss process
|
||||
.SH "SYNOPSIS"
|
||||
.HP \w'\fBbind10\fR\ 'u
|
||||
\fBbind10\fR [\fB\-m\ \fR\fB\fIfile\fR\fR] [\fB\-n\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-\-msgq\-socket\-file\ \fR\fB\fIfile\fR\fR] [\fB\-\-no\-cache\fR] [\fB\-\-user\ \fR\fB\fIuser\fR\fR] [\fB\-\-pretty\-name\ \fR\fB\fIname\fR\fR] [\fB\-\-verbose\fR]
|
||||
\fBbind10\fR [\fB\-c\ \fR\fB\fIconfig\-filename\fR\fR] [\fB\-m\ \fR\fB\fIfile\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fIdata_path\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-\-brittle\fR] [\fB\-\-cmdctl\-port\fR\ \fIport\fR] [\fB\-\-config\-file\fR\ \fIconfig\-filename\fR] [\fB\-\-data\-path\fR\ \fIdirectory\fR] [\fB\-\-msgq\-socket\-file\ \fR\fB\fIfile\fR\fR] [\fB\-\-no\-cache\fR] [\fB\-\-pid\-file\fR\ \fIfilename\fR] [\fB\-\-pretty\-name\ \fR\fB\fIname\fR\fR] [\fB\-\-user\ \fR\fB\fIuser\fR\fR] [\fB\-\-verbose\fR]
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
The
|
||||
@@ -32,6 +32,34 @@ daemon starts up other BIND 10 required daemons\&. It handles restarting of exit
|
||||
.PP
|
||||
The arguments are as follows:
|
||||
.PP
|
||||
\fB\-\-brittle\fR
|
||||
.RS 4
|
||||
Shutdown if any of the child processes of
|
||||
\fBbind10\fR
|
||||
exit\&. This is intended to help developers debug the server, and should not be used in production\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-c\fR \fIconfig\-filename\fR, \fB\-\-config\-file\fR \fIconfig\-filename\fR
|
||||
.RS 4
|
||||
The configuration filename to use\&. Can be either absolute or relative to data path\&. In case it is absolute, value of data path is not considered\&.
|
||||
.sp
|
||||
Defaults to b10\-config\&.db\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-\-cmdctl\-port\fR \fIport\fR
|
||||
.RS 4
|
||||
The
|
||||
\fBb10\-cmdctl\fR
|
||||
daemon will listen on this port\&. (See
|
||||
b10\-cmdctl(8)
|
||||
for the default\&.)
|
||||
.RE
|
||||
.PP
|
||||
\fB\-p\fR \fIdirectory\fR, \fB\-\-data\-path\fR \fIdirectory\fR
|
||||
.RS 4
|
||||
The path where BIND 10 programs look for various data files\&. Currently only b10\-cfgmgr uses it to locate the configuration file, but the usage might be extended for other programs and other types of files\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-m\fR \fIfile\fR, \fB\-\-msgq\-socket\-file\fR \fIfile\fR
|
||||
.RS 4
|
||||
The UNIX domain socket file for the
|
||||
@@ -57,6 +85,13 @@ to run as\&.
|
||||
must be initially ran as the root user to use this option\&. The default is to run as the current user\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-\-pid\-file\fR \fIfilename\fR
|
||||
.RS 4
|
||||
If defined, the PID of the
|
||||
\fBbind10\fR
|
||||
is stored in this file\&. This is used for testing purposes\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-\-pretty\-name \fR\fB\fIname\fR\fR
|
||||
.RS 4
|
||||
The name this process should have in tools like
|
||||
|
@@ -202,7 +202,7 @@ class BoB:
|
||||
|
||||
def __init__(self, msgq_socket_file=None, data_path=None,
|
||||
config_filename=None, nocache=False, verbose=False, setuid=None,
|
||||
username=None, cmdctl_port=None):
|
||||
username=None, cmdctl_port=None, brittle=False):
|
||||
"""
|
||||
Initialize the Boss of BIND. This is a singleton (only one can run).
|
||||
|
||||
@@ -235,6 +235,7 @@ class BoB:
|
||||
self.data_path = data_path
|
||||
self.config_filename = config_filename
|
||||
self.cmdctl_port = cmdctl_port
|
||||
self.brittle = brittle
|
||||
|
||||
def config_handler(self, new_config):
|
||||
# If this is initial update, don't do anything now, leave it to startup
|
||||
@@ -296,7 +297,7 @@ class BoB:
|
||||
|
||||
def command_handler(self, command, args):
|
||||
if self.verbose:
|
||||
sys.stdout.write("[bind10] Boss got command: " + command + "\n")
|
||||
sys.stdout.write("[bind10] Boss got command: " + str(command) + "\n")
|
||||
answer = isc.config.ccsession.create_answer(1, "command not implemented")
|
||||
if type(command) != str:
|
||||
answer = isc.config.ccsession.create_answer(1, "bad command")
|
||||
@@ -304,6 +305,15 @@ class BoB:
|
||||
if command == "shutdown":
|
||||
self.runnable = False
|
||||
answer = isc.config.ccsession.create_answer(0)
|
||||
elif command == "sendstats":
|
||||
# send statistics data to the stats daemon immediately
|
||||
cmd = isc.config.ccsession.create_command(
|
||||
'set', { "stats_data": {
|
||||
'bind10.boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', _BASETIME)
|
||||
}})
|
||||
seq = self.cc_session.group_sendmsg(cmd, 'Stats')
|
||||
self.cc_session.group_recvmsg(True, seq)
|
||||
answer = isc.config.ccsession.create_answer(0)
|
||||
elif command == "ping":
|
||||
answer = isc.config.ccsession.create_answer(0, "pong")
|
||||
elif command == "show_processes":
|
||||
@@ -710,20 +720,22 @@ class BoB:
|
||||
if self.verbose:
|
||||
sys.stdout.write("[bind10] All processes ended, server done.\n")
|
||||
|
||||
def _get_process_exit_status(self):
|
||||
return os.waitpid(-1, os.WNOHANG)
|
||||
|
||||
def reap_children(self):
|
||||
"""Check to see if any of our child processes have exited,
|
||||
and note this for later handling.
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
(pid, exit_status) = os.waitpid(-1, os.WNOHANG)
|
||||
(pid, exit_status) = self._get_process_exit_status()
|
||||
except OSError as o:
|
||||
if o.errno == errno.ECHILD: break
|
||||
# XXX: should be impossible to get any other error here
|
||||
raise
|
||||
if pid == 0: break
|
||||
if pid in self.processes:
|
||||
|
||||
# One of the processes we know about. Get information on it.
|
||||
proc_info = self.processes.pop(pid)
|
||||
proc_info.restart_schedule.set_run_stop_time()
|
||||
@@ -747,6 +759,11 @@ class BoB:
|
||||
sys.stdout.write(
|
||||
"[bind10] The b10-msgq process died, shutting down.\n")
|
||||
self.runnable = False
|
||||
|
||||
# If we're in 'brittle' mode, we want to shutdown after
|
||||
# any process dies.
|
||||
if self.brittle:
|
||||
self.runnable = False
|
||||
else:
|
||||
sys.stdout.write("[bind10] Unknown child pid %d exited.\n" % pid)
|
||||
|
||||
@@ -856,6 +873,8 @@ def parse_args(args=sys.argv[1:], Parser=OptionParser):
|
||||
parser.add_option("--pid-file", dest="pid_file", type="string",
|
||||
default=None,
|
||||
help="file to dump the PID of the BIND 10 process")
|
||||
parser.add_option("--brittle", dest="brittle", action="store_true",
|
||||
help="debugging flag: exit if any component dies")
|
||||
|
||||
(options, args) = parser.parse_args(args)
|
||||
|
||||
@@ -959,7 +978,7 @@ def main():
|
||||
# Go bob!
|
||||
boss_of_bind = BoB(options.msgq_socket_file, options.data_path,
|
||||
options.config_file, options.nocache, options.verbose,
|
||||
setuid, username, options.cmdctl_port)
|
||||
setuid, username, options.cmdctl_port, options.brittle)
|
||||
startup_result = boss_of_bind.startup()
|
||||
if startup_result:
|
||||
sys.stderr.write("[bind10] Error on startup: %s\n" % startup_result)
|
||||
@@ -967,17 +986,6 @@ def main():
|
||||
sys.stdout.write("[bind10] BIND 10 started\n")
|
||||
dump_pid(options.pid_file)
|
||||
|
||||
# send "bind10.boot_time" to b10-stats
|
||||
time.sleep(1) # wait a second
|
||||
if options.verbose:
|
||||
sys.stdout.write("[bind10] send \"bind10.boot_time\" to b10-stats\n")
|
||||
cmd = isc.config.ccsession.create_command('set',
|
||||
{ "stats_data": {
|
||||
'bind10.boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', _BASETIME)
|
||||
}
|
||||
})
|
||||
boss_of_bind.cc_session.group_sendmsg(cmd, 'Stats')
|
||||
|
||||
# In our main loop, we check for dead processes or messages
|
||||
# on the c-channel.
|
||||
wakeup_fd = wakeup_pipe[0]
|
||||
|
@@ -20,7 +20,7 @@
|
||||
<refentry>
|
||||
|
||||
<refentryinfo>
|
||||
<date>February 22, 2011</date>
|
||||
<date>March 31, 2011</date>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
@@ -44,16 +44,21 @@
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>bind10</command>
|
||||
<arg><option>-c <replaceable>config-filename</replaceable></option></arg>
|
||||
<arg><option>-m <replaceable>file</replaceable></option></arg>
|
||||
<arg><option>-n</option></arg>
|
||||
<arg><option>-p <replaceable>data_path</replaceable></option></arg>
|
||||
<arg><option>-u <replaceable>user</replaceable></option></arg>
|
||||
<arg><option>-v</option></arg>
|
||||
<arg><option>-c<replaceable>config-filename</replaceable></option></arg>
|
||||
<arg><option>-p<replaceable>data_path</replaceable></option></arg>
|
||||
<arg><option>--brittle</option></arg>
|
||||
<arg><option>--cmdctl-port</option> <replaceable>port</replaceable></arg>
|
||||
<arg><option>--config-file</option> <replaceable>config-filename</replaceable></arg>
|
||||
<arg><option>--data-path</option> <replaceable>directory</replaceable></arg>
|
||||
<arg><option>--msgq-socket-file <replaceable>file</replaceable></option></arg>
|
||||
<arg><option>--no-cache</option></arg>
|
||||
<arg><option>--user <replaceable>user</replaceable></option></arg>
|
||||
<arg><option>--pid-file</option> <replaceable>filename</replaceable></arg>
|
||||
<arg><option>--pretty-name <replaceable>name</replaceable></option></arg>
|
||||
<arg><option>--user <replaceable>user</replaceable></option></arg>
|
||||
<arg><option>--verbose</option></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@@ -82,9 +87,24 @@
|
||||
<para>The arguments are as follows:</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-c</option><replaceable>config-filename</replaceable>,
|
||||
<option>--brittle</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Shutdown if any of the child processes of
|
||||
<command>bind10</command> exit. This is intended to
|
||||
help developers debug the server, and should not be
|
||||
used in production.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-c</option> <replaceable>config-filename</replaceable>,
|
||||
<option>--config-file</option> <replaceable>config-filename</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
@@ -97,8 +117,22 @@
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-p</option><replaceable>data-path</replaceable>,
|
||||
<option>--data-path</option> <replaceable>data-path</replaceable>
|
||||
<option>--cmdctl-port</option> <replaceable>port</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>The <command>b10-cmdctl</command> daemon will listen
|
||||
on this port.
|
||||
(See
|
||||
<refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
|
||||
for the default.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-p</option> <replaceable>directory</replaceable>,
|
||||
<option>--data-path</option> <replaceable>directory</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>The path where BIND 10 programs look for various data files.
|
||||
@@ -134,7 +168,6 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-u</option> <replaceable>user</replaceable>, <option>--user</option> <replaceable>name</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
<para>The username for <command>bind10</command> to run as.
|
||||
<!-- TODO: example more detail. -->
|
||||
@@ -144,6 +177,16 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--pid-file</option> <replaceable>filename</replaceable></term>
|
||||
<listitem>
|
||||
<para>If defined, the PID of the <command>bind10</command> is stored
|
||||
in this file.
|
||||
This is used for testing purposes.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--pretty-name <replaceable>name</replaceable></option></term>
|
||||
|
||||
|
@@ -22,6 +22,11 @@
|
||||
"command_description": "Shut down BIND 10",
|
||||
"command_args": []
|
||||
},
|
||||
{
|
||||
"command_name": "sendstats",
|
||||
"command_description": "Send data to a statistics module at once",
|
||||
"command_args": []
|
||||
},
|
||||
{
|
||||
"command_name": "ping",
|
||||
"command_description": "Ping the boss process",
|
||||
|
@@ -1,5 +1,6 @@
|
||||
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
|
||||
#PYTESTS = args_test.py bind10_test.py
|
||||
# NOTE: this has a generated test found in the builddir
|
||||
PYTESTS = bind10_test.py
|
||||
EXTRA_DIST = $(PYTESTS)
|
||||
|
||||
@@ -14,5 +15,5 @@ endif
|
||||
echo Running test: $$pytest ; \
|
||||
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/bind10 \
|
||||
BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
|
||||
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
|
||||
$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
|
||||
done
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from bind10 import ProcessInfo, BoB, parse_args, dump_pid, unlink_pid_file
|
||||
from bind10 import ProcessInfo, BoB, parse_args, dump_pid, unlink_pid_file, _BASETIME
|
||||
|
||||
# XXX: environment tests are currently disabled, due to the preprocessor
|
||||
# setup that we have now complicating the environment
|
||||
@@ -24,6 +24,9 @@ import os
|
||||
import signal
|
||||
import socket
|
||||
from isc.net.addr import IPAddr
|
||||
import time
|
||||
import isc
|
||||
|
||||
from isc.testutils.parse_args import TestOptParser, OptsError
|
||||
|
||||
class TestProcessInfo(unittest.TestCase):
|
||||
@@ -123,6 +126,41 @@ class TestBoB(unittest.TestCase):
|
||||
self.assertEqual(bob.cfg_start_auth, True)
|
||||
self.assertEqual(bob.cfg_start_resolver, False)
|
||||
|
||||
def test_command_handler(self):
|
||||
class DummySession():
|
||||
def group_sendmsg(self, msg, group):
|
||||
(self.msg, self.group) = (msg, group)
|
||||
def group_recvmsg(self, nonblock, seq): pass
|
||||
bob = BoB()
|
||||
bob.verbose = True
|
||||
bob.cc_session = DummySession()
|
||||
# a bad command
|
||||
self.assertEqual(bob.command_handler(-1, None),
|
||||
isc.config.ccsession.create_answer(1, "bad command"))
|
||||
# "shutdown" command
|
||||
self.assertEqual(bob.command_handler("shutdown", None),
|
||||
isc.config.ccsession.create_answer(0))
|
||||
self.assertFalse(bob.runnable)
|
||||
# "sendstats" command
|
||||
self.assertEqual(bob.command_handler("sendstats", None),
|
||||
isc.config.ccsession.create_answer(0))
|
||||
self.assertEqual(bob.cc_session.group, "Stats")
|
||||
self.assertEqual(bob.cc_session.msg,
|
||||
isc.config.ccsession.create_command(
|
||||
'set', { "stats_data": {
|
||||
'bind10.boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', _BASETIME)
|
||||
}}))
|
||||
# "ping" command
|
||||
self.assertEqual(bob.command_handler("ping", None),
|
||||
isc.config.ccsession.create_answer(0, "pong"))
|
||||
# "show_processes" command
|
||||
self.assertEqual(bob.command_handler("show_processes", None),
|
||||
isc.config.ccsession.create_answer(0,
|
||||
bob.get_processes()))
|
||||
# an unknown command
|
||||
self.assertEqual(bob.command_handler("__UNKNOWN__", None),
|
||||
isc.config.ccsession.create_answer(1, "Unknown command"))
|
||||
|
||||
# Class for testing the BoB without actually starting processes.
|
||||
# This is used for testing the start/stop components routines and
|
||||
# the BoB commands.
|
||||
@@ -156,42 +194,52 @@ class MockBob(BoB):
|
||||
def start_msgq(self, c_channel_env):
|
||||
self.msgq = True
|
||||
self.processes[2] = ProcessInfo('b10-msgq', ['/bin/false'])
|
||||
self.processes[2].pid = 2
|
||||
|
||||
def start_cfgmgr(self, c_channel_env):
|
||||
self.cfgmgr = True
|
||||
self.processes[3] = ProcessInfo('b10-cfgmgr', ['/bin/false'])
|
||||
self.processes[3].pid = 3
|
||||
|
||||
def start_ccsession(self, c_channel_env):
|
||||
self.ccsession = True
|
||||
self.processes[4] = ProcessInfo('b10-ccsession', ['/bin/false'])
|
||||
self.processes[4].pid = 4
|
||||
|
||||
def start_auth(self, c_channel_env):
|
||||
self.auth = True
|
||||
self.processes[5] = ProcessInfo('b10-auth', ['/bin/false'])
|
||||
self.processes[5].pid = 5
|
||||
|
||||
def start_resolver(self, c_channel_env):
|
||||
self.resolver = True
|
||||
self.processes[6] = ProcessInfo('b10-resolver', ['/bin/false'])
|
||||
self.processes[6].pid = 6
|
||||
|
||||
def start_xfrout(self, c_channel_env):
|
||||
self.xfrout = True
|
||||
self.processes[7] = ProcessInfo('b10-xfrout', ['/bin/false'])
|
||||
self.processes[7].pid = 7
|
||||
|
||||
def start_xfrin(self, c_channel_env):
|
||||
self.xfrin = True
|
||||
self.processes[8] = ProcessInfo('b10-xfrin', ['/bin/false'])
|
||||
self.processes[8].pid = 8
|
||||
|
||||
def start_zonemgr(self, c_channel_env):
|
||||
self.zonemgr = True
|
||||
self.processes[9] = ProcessInfo('b10-zonemgr', ['/bin/false'])
|
||||
self.processes[9].pid = 9
|
||||
|
||||
def start_stats(self, c_channel_env):
|
||||
self.stats = True
|
||||
self.processes[10] = ProcessInfo('b10-stats', ['/bin/false'])
|
||||
self.processes[10].pid = 10
|
||||
|
||||
def start_cmdctl(self, c_channel_env):
|
||||
self.cmdctl = True
|
||||
self.processes[11] = ProcessInfo('b10-cmdctl', ['/bin/false'])
|
||||
self.processes[11].pid = 11
|
||||
|
||||
# We don't really use all of these stop_ methods. But it might turn out
|
||||
# someone would add some stop_ method to BoB and we want that one overriden
|
||||
@@ -550,6 +598,15 @@ class TestParseArgs(unittest.TestCase):
|
||||
options = parse_args(['--cmdctl-port=1234'], TestOptParser)
|
||||
self.assertEqual(1234, options.cmdctl_port)
|
||||
|
||||
def test_brittle(self):
|
||||
"""
|
||||
Test we can use the "brittle" flag.
|
||||
"""
|
||||
options = parse_args([], TestOptParser)
|
||||
self.assertFalse(options.brittle)
|
||||
options = parse_args(['--brittle'], TestOptParser)
|
||||
self.assertTrue(options.brittle)
|
||||
|
||||
class TestPIDFile(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.pid_file = '@builddir@' + os.sep + 'bind10.pid'
|
||||
@@ -597,5 +654,34 @@ class TestPIDFile(unittest.TestCase):
|
||||
self.assertRaises(IOError, dump_pid,
|
||||
'nonexistent_dir' + os.sep + 'bind10.pid')
|
||||
|
||||
class TestBrittle(unittest.TestCase):
|
||||
def test_brittle_disabled(self):
|
||||
bob = MockBob()
|
||||
bob.start_all_processes()
|
||||
bob.runnable = True
|
||||
|
||||
bob.reap_children()
|
||||
self.assertTrue(bob.runnable)
|
||||
|
||||
def simulated_exit(self):
|
||||
ret_val = self.exit_info
|
||||
self.exit_info = (0, 0)
|
||||
return ret_val
|
||||
|
||||
def test_brittle_enabled(self):
|
||||
bob = MockBob()
|
||||
bob.start_all_processes()
|
||||
bob.runnable = True
|
||||
|
||||
bob.brittle = True
|
||||
self.exit_info = (5, 0)
|
||||
bob._get_process_exit_status = self.simulated_exit
|
||||
|
||||
old_stdout = sys.stdout
|
||||
sys.stdout = open("/dev/null", "w")
|
||||
bob.reap_children()
|
||||
sys.stdout = old_stdout
|
||||
self.assertFalse(bob.runnable)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@@ -4,6 +4,8 @@ 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_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiodns
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiodns
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
|
||||
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
||||
@@ -45,6 +47,7 @@ b10_resolver_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/cc/libcc.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
|
||||
b10_resolver_LDADD += $(top_builddir)/src/lib/log/liblog.la
|
||||
|
@@ -12,6 +12,8 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
@@ -25,6 +27,7 @@
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <asiodns/asiodns.h>
|
||||
#include <asiolink/asiolink.h>
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
@@ -56,7 +59,8 @@ using namespace isc::cc;
|
||||
using namespace isc::config;
|
||||
using namespace isc::data;
|
||||
using isc::log::dlog;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include <asiodns/asiodns.h>
|
||||
#include <asiolink/asiolink.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -56,7 +57,8 @@ using namespace isc::dns;
|
||||
using namespace isc::data;
|
||||
using namespace isc::config;
|
||||
using isc::log::dlog;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::server_common::portconfig;
|
||||
|
||||
class ResolverImpl {
|
||||
@@ -347,7 +349,7 @@ Resolver::~Resolver() {
|
||||
}
|
||||
|
||||
void
|
||||
Resolver::setDNSService(asiolink::DNSService& dnss) {
|
||||
Resolver::setDNSService(isc::asiodns::DNSService& dnss) {
|
||||
dnss_ = &dnss;
|
||||
}
|
||||
|
||||
|
@@ -21,8 +21,16 @@
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <config/ccsession.h>
|
||||
#include <dns/message.h>
|
||||
#include <util/buffer.h>
|
||||
|
||||
#include <asiolink/asiolink.h>
|
||||
#include <asiodns/dns_server.h>
|
||||
#include <asiodns/dns_service.h>
|
||||
#include <asiodns/dns_lookup.h>
|
||||
#include <asiodns/dns_answer.h>
|
||||
#include <asiolink/io_message.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/simple_callback.h>
|
||||
|
||||
#include <nsas/nameserver_address_store.h>
|
||||
#include <cache/resolver_cache.h>
|
||||
@@ -74,11 +82,11 @@ public:
|
||||
/// shall return to the client
|
||||
/// \param buffer Pointer to an \c OutputBuffer for the resposne
|
||||
/// \param server Pointer to the \c DNSServer
|
||||
void processMessage(const asiolink::IOMessage& io_message,
|
||||
void processMessage(const isc::asiolink::IOMessage& io_message,
|
||||
isc::dns::MessagePtr query_message,
|
||||
isc::dns::MessagePtr answer_message,
|
||||
isc::util::OutputBufferPtr buffer,
|
||||
asiolink::DNSServer* server);
|
||||
isc::asiodns::DNSServer* server);
|
||||
|
||||
/// \brief Set and get the config session
|
||||
isc::config::ModuleCCSession* getConfigSession() const;
|
||||
@@ -88,7 +96,7 @@ public:
|
||||
isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
|
||||
|
||||
/// \brief Assign an ASIO IO Service queue to this Resolver object
|
||||
void setDNSService(asiolink::DNSService& dnss);
|
||||
void setDNSService(isc::asiodns::DNSService& dnss);
|
||||
|
||||
/// \brief Assign a NameserverAddressStore to this Resolver object
|
||||
void setNameserverAddressStore(isc::nsas::NameserverAddressStore &nsas);
|
||||
@@ -97,7 +105,7 @@ public:
|
||||
void setCache(isc::cache::ResolverCache& cache);
|
||||
|
||||
/// \brief Return this object's ASIO IO Service queue
|
||||
asiolink::DNSService& getDNSService() const { return (*dnss_); }
|
||||
isc::asiodns::DNSService& getDNSService() const { return (*dnss_); }
|
||||
|
||||
/// \brief Returns this object's NSAS
|
||||
isc::nsas::NameserverAddressStore& getNameserverAddressStore() const {
|
||||
@@ -110,13 +118,13 @@ public:
|
||||
};
|
||||
|
||||
/// \brief Return pointer to the DNS Lookup callback function
|
||||
asiolink::DNSLookup* getDNSLookupProvider() { return (dns_lookup_); }
|
||||
isc::asiodns::DNSLookup* getDNSLookupProvider() { return (dns_lookup_); }
|
||||
|
||||
/// \brief Return pointer to the DNS Answer callback function
|
||||
asiolink::DNSAnswer* getDNSAnswerProvider() { return (dns_answer_); }
|
||||
isc::asiodns::DNSAnswer* getDNSAnswerProvider() { return (dns_answer_); }
|
||||
|
||||
/// \brief Return pointer to the Checkin callback function
|
||||
asiolink::SimpleCallback* getCheckinProvider() { return (checkin_); }
|
||||
isc::asiolink::SimpleCallback* getCheckinProvider() { return (checkin_); }
|
||||
|
||||
/**
|
||||
* \brief Tell the Resolver that is has already been configured
|
||||
@@ -230,10 +238,10 @@ public:
|
||||
|
||||
private:
|
||||
ResolverImpl* impl_;
|
||||
asiolink::DNSService* dnss_;
|
||||
asiolink::SimpleCallback* checkin_;
|
||||
asiolink::DNSLookup* dns_lookup_;
|
||||
asiolink::DNSAnswer* dns_answer_;
|
||||
isc::asiodns::DNSService* dnss_;
|
||||
isc::asiolink::SimpleCallback* checkin_;
|
||||
isc::asiodns::DNSLookup* dns_lookup_;
|
||||
isc::asiodns::DNSAnswer* dns_answer_;
|
||||
isc::nsas::NameserverAddressStore* nsas_;
|
||||
isc::cache::ResolverCache* cache_;
|
||||
// This value is initally false, and will be set to true
|
||||
|
@@ -26,7 +26,7 @@ using namespace std;
|
||||
// Compare addresses etc.
|
||||
|
||||
ResponseScrubber::Category ResponseScrubber::addressCheck(
|
||||
const asiolink::IOEndpoint& to, const asiolink::IOEndpoint& from)
|
||||
const isc::asiolink::IOEndpoint& to, const isc::asiolink::IOEndpoint& from)
|
||||
{
|
||||
if (from.getProtocol() == to.getProtocol()) {
|
||||
if (from.getAddress() == to.getAddress()) {
|
||||
|
@@ -282,8 +282,8 @@ public:
|
||||
///
|
||||
/// \return SUCCESS if the two endpoints match, otherwise an error status
|
||||
/// indicating what was incorrect.
|
||||
static Category addressCheck(const asiolink::IOEndpoint& to,
|
||||
const asiolink::IOEndpoint& from);
|
||||
static Category addressCheck(const isc::asiolink::IOEndpoint& to,
|
||||
const isc::asiolink::IOEndpoint& from);
|
||||
|
||||
/// \brief Check QID
|
||||
///
|
||||
|
@@ -31,6 +31,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
|
||||
|
@@ -12,12 +12,15 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cc/data.h>
|
||||
|
||||
#include <asiodns/asiodns.h>
|
||||
#include <asiolink/asiolink.h>
|
||||
|
||||
#include <resolver/resolver.h>
|
||||
@@ -29,7 +32,8 @@
|
||||
using namespace std;
|
||||
using namespace isc::data;
|
||||
using namespace isc::testutils;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace isc::asiolink;
|
||||
using isc::UnitTestUtil;
|
||||
|
||||
namespace {
|
||||
|
@@ -41,6 +41,7 @@
|
||||
// Class for endpoint checks. The family of the endpoint is set in the
|
||||
// constructor; the address family by the string provided for the address.
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
class GenericEndpoint : public IOEndpoint {
|
||||
@@ -73,13 +74,14 @@ private:
|
||||
short protocol_; // Protocol of the endpoint
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
using namespace asio::ip;
|
||||
using namespace isc::dns;
|
||||
using namespace rdata;
|
||||
using namespace isc::dns::rdata::generic;
|
||||
using namespace isc::dns::rdata::in;
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
// Test class
|
||||
|
||||
|
18
src/bin/sockcreator/Makefile.am
Normal file
18
src/bin/sockcreator/Makefile.am
Normal file
@@ -0,0 +1,18 @@
|
||||
SUBDIRS = tests
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
|
||||
|
||||
AM_CXXFLAGS = $(B10_CXXFLAGS)
|
||||
|
||||
if USE_STATIC_LINK
|
||||
AM_LDFLAGS = -static
|
||||
endif
|
||||
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
|
||||
CLEANFILES = *.gcno *.gcda
|
||||
|
||||
pkglibexec_PROGRAMS = b10-sockcreator
|
||||
|
||||
b10_sockcreator_SOURCES = sockcreator.cc sockcreator.h main.cc
|
||||
b10_sockcreator_LDADD = $(top_builddir)/src/lib/util/io/libutil_io.la
|
49
src/bin/sockcreator/README
Normal file
49
src/bin/sockcreator/README
Normal file
@@ -0,0 +1,49 @@
|
||||
The socket creator
|
||||
==================
|
||||
|
||||
The only thing we need higher rights than standard user is binding sockets to
|
||||
ports lower than 1024. So we will have a separate process that keeps the
|
||||
rights, while the rests drop them for security reasons.
|
||||
|
||||
This process is the socket creator. Its goal is to be as simple as possible
|
||||
and to contain as little code as possible to minimise the amount of code
|
||||
running with higher privileges (to minimize the number of bugs and make
|
||||
checking/auditing it easier). It uses low-level OS API instead of some
|
||||
fancy library for that reason. It has only fixed-length reads so there's no
|
||||
place for buffer overruns.
|
||||
|
||||
Protocol
|
||||
--------
|
||||
|
||||
It talks with whoever started it by its stdin/stdout. It reads simple
|
||||
binary protocol from stdin and does what the commands ask. Command is a single
|
||||
byte (usually from the printable range, so it is easier to debug and guess
|
||||
what it does), followed by parameters.
|
||||
|
||||
Note that as send_fd and recv_fd works only with unix domain socket, it's stdio
|
||||
must be a socket, not pipe.
|
||||
|
||||
* 'T': It has no parameters. It asks the socket creator to terminate.
|
||||
|
||||
* 'S' 'U|T' '4|6' port address: Asks it to create a port. First parameter
|
||||
tels the socket type (either UDP or TCP). The second one is address family
|
||||
(either IPv4 or IPv6). Then there's 2 bytes of the port number, in the
|
||||
network byte order. The last one is either 4 or 16 bytes of address, as
|
||||
they would be passed to bind (note that both parameters are already prepared,
|
||||
like hton called on them).
|
||||
|
||||
The answer to this is either 'S' directly followed by the socket (using
|
||||
sendmsg) if it is successful. If it fails, 'E' is returned instead, followed
|
||||
by either 'S' or 'B' (either socket() or bind() call failed). Then there is
|
||||
one int (architecture-dependent length and endianess), which is the errno
|
||||
value after the failure.
|
||||
|
||||
The creator may also send these messages at any time (but not in the middle
|
||||
of another message):
|
||||
|
||||
* 'F': A fatal error has been detected. It is followed by one byte of error
|
||||
condition code and then the creator terminates with non-zero status.
|
||||
|
||||
The conditions are:
|
||||
* 'I': Invalid input (eg. someone sent a wrong letter and it does not
|
||||
understand it).
|
26
src/bin/sockcreator/main.cc
Normal file
26
src/bin/sockcreator/main.cc
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "sockcreator.h"
|
||||
|
||||
using namespace isc::socket_creator;
|
||||
|
||||
int
|
||||
main() {
|
||||
/*
|
||||
* TODO Maybe use some OS-specific caps interface and drop everything
|
||||
* but ability to bind ports? It would be nice.
|
||||
*/
|
||||
return run(0, 1); // Read commands from stdin, output to stdout
|
||||
}
|
151
src/bin/sockcreator/sockcreator.cc
Normal file
151
src/bin/sockcreator/sockcreator.cc
Normal file
@@ -0,0 +1,151 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "sockcreator.h"
|
||||
|
||||
#include <util/io/fd.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cerrno>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
using namespace isc::util::io;
|
||||
|
||||
namespace isc {
|
||||
namespace socket_creator {
|
||||
|
||||
int
|
||||
get_sock(const int type, struct sockaddr *bind_addr, const socklen_t addr_len)
|
||||
{
|
||||
int sock(socket(bind_addr->sa_family, type, 0));
|
||||
if (sock == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (bind(sock, bind_addr, addr_len) == -1) {
|
||||
return -2;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
// These are macros so they can exit the function
|
||||
#define READ(WHERE, HOW_MANY) do { \
|
||||
size_t how_many = (HOW_MANY); \
|
||||
if (read_data(input_fd, (WHERE), how_many) < how_many) { \
|
||||
return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRITE(WHAT, HOW_MANY) do { \
|
||||
if (!write_data(output_fd, (WHAT), (HOW_MANY))) { \
|
||||
return 2; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEFAULT \
|
||||
default: /* Unrecognized part of protocol */ \
|
||||
WRITE("FI", 2); \
|
||||
return 3;
|
||||
|
||||
int
|
||||
run(const int input_fd, const int output_fd, const get_sock_t get_sock,
|
||||
const send_fd_t send_fd)
|
||||
{
|
||||
for (;;) {
|
||||
// Read the command
|
||||
char command;
|
||||
READ(&command, 1);
|
||||
switch (command) {
|
||||
case 'T': // The "terminate" command
|
||||
return 0;
|
||||
case 'S': { // Create a socket
|
||||
// Read what type of socket they want
|
||||
char type[2];
|
||||
READ(type, 2);
|
||||
// Read the address they ask for
|
||||
struct sockaddr *addr(NULL);
|
||||
size_t addr_len(0);
|
||||
struct sockaddr_in addr_in;
|
||||
struct sockaddr_in6 addr_in6;
|
||||
switch (type[1]) { // The address family
|
||||
/*
|
||||
* Here are some casts. They are required by C++ and
|
||||
* the low-level interface (they are implicit in C).
|
||||
*/
|
||||
case '4':
|
||||
addr = static_cast<struct sockaddr *>(
|
||||
static_cast<void *>(&addr_in));
|
||||
addr_len = sizeof addr_in;
|
||||
memset(&addr_in, 0, sizeof addr_in);
|
||||
addr_in.sin_family = AF_INET;
|
||||
READ(static_cast<char *>(static_cast<void *>(
|
||||
&addr_in.sin_port)), 2);
|
||||
READ(static_cast<char *>(static_cast<void *>(
|
||||
&addr_in.sin_addr.s_addr)), 4);
|
||||
break;
|
||||
case '6':
|
||||
addr = static_cast<struct sockaddr *>(
|
||||
static_cast<void *>(&addr_in6));
|
||||
addr_len = sizeof addr_in6;
|
||||
memset(&addr_in6, 0, sizeof addr_in6);
|
||||
addr_in6.sin6_family = AF_INET6;
|
||||
READ(static_cast<char *>(static_cast<void *>(
|
||||
&addr_in6.sin6_port)), 2);
|
||||
READ(static_cast<char *>(static_cast<void *>(
|
||||
&addr_in6.sin6_addr.s6_addr)), 16);
|
||||
break;
|
||||
DEFAULT
|
||||
}
|
||||
int sock_type;
|
||||
switch (type[0]) { // Translate the type
|
||||
case 'T':
|
||||
sock_type = SOCK_STREAM;
|
||||
break;
|
||||
case 'U':
|
||||
sock_type = SOCK_DGRAM;
|
||||
break;
|
||||
DEFAULT
|
||||
}
|
||||
int result(get_sock(sock_type, addr, addr_len));
|
||||
if (result >= 0) { // We got the socket
|
||||
WRITE("S", 1);
|
||||
// FIXME: Check the output and write a test for it
|
||||
send_fd(output_fd, result);
|
||||
} else {
|
||||
WRITE("E", 1);
|
||||
switch (result) {
|
||||
case -1:
|
||||
WRITE("S", 1);
|
||||
break;
|
||||
case -2:
|
||||
WRITE("B", 1);
|
||||
break;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
int error(errno);
|
||||
WRITE(static_cast<char *>(static_cast<void *>(&error)),
|
||||
sizeof error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
DEFAULT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of the namespaces
|
||||
}
|
100
src/bin/sockcreator/sockcreator.h
Normal file
100
src/bin/sockcreator/sockcreator.h
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/**
|
||||
* \file sockcreator.h
|
||||
* \short Socket creator functionality.
|
||||
*
|
||||
* This module holds the functionality of the socket creator. It is
|
||||
* a separate module from main to ease up the tests.
|
||||
*/
|
||||
|
||||
#ifndef __SOCKCREATOR_H
|
||||
#define __SOCKCREATOR_H 1
|
||||
|
||||
#include <util/io/fd_share.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace isc {
|
||||
namespace socket_creator {
|
||||
|
||||
/**
|
||||
* \short Create a socket and bind it.
|
||||
*
|
||||
* This is just a bundle of socket() and bind() calls. The sa_family of
|
||||
* bind_addr is used to determine the domain of the socket.
|
||||
*
|
||||
* \return The file descriptor of the newly created socket, if everything
|
||||
* goes well. A negative number is returned if an error occurs -
|
||||
* -1 if the socket() call fails or -2 if bind() fails. In case of error,
|
||||
* errno is set (or better, left intact from socket() or bind()).
|
||||
* \param type The type of socket to create (SOCK_STREAM, SOCK_DGRAM, etc).
|
||||
* \param bind_addr The address to bind.
|
||||
* \param addr_len The actual length of bind_addr.
|
||||
*/
|
||||
int
|
||||
get_sock(const int type, struct sockaddr *bind_addr, const socklen_t addr_len);
|
||||
|
||||
/**
|
||||
* Type of the get_sock function, to pass it as parameter.
|
||||
*/
|
||||
typedef
|
||||
int
|
||||
(*get_sock_t)(const int, struct sockaddr *, const socklen_t);
|
||||
|
||||
/**
|
||||
* Type of the send_fd() function, so it can be passed as a parameter.
|
||||
*/
|
||||
typedef
|
||||
int
|
||||
(*send_fd_t)(const int, const int);
|
||||
|
||||
/**
|
||||
* \short Infinite loop parsing commands and returning the sockets.
|
||||
*
|
||||
* This reads commands and socket descriptions from the input_fd
|
||||
* file descriptor, creates sockets and writes the results (socket or
|
||||
* error) to output_fd.
|
||||
*
|
||||
* Current errors are:
|
||||
* - 1: Read error
|
||||
* - 2: Write error
|
||||
* - 3: Protocol error (unknown command, etc)
|
||||
* - 4: Some internal inconsistency detected
|
||||
*
|
||||
* It terminates either if a command asks it to or when unrecoverable
|
||||
* error happens.
|
||||
*
|
||||
* \return Like a return value of a main - 0 means everything OK, anything
|
||||
* else is error.
|
||||
* \param input_fd Here is where it reads the commads.
|
||||
* \param output_fd Here is where it writes the results.
|
||||
* \param get_sock_fun The function that is used to create the sockets.
|
||||
* This should be left on the default value, the parameter is here
|
||||
* for testing purposes.
|
||||
* \param send_fd_fun The function that is used to send the socket over
|
||||
* a file descriptor. This should be left on the default value, it is
|
||||
* here for testing purposes.
|
||||
*/
|
||||
int
|
||||
run(const int input_fd, const int output_fd,
|
||||
const get_sock_t get_sock_fun = get_sock,
|
||||
const send_fd_t send_fd_fun = isc::util::io::send_fd);
|
||||
|
||||
} // End of the namespaces
|
||||
}
|
||||
|
||||
#endif // __SOCKCREATOR_H
|
25
src/bin/sockcreator/tests/Makefile.am
Normal file
25
src/bin/sockcreator/tests/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
||||
CLEANFILES = *.gcno *.gcda
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
|
||||
AM_CXXFLAGS = $(B10_CXXFLAGS)
|
||||
|
||||
if USE_STATIC_LINK
|
||||
AM_LDFLAGS = -static
|
||||
endif
|
||||
|
||||
TESTS =
|
||||
if HAVE_GTEST
|
||||
TESTS += run_unittests
|
||||
run_unittests_SOURCES = ../sockcreator.cc ../sockcreator.h
|
||||
run_unittests_SOURCES += sockcreator_tests.cc
|
||||
run_unittests_SOURCES += run_unittests.cc
|
||||
|
||||
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
||||
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
|
||||
run_unittests_LDADD = $(GTEST_LDADD)
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/util/io/libutil_io.la
|
||||
run_unittests_LDADD += \
|
||||
$(top_builddir)/src/lib/util/unittests/libutil_unittests.la
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
22
src/bin/sockcreator/tests/run_unittests.cc
Normal file
22
src/bin/sockcreator/tests/run_unittests.cc
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
273
src/bin/sockcreator/tests/sockcreator_tests.cc
Normal file
273
src/bin/sockcreator/tests/sockcreator_tests.cc
Normal file
@@ -0,0 +1,273 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "../sockcreator.h"
|
||||
|
||||
#include <util/unittests/fork.h>
|
||||
#include <util/io/fd.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
using namespace isc::socket_creator;
|
||||
using namespace isc::util::unittests;
|
||||
using namespace isc::util::io;
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* Generic version of the creation of socket test. It just tries to
|
||||
* create the socket and checks the result is not negative (eg.
|
||||
* it is valid descriptor) and that it can listen.
|
||||
*
|
||||
* This is a macro so ASSERT_* does abort the TEST, not just the
|
||||
* function inside.
|
||||
*/
|
||||
#define TEST_ANY_CREATE(SOCK_TYPE, ADDR_TYPE, ADDR_FAMILY, FAMILY_FIELD, \
|
||||
ADDR_SET, CHECK_SOCK) \
|
||||
do { \
|
||||
/*
|
||||
* This should create an address that binds on all interfaces
|
||||
* and lets the OS choose a free port.
|
||||
*/ \
|
||||
struct ADDR_TYPE addr; \
|
||||
memset(&addr, 0, sizeof addr); \
|
||||
ADDR_SET(addr); \
|
||||
addr.FAMILY_FIELD = ADDR_FAMILY; \
|
||||
struct sockaddr *addr_ptr = static_cast<struct sockaddr *>( \
|
||||
static_cast<void *>(&addr)); \
|
||||
\
|
||||
int socket = get_sock(SOCK_TYPE, addr_ptr, sizeof addr); \
|
||||
/* Provide even nice error message. */ \
|
||||
ASSERT_GE(socket, 0) << "Couldn't create a socket of type " \
|
||||
#SOCK_TYPE " and family " #ADDR_FAMILY ", failed with " \
|
||||
<< socket << " and error " << strerror(errno); \
|
||||
CHECK_SOCK(ADDR_TYPE, socket); \
|
||||
EXPECT_EQ(0, close(socket)); \
|
||||
} while (0)
|
||||
|
||||
// Just helper macros
|
||||
#define INADDR_SET(WHAT) do { WHAT.sin_addr.s_addr = INADDR_ANY; } while (0)
|
||||
#define IN6ADDR_SET(WHAT) do { WHAT.sin6_addr = in6addr_loopback; } while (0)
|
||||
// If the get_sock returned something useful, listen must work
|
||||
#define TCP_CHECK(UNUSED, SOCKET) do { \
|
||||
EXPECT_EQ(0, listen(SOCKET, 1)); \
|
||||
} while (0)
|
||||
// More complicated with UDP, so we send a packet to ourselfs and se if it
|
||||
// arrives
|
||||
#define UDP_CHECK(ADDR_TYPE, SOCKET) do { \
|
||||
struct ADDR_TYPE addr; \
|
||||
memset(&addr, 0, sizeof addr); \
|
||||
struct sockaddr *addr_ptr = static_cast<struct sockaddr *>( \
|
||||
static_cast<void *>(&addr)); \
|
||||
\
|
||||
socklen_t len = sizeof addr; \
|
||||
ASSERT_EQ(0, getsockname(SOCKET, addr_ptr, &len)); \
|
||||
ASSERT_EQ(5, sendto(SOCKET, "test", 5, 0, addr_ptr, sizeof addr)) << \
|
||||
"Send failed with error " << strerror(errno) << " on socket " << \
|
||||
SOCKET; \
|
||||
char buffer[5]; \
|
||||
ASSERT_EQ(5, recv(SOCKET, buffer, 5, 0)) << \
|
||||
"Recv failed with error " << strerror(errno) << " on socket " << \
|
||||
SOCKET; \
|
||||
EXPECT_STREQ("test", buffer); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Several tests to ensure we can create the sockets.
|
||||
*/
|
||||
TEST(get_sock, udp4_create) {
|
||||
TEST_ANY_CREATE(SOCK_DGRAM, sockaddr_in, AF_INET, sin_family, INADDR_SET,
|
||||
UDP_CHECK);
|
||||
}
|
||||
|
||||
TEST(get_sock, tcp4_create) {
|
||||
TEST_ANY_CREATE(SOCK_STREAM, sockaddr_in, AF_INET, sin_family, INADDR_SET,
|
||||
TCP_CHECK);
|
||||
}
|
||||
|
||||
TEST(get_sock, udp6_create) {
|
||||
TEST_ANY_CREATE(SOCK_DGRAM, sockaddr_in6, AF_INET6, sin6_family,
|
||||
IN6ADDR_SET, UDP_CHECK);
|
||||
}
|
||||
|
||||
TEST(get_sock, tcp6_create) {
|
||||
TEST_ANY_CREATE(SOCK_STREAM, sockaddr_in6, AF_INET6, sin6_family,
|
||||
IN6ADDR_SET, TCP_CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to ask the get_sock function some nonsense and test if it
|
||||
* is able to report error.
|
||||
*/
|
||||
TEST(get_sock, fail_with_nonsense) {
|
||||
struct sockaddr addr;
|
||||
memset(&addr, 0, sizeof addr);
|
||||
ASSERT_LT(get_sock(0, &addr, sizeof addr), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions to pass to run during testing.
|
||||
*/
|
||||
int
|
||||
get_sock_dummy(const int type, struct sockaddr *addr, const socklen_t)
|
||||
{
|
||||
int result(0);
|
||||
int port(0);
|
||||
/*
|
||||
* We encode the type and address family into the int and return it.
|
||||
* Lets ignore the port and address for now
|
||||
* First bit is 1 if it is known type. Second tells if TCP or UDP.
|
||||
* The familly is similar - third bit is known address family,
|
||||
* the fourth is the family.
|
||||
*/
|
||||
switch (type) {
|
||||
case SOCK_STREAM:
|
||||
result += 1;
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
result += 3;
|
||||
break;
|
||||
}
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
result += 4;
|
||||
port = static_cast<struct sockaddr_in *>(
|
||||
static_cast<void *>(addr))->sin_port;
|
||||
break;
|
||||
case AF_INET6:
|
||||
result += 12;
|
||||
port = static_cast<struct sockaddr_in6 *>(
|
||||
static_cast<void *>(addr))->sin6_port;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The port should be 0xffff. If it's not, we change the result.
|
||||
* The port of 0xbbbb means bind should fail and 0xcccc means
|
||||
* socket should fail.
|
||||
*/
|
||||
if (port != 0xffff) {
|
||||
errno = 0;
|
||||
if (port == 0xbbbb) {
|
||||
return -2;
|
||||
} else if (port == 0xcccc) {
|
||||
return -1;
|
||||
} else {
|
||||
result += 16;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
send_fd_dummy(const int destination, const int what)
|
||||
{
|
||||
/*
|
||||
* Make sure it is 1 byte so we know the length. We do not use more during
|
||||
* the test anyway.
|
||||
*/
|
||||
char fd_data(what);
|
||||
if (!write_data(destination, &fd_data, 1)) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic test that it works, with various inputs and outputs.
|
||||
* It uses different functions to create the socket and send it and pass
|
||||
* data to it and check it returns correct data back, to see if the run()
|
||||
* parses the commands correctly.
|
||||
*/
|
||||
void run_test(const char *input_data, const size_t input_size,
|
||||
const char *output_data, const size_t output_size,
|
||||
bool should_succeed = true)
|
||||
{
|
||||
// Prepare the input feeder and output checker processes
|
||||
int input_fd(0), output_fd(0);
|
||||
pid_t input(provide_input(&input_fd, input_data, input_size)),
|
||||
output(check_output(&output_fd, output_data, output_size));
|
||||
ASSERT_NE(-1, input) << "Couldn't start input feeder";
|
||||
ASSERT_NE(-1, output) << "Couldn't start output checker";
|
||||
// Run the body
|
||||
int result(run(input_fd, output_fd, get_sock_dummy, send_fd_dummy));
|
||||
// Close the pipes
|
||||
close(input_fd);
|
||||
close(output_fd);
|
||||
// Did it run well?
|
||||
if (should_succeed) {
|
||||
EXPECT_EQ(0, result);
|
||||
} else {
|
||||
EXPECT_NE(0, result);
|
||||
}
|
||||
// Check the subprocesses say everything is OK too
|
||||
EXPECT_TRUE(process_ok(input));
|
||||
EXPECT_TRUE(process_ok(output));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check it terminates successfully when asked to.
|
||||
*/
|
||||
TEST(run, terminate) {
|
||||
run_test("T", 1, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check it rejects incorrect input.
|
||||
*/
|
||||
TEST(run, bad_input) {
|
||||
run_test("XXX", 3, "FI", 2, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check it correctly parses queries to create sockets.
|
||||
*/
|
||||
TEST(run, sockets) {
|
||||
run_test(
|
||||
"SU4\xff\xff\0\0\0\0" // This has 9 bytes
|
||||
"ST4\xff\xff\0\0\0\0" // This has 9 bytes
|
||||
"ST6\xff\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" // This has 21 bytes
|
||||
"SU6\xff\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" // This has 21 bytes
|
||||
"T", 61,
|
||||
"S\x07S\x05S\x0dS\x0f", 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if failures of get_socket are handled correctly.
|
||||
*/
|
||||
TEST(run, bad_sockets) {
|
||||
// We need to construct the answer, but it depends on int length.
|
||||
size_t int_len(sizeof(int));
|
||||
size_t result_len(4 + 2 * int_len);
|
||||
char result[4 + sizeof(int) * 2];
|
||||
// Both errno parts should be 0
|
||||
memset(result, 0, result_len);
|
||||
// Fill the 2 control parts
|
||||
strcpy(result, "EB");
|
||||
strcpy(result + 2 + int_len, "ES");
|
||||
// Run the test
|
||||
run_test(
|
||||
"SU4\xbb\xbb\0\0\0\0"
|
||||
"SU4\xcc\xcc\0\0\0\0"
|
||||
"T", 19,
|
||||
result, result_len);
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
'\" t
|
||||
.\" Title: b10-stats
|
||||
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||
.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
|
||||
.\" Date: Oct 15, 2010
|
||||
.\" Manual: BIND10
|
||||
.\" Source: BIND10
|
||||
@@ -9,6 +9,15 @@
|
||||
.\"
|
||||
.TH "B10\-STATS" "8" "Oct 15, 2010" "BIND10" "BIND10"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.\" http://bugs.debian.org/507673
|
||||
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
|
||||
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.ie \n(.g .ds Aq \(aq
|
||||
.el .ds Aq '
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * set default formatting
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" disable hyphenation
|
||||
@@ -35,6 +44,11 @@ with other modules like
|
||||
\fBbind10\fR,
|
||||
\fBb10\-auth\fR
|
||||
and so on\&. It waits for coming data from other modules, then other modules send data to stats module periodically\&. Other modules send stats data to stats module independently from implementation of stats module, so the frequency of sending data may not be constant\&. Stats module collects data and aggregates it\&.
|
||||
\fBb10\-stats\fR
|
||||
invokes "sendstats" command for
|
||||
\fBbind10\fR
|
||||
after its initial starting because it\*(Aqs sure to collect statistics data from
|
||||
\fBbind10\fR\&.
|
||||
.SH "OPTIONS"
|
||||
.PP
|
||||
The arguments are as follows:
|
||||
@@ -49,7 +63,8 @@ switches to verbose mode\&. It sends verbose messages to STDOUT\&.
|
||||
.PP
|
||||
/usr/local/share/bind10\-devel/stats\&.spec
|
||||
\(em This is a spec file for
|
||||
\fBb10\-stats\fR\&. It contains definitions of statistics items of BIND 10 and commands received vi bindctl\&.
|
||||
\fBb10\-stats\fR\&. It contains definitions of statistics items of BIND 10 and commands received via
|
||||
bindctl(1)\&.
|
||||
.SH "SEE ALSO"
|
||||
.PP
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY mdash "—">]>
|
||||
<!--
|
||||
- Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
|
||||
- Copyright (C) 2010,2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
-
|
||||
- Permission to use, copy, modify, and/or distribute this software for any
|
||||
- purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -64,7 +64,9 @@
|
||||
send stats data to stats module independently from
|
||||
implementation of stats module, so the frequency of sending data
|
||||
may not be constant. Stats module collects data and aggregates
|
||||
it.
|
||||
it. <command>b10-stats</command> invokes "sendstats" command
|
||||
for <command>bind10</command> after its initial starting because it's
|
||||
sure to collect statistics data from <command>bind10</command>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!@PYTHON@
|
||||
|
||||
# Copyright (C) 2010 Internet Systems Consortium.
|
||||
# Copyright (C) 2010, 2011 Internet Systems Consortium.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -15,8 +15,6 @@
|
||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = "$Revision$"
|
||||
|
||||
import sys; sys.path.append ('@@PYTHONPATH@@')
|
||||
import os
|
||||
import signal
|
||||
@@ -220,7 +218,13 @@ class CCSessionListener(Listener):
|
||||
self.stats_data['stats.start_time'] = get_datetime()
|
||||
self.stats_data['stats.last_update_time'] = get_datetime()
|
||||
self.stats_data['stats.lname'] = self.session.lname
|
||||
return self.cc_session.start()
|
||||
self.cc_session.start()
|
||||
# request Bob to send statistics data
|
||||
if self.verbose:
|
||||
sys.stdout.write("[b10-stats] request Bob to send statistics data\n")
|
||||
cmd = isc.config.ccsession.create_command("sendstats", None)
|
||||
seq = self.session.group_sendmsg(cmd, 'Boss')
|
||||
self.session.group_recvmsg(True, seq)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2010 Internet Systems Consortium.
|
||||
# Copyright (C) 2010,2011 Internet Systems Consortium.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -13,8 +13,6 @@
|
||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
__version__ = "$Revision$"
|
||||
|
||||
#
|
||||
# Tests for the stats module
|
||||
#
|
||||
@@ -504,6 +502,13 @@ class TestStats(unittest.TestCase):
|
||||
self.assertEqual(result_ok(),
|
||||
self.session.get_message("Stats", None))
|
||||
|
||||
def test_for_boss(self):
|
||||
last_queue = self.session.old_message_queue.pop()
|
||||
self.assertEqual(
|
||||
last_queue.msg, {'command': ['sendstats']})
|
||||
self.assertEqual(
|
||||
last_queue.env['group'], 'Boss')
|
||||
|
||||
class TestStats2(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
|
||||
# required by loadable python modules.
|
||||
LIBRARY_PATH_PLACEHOLDER =
|
||||
if SET_ENV_LIBRARY_PATH
|
||||
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
|
||||
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
|
||||
endif
|
||||
|
||||
# test using command-line arguments, so use check-local target instead of TESTS
|
||||
@@ -18,7 +18,7 @@ if ENABLE_PYTHON_COVERAGE
|
||||
endif
|
||||
for pytest in $(PYTESTS) ; do \
|
||||
echo Running test: $$pytest ; \
|
||||
env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
|
||||
env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/util/io/.libs \
|
||||
$(LIBRARY_PATH_PLACEHOLDER) \
|
||||
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
|
||||
done
|
||||
|
@@ -21,6 +21,7 @@ import os
|
||||
from isc.cc.session import *
|
||||
from pydnspp import *
|
||||
from xfrout import *
|
||||
import xfrout
|
||||
|
||||
# our fake socket, where we can read and insert messages
|
||||
class MySocket():
|
||||
@@ -433,5 +434,36 @@ class TestUnixSockServer(unittest.TestCase):
|
||||
sys.stdout = old_stdout
|
||||
os.rmdir(dir_name)
|
||||
|
||||
class TestInitialization(unittest.TestCase):
|
||||
def setEnv(self, name, value):
|
||||
if value is None:
|
||||
if name in os.environ:
|
||||
del os.environ[name]
|
||||
else:
|
||||
os.environ[name] = value
|
||||
|
||||
def setUp(self):
|
||||
self._oldSocket = os.getenv("BIND10_XFROUT_SOCKET_FILE")
|
||||
self._oldFromBuild = os.getenv("B10_FROM_BUILD")
|
||||
|
||||
def tearDown(self):
|
||||
self.setEnv("B10_FROM_BUILD", self._oldFromBuild)
|
||||
self.setEnv("BIND10_XFROUT_SOCKET_FILE", self._oldSocket)
|
||||
# Make sure even the computed values are back
|
||||
xfrout.init_paths()
|
||||
|
||||
def testNoEnv(self):
|
||||
self.setEnv("B10_FROM_BUILD", None)
|
||||
self.setEnv("BIND10_XFROUT_SOCKET_FILE", None)
|
||||
xfrout.init_paths()
|
||||
self.assertEqual(xfrout.UNIX_SOCKET_FILE,
|
||||
"@@LOCALSTATEDIR@@/auth_xfrout_conn")
|
||||
|
||||
def testProvidedSocket(self):
|
||||
self.setEnv("B10_FROM_BUILD", None)
|
||||
self.setEnv("BIND10_XFROUT_SOCKET_FILE", "The/Socket/File")
|
||||
xfrout.init_paths()
|
||||
self.assertEqual(xfrout.UNIX_SOCKET_FILE, "The/Socket/File")
|
||||
|
||||
if __name__== "__main__":
|
||||
unittest.main()
|
@@ -37,16 +37,20 @@ from optparse import OptionParser, OptionValueError
|
||||
from isc.util import socketserver_mixin
|
||||
|
||||
try:
|
||||
from libxfr_python import *
|
||||
from libutil_io_python import *
|
||||
from pydnspp import *
|
||||
except ImportError as e:
|
||||
# C++ loadable module may not be installed; even so the xfrout process
|
||||
# must keep running, so we warn about it and move forward.
|
||||
sys.stderr.write('[b10-xfrout] failed to import DNS or XFR module: %s\n' % str(e))
|
||||
sys.stderr.write('[b10-xfrout] failed to import DNS or isc.util.io module: %s\n' % str(e))
|
||||
|
||||
isc.util.process.rename()
|
||||
|
||||
if "B10_FROM_BUILD" in os.environ:
|
||||
def init_paths():
|
||||
global SPECFILE_PATH
|
||||
global AUTH_SPECFILE_PATH
|
||||
global UNIX_SOCKET_FILE
|
||||
if "B10_FROM_BUILD" in os.environ:
|
||||
SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/xfrout"
|
||||
AUTH_SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/auth"
|
||||
if "B10_FROM_SOURCE_LOCALSTATEDIR" in os.environ:
|
||||
@@ -54,13 +58,18 @@ if "B10_FROM_BUILD" in os.environ:
|
||||
"/auth_xfrout_conn"
|
||||
else:
|
||||
UNIX_SOCKET_FILE = os.environ["B10_FROM_BUILD"] + "/auth_xfrout_conn"
|
||||
else:
|
||||
else:
|
||||
PREFIX = "@prefix@"
|
||||
DATAROOTDIR = "@datarootdir@"
|
||||
SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
|
||||
AUTH_SPECFILE_PATH = SPECFILE_PATH
|
||||
if "BIND10_XFROUT_SOCKET_FILE" in os.environ:
|
||||
UNIX_SOCKET_FILE = os.environ["BIND10_XFROUT_SOCKET_FILE"]
|
||||
else:
|
||||
UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn"
|
||||
|
||||
init_paths()
|
||||
|
||||
SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec"
|
||||
AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + os.sep + "auth.spec"
|
||||
MAX_TRANSFERS_OUT = 10
|
||||
@@ -376,7 +385,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
|
||||
# This may happen when one xfrout process try to connect to
|
||||
# xfrout unix socket server, to check whether there is another
|
||||
# xfrout running.
|
||||
if sock_fd == XFR_FD_RECEIVE_FAIL:
|
||||
if sock_fd == FD_COMM_ERROR:
|
||||
self._log.log_message("error", "Failed to receive the file descriptor for XFR connection")
|
||||
return
|
||||
|
||||
|
@@ -22,10 +22,10 @@ import tempfile
|
||||
from zonemgr import *
|
||||
|
||||
ZONE_NAME_CLASS1_IN = ("sd.cn.", "IN")
|
||||
ZONE_NAME_CLASS2_CH = ("tw.cn", "CH")
|
||||
ZONE_NAME_CLASS2_CH = ("tw.cn.", "CH")
|
||||
ZONE_NAME_CLASS3_IN = ("example.com", "IN")
|
||||
ZONE_NAME_CLASS1_CH = ("sd.cn.", "CH")
|
||||
ZONE_NAME_CLASS2_IN = ("tw.cn", "IN")
|
||||
ZONE_NAME_CLASS2_IN = ("tw.cn.", "IN")
|
||||
|
||||
MAX_TRANSFER_TIMEOUT = 14400
|
||||
LOWERBOUND_REFRESH = 10
|
||||
@@ -46,9 +46,13 @@ class MySession():
|
||||
def group_recvmsg(self, nonblock, seq):
|
||||
return None, None
|
||||
|
||||
class MyZonemgrRefresh(ZonemgrRefresh):
|
||||
class FakeConfig:
|
||||
def __init__(self):
|
||||
class FakeConfig:
|
||||
self.zone_list = []
|
||||
self.set_zone_list_from_name_classes([ZONE_NAME_CLASS1_IN,
|
||||
ZONE_NAME_CLASS2_CH])
|
||||
def set_zone_list_from_name_classes(self, zones):
|
||||
self.zone_list = map(lambda nc: {"name": nc[0], "class": nc[1]}, zones)
|
||||
def get(self, name):
|
||||
if name == 'lowerbound_refresh':
|
||||
return LOWERBOUND_REFRESH
|
||||
@@ -58,9 +62,27 @@ class MyZonemgrRefresh(ZonemgrRefresh):
|
||||
return MAX_TRANSFER_TIMEOUT
|
||||
elif name == 'jitter_scope':
|
||||
return JITTER_SCOPE
|
||||
elif name == 'secondary_zones':
|
||||
return self.zone_list
|
||||
else:
|
||||
raise ValueError('Uknown config option')
|
||||
|
||||
class MyZonemgrRefresh(ZonemgrRefresh):
|
||||
def __init__(self):
|
||||
self._master_socket, self._slave_socket = socket.socketpair()
|
||||
self._zonemgr_refresh_info = {}
|
||||
|
||||
def get_zone_soa(zone_name, db_file):
|
||||
if zone_name == 'sd.cn.':
|
||||
return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
|
||||
'a.dns.cn. root.cnnic.cn. 2009073106 7200 3600 2419200 21600')
|
||||
elif zone_name == 'tw.cn.':
|
||||
return (1, 2, 'tw.cn.', 'cn.sd.', 21600, 'SOA', None,
|
||||
'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600')
|
||||
else:
|
||||
return None
|
||||
sqlite3_ds.get_zone_soa = get_zone_soa
|
||||
|
||||
ZonemgrRefresh.__init__(self, MySession(), "initdb.file",
|
||||
self._slave_socket, FakeConfig())
|
||||
current_time = time.time()
|
||||
@@ -70,7 +92,7 @@ class MyZonemgrRefresh(ZonemgrRefresh):
|
||||
'next_refresh_time': current_time + 6500,
|
||||
'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
|
||||
'zone_state': 0},
|
||||
('tw.cn', 'CH'): {
|
||||
('tw.cn.', 'CH'): {
|
||||
'last_refresh_time': current_time,
|
||||
'next_refresh_time': current_time + 6900,
|
||||
'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073112 7200 3600 2419200 21600',
|
||||
@@ -272,28 +294,6 @@ class TestZonemgrRefresh(unittest.TestCase):
|
||||
ZONE_NAME_CLASS1_IN)
|
||||
sqlite3_ds.get_zone_soa = old_get_zone_soa
|
||||
|
||||
def test_build_zonemgr_refresh_info(self):
|
||||
soa_rdata = 'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600'
|
||||
|
||||
def get_zones_info(db_file):
|
||||
return [("sd.cn.", "IN")]
|
||||
|
||||
def get_zone_soa(zone_name, db_file):
|
||||
return (1, 2, 'sd.cn.', 'cn.sd.', 21600, 'SOA', None,
|
||||
'a.dns.cn. root.cnnic.cn. 2009073106 1800 900 2419200 21600')
|
||||
|
||||
sqlite3_ds.get_zones_info = get_zones_info
|
||||
sqlite3_ds.get_zone_soa = get_zone_soa
|
||||
|
||||
self.zone_refresh._zonemgr_refresh_info = {}
|
||||
self.zone_refresh._build_zonemgr_refresh_info()
|
||||
self.assertEqual(1, len(self.zone_refresh._zonemgr_refresh_info))
|
||||
zone_soa_rdata = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_soa_rdata"]
|
||||
self.assertEqual(soa_rdata, zone_soa_rdata)
|
||||
self.assertEqual(ZONE_OK, self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["zone_state"])
|
||||
self.assertTrue("last_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
|
||||
self.assertTrue("next_refresh_time" in self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN].keys())
|
||||
|
||||
def test_zone_handle_notify(self):
|
||||
self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
|
||||
notify_master = self.zone_refresh._zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
|
||||
@@ -356,7 +356,7 @@ class TestZonemgrRefresh(unittest.TestCase):
|
||||
'next_refresh_time': time1 + 7200,
|
||||
'zone_soa_rdata': 'a.dns.cn. root.cnnic.cn. 2009073105 7200 3600 2419200 21600',
|
||||
'zone_state': ZONE_OK},
|
||||
("tw.cn","CH"):{
|
||||
("tw.cn.","CH"):{
|
||||
'last_refresh_time': time1 - 7200,
|
||||
'next_refresh_time': time1,
|
||||
'refresh_timeout': time1 + MAX_TRANSFER_TIMEOUT,
|
||||
@@ -424,7 +424,8 @@ class TestZonemgrRefresh(unittest.TestCase):
|
||||
"lowerbound_refresh" : 60,
|
||||
"lowerbound_retry" : 30,
|
||||
"max_transfer_timeout" : 19800,
|
||||
"jitter_scope" : 0.25
|
||||
"jitter_scope" : 0.25,
|
||||
"secondary_zones": []
|
||||
}
|
||||
self.zone_refresh.update_config_data(config_data)
|
||||
self.assertEqual(60, self.zone_refresh._lowerbound_refresh)
|
||||
@@ -440,6 +441,31 @@ class TestZonemgrRefresh(unittest.TestCase):
|
||||
self.zone_refresh.shutdown()
|
||||
self.assertFalse(listener.is_alive())
|
||||
|
||||
def test_secondary_zones(self):
|
||||
"""Test that we can modify the list of secondary zones"""
|
||||
config = FakeConfig()
|
||||
config.zone_list = []
|
||||
# First, remove everything
|
||||
self.zone_refresh.update_config_data(config)
|
||||
self.assertEqual(self.zone_refresh._zonemgr_refresh_info, {})
|
||||
# Put something in
|
||||
config.set_zone_list_from_name_classes([ZONE_NAME_CLASS1_IN])
|
||||
self.zone_refresh.update_config_data(config)
|
||||
self.assertTrue(("sd.cn.", "IN") in
|
||||
self.zone_refresh._zonemgr_refresh_info)
|
||||
# This one does not exist
|
||||
config.set_zone_list_from_name_classes(["example.net", "CH"])
|
||||
self.assertRaises(ZonemgrException,
|
||||
self.zone_refresh.update_config_data, config)
|
||||
# So it should not affect the old ones
|
||||
self.assertTrue(("sd.cn.", "IN") in
|
||||
self.zone_refresh._zonemgr_refresh_info)
|
||||
# Make sure it works even when we "accidentally" forget the final dot
|
||||
config.set_zone_list_from_name_classes([("sd.cn", "IN")])
|
||||
self.zone_refresh.update_config_data(config)
|
||||
self.assertTrue(("sd.cn.", "IN") in
|
||||
self.zone_refresh._zonemgr_refresh_info)
|
||||
|
||||
def tearDown(self):
|
||||
sys.stderr= self.stderr_backup
|
||||
|
||||
@@ -467,7 +493,8 @@ class MyZonemgr(Zonemgr):
|
||||
"lowerbound_refresh" : 10,
|
||||
"lowerbound_retry" : 5,
|
||||
"max_transfer_timeout" : 14400,
|
||||
"jitter_scope" : 0.1
|
||||
"jitter_scope" : 0.1,
|
||||
"secondary_zones": []
|
||||
}
|
||||
|
||||
def _start_zone_refresh_timer(self):
|
||||
@@ -483,9 +510,11 @@ class TestZonemgr(unittest.TestCase):
|
||||
"lowerbound_refresh" : 60,
|
||||
"lowerbound_retry" : 30,
|
||||
"max_transfer_timeout" : 14400,
|
||||
"jitter_scope" : 0.1
|
||||
"jitter_scope" : 0.1,
|
||||
"secondary_zones": []
|
||||
}
|
||||
self.zonemgr.config_handler(config_data1)
|
||||
self.assertEqual(self.zonemgr.config_handler(config_data1),
|
||||
{"result": [0]})
|
||||
self.assertEqual(config_data1, self.zonemgr._config_data)
|
||||
config_data2 = {"zone_name" : "sd.cn.", "port" : "53", "master" : "192.168.1.1"}
|
||||
self.zonemgr.config_handler(config_data2)
|
||||
@@ -494,6 +523,15 @@ class TestZonemgr(unittest.TestCase):
|
||||
config_data3 = {"jitter_scope" : 0.7}
|
||||
self.zonemgr.config_handler(config_data3)
|
||||
self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
|
||||
# The zone doesn't exist in database, it should be rejected
|
||||
self.zonemgr._zone_refresh = ZonemgrRefresh(None, "initdb.file", None,
|
||||
config_data1)
|
||||
config_data1["secondary_zones"] = [{"name": "nonexistent.example",
|
||||
"class": "IN"}]
|
||||
self.assertNotEqual(self.zonemgr.config_handler(config_data1),
|
||||
{"result": [0]})
|
||||
# As it is rejected, the old value should be kept
|
||||
self.assertEqual(0.5, self.zonemgr._config_data.get("jitter_scope"))
|
||||
|
||||
def test_get_db_file(self):
|
||||
self.assertEqual("initdb.file", self.zonemgr.get_db_file())
|
||||
|
@@ -100,9 +100,8 @@ class ZonemgrRefresh:
|
||||
self._cc = cc
|
||||
self._check_sock = slave_socket
|
||||
self._db_file = db_file
|
||||
self.update_config_data(config_data)
|
||||
self._zonemgr_refresh_info = {}
|
||||
self._build_zonemgr_refresh_info()
|
||||
self.update_config_data(config_data)
|
||||
self._running = False
|
||||
|
||||
def _random_jitter(self, max, jitter):
|
||||
@@ -148,16 +147,13 @@ class ZonemgrRefresh:
|
||||
|
||||
def _zone_not_exist(self, zone_name_class):
|
||||
""" Zone doesn't belong to zonemgr"""
|
||||
if zone_name_class in self._zonemgr_refresh_info.keys():
|
||||
return False
|
||||
return True
|
||||
return not zone_name_class in self._zonemgr_refresh_info
|
||||
|
||||
def zone_refresh_success(self, zone_name_class):
|
||||
"""Update zone info after zone refresh success"""
|
||||
if (self._zone_not_exist(zone_name_class)):
|
||||
raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
|
||||
"belong to zonemgr" % zone_name_class)
|
||||
return
|
||||
self.zonemgr_reload_zone(zone_name_class)
|
||||
self._set_zone_refresh_timer(zone_name_class)
|
||||
self._set_zone_state(zone_name_class, ZONE_OK)
|
||||
@@ -168,7 +164,6 @@ class ZonemgrRefresh:
|
||||
if (self._zone_not_exist(zone_name_class)):
|
||||
raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
|
||||
"belong to zonemgr" % zone_name_class)
|
||||
return
|
||||
# Is zone expired?
|
||||
if (self._zone_is_expired(zone_name_class)):
|
||||
self._set_zone_state(zone_name_class, ZONE_EXPIRED)
|
||||
@@ -181,7 +176,6 @@ class ZonemgrRefresh:
|
||||
if (self._zone_not_exist(zone_name_class)):
|
||||
raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) "
|
||||
"doesn't belong to zonemgr" % zone_name_class)
|
||||
return
|
||||
self._set_zone_notifier_master(zone_name_class, master)
|
||||
self._set_zone_notify_timer(zone_name_class)
|
||||
|
||||
@@ -192,6 +186,7 @@ class ZonemgrRefresh:
|
||||
|
||||
def zonemgr_add_zone(self, zone_name_class):
|
||||
""" Add a zone into zone manager."""
|
||||
log_msg("Loading zone (%s, %s)" % zone_name_class)
|
||||
zone_info = {}
|
||||
zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
|
||||
if not zone_soa:
|
||||
@@ -203,14 +198,6 @@ class ZonemgrRefresh:
|
||||
float(zone_soa[7].split(" ")[REFRESH_OFFSET])
|
||||
self._zonemgr_refresh_info[zone_name_class] = zone_info
|
||||
|
||||
def _build_zonemgr_refresh_info(self):
|
||||
""" Build zonemgr refresh info map."""
|
||||
log_msg("Start loading zone into zonemgr.")
|
||||
for zone_name, zone_class in sqlite3_ds.get_zones_info(self._db_file):
|
||||
zone_name_class = (zone_name, zone_class)
|
||||
self.zonemgr_add_zone(zone_name_class)
|
||||
log_msg("Finish loading zone into zonemgr.")
|
||||
|
||||
def _zone_is_expired(self, zone_name_class):
|
||||
"""Judge whether a zone is expired or not."""
|
||||
zone_expired_time = float(self._get_zone_soa_rdata(zone_name_class).split(" ")[EXPIRED_OFFSET])
|
||||
@@ -415,6 +402,32 @@ class ZonemgrRefresh:
|
||||
|
||||
def update_config_data(self, new_config):
|
||||
""" update ZonemgrRefresh config """
|
||||
backup = self._zonemgr_refresh_info.copy()
|
||||
try:
|
||||
required = {}
|
||||
# Add new zones
|
||||
for secondary_zone in new_config.get('secondary_zones'):
|
||||
name = secondary_zone['name']
|
||||
# Be tolerant to sclerotic users who forget the final dot
|
||||
if name[-1] != '.':
|
||||
name = name + '.'
|
||||
name_class = (name, secondary_zone['class'])
|
||||
required[name_class] = True
|
||||
# Add it only if it isn't there already
|
||||
if not name_class in self._zonemgr_refresh_info:
|
||||
self.zonemgr_add_zone(name_class)
|
||||
# Drop the zones that are no longer there
|
||||
# Do it in two phases, python doesn't like deleting while iterating
|
||||
to_drop = []
|
||||
for old_zone in self._zonemgr_refresh_info:
|
||||
if not old_zone in required:
|
||||
to_drop.append(old_zone)
|
||||
for drop in to_drop:
|
||||
del self._zonemgr_refresh_info[drop]
|
||||
# If we are not able to find it in database, restore the original
|
||||
except:
|
||||
self._zonemgr_refresh_info = backup
|
||||
raise
|
||||
self._lowerbound_refresh = new_config.get('lowerbound_refresh')
|
||||
self._lowerbound_retry = new_config.get('lowerbound_retry')
|
||||
self._max_transfer_timeout = new_config.get('max_transfer_timeout')
|
||||
@@ -471,27 +484,38 @@ class Zonemgr:
|
||||
def config_handler(self, new_config):
|
||||
""" Update config data. """
|
||||
answer = create_answer(0)
|
||||
ok = True
|
||||
complete = self._config_data.copy()
|
||||
for key in new_config:
|
||||
if key not in self._config_data:
|
||||
if key not in complete:
|
||||
answer = create_answer(1, "Unknown config data: " + str(key))
|
||||
ok = False
|
||||
continue
|
||||
self._config_data[key] = new_config[key]
|
||||
complete[key] = new_config[key]
|
||||
|
||||
self._config_data_check(self._config_data)
|
||||
if (self._zone_refresh):
|
||||
self._zone_refresh.update_config_data(self._config_data)
|
||||
self._config_data_check(complete)
|
||||
if self._zone_refresh is not None:
|
||||
try:
|
||||
self._zone_refresh.update_config_data(complete)
|
||||
except Exception as e:
|
||||
answer = create_answer(1, str(e))
|
||||
ok = False
|
||||
if ok:
|
||||
self._config_data = complete
|
||||
|
||||
return answer
|
||||
|
||||
def _config_data_check(self, config_data):
|
||||
"""Check whether the new config data is valid or
|
||||
not. """
|
||||
not. It contains only basic logic, not full check against
|
||||
database."""
|
||||
# jitter should not be bigger than half of the original value
|
||||
if config_data.get('jitter_scope') > 0.5:
|
||||
config_data['jitter_scope'] = 0.5
|
||||
log_msg("[b10-zonemgr] jitter_scope is too big, its value will "
|
||||
"be set to 0.5")
|
||||
|
||||
|
||||
def _parse_cmd_params(self, args, command):
|
||||
zone_name = args.get("zone_name")
|
||||
if not zone_name:
|
||||
|
@@ -25,6 +25,32 @@
|
||||
"item_type": "real",
|
||||
"item_optional": false,
|
||||
"item_default": 0.25
|
||||
},
|
||||
{
|
||||
"item_name": "secondary_zones",
|
||||
"item_type": "list",
|
||||
"item_optional": false,
|
||||
"item_default": [],
|
||||
"list_item_spec": {
|
||||
"item_name": "secondary_zone",
|
||||
"item_type": "map",
|
||||
"item_optional": false,
|
||||
"item_default": {},
|
||||
"map_item_spec": [
|
||||
{
|
||||
"item_name": "class",
|
||||
"item_type": "string",
|
||||
"item_optional": false,
|
||||
"item_default": "IN"
|
||||
},
|
||||
{
|
||||
"item_name": "name",
|
||||
"item_type": "string",
|
||||
"item_optional": false,
|
||||
"item_default": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
|
@@ -1,2 +1,2 @@
|
||||
SUBDIRS = exceptions util dns cc config python xfr bench log \
|
||||
asiolink nsas cache resolve testutils datasrc server_common
|
||||
SUBDIRS = exceptions util dns cc config python xfr bench log asiolink \
|
||||
asiodns nsas cache resolve testutils datasrc server_common
|
||||
|
34
src/lib/asiodns/Makefile.am
Normal file
34
src/lib/asiodns/Makefile.am
Normal file
@@ -0,0 +1,34 @@
|
||||
SUBDIRS = . tests
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
|
||||
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink -I$(top_builddir)/src/lib/asiolink
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
|
||||
|
||||
AM_CXXFLAGS = $(B10_CXXFLAGS)
|
||||
|
||||
CLEANFILES = *.gcno *.gcda
|
||||
|
||||
lib_LTLIBRARIES = libasiodns.la
|
||||
libasiodns_la_SOURCES = dns_answer.h
|
||||
libasiodns_la_SOURCES += asiodns.h
|
||||
libasiodns_la_SOURCES += asiodef.cc asiodef.h
|
||||
libasiodns_la_SOURCES += dns_lookup.h
|
||||
libasiodns_la_SOURCES += dns_server.h
|
||||
libasiodns_la_SOURCES += dns_service.cc dns_service.h
|
||||
libasiodns_la_SOURCES += tcp_server.cc tcp_server.h
|
||||
libasiodns_la_SOURCES += udp_server.cc udp_server.h
|
||||
libasiodns_la_SOURCES += io_fetch.cc io_fetch.h
|
||||
|
||||
EXTRA_DIST = asiodef.msg
|
||||
|
||||
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
|
||||
# B10_CXXFLAGS)
|
||||
libasiodns_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
if USE_CLANGPP
|
||||
# Same for clang++, but we need to turn off -Werror completely.
|
||||
libasiodns_la_CXXFLAGS += -Wno-error
|
||||
endif
|
||||
libasiodns_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
libasiodns_la_LIBADD = $(top_builddir)/src/lib/log/liblog.la
|
157
src/lib/asiodns/README
Normal file
157
src/lib/asiodns/README
Normal file
@@ -0,0 +1,157 @@
|
||||
The asiodns library is intended to provide an abstraction layer between
|
||||
BIND10 modules and asiolink library.
|
||||
|
||||
These DNS server and client routines are written using the "stackless
|
||||
coroutine" pattern invented by Chris Kohlhoff and described at
|
||||
http://blog.think-async.com/2010/03/potted-guide-to-stackless-coroutines.html.
|
||||
This is intended to simplify development a bit, since it allows the
|
||||
routines to be written in a straightfowrard step-step-step fashion rather
|
||||
than as a complex chain of separate handler functions.
|
||||
|
||||
Coroutine objects (i.e., UDPServer, TCPServer and IOFetch) are objects
|
||||
with reenterable operator() members. When an instance of one of these
|
||||
classes is called as a function, it resumes at the position where it left
|
||||
off. Thus, a UDPServer can issue an asynchronous I/O call and specify
|
||||
itself as the handler object; when the call completes, the UDPServer
|
||||
carries on at the same position. As a result, the code can look as
|
||||
if it were using synchronous, not asynchronous, I/O, providing some of
|
||||
the benefit of threading but with minimal switching overhead.
|
||||
|
||||
So, in simplified form, the behavior of a DNS Server is:
|
||||
|
||||
REENTER:
|
||||
while true:
|
||||
YIELD packet = read_packet
|
||||
FORK
|
||||
if not parent:
|
||||
break
|
||||
|
||||
# This callback informs the caller that a packet has arrived, and
|
||||
# gives it a chance to update configuration, etc
|
||||
SimpleCallback(packet)
|
||||
YIELD answer = DNSLookup(packet, this)
|
||||
response = DNSAnswer(answer)
|
||||
YIELD send(response)
|
||||
|
||||
At each "YIELD" point, the coroutine initiates an asynchronous operation,
|
||||
then pauses and turns over control to some other task on the ASIO service
|
||||
queue. When the operation completes, the coroutine resumes.
|
||||
|
||||
DNSLookup, DNSAnswer and SimpleCallback define callback methods
|
||||
used by a DNS Server to communicate with the module that called it.
|
||||
They are abstract-only classes whose concrete implementations
|
||||
are supplied by the calling module.
|
||||
|
||||
The DNSLookup callback always runs asynchronously. Concrete
|
||||
implementations must be sure to call the server's "resume" method when
|
||||
it is finished.
|
||||
|
||||
In an authoritative server, the DNSLookup implementation would examine
|
||||
the query, look up the answer, then call "resume". (See the diagram
|
||||
in doc/auth_process.jpg.)
|
||||
|
||||
In a recursive server, the DNSLookup impelemtation would initiate a
|
||||
DNSQuery, which in turn would be responsible for calling the server's
|
||||
"resume" method. (See the diagram in doc/recursive_process.jpg.)
|
||||
|
||||
A DNSQuery object is intended to handle resolution of a query over
|
||||
the network when the local authoritative data sources or cache are not
|
||||
sufficient. The plan is that it will make use of subsidiary DNSFetch
|
||||
calls to get data from particular authoritative servers, and when it has
|
||||
gotten a complete answer, it calls "resume".
|
||||
|
||||
In current form, however, DNSQuery is much simpler; it forwards queries
|
||||
to a single upstream resolver and passes the answers back to the client.
|
||||
It is constructed with the address of the forward server. Queries are
|
||||
initiated with the question to ask the forward server, a buffer into
|
||||
which to write the answer, and a pointer to the coroutine to be resumed
|
||||
when the answer has arrived. In simplified form, the DNSQuery routine is:
|
||||
|
||||
REENTER:
|
||||
render the question into a wire-format query packet
|
||||
YIELD send(query)
|
||||
YIELD response = read_packet
|
||||
server->resume
|
||||
|
||||
Currently, DNSQuery is only implemented for UDP queries. In future work
|
||||
it will be necessary to write code to fall back to TCP when circumstances
|
||||
require it.
|
||||
|
||||
|
||||
Upstream Fetches
|
||||
================
|
||||
Upstream fetches (queries by the resolver on behalf of a client) are made
|
||||
using a slightly-modified version of the pattern described above.
|
||||
|
||||
Sockets
|
||||
-------
|
||||
First, it will be useful to understand the class hierarchy used in the
|
||||
fetch logic:
|
||||
|
||||
IOSocket
|
||||
|
|
||||
IOAsioSocket
|
||||
|
|
||||
+-----+-----+
|
||||
| |
|
||||
UDPSocket TCPSocket
|
||||
|
||||
IOSocket is a wrapper class for a socket and is used by the authoritative
|
||||
server code. It is an abstract base class, providing little more that the ability to hold the socket and to return the protocol in use.
|
||||
|
||||
Built on this is IOAsioSocket, which adds the open, close, asyncSend and
|
||||
asyncReceive methods. This is a template class, which takes as template
|
||||
argument the class of the object that will be used as the callback when the
|
||||
asynchronous operation completes. This object can be of any type, but must
|
||||
include an operator() method with the signature:
|
||||
|
||||
operator()(asio::error_code ec, size_t length)
|
||||
|
||||
... the two arguments being the status of the completed I/O operation and
|
||||
the number of bytes transferred. (In the case of the open method, the second
|
||||
argument will be zero.)
|
||||
|
||||
Finally, the TCPSocket and UDPSocket classes provide the body of the
|
||||
asynchronous operations.
|
||||
|
||||
Fetch Sequence
|
||||
--------------
|
||||
The fetch is implemented by the IOFetch class, which takes as argument the
|
||||
protocol to use. The sequence is:
|
||||
|
||||
REENTER:
|
||||
render the question into a wire-format query packet
|
||||
open() // Open socket and optionally connect
|
||||
if (! synchronous) {
|
||||
YIELD;
|
||||
}
|
||||
YIELD asyncSend(query) // Send query
|
||||
do {
|
||||
YIELD asyncReceive(response) // Read response
|
||||
} while (! complete(response))
|
||||
close() // Drop connection and close socket
|
||||
server->resume
|
||||
|
||||
The open() method opens a socket for use. On TCP, it also makes a
|
||||
connection to the remote end. So under UDP the operation will complete
|
||||
immediately, but under TCP it could take a long time. One solution would be
|
||||
for the open operation to post an event to the I/O queue; then both cases
|
||||
could be regarded as being equivalent, with the completion being signalled
|
||||
by the posting of the completion event. However UDP is the most common case
|
||||
and that would involve extra overhead. So the open() returns a status
|
||||
indicating whether the operation completed asynchronously. If it did, the
|
||||
code yields back to the coroutine; if not the yield is bypassed.
|
||||
|
||||
The asynchronous send is straightforward, invoking the underlying ASIO
|
||||
function. (Note that the address/port is supplied to both the open() and
|
||||
asyncSend() methods - it is used by the TCPSocket in open() and by the
|
||||
UDPSocket in asyncSend().)
|
||||
|
||||
The asyncReceive() method issues an asynchronous read and waits for completion.
|
||||
The fetch object keeps track of the amount of data received so far and when
|
||||
the receive completes it calls a method on the socket to determine if the
|
||||
entire message has been received. (This will always be the case for UDP. On
|
||||
TCP though, the message is preceded by a count field as several reads may be
|
||||
required to read all the data.) The fetch loops until all the data is read.
|
||||
|
||||
Finally, the socket is closed and the server called to resume operation.
|
@@ -4,18 +4,20 @@
|
||||
#include <log/message_types.h>
|
||||
#include <log/message_initializer.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
extern const isc::log::MessageID ASIO_FETCHCOMP = "FETCHCOMP";
|
||||
extern const isc::log::MessageID ASIO_FETCHSTOP = "FETCHSTOP";
|
||||
extern const isc::log::MessageID ASIO_OPENSOCK = "OPENSOCK";
|
||||
extern const isc::log::MessageID ASIO_RECVSOCK = "RECVSOCK";
|
||||
extern const isc::log::MessageID ASIO_RECVTMO = "RECVTMO";
|
||||
extern const isc::log::MessageID ASIO_SENDSOCK = "SENDSOCK";
|
||||
extern const isc::log::MessageID ASIO_UNKORIGIN = "UNKORIGIN";
|
||||
extern const isc::log::MessageID ASIO_UNKRESULT = "UNKRESULT";
|
||||
extern const isc::log::MessageID ASIODNS_FETCHCOMP = "FETCHCOMP";
|
||||
extern const isc::log::MessageID ASIODNS_FETCHSTOP = "FETCHSTOP";
|
||||
extern const isc::log::MessageID ASIODNS_OPENSOCK = "OPENSOCK";
|
||||
extern const isc::log::MessageID ASIODNS_RECVSOCK = "RECVSOCK";
|
||||
extern const isc::log::MessageID ASIODNS_RECVTMO = "RECVTMO";
|
||||
extern const isc::log::MessageID ASIODNS_SENDSOCK = "SENDSOCK";
|
||||
extern const isc::log::MessageID ASIODNS_UNKORIGIN = "UNKORIGIN";
|
||||
extern const isc::log::MessageID ASIODNS_UNKRESULT = "UNKRESULT";
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
|
||||
namespace {
|
||||
|
23
src/lib/asiodns/asiodef.h
Normal file
23
src/lib/asiodns/asiodef.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// File created from asiodef.msg on Mon Feb 28 17:15:30 2011
|
||||
|
||||
#ifndef __ASIODEF_H
|
||||
#define __ASIODEF_H
|
||||
|
||||
#include <log/message_types.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
extern const isc::log::MessageID ASIODNS_FETCHCOMP;
|
||||
extern const isc::log::MessageID ASIODNS_FETCHSTOP;
|
||||
extern const isc::log::MessageID ASIODNS_OPENSOCK;
|
||||
extern const isc::log::MessageID ASIODNS_RECVSOCK;
|
||||
extern const isc::log::MessageID ASIODNS_RECVTMO;
|
||||
extern const isc::log::MessageID ASIODNS_SENDSOCK;
|
||||
extern const isc::log::MessageID ASIODNS_UNKORIGIN;
|
||||
extern const isc::log::MessageID ASIODNS_UNKRESULT;
|
||||
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
|
||||
#endif // __ASIODEF_H
|
@@ -12,8 +12,8 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
$PREFIX ASIO_
|
||||
$NAMESPACE asiolink
|
||||
$PREFIX ASIODNS_
|
||||
$NAMESPACE isc::asiodns
|
||||
|
||||
FETCHCOMP upstream fetch to %s(%d) has now completed
|
||||
+ A debug message, this records the the upstream fetch (a query made by the
|
23
src/lib/asiodns/asiodns.h
Normal file
23
src/lib/asiodns/asiodns.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef __ASIODNS_H
|
||||
#define __ASIODNS_H 1
|
||||
|
||||
#include <asiodns/dns_service.h>
|
||||
#include <asiodns/dns_server.h>
|
||||
#include <asiodns/dns_lookup.h>
|
||||
#include <asiodns/dns_answer.h>
|
||||
|
||||
#endif // __ASIODNS_H
|
@@ -16,8 +16,11 @@
|
||||
#define __ASIOLINK_DNS_ANSWER_H 1
|
||||
|
||||
#include <asiolink/io_message.h>
|
||||
#include <util/buffer.h>
|
||||
#include <dns/message.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/// \brief The \c DNSAnswer class is an abstract base class for a DNS
|
||||
/// Answer provider function.
|
||||
@@ -63,11 +66,12 @@ public:
|
||||
/// \param answer_message The DNS MessagePtr of the answer we are
|
||||
/// building
|
||||
/// \param buffer Intermediate data results are put here
|
||||
virtual void operator()(const IOMessage& io_message,
|
||||
virtual void operator()(const asiolink::IOMessage& io_message,
|
||||
isc::dns::MessagePtr query_message,
|
||||
isc::dns::MessagePtr answer_message,
|
||||
isc::util::OutputBufferPtr buffer) const = 0;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_DNS_ANSWER_H
|
@@ -16,11 +16,12 @@
|
||||
#define __ASIOLINK_DNS_LOOKUP_H 1
|
||||
|
||||
#include <asiolink/io_message.h>
|
||||
#include <asiolink/dns_server.h>
|
||||
#include <util/buffer.h>
|
||||
#include <asiodns/dns_server.h>
|
||||
#include <dns/message.h>
|
||||
#include <util/buffer.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/// \brief The \c DNSLookup class is an abstract base class for a DNS
|
||||
/// Lookup provider function.
|
||||
@@ -67,7 +68,7 @@ public:
|
||||
/// this MessagePtr
|
||||
/// \param buffer The final answer is put here
|
||||
/// \param server DNSServer object to use
|
||||
virtual void operator()(const IOMessage& io_message,
|
||||
virtual void operator()(const asiolink::IOMessage& io_message,
|
||||
isc::dns::MessagePtr message,
|
||||
isc::dns::MessagePtr answer_message,
|
||||
isc::util::OutputBufferPtr buffer,
|
||||
@@ -79,5 +80,6 @@ private:
|
||||
DNSLookup* self_;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_DNS_LOOKUP_H
|
@@ -17,7 +17,8 @@
|
||||
|
||||
#include <asiolink/io_message.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/// \brief The \c DNSServer class is a wrapper (and base class) for
|
||||
/// classes which provide DNS server functionality.
|
||||
@@ -34,7 +35,7 @@ namespace asiolink {
|
||||
/// instantiated through a base class) are sometimes passed by
|
||||
/// reference (as this superclass); calls to methods in the base
|
||||
/// class are then rerouted via this pointer to methods in the derived
|
||||
/// class. This allows code from outside asiolink, with no specific
|
||||
/// class. This allows code from outside asiodns, with no specific
|
||||
/// knowledge of \c TCPServer or \c UDPServer, to access their methods.
|
||||
///
|
||||
/// This class is both assignable and copy-constructable. Its subclasses
|
||||
@@ -151,5 +152,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
} // asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_DNS_SERVER_H
|
@@ -23,11 +23,11 @@
|
||||
#include <log/dummylog.h>
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <asiolink/dns_service.h>
|
||||
#include <dns_service.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/tcp_server.h>
|
||||
#include <asiolink/udp_server.h>
|
||||
#include <tcp_server.h>
|
||||
#include <udp_server.h>
|
||||
|
||||
#include <log/dummylog.h>
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
|
||||
using isc::log::dlog;
|
||||
|
||||
namespace asiolink {
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
class SimpleCallback;
|
||||
class DNSLookup;
|
||||
class DNSAnswer;
|
||||
|
||||
@@ -195,6 +197,5 @@ DNSService::clearServers() {
|
||||
impl_->servers_.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
@@ -18,10 +18,11 @@
|
||||
#include <resolve/resolver_interface.h>
|
||||
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/simple_callback.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
class SimpleCallback;
|
||||
class DNSLookup;
|
||||
class DNSAnswer;
|
||||
class DNSServiceImpl;
|
||||
@@ -54,8 +55,8 @@ public:
|
||||
/// \param checkin Provider for cc-channel events (see \c SimpleCallback)
|
||||
/// \param lookup The lookup provider (see \c DNSLookup)
|
||||
/// \param answer The answer provider (see \c DNSAnswer)
|
||||
DNSService(IOService& io_service, const char& port,
|
||||
const char& address, SimpleCallback* checkin,
|
||||
DNSService(asiolink::IOService& io_service, const char& port,
|
||||
const char& address, isc::asiolink::SimpleCallback* checkin,
|
||||
DNSLookup* lookup, DNSAnswer* answer);
|
||||
/// \brief The constructor with a specific port on which the services
|
||||
/// listen on.
|
||||
@@ -71,14 +72,14 @@ public:
|
||||
/// \param checkin Provider for cc-channel events (see \c SimpleCallback)
|
||||
/// \param lookup The lookup provider (see \c DNSLookup)
|
||||
/// \param answer The answer provider (see \c DNSAnswer)
|
||||
DNSService(IOService& io_service, const char& port,
|
||||
DNSService(asiolink::IOService& io_service, const char& port,
|
||||
const bool use_ipv4, const bool use_ipv6,
|
||||
SimpleCallback* checkin, DNSLookup* lookup,
|
||||
isc::asiolink::SimpleCallback* checkin, DNSLookup* lookup,
|
||||
DNSAnswer* answer);
|
||||
/// \brief The constructor without any servers.
|
||||
///
|
||||
/// Use addServer() to add some servers.
|
||||
DNSService(IOService& io_service, SimpleCallback* checkin,
|
||||
DNSService(asiolink::IOService& io_service, isc::asiolink::SimpleCallback* checkin,
|
||||
DNSLookup* lookup, DNSAnswer* answer);
|
||||
/// \brief The destructor.
|
||||
~DNSService();
|
||||
@@ -105,8 +106,9 @@ public:
|
||||
|
||||
private:
|
||||
DNSServiceImpl* impl_;
|
||||
IOService& io_service_;
|
||||
asiolink::IOService& io_service_;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_DNS_SERVICE_H
|
@@ -14,47 +14,50 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <unistd.h> // for some IPC/network system calls
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h> // for some IPC/network system calls
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <asio/deadline_timer.hpp>
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <asiolink/io_asio_socket.h>
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/tcp_endpoint.h>
|
||||
#include <asiolink/tcp_socket.h>
|
||||
#include <asiolink/udp_endpoint.h>
|
||||
#include <asiolink/udp_socket.h>
|
||||
|
||||
#include <dns/message.h>
|
||||
#include <dns/messagerenderer.h>
|
||||
#include <dns/opcode.h>
|
||||
#include <dns/rcode.h>
|
||||
#include <log/logger.h>
|
||||
|
||||
#include <asiodns/asiodef.h>
|
||||
#include <asiodns/io_fetch.h>
|
||||
|
||||
#include <util/buffer.h>
|
||||
#include <util/random/qid_gen.h>
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <asio/deadline_timer.hpp>
|
||||
|
||||
#include <asiolink/asiodef.h>
|
||||
#include <asiolink/io_address.h>
|
||||
#include <asiolink/io_asio_socket.h>
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_fetch.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/tcp_endpoint.h>
|
||||
#include <asiolink/tcp_socket.h>
|
||||
#include <asiolink/udp_endpoint.h>
|
||||
#include <asiolink/udp_socket.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace asio;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::dns;
|
||||
using namespace isc::util;
|
||||
using namespace isc::util::random;
|
||||
using namespace isc::log;
|
||||
using namespace std;
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/// Use the ASIO logger
|
||||
|
||||
@@ -88,6 +91,7 @@ struct IOFetchData {
|
||||
size_t offset; ///< Offset to receive data
|
||||
bool stopped; ///< Have we stopped running?
|
||||
int timeout; ///< Timeout in ms
|
||||
bool packet; ///< true if packet was supplied
|
||||
|
||||
// In case we need to log an error, the origin of the last asynchronous
|
||||
// I/O is recorded. To save time and simplify the code, this is recorded
|
||||
@@ -138,7 +142,6 @@ struct IOFetchData {
|
||||
question(query),
|
||||
msgbuf(new OutputBuffer(512)),
|
||||
received(buff),
|
||||
|
||||
callback(cb),
|
||||
timer(service.get_io_service()),
|
||||
protocol(proto),
|
||||
@@ -147,7 +150,8 @@ struct IOFetchData {
|
||||
offset(0),
|
||||
stopped(false),
|
||||
timeout(wait),
|
||||
origin(ASIO_UNKORIGIN),
|
||||
packet(false),
|
||||
origin(ASIODNS_UNKORIGIN),
|
||||
staging(),
|
||||
qid(QidGenerator::getInstance().generateQid())
|
||||
{}
|
||||
@@ -176,6 +180,19 @@ IOFetch::IOFetch(Protocol protocol, IOService& service,
|
||||
{
|
||||
}
|
||||
|
||||
IOFetch::IOFetch(Protocol protocol, IOService& service,
|
||||
OutputBufferPtr& outpkt, const IOAddress& address, uint16_t port,
|
||||
OutputBufferPtr& buff, Callback* cb, int wait)
|
||||
:
|
||||
data_(new IOFetchData(protocol, service,
|
||||
isc::dns::Question(isc::dns::Name("dummy.example.org"),
|
||||
isc::dns::RRClass::IN(), isc::dns::RRType::A()),
|
||||
address, port, buff, cb, wait))
|
||||
{
|
||||
data_->msgbuf = outpkt;
|
||||
data_->packet = true;
|
||||
}
|
||||
|
||||
// Return protocol in use.
|
||||
|
||||
IOFetch::Protocol
|
||||
@@ -202,6 +219,13 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
|
||||
/// This is done in a different scope to allow inline variable
|
||||
/// declarations.
|
||||
{
|
||||
if (data_->packet) {
|
||||
// A packet was given, overwrite the QID (which is in the
|
||||
// first two bytes of the packet).
|
||||
data_->msgbuf->writeUint16At(data_->qid, 0);
|
||||
|
||||
} else {
|
||||
// A question was given, construct the packet
|
||||
Message msg(Message::RENDER);
|
||||
msg.setQid(data_->qid);
|
||||
msg.setOpcode(Opcode::QUERY());
|
||||
@@ -211,6 +235,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
|
||||
MessageRenderer renderer(*data_->msgbuf);
|
||||
msg.toWire(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
// If we timeout, we stop, which will can cancel outstanding I/Os and
|
||||
// shutdown everything.
|
||||
@@ -223,7 +248,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
|
||||
|
||||
// Open a connection to the target system. For speed, if the operation
|
||||
// is synchronous (i.e. UDP operation) we bypass the yield.
|
||||
data_->origin = ASIO_OPENSOCK;
|
||||
data_->origin = ASIODNS_OPENSOCK;
|
||||
if (data_->socket->isOpenSynchronous()) {
|
||||
data_->socket->open(data_->remote_snd.get(), *this);
|
||||
} else {
|
||||
@@ -233,7 +258,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
|
||||
do {
|
||||
// Begin an asynchronous send, and then yield. When the send completes,
|
||||
// we will resume immediately after this point.
|
||||
data_->origin = ASIO_SENDSOCK;
|
||||
data_->origin = ASIODNS_SENDSOCK;
|
||||
CORO_YIELD data_->socket->asyncSend(data_->msgbuf->getData(),
|
||||
data_->msgbuf->getLength(), data_->remote_snd.get(), *this);
|
||||
|
||||
@@ -256,7 +281,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
|
||||
// received all the data before copying it back to the user's buffer.
|
||||
// And we want to minimise the amount of copying...
|
||||
|
||||
data_->origin = ASIO_RECVSOCK;
|
||||
data_->origin = ASIODNS_RECVSOCK;
|
||||
data_->cumulative = 0; // No data yet received
|
||||
data_->offset = 0; // First data into start of buffer
|
||||
data_->received->clear(); // Clear the receive buffer
|
||||
@@ -272,7 +297,7 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
|
||||
|
||||
// Finished with this socket, so close it. This will not generate an
|
||||
// I/O error, but reset the origin to unknown in case we change this.
|
||||
data_->origin = ASIO_UNKORIGIN;
|
||||
data_->origin = ASIODNS_UNKORIGIN;
|
||||
data_->socket->close();
|
||||
|
||||
/// We are done
|
||||
@@ -315,7 +340,7 @@ IOFetch::stop(Result result) {
|
||||
switch (result) {
|
||||
case TIME_OUT:
|
||||
if (logger.isDebugEnabled(1)) {
|
||||
logger.debug(20, ASIO_RECVTMO,
|
||||
logger.debug(20, ASIODNS_RECVTMO,
|
||||
data_->remote_snd->getAddress().toText().c_str(),
|
||||
static_cast<int>(data_->remote_snd->getPort()));
|
||||
}
|
||||
@@ -323,7 +348,7 @@ IOFetch::stop(Result result) {
|
||||
|
||||
case SUCCESS:
|
||||
if (logger.isDebugEnabled(50)) {
|
||||
logger.debug(30, ASIO_FETCHCOMP,
|
||||
logger.debug(30, ASIODNS_FETCHCOMP,
|
||||
data_->remote_rcv->getAddress().toText().c_str(),
|
||||
static_cast<int>(data_->remote_rcv->getPort()));
|
||||
}
|
||||
@@ -333,13 +358,13 @@ IOFetch::stop(Result result) {
|
||||
// Fetch has been stopped for some other reason. This is
|
||||
// allowed but as it is unusual it is logged, but with a lower
|
||||
// debug level than a timeout (which is totally normal).
|
||||
logger.debug(1, ASIO_FETCHSTOP,
|
||||
logger.debug(1, ASIODNS_FETCHSTOP,
|
||||
data_->remote_snd->getAddress().toText().c_str(),
|
||||
static_cast<int>(data_->remote_snd->getPort()));
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.error(ASIO_UNKRESULT, static_cast<int>(result),
|
||||
logger.error(ASIODNS_UNKRESULT, static_cast<int>(result),
|
||||
data_->remote_snd->getAddress().toText().c_str(),
|
||||
static_cast<int>(data_->remote_snd->getPort()));
|
||||
}
|
||||
@@ -363,10 +388,10 @@ IOFetch::stop(Result result) {
|
||||
void IOFetch::logIOFailure(asio::error_code ec) {
|
||||
|
||||
// Should only get here with a known error code.
|
||||
assert((data_->origin == ASIO_OPENSOCK) ||
|
||||
(data_->origin == ASIO_SENDSOCK) ||
|
||||
(data_->origin == ASIO_RECVSOCK) ||
|
||||
(data_->origin == ASIO_UNKORIGIN));
|
||||
assert((data_->origin == ASIODNS_OPENSOCK) ||
|
||||
(data_->origin == ASIODNS_SENDSOCK) ||
|
||||
(data_->origin == ASIODNS_RECVSOCK) ||
|
||||
(data_->origin == ASIODNS_UNKORIGIN));
|
||||
|
||||
static const char* PROTOCOL[2] = {"TCP", "UDP"};
|
||||
logger.error(data_->origin,
|
||||
@@ -377,5 +402,6 @@ void IOFetch::logIOFailure(asio::error_code ec) {
|
||||
static_cast<int>(data_->remote_snd->getPort()));
|
||||
}
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc {
|
||||
|
@@ -24,16 +24,17 @@
|
||||
#include <coroutine.h>
|
||||
|
||||
#include <asio/error_code.hpp>
|
||||
#include <asiolink/io_address.h>
|
||||
#include <asiolink/io_service.h>
|
||||
|
||||
#include <util/buffer.h>
|
||||
#include <dns/question.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
// Forward declarations
|
||||
class IOAddress;
|
||||
class IOFetchData;
|
||||
class IOService;
|
||||
|
||||
/// \brief Upstream Fetch Processing
|
||||
///
|
||||
@@ -116,12 +117,34 @@ public:
|
||||
///
|
||||
/// Creates the object that will handle the upstream fetch.
|
||||
///
|
||||
/// TODO: Need to randomise the source port
|
||||
///
|
||||
/// \param protocol Fetch protocol, either IOFetch::TCP or IOFetch::UDP
|
||||
/// \param service I/O Service object to handle the asynchronous
|
||||
/// operations.
|
||||
/// \param question DNS question to send to the upstream server.
|
||||
/// \param address IP address of upstream server
|
||||
/// \param port Port to which to connect on the upstream server
|
||||
/// \param buff Output buffer into which the response (in wire format)
|
||||
/// is written (if a response is received).
|
||||
/// \param cb Callback object containing the callback to be called when we
|
||||
/// terminate. The caller is responsible for managing this object
|
||||
/// and deleting it if necessary.
|
||||
/// \param wait Timeout for the fetch (in ms). The default value of
|
||||
/// -1 indicates no timeout.
|
||||
IOFetch(Protocol protocol, isc::asiolink::IOService& service,
|
||||
const isc::dns::Question& question,
|
||||
const isc::asiolink::IOAddress& address,
|
||||
uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
|
||||
int wait = -1);
|
||||
|
||||
/// \brief Constructor.
|
||||
///
|
||||
/// Creates the object that will handle the upstream fetch.
|
||||
///
|
||||
/// \param protocol Fetch protocol, either IOFetch::TCP or IOFetch::UDP
|
||||
/// \param service I/O Service object to handle the asynchronous
|
||||
/// operations.
|
||||
/// \param outpkt Packet to send to upstream server. Note that the
|
||||
/// QID (first two bytes of the packet) may be altered in the sending.
|
||||
/// \param buff Output buffer into which the response (in wire format)
|
||||
/// is written (if a response is received).
|
||||
/// \param cb Callback object containing the callback to be called
|
||||
@@ -132,8 +155,9 @@ public:
|
||||
/// (default = 53)
|
||||
/// \param wait Timeout for the fetch (in ms). The default value of
|
||||
/// -1 indicates no timeout.
|
||||
IOFetch(Protocol protocol, IOService& service,
|
||||
const isc::dns::Question& question, const IOAddress& address,
|
||||
IOFetch(Protocol protocol, isc::asiolink::IOService& service,
|
||||
isc::util::OutputBufferPtr& outpkt,
|
||||
const isc::asiolink::IOAddress& address,
|
||||
uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
|
||||
int wait = -1);
|
||||
|
||||
@@ -174,6 +198,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
|
||||
#endif // __IO_FETCH_H
|
@@ -29,7 +29,7 @@
|
||||
#include <asiolink/dummy_io_cb.h>
|
||||
#include <asiolink/tcp_endpoint.h>
|
||||
#include <asiolink/tcp_socket.h>
|
||||
#include <asiolink/tcp_server.h>
|
||||
#include <tcp_server.h>
|
||||
|
||||
|
||||
using namespace asio;
|
||||
@@ -39,8 +39,10 @@ using asio::ip::tcp;
|
||||
using namespace std;
|
||||
using namespace isc::dns;
|
||||
using namespace isc::util;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/// The following functions implement the \c TCPServer class.
|
||||
///
|
||||
@@ -238,5 +240,5 @@ TCPServer::resume(const bool done) {
|
||||
io_.post(*this);
|
||||
}
|
||||
|
||||
} // namespace asiolink
|
||||
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
@@ -24,9 +24,12 @@
|
||||
|
||||
#include <asiolink/asiolink.h>
|
||||
#include <coroutine.h>
|
||||
#include "dns_server.h"
|
||||
#include "dns_lookup.h"
|
||||
#include "dns_answer.h"
|
||||
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/// \brief A TCP-specific \c DNSServer object.
|
||||
///
|
||||
@@ -36,7 +39,7 @@ class TCPServer : public virtual DNSServer, public virtual coroutine {
|
||||
public:
|
||||
explicit TCPServer(asio::io_service& io_service,
|
||||
const asio::ip::address& addr, const uint16_t port,
|
||||
const SimpleCallback* checkin = NULL,
|
||||
const isc::asiolink::SimpleCallback* checkin = NULL,
|
||||
const DNSLookup* lookup = NULL,
|
||||
const DNSAnswer* answer = NULL);
|
||||
|
||||
@@ -95,7 +98,7 @@ private:
|
||||
|
||||
// \c IOMessage and \c Message objects to be passed to the
|
||||
// DNS lookup and answer providers
|
||||
boost::shared_ptr<asiolink::IOMessage> io_message_;
|
||||
boost::shared_ptr<isc::asiolink::IOMessage> io_message_;
|
||||
isc::dns::MessagePtr query_message_;
|
||||
isc::dns::MessagePtr answer_message_;
|
||||
|
||||
@@ -108,13 +111,14 @@ private:
|
||||
bool done_;
|
||||
|
||||
// Callback functions provided by the caller
|
||||
const SimpleCallback* checkin_callback_;
|
||||
const isc::asiolink::SimpleCallback* checkin_callback_;
|
||||
const DNSLookup* lookup_callback_;
|
||||
const DNSAnswer* answer_callback_;
|
||||
|
||||
boost::shared_ptr<IOEndpoint> peer_;
|
||||
boost::shared_ptr<IOSocket> iosock_;
|
||||
boost::shared_ptr<isc::asiolink::IOEndpoint> peer_;
|
||||
boost::shared_ptr<isc::asiolink::IOSocket> iosock_;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
#endif // __TCP_SERVER_H
|
50
src/lib/asiodns/tests/Makefile.am
Normal file
50
src/lib/asiodns/tests/Makefile.am
Normal file
@@ -0,0 +1,50 @@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
|
||||
AM_CPPFLAGS += $(BOOST_INCLUDES)
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/bin
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc -I$(top_builddir)/src/lib/util
|
||||
AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(srcdir)/testdata\"
|
||||
|
||||
AM_CXXFLAGS = $(B10_CXXFLAGS)
|
||||
|
||||
if USE_STATIC_LINK
|
||||
AM_LDFLAGS = -static
|
||||
endif
|
||||
|
||||
CLEANFILES = *.gcno *.gcda
|
||||
|
||||
TESTS =
|
||||
if HAVE_GTEST
|
||||
TESTS += run_unittests
|
||||
run_unittests_SOURCES = run_unittests.cc
|
||||
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
|
||||
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
|
||||
run_unittests_SOURCES += io_service_unittest.cc
|
||||
run_unittests_SOURCES += dns_server_unittest.cc
|
||||
run_unittests_SOURCES += io_fetch_unittest.cc
|
||||
|
||||
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
||||
|
||||
run_unittests_LDADD = $(GTEST_LDADD)
|
||||
run_unittests_LDADD += $(SQLITE_LIBS)
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
|
||||
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
|
||||
|
||||
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
|
||||
|
||||
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
|
||||
# B10_CXXFLAGS)
|
||||
run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
if USE_GXX
|
||||
run_unittests_CXXFLAGS += -Wno-unused-parameter
|
||||
endif
|
||||
if USE_CLANGPP
|
||||
# Same for clang++, but we need to turn off -Werror completely.
|
||||
run_unittests_CXXFLAGS += -Wno-error
|
||||
endif
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
@@ -18,10 +18,10 @@
|
||||
#include <asio.hpp>
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_error.h>
|
||||
#include <asiolink/udp_server.h>
|
||||
#include <asiolink/tcp_server.h>
|
||||
#include <asiolink/dns_answer.h>
|
||||
#include <asiolink/dns_lookup.h>
|
||||
#include <asiodns/udp_server.h>
|
||||
#include <asiodns/tcp_server.h>
|
||||
#include <asiodns/dns_answer.h>
|
||||
#include <asiodns/dns_lookup.h>
|
||||
#include <string>
|
||||
#include <csignal>
|
||||
#include <unistd.h> //for alarm
|
||||
@@ -65,7 +65,8 @@
|
||||
/// involved so the message sending between client and server is plain text
|
||||
/// And the valid checker, question lookup and answer composition are dummy.
|
||||
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::asiodns;
|
||||
using namespace asio;
|
||||
|
||||
namespace {
|
@@ -38,16 +38,18 @@
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_fetch.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiodns/io_fetch.h>
|
||||
|
||||
using namespace asio;
|
||||
using namespace isc::dns;
|
||||
using namespace isc::util;
|
||||
using namespace asio::ip;
|
||||
using namespace std;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
const asio::ip::address TEST_HOST(asio::ip::address::from_string("127.0.0.1"));
|
||||
const uint16_t TEST_PORT(5301);
|
||||
@@ -722,4 +724,5 @@ TEST_F(IOFetchTest, TcpSendReceive8192ShortSend) {
|
||||
}
|
||||
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
@@ -17,8 +17,10 @@
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <asiolink/asiolink.h>
|
||||
#include <asiodns/asiodns.h>
|
||||
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::asiodns;
|
||||
|
||||
const char* const TEST_SERVER_PORT = "53535";
|
||||
const char* const TEST_CLIENT_PORT = "53536";
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
|
||||
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -12,21 +12,17 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/exception_translator.hpp>
|
||||
#include <boost/python/return_internal_reference.hpp>
|
||||
#include <boost/python/copy_const_reference.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <xfr/fd_share.h>
|
||||
#include <log/root_logger_name.h>
|
||||
#include <dns/tests/unittest_util.h>
|
||||
|
||||
using namespace isc::xfr;
|
||||
using namespace boost::python;
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv); // Initialize Google test
|
||||
isc::log::setRootLoggerName("unittest"); // Set a root logger name
|
||||
isc::UnitTestUtil::addDataPath(TEST_DATA_DIR); // Add location of test data
|
||||
|
||||
BOOST_PYTHON_MODULE(bind10_xfr) {
|
||||
def("recv_fd", &recv_fd);
|
||||
def("send_fd", &send_fd);
|
||||
return (RUN_ALL_TESTS());
|
||||
}
|
@@ -27,8 +27,8 @@
|
||||
#include <asio/error.hpp>
|
||||
#include <asiolink/dummy_io_cb.h>
|
||||
#include <asiolink/udp_endpoint.h>
|
||||
#include <asiolink/udp_server.h>
|
||||
#include <asiolink/udp_socket.h>
|
||||
#include "udp_server.h"
|
||||
|
||||
#include <dns/opcode.h>
|
||||
|
||||
@@ -39,8 +39,10 @@ using isc::log::dlog;
|
||||
using namespace std;
|
||||
using namespace isc::dns;
|
||||
using namespace isc::util;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
/*
|
||||
* Some of the member variables here are shared_ptrs and some are
|
||||
@@ -319,4 +321,5 @@ UDPServer::hasAnswer() {
|
||||
return (data_->done_);
|
||||
}
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
@@ -19,14 +19,15 @@
|
||||
#error "asio.hpp must be included before including this, see asiolink.h as to why"
|
||||
#endif
|
||||
|
||||
#include <asiolink/dns_server.h>
|
||||
#include <asiolink/simple_callback.h>
|
||||
#include <asiolink/dns_lookup.h>
|
||||
#include <asiolink/dns_answer.h>
|
||||
#include <asiodns/dns_answer.h>
|
||||
#include <asiodns/dns_lookup.h>
|
||||
#include <asiodns/dns_server.h>
|
||||
|
||||
#include <coroutine.h>
|
||||
|
||||
namespace asiolink {
|
||||
namespace isc {
|
||||
namespace asiodns {
|
||||
|
||||
//
|
||||
// Asynchronous UDP server coroutine
|
||||
@@ -47,7 +48,7 @@ public:
|
||||
/// \param answer the callbackprovider for DNS answer events
|
||||
explicit UDPServer(asio::io_service& io_service,
|
||||
const asio::ip::address& addr, const uint16_t port,
|
||||
SimpleCallback* checkin = NULL,
|
||||
isc::asiolink::SimpleCallback* checkin = NULL,
|
||||
DNSLookup* lookup = NULL,
|
||||
DNSAnswer* answer = NULL);
|
||||
|
||||
@@ -102,5 +103,6 @@ private:
|
||||
boost::shared_ptr<Data> data_;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace asiodns
|
||||
} // namespace isc
|
||||
#endif // __UDP_SERVER_H
|
@@ -13,31 +13,21 @@ CLEANFILES = *.gcno *.gcda
|
||||
# which would make the build fail with -Werror (our default setting).
|
||||
lib_LTLIBRARIES = libasiolink.la
|
||||
libasiolink_la_SOURCES = asiolink.h
|
||||
libasiolink_la_SOURCES += asiodef.cc asiodef.h
|
||||
libasiolink_la_SOURCES += dns_answer.h
|
||||
libasiolink_la_SOURCES += dns_lookup.h
|
||||
libasiolink_la_SOURCES += dns_server.h
|
||||
libasiolink_la_SOURCES += dns_service.cc dns_service.h
|
||||
libasiolink_la_SOURCES += dummy_io_cb.h
|
||||
libasiolink_la_SOURCES += interval_timer.cc interval_timer.h
|
||||
libasiolink_la_SOURCES += io_address.cc io_address.h
|
||||
libasiolink_la_SOURCES += io_asio_socket.h
|
||||
libasiolink_la_SOURCES += io_endpoint.cc io_endpoint.h
|
||||
libasiolink_la_SOURCES += io_error.h
|
||||
libasiolink_la_SOURCES += io_fetch.cc io_fetch.h
|
||||
libasiolink_la_SOURCES += io_message.h
|
||||
libasiolink_la_SOURCES += io_service.h io_service.cc
|
||||
libasiolink_la_SOURCES += io_socket.h io_socket.cc
|
||||
libasiolink_la_SOURCES += simple_callback.h
|
||||
libasiolink_la_SOURCES += tcp_endpoint.h
|
||||
libasiolink_la_SOURCES += tcp_server.cc tcp_server.h
|
||||
libasiolink_la_SOURCES += tcp_socket.h
|
||||
libasiolink_la_SOURCES += udp_endpoint.h
|
||||
libasiolink_la_SOURCES += udp_server.cc udp_server.h
|
||||
libasiolink_la_SOURCES += udp_socket.h
|
||||
|
||||
EXTRA_DIST = asiodef.msg
|
||||
|
||||
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
|
||||
# B10_CXXFLAGS)
|
||||
libasiolink_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
|
@@ -16,167 +16,7 @@ including:
|
||||
them in only one place allows us to relax strictness here, while
|
||||
leaving it in place elsewhere.
|
||||
|
||||
Currently, the asiolink library only supports DNS servers (i.e., b10-auth
|
||||
and b10-resolver). The plan is to make it more generic and allow it to
|
||||
support other modules as well.
|
||||
|
||||
Some of the classes defined here--for example, IOSocket, IOEndpoint,
|
||||
and IOAddress--are to be used by BIND 10 modules as wrappers around
|
||||
ASIO-specific classes.
|
||||
|
||||
Other classes implement the DNS protocol on behalf of BIND 10 modules.
|
||||
|
||||
These DNS server and client routines are written using the "stackless
|
||||
coroutine" pattern invented by Chris Kohlhoff and described at
|
||||
http://blog.think-async.com/2010/03/potted-guide-to-stackless-coroutines.html.
|
||||
This is intended to simplify development a bit, since it allows the
|
||||
routines to be written in a straightfowrard step-step-step fashion rather
|
||||
than as a complex chain of separate handler functions.
|
||||
|
||||
Coroutine objects (i.e., UDPServer, TCPServer and IOFetch) are objects
|
||||
with reenterable operator() members. When an instance of one of these
|
||||
classes is called as a function, it resumes at the position where it left
|
||||
off. Thus, a UDPServer can issue an asynchronous I/O call and specify
|
||||
itself as the handler object; when the call completes, the UDPServer
|
||||
carries on at the same position. As a result, the code can look as
|
||||
if it were using synchronous, not asynchronous, I/O, providing some of
|
||||
the benefit of threading but with minimal switching overhead.
|
||||
|
||||
So, in simplified form, the behavior of a DNS Server is:
|
||||
|
||||
REENTER:
|
||||
while true:
|
||||
YIELD packet = read_packet
|
||||
FORK
|
||||
if not parent:
|
||||
break
|
||||
|
||||
# This callback informs the caller that a packet has arrived, and
|
||||
# gives it a chance to update configuration, etc
|
||||
SimpleCallback(packet)
|
||||
YIELD answer = DNSLookup(packet, this)
|
||||
response = DNSAnswer(answer)
|
||||
YIELD send(response)
|
||||
|
||||
At each "YIELD" point, the coroutine initiates an asynchronous operation,
|
||||
then pauses and turns over control to some other task on the ASIO service
|
||||
queue. When the operation completes, the coroutine resumes.
|
||||
|
||||
DNSLookup, DNSAnswer and SimpleCallback define callback methods
|
||||
used by a DNS Server to communicate with the module that called it.
|
||||
They are abstract-only classes whose concrete implementations
|
||||
are supplied by the calling module.
|
||||
|
||||
The DNSLookup callback always runs asynchronously. Concrete
|
||||
implementations must be sure to call the server's "resume" method when
|
||||
it is finished.
|
||||
|
||||
In an authoritative server, the DNSLookup implementation would examine
|
||||
the query, look up the answer, then call "resume". (See the diagram
|
||||
in doc/auth_process.jpg.)
|
||||
|
||||
In a recursive server, the DNSLookup impelemtation would initiate a
|
||||
DNSQuery, which in turn would be responsible for calling the server's
|
||||
"resume" method. (See the diagram in doc/recursive_process.jpg.)
|
||||
|
||||
A DNSQuery object is intended to handle resolution of a query over
|
||||
the network when the local authoritative data sources or cache are not
|
||||
sufficient. The plan is that it will make use of subsidiary DNSFetch
|
||||
calls to get data from particular authoritative servers, and when it has
|
||||
gotten a complete answer, it calls "resume".
|
||||
|
||||
In current form, however, DNSQuery is much simpler; it forwards queries
|
||||
to a single upstream resolver and passes the answers back to the client.
|
||||
It is constructed with the address of the forward server. Queries are
|
||||
initiated with the question to ask the forward server, a buffer into
|
||||
which to write the answer, and a pointer to the coroutine to be resumed
|
||||
when the answer has arrived. In simplified form, the DNSQuery routine is:
|
||||
|
||||
REENTER:
|
||||
render the question into a wire-format query packet
|
||||
YIELD send(query)
|
||||
YIELD response = read_packet
|
||||
server->resume
|
||||
|
||||
Currently, DNSQuery is only implemented for UDP queries. In future work
|
||||
it will be necessary to write code to fall back to TCP when circumstances
|
||||
require it.
|
||||
|
||||
|
||||
Upstream Fetches
|
||||
================
|
||||
Upstream fetches (queries by the resolver on behalf of a client) are made
|
||||
using a slightly-modified version of the pattern described above.
|
||||
|
||||
Sockets
|
||||
-------
|
||||
First, it will be useful to understand the class hierarchy used in the
|
||||
fetch logic:
|
||||
|
||||
IOSocket
|
||||
|
|
||||
IOAsioSocket
|
||||
|
|
||||
+-----+-----+
|
||||
| |
|
||||
UDPSocket TCPSocket
|
||||
|
||||
IOSocket is a wrapper class for a socket and is used by the authoritative
|
||||
server code. It is an abstract base class, providing little more that the ability to hold the socket and to return the protocol in use.
|
||||
|
||||
Built on this is IOAsioSocket, which adds the open, close, asyncSend and
|
||||
asyncReceive methods. This is a template class, which takes as template
|
||||
argument the class of the object that will be used as the callback when the
|
||||
asynchronous operation completes. This object can be of any type, but must
|
||||
include an operator() method with the signature:
|
||||
|
||||
operator()(asio::error_code ec, size_t length)
|
||||
|
||||
... the two arguments being the status of the completed I/O operation and
|
||||
the number of bytes transferred. (In the case of the open method, the second
|
||||
argument will be zero.)
|
||||
|
||||
Finally, the TCPSocket and UDPSocket classes provide the body of the
|
||||
asynchronous operations.
|
||||
|
||||
Fetch Sequence
|
||||
--------------
|
||||
The fetch is implemented by the IOFetch class, which takes as argument the
|
||||
protocol to use. The sequence is:
|
||||
|
||||
REENTER:
|
||||
render the question into a wire-format query packet
|
||||
open() // Open socket and optionally connect
|
||||
if (! synchronous) {
|
||||
YIELD;
|
||||
}
|
||||
YIELD asyncSend(query) // Send query
|
||||
do {
|
||||
YIELD asyncReceive(response) // Read response
|
||||
} while (! complete(response))
|
||||
close() // Drop connection and close socket
|
||||
server->resume
|
||||
|
||||
The open() method opens a socket for use. On TCP, it also makes a
|
||||
connection to the remote end. So under UDP the operation will complete
|
||||
immediately, but under TCP it could take a long time. One solution would be
|
||||
for the open operation to post an event to the I/O queue; then both cases
|
||||
could be regarded as being equivalent, with the completion being signalled
|
||||
by the posting of the completion event. However UDP is the most common case
|
||||
and that would involve extra overhead. So the open() returns a status
|
||||
indicating whether the operation completed asynchronously. If it did, the
|
||||
code yields back to the coroutine; if not the yield is bypassed.
|
||||
|
||||
The asynchronous send is straightforward, invoking the underlying ASIO
|
||||
function. (Note that the address/port is supplied to both the open() and
|
||||
asyncSend() methods - it is used by the TCPSocket in open() and by the
|
||||
UDPSocket in asyncSend().)
|
||||
|
||||
The asyncReceive() method issues an asynchronous read and waits for completion.
|
||||
The fetch object keeps track of the amount of data received so far and when
|
||||
the receive completes it calls a method on the socket to determine if the
|
||||
entire message has been received. (This will always be the case for UDP. On
|
||||
TCP though, the message is preceded by a count field as several reads may be
|
||||
required to read all the data.) The fetch loops until all the data is read.
|
||||
|
||||
Finally, the socket is closed and the server called to resume operation.
|
||||
|
@@ -1,21 +0,0 @@
|
||||
// File created from asiodef.msg on Mon Feb 28 17:15:30 2011
|
||||
|
||||
#ifndef __ASIODEF_H
|
||||
#define __ASIODEF_H
|
||||
|
||||
#include <log/message_types.h>
|
||||
|
||||
namespace asiolink {
|
||||
|
||||
extern const isc::log::MessageID ASIO_FETCHCOMP;
|
||||
extern const isc::log::MessageID ASIO_FETCHSTOP;
|
||||
extern const isc::log::MessageID ASIO_OPENSOCK;
|
||||
extern const isc::log::MessageID ASIO_RECVSOCK;
|
||||
extern const isc::log::MessageID ASIO_RECVTMO;
|
||||
extern const isc::log::MessageID ASIO_SENDSOCK;
|
||||
extern const isc::log::MessageID ASIO_UNKORIGIN;
|
||||
extern const isc::log::MessageID ASIO_UNKRESULT;
|
||||
|
||||
} // namespace asiolink
|
||||
|
||||
#endif // __ASIODEF_H
|
@@ -20,10 +20,6 @@
|
||||
// See the description of the namespace below.
|
||||
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/dns_service.h>
|
||||
#include <asiolink/dns_server.h>
|
||||
#include <asiolink/dns_lookup.h>
|
||||
#include <asiolink/dns_answer.h>
|
||||
#include <asiolink/simple_callback.h>
|
||||
#include <asiolink/interval_timer.h>
|
||||
|
||||
@@ -62,11 +58,6 @@
|
||||
/// this module. The resulting interfaces are thus straightforward mapping
|
||||
/// to the ASIO counterparts.
|
||||
///
|
||||
/// Notes to developers:
|
||||
/// Currently the wrapper interface is fairly specific to use by a
|
||||
/// DNS server, i.e., b10-auth or b10-resolver. But the plan is to
|
||||
/// generalize it and have other modules use it as well.
|
||||
///
|
||||
/// 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
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <asio/error.hpp>
|
||||
#include <asio/error_code.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief Asynchronous I/O Completion Callback
|
||||
@@ -55,5 +56,6 @@ public:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
#endif // __DUMMY_IO_CB_H
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <asiolink/interval_timer.h>
|
||||
#include <asiolink/io_service.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
class IntervalTimerImpl {
|
||||
@@ -133,4 +134,5 @@ IntervalTimer::getInterval() const {
|
||||
return (impl_->getInterval());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <asiolink/io_service.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
struct IntervalTimerImpl;
|
||||
@@ -130,4 +131,5 @@ private:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_INTERVAL_TIMER_H
|
||||
|
@@ -31,6 +31,7 @@ using asio::ip::tcp;
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
// XXX: we cannot simply construct the address in the initialization list,
|
||||
@@ -62,4 +63,5 @@ IOAddress::getFamily() const {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c IOAddress class represents an IP addresses (version
|
||||
@@ -119,5 +120,6 @@ private:
|
||||
asio::ip::address asio_address_;
|
||||
};
|
||||
|
||||
} // asiolink
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __IO_ADDRESS_H
|
||||
|
@@ -31,7 +31,7 @@
|
||||
#include <asiolink/io_error.h>
|
||||
#include <asiolink/io_socket.h>
|
||||
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief Socket not open
|
||||
@@ -395,5 +395,6 @@ private:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
#endif // __IO_ASIO_SOCKET_H
|
||||
|
@@ -28,6 +28,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
const IOEndpoint*
|
||||
@@ -57,4 +58,5 @@ IOEndpoint::operator!=(const IOEndpoint& other) const {
|
||||
return (!operator==(other));
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <asiolink/io_address.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c IOEndpoint class is an abstract base class to represent
|
||||
@@ -117,5 +118,6 @@ public:
|
||||
const unsigned short port);
|
||||
};
|
||||
|
||||
} // asiolink
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __IO_ENDPOINT_H
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief An exception that is thrown if an error occurs within the IO
|
||||
@@ -30,6 +31,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
} // asiolink
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
#endif // __IO_ERROR_H
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_socket.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c IOMessage class encapsulates an incoming message received
|
||||
@@ -96,5 +97,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
} // asiolink
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __IO_MESSAGE_H
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <asio.hpp>
|
||||
#include <asiolink/io_service.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
class IOServiceImpl {
|
||||
@@ -95,4 +96,5 @@ IOService::get_io_service() {
|
||||
return (io_impl_->get_io_service());
|
||||
}
|
||||
|
||||
} // namepsace asiolink
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
@@ -19,6 +19,7 @@ namespace asio {
|
||||
class io_service;
|
||||
}
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
struct IOServiceImpl;
|
||||
@@ -74,4 +75,5 @@ private:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_IO_SERVICE_H
|
||||
|
@@ -16,8 +16,7 @@
|
||||
|
||||
#include <asio.hpp>
|
||||
|
||||
using namespace asio;
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c DummySocket class is a concrete derived class of
|
||||
@@ -62,4 +61,5 @@ IOSocket::getDummyTCPSocket() {
|
||||
return (socket);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c IOSocket class is an abstract base class to represent
|
||||
@@ -120,5 +121,6 @@ public:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
#endif // __IO_SOCKET_H
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <asiolink/io_message.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c SimpleCallback class is an abstract base class for a
|
||||
@@ -68,4 +69,5 @@ private:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __ASIOLINK_SIMPLE_CALLBACK_H
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <asiolink/io_endpoint.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief The \c TCPEndpoint class is a concrete derived class of
|
||||
@@ -110,4 +111,5 @@ private:
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
#endif // __TCP_ENDPOINT_H
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/tcp_endpoint.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// \brief Buffer Too Large
|
||||
@@ -412,5 +413,6 @@ TCPSocket<C>::close() {
|
||||
}
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
#endif // __TCP_SOCKET_H
|
||||
|
@@ -21,15 +21,12 @@ run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
|
||||
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
|
||||
run_unittests_SOURCES += io_address_unittest.cc
|
||||
run_unittests_SOURCES += io_endpoint_unittest.cc
|
||||
run_unittests_SOURCES += io_fetch_unittest.cc
|
||||
run_unittests_SOURCES += io_socket_unittest.cc
|
||||
run_unittests_SOURCES += io_service_unittest.cc
|
||||
run_unittests_SOURCES += interval_timer_unittest.cc
|
||||
run_unittests_SOURCES += tcp_endpoint_unittest.cc
|
||||
run_unittests_SOURCES += tcp_socket_unittest.cc
|
||||
run_unittests_SOURCES += udp_endpoint_unittest.cc
|
||||
run_unittests_SOURCES += udp_socket_unittest.cc
|
||||
run_unittests_SOURCES += dns_server_unittest.cc
|
||||
|
||||
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
||||
|
||||
|
@@ -26,7 +26,7 @@ const boost::posix_time::time_duration TIMER_MARGIN_MSEC =
|
||||
boost::posix_time::milliseconds(50);
|
||||
}
|
||||
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
// This fixture is for testing IntervalTimer. Some callback functors are
|
||||
// registered as callback function of the timer to test if they are called
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include <asiolink/io_error.h>
|
||||
#include <asiolink/io_address.h>
|
||||
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
TEST(IOAddressTest, fromText) {
|
||||
IOAddress io_address_v4("192.0.2.1");
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_error.h>
|
||||
|
||||
using namespace asiolink;
|
||||
using namespace isc::asiolink;
|
||||
|
||||
TEST(IOEndpointTest, createUDPv4) {
|
||||
const IOEndpoint* ep;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user