[svn] commit: r3125 - in /branches/trac327/src: bin/bind10/tests/bind10_test.py bin/recurse/recursor.cc lib/asiolink/asiolink.cc lib/asiolink/asiolink.h lib/asiolink/internal/udpdns.h lib/asiolink/tests/asio_link_unittest.cc lib/asiolink/udpdns.cc
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Oct 6 19:22:07 UTC 2010
Author: each
Date: Wed Oct 6 19:22:07 2010
New Revision: 3125
Log:
Added some asiolink tests, fixed BoB tests
Modified:
branches/trac327/src/bin/bind10/tests/bind10_test.py
branches/trac327/src/bin/recurse/recursor.cc
branches/trac327/src/lib/asiolink/asiolink.cc
branches/trac327/src/lib/asiolink/asiolink.h
branches/trac327/src/lib/asiolink/internal/udpdns.h
branches/trac327/src/lib/asiolink/tests/asio_link_unittest.cc
branches/trac327/src/lib/asiolink/udpdns.cc
Modified: branches/trac327/src/bin/bind10/tests/bind10_test.py
==============================================================================
--- branches/trac327/src/bin/bind10/tests/bind10_test.py (original)
+++ branches/trac327/src/bin/bind10/tests/bind10_test.py Wed Oct 6 19:22:07 2010
@@ -99,7 +99,7 @@
bob = BoB()
self.assertEqual(bob.verbose, False)
self.assertEqual(bob.msgq_socket_file, None)
- self.assertEqual(bob.auth_port, 5300)
+ self.assertEqual(bob.dns_port, 5300)
self.assertEqual(bob.cc_session, None)
self.assertEqual(bob.address, None)
self.assertEqual(bob.processes, {})
@@ -115,11 +115,11 @@
self.assertEqual(bob.dead_processes, {})
self.assertEqual(bob.runnable, False)
- def test_init_alternate_auth_port(self):
+ def test_init_alternate_dns_port(self):
bob = BoB(None, 9999)
self.assertEqual(bob.verbose, False)
self.assertEqual(bob.msgq_socket_file, None)
- self.assertEqual(bob.auth_port, 9999)
+ self.assertEqual(bob.dns_port, 9999)
self.assertEqual(bob.cc_session, None)
self.assertEqual(bob.address, None)
self.assertEqual(bob.processes, {})
@@ -129,7 +129,7 @@
def test_init_alternate_address(self):
bob = BoB(None, 5300, '127.127.127.127')
self.assertEqual(bob.verbose, False)
- self.assertEqual(bob.auth_port, 5300)
+ self.assertEqual(bob.dns_port, 5300)
self.assertEqual(bob.msgq_socket_file, None)
self.assertEqual(bob.cc_session, None)
self.assertEqual(bob.address.addr, socket.inet_aton('127.127.127.127'))
Modified: branches/trac327/src/bin/recurse/recursor.cc
==============================================================================
--- branches/trac327/src/bin/recurse/recursor.cc (original)
+++ branches/trac327/src/bin/recurse/recursor.cc Wed Oct 6 19:22:07 2010
@@ -81,8 +81,7 @@
}
}
- void processNormalQuery(const IOMessage& io_message,
- const Question& question, MessagePtr message,
+ void processNormalQuery(const Question& question, MessagePtr message,
OutputBufferPtr buffer,
DNSServer* server);
ModuleCCSession* config_session_;
@@ -406,8 +405,7 @@
// The RecursiveQuery object will post the "resume" event to the
// DNSServer when an answer arrives, so we don't have to do it now.
sendAnswer = false;
- impl_->processNormalQuery(io_message, *question, message,
- buffer, server);
+ impl_->processNormalQuery(*question, message, buffer, server);
}
}
@@ -417,8 +415,7 @@
}
void
-RecursorImpl::processNormalQuery(const IOMessage& io_message,
- const Question& question, MessagePtr message,
+RecursorImpl::processNormalQuery(const Question& question, MessagePtr message,
OutputBufferPtr buffer, DNSServer* server)
{
const bool dnssec_ok = message->isDNSSECSupported();
@@ -428,7 +425,7 @@
message->setRcode(Rcode::NOERROR());
message->setDNSSECSupported(dnssec_ok);
message->setUDPSize(RecursorImpl::DEFAULT_LOCAL_UDPSIZE);
- rec_query_->sendQuery(io_message, question, buffer, server);
+ rec_query_->sendQuery(question, buffer, server);
}
ConstElementPtr
Modified: branches/trac327/src/lib/asiolink/asiolink.cc
==============================================================================
--- branches/trac327/src/lib/asiolink/asiolink.cc (original)
+++ branches/trac327/src/lib/asiolink/asiolink.cc Wed Oct 6 19:22:07 2010
@@ -93,8 +93,9 @@
remote_endpoint_(remote_endpoint)
{}
-RecursiveQuery::RecursiveQuery(IOService& io_service, const char& forward) :
- io_service_(io_service)
+RecursiveQuery::RecursiveQuery(IOService& io_service, const char& forward,
+ uint16_t port) :
+ io_service_(io_service), port_(port)
{
error_code err;
ns_addr_ = ip::address::from_string(&forward, err);
@@ -105,8 +106,7 @@
}
void
-RecursiveQuery::sendQuery(const IOMessage& io_message,
- const Question& question, OutputBufferPtr buffer,
+RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
DNSServer* server)
{
@@ -115,7 +115,7 @@
// UDP and then fall back to TCP on failure, but for the moment
// we're only going to handle UDP.
asio::io_service& io = io_service_.get_io_service();
- UDPQuery q(io, io_message, question, ns_addr_, buffer, server);
+ UDPQuery q(io, question, ns_addr_, port_, buffer, server);
io.post(q);
}
@@ -233,6 +233,11 @@
}
void
+IOService::run_one() {
+ impl_->io_service_.run_one();
+}
+
+void
IOService::stop() {
impl_->io_service_.stop();
}
Modified: branches/trac327/src/lib/asiolink/asiolink.h
==============================================================================
--- branches/trac327/src/lib/asiolink/asiolink.h (original)
+++ branches/trac327/src/lib/asiolink/asiolink.h Wed Oct 6 19:22:07 2010
@@ -446,6 +446,13 @@
/// the \c stop() method is called via some handler.
void run();
+ /// \brief Run the underlying event loop for a single event.
+ ///
+ /// This method return control to the caller as soon as the
+ /// first handler has completed. (If no handlers are ready when
+ /// it is run, it will block until one is.)
+ void run_one();
+
/// \brief Stop the underlying event loop.
///
/// This will return the control to the caller of the \c run() method.
@@ -727,12 +734,12 @@
/// This is currently the only way to construct \c RecursiveQuery
/// object. The address of the forward nameserver is specified,
/// and all upstream queries will be sent to that one address.
- RecursiveQuery(IOService& io_service, const char& forward);
+ RecursiveQuery(IOService& io_service, const char& forward,
+ uint16_t port = 53);
//@}
/// \brief Initiates an upstream query in the \c RecursiveQuery object.
///
- /// \param io_message The message from the original client
/// \param question The question being answered <qname/qclass/qtype>
/// \param buffer An output buffer into which the response can be copied
/// \param server A pointer to the \c DNSServer object handling the client
@@ -741,13 +748,13 @@
/// the upstream name server. When a reply arrives, 'server'
/// is placed on the ASIO service queue via io_service::post(), so
/// that the original \c DNSServer objct can resume processing.
- void sendQuery(const IOMessage& io_message,
- const isc::dns::Question& question,
+ void sendQuery(const isc::dns::Question& question,
isc::dns::OutputBufferPtr buffer,
DNSServer* server);
private:
IOService& io_service_;
asio::ip::address ns_addr_;
+ uint16_t port_;
};
} // asiolink
Modified: branches/trac327/src/lib/asiolink/internal/udpdns.h
==============================================================================
--- branches/trac327/src/lib/asiolink/internal/udpdns.h (original)
+++ branches/trac327/src/lib/asiolink/internal/udpdns.h Wed Oct 6 19:22:07 2010
@@ -166,9 +166,9 @@
class UDPQuery : public coroutine {
public:
explicit UDPQuery(asio::io_service& io_service,
- const IOMessage& io_message,
const isc::dns::Question& q,
const asio::ip::address& addr,
+ uint16_t port,
isc::dns::OutputBufferPtr buffer,
DNSServer* server);
void operator()(asio::error_code ec = asio::error_code(),
Modified: branches/trac327/src/lib/asiolink/tests/asio_link_unittest.cc
==============================================================================
--- branches/trac327/src/lib/asiolink/tests/asio_link_unittest.cc (original)
+++ branches/trac327/src/lib/asiolink/tests/asio_link_unittest.cc Wed Oct 6 19:22:07 2010
@@ -17,11 +17,18 @@
#include <config.h>
+#include <string.h>
+
+#include <boost/lexical_cast.hpp>
+
#include <gtest/gtest.h>
#include <exceptions/exceptions.h>
#include <dns/tests/unittest_util.h>
+
+#include <dns/buffer.h>
+#include <dns/message.h>
#include <asiolink/asiolink.h>
#include <asiolink/internal/tcpdns.h>
@@ -30,9 +37,11 @@
using isc::UnitTestUtil;
using namespace std;
using namespace asiolink;
+using namespace isc::dns;
namespace {
-const char* const TEST_PORT = "53535";
+const char* const TEST_SERVER_PORT = "53535";
+const char* const TEST_CLIENT_PORT = "53535";
const char* const TEST_IPV6_ADDR = "::1";
const char* const TEST_IPV4_ADDR = "127.0.0.1";
// This data is intended to be valid as a DNS/TCP-like message: the first
@@ -127,52 +136,54 @@
}
TEST(IOServiceTest, badAddress) {
- EXPECT_THROW(IOService(*TEST_PORT, *"192.0.2.1.1", NULL, NULL, NULL), IOError);
- EXPECT_THROW(IOService(*TEST_PORT, *"2001:db8:::1", NULL, NULL, NULL), IOError);
- EXPECT_THROW(IOService(*TEST_PORT, *"localhost", NULL, NULL, NULL), IOError);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *"192.0.2.1.1", NULL, NULL, NULL), IOError);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *"2001:db8:::1", NULL, NULL, NULL), IOError);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *"localhost", NULL, NULL, NULL), IOError);
}
TEST(IOServiceTest, unavailableAddress) {
// These addresses should generally be unavailable as a valid local
// address, although there's no guarantee in theory.
- EXPECT_THROW(IOService(*TEST_PORT, *"255.255.0.0", NULL, NULL, NULL), IOError);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *"255.255.0.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(IOService(*TEST_PORT, *"::ffff:255.255.0.0", NULL, NULL, NULL), IOError);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *"::ffff:255.255.0.0", NULL, NULL, NULL), IOError);
}
TEST(IOServiceTest, duplicateBind) {
// In each sub test case, second attempt should fail due to duplicate bind
// IPv6, "any" address
- IOService* io_service = new IOService(*TEST_PORT, false, true, NULL, NULL, NULL);
- EXPECT_THROW(IOService(*TEST_PORT, false, true, NULL, NULL, NULL), IOError);
+ IOService* io_service = new IOService(*TEST_SERVER_PORT, false, true, NULL, NULL, NULL);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, false, true, NULL, NULL, NULL), IOError);
delete io_service;
// IPv6, specific address
- io_service = new IOService(*TEST_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL);
- EXPECT_THROW(IOService(*TEST_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL), IOError);
+ io_service = new IOService(*TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL), IOError);
delete io_service;
// IPv4, "any" address
- io_service = new IOService(*TEST_PORT, true, false, NULL, NULL, NULL);
- EXPECT_THROW(IOService(*TEST_PORT, true, false, NULL, NULL, NULL), IOError);
+ io_service = new IOService(*TEST_SERVER_PORT, true, false, NULL, NULL, NULL);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, true, false, NULL, NULL, NULL), IOError);
delete io_service;
// IPv4, specific address
- io_service = new IOService(*TEST_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL);
- EXPECT_THROW(IOService(*TEST_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL), IOError);
+ io_service = new IOService(*TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL);
+ EXPECT_THROW(IOService(*TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL), IOError);
delete io_service;
}
struct addrinfo*
-resolveAddress(const int family, const int sock_type, const int protocol) {
+resolveAddress(const int family, const int sock_type, 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;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@@ -181,7 +192,7 @@
hints.ai_protocol = protocol;
struct addrinfo* res;
- const int error = getaddrinfo(addr, TEST_PORT, &hints, &res);
+ const int error = getaddrinfo(addr, port, &hints, &res);
if (error != 0) {
isc_throw(IOError, "getaddrinfo failed: " << gai_strerror(error));
}
@@ -219,7 +230,7 @@
}
}
void sendUDP(const int family) {
- res_ = resolveAddress(family, SOCK_DGRAM, IPPROTO_UDP);
+ res_ = resolveAddress(family, SOCK_DGRAM, IPPROTO_UDP, false);
sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
if (sock_ < 0) {
@@ -233,7 +244,7 @@
io_service_->run();
}
void sendTCP(const int family) {
- res_ = resolveAddress(family, SOCK_STREAM, IPPROTO_TCP);
+ res_ = resolveAddress(family, SOCK_STREAM, IPPROTO_TCP, false);
sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
if (sock_ < 0) {
@@ -244,21 +255,51 @@
}
const int cc = send(sock_, test_data, sizeof(test_data), 0);
if (cc != sizeof(test_data)) {
- isc_throw(IOError, "unexpected sendto result: " << cc);
+ isc_throw(IOError, "unexpected send result: " << cc);
}
io_service_->run();
+ }
+ void recvUDP(const int family, void* buffer, size_t size) {
+ res_ = resolveAddress(family, SOCK_DGRAM, IPPROTO_UDP, true);
+
+ sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
+ if (sock_ < 0) {
+ isc_throw(IOError, "failed to open test socket");
+ }
+
+ if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
+ isc_throw(IOError, "bind failed: " << gai_strerror(errno));
+ }
+
+ // The IO service queue should have a RecursiveQuery object scheduled
+ // to run at this point. This call will cause it to begin an
+ // async send, then return.
+ io_service_->run_one();
+
+ // ... and this completes the send().
+ io_service_->run_one();
+
+ // Now we attempt to recv() whatever was sent
+ struct sockaddr addr;
+ socklen_t addrlen;
+ fcntl(sock_, F_SETFD, O_NONBLOCK);
+ const int cc = recvfrom(sock_, buffer, size, MSG_DONTWAIT,
+ &addr, &addrlen);
+ if (cc < 0) {
+ isc_throw(IOError, "recvfrom failed");
+ }
}
void setIOService(const char& address) {
delete io_service_;
io_service_ = NULL;
callback_ = new ASIOCallBack(this);
- io_service_ = new IOService(*TEST_PORT, address, callback_, NULL, NULL);
+ io_service_ = new IOService(*TEST_SERVER_PORT, address, callback_, NULL, NULL);
}
void setIOService(const bool use_ipv4, const bool use_ipv6) {
delete io_service_;
io_service_ = NULL;
callback_ = new ASIOCallBack(this);
- io_service_ = new IOService(*TEST_PORT, use_ipv4, use_ipv6, callback_,
+ io_service_ = new IOService(*TEST_SERVER_PORT, use_ipv4, use_ipv6, callback_,
NULL, NULL);
}
void doTest(const int family, const int protocol) {
@@ -285,6 +326,51 @@
callback_data_.size(),
expected_data, expected_datasize);
}
+
+protected:
+ class MockServer : public DNSServer {
+ public:
+ explicit MockServer(asio::io_service& io_service,
+ const asio::ip::address& addr, const uint16_t port,
+ SimpleCallback* checkin = NULL,
+ DNSLookup* lookup = NULL,
+ DNSAnswer* answer = NULL) :
+ io_(io_service),
+ checkin_(checkin), lookup_(lookup), answer_(answer)
+ {
+ // HERE set up address
+ }
+
+ void operator()(asio::error_code ec = asio::error_code(),
+ size_t length = 0)
+ {
+ // Do some stuff
+ }
+
+ void resume(const bool done) {
+ done_ = done;
+ io_.post(*this);
+ }
+
+ DNSServer* clone() {
+ MockServer* s = new MockServer(*this);
+ return (s);
+ }
+
+ inline void asyncLookup() {
+ // (*lookup_)(*io_message_, message_, respbuf_, this);
+ }
+
+ private:
+ asio::io_service& io_;
+ bool done_;
+
+ // Callback functions provided by the caller
+ const SimpleCallback* checkin_;
+ const DNSLookup* lookup_;
+ const DNSAnswer* answer_;
+ };
+
private:
class ASIOCallBack : public SimpleCallback {
public:
@@ -388,4 +474,37 @@
EXPECT_THROW(sendTCP(AF_INET6), IOError);
}
-}
+TEST_F(ASIOLinkTest, recursiveSetupV4) {
+ setIOService(true, false);
+ uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+ EXPECT_NO_THROW(RecursiveQuery(*io_service_, *TEST_IPV4_ADDR, port));
+}
+
+TEST_F(ASIOLinkTest, recursiveSetupV6) {
+ setIOService(false, true);
+ uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+ EXPECT_NO_THROW(RecursiveQuery(*io_service_, *TEST_IPV6_ADDR, port));
+}
+
+// Test disabled because recvUDP() isn't working yet
+TEST_F(ASIOLinkTest, DISABLED_recursiveSend) {
+ setIOService(true, false);
+ asio::io_service& io = io_service_->get_io_service();
+
+ // Note: We use the test prot plus one to ensure we aren't binding
+ // to the same port as the actual server
+ uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+ asio::ip::address addr = asio::ip::address::from_string(TEST_IPV4_ADDR);
+
+ MockServer server(io, addr, port, NULL, NULL, NULL);
+ RecursiveQuery rq(*io_service_, *TEST_IPV4_ADDR, port);
+
+ Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
+ OutputBufferPtr buffer(new OutputBuffer(0));
+ rq.sendQuery(q, buffer, &server);
+
+ char data[4096];
+ EXPECT_NO_THROW(recvUDP(AF_INET, data, sizeof(data)));
+}
+
+}
Modified: branches/trac327/src/lib/asiolink/udpdns.cc
==============================================================================
--- branches/trac327/src/lib/asiolink/udpdns.cc (original)
+++ branches/trac327/src/lib/asiolink/udpdns.cc Wed Oct 6 19:22:07 2010
@@ -207,15 +207,15 @@
/// The following functions implement the \c UDPQuery class.
///
/// The constructor
-UDPQuery::UDPQuery(io_service& io_service, const IOMessage& io_message,
- const Question& q, const ip::address& addr,
+UDPQuery::UDPQuery(io_service& io_service,
+ const Question& q, const ip::address& addr, uint16_t port,
OutputBufferPtr buffer, DNSServer* server) :
question_(q), buffer_(buffer), server_(server->clone())
{
udp proto = addr.is_v4() ? udp::v4() : udp::v6();
socket_.reset(new udp::socket(io_service, proto));
msgbuf_.reset(new OutputBuffer(512));
- remote_ = udp::endpoint(addr, 53);
+ remote_ = udp::endpoint(addr, port);
}
/// The function operator is implemented with the "stackless coroutine"
More information about the bind10-changes
mailing list