BIND 10 master, updated. 923c859c0ff6fcfc3d0c268cd20d493b71e66d29 [master] Merge branch 'trac1820'
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Apr 4 21:53:23 UTC 2012
The branch, master has been updated
via 923c859c0ff6fcfc3d0c268cd20d493b71e66d29 (commit)
via 350e65820efee213ef09122b88cdfdb7f4ab38b0 (commit)
via 9e77d650e31a106518ad263092f6a7e2a69d22a1 (commit)
via 1eb1ca43bb8682d49c2396395919d8445a28c012 (commit)
via a3f1538ebc5aa4b0a6ee49fee142646ff3bfee2c (commit)
from 7f720276658e694a1edbb8ce105b04a8dcf1d36c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 923c859c0ff6fcfc3d0c268cd20d493b71e66d29
Merge: 7f72027 350e658
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Wed Apr 4 14:43:57 2012 -0700
[master] Merge branch 'trac1820'
-----------------------------------------------------------------------
Summary of changes:
src/lib/asiodns/dns_service.cc | 160 ++------------
src/lib/asiodns/dns_service.h | 34 +---
src/lib/asiodns/sync_udp_server.cc | 23 --
src/lib/asiodns/sync_udp_server.h | 13 -
src/lib/asiodns/tcp_server.cc | 22 --
src/lib/asiodns/tcp_server.h | 6 -
src/lib/asiodns/tests/dns_server_unittest.cc | 48 ++---
src/lib/asiodns/tests/dns_service_unittest.cc | 91 --------
src/lib/asiodns/udp_server.cc | 6 -
src/lib/asiodns/udp_server.h | 13 -
src/lib/resolve/tests/recursive_query_unittest.cc | 247 +++++++++++++--------
11 files changed, 189 insertions(+), 474 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/asiodns/dns_service.cc b/src/lib/asiodns/dns_service.cc
index ee7cf74..2cfdea5 100644
--- a/src/lib/asiodns/dns_service.cc
+++ b/src/lib/asiodns/dns_service.cc
@@ -14,30 +14,19 @@
#include <config.h>
-#include <unistd.h> // for some IPC/network system calls
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include <boost/lexical_cast.hpp>
-
-#include <log/dummylog.h>
-
#include <exceptions/exceptions.h>
-#include <asio.hpp>
#include <dns_service.h>
+
#include <asiolink/io_service.h>
+
+#include <asio.hpp> // xxx_server.h requires this to be included first
#include <tcp_server.h>
#include <udp_server.h>
#include <sync_udp_server.h>
-#include <log/dummylog.h>
-
-#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
-using isc::log::dlog;
-
using namespace isc::asiolink;
namespace isc {
@@ -46,29 +35,13 @@ namespace asiodns {
class DNSLookup;
class DNSAnswer;
-namespace {
-
-asio::ip::address
-convertAddr(const std::string& address) {
- asio::error_code err;
- asio::ip::address addr = asio::ip::address::from_string(address, err);
- if (err) {
- isc_throw(IOError, "Invalid IP address '" << &address << "': "
- << err.message());
- }
- return (addr);
-}
-
-}
-
-
class DNSServiceImpl {
public:
- DNSServiceImpl(IOService& io_service, const char& port,
- const asio::ip::address* v4addr,
- const asio::ip::address* v6addr,
- SimpleCallback* checkin, DNSLookup* lookup,
- DNSAnswer* answe);
+ DNSServiceImpl(IOService& io_service, SimpleCallback* checkin,
+ DNSLookup* lookup, DNSAnswer* answer) :
+ io_service_(io_service), checkin_(checkin), lookup_(lookup),
+ answer_(answer)
+ {}
IOService& io_service_;
@@ -77,9 +50,9 @@ public:
typedef boost::shared_ptr<TCPServer> TCPServerPtr;
typedef boost::shared_ptr<DNSServer> DNSServerPtr;
std::vector<DNSServerPtr> servers_;
- SimpleCallback *checkin_;
- DNSLookup *lookup_;
- DNSAnswer *answer_;
+ SimpleCallback* checkin_;
+ DNSLookup* lookup_;
+ DNSAnswer* answer_;
template<class Ptr, class Server> void addServerFromFD(int fd, int af) {
Ptr server(new Server(io_service_.get_io_service(), fd, af, checkin_,
@@ -87,107 +60,12 @@ public:
(*server)();
servers_.push_back(server);
}
-
- void addServer(uint16_t port, const asio::ip::address& address) {
- try {
- dlog(std::string("Initialize TCP server at ") +
- address.to_string() + ":" +
- boost::lexical_cast<std::string>(port));
- TCPServerPtr tcpServer(new TCPServer(io_service_.get_io_service(),
- address, port, checkin_,
- lookup_, answer_));
- (*tcpServer)();
- servers_.push_back(tcpServer);
- dlog(std::string("Initialize UDP server at ") +
- address.to_string() + ":" +
- boost::lexical_cast<std::string>(port));
- UDPServerPtr udpServer(new UDPServer(io_service_.get_io_service(),
- address, port, checkin_, lookup_, answer_));
- (*udpServer)();
- servers_.push_back(udpServer);
- } catch (const asio::system_error& err) {
- // We need to catch and convert any ASIO level exceptions.
- // This can happen for unavailable address, binding a privilege port
- // without the privilege, etc.
- isc_throw(IOError, "Failed to initialize network servers: " <<
- err.what());
- }
- }
- void addServer(const char& port, const asio::ip::address& address) {
- uint16_t portnum;
- try {
- // XXX: SunStudio with stlport4 doesn't reject some invalid
- // representation such as "-1" by lexical_cast<uint16_t>, so
- // we convert it into a signed integer of a larger size and perform
- // range check ourselves.
- const int32_t portnum32 = boost::lexical_cast<int32_t>(&port);
- if (portnum32 < 0 || portnum32 > 65535) {
- isc_throw(IOError, "Invalid port number '" << &port);
- }
- portnum = portnum32;
- } catch (const boost::bad_lexical_cast& ex) {
- isc_throw(IOError, "Invalid port number '" << &port << "': " <<
- ex.what());
- }
- addServer(portnum, address);
- }
};
-DNSServiceImpl::DNSServiceImpl(IOService& io_service,
- const char& port,
- const asio::ip::address* const v4addr,
- const asio::ip::address* const v6addr,
- SimpleCallback* checkin,
- DNSLookup* lookup,
- DNSAnswer* answer) :
- io_service_(io_service),
- checkin_(checkin),
- lookup_(lookup),
- answer_(answer)
-{
-
- if (v4addr) {
- addServer(port, *v4addr);
- }
- if (v6addr) {
- addServer(port, *v6addr);
- }
-}
-
-DNSService::DNSService(IOService& io_service,
- const char& port, const char& address,
- SimpleCallback* checkin,
- DNSLookup* lookup,
- DNSAnswer* answer) :
- impl_(new DNSServiceImpl(io_service, port, NULL, NULL, checkin, lookup,
- answer)),
- io_service_(io_service)
-{
- addServer(port, &address);
-}
-
-DNSService::DNSService(IOService& io_service,
- const char& port,
- const bool use_ipv4, const bool use_ipv6,
- SimpleCallback* checkin,
- DNSLookup* lookup,
- DNSAnswer* answer) :
- impl_(NULL), io_service_(io_service)
-{
- const asio::ip::address v4addr_any =
- asio::ip::address(asio::ip::address_v4::any());
- const asio::ip::address* const v4addrp = use_ipv4 ? &v4addr_any : NULL;
- const asio::ip::address v6addr_any =
- asio::ip::address(asio::ip::address_v6::any());
- const asio::ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
- impl_ = new DNSServiceImpl(io_service, port, v4addrp, v6addrp, checkin,
- lookup, answer);
-}
-
DNSService::DNSService(IOService& io_service, SimpleCallback* checkin,
- DNSLookup* lookup, DNSAnswer *answer) :
- impl_(new DNSServiceImpl(io_service, *"0", NULL, NULL, checkin, lookup,
- answer)), io_service_(io_service)
+ DNSLookup* lookup, DNSAnswer *answer) :
+ impl_(new DNSServiceImpl(io_service, checkin, lookup, answer)),
+ io_service_(io_service)
{
}
@@ -195,16 +73,6 @@ DNSService::~DNSService() {
delete impl_;
}
-void
-DNSService::addServer(const char& port, const std::string& address) {
- impl_->addServer(port, convertAddr(address));
-}
-
-void
-DNSService::addServer(uint16_t port, const std::string& address) {
- impl_->addServer(port, convertAddr(address));
-}
-
void DNSService::addServerTCPFromFD(int fd, int af) {
impl_->addServerFromFD<DNSServiceImpl::TCPServerPtr, TCPServer>(fd, af);
}
diff --git a/src/lib/asiodns/dns_service.h b/src/lib/asiodns/dns_service.h
index 161658f..8f2f6d7 100644
--- a/src/lib/asiodns/dns_service.h
+++ b/src/lib/asiodns/dns_service.h
@@ -112,40 +112,14 @@ private:
static const unsigned int SERVER_DEFINED_FLAGS = 1;
public:
- /// \brief The constructor with a specific IP address and port on which
- /// the services listen on.
- ///
- /// \param io_service The IOService to work with
- /// \param port the port to listen on
- /// \param address the IP address to listen on
- /// \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(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.
+ /// \brief The constructor without any servers.
///
- /// It effectively listens on "any" IPv4 and/or IPv6 addresses.
- /// IPv4/IPv6 services will be available if and only if \c use_ipv4
- /// or \c use_ipv6 is \c true, respectively.
+ /// Use addServerTCPFromFD() or addServerUDPFromFD() to add some servers.
///
/// \param io_service The IOService to work with
- /// \param port the port to listen on
- /// \param use_ipv4 If true, listen on ipv4 'any'
- /// \param use_ipv6 If true, listen on ipv6 'any'
/// \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(asiolink::IOService& io_service, const char& port,
- const bool use_ipv4, const bool use_ipv6,
- isc::asiolink::SimpleCallback* checkin, DNSLookup* lookup,
- DNSAnswer* answer);
- /// \brief The constructor without any servers.
- ///
- /// Use addServer() to add some servers.
DNSService(asiolink::IOService& io_service,
isc::asiolink::SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer* answer);
@@ -154,10 +128,6 @@ public:
virtual ~DNSService();
//@}
- /// \brief Add another server to the service
- void addServer(uint16_t port, const std::string &address);
- void addServer(const char& port, const std::string& address);
-
/// \brief Add another TCP server/listener to the service from already
/// opened file descriptor
///
diff --git a/src/lib/asiodns/sync_udp_server.cc b/src/lib/asiodns/sync_udp_server.cc
index fb53fba..a31301d 100644
--- a/src/lib/asiodns/sync_udp_server.cc
+++ b/src/lib/asiodns/sync_udp_server.cc
@@ -38,29 +38,6 @@ using namespace isc::asiolink;
namespace isc {
namespace asiodns {
-SyncUDPServer::SyncUDPServer(asio::io_service& io_service,
- const asio::ip::address& addr,
- const uint16_t port,
- asiolink::SimpleCallback* checkin,
- DNSLookup* lookup, DNSAnswer* answer) :
- output_buffer_(new isc::util::OutputBuffer(0)),
- query_(new isc::dns::Message(isc::dns::Message::PARSE)),
- answer_(new isc::dns::Message(isc::dns::Message::RENDER)),
- io_(io_service), checkin_callback_(checkin), lookup_callback_(lookup),
- answer_callback_(answer), stopped_(false)
-{
- // We must use different instantiations for v4 and v6;
- // otherwise ASIO will bind to both
- asio::ip::udp proto = addr.is_v4() ? asio::ip::udp::v4() :
- asio::ip::udp::v6();
- socket_.reset(new asio::ip::udp::socket(io_service, proto));
- socket_->set_option(asio::socket_base::reuse_address(true));
- if (addr.is_v6()) {
- socket_->set_option(asio::ip::v6_only(true));
- }
- socket_->bind(asio::ip::udp::endpoint(addr, port));
-}
-
SyncUDPServer::SyncUDPServer(asio::io_service& io_service, const int fd,
const int af, asiolink::SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer* answer) :
diff --git a/src/lib/asiodns/sync_udp_server.h b/src/lib/asiodns/sync_udp_server.h
index f21d3e5..9718422 100644
--- a/src/lib/asiodns/sync_udp_server.h
+++ b/src/lib/asiodns/sync_udp_server.h
@@ -44,19 +44,6 @@ class SyncUDPServer : public DNSServer, public boost::noncopyable {
public:
/// \brief Constructor
/// \param io_service the asio::io_service to work with
- /// \param addr the IP address to listen for queries on
- /// \param port the port to listen for queries on
- /// \param checkin the callbackprovider for non-DNS events
- /// \param lookup the callbackprovider for DNS lookup events
- /// \param answer the callbackprovider for DNS answer events
- explicit SyncUDPServer(asio::io_service& io_service,
- const asio::ip::address& addr, const uint16_t port,
- isc::asiolink::SimpleCallback* checkin = NULL,
- DNSLookup* lookup = NULL,
- DNSAnswer* answer = NULL);
-
- /// \brief Constructor
- /// \param io_service the asio::io_service to work with
/// \param fd the file descriptor of opened UDP socket
/// \param af address family, either AF_INET or AF_INET6
/// \param checkin the callbackprovider for non-DNS events
diff --git a/src/lib/asiodns/tcp_server.cc b/src/lib/asiodns/tcp_server.cc
index 3e97e14..8e4b4d6 100644
--- a/src/lib/asiodns/tcp_server.cc
+++ b/src/lib/asiodns/tcp_server.cc
@@ -47,28 +47,6 @@ namespace asiodns {
/// The following functions implement the \c TCPServer class.
///
/// The constructor
-TCPServer::TCPServer(io_service& io_service,
- const ip::address& addr, const uint16_t port,
- const SimpleCallback* checkin,
- const DNSLookup* lookup,
- const DNSAnswer* answer) :
- io_(io_service), done_(false),
- checkin_callback_(checkin), lookup_callback_(lookup),
- answer_callback_(answer)
-{
- tcp::endpoint endpoint(addr, port);
- acceptor_.reset(new tcp::acceptor(io_service));
- acceptor_->open(endpoint.protocol());
- // Set v6-only (we use a separate instantiation for v4,
- // otherwise asio will bind to both v4 and v6
- if (addr.is_v6()) {
- acceptor_->set_option(ip::v6_only(true));
- }
- acceptor_->set_option(tcp::acceptor::reuse_address(true));
- acceptor_->bind(endpoint);
- acceptor_->listen();
-}
-
TCPServer::TCPServer(io_service& io_service, int fd, int af,
const SimpleCallback* checkin,
const DNSLookup* lookup,
diff --git a/src/lib/asiodns/tcp_server.h b/src/lib/asiodns/tcp_server.h
index a75fddb..01695e4 100644
--- a/src/lib/asiodns/tcp_server.h
+++ b/src/lib/asiodns/tcp_server.h
@@ -37,12 +37,6 @@ namespace asiodns {
/// defined in coroutine.h.
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 isc::asiolink::SimpleCallback* checkin = NULL,
- const DNSLookup* lookup = NULL,
- const DNSAnswer* answer = NULL);
-
/// \brief Constructor
/// \param io_service the asio::io_service to work with
/// \param fd the file descriptor of opened TCP socket
diff --git a/src/lib/asiodns/tests/dns_server_unittest.cc b/src/lib/asiodns/tests/dns_server_unittest.cc
index 0064bba..a5e83c7 100644
--- a/src/lib/asiodns/tests/dns_server_unittest.cc
+++ b/src/lib/asiodns/tests/dns_server_unittest.cc
@@ -414,22 +414,7 @@ class DNSServerTestBase : public::testing::Test {
static bool io_service_is_time_out;
};
-// Initialization with name and port
-template<class UDPServerClass>
-class AddrPortInit : public DNSServerTestBase<UDPServerClass> {
-protected:
- AddrPortInit() {
- this->udp_server_ = new UDPServerClass(this->service,
- this->server_address_,
- server_port, this->checker_,
- this->lookup_, this->answer_);
- this->tcp_server_ = new TCPServer(this->service, this->server_address_,
- server_port, this->checker_,
- this->lookup_, this->answer_);
- }
-};
-
-// Initialization by the file descriptor
+// Initialization (by the file descriptor)
template<class UDPServerClass>
class FdInit : public DNSServerTestBase<UDPServerClass> {
private:
@@ -494,8 +479,7 @@ protected:
template<class Parent>
class DNSServerTest : public Parent { };
-typedef ::testing::Types<AddrPortInit<UDPServer>, AddrPortInit<SyncUDPServer>,
- FdInit<UDPServer>, FdInit<SyncUDPServer> >
+typedef ::testing::Types<FdInit<UDPServer>, FdInit<SyncUDPServer> >
ServerTypes;
TYPED_TEST_CASE(DNSServerTest, ServerTypes);
@@ -507,12 +491,6 @@ bool DNSServerTestBase<UDPServerClass>::io_service_is_time_out = false;
template<class UDPServerClass>
asio::io_service* DNSServerTestBase<UDPServerClass>::current_service(NULL);
-typedef ::testing::Types<AddrPortInit<SyncUDPServer>, FdInit<SyncUDPServer> >
- SyncTypes;
-template<class Parent>
-class SyncServerTest : public Parent { };
-TYPED_TEST_CASE(SyncServerTest, SyncTypes);
-
// Test whether server stopped successfully after client get response
// client will send query and start to wait for response, once client
// get response, udp server will be stopped, the io service won't quit
@@ -558,7 +536,8 @@ TYPED_TEST(DNSServerTest, stopUDPServerDuringPrepareAnswer) {
EXPECT_TRUE(this->serverStopSucceed());
}
-static void stopServerManyTimes(DNSServer *server, unsigned int times) {
+void
+stopServerManyTimes(DNSServer *server, unsigned int times) {
for (unsigned int i = 0; i < times; ++i) {
server->stop();
}
@@ -680,18 +659,19 @@ TYPED_TEST(DNSServerTestBase, DISABLED_invalidUDPFD) {
isc::asiolink::IOError);
}
-// Check it rejects some of the unsupported operatirons
-TYPED_TEST(SyncServerTest, unsupportedOps) {
- EXPECT_THROW(this->udp_server_->clone(), isc::Unexpected);
- EXPECT_THROW(this->udp_server_->asyncLookup(), isc::Unexpected);
+// A specialized test type for SyncUDPServer.
+typedef FdInit<SyncUDPServer> SyncServerTest;
+
+// Check it rejects some of the unsupported operations
+TEST_F(SyncServerTest, unsupportedOps) {
+ EXPECT_THROW(udp_server_->clone(), isc::Unexpected);
+ EXPECT_THROW(udp_server_->asyncLookup(), isc::Unexpected);
}
// Check it rejects forgotten resume (eg. insists that it is synchronous)
-TYPED_TEST(SyncServerTest, mustResume) {
- this->lookup_->allow_resume_ = false;
- ASSERT_THROW(this->testStopServerByStopper(this->udp_server_,
- this->udp_client_,
- this->lookup_),
+TEST_F(SyncServerTest, mustResume) {
+ lookup_->allow_resume_ = false;
+ ASSERT_THROW(testStopServerByStopper(udp_server_, udp_client_, lookup_),
isc::Unexpected);
}
diff --git a/src/lib/asiodns/tests/dns_service_unittest.cc b/src/lib/asiodns/tests/dns_service_unittest.cc
index beac02b..ce8eee9 100644
--- a/src/lib/asiodns/tests/dns_service_unittest.cc
+++ b/src/lib/asiodns/tests/dns_service_unittest.cc
@@ -39,98 +39,7 @@ using boost::lexical_cast;
namespace {
const char* const TEST_SERVER_PORT = "53535";
-const char* const TEST_CLIENT_PORT = "53536";
const char* const TEST_IPV6_ADDR = "::1";
-const char* const TEST_IPV4_ADDR = "127.0.0.1";
-
-TEST(IOServiceTest, badPort) {
- IOService io_service;
- EXPECT_THROW(DNSService(io_service, *"65536", true, false, NULL, NULL, NULL), IOError);
- EXPECT_THROW(DNSService(io_service, *"53210.0", true, false, NULL, NULL, NULL), IOError);
- EXPECT_THROW(DNSService(io_service, *"-1", true, false, NULL, NULL, NULL), IOError);
- EXPECT_THROW(DNSService(io_service, *"domain", true, false, NULL, NULL, NULL), IOError);
-}
-
-TEST(IOServiceTest, badAddress) {
- IOService io_service;
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"192.0.2.1.1", NULL, NULL, NULL), IOError);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"2001:db8:::1", NULL, NULL, NULL), IOError);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"localhost", NULL, NULL, NULL), IOError);
-}
-
-TEST(IOServiceTest, unavailableAddress) {
- IOService io_service;
- // These addresses should generally be unavailable as a valid local
- // address, although there's no guarantee in theory.
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"192.0.2.0", NULL, NULL, NULL), IOError);
-
- // Some OSes would simply reject binding attempt for an AF_INET6 socket
- // to an IPv4-mapped IPv6 address. Even if those that allow it, since
- // the corresponding IPv4 address is the same as the one used in the
- // AF_INET socket case above, it should at least show the same result
- // as the previous one.
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:192.0.2.0", NULL, NULL, NULL), IOError);
-}
-
-TEST(IOServiceTest, duplicateBind_v6) {
- // In each sub test case, second attempt should fail due to duplicate bind
- IOService io_service;
-
- // IPv6, "any" address
- DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, false, true, NULL, NULL, NULL);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, false, true, NULL, NULL, NULL), IOError);
- delete dns_service;
-
-}
-
-TEST(IOServiceTest, duplicateBind_v6_address) {
- // In each sub test case, second attempt should fail due to duplicate bind
- IOService io_service;
-
- // IPv6, specific address
- DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL), IOError);
- delete dns_service;
-
-}
-
-TEST(IOServiceTest, duplicateBind_v4) {
- // In each sub test case, second attempt should fail due to duplicate bind
- IOService io_service;
-
- // IPv4, "any" address
- DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, true, false, NULL, NULL, NULL);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, true, false, NULL, NULL, NULL), IOError);
- delete dns_service;
-
-}
-
-TEST(IOServiceTest, duplicateBind_v4_address) {
- // In each sub test case, second attempt should fail due to duplicate bind
- IOService io_service;
-
- // IPv4, specific address
- DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL), IOError);
- delete dns_service;
-}
-
-// Disabled because IPv4-mapped addresses don't seem to be working with
-// the IOService constructor
-TEST(IOServiceTest, DISABLED_IPv4MappedDuplicateBind) {
- IOService io_service;
- // Duplicate bind on IPv4-mapped IPv6 address
- DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *"127.0.0.1", NULL, NULL, NULL);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:127.0.0.1", NULL, NULL, NULL), IOError);
- delete dns_service;
-
- // XXX:
- // Currently, this throws an "invalid argument" exception. I have
- // not been able to get IPv4-mapped addresses to work.
- dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:127.0.0.1", NULL, NULL, NULL);
- EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"127.0.0.1", NULL, NULL, NULL), IOError);
- delete dns_service;
-}
// A simple lookup callback for DNS services. It records the pointer value of
// to given output buffer each time the callback is called (up to two times)
diff --git a/src/lib/asiodns/udp_server.cc b/src/lib/asiodns/udp_server.cc
index 0fb8bec..0f5456b 100644
--- a/src/lib/asiodns/udp_server.cc
+++ b/src/lib/asiodns/udp_server.cc
@@ -182,12 +182,6 @@ struct UDPServer::Data {
///
/// The constructor. It just creates new internal state object
/// and lets it handle the initialization.
-UDPServer::UDPServer(io_service& io_service, const ip::address& addr,
- const uint16_t port, SimpleCallback* checkin,
- DNSLookup* lookup, DNSAnswer* answer) :
- data_(new Data(io_service, addr, port, checkin, lookup, answer))
-{ }
-
UDPServer::UDPServer(io_service& io_service, int fd, int af,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer) :
diff --git a/src/lib/asiodns/udp_server.h b/src/lib/asiodns/udp_server.h
index 2b6a574..b32c06c 100644
--- a/src/lib/asiodns/udp_server.h
+++ b/src/lib/asiodns/udp_server.h
@@ -41,19 +41,6 @@ class UDPServer : public virtual DNSServer, public virtual coroutine {
public:
/// \brief Constructor
/// \param io_service the asio::io_service to work with
- /// \param addr the IP address to listen for queries on
- /// \param port the port to listen for queries on
- /// \param checkin the callbackprovider for non-DNS events
- /// \param lookup the callbackprovider for DNS lookup events
- /// \param answer the callbackprovider for DNS answer events
- explicit UDPServer(asio::io_service& io_service,
- const asio::ip::address& addr, const uint16_t port,
- isc::asiolink::SimpleCallback* checkin = NULL,
- DNSLookup* lookup = NULL,
- DNSAnswer* answer = NULL);
-
- /// \brief Constructor
- /// \param io_service the asio::io_service to work with
/// \param fd the file descriptor of opened UDP socket
/// \param af address family, either AF_INET or AF_INET6
/// \param checkin the callbackprovider for non-DNS events
diff --git a/src/lib/resolve/tests/recursive_query_unittest.cc b/src/lib/resolve/tests/recursive_query_unittest.cc
index 83ea052..a8b8057 100644
--- a/src/lib/resolve/tests/recursive_query_unittest.cc
+++ b/src/lib/resolve/tests/recursive_query_unittest.cc
@@ -18,10 +18,12 @@
#include <sys/socket.h>
#include <sys/time.h>
-#include <string.h>
+#include <cstring>
+#include <boost/noncopyable.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <gtest/gtest.h>
@@ -62,6 +64,7 @@ using namespace isc::asiodns;
using namespace isc::asiolink;
using namespace isc::dns;
using namespace isc::util;
+using boost::scoped_ptr;
namespace isc {
namespace asiodns {
@@ -85,18 +88,14 @@ const char* const TEST_IPV4_ADDR = "127.0.0.1";
// for the tests below.
const uint8_t test_data[] = {0, 4, 1, 2, 3, 4};
-// This function returns an addrinfo structure for use by tests, using
-// different addresses and ports depending on whether we're testing
-// IPv4 or v6, TCP or UDP, and client or server operation.
+// This function returns an addrinfo structure for use by tests.
struct addrinfo*
-resolveAddress(const int family, const int protocol, const bool client) {
- const char* const addr = (family == AF_INET6) ?
- TEST_IPV6_ADDR : TEST_IPV4_ADDR;
- const char* const port = client ? TEST_CLIENT_PORT : TEST_SERVER_PORT;
-
+resolveAddress(const int protocol, const char* const addr,
+ const char* const port)
+{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
+ hints.ai_family = AF_UNSPEC; // let the address decide it.
hints.ai_socktype = (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = protocol;
hints.ai_flags = AI_NUMERICSERV;
@@ -110,6 +109,51 @@ resolveAddress(const int family, const int protocol, const bool client) {
return (res);
}
+// convenience shortcut of the other version using different addresses and
+// ports depending on whether we're testing IPv4 or v6, TCP or UDP, and
+// client or server operation.
+struct addrinfo*
+resolveAddress(const int family, const int protocol, const bool client) {
+ return (resolveAddress(protocol,
+ (family == AF_INET6) ? TEST_IPV6_ADDR :
+ TEST_IPV4_ADDR,
+ client ? TEST_CLIENT_PORT : TEST_SERVER_PORT));
+}
+
+// A helper holder of addrinfo so we can safely release the resource
+// either when leaving the defined scope either normally or due to exception.
+struct ScopedAddrInfo {
+ ScopedAddrInfo(struct addrinfo* res) : res_(res) {}
+ ~ScopedAddrInfo() { freeaddrinfo(res_); }
+ struct addrinfo* res_;
+};
+
+// Similar to ScopedAddrInfo but for socket FD. It also supports the "release"
+// operation so it can release the ownership of the FD.
+// This is made non copyable to avoid making an accidental copy, which could
+// result in duplicate close.
+struct ScopedSocket : private boost::noncopyable {
+ ScopedSocket() : s_(-1) {}
+ ScopedSocket(int s) : s_(s) {}
+ ~ScopedSocket() {
+ if (s_ >= 0) {
+ close(s_);
+ }
+ }
+ void reset(int new_s) {
+ if (s_ >= 0) {
+ close(s_);
+ }
+ s_ = new_s;
+ }
+ int release() {
+ int s = s_;
+ s_ = -1;
+ return (s);
+ }
+ int s_;
+};
+
// This fixture is a framework for various types of network operations
// using the ASIO interfaces. Each test case creates an IOService object,
// opens a local "client" socket for testing, sends data via the local socket
@@ -129,27 +173,20 @@ protected:
// It would delete itself, but after the io_service_, which could
// segfailt in case there were unhandled requests
resolver_.reset();
- if (res_ != NULL) {
- freeaddrinfo(res_);
- }
- if (sock_ != -1) {
- close(sock_);
- }
- delete dns_service_;
- delete callback_;
- delete io_service_;
}
// Send a test UDP packet to a mock server
void sendUDP(const int family) {
- res_ = resolveAddress(family, IPPROTO_UDP, false);
+ ScopedAddrInfo sai(resolveAddress(family, IPPROTO_UDP, false));
+ struct addrinfo* res = sai.res_;
- sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
- if (sock_ < 0) {
+ sock_.reset(socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol));
+ if (sock_.s_ < 0) {
isc_throw(IOError, "failed to open test socket");
}
- const int cc = sendto(sock_, test_data, sizeof(test_data), 0,
- res_->ai_addr, res_->ai_addrlen);
+ const int cc = sendto(sock_.s_, test_data, sizeof(test_data), 0,
+ res->ai_addr, res->ai_addrlen);
if (cc != sizeof(test_data)) {
isc_throw(IOError, "unexpected sendto result: " << cc);
}
@@ -158,16 +195,18 @@ protected:
// Send a test TCP packet to a mock server
void sendTCP(const int family) {
- res_ = resolveAddress(family, IPPROTO_TCP, false);
+ ScopedAddrInfo sai(resolveAddress(family, IPPROTO_TCP, false));
+ struct addrinfo* res = sai.res_;
- sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
- if (sock_ < 0) {
+ sock_.reset(socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol));
+ if (sock_.s_ < 0) {
isc_throw(IOError, "failed to open test socket");
}
- if (connect(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
+ if (connect(sock_.s_, res->ai_addr, res->ai_addrlen) < 0) {
isc_throw(IOError, "failed to connect to the test server");
}
- const int cc = send(sock_, test_data, sizeof(test_data), 0);
+ const int cc = send(sock_.s_, test_data, sizeof(test_data), 0);
if (cc != sizeof(test_data)) {
isc_throw(IOError, "unexpected send result: " << cc);
}
@@ -178,14 +217,16 @@ protected:
// recursive lookup. The caller must place a RecursiveQuery
// on the IO Service queue before running this routine.
void recvUDP(const int family, void* buffer, size_t& size) {
- res_ = resolveAddress(family, IPPROTO_UDP, true);
+ ScopedAddrInfo sai(resolveAddress(family, IPPROTO_UDP, true));
+ struct addrinfo* res = sai.res_;
- sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
- if (sock_ < 0) {
+ sock_.reset(socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol));
+ if (sock_.s_ < 0) {
isc_throw(IOError, "failed to open test socket");
}
- if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
+ if (bind(sock_.s_, res->ai_addr, res->ai_addrlen) < 0) {
isc_throw(IOError, "bind failed: " << strerror(errno));
}
@@ -205,7 +246,7 @@ protected:
// we add an ad hoc timeout.
const struct timeval timeo = { 10, 0 };
int recv_options = 0;
- if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
+ if (setsockopt(sock_.s_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
sizeof(timeo))) {
if (errno == ENOPROTOOPT) {
// Workaround for Solaris: it doesn't accept SO_RCVTIMEO
@@ -218,7 +259,7 @@ protected:
isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
}
}
- const int ret = recv(sock_, buffer, size, recv_options);
+ const int ret = recv(sock_.s_, buffer, size, recv_options);
if (ret < 0) {
isc_throw(IOError, "recvfrom failed: " << strerror(errno));
}
@@ -227,38 +268,68 @@ protected:
size = ret;
}
+ void
+ addServer(const string& address, const char* const port, int protocol) {
+ ScopedAddrInfo sai(resolveAddress(protocol, address.c_str(), port));
+ struct addrinfo* res = sai.res_;
+ const int family = res->ai_family;
+
+ ScopedSocket sock(socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol));
+ const int s = sock.s_;
+ if (s < 0) {
+ isc_throw(isc::Unexpected, "failed to open a test socket");
+ }
+ const int on = 1;
+ if (family == AF_INET6) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) ==
+ -1) {
+ isc_throw(isc::Unexpected,
+ "failed to set socket option(IPV6_V6ONLY)");
+ }
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
+ isc_throw(isc::Unexpected,
+ "failed to set socket option(SO_REUSEADDR)");
+ }
+ if (bind(s, res->ai_addr, res->ai_addrlen) != 0) {
+ isc_throw(isc::Unexpected, "failed to bind a test socket");
+ }
+ if (protocol == IPPROTO_TCP) {
+ dns_service_->addServerTCPFromFD(sock.release(), family);
+ } else {
+ dns_service_->addServerUDPFromFD(sock.release(), family);
+ }
+ }
// Set up an IO Service queue using the specified address
- void setDNSService(const char& address) {
- delete dns_service_;
- dns_service_ = NULL;
- delete io_service_;
- io_service_ = new IOService();
- callback_ = new ASIOCallBack(this);
- dns_service_ = new DNSService(*io_service_, *TEST_SERVER_PORT, address, callback_, NULL, NULL);
+ void setDNSService(const string& address) {
+ setDNSService();
+ addServer(address, TEST_SERVER_PORT, IPPROTO_TCP);
+ addServer(address, TEST_SERVER_PORT, IPPROTO_UDP);
}
// Set up an IO Service queue using the "any" address, on IPv4 if
// 'use_ipv4' is true and on IPv6 if 'use_ipv6' is true.
void setDNSService(const bool use_ipv4, const bool use_ipv6) {
- delete dns_service_;
- dns_service_ = NULL;
- delete io_service_;
- io_service_ = new IOService();
- callback_ = new ASIOCallBack(this);
- dns_service_ = new DNSService(*io_service_, *TEST_SERVER_PORT, use_ipv4, use_ipv6, callback_,
- NULL, NULL);
+ setDNSService();
+ if (use_ipv6) {
+ addServer("::", TEST_SERVER_PORT, IPPROTO_TCP);
+ addServer("::", TEST_SERVER_PORT, IPPROTO_UDP);
+ }
+ if (use_ipv4) {
+ addServer("0.0.0.0", TEST_SERVER_PORT, IPPROTO_TCP);
+ addServer("0.0.0.0", TEST_SERVER_PORT, IPPROTO_UDP);
+ }
}
// Set up empty DNS Service
// Set up an IO Service queue without any addresses
void setDNSService() {
- delete dns_service_;
- dns_service_ = NULL;
- delete io_service_;
- io_service_ = new IOService();
- callback_ = new ASIOCallBack(this);
- dns_service_ = new DNSService(*io_service_, callback_, NULL, NULL);
+ io_service_.reset(new IOService());
+ callback_.reset(new ASIOCallBack(this));
+ dns_service_.reset(new DNSService(*io_service_, callback_.get(), NULL,
+ NULL));
}
// Run a simple server test, on either IPv4 or IPv6, and over either
@@ -277,7 +348,7 @@ protected:
// There doesn't seem to be an effective test for the validity of
// 'native'.
// One thing we are sure is it must be different from our local socket.
- EXPECT_NE(sock_, callback_native_);
+ EXPECT_NE(sock_.s_, callback_native_);
EXPECT_EQ(protocol, callback_protocol_);
EXPECT_EQ(family == AF_INET6 ? TEST_IPV6_ADDR : TEST_IPV4_ADDR,
callback_address_);
@@ -425,28 +496,26 @@ private:
protected:
// We use a pointer for io_service_, because for some tests we
// need to recreate a new one within one onstance of this class
- IOService* io_service_;
- DNSService* dns_service_;
- isc::nsas::NameserverAddressStore* nsas_;
+ scoped_ptr<IOService> io_service_;
+ scoped_ptr<DNSService> dns_service_;
+ scoped_ptr<isc::nsas::NameserverAddressStore> nsas_;
isc::cache::ResolverCache cache_;
- ASIOCallBack* callback_;
+ scoped_ptr<ASIOCallBack> callback_;
int callback_protocol_;
int callback_native_;
string callback_address_;
vector<uint8_t> callback_data_;
- int sock_;
- struct addrinfo* res_;
+ ScopedSocket sock_;
boost::shared_ptr<isc::util::unittests::TestResolver> resolver_;
};
RecursiveQueryTest::RecursiveQueryTest() :
dns_service_(NULL), callback_(NULL), callback_protocol_(0),
- callback_native_(-1), sock_(-1), res_(NULL),
- resolver_(new isc::util::unittests::TestResolver())
+ callback_native_(-1), resolver_(new isc::util::unittests::TestResolver())
{
- io_service_ = new IOService();
+ io_service_.reset(new IOService());
setDNSService(true, true);
- nsas_ = new isc::nsas::NameserverAddressStore(resolver_);
+ nsas_.reset(new isc::nsas::NameserverAddressStore(resolver_));
}
TEST_F(RecursiveQueryTest, v6UDPSend) {
@@ -477,24 +546,24 @@ TEST_F(RecursiveQueryTest, v6UDPSendSpecific) {
// an error on a subsequent read operation. We could do it, but for
// simplicity we only tests the easier cases for now.
- setDNSService(*TEST_IPV6_ADDR);
+ setDNSService(TEST_IPV6_ADDR);
doTest(AF_INET6, IPPROTO_UDP);
}
TEST_F(RecursiveQueryTest, v6TCPSendSpecific) {
- setDNSService(*TEST_IPV6_ADDR);
+ setDNSService(TEST_IPV6_ADDR);
doTest(AF_INET6, IPPROTO_TCP);
EXPECT_THROW(sendTCP(AF_INET), IOError);
}
TEST_F(RecursiveQueryTest, v4UDPSendSpecific) {
- setDNSService(*TEST_IPV4_ADDR);
+ setDNSService(TEST_IPV4_ADDR);
doTest(AF_INET, IPPROTO_UDP);
}
TEST_F(RecursiveQueryTest, v4TCPSendSpecific) {
- setDNSService(*TEST_IPV4_ADDR);
+ setDNSService(TEST_IPV4_ADDR);
doTest(AF_INET, IPPROTO_TCP);
EXPECT_THROW(sendTCP(AF_INET6), IOError);
@@ -502,7 +571,7 @@ TEST_F(RecursiveQueryTest, v4TCPSendSpecific) {
TEST_F(RecursiveQueryTest, v6AddServer) {
setDNSService();
- dns_service_->addServer(*TEST_SERVER_PORT, TEST_IPV6_ADDR);
+ addServer(TEST_IPV6_ADDR, TEST_SERVER_PORT, IPPROTO_TCP);
doTest(AF_INET6, IPPROTO_TCP);
EXPECT_THROW(sendTCP(AF_INET), IOError);
@@ -510,7 +579,7 @@ TEST_F(RecursiveQueryTest, v6AddServer) {
TEST_F(RecursiveQueryTest, v4AddServer) {
setDNSService();
- dns_service_->addServer(*TEST_SERVER_PORT, TEST_IPV4_ADDR);
+ addServer(TEST_IPV4_ADDR, TEST_SERVER_PORT, IPPROTO_TCP);
doTest(AF_INET, IPPROTO_TCP);
EXPECT_THROW(sendTCP(AF_INET6), IOError);
@@ -607,41 +676,43 @@ TEST_F(RecursiveQueryTest, forwarderSend) {
}
int
-createTestSocket()
-{
- struct addrinfo* res_ = resolveAddress(AF_INET, IPPROTO_UDP, true);
- int sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
- if (sock_ < 0) {
+createTestSocket() {
+ ScopedAddrInfo sai(resolveAddress(AF_INET, IPPROTO_UDP, true));
+ struct addrinfo* res = sai.res_;
+
+ ScopedSocket sock(socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol));
+ if (sock.s_ < 0) {
isc_throw(IOError, "failed to open test socket");
}
- if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
+ if (bind(sock.s_, res->ai_addr, res->ai_addrlen) < 0) {
isc_throw(IOError, "failed to bind test socket");
}
- return sock_;
+ return (sock.release());
}
int
-setSocketTimeout(int sock_, size_t tv_sec, size_t tv_usec) {
+setSocketTimeout(int sock, size_t tv_sec, size_t tv_usec) {
const struct timeval timeo = { tv_sec, tv_usec };
int recv_options = 0;
- if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
if (errno == ENOPROTOOPT) { // see RecursiveQueryTest::recvUDP()
recv_options = MSG_DONTWAIT;
} else {
isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
}
}
- return recv_options;
+ return (recv_options);
}
// try to read from the socket max time
// *num is incremented for every succesfull read
// returns true if it can read max times, false otherwise
-bool tryRead(int sock_, int recv_options, size_t max, int* num) {
+bool tryRead(int sock, int recv_options, size_t max, int* num) {
size_t i = 0;
do {
char inbuff[512];
- if (recv(sock_, inbuff, sizeof(inbuff), recv_options) < 0) {
+ if (recv(sock, inbuff, sizeof(inbuff), recv_options) < 0) {
return false;
} else {
++i;
@@ -691,7 +762,7 @@ TEST_F(RecursiveQueryTest, forwardQueryTimeout) {
setDNSService();
// Prepare the socket
- sock_ = createTestSocket();
+ sock_.reset(createTestSocket());
// Prepare the server
bool done(true);
@@ -725,7 +796,7 @@ TEST_F(RecursiveQueryTest, forwardClientTimeout) {
// Prepare the service (we do not use the common setup, we do not answer
setDNSService();
- sock_ = createTestSocket();
+ sock_.reset(createTestSocket());
// Prepare the server
bool done1(true);
@@ -759,7 +830,7 @@ TEST_F(RecursiveQueryTest, forwardLookupTimeout) {
setDNSService();
// Prepare the socket
- sock_ = createTestSocket();
+ sock_.reset(createTestSocket());
// Prepare the server
bool done(true);
@@ -794,7 +865,7 @@ TEST_F(RecursiveQueryTest, lowtimeouts) {
setDNSService();
// Prepare the socket
- sock_ = createTestSocket();
+ sock_.reset(createTestSocket());
// Prepare the server
bool done(true);
More information about the bind10-changes
mailing list