Commit 0164aa87 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

- 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
parent db8a6b60
......@@ -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(),
......
......@@ -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
......
......@@ -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"
......
......@@ -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);
}
......@@ -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:
......
......@@ -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());
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment