Browse Source

- some style fixes: s/Rr/RR/, s/RDATAPTR/RdataPtr/ (RDATAPTR is still available
for compatibility)
- added some support methods to handle Rdata in more polymorphic way


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

JINMEI Tatuya 15 years ago
parent
commit
0164aa87b6

+ 4 - 4
src/lib/dns/message.cc

@@ -77,7 +77,7 @@ Message::initialize()
 }
 
 void
-Message::addRrset(section_t section, RRsetPtr rrsetp)
+Message::addRRset(section_t section, RRsetPtr rrsetp)
 {
     if (section >= SECTION_MAX)
         throw DNSInvalidMessageSection();
@@ -90,7 +90,7 @@ void
 Message::addQuestion(const Name& qname, const RRClass& qclass,
                       const RRType& qtype)
 {
-    addRrset(SECTION_QUESTION, RRsetPtr(new Question(qname, qclass, qtype)));
+    addRRset(SECTION_QUESTION, RRsetPtr(new Question(qname, qclass, qtype)));
 }
 
 void
@@ -185,7 +185,7 @@ Message::parse_question()
 
         RRType rrtype(buffer_->readUint16());
         RRClass rrclass(buffer_->readUint16());
-        addRrset(SECTION_QUESTION,
+        addRRset(SECTION_QUESTION,
                  RRsetPtr(new Question(name, rrclass, rrtype))); 
     }
 }
@@ -300,7 +300,7 @@ struct MatchRR : public std::binary_function<RRsetPtr, RR, bool> {
 };
 
 void
