Browse Source

added an experimental implementation of "optimized built-in answers".
this version records pre-rendered authors/version.bind answers and reuses
them to build responses very efficiently.
This implementation intends to show how we can customize the RRset class
by inheritance from the base abstract class to optimize response generation.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@562 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya 15 years ago
parent
commit
81f56e2daa

+ 1 - 0
src/bin/parkinglot/Makefile.am

@@ -5,6 +5,7 @@ parkinglot_SOURCES = common.cc common.h zoneset.h zoneset.cc parkinglot.cc
 parkinglot_SOURCES += parkinglot.h main.cc
 parkinglot_SOURCES += data_source_plot.h data_source_plot.cc
 parkinglot_SOURCES += data_source.h data_source.cc
+parkinglot_SOURCES += builtin.h builtin.cc
 parkinglot_LDADD =  $(top_srcdir)/src/lib/dns/cpp/.libs/libdns.a
 parkinglot_LDADD += $(top_srcdir)/src/lib/config/cpp/libclient.a
 parkinglot_LDADD += $(top_srcdir)/src/lib/cc/cpp/libcc.a

+ 217 - 0
src/bin/parkinglot/builtin.cc

@@ -0,0 +1,217 @@
+// 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.
+
+// $Id$
+
+#include <string>
+#include <vector>
+
+#include <dns/cpp/buffer.h>
+#include <dns/cpp/messagerenderer.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/rdata.h>
+#include <dns/cpp/rrclass.h>
+#include <dns/cpp/rrtype.h>
+#include <dns/cpp/rrttl.h>
+#include <dns/cpp/rrset.h>
+
+#include "builtin.h"
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+namespace {
+const Name authors_name("authors.bind");
+const Name version_name("version.bind");
+
+const char* authors[] = {
+    "Han Feng",
+    "Kazunori Fujiwara",
+    "Michael Graff",
+    "Evan Hunt",
+    "Jelte Jansen",
+    "Jin Jian",
+    "JINMEI Tatuya",
+    "Naoki Kambe",
+    "Shane Kerr",
+    "Zhang Likun",
+    "Jeremy C. Reed",
+    NULL
+};
+
+const char* version[] = {
+    "BIND10 0.0.1",
+    NULL
+};
+
+const char* author_authorities[] = {
+    "authors.bind",
+    NULL
+};
+
+const char* version_authorities[] = {
+    "version.bind",
+    NULL
+};
+
+class BuiltinRRset : public AbstractRRset {
+private:
+    BuiltinRRset(const BuiltinRRset& source);
+    void operator=(const BuiltinRRset& source);
+public:
+    BuiltinRRset(const Name& name, const RRType& rrtype,
+                 const char** rdata_string_list);
+    virtual void addRdata(const rdata::RdataPtr rdata)
+    {
+        // ignore it (or we might throw an exception)
+    }
+    virtual unsigned int getRdataCount() const { return (num_rdata_); }
+    virtual const Name& getName() const { return (name_); }
+    virtual const RRClass& getClass() const { return (rrclass_); }
+    virtual const RRType& getType() const { return (rrtype_); }
+    virtual const RRTTL& getTTL() const { return (rrttl_); }
+    virtual void setTTL(const RRTTL& ttl)
+    {
+        // ignore it (or we might throw an exception)
+    }
+    virtual unsigned int toWire(MessageRenderer& renderer) const;
+    virtual RdataIteratorPtr getRdataIterator() const;
+
+    const Name name_;
+    const RRType rrtype_;
+    const RRClass rrclass_;
+    const RRTTL rrttl_;
+    vector<RdataPtr> rdatavector_;
+    unsigned int num_rdata_;
+    OutputBuffer wire_data_;    // pre-rendered RRset
+    size_t data_offset_;        // offset to the RRset data
+
+    static const size_t DATA_OFFSET = 12; // length of DNS header
+};
+
+class BuiltinRdataIterator : public RdataIterator {
+private:
+    BuiltinRdataIterator() {}
+public:
+    BuiltinRdataIterator(const vector<RdataPtr>& datavector) :
+        datavector_(&datavector) {}
+    ~BuiltinRdataIterator() {}
+    virtual void first() { it_ = datavector_->begin(); }
+    virtual void next() { ++it_; }
+    virtual const rdata::Rdata& getCurrent() const { return (**it_); }
+    virtual bool isLast() const { return (it_ == datavector_->end()); }
+private:
+    const vector<RdataPtr>* datavector_;
+    vector<RdataPtr>::const_iterator it_;
+};
+}
+
+BuiltinRRset::BuiltinRRset(const Name& name, const RRType& rrtype,
+                           const char** rdata_string_list) :
+    name_(name), rrtype_(rrtype), rrclass_(RRClass::CH()), rrttl_(RRTTL(0)),
+    num_rdata_(0), wire_data_(512)
+{
+    MessageRenderer renderer(wire_data_);
+    renderer.skip(DATA_OFFSET); // leave the space for the DNS header
+    renderer.writeName(name);
+    data_offset_ = renderer.getLength(); // remember the start position
+
+    RRset tmprrset(name, rrclass_, rrtype_, rrttl_);
+
+    for (int i = 0; rdata_string_list[i] != NULL; ++i) {
+        RdataPtr rdata = createRdata(rrtype_, rrclass_,
+                                     string(rdata_string_list[i]));
+        rdatavector_.push_back(rdata);
+        tmprrset.addRdata(rdata);
+    }
+
+    // pre-render the RRset
+    tmprrset.toWire(renderer);
+    num_rdata_ = rdatavector_.size();
+}
+
+unsigned int
+BuiltinRRset::toWire(MessageRenderer& renderer) const
+{
+    // XXX: we should confirm the query name matches the pre-rendered data
+    // and it's stored in the Question section.  This proof-of-concept
+    // implementation omits the check for brevity.
+    renderer.writeData(static_cast<const uint8_t*>(wire_data_.getData())
+                       + data_offset_, wire_data_.getLength() - data_offset_);
+    return (num_rdata_);
+}
+
+RdataIteratorPtr
+BuiltinRRset::getRdataIterator() const
+{
+    return (RdataIteratorPtr(new BuiltinRdataIterator(rdatavector_)));
+}
+
+struct BuiltinRRsetsImpl {
+    BuiltinRRsetsImpl(const Name& answer_name, const char** answers,
+                      const char** authorities);
+    RRsetPtr rrset_answer;
+    RRsetPtr rrset_authority;
+};
+
+BuiltinRRsetsImpl::BuiltinRRsetsImpl(const Name& answer_name,
+                                     const char** answers,
+                                     const char** authorities)
+{
+    rrset_answer = RRsetPtr(new BuiltinRRset(answer_name, RRType::TXT(),
+                                             answers));
+    rrset_authority = RRsetPtr(new BuiltinRRset(answer_name, RRType::NS(),
+                                                authorities));
+}
+
+BuiltinRRsets::BuiltinRRsets(const Name& name,
+                             const char** answers,
+                             const char** authorities)
+{
+    impl_ = new BuiltinRRsetsImpl(name, answers, authorities);
+}
+
+BuiltinRRsets::~BuiltinRRsets()
+{
+    delete impl_;
+}
+
+RRsetPtr
+BuiltinRRsets::getAnswer() const
+{
+    return (impl_->rrset_answer);
+}
+
+RRsetPtr
+BuiltinRRsets::getAuthority() const
+{
+    return (impl_->rrset_authority);
+}
+
+const BuiltinRRsets&
+getBuiltinAuthors()
+{
+    static BuiltinRRsets builtin_version(authors_name, authors,
+                                         author_authorities);
+    return (builtin_version);
+}
+
+const BuiltinRRsets&
+getBuiltinVersion()
+{
+    static BuiltinRRsets builtin_version(version_name, version,
+                                         version_authorities);
+    return (builtin_version);
+}

+ 49 - 0
src/bin/parkinglot/builtin.h

@@ -0,0 +1,49 @@
+// 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.
+
+// $Id$
+
+#ifndef __BUILTIN_H
+#define __BUILTIN_H 1
+
+#include <boost/shared_ptr.hpp>
+
+#include <dns/cpp/name.h>
+#include <dns/cpp/rrset.h>
+
+struct BuiltinRRsetsImpl;
+
+class isc::dns::Name;
+
+class BuiltinRRsets {
+public:
+    BuiltinRRsets(const isc::dns::Name& name, const char** answers,
+                  const char** authorities);
+    ~BuiltinRRsets();
+    isc::dns::RRsetPtr getAnswer() const;
+    isc::dns::RRsetPtr getAuthority() const;
+private:
+    BuiltinRRsets(const BuiltinRRsets& source);
+    void operator=(const BuiltinRRsets& source);
+    BuiltinRRsetsImpl* impl_;
+};
+
+const BuiltinRRsets& getBuiltinAuthors();
+const BuiltinRRsets& getBuiltinVersion();
+
+#endif // __BUILTIN_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 17 - 1
src/bin/parkinglot/parkinglot.cc

@@ -36,6 +36,7 @@
 #include <cc/cpp/data.h>
 
 #include "common.h"
+#include "builtin.h"
 #include "parkinglot.h"
 
 #include <boost/lexical_cast.hpp>
@@ -106,6 +107,11 @@ struct GlueInserter {
 };
 }
 
+namespace {
+const Name authors_name("authors.bind");
+const Name version_name("version.bind");
+}
+
 void
 ParkingLot::processMessage() {
     struct sockaddr_storage ss;
@@ -146,7 +152,17 @@ ParkingLot::processMessage() {
         SearchResult::status_type status;
         bool included_ns = false;
         msg.setRcode(Rcode::NOERROR());
-        if (data_source.hasZoneFor(query->getName(), zname)) {
+        if (qtype == RRType::TXT() && qclass == RRClass::CH() &&
+            name == authors_name) {
+            msg.addRRset(Section::ANSWER(), getBuiltinAuthors().getAnswer());
+            msg.addRRset(Section::AUTHORITY(),
+                         getBuiltinAuthors().getAuthority());
+        } else if (qtype == RRType::TXT() && qclass == RRClass::CH() &&
+            name == version_name) {
+            msg.addRRset(Section::ANSWER(), getBuiltinVersion().getAnswer());
+            msg.addRRset(Section::AUTHORITY(),
+                         getBuiltinVersion().getAuthority());
+        } else if (data_source.hasZoneFor(query->getName(), zname)) {
             status = data_source.addToMessage(msg, Section::ANSWER(), zname,
                                               name, qclass, qtype);
             // rcode is based on this result?