[svn] commit: r811 - in /branches/each-ds/src/lib: auth/cpp/data_source.cc auth/cpp/query.h dns/cpp/message.h

BIND 10 source code commits bind10-changes at lists.isc.org
Sat Feb 13 16:41:11 UTC 2010


Author: each
Date: Sat Feb 13 16:41:11 2010
New Revision: 811

Log:
checkpoint:
 - much query API cleanup
 - query state is now part of the QueryTask rather than the Query itself
   (this will help support multiple-RRset answers)
 - added some comments

Modified:
    branches/each-ds/src/lib/auth/cpp/data_source.cc
    branches/each-ds/src/lib/auth/cpp/query.h
    branches/each-ds/src/lib/dns/cpp/message.h

Modified: branches/each-ds/src/lib/auth/cpp/data_source.cc
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/data_source.cc (original)
+++ branches/each-ds/src/lib/auth/cpp/data_source.cc Sat Feb 13 16:41:11 2010
@@ -24,36 +24,37 @@
             const rdata::generic::NS& ns =
                 dynamic_cast<const rdata::generic::NS&>(rd);
             const Name& nsname(ns.getNSName());
-            bool add = false;
 
             // Don't bother with A/AAAA record in the additional section
             // if they match the qname/qtype that we've already answered.
             if (nsname != q.qname() || q.qtype() != RRType::A()) {
-                q.tasks().push(QueryTask(nsname, q.qclass(), RRType::A(),
-                                         Section::ADDITIONAL()));
-                add = true;
+                QueryTask t(nsname, q.qclass(), RRType::A(),
+                            Section::ADDITIONAL()); 
+                t.state = QueryTask::GETADDITIONAL;
+                q.tasks().push(t);
             }
             if (nsname != q.qname() || q.qtype() != RRType::AAAA()) {
-                q.tasks().push(QueryTask(nsname, q.qclass(), RRType::AAAA(),
-                                         Section::ADDITIONAL())); 
-                add = true;
-            }
-            if (add) {
-                q.setStatus(QUERY_GETADDITIONAL);
+                QueryTask t(nsname, q.qclass(), RRType::AAAA(),
+                            Section::ADDITIONAL()); 
+                t.state = QueryTask::GETADDITIONAL;
+                q.tasks().push(t);
             }
         } else if (rrset->getType() == RRType::MX()) {
             const rdata::generic::MX& mx =
                 dynamic_cast<const rdata::generic::MX&>(rd);
-            const Name& mxname(mx.getMXName());
-            q.tasks().push(QueryTask(mxname, q.qclass(), RRType::A(),
-                                     Section::ADDITIONAL()));
-            q.tasks().push(QueryTask(mxname, q.qclass(), RRType::AAAA(),
-                                     Section::ADDITIONAL())); 
-            q.setStatus(QUERY_GETADDITIONAL);
+            QueryTask t(mx.getMXName(), q.qclass(), RRType::A(),
+                        Section::ADDITIONAL(), QueryTask::ADDR_QUERY); 
+            t.state = QueryTask::GETADDITIONAL;
+            q.tasks().push(t);
         }
     }
 }
 
