[svn] commit: r509 - in /branches/jinmei-dnsrdata/src/lib/dns/cpp: Makefile.am message.cc message.h message_unittest.cc question.cc question.h question_unittest.cc testdata/message_fromWire1 testdata/message_toWire1 unittest_util.h

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Jan 26 02:09:25 UTC 2010


Author: jinmei
Date: Tue Jan 26 02:09:25 2010
New Revision: 509

Log:
added question/rrsets iterators, some cleanups and fixes, some test cases.

Added:
    branches/jinmei-dnsrdata/src/lib/dns/cpp/message.h   (with props)
    branches/jinmei-dnsrdata/src/lib/dns/cpp/message_unittest.cc   (with props)
    branches/jinmei-dnsrdata/src/lib/dns/cpp/testdata/message_fromWire1
    branches/jinmei-dnsrdata/src/lib/dns/cpp/testdata/message_toWire1
Modified:
    branches/jinmei-dnsrdata/src/lib/dns/cpp/Makefile.am
    branches/jinmei-dnsrdata/src/lib/dns/cpp/message.cc   (contents, props changed)
    branches/jinmei-dnsrdata/src/lib/dns/cpp/question.cc   (props changed)
    branches/jinmei-dnsrdata/src/lib/dns/cpp/question.h   (props changed)
    branches/jinmei-dnsrdata/src/lib/dns/cpp/question_unittest.cc   (contents, props changed)
    branches/jinmei-dnsrdata/src/lib/dns/cpp/unittest_util.h

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/Makefile.am
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/Makefile.am (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/Makefile.am Tue Jan 26 02:09:25 2010
@@ -23,6 +23,7 @@
 run_unittests_SOURCES += rrset_unittest.cc
 run_unittests_SOURCES += question_unittest.cc
 run_unittests_SOURCES += rrparamregistry_unittest.cc
+run_unittests_SOURCES += message_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(GTEST_LDFLAGS)

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/message.cc
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/message.cc (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/message.cc Tue Jan 26 02:09:25 2010
@@ -41,235 +41,83 @@
 namespace isc {
 namespace dns {
 
-struct MessageImpl {
-    // Open issues: should we rather have a header in wire-format
-    // for efficiency?
-    qid_t qid_;
-    rcode_t rcode_;
-    opcode_t opcode_;
-    flags_t flags_;
-
-    static const unsigned int SECTION_MAX = 4; // TODO: revisit this design
-
-    int counts_[SECTION_MAX];   // TODO: revisit this definition
-    vector<QuestionPtr> questions_;
-    vector<RRsetPtr> rrsets_[SECTION_MAX];
-
-#ifdef notyet
-    // tsig/sig0: TODO
-    EDNS* edns_;
-    RRsetsSorter* sorter_;
-#endif
-
-    void parseQuestion(Message& message, InputBuffer& buffer);
-    void parseSection(Message& messge, const Section& section,
-                      InputBuffer& buffer);
-};
-
 namespace {
-inline unsigned int
-sectionCodeToId(const Section& section)
-{
-    unsigned int code = section.getCode();
-    assert(code > 1);
-    return (section.getCode() - 1);
-}
-}
-
-Message::Message() :
-    impl_(new MessageImpl())
-{}
-
-Message::~Message()
-{
-    delete impl_;
-}
-
-bool
-Message::getHeaderFlag(const MessageFlag& flag) const
-{
-    return ((impl_->flags_ & flag.getBit()) != 0);
-}
-
-void
-Message::setHeaderFlag(const MessageFlag& flag)
-{
-    impl_->flags_ |= flag.getBit();
-}
-
-void
-Message::addRRset(const Section& section, RRsetPtr rrset)
-{
-    // Note: should check duplicate (TBD)
-    impl_->rrsets_[sectionCodeToId(section)].push_back(rrset);
-}
-
-void
-Message::addQuestion(const QuestionPtr question)
-{
-    impl_->questions_.push_back(question);
-}
-
-namespace {
-template <typename T>
-struct RenderSection
-{
-    RenderSection(MessageRenderer& renderer) :
-        counter_(0), renderer_(renderer) {}
-    void operator()(const T& entry)
-    {
-        // TBD: if truncation is necessary, do something special.
-        // throw an exception, set an internal flag, etc.
-        counter_ += entry->toWire(renderer_);
-    }
-    unsigned int getTotalCount() { return (counter_); }
-    unsigned int counter_;
-    MessageRenderer& renderer_;
-};
-}
-
-void
-Message::toWire(MessageRenderer& renderer)
-{
-    uint16_t codes_and_flags;
-
-    // reserve room for the header
-    renderer.skip(HEADERLEN);
-
-    unsigned int qrcount =
-        for_each(impl_->questions_.begin(), impl_->questions_.end(),
-                 RenderSection<QuestionPtr>(renderer)).getTotalCount();
-
-    // TBD: sort RRsets in each section based on configuration policy.
-    unsigned int ancount =
-        for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
-                 impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
-                 RenderSection<RRsetPtr>(renderer)).getTotalCount();
-    unsigned int nscount =
-        for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
-                 impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
-                 RenderSection<RRsetPtr>(renderer)).getTotalCount();
-    unsigned int adcount =
-        for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
-                 impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
-                 RenderSection<RRsetPtr>(renderer)).getTotalCount();
-
-    // TBD: EDNS, TSIG, etc.
-
-    // fill in the header
-    size_t header_pos = 0;
-    renderer.writeUint16At(impl_->qid_, header_pos);
-    header_pos += sizeof(uint16_t);
-    codes_and_flags = (impl_->opcode_ << OPCODE_SHIFT) & OPCODE_MASK;
-    codes_and_flags |= (impl_->rcode_ & RCODE_MASK);
-    codes_and_flags |= (impl_->flags_ & FLAG_MASK);
-    renderer.writeUint16At(codes_and_flags, header_pos);
-    header_pos += sizeof(uint16_t);
-    // XXX: should avoid repeated pattern (TODO)
-    renderer.writeUint16At(qrcount, header_pos);
-    header_pos += sizeof(uint16_t);
-    renderer.writeUint16At(ancount, header_pos);
-    header_pos += sizeof(uint16_t);
-    renderer.writeUint16At(nscount, header_pos);
-    header_pos += sizeof(uint16_t);
-    renderer.writeUint16At(adcount, header_pos);
-    header_pos += sizeof(uint16_t);
-}
-
-void
-Message::fromWire(InputBuffer& buffer)
-{
-    if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
-        dns_throw(MessageTooShort, "");
-    }
-
-    impl_->qid_ = buffer.readUint16();
-    uint16_t codes_and_flags = buffer.readUint16();
-    impl_->opcode_ = ((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT);
-    impl_->rcode_ = (codes_and_flags & RCODE_MASK);
-    impl_->flags_ = (codes_and_flags & FLAG_MASK);
-    impl_->counts_[Section::QUESTION().getCode()] = buffer.readUint16();
-    impl_->counts_[Section::ANSWER().getCode()] = buffer.readUint16();
-    impl_->counts_[Section::AUTHORITY().getCode()] = buffer.readUint16();
-    impl_->counts_[Section::ADDITIONAL().getCode()] = buffer.readUint16();
-
-    impl_->parseQuestion(*this, buffer);
-    impl_->parseSection(*this, Section::ANSWER(), buffer);
-    impl_->parseSection(*this, Section::AUTHORITY(), buffer);
-    impl_->parseSection(*this, Section::ADDITIONAL(), buffer);
-}
-
-void
-MessageImpl::parseQuestion(Message& message, InputBuffer& buffer)
-{
-    for (unsigned int count = 0;
-         count < counts_[Section::QUESTION().getCode()];
-         count++) {
-        Name name(buffer);
-
-        if ((buffer.getLength() - buffer.getPosition()) <
-            2 * sizeof(uint16_t)) {
-            dns_throw(MessageTooShort, "");
-        }
-        RRType rrtype(buffer.readUint16());
-        RRClass rrclass(buffer.readUint16());
-
-        // XXX: need a duplicate check.  We might also want to have an optimized
-        // algorithm that requires the question section contain exactly one
-        // RR.
-
-        questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype))); 
-    }
-}
-
-namespace {
-struct MatchRR : public unary_function<RRsetPtr, bool> {
-    MatchRR(const Name& name, const RRType& rrtype, const RRClass& rrclass) :
-        name_(name), rrtype_(rrtype), rrclass_(rrclass) {}
-    bool operator()(const RRsetPtr& rrset) const
-    {
-        return (rrset->getType() == rrtype_ &&
-                rrset->getClass() == rrclass_ &&
-                rrset->getName() == name_);
-    }
-    const Name& name_;
-    const RRType& rrtype_;
-    const RRClass& rrclass_;
-};
-}
-
-void
-MessageImpl::parseSection(Message& messge, const Section& section,
-                          InputBuffer& buffer)
-{
-    for (unsigned int count = 0; count < counts_[section.getCode()]; count++) {
-        Name name(buffer);
-
-        if ((buffer.getLength() - buffer.getPosition()) <
-            2 * sizeof(uint16_t) + sizeof(uint32_t)) {
-            dns_throw(MessageTooShort, "");
-        }
-
-        RRType rrtype(buffer.readUint16());
-        RRClass rrclass(buffer.readUint16());
-        RRTTL ttl(buffer.readUint32());
-        size_t rdlen = buffer.readUint16();
-        RdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
-
-        vector<RRsetPtr>::iterator it =
-            find_if(rrsets_[sectionCodeToId(section)].begin(),
-                    rrsets_[sectionCodeToId(section)].end(),
-                    MatchRR(name, rrtype, rrclass));
-        if (it != rrsets_[sectionCodeToId(section)].end()) {
-            (*it)->setTTL(min((*it)->getTTL(), ttl));
-            (*it)->addRdata(rdata);
-        } else {
-            RRsetPtr rrset = RRsetPtr(new RRset(name, rrclass, rrtype, ttl)); 
-            rrset->addRdata(rdata);
-            rrsets_[sectionCodeToId(section)].push_back(rrset);
-        }
-    }
-}
+typedef uint16_t flags_t;
+
+// protocol constants
+static const size_t HEADERLEN = 12;
+
+static const flags_t FLAG_QR = 0x8000;
+static const flags_t FLAG_AA = 0x0400;
+static const flags_t FLAG_TC = 0x0200;
+static const flags_t FLAG_RD = 0x0100;
+static const flags_t FLAG_RA = 0x0080;
+static const flags_t FLAG_AD = 0x0020;
+static const flags_t FLAG_CD = 0x0010;
+
+static const unsigned int OPCODE_MASK = 0x7800;
+static const unsigned int OPCODE_SHIFT = 11;
+static const unsigned int RCODE_MASK = 0x000f;
+static const unsigned int FLAG_MASK = 0x8ff0;
+
+static const unsigned int MESSAGE_REPLYPRESERVE = (FLAG_RD | FLAG_CD);
+
+static const Rcode* rcodes[] = {
+    &Rcode::NOERROR(),
+    &Rcode::FORMERR(),
+    &Rcode::SERVFAIL(),
+    &Rcode::NXDOMAIN(),
+    &Rcode::NOTIMP(),
+    &Rcode::REFUSED(),
+    &Rcode::YXDOMAIN(),
+    &Rcode::YXRRSET(),
+    &Rcode::NXRRSET(),
+    &Rcode::NOTAUTH(),
+    &Rcode::NOTZONE(),
+    &Rcode::RESERVED11(),
+    &Rcode::RESERVED12(),
+    &Rcode::RESERVED13(),
+    &Rcode::RESERVED14(),
+    &Rcode::RESERVED15()
+};
+
+static const char *rcodetext[] = {
+    "NOERROR",
+    "FORMERR",
+    "SERVFAIL",
+    "NXDOMAIN",
+    "NOTIMP",
+    "REFUSED",
+    "YXDOMAIN",
+    "YXRRSET",
+    "NXRRSET",
+    "NOTAUTH",
+    "NOTZONE",
+    "RESERVED11",
+    "RESERVED12",
+    "RESERVED13",
+    "RESERVED14",
+    "RESERVED15"
+};
+
+static const Opcode* opcodes[] = {
+    &Opcode::QUERY(),
+    &Opcode::IQUERY(),
+    &Opcode::STATUS(),
+    &Opcode::RESERVED3(),
+    &Opcode::NOTIFY(),
+    &Opcode::UPDATE(),
+    &Opcode::RESERVED6(),
+    &Opcode::RESERVED7(),
+    &Opcode::RESERVED8(),
+    &Opcode::RESERVED9(),
+    &Opcode::RESERVED10(),
+    &Opcode::RESERVED11(),
+    &Opcode::RESERVED12(),
+    &Opcode::RESERVED13(),
+    &Opcode::RESERVED14(),
+    &Opcode::RESERVED15()
+};
 
 static const char *opcodetext[] = {
     "QUERY",
@@ -289,25 +137,300 @@
     "RESERVED14",
     "RESERVED15"
 };
