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

[2087] Add MessageRenderer::writeName() variant for LabelSequence

The Name tests are not repeated as the Name variant is a wrapper
around the LabelSequence variant. Such tests would be redundant.
Instead, tests for LabelSequence specific stripLeft(), stripRight()
were added.
parent 5f6ead50
......@@ -45,6 +45,23 @@ class LabelSequence {
friend std::string Name::toText(bool) const;
public:
/// \brief Constructs a LabelSequence for the given label sequence
///
/// \note The associated data MUST remain in scope during the lifetime
/// of this LabelSequence, since only the pointers are copied.
///
/// \note No validation is done on the given data upon construction;
/// use with care.
///
/// \param ls The LabelSequence to construct a LabelSequence from
explicit LabelSequence(const LabelSequence& ls):
data_(ls.data_),
offsets_(ls.offsets_),
offsets_size_(ls.offsets_size_),
first_label_(ls.first_label_),
last_label_(ls.last_label_)
{}
/// \brief Constructs a LabelSequence for the given name
///
/// \note The associated Name MUST remain in scope during the lifetime
......
......@@ -289,8 +289,8 @@ MessageRenderer::setCompressMode(const CompressMode mode) {
}
void
MessageRenderer::writeName(const Name& name, const bool compress) {
LabelSequence sequence(name);
MessageRenderer::writeName(const LabelSequence& ls, const bool compress) {
LabelSequence sequence(ls);
const size_t nlabels = sequence.getLabelCount();
size_t data_len;
const uint8_t* data;
......@@ -317,14 +317,17 @@ MessageRenderer::writeName(const Name& name, const bool compress) {
if (ptr_offset != MessageRendererImpl::NO_OFFSET) {
break;
}
sequence.stripLeft(1);
if (nlabels_uncomp + 1 < nlabels) {
sequence.stripLeft(1);
}
}
// Record the current offset before updating the offset table
size_t offset = getLength();
// Write uncompress part:
if (nlabels_uncomp > 0 || !compress) {
LabelSequence uncomp_sequence(name);
LabelSequence uncomp_sequence(ls);
if (compress && nlabels > nlabels_uncomp) {
// If there's compressed part, strip off that part.
uncomp_sequence.stripRight(nlabels - nlabels_uncomp);
......@@ -342,7 +345,7 @@ MessageRenderer::writeName(const Name& name, const bool compress) {
// in the hash table. The renderer's buffer has just stored the
// corresponding data, so we use the rendered data to get the length
// of each label of the names.
size_t seqlen = name.getLength();
size_t seqlen = ls.getDataLength();
for (size_t i = 0; i < nlabels_uncomp; ++i) {
const uint8_t label_len = getBuffer()[offset];
if (label_len == 0) { // offset for root doesn't need to be stored.
......@@ -359,6 +362,11 @@ MessageRenderer::writeName(const Name& name, const bool compress) {
}
}
void
MessageRenderer::writeName(const Name& name, const bool compress) {
writeName(LabelSequence(name), compress);
}
AbstractMessageRenderer::AbstractMessageRenderer() :
local_buffer_(0), buffer_(&local_buffer_)
{
......
......@@ -22,6 +22,7 @@ namespace isc {
namespace dns {
// forward declarations
class Name;
class LabelSequence;
/// \brief The \c AbstractMessageRenderer class is an abstract base class
/// that provides common interfaces for rendering a DNS message into a buffer
......@@ -372,6 +373,23 @@ public:
virtual void clear();
virtual void writeName(const Name& name, bool compress = true);
/// \brief Write a \c LabelSequence object into the internal buffer
/// in wire format, with or without name compression.
///
/// If the optional parameter \c compress is \c true, this method tries to
/// compress the \c ls if possible, searching the entire message that has
/// been rendered. Otherwise name compression is omitted. Its default
/// value is \c true.
///
/// Note: even if \c compress is \c true, the position of the \c ls (and
/// possibly its ancestor names) in the message is recorded and may be used
/// for compressing subsequent names.
///
/// \param ls A \c LabelSequence object to be written.
/// \param compress A boolean indicating whether to enable name compression.
void writeName(const LabelSequence& ls, bool compress = true);
private:
struct MessageRendererImpl;
MessageRendererImpl* impl_;
......
......@@ -15,6 +15,7 @@
#include <exceptions/exceptions.h>
#include <util/buffer.h>
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/messagerenderer.h>
#include <dns/tests/unittest_util.h>
......@@ -28,6 +29,7 @@
using isc::UnitTestUtil;
using isc::dns::Name;
using isc::dns::LabelSequence;
using isc::dns::MessageRenderer;
using isc::util::OutputBuffer;
using boost::lexical_cast;
......@@ -176,6 +178,67 @@ TEST_F(MessageRendererTest, writeRootName) {
expected.getLength());
}
TEST_F(MessageRendererTest, writeNameLabelSequence1) {
UnitTestUtil::readWireData("name_toWire7", data);
Name n1("a.example.com");
LabelSequence ls1(n1);
// a.example.com.
renderer.writeName(ls1);
ls1.stripLeft(1);
// example.com.
renderer.writeName(ls1);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
renderer.getLength(), &data[0], data.size());
}
TEST_F(MessageRendererTest, writeNameLabelSequence2) {
UnitTestUtil::readWireData("name_toWire8", data);
Name n1("a.example.com");
LabelSequence ls1(n1);
ls1.stripRight(1);
// a.example.com (without root .)
renderer.writeName(ls1);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
renderer.getLength(), &data[0], data.size());
}
TEST_F(MessageRendererTest, writeNameLabelSequence3) {
UnitTestUtil::readWireData("name_toWire9", data);
Name n1("a.example.com");
LabelSequence ls1(n1);
// a.example.com.
renderer.writeName(ls1);
ls1.stripRight(1);
// a.example.com (without root .)
renderer.writeName(ls1);
ls1.stripRight(1);
// a.example
renderer.writeName(ls1);
ls1.stripLeft(1);
// example
renderer.writeName(ls1);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
renderer.getLength(), &data[0], data.size());
}
TEST_F(MessageRendererTest, setBuffer) {
OutputBuffer new_buffer(0);
renderer.setBuffer(&new_buffer);
......
......@@ -93,6 +93,7 @@ EXTRA_DIST += name_fromWire9 name_fromWire10 name_fromWire11 name_fromWire12
EXTRA_DIST += name_fromWire13 name_fromWire14
EXTRA_DIST += name_toWire1 name_toWire2 name_toWire3 name_toWire4
EXTRA_DIST += name_toWire5.spec name_toWire6.spec
EXTRA_DIST += name_toWire7 name_toWire8 name_toWire9
EXTRA_DIST += question_fromWire question_toWire1 question_toWire2
EXTRA_DIST += rdatafields1.spec rdatafields2.spec rdatafields3.spec
EXTRA_DIST += rdatafields4.spec rdatafields5.spec rdatafields6.spec
......
#
# Rendering names including one explicitly uncompressed.
# [x] means a compression pointer pointing to offset 'x'.
#
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (bytes)
#(1) a (7) e x a m p l e (3) c o m .
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
#[02] pointing to -> "example.com."
c0 02
#
# Rendering names.
# [x] means a compression pointer pointing to offset 'x'.
#
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 (bytes)
#(1) a (7) e x a m p l e (3) c o m
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d
#
# Rendering names including one explicitly uncompressed.
# [x] means a compression pointer pointing to offset 'x'.
#
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (bytes)
#(1) a (7) e x a m p l e (3) c o m .
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
#(1) a (7) e x a m p l e (3) c o m
01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d
#(1) a (7) e x a m p l e
01 61 07 65 78 61 6d 70 6c 65
#[1f] pointing to ^^ "example"
c0 1f
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