[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