BIND 10 master, updated. 8cb9313e68bb0a7867e9c1dc6e51de1b3763fe95 [master] Fixed some merge misses for trac494

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Feb 3 17:08:03 UTC 2011


The branch, master has been updated
       via  8cb9313e68bb0a7867e9c1dc6e51de1b3763fe95 (commit)
       via  75692d6d89837df09f1e2c74d0fd069553fa13d8 (commit)
       via  cc5136da5b04edb3cdc66e90f2f60f0f0291e8ff (commit)
       via  430e0e89ec5ab05bdbbd43b5fba9c93bdcf8f6c9 (commit)
       via  640640363d2a29cc0f4ab8151ca5c02dc9f7c361 (commit)
       via  b7c5f0703226ea1f68af4802e4b410cc42e98144 (commit)
       via  cf6de64ab83a1db3a71aa065c1d247462f236ea8 (commit)
       via  5f6cbcc31cc0f16af49dd433ac96da967d200d6c (commit)
       via  923977389a20aa0396dccec4867f3721fc95a4bd (commit)
       via  d8a7320161d314a5863183a063d0e00fdd1017bd (commit)
       via  f0a43d242f48103eec0703d7081522ec0f2225a9 (commit)
       via  a6f9d5cd07ea1b21641232312cc15adcce91f1ec (commit)
       via  2363b50bc04e0218e185561a4e198f21e8783905 (commit)
       via  9f172776a92413f7ba09fae87c98522c3d55fe63 (commit)
       via  8a175757cd9b46205b7118c3e7fad72883f130e5 (commit)
      from  254f34910f282862727eaed7557657726887439d (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 8cb9313e68bb0a7867e9c1dc6e51de1b3763fe95
Author: Jelte Jansen <jelte at isc.org>
Date:   Thu Feb 3 18:06:58 2011 +0100

    [master] Fixed some merge misses for trac494

commit 75692d6d89837df09f1e2c74d0fd069553fa13d8
Merge: 254f34910f282862727eaed7557657726887439d cc5136da5b04edb3cdc66e90f2f60f0f0291e8ff
Author: Jelte Jansen <jelte at isc.org>
Date:   Thu Feb 3 17:25:38 2011 +0100

    Merge branch 'trac494'
    
    Conflicts:
    	src/lib/asiolink/asiolink.cc

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    2 +
 src/bin/resolver/resolver.cc                       |   21 ++++-
 src/bin/resolver/resolver.h                        |    8 ++-
 src/lib/Makefile.am                                |    4 +-
 src/lib/asiolink/Makefile.am                       |    1 +
 src/lib/asiolink/asiolink.cc                       |   51 ++++++++---
 src/lib/asiolink/asiolink.h                        |   54 ++++++++---
 src/lib/asiolink/tests/asiolink_unittest.cc        |   12 +-
 src/lib/nsas/Makefile.am                           |    1 -
 src/lib/nsas/nameserver_address_store.cc           |    9 +-
 src/lib/nsas/nameserver_address_store.h            |    7 +-
 src/lib/nsas/nameserver_entry.cc                   |   26 ++++-
 src/lib/nsas/nameserver_entry.h                    |    8 +-
 src/lib/nsas/resolver_interface.h                  |   78 ----------------
 .../tests/nameserver_address_store_unittest.cc     |    2 +-
 src/lib/nsas/tests/nameserver_address_unittest.cc  |    6 +-
 src/lib/nsas/tests/nameserver_entry_unittest.cc    |   16 ++--
 src/lib/nsas/tests/nsas_test.h                     |   31 +++++--
 src/lib/nsas/tests/zone_entry_unittest.cc          |    9 +-
 src/lib/nsas/zone_entry.cc                         |   22 ++++-
 src/lib/nsas/zone_entry.h                          |    8 +-
 src/lib/resolve/Makefile.am                        |   17 ++++
 .../tests/run_unittests.cc => resolve/resolve.h}   |   13 +--
 .../resolver_callback.cc}                          |   26 +++--
 src/lib/resolve/resolver_callback.h                |   48 ++++++++++
 src/lib/resolve/resolver_interface.h               |   98 ++++++++++++++++++++
 src/lib/{exceptions => resolve}/tests/Makefile.am  |   13 ++-
 .../resolve/tests/resolver_callback_unittest.cc    |   90 ++++++++++++++++++
 src/lib/{nsas => resolve}/tests/run_unittests.cc   |    2 -
 src/lib/testutils/srv_test.cc                      |    1 +
 src/lib/testutils/srv_test.h                       |    2 +-
 31 files changed, 500 insertions(+), 186 deletions(-)
 delete mode 100644 src/lib/nsas/resolver_interface.h
 create mode 100644 src/lib/resolve/Makefile.am
 copy src/lib/{cc/tests/run_unittests.cc => resolve/resolve.h} (76%)
 copy src/lib/{nsas/nameserver_address.cc => resolve/resolver_callback.cc} (67%)
 create mode 100644 src/lib/resolve/resolver_callback.h
 create mode 100644 src/lib/resolve/resolver_interface.h
 copy src/lib/{exceptions => resolve}/tests/Makefile.am (66%)
 create mode 100644 src/lib/resolve/tests/resolver_callback_unittest.cc
 copy src/lib/{nsas => resolve}/tests/run_unittests.cc (97%)

-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index f08f044..7de33f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -652,6 +652,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/datasrc/tests/Makefile
                  src/lib/xfr/Makefile
                  src/lib/log/Makefile
+                 src/lib/resolve/Makefile
+                 src/lib/resolve/tests/Makefile
                  src/lib/testutils/Makefile
                  src/lib/testutils/testdata/Makefile
                  src/lib/nsas/Makefile
diff --git a/src/bin/resolver/resolver.cc b/src/bin/resolver/resolver.cc
index 4fd887e..9e9bbd4 100644
--- a/src/bin/resolver/resolver.cc
+++ b/src/bin/resolver/resolver.cc
@@ -131,6 +131,9 @@ public:
         }
     }
 
