Browse Source

[trac494] initial abstraction for runningquery results

Added a abstract placeholder for callbacks in asio (for now); which has
two subclasses; one takes a DNSServer* and calls resume() on it when the
runningquery finished its lookup (or fails), the other one is provided a
callback as defined in isc::nsas::ResolverInterface.

These are more objects that are newed while running and delete
themselves, and they may not even be necessary, but for now this makes
it work while doing the least amount of changes in other parts.

RunnigQuery now takes one of these objects instead of a DNSServer*, and
the objects decide what should be done once it is ready.

Things to do:
- remove the temporary MyCallback class from resolver (perhaps move it
  to a unittest)
- move ResolverInterface out of nsas, as well as its Callback thingy,
  and merge it with the new callback holders
- general cleanup and tests (although, as with current resolver tests,
  need framework to fake outside query handling)
Jelte Jansen 14 years ago
parent
commit
8a175757cd

+ 1 - 1
src/bin/msgq/msgq.py.in

@@ -190,7 +190,7 @@ class MsgQ:
         # TODO: When we have logging, we might want
         # TODO: When we have logging, we might want
         # to add a debug message here that a new connection
         # to add a debug message here that a new connection
         # was made
         # was made
-        self.register_socket(self, newsocket)
+        self.register_socket(newsocket)
 
 
     def register_socket(self, newsocket):
     def register_socket(self, newsocket):
         """
         """

+ 51 - 0
src/bin/resolver/resolver.cc

@@ -126,6 +126,9 @@ public:
         }
         }
     }
     }
 
 