-
-static const char *rcodetext[] = {
-    "NOERROR",
-    "FORMERR",
-    "SERVFAIL",
-    "NXDOMAIN",
-    "NOTIMP",
-    "REFUSED",
-    "YXDOMAIN",
-    "YXRRSET",
-    "NXRRSET",
-    "NOTAUTH",
-    "NOTZONE",
-    "RESERVED11",
-    "RESERVED12",
-    "RESERVED13",
-    "RESERVED14",
-    "RESERVED15"
-};
+}
+
+string
+Opcode::toText() const
+{
+    return (opcodetext[code_]);
+}
+
+string
+Rcode::toText() const
+{
+    return (rcodetext[code_]);
+}
+
+struct MessageImpl {
+    MessageImpl();
+    // Open issues: should we rather have a header in wire-format
+    // for efficiency?
+    qid_t qid_;
+    const Rcode* rcode_;
+    const Opcode* opcode_;
+    flags_t flags_;
+
+    static const unsigned int SECTION_MAX = 4; // TODO: revisit this design
+    int counts_[SECTION_MAX];   // TODO: revisit this definition
+    vector<QuestionPtr> questions_;
+    vector<RRsetPtr> rrsets_[SECTION_MAX];
+
+#ifdef notyet
+    // tsig/sig0: TODO
+    EDNS* edns_;
+    RRsetsSorter* sorter_;
+#endif
+
+    void parseQuestion(Message& message, InputBuffer& buffer);
+    void parseSection(Message& messge, const Section& section,
+                      InputBuffer& buffer);
+};
+
+MessageImpl::MessageImpl() :
+    qid_(0), rcode_(NULL), opcode_(NULL), flags_(0)
+{
+    for (int i = 0; i < SECTION_MAX; i++) {
+        counts_[i] = 0;
+    }
+}
+
+namespace {
+inline unsigned int
+sectionCodeToId(const Section& section)
+{
+    unsigned int code = section.getCode();
+    assert(code > 0);
+    return (section.getCode() - 1);
+}
+}
+
+Message::Message() :
+    impl_(new MessageImpl())
+{
+}
+
+Message::~Message()
+{
+    delete impl_;
+}
+
+bool
+Message::getHeaderFlag(const MessageFlag& flag) const
+{
+    return ((impl_->flags_ & flag.getBit()) != 0);
+}
+
+void
+Message::setHeaderFlag(const MessageFlag& flag)
+{
+    impl_->flags_ |= flag.getBit();
+}
+
+qid_t
+Message::getQid() const
+{
+    return (impl_->qid_);
+}
+
+void
+Message::setQid(qid_t qid)
+{
+    impl_->qid_ = qid;
+}
+
+const Rcode&
+Message::getRcode() const
+{
+    return (*impl_->rcode_);
+}
+
+void
+Message::setRcode(const Rcode& rcode)
+{
+    impl_->rcode_ = &rcode;
+}
+
+const Opcode&
+Message::getOpcode() const
+{
+    return (*impl_->opcode_);
+}
+
+void
+Message::setOpcode(const Opcode& opcode)
+{
+    impl_->opcode_ = &opcode;
+}
+
+void
+Message::addRRset(const Section& section, RRsetPtr rrset)
+{
+    // Note: should check duplicate (TBD)
+    impl_->rrsets_[sectionCodeToId(section)].push_back(rrset);
+}
+
+void
+Message::addQuestion(const QuestionPtr question)
+{
+    impl_->questions_.push_back(question);
+}
+
+void
+Message::addQuestion(const Question& question)
+{
+    impl_->questions_.push_back(QuestionPtr(new Question(question)));
+}
+
+namespace {
+template <typename T>
+struct RenderSection
+{
+    RenderSection(MessageRenderer& renderer) :
+        counter_(0), renderer_(renderer) {}
+    void operator()(const T& entry)
+    {
+        // TBD: if truncation is necessary, do something special.
+        // throw an exception, set an internal flag, etc.
+        counter_ += entry->toWire(renderer_);
+    }
+    unsigned int getTotalCount() { return (counter_); }
+    unsigned int counter_;
+    MessageRenderer& renderer_;
+};
+}
+
+void
+Message::toWire(MessageRenderer& renderer)
+{
+    uint16_t codes_and_flags;
+
+    // reserve room for the header
+    renderer.skip(HEADERLEN);
+
+    uint16_t qrcount =
+        for_each(impl_->questions_.begin(), impl_->questions_.end(),
+                 RenderSection<QuestionPtr>(renderer)).getTotalCount();
+
+    // TBD: sort RRsets in each section based on configuration policy.
+    uint16_t ancount =
+        for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
+                 impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
+                 RenderSection<RRsetPtr>(renderer)).getTotalCount();
+    uint16_t nscount =
+        for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
+                 impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
+                 RenderSection<RRsetPtr>(renderer)).getTotalCount();
+    uint16_t arcount =
+        for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
+                 impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
+                 RenderSection<RRsetPtr>(renderer)).getTotalCount();
+
+    // TBD: EDNS, TSIG, etc.
+
+    // fill in the header
+    size_t header_pos = 0;
+    renderer.writeUint16At(impl_->qid_, header_pos);
+    header_pos += sizeof(uint16_t);
+    codes_and_flags = (impl_->opcode_->getCode() << OPCODE_SHIFT) & OPCODE_MASK;
+    codes_and_flags |= (impl_->rcode_->getCode() & RCODE_MASK);
+    codes_and_flags |= (impl_->flags_ & FLAG_MASK);
+    renderer.writeUint16At(codes_and_flags, header_pos);
+    header_pos += sizeof(uint16_t);
+    // XXX: should avoid repeated pattern (TODO)
+    renderer.writeUint16At(qrcount, header_pos);
+    header_pos += sizeof(uint16_t);
+    renderer.writeUint16At(ancount, header_pos);
+    header_pos += sizeof(uint16_t);
+    renderer.writeUint16At(nscount, header_pos);
+    header_pos += sizeof(uint16_t);
+    renderer.writeUint16At(arcount, header_pos);
+    header_pos += sizeof(uint16_t);
+}
+
+void
+Message::fromWire(InputBuffer& buffer)
+{
+    if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
+        dns_throw(MessageTooShort, "");
+    }
+
+    impl_->qid_ = buffer.readUint16();
+    uint16_t codes_and_flags = buffer.readUint16();
+    impl_->opcode_ = opcodes[((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT)];
+    impl_->rcode_ = rcodes[(codes_and_flags & RCODE_MASK)];
+    impl_->flags_ = (codes_and_flags & FLAG_MASK);
+    impl_->counts_[Section::QUESTION().getCode()] = buffer.readUint16();
+    impl_->counts_[Section::ANSWER().getCode()] = buffer.readUint16();
+    impl_->counts_[Section::AUTHORITY().getCode()] = buffer.readUint16();
+    impl_->counts_[Section::ADDITIONAL().getCode()] = buffer.readUint16();
+
+    impl_->parseQuestion(*this, buffer);
+    impl_->parseSection(*this, Section::ANSWER(), buffer);
+    impl_->parseSection(*this, Section::AUTHORITY(), buffer);
+    impl_->parseSection(*this, Section::ADDITIONAL(), buffer);
+}
+
+void
+MessageImpl::parseQuestion(Message& message, InputBuffer& buffer)
+{
+    for (unsigned int count = 0;
+         count < counts_[Section::QUESTION().getCode()];
+         count++) {
+        Name name(buffer);
+
+        if ((buffer.getLength() - buffer.getPosition()) <
+            2 * sizeof(uint16_t)) {
+            dns_throw(MessageTooShort, "");
+        }
+        RRType rrtype(buffer.readUint16());
+        RRClass rrclass(buffer.readUint16());
+
+        // XXX: need a duplicate check.  We might also want to have an optimized
+        // algorithm that requires the question section contain exactly one
+        // RR.
+
+        questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype))); 
+    }
+}
+
+namespace {
+struct MatchRR : public unary_function<RRsetPtr, bool> {
+    MatchRR(const Name& name, const RRType& rrtype, const RRClass& rrclass) :
+        name_(name), rrtype_(rrtype), rrclass_(rrclass) {}
+    bool operator()(const RRsetPtr& rrset) const
+    {
+        return (rrset->getType() == rrtype_ &&
+                rrset->getClass() == rrclass_ &&
+                rrset->getName() == name_);
+    }
+    const Name& name_;
+    const RRType& rrtype_;
+    const RRClass& rrclass_;
+};
+}
+
+void
+MessageImpl::parseSection(Message& messge, const Section& section,
+                          InputBuffer& buffer)
+{
+    for (unsigned int count = 0; count < counts_[section.getCode()]; count++) {
+        Name name(buffer);
+
+        if ((buffer.getLength() - buffer.getPosition()) <
+            2 * sizeof(uint16_t) + sizeof(uint32_t)) {
+            dns_throw(MessageTooShort, "");
+        }
+
+        RRType rrtype(buffer.readUint16());
+        RRClass rrclass(buffer.readUint16());
+        RRTTL ttl(buffer.readUint32());
+        size_t rdlen = buffer.readUint16();
+        RdataPtr rdata = createRdata(rrtype, rrclass, buffer, rdlen);
+
+        vector<RRsetPtr>::iterator it =
+            find_if(rrsets_[sectionCodeToId(section)].begin(),
+                    rrsets_[sectionCodeToId(section)].end(),
+                    MatchRR(name, rrtype, rrclass));
+        if (it != rrsets_[sectionCodeToId(section)].end()) {
+            (*it)->setTTL(min((*it)->getTTL(), ttl));
+            (*it)->addRdata(rdata);
+        } else {
+            RRsetPtr rrset = RRsetPtr(new RRset(name, rrclass, rrtype, ttl)); 
+            rrset->addRdata(rdata);
+            rrsets_[sectionCodeToId(section)].push_back(rrset);
+        }
+    }
+}
 
 namespace {
 static const char *sectiontext[] = {
@@ -324,7 +447,7 @@
         section_(section), output_(output) {}
     void operator()(const T& entry)
     {
-        output_ += "\n;; " + string(sectiontext[section_.getCode()]) +
+        output_ += ";; " + string(sectiontext[section_.getCode()]) +
             " SECTION:\n";
         if (section_ == Section::QUESTION()) {
             output_ += ";";
@@ -341,9 +464,9 @@
 {
     string s;
 
-    s += ";; ->>HEADER<<- opcode: " + string(opcodetext[impl_->opcode_]);
+    s += ";; ->>HEADER<<- opcode: " + impl_->opcode_->toText();
     // for simplicity we don't consider extended rcode (unlike BIND9)
-    s += ", status: " + string(rcodetext[impl_->rcode_]);
+    s += ", status: " + impl_->rcode_->toText();
     s += ", id: " + boost::lexical_cast<string>(impl_->qid_);
     s += "\n;; flags: ";
     if (getHeaderFlag(MessageFlag::QR()))
@@ -370,23 +493,26 @@
         lexical_cast<string>(impl_->counts_[Section::AUTHORITY().getCode()]);
     s += ", ADDITIONAL: " +
         lexical_cast<string>(impl_->counts_[Section::ADDITIONAL().getCode()])
-        + "\n";
+        + "\n\n";
 
     if (!impl_->questions_.empty()) {
         for_each(impl_->questions_.begin(), impl_->questions_.end(),
                  SectionFormatter<QuestionPtr>(Section::QUESTION(), s));
     }
     if (!impl_->rrsets_[sectionCodeToId(Section::ANSWER())].empty()) {
-        for_each(impl_->questions_.begin(), impl_->questions_.end(),
-                 SectionFormatter<QuestionPtr>(Section::ANSWER(), s));
+        for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
+                 impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
+                 SectionFormatter<RRsetPtr>(Section::ANSWER(), s));
     }
     if (!impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].empty()) {
-        for_each(impl_->questions_.begin(), impl_->questions_.end(),
-                 SectionFormatter<QuestionPtr>(Section::AUTHORITY(), s));
+        for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
+                 impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
+                 SectionFormatter<RRsetPtr>(Section::AUTHORITY(), s));
     }
     if (!impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].empty()) {
-        for_each(impl_->questions_.begin(), impl_->questions_.end(),
-                 SectionFormatter<QuestionPtr>(Section::ADDITIONAL(), s));
+        for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
+                 impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
+                 SectionFormatter<RRsetPtr>(Section::ADDITIONAL(), s));
     }
 
     return (s);
