Commit 000f7efd authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

[1396] Add RRset::getLength()

parent 7f9bc845
......@@ -289,6 +289,50 @@ BasicRRset::toText() const {
return (AbstractRRset::toText());
}
uint16_t
BasicRRset::getLength() const {
uint16_t length = 0;
RdataIteratorPtr it = getRdataIterator();
if (it->isLast()) {
// empty rrsets are only allowed for classes ANY and NONE
if (getClass() != RRClass::ANY() &&
getClass() != RRClass::NONE()) {
isc_throw(EmptyRRset, "getLength() is attempted for an empty RRset");
}
// For an empty RRset, write the name, type, class and TTL once,
// followed by empty rdata.
length += getName().getLength();
length += 2; // TYPE field
length += 2; // CLASS field
length += 2; // TTL field
length += 2; // RDLENGTH field (=0 in wire format)
return (length);
}
do {
// This is a size_t as some of the following additions may
// overflow due to a programming mistake somewhere.
size_t rrlen = 0;
rrlen += getName().getLength();
rrlen += 2; // TYPE field
rrlen += 2; // CLASS field
rrlen += 2; // TTL field
rrlen += 2; // RDLENGTH field
rrlen += it->getCurrent().getLength();
assert(length + rrlen < 65536);
length += rrlen;
it->next();
} while (!it->isLast());
return (length);
}
unsigned int
BasicRRset::toWire(OutputBuffer& buffer) const {
return (AbstractRRset::toWire(buffer));
......@@ -322,6 +366,21 @@ RRset::getRRsigDataCount() const {
}
}
uint16_t
RRset::getLength() const {
uint16_t length = BasicRRset::getLength();
if (rrsig_) {
const uint16_t rrsigs_length = rrsig_->getLength();
// the uint16_ts are promoted to ints during addition below, so
// it won't overflow a 16-bit register.
assert(length + rrsigs_length < 65536);
length += rrsigs_length;
}
return (length);
}
unsigned int
RRset::toWire(OutputBuffer& buffer) const {
unsigned int rrs_written = BasicRRset::toWire(buffer);
......
......@@ -206,6 +206,20 @@ public:
/// \return The number of \c Rdata objects contained.
virtual unsigned int getRdataCount() const = 0;
/// \brief Get the wire format length of the \c AbstractRRset.
///
/// This method returns the wire format length of the
/// \c AbstractRRset, which is calculated by summing the individual
/// lengths of the various fields that make up each RR.
///
/// NOTE: When including name lengths, the allocation for
/// uncompressed name wire format representation is used.
///
/// \return The length of the wire format representation of the
/// \c AbstractRRset.
/// \throw \c EmptyRRset if the \c AbstractRRset is empty.
virtual uint16_t getLength() const = 0;
/// \brief Returns the owner name of the \c RRset.
///
/// \return A reference to a \c Name class object corresponding to the
......@@ -642,6 +656,13 @@ public:
/// \return The number of \c Rdata objects contained.
virtual unsigned int getRdataCount() const;
/// \brief Get the wire format length of the \c BasicRRset.
///
/// \return The length of the wire format representation of the
/// \c BasicRRset.
/// \throw \c EmptyRRset if the \c BasicRRset is empty.
virtual uint16_t getLength() const;
/// \brief Returns the owner name of the \c RRset.
///
/// This method never throws an exception.
......@@ -813,6 +834,13 @@ public:
virtual ~RRset();
/// \brief Get the wire format length of the \c RRset.
///
/// \return The length of the wire format representation of the
/// \c RRset.
/// \throw \c EmptyRRset if the \c RRset is empty.
virtual uint16_t getLength() const;
/// \brief Render the RRset in the wire format with name compression and
/// truncation handling.
///
......
......@@ -204,6 +204,30 @@ TEST_F(RRsetTest, toText) {
rrset_none_a_empty.toText());
}
TEST_F(RRsetTest, getLength) {
// Empty RRset should throw
EXPECT_THROW(rrset_a_empty.getLength(), EmptyRRset);
// Unless it is type ANY or NONE:
// test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
// TYPE field = 2 octets
// CLASS field = 2 octets
// TTL field = 2 octets
// RDLENGTH field = 2 octets
// Total = 18 + 2 + 2 + 2 + 2 = 26 octets
EXPECT_EQ(26, rrset_any_a_empty.getLength());
EXPECT_EQ(26, rrset_none_a_empty.getLength());
// RRset with single RDATA
// 26 (above) + 4 octets (A RDATA) = 30 octets
rrset_a_empty.addRdata(in::A("192.0.2.1"));
EXPECT_EQ(30, rrset_a_empty.getLength());
// 2 A RRs
rrset_a_empty.addRdata(in::A("192.0.2.2"));
EXPECT_EQ(60, rrset_a_empty.getLength());
}
TEST_F(RRsetTest, toWireBuffer) {
rrset_a.toWire(buffer);
......@@ -365,4 +389,38 @@ TEST_F(RRsetRRSIGTest, toText) {
"20100322084538 20100220084538 1 example.com. FAKEFAKEFAKEFAKE\n",
rrset_aaaa->toText());
}
TEST_F(RRsetRRSIGTest, getLength) {
// A RR
// test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
// TYPE field = 2 octets
// CLASS field = 2 octets
// TTL field = 2 octets
// RDLENGTH field = 2 octets
// A RDATA = 4 octets
// Total = 18 + 2 + 2 + 2 + 2 + 4 = 30 octets
// 2 A RRs
EXPECT_EQ(60, rrset_a->getLength());
// RRSIG
// test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
// TYPE field = 2 octets
// CLASS field = 2 octets
// TTL field = 2 octets
// RDLENGTH field = 2 octets
// RRSIG RDATA = 40 octets
// Total = 18 + 2 + 2 + 2 + 2 + 40 = 66 octets
RRsetPtr my_rrsig(new RRset(test_name, RRClass::IN(),
RRType::RRSIG(), RRTTL(3600)));
my_rrsig->addRdata(generic::RRSIG("A 4 3 3600 "
"20000101000000 20000201000000 "
"12345 example.com. FAKEFAKEFAKE"));
EXPECT_EQ(66, my_rrsig->getLength());
// RRset with attached RRSIG
rrset_a->addRRsig(my_rrsig);
EXPECT_EQ(60 + 66, rrset_a->getLength());
}
}
Supports Markdown
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