summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMukund Sivaraman <muks@isc.org>2012-07-12 05:58:00 +0200
committerMukund Sivaraman <muks@isc.org>2012-07-12 05:58:00 +0200
commita16d2686dc4f3ed114b3c43bec1c940b013e4998 (patch)
tree52435a275487e12014d0431c67cd808e2b48f117
parent[2087] Change alignment of test data (diff)
downloadkea-a16d2686dc4f3ed114b3c43bec1c940b013e4998.tar.xz
kea-a16d2686dc4f3ed114b3c43bec1c940b013e4998.zip
[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.
-rw-r--r--src/lib/dns/labelsequence.h17
-rw-r--r--src/lib/dns/messagerenderer.cc18
-rw-r--r--src/lib/dns/messagerenderer.h18
-rw-r--r--src/lib/dns/tests/messagerenderer_unittest.cc63
-rw-r--r--src/lib/dns/tests/testdata/Makefile.am1
-rw-r--r--src/lib/dns/tests/testdata/name_toWire710
-rw-r--r--src/lib/dns/tests/testdata/name_toWire87
-rw-r--r--src/lib/dns/tests/testdata/name_toWire913
8 files changed, 142 insertions, 5 deletions
diff --git a/src/lib/dns/labelsequence.h b/src/lib/dns/labelsequence.h
index 019250e72c..398c9afad9 100644
--- a/src/lib/dns/labelsequence.h
+++ b/src/lib/dns/labelsequence.h
@@ -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
diff --git a/src/lib/dns/messagerenderer.cc b/src/lib/dns/messagerenderer.cc
index ca4ea542b6..628892cee5 100644
--- a/src/lib/dns/messagerenderer.cc
+++ b/src/lib/dns/messagerenderer.cc
@@ -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_)
{
diff --git a/src/lib/dns/messagerenderer.h b/src/lib/dns/messagerenderer.h
index 4c1c92a34f..5a81eb2bc9 100644
--- a/src/lib/dns/messagerenderer.h
+++ b/src/lib/dns/messagerenderer.h
@@ -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_;
diff --git a/src/lib/dns/tests/messagerenderer_unittest.cc b/src/lib/dns/tests/messagerenderer_unittest.cc
index bc526af3eb..582c164b6c 100644
--- a/src/lib/dns/tests/messagerenderer_unittest.cc
+++ b/src/lib/dns/tests/messagerenderer_unittest.cc
@@ -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);
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
index fb1ec5b5c0..043ea559fc 100644
--- a/src/lib/dns/tests/testdata/Makefile.am
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -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
diff --git a/src/lib/dns/tests/testdata/name_toWire7 b/src/lib/dns/tests/testdata/name_toWire7
new file mode 100644
index 0000000000..bff599f50c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire7
@@ -0,0 +1,10 @@
+#
+# 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
diff --git a/src/lib/dns/tests/testdata/name_toWire8 b/src/lib/dns/tests/testdata/name_toWire8
new file mode 100644
index 0000000000..d01093ba7e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire8
@@ -0,0 +1,7 @@
+#
+# 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
diff --git a/src/lib/dns/tests/testdata/name_toWire9 b/src/lib/dns/tests/testdata/name_toWire9
new file mode 100644
index 0000000000..51a198785e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire9
@@ -0,0 +1,13 @@
+#
+# 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