diff options
author | Mukund Sivaraman <muks@isc.org> | 2012-07-12 05:58:00 +0200 |
---|---|---|
committer | Mukund Sivaraman <muks@isc.org> | 2012-07-12 05:58:00 +0200 |
commit | a16d2686dc4f3ed114b3c43bec1c940b013e4998 (patch) | |
tree | 52435a275487e12014d0431c67cd808e2b48f117 | |
parent | [2087] Change alignment of test data (diff) | |
download | kea-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.h | 17 | ||||
-rw-r--r-- | src/lib/dns/messagerenderer.cc | 18 | ||||
-rw-r--r-- | src/lib/dns/messagerenderer.h | 18 | ||||
-rw-r--r-- | src/lib/dns/tests/messagerenderer_unittest.cc | 63 | ||||
-rw-r--r-- | src/lib/dns/tests/testdata/Makefile.am | 1 | ||||
-rw-r--r-- | src/lib/dns/tests/testdata/name_toWire7 | 10 | ||||
-rw-r--r-- | src/lib/dns/tests/testdata/name_toWire8 | 7 | ||||
-rw-r--r-- | src/lib/dns/tests/testdata/name_toWire9 | 13 |
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 |