+//
+// doQuery: Processes a query.
+// On success, the query status is set to Query::SUCCESS and
+// on failure, Query::FAILURE.
+// 
 void
 DataSrc::doQuery(Query q) {
     Result result;
@@ -68,6 +69,7 @@
         NameMatch match(task.qname);
         findClosestEnclosure(match);
         const DataSrc* ds = match.bestDataSrc();
+        const Name* zone = match.closestName();
 
         if (ds == NULL) {
             result = ZONE_NOT_FOUND;
@@ -75,7 +77,7 @@
             result = ds->findRRset(q, task.qname, task.qclass, task.qtype,
                                    data, sigs);
 
-            // Check answer validity:
+            // XXX:
             // For this version, there should only be one RRset in data,
             // and no more than one RRset in sigs.  We will address other
             // cases (e.g. ANY queries) later.
@@ -85,110 +87,110 @@
         }
 
         switch (result) {
-            case SUCCESS:
-                m.addRRset(task.section, data[0]);
+        case SUCCESS:
+            m.addRRset(task.section, data[0]);
+            if (q.wantDnssec() && sigs.size() == 1) {
+                m.addRRset(task.section, sigs[0]);
+            }
+
+            switch (task.state) {
+            case QueryTask::GETANSWER:
+            case QueryTask::FOLLOWCNAME:
+                getAdditional(q, data[0]);
+                if (q.tasks().empty()) {
+                    // No additional processing is needed, so now
+                    // add the authority section.
+                    if (data[0]->getType() != RRType::NS()) {
+                        QueryTask t(Name(*zone), task.qclass,
+                                     RRType::NS(),
+                                     Section::AUTHORITY());
+                        t.state = QueryTask::GETAUTHORITY;
+                        q.tasks().push(t);
+                    }
+                }
+                continue;
+
+            case QueryTask::GETADDITIONAL:
+                // If no more work items, add authority section now
+                if (q.tasks().empty()) {
+                    q.setStatus(Query::Query::SUCCESS);
+                    return;
+                }
+                continue;
+
+            case QueryTask::GETAUTHORITY:
+                getAdditional(q, data[0]);
+                if (q.tasks().empty()) {
+                    q.setStatus(Query::SUCCESS);
+                    return;
+                }
+                continue;
+
+            default:
+                dns_throw (Unexpected, "unexpected query state");
+            }
+
+        case CNAME_FOUND:
+            if (data.size() != 1 || data[0]->getType() != RRType::CNAME()) {
+                dns_throw (Unexpected, "invalid data");
+            }
+
+            m.addRRset(task.section, data[0]);
+            if (q.wantDnssec() && sigs.size() == 1) {
+                m.addRRset(task.section, sigs[0]);
+            }
+
+            it = data[0]->getRdataIterator();
+            for (it->first(); !it->isLast(); it->next()) {
+                const rdata::Rdata& rd(it->getCurrent());
+                const rdata::generic::CNAME& cname =
+                    dynamic_cast<const rdata::generic::CNAME&>(rd);
+                const Name& target(cname.getCname());
+                QueryTask t(target, task.qclass, task.qtype,
+                            Section::ANSWER());
+                t.state = QueryTask::FOLLOWCNAME;
+                q.tasks().push(t);
+                break;
+            }
+            continue;
+
+        case NAME_NOT_FOUND:
+        case TYPE_NOT_FOUND:
+            if (task.state == QueryTask::GETANSWER) {
+                if (result == NAME_NOT_FOUND) {
+                    m.setRcode(Rcode::NXDOMAIN());
+                }
+
+                result = ds->findRRset(q, Name(*zone), task.qclass,
+                                       RRType::SOA(), data, sigs);
+                if (result != SUCCESS) {
+                    m.setRcode(Rcode::SERVFAIL());
+                    return;
+                }
+
+                m.addRRset(Section::AUTHORITY(), data[0]);
                 if (q.wantDnssec() && sigs.size() == 1) {
-                    m.addRRset(task.section, sigs[0]);
-                }
-
-                switch (q.status()) {
-                    case QUERY_GETANSWER:
-                    case QUERY_FOLLOWCNAME:
-                        getAdditional(q, data[0]);
-                        if (q.tasks().empty()) {
-                            // No additional processing is needed, so now
-                            // add the authority section.
-                            if (data[0]->getType() != RRType::NS()) {
-                                QueryTask qt(Name(*match.closestName()),
-                                                  task.qclass, RRType::NS(),
-                                                  Section::AUTHORITY());
-                                q.tasks().push(qt);
-                            }
-                            q.setStatus(QUERY_GETAUTHORITY);
-                        }
-                        continue;
-
-                    case QUERY_GETADDITIONAL:
-                        // If no more work items, add authority section now
-                        if (q.tasks().empty()) {
-                            q.setStatus(QUERY_SUCCESS);
-                            return;
-                        }
-                        continue;
-
-                    case QUERY_GETAUTHORITY:
-                        getAdditional(q, data[0]);
-                        if (q.tasks().empty()) {
-                            q.setStatus(QUERY_SUCCESS);
-                            return;
-                        }
-                        continue;
-
-                    default:
-                        dns_throw (Unexpected, "unexpected query status");
-                }
-
-            case CNAME_FOUND:
-                if (data[0]->getType() != RRType::CNAME()) {
-                    dns_throw (Unexpected, "unexpected query status");
-                }
-
-                m.addRRset(task.section, data[0]);
-                if (q.wantDnssec() && sigs.size() == 1) {
-                    m.addRRset(task.section, sigs[0]);
-                }
-
-                it = data[0]->getRdataIterator();
-                for (it->first(); !it->isLast(); it->next()) {
-                    const rdata::Rdata& rd(it->getCurrent());
-                    const rdata::generic::CNAME& cname =
-                        dynamic_cast<const rdata::generic::CNAME&>(rd);
-                    const Name& target(cname.getCname());
-                    q.tasks().push(QueryTask(target, task.qclass, task.qtype,
-                                             Section::ANSWER()));
-                    q.setStatus(QUERY_FOLLOWCNAME);
-                    break;
-                }
-                continue;
-
-            case NAME_NOT_FOUND:
-            case TYPE_NOT_FOUND:
-                if (q.status() == QUERY_GETANSWER) {
-                    if (result == NAME_NOT_FOUND) {
-                        m.setRcode(Rcode::NXDOMAIN());
-                    }
-
-                    result = ds->findRRset(q, Name(*match.closestName()),
-                                           task.qclass, RRType::SOA(),
-                                           data, sigs);
-                    if (result != SUCCESS) {
-                        m.setRcode(Rcode::SERVFAIL());
-                        return;
-                    }
-
-                    m.addRRset(Section::AUTHORITY(), data[0]);
-                    if (q.wantDnssec() && sigs.size() == 1) {
-                        m.addRRset(Section::AUTHORITY(), sigs[0]);
-                    }
-
-                    q.setStatus(QUERY_FAIL);
-                    return;
-                }
-                continue;
-
-            case ZONE_NOT_FOUND:
-                if (q.status() == QUERY_GETANSWER) {
-                    m.setRcode(Rcode::REFUSED());
-                    q.setStatus(QUERY_FAIL);
-                    return;
-                }
-                continue;
-
-            case NOT_IMPLEMENTED:
-            case ERROR:
-                m.setRcode(Rcode::SERVFAIL());
-                q.setStatus(QUERY_FAIL);
+                    m.addRRset(Section::AUTHORITY(), sigs[0]);
+                }
+
+                q.setStatus(Query::FAILURE);
                 return;
+            }
+            continue;
+
+        case ZONE_NOT_FOUND:
+            if (task.state == QueryTask::GETANSWER) {
+                m.setRcode(Rcode::REFUSED());
+                q.setStatus(Query::FAILURE);
+                return;
+            }
+            continue;
+
+        case NOT_IMPLEMENTED:
+        case ERROR:
+            m.setRcode(Rcode::SERVFAIL());
+            q.setStatus(Query::FAILURE);
+            return;
         }
     }
 };

