Commit e3038321 authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

Merge branch 'trac1839'

parents 3acb0511 0b20f8d3
......@@ -17,6 +17,7 @@
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <util/buffer.h>
#include <dns/messagerenderer.h>
......@@ -71,7 +72,10 @@ AbstractRRset::toText() const {
return (s);
}
namespace {
namespace { // unnamed namespace
// FIXME: This method's code should somehow be unified with
// BasicRRsetImpl::toWire() below to avoid duplication.
template <typename T>
inline unsigned int
rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) {
......@@ -124,7 +128,8 @@ rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) {
return (n);
}
}
} // end of unnamed namespace
unsigned int
AbstractRRset::toWire(OutputBuffer& buffer) const {
......@@ -164,6 +169,9 @@ public:
BasicRRsetImpl(const Name& name, const RRClass& rrclass,
const RRType& rrtype, const RRTTL& ttl) :
name_(name), rrclass_(rrclass), rrtype_(rrtype), ttl_(ttl) {}
unsigned int toWire(AbstractMessageRenderer& renderer, size_t limit) const;
Name name_;
RRClass rrclass_;
RRType rrtype_;
......@@ -174,6 +182,58 @@ public:
vector<ConstRdataPtr> rdatalist_;
};
// FIXME: This method's code should somehow be unified with
// rrsetToWire() above to avoid duplication.
unsigned int
BasicRRsetImpl::toWire(AbstractMessageRenderer& renderer, size_t limit) const {
if (rdatalist_.empty()) {
// empty rrsets are only allowed for classes ANY and NONE
if (rrclass_ != RRClass::ANY() &&
rrclass_ != RRClass::NONE()) {
isc_throw(EmptyRRset, "toWire() is attempted for an empty RRset");
}
// For an empty RRset, write the name, type, class and TTL once,
// followed by empty rdata.
name_.toWire(renderer);
rrtype_.toWire(renderer);
rrclass_.toWire(renderer);
ttl_.toWire(renderer);
renderer.writeUint16(0);
// Still counts as 1 'rr'; it does show up in the message
return (1);
}
unsigned int n = 0;
// sort the set of Rdata based on rrset-order and sortlist, and possible
// other options. Details to be considered.
BOOST_FOREACH(const ConstRdataPtr& rdata, rdatalist_) {
const size_t pos0 = renderer.getLength();
assert(pos0 < 65536);
name_.toWire(renderer);
rrtype_.toWire(renderer);
rrclass_.toWire(renderer);
ttl_.toWire(renderer);
const size_t pos = renderer.getLength();
renderer.skip(sizeof(uint16_t)); // leave the space for RDLENGTH
rdata->toWire(renderer);
renderer.writeUint16At(renderer.getLength() - pos - sizeof(uint16_t),
pos);
if (limit > 0 && renderer.getLength() > limit) {
// truncation is needed
renderer.trim(renderer.getLength() - pos0);
return (n);
}
++n;
}
return (n);
}
BasicRRset::BasicRRset(const Name& name, const RRClass& rrclass,
const RRType& rrtype, const RRTTL& ttl)
{
......@@ -236,7 +296,12 @@ BasicRRset::toWire(OutputBuffer& buffer) const {
unsigned int
BasicRRset::toWire(AbstractMessageRenderer& renderer) const {
return (AbstractRRset::toWire(renderer));
const unsigned int rrs_written = impl_->toWire(renderer,
renderer.getLengthLimit());
if (impl_->rdatalist_.size() > rrs_written) {
renderer.setTruncated();
}
return (rrs_written);
}
RRset::RRset(const Name& name, const RRClass& rrclass,
......@@ -259,15 +324,13 @@ RRset::getRRsigDataCount() const {
unsigned int
RRset::toWire(OutputBuffer& buffer) const {
unsigned int rrs_written;
rrs_written = rrsetToWire<OutputBuffer>(*this, buffer, 0);
unsigned int rrs_written = BasicRRset::toWire(buffer);
if (getRdataCount() > rrs_written) {
return (rrs_written);
}
if (rrsig_) {
rrs_written += rrsetToWire<OutputBuffer>(*(rrsig_.get()), buffer, 0);
rrs_written += rrsig_->toWire(buffer);
}
return (rrs_written);
......@@ -275,24 +338,17 @@ RRset::toWire(OutputBuffer& buffer) const {
unsigned int
RRset::toWire(AbstractMessageRenderer& renderer) const {
unsigned int rrs_written;
rrs_written =
rrsetToWire<AbstractMessageRenderer>(*this, renderer,
renderer.getLengthLimit());
unsigned int rrs_written = BasicRRset::toWire(renderer);
if (getRdataCount() > rrs_written) {
renderer.setTruncated();
return (rrs_written);
}
if (rrsig_) {
rrs_written +=
rrsetToWire<AbstractMessageRenderer>(*(rrsig_.get()), renderer,
renderer.getLengthLimit());
}
rrs_written += rrsig_->toWire(renderer);
if (getRdataCount() + getRRsigDataCount() > rrs_written) {
renderer.setTruncated();
if (getRdataCount() + getRRsigDataCount() > rrs_written) {
renderer.setTruncated();
}
}
return (rrs_written);
......
......@@ -211,11 +211,13 @@ TEST_F(RRsetTest, toWireBuffer) {
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
buffer.getLength(), &wiredata[0], wiredata.size());
// toWire() cannot be performed for an empty RRset.
// toWire() cannot be performed for an empty RRset except when
// class=ANY or class=NONE.
buffer.clear();
EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
// Unless it is type ANY or None
// When class=ANY or class=NONE, toWire() can also be performed for
// an empty RRset.
buffer.clear();
rrset_any_a_empty.toWire(buffer);
wiredata.clear();
......@@ -240,25 +242,26 @@ TEST_F(RRsetTest, toWireRenderer) {
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
renderer.getLength(), &wiredata[0], wiredata.size());
// toWire() cannot be performed for an empty RRset.
buffer.clear();
EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
// toWire() cannot be performed for an empty RRset except when
// class=ANY or class=NONE.
renderer.clear();
EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
// Unless it is type ANY or None
// toWire() can also be performed for an empty RRset.
buffer.clear();
rrset_any_a_empty.toWire(buffer);
// When class=ANY or class=NONE, toWire() can also be performed for
// an empty RRset.
renderer.clear();
rrset_any_a_empty.toWire(renderer);
wiredata.clear();
UnitTestUtil::readWireData("rrset_toWire3", wiredata);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
buffer.getLength(), &wiredata[0], wiredata.size());
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
renderer.getLength(), &wiredata[0], wiredata.size());
buffer.clear();
rrset_none_a_empty.toWire(buffer);
renderer.clear();
rrset_none_a_empty.toWire(renderer);
wiredata.clear();
UnitTestUtil::readWireData("rrset_toWire4", wiredata);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
buffer.getLength(), &wiredata[0], wiredata.size());
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
renderer.getLength(), &wiredata[0], wiredata.size());
}
// test operator<<. We simply confirm it appends the result of 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