+    void resolve(const isc::dns::QuestionPtr& question,
+        const isc::resolve::ResolverInterface::CallbackPtr& callback);
+
     void processNormalQuery(const Question& question,
                             MessagePtr answer_message,
                             OutputBufferPtr buffer,
@@ -333,7 +336,6 @@ Resolver::~Resolver() {
     delete checkin_;
     delete dns_lookup_;
     delete dns_answer_;
-    dlog("Deleting the Resolver",true);
 }
 
 void
@@ -352,6 +354,14 @@ Resolver::getConfigSession() const {
 }
 
 void
+Resolver::resolve(const isc::dns::QuestionPtr& question,
+    const isc::resolve::ResolverInterface::CallbackPtr& callback)
+{
+    impl_->resolve(question, callback);
+}
+
+
+void
 Resolver::processMessage(const IOMessage& io_message,
                          MessagePtr query_message,
                          MessagePtr answer_message,
@@ -435,13 +445,20 @@ Resolver::processMessage(const IOMessage& io_message,
 }
 
 void
+ResolverImpl::resolve(const QuestionPtr& question,
+    const isc::resolve::ResolverInterface::CallbackPtr& callback)
+{
+    rec_query_->resolve(question, callback);
+}
+
+void
 ResolverImpl::processNormalQuery(const Question& question,
                                  MessagePtr answer_message,
                                  OutputBufferPtr buffer,
                                  DNSServer* server)
 {
     dlog("Processing normal query");
-    rec_query_->sendQuery(question, answer_message, buffer, server);
+    rec_query_->resolve(question, answer_message, buffer, server);
 }
 
 namespace {
diff --git a/src/bin/resolver/resolver.h b/src/bin/resolver/resolver.h
index 5bce24d..3a5219f 100644
--- a/src/bin/resolver/resolver.h
+++ b/src/bin/resolver/resolver.h
@@ -24,6 +24,8 @@
 
 #include <asiolink/asiolink.h>
 
+#include <resolve/resolver_interface.h>
+
 class ResolverImpl;
 
 /**
@@ -35,7 +37,7 @@ class ResolverImpl;
  * answer. It doesn't really know about chasing referrals and similar, it
  * simply plugs the parts that know into the network handling code.
  */
-class Resolver {
+class Resolver : public isc::resolve::ResolverInterface {
     ///
     /// \name Constructors, Assignment Operator and Destructor.
     ///
@@ -51,6 +53,10 @@ public:
     ~Resolver();
     //@}
 
+    virtual void resolve(
+        const isc::dns::QuestionPtr& question,
+        const isc::resolve::ResolverInterface::CallbackPtr& callback);
+
     /// \brief Process an incoming DNS message, then signal 'server' to resume 
     ///
     /// A DNS query (or other message) has been received by a \c DNSServer
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 866ca65..b7b80bf 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,2 +1,2 @@
-SUBDIRS = exceptions dns cc config datasrc python xfr bench log asiolink \
-    testutils nsas
+SUBDIRS = exceptions dns cc config datasrc python xfr bench log \
+          resolve asiolink testutils nsas
diff --git a/src/lib/asiolink/Makefile.am b/src/lib/asiolink/Makefile.am
index 26d9a68..99b3c66 100644
--- a/src/lib/asiolink/Makefile.am
+++ b/src/lib/asiolink/Makefile.am
@@ -32,3 +32,4 @@ libasiolink_la_CXXFLAGS += -Wno-error
 endif
 libasiolink_la_CPPFLAGS = $(AM_CPPFLAGS)
 libasiolink_la_LIBADD = $(top_builddir)/src/lib/log/liblog.la
+libasiolink_la_LIBADD += $(top_builddir)/src/lib/resolve/libresolve.la
diff --git a/src/lib/asiolink/asiolink.cc b/src/lib/asiolink/asiolink.cc
index be86a5f..9adb52b 100644
--- a/src/lib/asiolink/asiolink.cc
+++ b/src/lib/asiolink/asiolink.cc
@@ -31,13 +31,15 @@
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/rcode.h>
+#include <dns/opcode.h>
 
 #include <asiolink/asiolink.h>
 #include <asiolink/internal/tcpdns.h>
 #include <asiolink/internal/udpdns.h>
 
-#include <log/dummylog.h>
+#include <resolve/resolve.h>
 
+#include <log/dummylog.h>
 
 using namespace asio;
 using asio::ip::udp;
@@ -360,7 +362,8 @@ private:
     OutputBufferPtr buffer_;
 
     // Server to notify when we succeed or fail
-    shared_ptr<DNSServer> server_;
+    //shared_ptr<DNSServer> server_;
+    isc::resolve::ResolverInterface::CallbackPtr resolvercallback_;
 
     /*
      * TODO Do something more clever with timeouts. In the long term, some
@@ -487,7 +490,8 @@ public:
     RunningQuery(asio::io_service& io, const Question &question,
         MessagePtr answer_message, shared_ptr<AddressVector> upstream,
         shared_ptr<AddressVector> upstream_root,
-        OutputBufferPtr buffer, DNSServer* server,
+        OutputBufferPtr buffer,
+        isc::resolve::ResolverInterface::CallbackPtr cb,
         int query_timeout, int client_timeout, int lookup_timeout,
         unsigned retries) :
         io_(io),
@@ -496,7 +500,7 @@ public:
         upstream_(upstream),
         upstream_root_(upstream_root),
         buffer_(buffer),
-        server_(server->clone()),
+        resolvercallback_(cb),
         query_timeout_(query_timeout),
         retries_(retries),
         client_timer(io),
@@ -557,7 +561,11 @@ public:
         // same goes if we have an outstanding query (can't delete
         // until that one comes back to us)
         done_ = true;
-        server_->resume(resume);
+        if (resume) {
+            resolvercallback_->success(answer_message_);
+        } else {
+            resolvercallback_->failure();
+        }
         if (lookup_timer.cancel() != 0) {
             return;
         }
@@ -589,14 +597,14 @@ public:
             }
             
             if (done_) {
-                stop(result == UDPQuery::SUCCESS);
+                stop(true);
             }
         } else if (!done_ && retries_--) {
             // We timed out, but we have some retries, so send again
             dlog("Timeout, resending query");
             send();
         } else {
-            // We are done
+            // out of retries, give up for now
             stop(false);
         }
     }
@@ -605,19 +613,38 @@ public:
 }
 
 void
-RecursiveQuery::sendQuery(const Question& question,
-                          MessagePtr answer_message,
-                          OutputBufferPtr buffer,
-                          DNSServer* server)
+RecursiveQuery::resolve(const isc::dns::QuestionPtr& question,
+    const isc::resolve::ResolverInterface::CallbackPtr callback)
+{
+    asio::io_service& io = dns_service_.get_io_service();
+
+    MessagePtr answer_message(new Message(Message::RENDER));
+    OutputBufferPtr buffer(new OutputBuffer(0));
+    
+    // It will delete itself when it is done
+    new RunningQuery(io, *question, answer_message, upstream_,
+                     upstream_root_, buffer, callback, query_timeout_,
+                     client_timeout_, lookup_timeout_, retries_);
+}
+
+void
+RecursiveQuery::resolve(const Question& question,
+                        MessagePtr answer_message,
+                        OutputBufferPtr buffer,
+                        DNSServer* server)
 {
     // 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.
     asio::io_service& io = dns_service_.get_io_service();
+
+    isc::resolve::ResolverInterface::CallbackPtr crs(
+        new isc::resolve::ResolverCallbackServer(server));
+    
     // It will delete itself when it is done
     new RunningQuery(io, question, answer_message, upstream_, upstream_root_,
-                         buffer, server, query_timeout_, client_timeout_,
+                         buffer, crs, query_timeout_, client_timeout_,
                          lookup_timeout_, retries_);
 }
 
diff --git a/src/lib/asiolink/asiolink.h b/src/lib/asiolink/asiolink.h
index 5e46dfc..44ff383 100644
--- a/src/lib/asiolink/asiolink.h
+++ b/src/lib/asiolink/asiolink.h
@@ -31,6 +31,7 @@
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/question.h>
+#include <dns/rcode.h>
 
 #include <exceptions/exceptions.h>
 
@@ -39,6 +40,8 @@
 #include <asiolink/iomessage.h>
 #include <asiolink/iosocket.h>
 
+#include <resolve/resolver_interface.h>
+
 namespace asio {
 // forward declaration for IOService::get_io_service() below
 class io_service;
@@ -99,6 +102,7 @@ class DNSServiceImpl;
 struct IOServiceImpl;
 struct IntervalTimerImpl;
 
+
 /// \brief An exception that is thrown if an error occurs within the IO
 /// module.  This is mainly intended to be a wrapper exception class for
 /// ASIO specific exceptions.
@@ -529,11 +533,13 @@ class RecursiveQuery {
     ///
     //@{
 public:
-    /// \brief Constructor for use when acting as a forwarder
+    /// \brief Constructor
     ///
     /// This is currently the only way to construct \c RecursiveQuery
-    /// object.  The addresses of the forward nameservers is specified,
-    /// and every upstream query will be sent to one random address.
+    /// object. If the addresses of the forward nameservers is specified,
+    /// and every upstream query will be sent to one random address, and
+    /// the result sent back directly. If not, it will do full resolving.
+    ///
     /// \param dns_service The DNS Service to perform the recursive
     ///        query on.
     /// \param upstream Addresses and ports of the upstream servers
@@ -556,20 +562,42 @@ public:
                    unsigned retries = 3);
     //@}
 
-    /// \brief Initiates an upstream query in the \c RecursiveQuery object.
+    /// \brief Initiate resolving
+    /// 
+    /// When sendQuery() is called, a (set of) message(s) is sent
+    /// asynchronously. If upstream servers are set, one is chosen
+    /// and the response (if any) from that server will be returned.
+    ///
+    /// If not upstream is set, a root server is chosen from the
+    /// root_servers, and the RunningQuery shall do a full resolve
+    /// (i.e. if the answer is a delegation, it will be followed, etc.)
+    /// until there is an answer or an error.
+    ///
+    /// When there is a response or an error and we give up, the given
+    /// CallbackPtr object shall be called (with either success() or
+    /// failure(). See ResolverInterface::Callback for more information.
+    ///
+    /// \param question The question being answered <qname/qclass/qtype>
+    /// \param callback Callback object. See
+    ///        \c ResolverInterface::Callback for more information
+    void resolve(const isc::dns::QuestionPtr& question,
+                 const isc::resolve::ResolverInterface::CallbackPtr callback);
+
+
+    /// \brief Initiates resolving for the given question.
     ///
-    /// When sendQuery() is called, a message is sent asynchronously to
-    /// 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.
+    /// This actually calls the previous sendQuery() with a default
+    /// callback object, which calls resume() on the given DNSServer
+    /// object.
     ///
     /// \param question The question being answered <qname/qclass/qtype>
-    /// \param buffer An output buffer into which the response can be copied
+    /// \param answer_message An output Message into which the final response will be copied
+    /// \param buffer An output buffer into which the intermediate responses will be copied
     /// \param server A pointer to the \c DNSServer object handling the client
-    void sendQuery(const isc::dns::Question& question,
-                   isc::dns::MessagePtr answer_message,
-                   isc::dns::OutputBufferPtr buffer,
-                   DNSServer* server);
+    void resolve(const isc::dns::Question& question,
+                 isc::dns::MessagePtr answer_message,
+                 isc::dns::OutputBufferPtr buffer,
+                 DNSServer* server);
 private:
     DNSService& dns_service_;
     boost::shared_ptr<std::vector<std::pair<std::string, uint16_t> > >
diff --git a/src/lib/asiolink/tests/asiolink_unittest.cc b/src/lib/asiolink/tests/asiolink_unittest.cc
index 2f18f7d..393e417 100644
--- a/src/lib/asiolink/tests/asiolink_unittest.cc
+++ b/src/lib/asiolink/tests/asiolink_unittest.cc
@@ -678,7 +678,7 @@ TEST_F(ASIOLinkTest, forwarderSend) {
     Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
     OutputBufferPtr buffer(new OutputBuffer(0));
     MessagePtr answer(new Message(Message::RENDER));
-    rq.sendQuery(q, answer, buffer, &server);
+    rq.resolve(q, answer, buffer, &server);
 
     char data[4096];
     size_t size = sizeof(data);
@@ -765,7 +765,7 @@ TEST_F(ASIOLinkTest, forwardQueryTimeout) {
     Question question(Name("example.net"), RRClass::IN(), RRType::A());
     OutputBufferPtr buffer(new OutputBuffer(0));
     MessagePtr answer(new Message(Message::RENDER));
-    query.sendQuery(question, answer, buffer, &server);
+    query.resolve(question, answer, buffer, &server);
 
     // Run the test
     io_service_->run();
@@ -808,7 +808,7 @@ TEST_F(ASIOLinkTest, forwardClientTimeout) {
                          50, 120, 1000, 3);
     Question question(Name("example.net"), RRClass::IN(), RRType::A());
     OutputBufferPtr buffer(new OutputBuffer(0));
-    query.sendQuery(question, answer, buffer, &server);
+    query.resolve(question, answer, buffer, &server);
 
     // Run the test
     io_service_->run();
@@ -854,7 +854,7 @@ TEST_F(ASIOLinkTest, forwardLookupTimeout) {
                          50, 4000, 120, 5);
     Question question(Name("example.net"), RRClass::IN(), RRType::A());
     OutputBufferPtr buffer(new OutputBuffer(0));
-    query.sendQuery(question, answer, buffer, &server);
+    query.resolve(question, answer, buffer, &server);
 
     // Run the test
     io_service_->run();
@@ -888,7 +888,7 @@ TEST_F(ASIOLinkTest, DISABLED_recursiveSendOk) {
     Question q(Name("www.isc.org"), RRClass::IN(), RRType::A());
     OutputBufferPtr buffer(new OutputBuffer(0));
     MessagePtr answer(new Message(Message::RENDER));
-    rq.sendQuery(q, answer, buffer, &server);
+    rq.resolve(q, answer, buffer, &server);
     io_service_->run();
 
     // Check that the answer we got matches the one we wanted
@@ -913,7 +913,7 @@ TEST_F(ASIOLinkTest, DISABLED_recursiveSendNXDOMAIN) {
     Question q(Name("wwwdoesnotexist.isc.org"), RRClass::IN(), RRType::A());
     OutputBufferPtr buffer(new OutputBuffer(0));
     MessagePtr answer(new Message(Message::RENDER));
-    rq.sendQuery(q, answer, buffer, &server);
+    rq.resolve(q, answer, buffer, &server);
     io_service_->run();
 
     // Check that the answer we got matches the one we wanted
diff --git a/src/lib/nsas/Makefile.am b/src/lib/nsas/Makefile.am
index 02f4132..a88bd22 100644
--- a/src/lib/nsas/Makefile.am
+++ b/src/lib/nsas/Makefile.am
@@ -35,7 +35,6 @@ libnsas_la_SOURCES += nsas_entry.h nsas_types.h
 libnsas_la_SOURCES += zone_entry.cc zone_entry.h
 libnsas_la_SOURCES += fetchable.h
 libnsas_la_SOURCES += address_request_callback.h
-libnsas_la_SOURCES += resolver_interface.h
 libnsas_la_SOURCES += random_number_generator.h
 
 CLEANFILES = *.gcno *.gcda
diff --git a/src/lib/nsas/nameserver_address_store.cc b/src/lib/nsas/nameserver_address_store.cc
index e52047a..0ba9c8e 100644
--- a/src/lib/nsas/nameserver_address_store.cc
+++ b/src/lib/nsas/nameserver_address_store.cc
@@ -56,8 +56,8 @@ namespace nsas {
 // hash table, on the assumption that three elements is the longest linear
 // search we want to do when looking up names in the hash table.
 NameserverAddressStore::NameserverAddressStore(
-    boost::shared_ptr<ResolverInterface> resolver, uint32_t zonehashsize,
-    uint32_t nshashsize) :
+    boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
+    uint32_t zonehashsize, uint32_t nshashsize) :
     zone_hash_(new HashTable<ZoneEntry>(new NsasEntryCompare<ZoneEntry>,
         zonehashsize)),
     nameserver_hash_(new HashTable<NameserverEntry>(
@@ -78,8 +78,9 @@ namespace {
  * called at all to create the object, just call the function.
  */
 boost::shared_ptr<ZoneEntry>
-newZone(const boost::shared_ptr<ResolverInterface>* resolver, const string* zone,
-    const RRClass* class_code,
+newZone(
+    const boost::shared_ptr<isc::resolve::ResolverInterface>* resolver,
+    const string* zone, const RRClass* class_code,
     const boost::shared_ptr<HashTable<NameserverEntry> >* ns_hash,
     const boost::shared_ptr<LruList<NameserverEntry> >* ns_lru)
 {
diff --git a/src/lib/nsas/nameserver_address_store.h b/src/lib/nsas/nameserver_address_store.h
index b435d12..f183871 100644
--- a/src/lib/nsas/nameserver_address_store.h
+++ b/src/lib/nsas/nameserver_address_store.h
@@ -20,6 +20,8 @@
 
 #include <boost/shared_ptr.hpp>
 
+#include <resolve/resolver_interface.h>
+
 #include "nsas_types.h"
 
 namespace isc {
@@ -62,7 +64,8 @@ public:
     /// value of 3001 is the first prime number over 3000, and by implication,
     /// there is an assumption that there will be more nameservers than zones
     /// in the store.
-    NameserverAddressStore(boost::shared_ptr<ResolverInterface> resolver,
+    NameserverAddressStore(
+        boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
         uint32_t zonehashsize = 1009, uint32_t nshashsize = 3001);
 
     /// \brief Destructor
@@ -105,7 +108,7 @@ protected:
     boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru_;
     // The resolver we use
 private:
-    boost::shared_ptr<ResolverInterface> resolver_;
+    boost::shared_ptr<isc::resolve::ResolverInterface> resolver_;
     //}@
 };
 
diff --git a/src/lib/nsas/nameserver_entry.cc b/src/lib/nsas/nameserver_entry.cc
index e48b9fc..53f4233 100644
--- a/src/lib/nsas/nameserver_entry.cc
+++ b/src/lib/nsas/nameserver_entry.cc
@@ -30,12 +30,14 @@
 #include <dns/name.h>
 #include <dns/rrclass.h>
 #include <dns/rrttl.h>
+#include <dns/rcode.h>
+#include <dns/opcode.h>
 #include <dns/question.h>
+#include <resolve/resolver_interface.h>
 
 #include "address_entry.h"
 #include "nameserver_address.h"
 #include "nameserver_entry.h"
-#include "resolver_interface.h"
 
 using namespace asiolink;
 using namespace isc::nsas;
@@ -199,7 +201,8 @@ NameserverEntry::setAddressUnreachable(const IOAddress& address) {
  * fed back trough this. It holds a shared pointer to the entry so it is not
  * destroyed too soon.
  */
-class NameserverEntry::ResolverCallback : public ResolverInterface::Callback {
+class NameserverEntry::ResolverCallback :
+        public isc::resolve::ResolverInterface::Callback {
     public:
         ResolverCallback(boost::shared_ptr<NameserverEntry> entry,
             AddressFamily family, const RRType& type) :
@@ -213,11 +216,22 @@ class NameserverEntry::ResolverCallback : public ResolverInterface::Callback {
          * This extracts the addresses out from the response and puts them
          * inside the entry. It tries to reuse the address entries from before (if there were any), to keep their RTTs.
          */
-        virtual void success(const boost::shared_ptr<AbstractRRset>& response) {
+        virtual void success(MessagePtr response_message) {
             time_t now = time(NULL);
 
             Lock lock(entry_->mutex_);
 
+            // TODO: find the correct RRset, not simply the first
+            if (!response_message ||
+                response_message->getRcode() != isc::dns::Rcode::NOERROR() ||
+                response_message->getRRCount(isc::dns::Message::SECTION_ANSWER) == 0) {
+                failureInternal(lock);
+            }
+                
+            isc::dns::RRsetIterator rrsi =
+                response_message->beginSection(isc::dns::Message::SECTION_ANSWER);
+            const isc::dns::RRsetPtr response = *rrsi;
+            
             vector<AddressEntry> entries;
 
             if (response->getType() != type_ ||
@@ -363,7 +377,8 @@ class NameserverEntry::ResolverCallback : public ResolverInterface::Callback {
 };
 
 void
-NameserverEntry::askIP(boost::shared_ptr<ResolverInterface> resolver,
+NameserverEntry::askIP(
+    boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
     const RRType& type, AddressFamily family)
 {
     QuestionPtr question(new Question(Name(getName()), RRClass(getClass()),
@@ -374,7 +389,8 @@ NameserverEntry::askIP(boost::shared_ptr<ResolverInterface> resolver,
 }
 
 void
-NameserverEntry::askIP(boost::shared_ptr<ResolverInterface> resolver,
+NameserverEntry::askIP(
+    boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
     boost::shared_ptr<Callback> callback, AddressFamily family)
 {
     Lock lock(mutex_);
diff --git a/src/lib/nsas/nameserver_entry.h b/src/lib/nsas/nameserver_entry.h
index 1024b7b..9a8e542 100644
--- a/src/lib/nsas/nameserver_entry.h
+++ b/src/lib/nsas/nameserver_entry.h
@@ -36,13 +36,14 @@
 #include <dns/rrset.h>
 #include <dns/rrtype.h>
 
+#include <resolve/resolver_interface.h>
+
 #include "address_entry.h"
 #include "asiolink.h"
 #include "nsas_types.h"
 #include "hash_key.h"
 #include "lru_list.h"
 #include "fetchable.h"
-#include "resolver_interface.h"
 #include "nsas_entry.h"
 #include "nameserver_address.h"
 
@@ -84,7 +85,6 @@ public:
 };
 
 class ZoneEntry;
-class ResolverInterface;
 
 /// \brief Nameserver Entry
 ///
@@ -247,7 +247,7 @@ public:
      *     even when there are addresses, if there are no addresses for this
      *     family.
      */
-    void askIP(boost::shared_ptr<ResolverInterface> resolver,
+    void askIP(boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
         boost::shared_ptr<Callback> callback, AddressFamily family);
     //@}
 
@@ -279,7 +279,7 @@ private:
     /// \short Private version that does the actual asking of one address type
     ///
     /// Call unlocked.
-    void askIP(boost::shared_ptr<ResolverInterface> resolver,
+    void askIP(boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
         const isc::dns::RRType&, AddressFamily);
 };
 
diff --git a/src/lib/nsas/resolver_interface.h b/src/lib/nsas/resolver_interface.h
deleted file mode 100644
index 7f93487..0000000
--- a/src/lib/nsas/resolver_interface.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2010  CZ NIC
-//
-// 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 __RESOLVER_INTERFACE_H
-#define __RESOLVER_INTERFACE_H
-
-#include <dns/message.h>
-#include <dns/rrset.h>
-
-/**
- * \file resolver_interface.h
- * \short Temporary interface to resolver.
- *
- * This file contains a dummy interface for the resolver, which does not yet
- * exist. When the resolver appears, this file should either wrap its
- * interface or, better, be removed completely.
- */
-
-namespace isc {
-namespace nsas {
-
-/**
- * \short Abstract interface to the resolver.
- *
- * Abstract interface to the resolver. The NameserverAddressStore uses this
- * to ask for addresses. It is here because resolver does not yet exist.
- *
- * It is abstract to allow tests pass dummy resolvers.
- */
-class ResolverInterface {
-    public:
-        /// \short An abstract callback when data from resolver are ready.
-        class Callback {
-            public:
-                /// \short Some data arrived.
-                virtual void success(
-                    const boost::shared_ptr<isc::dns::AbstractRRset>&
-                    response) = 0;
-                /**
-                 * \short No data available.
-                 *
-                 * \todo Pass some reason.
-                 */
-                virtual void failure() = 0;
-                /// \short Virtual destructor, so descendants are cleaned up
-                virtual ~ Callback() {};
-        };
-        typedef boost::shared_ptr<Callback> CallbackPtr;
-        /**
-         * \short Ask a question.
-         *
-         * Asks the resolver a question. Once the answer is ready
-         * the callback is called.
-         *
-         * \param question What to ask. The resolver will decide who.
-         * \param callback What should happen when the answer is ready.
-         */
-        virtual void resolve(const isc::dns::QuestionPtr& question,
-            const CallbackPtr& callback) = 0;
-        /// \short Virtual destructor, so descendants are properly cleaned up
-        virtual ~ ResolverInterface() {}
-};
-
-} // namespace nsas
-} // namespace isc
-
-#endif //__RESOLVER_INTERFACE_H
diff --git a/src/lib/nsas/tests/nameserver_address_store_unittest.cc b/src/lib/nsas/tests/nameserver_address_store_unittest.cc
index a2b3d42..95b46a8 100644
--- a/src/lib/nsas/tests/nameserver_address_store_unittest.cc
+++ b/src/lib/nsas/tests/nameserver_address_store_unittest.cc
@@ -86,7 +86,7 @@ public:
      * if it is asked for by the resolver.
      */
     void lookupAndAnswer(const string& name, const RRClass& class_code,
-        boost::shared_ptr<AbstractRRset> authority,
+        RRsetPtr authority,
         boost::shared_ptr<AddressRequestCallback> callback)
     {
         size_t size(resolver_->requests.size());
diff --git a/src/lib/nsas/tests/nameserver_address_unittest.cc b/src/lib/nsas/tests/nameserver_address_unittest.cc
index 2f12f41..35a46f0 100644
--- a/src/lib/nsas/tests/nameserver_address_unittest.cc
+++ b/src/lib/nsas/tests/nameserver_address_unittest.cc
@@ -39,7 +39,7 @@ class NameserverEntrySample {
 public:
     NameserverEntrySample():
         name_("example.org"),
-        rrv4_(new BasicRRset(name_, RRClass::IN(), RRType::A(), RRTTL(1200)))
+        rrv4_(new RRset(name_, RRClass::IN(), RRType::A(), RRTTL(1200)))
     {
         // Add some sample A records
         rrv4_->addRdata(ConstRdataPtr(new RdataTest<A>("1.2.3.4")));
@@ -50,7 +50,7 @@ public:
         boost::shared_ptr<TestResolver> resolver(new TestResolver);
         ns_->askIP(resolver, boost::shared_ptr<Callback>(new Callback), ANY_OK);
         resolver->asksIPs(name_, 0, 1);
-        resolver->requests[0].second->success(rrv4_);
+        resolver->requests[0].second->success(createResponseMessage(rrv4_));
     }
 
     // Return the sample NameserverEntry
@@ -73,7 +73,7 @@ public:
 
 private:
     Name name_;                             ///< Name of the sample
-    boost::shared_ptr<BasicRRset> rrv4_;           ///< Standard RRSet - IN, A, lowercase name
+    RRsetPtr rrv4_;           ///< Standard RRSet - IN, A, lowercase name
     boost::shared_ptr<NameserverEntry> ns_; ///< Shared_ptr that points to a NameserverEntry object
 
     class Callback : public NameserverEntry::Callback {
diff --git a/src/lib/nsas/tests/nameserver_entry_unittest.cc b/src/lib/nsas/tests/nameserver_entry_unittest.cc
index 2f5dc2a..9e4cec7 100644
--- a/src/lib/nsas/tests/nameserver_entry_unittest.cc
+++ b/src/lib/nsas/tests/nameserver_entry_unittest.cc
@@ -69,10 +69,10 @@ private:
      *     as a failure.
      */
     void fillSet(boost::shared_ptr<TestResolver> resolver, size_t index,
-        boost::shared_ptr<BasicRRset> set)
+        RRsetPtr set)
     {
         if (set) {
-            resolver->requests[index].second->success(set);
+            resolver->requests[index].second->success(createResponseMessage(set));
         } else {
             resolver->requests[index].second->failure();
         }
@@ -80,7 +80,7 @@ private:
 protected:
     /// Fills the nameserver entry with data trough ask IP
     void fillNSEntry(boost::shared_ptr<NameserverEntry> entry,
-        boost::shared_ptr<BasicRRset> rrv4, boost::shared_ptr<BasicRRset> rrv6)
+        RRsetPtr rrv4, RRsetPtr rrv6)
     {
         // Prepare data to run askIP
         boost::shared_ptr<TestResolver> resolver(new TestResolver);
@@ -212,13 +212,13 @@ TEST_F(NameserverEntryTest, ExpirationTime) {
     // Test where there is a single TTL
     boost::shared_ptr<NameserverEntry> alpha(new NameserverEntry(EXAMPLE_CO_UK,
         RRClass::IN()));
-    fillNSEntry(alpha, rrv4_, boost::shared_ptr<BasicRRset>());
+    fillNSEntry(alpha, rrv4_, RRsetPtr());
     expiration = alpha->getExpiration();
     EXPECT_EQ(expiration, curtime + rrv4_->getTTL().getValue());
 
     boost::shared_ptr<NameserverEntry> beta(new NameserverEntry(EXAMPLE_CO_UK,
         RRClass::IN()));
-    fillNSEntry(beta, boost::shared_ptr<BasicRRset>(), rrv6_);
+    fillNSEntry(beta, RRsetPtr(), rrv6_);
     expiration = beta->getExpiration();
     EXPECT_EQ(expiration, curtime + rrv6_->getTTL().getValue());
 
@@ -237,7 +237,7 @@ TEST_F(NameserverEntryTest, ExpirationTime) {
 
     boost::shared_ptr<NameserverEntry> delta(new NameserverEntry(EXAMPLE_CO_UK,
         RRClass::IN()));
-    fillNSEntry(delta, rrv4_, boost::shared_ptr<BasicRRset>());
+    fillNSEntry(delta, rrv4_, RRsetPtr());
     EXPECT_GT(delta->getExpiration(), rrv4_->getTTL().getValue());
 }
 
@@ -347,9 +347,9 @@ TEST_F(NameserverEntryTest, DirectAnswer) {
     resolver->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
         RRType::AAAA()), rrv6_);
     resolver->addPresetAnswer(Question(Name(EXAMPLE_NET), RRClass::IN(),
-        RRType::A()), boost::shared_ptr<AbstractRRset>());
+        RRType::A()), RRsetPtr());
     resolver->addPresetAnswer(Question(Name(EXAMPLE_NET), RRClass::IN(),
-        RRType::AAAA()), boost::shared_ptr<AbstractRRset>());
+        RRType::AAAA()), RRsetPtr());
 
     // A successfull test first
     entry->askIP(resolver, callback, ANY_OK);
diff --git a/src/lib/nsas/tests/nsas_test.h b/src/lib/nsas/tests/nsas_test.h
index a0b86df..b4446a4 100644
--- a/src/lib/nsas/tests/nsas_test.h
+++ b/src/lib/nsas/tests/nsas_test.h
@@ -25,18 +25,33 @@
 
 #include <config.h>
 
+#include <dns/message.h>
 #include <dns/buffer.h>
 #include <dns/rdata.h>
 #include <dns/rrtype.h>
 #include <dns/rrttl.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdataclass.h>
+#include <resolve/resolver_interface.h>
 #include "../nsas_entry.h"
-#include "../resolver_interface.h"
 
 using namespace isc::dns::rdata;
 using namespace isc::dns;
 
+namespace {
+    MessagePtr
+    createResponseMessage(RRsetPtr answer_rrset)
+    {
+        MessagePtr response(new Message(Message::RENDER));
+        response->setOpcode(Opcode::QUERY());
+        response->setRcode(Rcode::NOERROR());
+        response->addRRset(Message::SECTION_ANSWER, answer_rrset);
+        return response;
+    }
+}
+
 namespace isc {
 namespace dns {
 
@@ -217,13 +232,13 @@ using namespace std;
  * This pretends to be a resolver. It stores the queries and
  * they can be answered.
  */
-class TestResolver : public isc::nsas::ResolverInterface {
+class TestResolver : public isc::resolve::ResolverInterface {
     private:
         bool checkIndex(size_t index) {
             return (requests.size() > index);
         }
 
-        typedef std::map<isc::dns::Question, boost::shared_ptr<AbstractRRset> >
+        typedef std::map<isc::dns::Question, RRsetPtr >
             PresetAnswers;
         PresetAnswers answers_;
     public:
@@ -235,7 +250,7 @@ class TestResolver : public isc::nsas::ResolverInterface {
                 requests.push_back(Request(q, c));
             } else {
                 if (it->second) {
-                    c->success(it->second);
+                    c->success(createResponseMessage(it->second));
                 } else {
                     c->failure();
                 }
@@ -248,7 +263,7 @@ class TestResolver : public isc::nsas::ResolverInterface {
          * it goes to requests and you can answer later.
          */
         void addPresetAnswer(const isc::dns::Question& question,
-            boost::shared_ptr<AbstractRRset> answer)
+            RRsetPtr answer)
         {
             answers_[question] = answer;
         }
@@ -308,11 +323,11 @@ class TestResolver : public isc::nsas::ResolverInterface {
             RRsetPtr set(new RRset(name, RRClass::IN(),
                 type, RRTTL(TTL)));
             set->addRdata(rdata);
-            requests[index].second->success(set);
+            requests[index].second->success(createResponseMessage(set));
         }
 
         void provideNS(size_t index,
-            boost::shared_ptr<AbstractRRset> nameservers)
+            RRsetPtr nameservers)
         {
             if (index >= requests.size()) {
                 throw NoSuchRequest();
@@ -322,7 +337,7 @@ class TestResolver : public isc::nsas::ResolverInterface {
             {
                 throw DifferentRequest();
             }
-            requests[index].second->success(nameservers);
+            requests[index].second->success(createResponseMessage(nameservers));
         }
 };
 
diff --git a/src/lib/nsas/tests/zone_entry_unittest.cc b/src/lib/nsas/tests/zone_entry_unittest.cc
index ca19110..8a3c6f2 100644
--- a/src/lib/nsas/tests/zone_entry_unittest.cc
+++ b/src/lib/nsas/tests/zone_entry_unittest.cc
@@ -42,7 +42,8 @@ namespace {
 /// \brief Inherited version with access into its internals for tests
 class InheritedZoneEntry : public ZoneEntry {
     public:
-        InheritedZoneEntry(boost::shared_ptr<ResolverInterface> resolver,
+        InheritedZoneEntry(
+            boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
             const std::string& name, const RRClass& class_code,
             boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table,
             boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru) :
@@ -459,7 +460,7 @@ TEST_F(ZoneEntryTest, DirectAnswer) {
 
     // One unsuccessfull attempt, nameservers fail
     resolver_->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
-        RRType::NS()), boost::shared_ptr<AbstractRRset>());
+        RRType::NS()), RRsetPtr());
     zone->addCallback(callback_, ANY_OK);
     EXPECT_EQ(0, callback_->successes_.size());
     EXPECT_EQ(1, callback_->unreachable_count_);
@@ -493,9 +494,9 @@ TEST_F(ZoneEntryTest, DirectAnswer) {
     callback_->successes_.clear();
     // Now, pretend we do not have IP addresses
     resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(), RRType::A()),
-        boost::shared_ptr<AbstractRRset>());
+        RRsetPtr());
     resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(),
-        RRType::AAAA()), boost::shared_ptr<AbstractRRset>());
+        RRType::AAAA()), RRsetPtr());
     // Get another zone and ask it again. It should fail.
     // Clean the table first, though, so it does not find the old nameserver
     nameserver_table_->remove(HashKey(ns_name.toText(), RRClass::IN()));
diff --git a/src/lib/nsas/zone_entry.cc b/src/lib/nsas/zone_entry.cc
index 4009fe7..395b06c 100644
--- a/src/lib/nsas/zone_entry.cc
+++ b/src/lib/nsas/zone_entry.cc
@@ -22,6 +22,7 @@
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
 #include <dns/rrttl.h>
+#include <dns/rcode.h>
 #include <dns/rdataclass.h>
 
 using namespace std;
@@ -32,7 +33,8 @@ using namespace dns;
 
 namespace nsas {
 
-ZoneEntry::ZoneEntry(boost::shared_ptr<ResolverInterface> resolver,
+ZoneEntry::ZoneEntry(
+    boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
     const std::string& name, const isc::dns::RRClass& class_code,
     boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table,
     boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru) :
@@ -73,7 +75,8 @@ newNs(const std::string* name, const RRClass* class_code) {
  * code. It manipulates directly ZoneEntry's data members, locks it and like
  * that. Mostly eliminates C++ bad design of missing lambda functions.
  */
-class ZoneEntry::ResolverCallback : public ResolverInterface::Callback {
+class ZoneEntry::ResolverCallback :
+        public isc::resolve::ResolverInterface::Callback {
     public:
         /// \short Constructor. Pass "this" zone entry
         ResolverCallback(boost::shared_ptr<ZoneEntry> entry) :
@@ -90,8 +93,21 @@ class ZoneEntry::ResolverCallback : public ResolverInterface::Callback {
          * examining them and seeing if some addresses are already there
          * and to ask for the rest of them.
          */
-        virtual void success(const boost::shared_ptr<AbstractRRset>& answer) {
+        virtual void success(MessagePtr response_message) {
             Lock lock(entry_->mutex_);
+
+            // TODO: find the correct RRset, not simply the first
+            if (!response_message ||
+                response_message->getRcode() != isc::dns::Rcode::NOERROR() ||
+                response_message->getRRCount(isc::dns::Message::SECTION_ANSWER) == 0) {
+                // todo: define this
+                failureInternal(300);
+            }
+
+            isc::dns::RRsetIterator rrsi =
+                response_message->beginSection(isc::dns::Message::SECTION_ANSWER);
+            const isc::dns::RRsetPtr answer = *rrsi;
+
             RdataIteratorPtr iterator(answer->getRdataIterator());
             // If there are no data
             if (iterator->isLast()) {
diff --git a/src/lib/nsas/zone_entry.h b/src/lib/nsas/zone_entry.h
index 8ae36f7..c105f70 100644
--- a/src/lib/nsas/zone_entry.h
+++ b/src/lib/nsas/zone_entry.h
@@ -36,11 +36,12 @@
 
 #include <dns/rrset.h>
 
+#include <resolve/resolver_interface.h>
+
 #include "hash_key.h"
 #include "nsas_entry.h"
 #include "asiolink.h"
 #include "fetchable.h"
-#include "resolver_interface.h"
 #include "nsas_types.h"
 #include "random_number_generator.h"
 
@@ -76,7 +77,8 @@ public:
      * \todo Move to cc file, include the lookup (if NSAS uses resolver for
      *     everything)
      */
-    ZoneEntry(boost::shared_ptr<ResolverInterface> resolver,
+    ZoneEntry(
+        boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
         const std::string& name, const isc::dns::RRClass& class_code,
         boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table,
         boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru);
@@ -151,7 +153,7 @@ private:
     void process(AddressFamily family,
         const boost::shared_ptr<NameserverEntry>& nameserver);
     // Resolver we use
-    boost::shared_ptr<ResolverInterface> resolver_;
+    boost::shared_ptr<isc::resolve::ResolverInterface> resolver_;
     // We store the nameserver table and lru, so we can look up when there's
     // update
     boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table_;
diff --git a/src/lib/resolve/Makefile.am b/src/lib/resolve/Makefile.am
new file mode 100644
index 0000000..8edb594
--- /dev/null
+++ b/src/lib/resolve/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += $(SQLITE_CFLAGS)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libresolve.la
+libresolve_la_SOURCES = resolve.h
+libresolve_la_SOURCES += resolver_interface.h
+libresolve_la_SOURCES += resolver_callback.h resolver_callback.cc
+libresolve_la_LIBADD = $(top_builddir)/src/lib/dns/libdns++.la
+libresolve_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
diff --git a/src/lib/resolve/resolve.h b/src/lib/resolve/resolve.h
new file mode 100644
index 0000000..63c9b58
--- /dev/null
+++ b/src/lib/resolve/resolve.h
@@ -0,0 +1,20 @@
+// 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 _ISC_RESOLVE_H
+#define _ISC_RESOLVE_H 1
+
+#include <resolve/resolver_interface.h>
+#include <resolve/resolver_callback.h>
+#endif // ISC_RESOLVE_H_
diff --git a/src/lib/resolve/resolver_callback.cc b/src/lib/resolve/resolver_callback.cc
new file mode 100644
index 0000000..c0db55e
--- /dev/null
+++ b/src/lib/resolve/resolver_callback.cc
@@ -0,0 +1,36 @@
+// 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 <resolve/resolver_callback.h>
+
+namespace isc {
+namespace resolve {
+
+void
+ResolverCallbackServer::success(const isc::dns::MessagePtr response)
+{
+    // ignore our response here
+    (void)response;
+    
+    server_->resume(true);
+}
+
+void
+ResolverCallbackServer::failure()
+{
+    server_->resume(false);
+}
+
+} // namespace resolve
+} // namespace isc
diff --git a/src/lib/resolve/resolver_callback.h b/src/lib/resolve/resolver_callback.h
new file mode 100644
index 0000000..f69d8a7
--- /dev/null
+++ b/src/lib/resolve/resolver_callback.h
@@ -0,0 +1,48 @@
+// 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 _ISC_RESOLVER_CALLBACK_H
+#define _ISC_RESOLVER_CALLBACK_H 1
+
+#include <asiolink/asiolink.h>
+#include <dns/message.h>
+
+namespace isc {
+namespace resolve {
+
+/// \short Standard Callback for sendQuery for DNSServer instances
+///
+/// This is a standard ResolverInterface::Callback implementation
+/// that is used by Resolver; when RunningQuery finishes and has either
+/// some data or an error, DNSServer::resume() will be called.
+///
+/// This class will ignore the response MessagePtr in the callback,
+/// as the server itself should also have a reference.
+class ResolverCallbackServer : public ResolverInterface::Callback {
+public:
+    ResolverCallbackServer(asiolink::DNSServer* server) :
+        server_(server->clone()) {}
+    ~ResolverCallbackServer() { delete server_; };
+    
+    void success(const isc::dns::MessagePtr response);
+    void failure();
+
+private:
+    asiolink::DNSServer* server_;
+};
+
+} //namespace resolve
+} //namespace isc
+
+#endif // ISC_RESOLVER_CALLBACK_H_
diff --git a/src/lib/resolve/resolver_interface.h b/src/lib/resolve/resolver_interface.h
new file mode 100644
index 0000000..e08bb64
--- /dev/null
+++ b/src/lib/resolve/resolver_interface.h
@@ -0,0 +1,98 @@
+// Copyright (C) 2010  CZ NIC
+//
+// 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 __RESOLVER_INTERFACE_H
+#define __RESOLVER_INTERFACE_H
+
+#include <dns/message.h>
+
+///
+/// \file resolver_interface.h
+/// \short Interface to resolver.
+///
+/// This file contains an interface for the resolver. By subclassing
+/// this abstract interface, other parts of the system can ask the
+/// resolver to do some resolving too.
+///
+/// This is done by creating a subclass of ResolverInterface::Callback,
+/// which defines what to do with the result, and then calling resolve()
+/// on the ResolverInterface implementation.
+///
+/// One default Callback subclass is provided right now, in
+/// resolver_callback.[h|cc], which calls resumse() on a given DNSServer
+///
+
+namespace isc {
+namespace resolve {
+
+///
+/// \short Abstract interface to the resolver.
+///
+/// Abstract interface to the resolver. The NameserverAddressStore uses this
+/// to ask for addresses. It is here because resolver does not yet exist.
+///
+/// It is abstract to allow tests pass dummy resolvers.
+///
+class ResolverInterface {
+    public:
+        /// \short An abstract callback for when the resolver is done.
+        ///
+        /// You can pass an instance of a subclass of this (as a
+        /// CallbackPtr) to RecursiveQuery::sendQuery(), and when it
+        /// is done, it will either call success() if there is an
+        /// answer MessagePtr, or failure(), if the resolver was not
+        /// able to find anything.
+        ///
+        /// Note that a result Message does not necessarily contain
+        /// the actual answer (it could be a noerror/nodata response).
+        class Callback {
+            public:
+                /// \short Some data arrived.
+                virtual void success(const isc::dns::MessagePtr response) = 0;
+                
+                ///
+                ///\short No data available.
+                ///
+                ///\todo Provide error reason (result of the
+                ///      classification call, for instance? We'd also
+                ///      need some way to say 'everything times out')
+                ///
+                virtual void failure() = 0;
+
+                /// \short Virtual destructor, so descendants are cleaned up
+                virtual ~Callback() {};
+        };
+
+        typedef boost::shared_ptr<Callback> CallbackPtr;
+
+        ///
+        ///\short Ask a question.
+        ///
+        /// Asks the resolver a question. Once the answer is ready
+        /// the callback is called.
+        ///
+        /// \param question What to ask. The resolver will decide who.
+        /// \param callback What should happen when the answer is ready.
+        ///
+        virtual void resolve(const isc::dns::QuestionPtr& question,
+            const CallbackPtr& callback) = 0;
+
+        /// \short Virtual destructor, so descendants are properly cleaned up
+        virtual ~ ResolverInterface() {}
+};
+
+} // namespace nsas
+} // namespace isc
+
+#endif //__RESOLVER_INTERFACE_H
diff --git a/src/lib/resolve/tests/Makefile.am b/src/lib/resolve/tests/Makefile.am
new file mode 100644
index 0000000..e064cc0
--- /dev/null
+++ b/src/lib/resolve/tests/Makefile.am
@@ -0,0 +1,24 @@
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+run_unittests_SOURCES = run_unittests.cc
+run_unittests_SOURCES += resolver_callback_unittest.cc
+
+run_unittests_LDADD = $(GTEST_LDADD)
+run_unittests_LDADD +=  $(top_builddir)/src/lib/resolve/libresolve.la
+
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/resolve/tests/resolver_callback_unittest.cc b/src/lib/resolve/tests/resolver_callback_unittest.cc
new file mode 100644
index 0000000..6370e22
--- /dev/null
+++ b/src/lib/resolve/tests/resolver_callback_unittest.cc
@@ -0,0 +1,90 @@
+// Copyright (C) 2010  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 <resolve/resolver_callback.h>
+#include <asiolink/asiolink.h>
+
+using namespace isc::resolve;
+
+// Dummy subclass for DNSServer*
+// We want to check if resume is called
+// Since the server will get cloned(), we want the clones to share
+// our bools for whether resume got called and with what value
+class DummyServer : public asiolink::DNSServer {
+public:
+    DummyServer(DummyServer* orig) {
+        resume_called_ = orig->getResumeCalled();
+        resume_value_ = orig->getResumeValue();
+    }
+    DummyServer(bool* resume_called, bool* resume_value) :
+        resume_called_(resume_called), resume_value_(resume_value)
+    {}
+    
+    bool* getResumeCalled() { return resume_called_; }
+    bool* getResumeValue() { return resume_value_; }
+    
+    DNSServer* clone() {
+        DummyServer* n = new DummyServer(this);
+        return n;
+    }
+
+    void resume(bool value) {
+        *resume_called_ = true;
+        *resume_value_ = value;
+    }
+
+private:
+    bool* resume_called_;
+    bool* resume_value_;
+};
+
+class ResolverCallbackServerTest : public ::testing::Test {
+public:
+    ResolverCallbackServerTest() : resume_called_(false),
+                                   resume_value_(false) {
+        server_ = new DummyServer(&resume_called_, &resume_value_);
+        callback_ = new ResolverCallbackServer(server_);
+    };
+
+    ~ResolverCallbackServerTest() {
+        delete callback_;
+        delete server_;
+    }
+
+    DummyServer* getServer() { return server_; }
+    ResolverCallbackServer* getCallback() { return callback_; }
+    bool getResumeCalled() { return resume_called_; }
+    bool getResumeValue() { return resume_value_; }
+
+private:
+    DummyServer* server_;
+    ResolverCallbackServer* callback_;
+    bool resume_called_;
+    bool resume_value_;
+};
+
+TEST_F(ResolverCallbackServerTest, testSuccess) {
+    EXPECT_FALSE(getResumeCalled());
+    getCallback()->success(isc::dns::MessagePtr());
+    EXPECT_TRUE(getResumeCalled());
+    EXPECT_TRUE(getResumeValue());
+}
+
+TEST_F(ResolverCallbackServerTest, testFailure) {
+    EXPECT_FALSE(getResumeCalled());
+    getCallback()->failure();
+    EXPECT_TRUE(getResumeCalled());
+    EXPECT_FALSE(getResumeValue());
+}
diff --git a/src/lib/resolve/tests/run_unittests.cc b/src/lib/resolve/tests/run_unittests.cc
new file mode 100644
index 0000000..f80e167
--- /dev/null
+++ b/src/lib/resolve/tests/run_unittests.cc
@@ -0,0 +1,24 @@
+// 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
+// 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 <dns/tests/unittest_util.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    return (RUN_ALL_TESTS());
+}
diff --git a/src/lib/testutils/srv_test.cc b/src/lib/testutils/srv_test.cc
index 0a27eba..c0d6e0f 100644
--- a/src/lib/testutils/srv_test.cc
+++ b/src/lib/testutils/srv_test.cc
@@ -33,6 +33,7 @@ const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
 
 SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
                              parse_message(new Message(Message::PARSE)),
+                             response_message(new Message(Message::RENDER)),
                              default_qid(0x1035),
                              opcode(Opcode(Opcode::QUERY())),
                              qname("www.example.com"),
diff --git a/src/lib/testutils/srv_test.h b/src/lib/testutils/srv_test.h
index 061076d..7361a76 100644
--- a/src/lib/testutils/srv_test.h
+++ b/src/lib/testutils/srv_test.h
@@ -89,8 +89,8 @@ protected:
     MockSession notify_session;
     MockServer dnsserv;
     isc::dns::Message request_message;
-    isc::dns::MessagePtr response_message;
     isc::dns::MessagePtr parse_message;
+    isc::dns::MessagePtr response_message;
     const isc::dns::qid_t default_qid;
     const isc::dns::Opcode opcode;
     const isc::dns::Name qname;




More information about the bind10-changes mailing list