+    void resolve(const isc::dns::QuestionPtr& question,
+                 const isc::nsas::ResolverInterface::CallbackPtr& callback);
+
     void processNormalQuery(const Question& question,
     void processNormalQuery(const Question& question,
                             MessagePtr answer_message,
                             MessagePtr answer_message,
                             OutputBufferPtr buffer,
                             OutputBufferPtr buffer,
@@ -341,6 +344,36 @@ Resolver::getConfigSession() const {
     return (impl_->config_session_);
     return (impl_->config_session_);
 }
 }
 
 
+/* tmp for in-dev testing */
+class MyCallback : public nsas::ResolverInterface::Callback {
+public:
+    virtual void success(
+        const boost::shared_ptr<isc::dns::AbstractRRset>&
+        response) {
+        std::cout << "[XX] CALLBACK FOR LOOKUP!" << std::endl;
+        std::cout << "[XX] GOT: " << *response << std::endl;
+        std::cout << "[XX] END" << std::endl;
+    };
+
+    virtual void failure() {
+        std::cout << "[XX] internal lookup failed" << std::endl;
+    }
+
+    ~MyCallback() {
+        std::cout << "[XX] MyCallback deleted!" << std::endl;
+    }
+};
+
+void
+Resolver::resolve(const isc::dns::QuestionPtr& question,
+                  const isc::nsas::ResolverInterface::CallbackPtr& callback)
+{
+    std::cout << "[XX] asked to resolve: " << *question << std::endl;
+    impl_->resolve(question, callback);
+    std::cout << "[XX] done?" << std::endl;
+}
+
+
 void
 void
 Resolver::processMessage(const IOMessage& io_message,
 Resolver::processMessage(const IOMessage& io_message,
                          MessagePtr query_message,
                          MessagePtr query_message,
@@ -348,6 +381,17 @@ Resolver::processMessage(const IOMessage& io_message,
                          OutputBufferPtr buffer,
                          OutputBufferPtr buffer,
                          DNSServer* server)
                          DNSServer* server)
 {
 {
+    std::cout << "[XX] remove this :p" << std::endl;
+    QuestionPtr q(new Question(Name("www.tjeb.nl"), RRClass::IN(), RRType::A()));
+    boost::shared_ptr<MyCallback> callback(new MyCallback());
+
+    std::cout << "[XX] CREATED CALLBACK AT " << callback << std::endl;
+
+    resolve(q, callback);
+    //resolve(q, callback);
+    std::cout << "[XX] up to here" << std::endl;
+
+
     dlog("Got a DNS message");
     dlog("Got a DNS message");
     InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
     InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
     // First, check the header part.  If we fail even for the base header,
     // First, check the header part.  If we fail even for the base header,
@@ -425,6 +469,13 @@ Resolver::processMessage(const IOMessage& io_message,
 }
 }
 
 
 void
 void
+ResolverImpl::resolve(const QuestionPtr& question,
+                      const isc::nsas::ResolverInterface::CallbackPtr& callback)
+{
+    rec_query_->sendQuery(question, callback);
+}
+
+void
 ResolverImpl::processNormalQuery(const Question& question,
 ResolverImpl::processNormalQuery(const Question& question,
                                  MessagePtr answer_message,
                                  MessagePtr answer_message,
                                  OutputBufferPtr buffer,
                                  OutputBufferPtr buffer,

+ 6 - 1
src/bin/resolver/resolver.h

@@ -24,6 +24,8 @@
 
 
 #include <asiolink/asiolink.h>
 #include <asiolink/asiolink.h>
 
 
+#include <nsas/resolver_interface.h>
+
 class ResolverImpl;
 class ResolverImpl;
 
 
 /**
 /**
@@ -35,7 +37,7 @@ class ResolverImpl;
  * answer. It doesn't really know about chasing referrals and similar, it
  * answer. It doesn't really know about chasing referrals and similar, it
  * simply plugs the parts that know into the network handling code.
  * simply plugs the parts that know into the network handling code.
  */
  */
-class Resolver {
+class Resolver : public isc::nsas::ResolverInterface {
     ///
     ///
     /// \name Constructors, Assignment Operator and Destructor.
     /// \name Constructors, Assignment Operator and Destructor.
     ///
     ///
@@ -51,6 +53,9 @@ public:
     ~Resolver();
     ~Resolver();
     //@}
     //@}
 
 
+    virtual void resolve(const isc::dns::QuestionPtr& question,
+                         const isc::nsas::ResolverInterface::CallbackPtr& callback);
+
     /// \brief Process an incoming DNS message, then signal 'server' to resume 
     /// \brief Process an incoming DNS message, then signal 'server' to resume 
     ///
     ///
     /// A DNS query (or other message) has been received by a \c DNSServer
     /// A DNS query (or other message) has been received by a \c DNSServer

+ 61 - 8
src/lib/asiolink/asiolink.cc

@@ -31,6 +31,7 @@
 #include <dns/buffer.h>
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/message.h>
 #include <dns/rcode.h>
 #include <dns/rcode.h>
+#include <dns/opcode.h>
 
 
 #include <asiolink/asiolink.h>
 #include <asiolink/asiolink.h>
 #include <asiolink/internal/tcpdns.h>
 #include <asiolink/internal/tcpdns.h>
@@ -38,7 +39,6 @@
 
 
 #include <log/dummylog.h>
 #include <log/dummylog.h>
 
 
-
 using namespace asio;
 using namespace asio;
 using asio::ip::udp;
 using asio::ip::udp;
 using asio::ip::tcp;
 using asio::ip::tcp;
@@ -354,7 +354,8 @@ private:
     OutputBufferPtr buffer_;
     OutputBufferPtr buffer_;
 
 
     // Server to notify when we succeed or fail
     // Server to notify when we succeed or fail
-    shared_ptr<DNSServer> server_;
+    //shared_ptr<DNSServer> server_;
+    AbstractResolverCallback* resolvercallback_;
 
 
     /*
     /*
      * TODO Do something more clever with timeouts. In the long term, some
      * TODO Do something more clever with timeouts. In the long term, some
@@ -475,7 +476,10 @@ public:
     RunningQuery(asio::io_service& io, const Question &question,
     RunningQuery(asio::io_service& io, const Question &question,
         MessagePtr answer_message, shared_ptr<AddressVector> upstream,
         MessagePtr answer_message, shared_ptr<AddressVector> upstream,
         shared_ptr<AddressVector> upstream_root,
         shared_ptr<AddressVector> upstream_root,
-        OutputBufferPtr buffer, DNSServer* server, int timeout,
+        OutputBufferPtr buffer,
+        //DNSServer* server,
+        AbstractResolverCallback* cb,
+        int timeout,
         unsigned retries) :
         unsigned retries) :
         io_(io),
         io_(io),
         question_(question),
         question_(question),
@@ -483,7 +487,8 @@ public:
         upstream_(upstream),
         upstream_(upstream),
         upstream_root_(upstream_root),
         upstream_root_(upstream_root),
         buffer_(buffer),
         buffer_(buffer),
-        server_(server->clone()),
+        //server_(server->clone()),
+        resolvercallback_(cb),
         timeout_(timeout),
         timeout_(timeout),
         retries_(retries),
         retries_(retries),
         zone_servers_()
         zone_servers_()
@@ -533,7 +538,8 @@ public:
             }
             }
             
             
             if (done) {
             if (done) {
-                server_->resume(result == UDPQuery::SUCCESS);
+                resolvercallback_->callback(result == UDPQuery::SUCCESS);
+                //server_->resume(result == UDPQuery::SUCCESS);
                 delete this;
                 delete this;
             }
             }
         } else if (retries_--) {
         } else if (retries_--) {
@@ -542,7 +548,8 @@ public:
             send();
             send();
         } else {
         } else {
             // out of retries, give up for now
             // out of retries, give up for now
-            server_->resume(false);
+            resolvercallback_->callback(false);
+            //server_->resume(false);
             delete this;
             delete this;
         }
         }
     }
     }
@@ -551,6 +558,23 @@ public:
 }
 }
 
 
 void
 void
+RecursiveQuery::sendQuery(const isc::dns::QuestionPtr& question,
+    const isc::nsas::ResolverInterface::CallbackPtr callback)
+{
+    asio::io_service& io = dns_service_.get_io_service();
+
+    MessagePtr answer_message(new Message(Message::RENDER));
+    answer_message->setOpcode(isc::dns::Opcode::QUERY());
+    OutputBufferPtr buffer(new OutputBuffer(0));
+    ResolverCallbackDirect* rcd = new ResolverCallbackDirect(callback,
+                                                             answer_message);
+    
+    // It will delete itself when it is done
+    new RunningQuery(io, *question, answer_message, upstream_,
+                     upstream_root_, buffer, rcd, timeout_, retries_);
+}
+
+void
 RecursiveQuery::sendQuery(const Question& question,
 RecursiveQuery::sendQuery(const Question& question,
                           MessagePtr answer_message,
                           MessagePtr answer_message,
                           OutputBufferPtr buffer,
                           OutputBufferPtr buffer,
@@ -561,11 +585,40 @@ RecursiveQuery::sendQuery(const Question& question,
     // UDP and then fall back to TCP on failure, but for the moment
     // UDP and then fall back to TCP on failure, but for the moment
     // we're only going to handle UDP.
     // we're only going to handle UDP.
     asio::io_service& io = dns_service_.get_io_service();
     asio::io_service& io = dns_service_.get_io_service();
+
+    ResolverCallbackServer* crs = new ResolverCallbackServer(server);
+    
     // It will delete itself when it is done
     // It will delete itself when it is done
-    new RunningQuery(io, question, answer_message, upstream_, upstream_root_,
-                         buffer, server, timeout_, retries_);
+    new RunningQuery(io, question, answer_message, upstream_,
+                     upstream_root_, buffer, crs, timeout_, retries_);
+}
+
+void
+ResolverCallbackServer::callback(bool result) {
+    server_->resume(result);
+    delete server_;
+    delete this;
+}
+
+void
+ResolverCallbackDirect::callback(bool result)
+{
+    // simply return with the first rrset from answer right now
+    if (result &&
+        answer_message_->getRcode() == isc::dns::Rcode::NOERROR() &&
+        answer_message_->getRRCount(isc::dns::Message::SECTION_ANSWER) > 0) {
+        std::cout << *answer_message_ << std::endl;
+        isc::dns::RRsetIterator rrsi = answer_message_->beginSection(isc::dns::Message::SECTION_ANSWER);
+        const isc::dns::RRsetPtr result = *rrsi;
+        callback_->success(result);
+    } else {
+        callback_->failure();
+    }
+    // once called back we don't need ourselves anymore
+    delete this;
 }
 }
 
 
+
 class IntervalTimerImpl {
 class IntervalTimerImpl {
 private:
 private:
     // prohibit copy
     // prohibit copy

+ 45 - 0
src/lib/asiolink/asiolink.h

@@ -31,6 +31,7 @@
 #include <dns/buffer.h>
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/message.h>
 #include <dns/question.h>
 #include <dns/question.h>
+#include <dns/rcode.h>
 
 
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
 
 
@@ -39,6 +40,8 @@
 #include <asiolink/iomessage.h>
 #include <asiolink/iomessage.h>
 #include <asiolink/iosocket.h>
 #include <asiolink/iosocket.h>
 
 
+#include <nsas/resolver_interface.h>
+
 namespace asio {
 namespace asio {
 // forward declaration for IOService::get_io_service() below
 // forward declaration for IOService::get_io_service() below
 class io_service;
 class io_service;
@@ -99,6 +102,7 @@ class DNSServiceImpl;
 struct IOServiceImpl;
 struct IOServiceImpl;
 struct IntervalTimerImpl;
 struct IntervalTimerImpl;
 
 
+
 /// \brief An exception that is thrown if an error occurs within the IO
 /// \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
 /// module.  This is mainly intended to be a wrapper exception class for
 /// ASIO specific exceptions.
 /// ASIO specific exceptions.
@@ -367,6 +371,43 @@ private:
     DNSServer* self_;
     DNSServer* self_;
 };
 };
 
 
+// We define two types of callbackholders for processing recursive
+// queries; one calls back the original DNSServer to resume()
+// the other uses direct callbacks (for instance when we need to
+// resolve something ourselves)
+// Caller warning: only callback once! The objects will delete
+// themselves on callback (after they have done they callback)
+class AbstractResolverCallback {
+public:
+    ~AbstractResolverCallback() {};
+    virtual void callback(bool result) = 0;
+};
+
+class ResolverCallbackServer : public AbstractResolverCallback {
+public:
+    ResolverCallbackServer(DNSServer* server) :
+        server_(server->clone()) {}
+    void callback(bool result);
+
+private:
+    DNSServer* server_;
+};
+
+class ResolverCallbackDirect : public AbstractResolverCallback {
+public:
+    ResolverCallbackDirect(
+        const isc::nsas::ResolverInterface::CallbackPtr callback,
+        isc::dns::MessagePtr answer_message) :
+            callback_(callback),
+            answer_message_(answer_message) {}
+    void callback(bool result);
+
+private:
+    const isc::nsas::ResolverInterface::CallbackPtr callback_;
+    isc::dns::MessagePtr answer_message_;
+};
+        
+
 /// \brief The \c DNSLookup class is an abstract base class for a DNS
 /// \brief The \c DNSLookup class is an abstract base class for a DNS
 /// Lookup provider function.
 /// Lookup provider function.
 ///
 ///
@@ -553,6 +594,10 @@ public:
                    int timeout = -1, unsigned retries = 0);
                    int timeout = -1, unsigned retries = 0);
     //@}
     //@}
 
 
+    void sendQuery(const isc::dns::QuestionPtr& question,
+                   const isc::nsas::ResolverInterface::CallbackPtr callback);
+
+
     /// \brief Initiates an upstream query in the \c RecursiveQuery object.
     /// \brief Initiates an upstream query in the \c RecursiveQuery object.
     ///
     ///
     /// When sendQuery() is called, a message is sent asynchronously to
     /// When sendQuery() is called, a message is sent asynchronously to