@@ -403,5 +529,189 @@
     impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
 }
 
+///
+/// Question iterator
+///
+struct QuestionIteratorImpl {
+    QuestionIteratorImpl(const vector<QuestionPtr>::const_iterator& it) :
+        it_(it) {}
+    vector<QuestionPtr>::const_iterator it_;
+};
+
+const QuestionIterator
+Message::beginQuestion() const
+{
+    return QuestionIterator(QuestionIteratorImpl(impl_->questions_.begin()));
+}
+
+const QuestionIterator
+Message::endQuestion() const
+{
+    return QuestionIterator(QuestionIteratorImpl(impl_->questions_.end()));
+}
+
+QuestionIterator::QuestionIterator(const QuestionIteratorImpl& impl)
+{
+    impl_ = new QuestionIteratorImpl(impl.it_);
+}
+
+QuestionIterator::~QuestionIterator()
+{
+    delete impl_;
+}
+
+QuestionIterator::QuestionIterator(const QuestionIterator& source) :
+    impl_(new QuestionIteratorImpl(source.impl_->it_))
+{}
+
+void
+QuestionIterator::operator=(const QuestionIterator& source)
+{
+    if (impl_ == source.impl_) {
+        return;
+    }
+    QuestionIteratorImpl* newimpl = new QuestionIteratorImpl(source.impl_->it_);
+    delete impl_;
+    impl_ = newimpl;
+}
+
+QuestionIterator&
+QuestionIterator::operator++()
+{
+    ++(impl_->it_);
+    return (*this);
+}
+
+QuestionIterator
+QuestionIterator::operator++(int)
+{
+    QuestionIterator tmp(*this);
+    ++(*this);
+    return (tmp);
+}
+
+const QuestionPtr&
+QuestionIterator::operator*() const
+{
+    return (*(impl_->it_));
+}
+
+const QuestionPtr*
+QuestionIterator::operator->() const
+{
+    return (impl_->it_.operator->());
+}
+
+bool
+QuestionIterator::operator!=(const QuestionIterator& other) const
+{
+    return (impl_->it_ != other.impl_->it_);
+}
+
+///
+/// RRsets iterators
+///
+struct SectionIteratorImpl {
+    SectionIteratorImpl(const vector<RRsetPtr>::const_iterator& it) :
+        it_(it) {}
+    vector<RRsetPtr>::const_iterator it_;
+};
+
+const SectionIterator
+Message::beginSection(const Section& section) const
+{
+    if (section == Section::QUESTION()) {
+        dns_throw(InvalidMessageSection, "");
+    }
+
+    return SectionIterator(SectionIteratorImpl(impl_->rrsets_[sectionCodeToId(section)].begin()));
+}
+
+const SectionIterator
+Message::endSection(const Section& section) const
+{
+    if (section == Section::QUESTION()) {
+        dns_throw(InvalidMessageSection, "");
+    }
+
+    return SectionIterator(SectionIteratorImpl(impl_->rrsets_[sectionCodeToId(section)].end()));
+}
+
+SectionIterator::SectionIterator(const SectionIteratorImpl& impl)
+{
+    impl_ = new SectionIteratorImpl(impl.it_);
+}
+
+SectionIterator::~SectionIterator()
+{
+    delete impl_;
+}
+
+SectionIterator::SectionIterator(const SectionIterator& source) :
+    impl_(new SectionIteratorImpl(source.impl_->it_))
+{}
+
+void
+SectionIterator::operator=(const SectionIterator& source)
+{
+    if (impl_ == source.impl_) {
+        return;
+    }
+    SectionIteratorImpl* newimpl = new SectionIteratorImpl(source.impl_->it_);
+    delete impl_;
+    impl_ = newimpl;
+}
+
+SectionIterator&
+SectionIterator::operator++()
+{
+    ++(impl_->it_);
+    return (*this);
+}
+
+SectionIterator
+SectionIterator::operator++(int)
+{
+    SectionIterator tmp(*this);
+    ++(*this);
+    return (tmp);
+}
+
+const RRsetPtr&
+SectionIterator::operator*() const
+{
+    return (*(impl_->it_));
+}
+
+const RRsetPtr*
+SectionIterator::operator->() const
+{
+    return (impl_->it_.operator->());
+}
+
+bool
+SectionIterator::operator!=(const SectionIterator& other) const
+{
+    return (impl_->it_ != other.impl_->it_);
+}
+
+ostream&
+operator<<(ostream& os, const Opcode& opcode)
+{
+    return (os << opcode.toText());
+}
+
+ostream&
+operator<<(ostream& os, const Rcode& rcode)
+{
+    return (os << rcode.toText());
+}
+
+ostream&
+operator<<(ostream& os, const Message& message)
+{
+    return (os << message.toText());
+}
+
 } // end of namespace dns
 } // end of namespace isc

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/question_unittest.cc
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/question_unittest.cc (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/question_unittest.cc Tue Jan 26 02:09:25 2010
@@ -36,7 +36,6 @@
                      test_question(Name("example.com"), RRClass::IN(),
                                    RRType::NS()) 
     {}
-    static Question factoryFromFile(const char* datafile);
     OutputBuffer obuffer;
     MessageRenderer renderer;
     Question test_question;

Modified: branches/jinmei-dnsrdata/src/lib/dns/cpp/unittest_util.h
==============================================================================
--- branches/jinmei-dnsrdata/src/lib/dns/cpp/unittest_util.h (original)
+++ branches/jinmei-dnsrdata/src/lib/dns/cpp/unittest_util.h Tue Jan 26 02:09:25 2010
@@ -76,7 +76,6 @@
     matchName(const char* nameexp1, const char* nameexp2,
               const isc::dns::Name& name1, const isc::dns::Name& name2);
 };
-
 }
 #endif // __UNITTEST_UTIL_H
 




More information about the bind10-changes mailing list