-Message::addRr(section_t section, const RR& rr)
+Message::addRR(section_t section, const RR& rr)
 {
     std::vector<RRsetPtr>::iterator it;
     it = find_if(sections_[section].begin(), sections_[section].end(),

+ 4 - 4
src/lib/dns/message.h

@@ -91,14 +91,14 @@ public:
     //     of RR in the message
     const std::vector<RRsetPtr>& getSection(section_t section) const
     { return (sections_[section]); }
-    void addRrset(section_t section, RRsetPtr rrset);
+    void addRRset(section_t section, RRsetPtr rrset);
     // addQuestion() is redundant in that it's a special case of add_rrset,
     // but it'd be convenient for general purpose applications.
     void addQuestion(const Name& qname, const RRClass& qclass,
                      const RRType& qtype);
-    void removeRrset(section_t section, RRsetPtr rrset);
-    void addRr(section_t section, const RR& rr);
-    void removeRr(section_t section, const RR& rr);
+    void removeRRset(section_t section, RRsetPtr rrset);
+    void addRR(section_t section, const RR& rr);
+    void removeRR(section_t section, const RR& rr);
 
     // should we separate methods for different EDNS0-related
     // parameters/options?  it would probably be better to have a

+ 3 - 3
src/lib/dns/message_unittest.cc

@@ -99,14 +99,14 @@ TEST_F(MessageTest, makeResponse)
 TEST_F(MessageTest, addRr)
 {
     // Add one RR to the answer section.
-    response.addRr(SECTION_ANSWER, RR(Name("www.example.com"), RRClass::IN,
+    response.addRR(SECTION_ANSWER, RR(Name("www.example.com"), RRClass::IN,
                                        RRType::A, TTL(3600), A("192.0.2.1")));
     EXPECT_EQ("www.example.com. 3600 IN A 192.0.2.1",
               (**response.getSection(SECTION_ANSWER).begin()).toText());
 
     // Add another RR of the same RRset with a larger TTL.  The original
     // (smaller) TTL should remain.
-    response.addRr(SECTION_ANSWER, RR(Name("www.example.com"), RRClass::IN,
+    response.addRR(SECTION_ANSWER, RR(Name("www.example.com"), RRClass::IN,
                                        RRType::A, TTL(7200), A("192.0.2.2")));
     EXPECT_EQ("www.example.com. 3600 IN A 192.0.2.1\n"
               "www.example.com. 3600 IN A 192.0.2.2",
@@ -114,7 +114,7 @@ TEST_F(MessageTest, addRr)
 
     // Add one more RR of the same RRset with a smaller TTL.  The new (smaller)
     // TTL should replace with the old one.
-    response.addRr(SECTION_ANSWER, RR(Name("www.example.com"), RRClass::IN,
+    response.addRR(SECTION_ANSWER, RR(Name("www.example.com"), RRClass::IN,
                                        RRType::A, TTL(1800), A("192.0.2.3")));
     EXPECT_EQ("www.example.com. 1800 IN A 192.0.2.1\n"
               "www.example.com. 1800 IN A 192.0.2.2\n"

+ 75 - 17
src/lib/dns/rrset.cc

@@ -20,11 +20,16 @@
 #include <arpa/inet.h>
 
 #include <stdexcept>
-#include <cstring>
+//#include <cstring>
+#include <utility>
+#include <map>
 
 #include <dns/buffer.h>
 #include <dns/rrset.h>
 
+using std::pair;
+using std::map;
+
 using isc::dns::RRClass;
 using isc::dns::RRType;
 using isc::dns::TTL;
@@ -111,6 +116,64 @@ TTL::toWire(Buffer& buffer) const
     buffer.writeUint32(ttlval_);
 }
 
+typedef Rdata* (*RdataFactory)(const std::string& text_rdata);
+typedef pair<RRClass, RRType> RRClassTypePair;
+static map<RRClassTypePair, RdataFactory> rdata_factory_repository;
+
+struct RdataFactoryRegister {
+public:
+    RdataFactoryRegister();
+    ~RdataFactoryRegister() {}
+private:
+};
+
+static RdataFactoryRegister rdata_factory;
+
+Rdata *
+createADataFromText(const std::string& text_rdata)
+{
+    return (new A(text_rdata));
+}
+
+Rdata *
+createAAAADataFromText(const std::string& text_rdata)
+{
+    return (new AAAA(text_rdata));
+}
+
+Rdata *
+createNSDataFromText(const std::string& text_rdata)
+{
+    return (new NS(text_rdata));
+}
+
+RdataFactoryRegister::RdataFactoryRegister()
+{
+    rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
+                                    (RRClassTypePair(RRClass::IN, RRType::A),
+                                     createADataFromText));
+    rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
+                                    (RRClassTypePair(RRClass::IN, RRType::AAAA),
+                                     createAAAADataFromText));
+    //XXX: NS belongs to the 'generic' class.  should revisit it.
+    rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
+                                    (RRClassTypePair(RRClass::IN, RRType::NS),
+                                     createNSDataFromText));
+}
+
+Rdata *
+Rdata::fromText(const RRClass& rrclass, const RRType& rrtype,
+                const std::string& text_rdata)
+{
+    map<RRClassTypePair, RdataFactory>::const_iterator entry;
+    entry = rdata_factory_repository.find(RRClassTypePair(rrclass, rrtype));
+    if (entry != rdata_factory_repository.end()) {
+        return (entry->second(text_rdata));
+    }
+
+    throw DNSInvalidRRType();
+}
+
 A::A(const std::string& addrstr)
 {
     if (inet_pton(AF_INET, addrstr.c_str(), &addr_) != 1)
@@ -215,7 +278,7 @@ RRset::toText() const
 {
     std::string s;
 
-    for (std::vector<Rdata::RDATAPTR>::const_iterator it = rdatalist_.begin();
+    for (std::vector<Rdata::RdataPtr>::const_iterator it = rdatalist_.begin();
          it != rdatalist_.end();
          ++it)
     {
@@ -230,7 +293,7 @@ RRset::toText() const
 }
 
 void
-RRset::addRdata(Rdata::RDATAPTR rdata)
+RRset::addRdata(Rdata::RdataPtr rdata)
 {
     if (rdata->getType() != rrtype_)
         throw DNSRRtypeMismatch();
@@ -247,7 +310,7 @@ RRset::toWire(Buffer& buffer, NameCompressor& compressor, section_t section)
     // section is not currently used.  will be, when we implement rrset-order
     // etc.
 
-    for (std::vector<Rdata::RDATAPTR>::iterator it = rdatalist_.begin();
+    for (std::vector<Rdata::RdataPtr>::iterator it = rdatalist_.begin();
          it != rdatalist_.end();
          ++it, ++num_rrs)
     {
@@ -286,17 +349,12 @@ RR::RR(const Name& name, const RRClass& rrclass, const RRType& rrtype,
        const TTL& ttl, const Rdata::Rdata& rdata) :
     rrset_(name, rrclass, rrtype, ttl)
 {
-    // XXX: this implementation is BAD.  we took the ugly bad fastest approach
-    // for rapid experiment.  should rewrite it.
-    if (rrtype == RRType::A) {
-        rrset_.addRdata(Rdata::RDATAPTR(new A(rdata.toText())));
-    } else if (rrtype == RRType::AAAA) {
-        rrset_.addRdata(Rdata::RDATAPTR(new AAAA(rdata.toText())));
-    } else if (rrtype == RRType::NS) {
-        rrset_.addRdata(Rdata::RDATAPTR(new NS(rdata.toText())));
-    } else {
-        // XXX
-        throw std::runtime_error("RR constructor encountered "
-                                 "an unsupported type");
-    }
+    rrset_.addRdata(Rdata::RdataPtr(rdata.copy()));
+}
+
+RR::RR(const Name& name, const RRClass& rrclass, const RRType& rrtype,
+       const TTL& ttl, Rdata::RdataPtr rdata) :
+    rrset_(name, rrclass, rrtype, ttl)
+{
+    rrset_.addRdata(rdata);
 }

+ 21 - 9
src/lib/dns/rrset.h

@@ -53,6 +53,8 @@ public:
     { return (classval_ == other.classval_); }
     bool operator!=(const RRClass& other) const
     { return (classval_ != other.classval_); }
+    bool operator<(const RRClass& other) const
+    { return (classval_ < other.classval_); }
 
     // (Some) well-known RRclass constants
     static const RRClass IN;
@@ -73,6 +75,8 @@ public:
     { return (typeval_ == other.typeval_); }
     bool operator!=(const RRType& other) const
     { return (typeval_ != other.typeval_); }
+    bool operator<(const RRType& other) const
+    { return (typeval_ < other.typeval_); }
 
     // (Some) Well-known RRtype constants
     static const RRType A;
@@ -113,10 +117,11 @@ namespace Rdata {
 // if we worry about data copy, we may have to use
 // shared pointers at the cost of depending on boost.
 class Rdata;
-typedef boost::shared_ptr<Rdata> RDATAPTR;
+typedef boost::shared_ptr<Rdata> RDATAPTR; // for compatibility
+typedef boost::shared_ptr<Rdata> RdataPtr;
 // if we want to avoid the dependency, use this; but we'll have
 // to care much more about resource leak.
-//typedef Rdata * RDATAPTR;
+//typedef Rdata * RdataPtr;
 
 // Abstract RDATA class
 class Rdata {
@@ -130,6 +135,10 @@ public:
     // need generic method for getting n-th field? c.f. ldns
     // e.g. string getField(int n);
 
+    // A semi polymorphic factory.
+    static Rdata* fromText(const RRClass& rrclass, const RRType& rrtype,
+                           const std::string& text_rdata);
+
     // polymorphic copy constructor (XXX should revisit it)
     virtual Rdata* copy() const = 0;
 };
@@ -232,7 +241,7 @@ public:
     virtual std::string toText() const = 0;
     virtual int toWire(Buffer& buffer, NameCompressor& compressor,
                         section_t section) = 0;
-    virtual void addRdata(Rdata::RDATAPTR rdata) = 0;
+    virtual void addRdata(Rdata::RdataPtr rdata) = 0;
     virtual unsigned int countRdata() const = 0;
     virtual const Name& getName() const = 0;
     virtual const RRClass& getClass() const = 0;
@@ -248,7 +257,7 @@ public:
                    const RRType &rrtype, const TTL &ttl) :
         name_(name), rrclass_(rrclass), rrtype_(rrtype), ttl_(ttl) {}
     unsigned int countRdata() const { return (rdatalist_.size()); }
-    void addRdata(Rdata::RDATAPTR rdata);
+    void addRdata(Rdata::RdataPtr rdata);
     void removeRdata(const Rdata::Rdata& rdata);
     std::string toText() const;
     int toWire(Buffer& buffer, NameCompressor& compressor, section_t section);
@@ -258,7 +267,7 @@ public:
     const TTL& getTtl() const { return (ttl_); }
     // once constructed, only TTL and rdatalist can be modified.
     void setTtl(const TTL& ttl) { ttl_ = ttl; }
-    const std::vector<Rdata::RDATAPTR>& getRdatalist() const
+    const std::vector<Rdata::RdataPtr>& getRdatalist() const
     { return (rdatalist_); }
     template <typename T> void getRdatalist(std::vector<T>&) const;
 private:
@@ -266,7 +275,7 @@ private:
     RRClass rrclass_;
     RRType rrtype_;
     TTL ttl_;
-    std::vector<Rdata::RDATAPTR> rdatalist_;
+    std::vector<Rdata::RdataPtr> rdatalist_;
 };
 
 //
@@ -287,7 +296,7 @@ public:
     const RRType& getType() const { return (rrtype_); }
     const TTL& getTtl() const { return (ttl_); } // XXX
     void setTtl(const TTL& ttl) {}              // XXX
-    void addRdata(Rdata::RDATAPTR rdata) {}     // XXX
+    void addRdata(Rdata::RdataPtr rdata) {}     // XXX
 private:
     Name name_;
     RRClass rrclass_;
@@ -300,7 +309,7 @@ template <typename T>
 void
 RRset::getRdatalist(std::vector<T>& v) const
 {
-    std::vector<Rdata::RDATAPTR>::const_iterator it;
+    std::vector<Rdata::RdataPtr>::const_iterator it;
     for (it = rdatalist_.begin(); it != rdatalist_.end(); ++it) {
         const T& concreteRdata = static_cast<const T&>(**it); // XXX
         if (T::getTypeStatic() != (**it).getType()) {
@@ -322,12 +331,15 @@ public:
     explicit RR(const Name& name, const RRClass& rrclass,
                 const RRType& rrtype, const TTL& ttl,
                 const Rdata::Rdata& rdata);
+    explicit RR(const Name& name, const RRClass& rrclass,
+                const RRType& rrtype, const TTL& ttl,
+                Rdata::RdataPtr rdata);
     std::string toText() const { return (rrset_.toText()); }
     const Name& getName() const { return (rrset_.getName()); }
     const RRClass& getClass() const { return (rrset_.getClass()); }
     const RRType& getType() const { return (rrset_.getType()); }
     const TTL& getTtl() const { return (rrset_.getTtl()); }
-    const Rdata::RDATAPTR getRdata() const
+    const Rdata::RdataPtr getRdata() const
     { return (*rrset_.getRdatalist().begin()); }
     void setTtl(const TTL& ttl) { rrset_.setTtl(ttl); }
 private:

+ 24 - 4
src/lib/dns/rrset_unittest.cc

@@ -25,7 +25,8 @@ using isc::dns::Name;
 using isc::dns::RRClass;
 using isc::dns::RRType;
 using isc::dns::TTL;
-using isc::dns::Rdata::RDATAPTR;
+using isc::dns::Rdata::RdataPtr;
+using isc::dns::Rdata::Rdata;
 using isc::dns::Rdata::IN::A;
 using isc::dns::Rdata::IN::AAAA;
 using isc::dns::Rdata::Generic::NS;
@@ -84,6 +85,18 @@ TEST_F(TTLTest, getValue)
     EXPECT_EQ(0, ttl0.getValue());
 }
 
+// The fixture for testing generic Rdata class
+class RdataTest : public ::testing::Test {
+protected:
+    RdataTest() {}
+};
+
+TEST_F(RdataTest, fromToText)
+{
+    EXPECT_EQ("192.0.2.1",
+              Rdata::fromText(RRClass::IN, RRType::A, "192.0.2.1")->toText());
+}
+
 // The fixture for testing class IN/A Rdata
 class Rdata_IN_A_Test : public ::testing::Test {
 protected:
@@ -129,9 +142,9 @@ protected:
         rrset_a(Name("www.example.com"), RRClass::IN, RRType::A, TTL(3600)),
         rrset_aaaa(Name("ns.example.net"), RRClass::IN, RRType::AAAA, TTL(60))
     {
-        rrset_a.addRdata(RDATAPTR(new A("192.0.2.1")));
-        rrset_a.addRdata(RDATAPTR(new A("192.0.2.255")));
-        rrset_aaaa.addRdata(RDATAPTR(new AAAA("2001:db8::1234")));
+        rrset_a.addRdata(RdataPtr(new A("192.0.2.1")));
+        rrset_a.addRdata(RdataPtr(new A("192.0.2.255")));
+        rrset_aaaa.addRdata(RdataPtr(new AAAA("2001:db8::1234")));
     }
           
     RRset rrset_a;
@@ -197,4 +210,11 @@ TEST_F(RRTest, toText)
     EXPECT_EQ("ns.example.net. 60 IN AAAA 2001:db8::1234", rr_aaaa.toText());
     EXPECT_EQ("example.net. 1800 IN NS ns.example.net.", rr_ns.toText());
 }
+
+TEST_F(RRTest, construtFromRdataPtr)
+{
+    EXPECT_EQ("www.example.com. 3600 IN A 192.0.2.1",
+              RR(Name("www.example.com"), RRClass::IN, RRType::A, TTL(3600),
+                 RdataPtr(new A("192.0.2.1"))).toText());
+}
 }