BIND 10 master, updated. 29d36377ec206cbe52274ee9a5a6e88ef27921d5 [master] Fix bug introduced in trac 900 change
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed May 11 06:45:27 UTC 2011
The branch, master has been updated
discards a1926a26c7922cec0d95e00df7aa3bed794d250a (commit)
discards 4569c1b87f5d04f663e1c8e2813d090a78dd9e40 (commit)
discards 7f642b767c8274a6f3344e4a5e1141e9e7f38924 (commit)
discards ea37ca8caa7c56fea957fc7aac066d5708675f28 (commit)
discards 45417c48a7d32fb6e3f7fdccc70ec2faa8441135 (commit)
discards 81b2d1ceaf680d740f66250b848eea1db05c4a3b (commit)
discards 583203a8ca082541bc2982752b20294bb972bdcc (commit)
This update discarded existing revisions and left the branch pointing at
a previous point in the repository history.
* -- * -- N (29d36377ec206cbe52274ee9a5a6e88ef27921d5)
\
O -- O -- O (a1926a26c7922cec0d95e00df7aa3bed794d250a)
The removed revisions are not necessarilly gone - if another reference
still refers to them they will stay in the repository.
No new revisions were added by this update.
Summary of changes:
ChangeLog | 5 -
doc/Doxyfile | 1 -
src/bin/resolver/resolver.cc | 16 +-
src/lib/asiodns/io_fetch.cc | 73 +++-----
src/lib/asiodns/io_fetch.h | 24 ---
src/lib/dns/message.h | 1 -
src/lib/resolve/recursive_query.cc | 221 ++++-----------------
src/lib/resolve/recursive_query.h | 14 --
src/lib/resolve/tests/recursive_query_unittest.cc | 134 ++++++-------
9 files changed, 131 insertions(+), 358 deletions(-)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 06a0c2c..6c7beda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,3 @@
-235. [func] zhang likun
- Implement the simplest forwarder, which pass everything throught
- except QID, port number. The response will not be cached.
- (Trac #598_new, git 4569c1b87f5d04f663e1c8e2813d090a78dd9e40)
-
234. [func] jerry
src/bin/xfrin: update xfrin to use TSIG. Currently it only supports
sending a signed TSIG request or SOA request.
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 783e63a..a57d275 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -574,7 +574,6 @@ INPUT = ../src/lib/cc ../src/lib/config \
../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/
- ../src/lib/resolve
# 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
diff --git a/src/bin/resolver/resolver.cc b/src/bin/resolver/resolver.cc
index e43b48e..591e214 100644
--- a/src/bin/resolver/resolver.cc
+++ b/src/bin/resolver/resolver.cc
@@ -144,7 +144,7 @@ public:
void resolve(const isc::dns::QuestionPtr& question,
const isc::resolve::ResolverInterface::CallbackPtr& callback);
- void processNormalQuery(ConstMessagePtr query_message,
+ void processNormalQuery(const Question& question,
MessagePtr answer_message,
OutputBufferPtr buffer,
DNSServer* server);
@@ -468,7 +468,7 @@ Resolver::processMessage(const IOMessage& io_message,
// 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(query_message, answer_message,
+ impl_->processNormalQuery(*question, answer_message,
buffer, server);
}
}
@@ -486,19 +486,13 @@ ResolverImpl::resolve(const QuestionPtr& question,
}
void
-ResolverImpl::processNormalQuery(ConstMessagePtr query_message,
+ResolverImpl::processNormalQuery(const Question& question,
MessagePtr answer_message,
OutputBufferPtr buffer,
DNSServer* server)
{
- if (upstream_.empty()) {
- dlog("Processing normal query");
- ConstQuestionPtr question = *query_message->beginQuestion();
- rec_query_->resolve(*question, answer_message, buffer, server);
- } else {
- dlog("Processing forward query");
- rec_query_->forward(query_message, answer_message, buffer, server);
- }
+ dlog("Processing normal query");
+ rec_query_->resolve(question, answer_message, buffer, server);
}
ConstElementPtr
diff --git a/src/lib/asiodns/io_fetch.cc b/src/lib/asiodns/io_fetch.cc
index e535381..cc8bd11 100644
--- a/src/lib/asiodns/io_fetch.cc
+++ b/src/lib/asiodns/io_fetch.cc
@@ -35,6 +35,7 @@
#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>
@@ -90,6 +91,7 @@ struct IOFetchData {
///< Socket to use for I/O
boost::scoped_ptr<IOEndpoint> remote_snd;///< Where the fetch is sent
boost::scoped_ptr<IOEndpoint> remote_rcv;///< Where the response came from
+ isc::dns::Question question; ///< Question to be asked
OutputBufferPtr msgbuf; ///< Wire buffer for question
OutputBufferPtr received; ///< Received data put here
IOFetch::Callback* callback; ///< Called on I/O Completion
@@ -119,6 +121,7 @@ struct IOFetchData {
/// \param proto Either IOFetch::TCP or IOFetch::UDP.
/// \param service I/O Service object to handle the asynchronous
/// operations.
+ /// \param query DNS question to send to the upstream server.
/// \param address IP address of upstream server
/// \param port Port to use for the query
/// \param buff Output buffer into which the response (in wire format)
@@ -130,8 +133,8 @@ struct IOFetchData {
///
/// TODO: May need to alter constructor (see comment 4 in Trac ticket #554)
IOFetchData(IOFetch::Protocol proto, IOService& service,
- const IOAddress& address, uint16_t port, OutputBufferPtr& buff,
- IOFetch::Callback* cb, int wait)
+ const isc::dns::Question& query, const IOAddress& address,
+ uint16_t port, OutputBufferPtr& buff, IOFetch::Callback* cb, int wait)
:
socket((proto == IOFetch::UDP) ?
static_cast<IOAsioSocket<IOFetch>*>(
@@ -147,6 +150,7 @@ struct IOFetchData {
static_cast<IOEndpoint*>(new UDPEndpoint(address, port)) :
static_cast<IOEndpoint*>(new TCPEndpoint(address, port))
),
+ question(query),
msgbuf(new OutputBuffer(512)),
received(buff),
callback(cb),
@@ -181,10 +185,10 @@ struct IOFetchData {
IOFetch::IOFetch(Protocol protocol, IOService& service,
const isc::dns::Question& question, const IOAddress& address, uint16_t port,
OutputBufferPtr& buff, Callback* cb, int wait)
+ :
+ data_(new IOFetchData(protocol, service, question, address,
+ port, buff, cb, wait))
{
- MessagePtr query_msg(new Message(Message::RENDER));
- initIOFetch(query_msg, protocol, service, question, address, port, buff,
- cb, wait);
}
IOFetch::IOFetch(Protocol protocol, IOService& service,
@@ -192,56 +196,14 @@ IOFetch::IOFetch(Protocol protocol, IOService& service,
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;
}
-IOFetch::IOFetch(Protocol protocol, IOService& service,
- ConstMessagePtr query_message, const IOAddress& address, uint16_t port,
- OutputBufferPtr& buff, Callback* cb, int wait)
-{
- MessagePtr msg(new Message(Message::RENDER));
-
- msg->setHeaderFlag(Message::HEADERFLAG_RD,
- query_message->getHeaderFlag(Message::HEADERFLAG_RD));
- msg->setHeaderFlag(Message::HEADERFLAG_CD,
- query_message->getHeaderFlag(Message::HEADERFLAG_CD));
-
- ConstEDNSPtr edns(query_message->getEDNS());
- const bool dnssec_ok = edns && edns->getDNSSECAwareness();
- if (edns) {
- EDNSPtr edns_response(new EDNS());
- edns_response->setDNSSECAwareness(dnssec_ok);
- // TODO: We should make our own edns bufsize length configurable
- edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
- msg->setEDNS(edns_response);
- }
-
- initIOFetch(msg, protocol, service,
- **(query_message->beginQuestion()),
- address, port, buff, cb, wait);
-}
-
-void
-IOFetch::initIOFetch(MessagePtr& query_msg, Protocol protocol, IOService& service,
- const isc::dns::Question& question,
- const IOAddress& address, uint16_t port,
- OutputBufferPtr& buff, Callback* cb, int wait)
-{
- data_ = boost::shared_ptr<IOFetchData>(new IOFetchData(
- protocol, service, address, port, buff, cb, wait));
-
- query_msg->setQid(data_->qid);
- query_msg->setOpcode(Opcode::QUERY());
- query_msg->setRcode(Rcode::NOERROR());
- query_msg->setHeaderFlag(Message::HEADERFLAG_RD);
- query_msg->addQuestion(question);
- MessageRenderer renderer(*data_->msgbuf);
- query_msg->toWire(renderer);
-}
-
// Return protocol in use.
IOFetch::Protocol
@@ -273,7 +235,17 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
// 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());
+ msg.setRcode(Rcode::NOERROR());
+ msg.setHeaderFlag(Message::HEADERFLAG_RD);
+ msg.addQuestion(data_->question);
+ MessageRenderer renderer(*data_->msgbuf);
+ msg.toWire(renderer);
+ }
}
// If we timeout, we stop, which will can cancel outstanding I/Os and
@@ -434,3 +406,4 @@ void IOFetch::logIOFailure(asio::error_code ec) {
} // namespace asiodns
} // namespace isc {
+
diff --git a/src/lib/asiodns/io_fetch.h b/src/lib/asiodns/io_fetch.h
index 9626ffe..98c917d 100644
--- a/src/lib/asiodns/io_fetch.h
+++ b/src/lib/asiodns/io_fetch.h
@@ -29,7 +29,6 @@
#include <util/buffer.h>
#include <dns/question.h>
-#include <dns/message.h>
namespace isc {
namespace asiodns {
@@ -137,20 +136,6 @@ public:
uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
int wait = -1);
- /// \brief Constructor
- /// This constructor has one parameter "query_message", which
- /// is the shared_ptr to a full query message. It's different
- /// with above contructor which has only question section. All
- /// other parameters are same.
- ///
- /// \param query_message the shared_ptr to a full query message
- /// got from a query client.
- IOFetch(Protocol protocol, isc::asiolink::IOService& service,
- isc::dns::ConstMessagePtr query_message,
- 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.
@@ -199,15 +184,6 @@ public:
void stop(Result reason = STOPPED);
private:
- /// \brief IOFetch Initialization Function.
- /// All the parameters are same with the constructor, except
- /// parameter "query_message"
- /// \param query_message the message to be sent out.
- void initIOFetch(isc::dns::MessagePtr& query_message, 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);
-
/// \brief Log I/O Failure
///
/// Records an I/O failure to the log file
diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h
index fcc53e9..8a657da 100644
--- a/src/lib/dns/message.h
+++ b/src/lib/dns/message.h
@@ -601,7 +601,6 @@ private:
/// that ongoing state information will not be lost if the object
/// that originated the asynchronous call falls out of scope.
typedef boost::shared_ptr<Message> MessagePtr;
-typedef boost::shared_ptr<const Message> ConstMessagePtr;
/// Insert the \c Message as a string into stream.
///
diff --git a/src/lib/resolve/recursive_query.cc b/src/lib/resolve/recursive_query.cc
index ef3b259..34411ee 100644
--- a/src/lib/resolve/recursive_query.cc
+++ b/src/lib/resolve/recursive_query.cc
@@ -191,12 +191,13 @@ private:
// Info for (re)sending the query (the question and destination)
Question question_;
- // This is the query message got from client
- ConstMessagePtr query_message_;
-
// This is where we build and store our final answer
MessagePtr answer_message_;
+ // currently we use upstream as the current list of NS records
+ // we should differentiate between forwarding and resolving
+ boost::shared_ptr<AddressVector> upstream_;
+
// Test server - only used for testing. This takes precedence over all
// other servers if the port is non-zero.
std::pair<std::string, uint16_t> test_server_;
@@ -343,8 +344,13 @@ private:
}
}
- // 'general' send, ask the NSAS to give us an address.
+ // 'general' send; if we are in forwarder mode, send a query to
+ // a random nameserver in our forwarders list. If we are in
+ // recursive mode, ask the NSAS to give us an address.
void send(IOFetch::Protocol protocol = IOFetch::UDP) {
+ // If are in forwarder mode, send it to a random
+ // forwarder. If not, ask the NSAS for an address
+ const int uc = upstream_->size();
protocol_ = protocol; // Store protocol being used for this
if (test_server_.second != 0) {
dlog("Sending upstream query (" + question_.toText() +
@@ -356,6 +362,18 @@ private:
test_server_.second, buffer_, this,
query_timeout_);
io_.get_io_service().post(query);
+ } else if (uc > 0) {
+ // TODO: use boost, or rand()-utility function we provide
+ int serverIndex = rand() % uc;
+ dlog("Sending upstream query (" + question_.toText() +
+ ") to " + upstream_->at(serverIndex).first);
+ ++outstanding_events_;
+ gettimeofday(¤t_ns_qsent_time, NULL);
+ IOFetch query(protocol, io_, question_,
+ upstream_->at(serverIndex).first,
+ upstream_->at(serverIndex).second, buffer_, this,
+ query_timeout_);
+ io_.get_io_service().post(query);
} else {
// Ask the NSAS for an address for the current zone,
// the callback will call the actual sendTo()
@@ -530,6 +548,7 @@ public:
RunningQuery(IOService& io,
const Question& question,
MessagePtr answer_message,
+ boost::shared_ptr<AddressVector> upstream,
std::pair<std::string, uint16_t>& test_server,
OutputBufferPtr buffer,
isc::resolve::ResolverInterface::CallbackPtr cb,
@@ -541,8 +560,8 @@ public:
:
io_(io),
question_(question),
- query_message_(),
answer_message_(answer_message),
+ upstream_(upstream),
test_server_(test_server),
buffer_(buffer),
resolvercallback_(cb),
@@ -690,7 +709,8 @@ public:
incoming.fromWire(ibuf);
buffer_->clear();
- if (incoming.getRcode() == Rcode::NOERROR()) {
+ if (recursive_mode() &&
+ incoming.getRcode() == Rcode::NOERROR()) {
done_ = handleRecursiveAnswer(incoming);
} else {
isc::resolve::copyResponseMessage(incoming, answer_message_);
@@ -724,11 +744,13 @@ public:
} else if (!done_ && retries_--) {
// Query timed out, but we have some retries, so send again
dlog("Timeout for " + question_.toText() + " to " + current_ns_address.getAddress().toText() + ", resending query");
- current_ns_address.updateRTT(isc::nsas::AddressEntry::UNREACHABLE);
+ if (recursive_mode()) {
+ current_ns_address.updateRTT(isc::nsas::AddressEntry::UNREACHABLE);
+ }
send();
} else {
// We are either already done, or out of retries
- if (result == IOFetch::TIME_OUT) {
+ if (recursive_mode() && result == IOFetch::TIME_OUT) {
dlog("Timeout for " + question_.toText() + " to " + current_ns_address.getAddress().toText() + ", giving up");
current_ns_address.updateRTT(isc::nsas::AddressEntry::UNREACHABLE);
}
@@ -745,148 +767,12 @@ public:
void makeSERVFAIL() {
isc::resolve::makeErrorMessage(answer_message_, Rcode::SERVFAIL());
}
-};
-
-class ForwardQuery : public IOFetch::Callback {
-private:
- // The io service to handle async calls
- IOService& io_;
-
- // This is the query message got from client
- ConstMessagePtr query_message_;
-
- // This is where we build and store our final answer
- MessagePtr answer_message_;
-
- // List of nameservers to forward to
- boost::shared_ptr<AddressVector> upstream_;
-
- // Buffer to store the result.
- OutputBufferPtr buffer_;
-
- // This will be notified when we succeed or fail
- isc::resolve::ResolverInterface::CallbackPtr resolvercallback_;
-
- /*
- * TODO Do something more clever with timeouts. In the long term, some
- * computation of average RTT, increase with each retry, etc.
- */
- // Timeout information
- int query_timeout_;
-
- // TODO: replace by our wrapper
- asio::deadline_timer client_timer;
- asio::deadline_timer lookup_timer;
-
- // If we have a client timeout, we send back an answer, but don't
- // stop. We use this variable to make sure we don't send another
- // answer if we do find one later (or if we have a lookup_timeout)
- bool answer_sent_;
-
- // send the query to the server.
- void send(IOFetch::Protocol protocol = IOFetch::UDP) {
- const int uc = upstream_->size();
- buffer_->clear();
- int serverIndex = rand() % uc;
- ConstQuestionPtr question = *(query_message_->beginQuestion());
- dlog("Sending upstream query (" + question->toText() +
- ") to " + upstream_->at(serverIndex).first);
- // Forward the query, create the IOFetch with
- // query message, so that query flags can be forwarded
- // together.
- IOFetch query(protocol, io_, query_message_,
- upstream_->at(serverIndex).first,
- upstream_->at(serverIndex).second,
- buffer_, this, query_timeout_);
-
- io_.get_io_service().post(query);
- }
-
-public:
- ForwardQuery(IOService& io,
- ConstMessagePtr query_message,
- MessagePtr answer_message,
- boost::shared_ptr<AddressVector> upstream,
- OutputBufferPtr buffer,
- isc::resolve::ResolverInterface::CallbackPtr cb,
- int query_timeout, int client_timeout, int lookup_timeout) :
- io_(io),
- query_message_(query_message),
- answer_message_(answer_message),
- upstream_(upstream),
- buffer_(buffer),
- resolvercallback_(cb),
- query_timeout_(query_timeout),
- client_timer(io.get_io_service()),
- lookup_timer(io.get_io_service()),
- answer_sent_(false)
- {
- // Setup the timer to stop trying (lookup_timeout)
- if (lookup_timeout >= 0) {
- lookup_timer.expires_from_now(
- boost::posix_time::milliseconds(lookup_timeout));
- lookup_timer.async_wait(boost::bind(&ForwardQuery::stop, this, false));
- }
-
- // Setup the timer to send an answer (client_timeout)
- if (client_timeout >= 0) {
- client_timer.expires_from_now(
- boost::posix_time::milliseconds(client_timeout));
- client_timer.async_wait(boost::bind(&ForwardQuery::clientTimeout, this));
- }
-
- send();
- }
-
- virtual void clientTimeout() {
- // Return a SERVFAIL, but do not stop until
- // we have an answer or timeout ourselves
- isc::resolve::makeErrorMessage(answer_message_,
- Rcode::SERVFAIL());
- if (!answer_sent_) {
- answer_sent_ = true;
- resolvercallback_->success(answer_message_);
- }
- }
-
- virtual void stop(bool resume) {
- // if we cancel our timers, we will still get an event for
- // that, so we cannot delete ourselves just yet (those events
- // would be bound to a deleted object)
- // cancel them one by one, both cancels should get us back
- // here again.
- // same goes if we have an outstanding query (can't delete
- // until that one comes back to us)
- if (resume && !answer_sent_) {
- answer_sent_ = true;
- resolvercallback_->success(answer_message_);
- } else {
- resolvercallback_->failure();
- }
- if (lookup_timer.cancel() != 0) {
- return;
- }
- if (client_timer.cancel() != 0) {
- return;
- }
-
- delete this;
- }
-
- // This function is used as callback from DNSQuery.
- virtual void operator()(IOFetch::Result result) {
- // XXX is this the place for TCP retry?
- if (result != IOFetch::TIME_OUT) {
- // we got an answer
- Message incoming(Message::PARSE);
- InputBuffer ibuf(buffer_->getData(), buffer_->getLength());
- incoming.fromWire(ibuf);
- isc::resolve::copyResponseMessage(incoming, answer_message_);
- stop(true);
- } else {
- // timeout, give up for now
- stop(false);
- }
+
+ // Returns true if we are in 'recursive' mode
+ // Returns false if we are in 'forwarding' mode
+ // (i.e. if we have anything in upstream_)
+ bool recursive_mode() const {
+ return upstream_->empty();
}
};
@@ -929,7 +815,7 @@ RecursiveQuery::resolve(const QuestionPtr& question,
} else {
dlog("Message not found in cache, starting recursive query");
// It will delete itself when it is done
- new RunningQuery(io, *question, answer_message,
+ new RunningQuery(io, *question, answer_message, upstream_,
test_server_, buffer, callback,
query_timeout_, client_timeout_,
lookup_timeout_, retries_, nsas_,
@@ -983,7 +869,7 @@ RecursiveQuery::resolve(const Question& question,
} else {
dlog("Message not found in cache, starting recursive query");
// It will delete itself when it is done
- new RunningQuery(io, question, answer_message,
+ new RunningQuery(io, question, answer_message, upstream_,
test_server_, buffer, crs, query_timeout_,
client_timeout_, lookup_timeout_, retries_,
nsas_, cache_, rtt_recorder_);
@@ -991,36 +877,5 @@ RecursiveQuery::resolve(const Question& question,
}
}
-void
-RecursiveQuery::forward(ConstMessagePtr query_message,
- MessagePtr answer_message,
- OutputBufferPtr buffer,
- DNSServer* server,
- isc::resolve::ResolverInterface::CallbackPtr callback)
-{
- // XXX: eventually we will need to be able to determine whether
- // the message should be sent via TCP or UDP, or sent initially via
- // UDP and then fall back to TCP on failure, but for the moment
- // we're only going to handle UDP.
- IOService& io = dns_service_.getIOService();
-
- if (!callback) {
- callback.reset(new isc::resolve::ResolverCallbackServer(server));
- }
-
- // TODO: general 'prepareinitialanswer'
- answer_message->setOpcode(isc::dns::Opcode::QUERY());
- ConstQuestionPtr question = *query_message->beginQuestion();
- answer_message->addQuestion(*question);
-
- // implement the simplest forwarder, which will pass
- // everything throught without interpretation, except
- // QID, port number. The response will not be cached.
- // It will delete itself when it is done
- new ForwardQuery(io, query_message, answer_message,
- upstream_, buffer, callback, query_timeout_,
- client_timeout_, lookup_timeout_);
-}
-
} // namespace asiodns
} // namespace isc
diff --git a/src/lib/resolve/recursive_query.h b/src/lib/resolve/recursive_query.h
index b9fb80d..c082426 100644
--- a/src/lib/resolve/recursive_query.h
+++ b/src/lib/resolve/recursive_query.h
@@ -141,20 +141,6 @@ public:
isc::util::OutputBufferPtr buffer,
DNSServer* server);
- /// \brief Initiates forwarding for the given query.
- ///
- /// Others parameters are same with the parameters of
- /// function resolve().
- ///
- /// \param query_message the full query got from client.
- /// \param callback callback object
- void forward(isc::dns::ConstMessagePtr query_message,
- isc::dns::MessagePtr answer_message,
- isc::util::OutputBufferPtr buffer,
- DNSServer* server,
- isc::resolve::ResolverInterface::CallbackPtr callback =
- isc::resolve::ResolverInterface::CallbackPtr());
-
/// \brief Set Test Server
///
/// This method is *only* for unit testing the class. If set, it enables
diff --git a/src/lib/resolve/tests/recursive_query_unittest.cc b/src/lib/resolve/tests/recursive_query_unittest.cc
index 9f92e00..04a7803 100644
--- a/src/lib/resolve/tests/recursive_query_unittest.cc
+++ b/src/lib/resolve/tests/recursive_query_unittest.cc
@@ -37,7 +37,6 @@
#include <nsas/nameserver_address_store.h>
#include <cache/resolver_cache.h>
-#include <resolve/resolve.h>
// IMPORTANT: We shouldn't directly use ASIO definitions in this test.
// In particular, we must not include asio.hpp in this file.
@@ -580,12 +579,9 @@ TEST_F(RecursiveQueryTest, forwarderSend) {
singleAddress(TEST_IPV4_ADDR, port));
Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
- Message query_message(Message::RENDER);
- isc::resolve::initResponseMessage(q, query_message);
-
OutputBufferPtr buffer(new OutputBuffer(0));
MessagePtr answer(new Message(Message::RENDER));
- rq.forward(ConstMessagePtr(&query_message), answer, buffer, &server);
+ rq.resolve(q, answer, buffer, &server);
char data[4096];
size_t size = sizeof(data);
@@ -650,41 +646,8 @@ bool tryRead(int sock_, int recv_options, size_t max, int* num) {
return true;
}
-// Mock resolver callback for testing forward query.
-class MockResolverCallback : public isc::resolve::ResolverInterface::Callback {
-public:
- enum ResultValue {
- DEFAULT = 0,
- SUCCESS = 1,
- FAILURE = 2
- };
-
- MockResolverCallback(DNSServer* server):
- result(DEFAULT),
- server_(server->clone())
- {}
-
- ~MockResolverCallback() {
- delete server_;
- }
-
- void success(const isc::dns::MessagePtr response) {
- result = SUCCESS;
- server_->resume(true);
- }
-
- void failure() {
- result = FAILURE;
- server_->resume(false);
- }
- uint32_t result;
-private:
- DNSServer* server_;
-};
-
-// Test query timeout, set query timeout is lower than client timeout
-// and lookup timeout.
+// Test it tries the correct amount of times before giving up
TEST_F(RecursiveQueryTest, forwardQueryTimeout) {
// Prepare the service (we do not use the common setup, we do not answer
setDNSService();
@@ -706,20 +669,26 @@ TEST_F(RecursiveQueryTest, forwardQueryTimeout) {
Question question(Name("example.net"), RRClass::IN(), RRType::A());
OutputBufferPtr buffer(new OutputBuffer(0));
MessagePtr answer(new Message(Message::RENDER));
- Message query_message(Message::RENDER);
- isc::resolve::initResponseMessage(question, query_message);
+ query.resolve(question, answer, buffer, &server);
- boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
- query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
// Run the test
io_service_->run();
- EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
+
+ // Read up to 3 packets. Use some ad hoc timeout to prevent an infinite
+ // block (see also recvUDP()).
+ int recv_options = setSocketTimeout(sock_, 10, 0);
+ int num = 0;
+ bool read_success = tryRead(sock_, recv_options, 3, &num);
+
+ // The query should 'succeed' with an error response
+ EXPECT_TRUE(done);
+ EXPECT_EQ(3, num);
+ EXPECT_TRUE(read_success);
}
// If we set client timeout to lower than querytimeout, we should
-// get a failure answer
-// (no actual answer is given here yet. TODO the returned error message
-// should be tested)
+// get a failure answer, but still see retries
+// (no actual answer is given here yet)
TEST_F(RecursiveQueryTest, forwardClientTimeout) {
// Prepare the service (we do not use the common setup, we do not answer
setDNSService();
@@ -734,25 +703,36 @@ TEST_F(RecursiveQueryTest, forwardClientTimeout) {
// Do the answer
const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+ // Set it up to retry twice before client timeout fires
+ // Since the lookup timer has not fired, it should retry
+ // four times
RecursiveQuery query(*dns_service_,
*nsas_, cache_,
singleAddress(TEST_IPV4_ADDR, port),
singleAddress(TEST_IPV4_ADDR, port),
- 1000, 10, 4000, 4);
- Question q(Name("example.net"), RRClass::IN(), RRType::A());
+ 200, 480, 4000, 4);
+ Question question(Name("example.net"), RRClass::IN(), RRType::A());
OutputBufferPtr buffer(new OutputBuffer(0));
- Message query_message(Message::RENDER);
- isc::resolve::initResponseMessage(q, query_message);
+ query.resolve(question, answer, buffer, &server);
- boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
- query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
// Run the test
io_service_->run();
- EXPECT_EQ(callback->result, MockResolverCallback::SUCCESS);
+
+ // we know it'll fail, so make it a shorter timeout
+ int recv_options = setSocketTimeout(sock_, 1, 0);
+
+ // Try to read 4 times
+ int num = 0;
+ bool read_success = tryRead(sock_, recv_options, 4, &num);
+
+ // The query should fail
+ EXPECT_TRUE(done1);
+ EXPECT_EQ(3, num);
+ EXPECT_FALSE(read_success);
}
-// If we set lookup timeout to lower than querytimeout, the lookup
-// will fail.
+// If we set lookup timeout to lower than querytimeout*retries, we should
+// fail before the full amount of retries
TEST_F(RecursiveQueryTest, forwardLookupTimeout) {
// Prepare the service (we do not use the common setup, we do not answer
setDNSService();
@@ -768,22 +748,30 @@ TEST_F(RecursiveQueryTest, forwardLookupTimeout) {
// Do the answer
const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+ // Set up the test so that it will retry 5 times, but the lookup
+ // timeout will fire after only 3 normal timeouts
RecursiveQuery query(*dns_service_,
*nsas_, cache_,
singleAddress(TEST_IPV4_ADDR, port),
singleAddress(TEST_IPV4_ADDR, port),
- 1000, 4000, 10, 5);
+ 200, 4000, 480, 5);
Question question(Name("example.net"), RRClass::IN(), RRType::A());
OutputBufferPtr buffer(new OutputBuffer(0));
+ query.resolve(question, answer, buffer, &server);
- Message query_message(Message::RENDER);
- isc::resolve::initResponseMessage(question, query_message);
-
- boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
- query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
// Run the test
io_service_->run();
- EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
+
+ int recv_options = setSocketTimeout(sock_, 1, 0);
+
+ // Try to read 5 times, should stop after 3 reads
+ int num = 0;
+ bool read_success = tryRead(sock_, recv_options, 5, &num);
+
+ // The query should fail and respond with an error
+ EXPECT_TRUE(done);
+ EXPECT_EQ(3, num);
+ EXPECT_FALSE(read_success);
}
// Set everything very low and see if this doesn't cause weird
@@ -803,6 +791,8 @@ TEST_F(RecursiveQueryTest, lowtimeouts) {
// Do the answer
const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+ // Set up the test so that it will retry 5 times, but the lookup
+ // timeout will fire after only 3 normal timeouts
RecursiveQuery query(*dns_service_,
*nsas_, cache_,
singleAddress(TEST_IPV4_ADDR, port),
@@ -810,15 +800,21 @@ TEST_F(RecursiveQueryTest, lowtimeouts) {
1, 1, 1, 1);
Question question(Name("example.net"), RRClass::IN(), RRType::A());
OutputBufferPtr buffer(new OutputBuffer(0));
+ query.resolve(question, answer, buffer, &server);
- Message query_message(Message::RENDER);
- isc::resolve::initResponseMessage(question, query_message);
-
- boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
- query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
// Run the test
io_service_->run();
- EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
+
+ int recv_options = setSocketTimeout(sock_, 1, 0);
+
+ // Try to read 5 times, should stop after 3 reads
+ int num = 0;
+ bool read_success = tryRead(sock_, recv_options, 5, &num);
+
+ // The query should fail and respond with an error
+ EXPECT_TRUE(done);
+ EXPECT_EQ(1, num);
+ EXPECT_FALSE(read_success);
}
// as mentioned above, we need a more better framework for this,
More information about the bind10-changes
mailing list