Modified: branches/each-ds/src/lib/auth/cpp/query.h
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/query.h (original)
+++ branches/each-ds/src/lib/auth/cpp/query.h Sat Feb 13 16:41:11 2010
@@ -31,15 +31,6 @@
 namespace isc {
 namespace auth {
 
-enum QueryStatus {
-    QUERY_GETANSWER,
-    QUERY_GETADDITIONAL,
-    QUERY_GETAUTHORITY,
-    QUERY_FOLLOWCNAME,
-    QUERY_SUCCESS,
-    QUERY_FAIL
-};
-
 ///
 /// \brief exception to throw if a DNS Message is malformed
 /// 
@@ -52,15 +43,75 @@
 // An individual task to be carried out by the query logic
 class QueryTask {
 public:
-    QueryTask(const Name& n, const RRClass& c,
-              const RRType& t, const Section& s) :
-        qname(n), qclass(c), qtype(t), section(s) {}
-    virtual ~QueryTask() {}
+    // XXX: Members are currently public, but should probably be
+    // moved to private and wrapped in get() functions later.
 
+    // The standard query tuple: qname/qclass/qtype.
+    // Note that qtype is ignored in the ADDR_QUERY case.
     const Name qname;
     const RRClass& qclass;
     const RRType& qtype;
+
+    // The section of the reply into which the data should be
+    // written after it has been fetched from the data source.
     const Section& section;
+
+    // This indicates the operation to be carried out:
+    // - STD_QUERY: look for an authoritative match for
+    //   qname/qclass/qtype, or for qname/qclass/CNAME,
+    //   or for a zone cut/referral.
+    // - SIMPLE_QUERY: look for a match for qname/qclass/qtype
+    //   in local data, regardless of authority
+    // - ADDR_QUERY: look for matches with qname/qclass/A
+    //   OR qname/class/AAAA in local data, regardless of
+    //   authority (this can be implemented with two successive
+    //   SIMPLE_QUERY lookups or as a single lookup, depending
+    //   on the Data Source implementation.
+
+    const enum Op {
+        STD_QUERY,
+        SIMPLE_QUERY,
+        ADDR_QUERY
+    } op;
+
+    // This indicates the state of the query as of the time when
+    // this answer should be processed.
+    // - GETANSWER: We are looking for the answer to a query.
+    // - FOLLOWCNAME: We are looking for the target of a CNAME RR that
+    //   was found via a GETANSWER query task.
+    // - GETAUTHORITY: We are looking for the authority information.
+    //   If a complete answer was previously found, this might be a
+    //   query for NS records.  If no complete answer has been found,
+    //   this might be a query for an SOA, NSEC or NSEC3 records.
+    // - GETADDITIONAL: We are filling in additional data, either
+    //   as a result of finding NS or MX records via a GETANSWER
+    //   query task, or as a result of finding NS records via a
+    //   GETAUTHORITY query task.
+    enum State {
+        GETANSWER,
+        GETADDITIONAL,
+        GETAUTHORITY,
+        FOLLOWCNAME
+    } state;
+
+    QueryTask(const Name& n, const RRClass& c,
+              const RRType& t, const Section& sect) :
+        qname(n), qclass(c), qtype(t),
+        section(sect), op(SIMPLE_QUERY), state(GETANSWER) {}
+    QueryTask(const Name& n, const RRClass& c,
+              const RRType& t, const Section& sect, const Op o) :
+        qname(n), qclass(c), qtype(t),
+        section(sect), op(o), state(GETANSWER) {}
+    QueryTask(const Name& n, const RRClass& c,
+              const RRType& t, const Section& sect, const State st) :
+        qname(n), qclass(c), qtype(t),
+        section(sect), op(SIMPLE_QUERY), state(st) {}
+    QueryTask(const Name& n, const RRClass& c,
+              const RRType& t, const Section& sect,
+              const Op o, const State st) :
+        qname(n), qclass(c), qtype(t),
+        section(sect), op(o), state(st) {}
+    virtual ~QueryTask() {}
 };
 
 typedef std::queue<QueryTask> QueryTaskQueue;
@@ -71,11 +122,17 @@
 // Data Source query
 class Query {
 public:
+    enum Status {
+        RUNNING,
+        SUCCESS,
+        FAILURE
+    };
+
     Query(Message& m, bool dnssec) {
         message_ = &m;
         want_additional = true;
         want_dnssec = dnssec;
-        status_ = QUERY_GETANSWER;
+        status_ = RUNNING;
 
         // Check message formatting
         QuestionIterator qid = message_->beginQuestion();
@@ -83,7 +140,7 @@
         if (qid != message_->endQuestion())
                 dns_throw(MalformedMessage, "too many questions");
 
-        // Populate the query tasks queue with the initial question
+        // Populate the query task queue with the initial question
         QuestionPtr query = *message_->beginQuestion();
         qname_ = &query->getName();
         qclass_ = &query->getClass();
@@ -112,13 +169,12 @@
     Message& message() { return *message_; }
     QueryTaskQueue& tasks() { return querytasks; }
 
-    QueryStatus status() { return status_; }
-    void setStatus(QueryStatus s) { status_ = s; }
-
-protected:
-    QueryStatus status_;
+    Status status() { return status_; }
+    void setStatus(Status s) { status_ = s; }
 
 private:
+    Status status_;
+
     const Name* qname_;
     const RRClass* qclass_;
     const RRType* qtype_;

Modified: branches/each-ds/src/lib/dns/cpp/message.h
==============================================================================
--- branches/each-ds/src/lib/dns/cpp/message.h (original)
+++ branches/each-ds/src/lib/dns/cpp/message.h Sat Feb 13 16:41:11 2010
@@ -528,6 +528,11 @@
     static const rcode_t RCODE_NXDOMAIN = 3;
     static const rcode_t RCODE_NOTIMP = 4;
     static const rcode_t RCODE_REFUSED = 5;
+    static const rcode_t RCODE_YXDOMAIN = 6;
+    static const rcode_t RCODE_YXRRSET = 7;
+    static const rcode_t RCODE_NXRRSET = 8;
+    static const rcode_t RCODE_NOTAUTH = 9;
+    static const rcode_t RCODE_NOTZONE = 10;
     // ...more to follow
 
     static const opcode_t OPCODE_QUERY = 0;




More information about the bind10-changes mailing list