Commit b33929ed authored by Jelte Jansen's avatar Jelte Jansen

[master] Merge branch 'trac1602'

parents 70778ebe cb28f3c4
......@@ -91,6 +91,7 @@ libdns___la_LDFLAGS = -no-undefined -version-info 1:0:1
libdns___la_SOURCES =
libdns___la_SOURCES += edns.h edns.cc
libdns___la_SOURCES += exceptions.h exceptions.cc
libdns___la_SOURCES += labelsequence.h labelsequence.cc
libdns___la_SOURCES += masterload.h masterload.cc
libdns___la_SOURCES += message.h message.cc
libdns___la_SOURCES += messagerenderer.h messagerenderer.cc
......@@ -140,6 +141,7 @@ libdns___includedir = $(includedir)/dns
libdns___include_HEADERS = \
edns.h \
exceptions.h \
labelsequence.h \
message.h \
messagerenderer.h \
name.h \
......
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dns/labelsequence.h>
#include <exceptions/exceptions.h>
#include <iostream>
namespace isc {
namespace dns {
const char*
LabelSequence::getData(size_t *len) const {
// If the labelsequence is absolute, the current last_label_ falls
// out of the vector (since it points to the 'label' after the
// root label, which doesn't exist; in that case, return
// the length for the 'previous' label (the root label) plus
// one (for the root label zero octet)
if (isAbsolute()) {
*len = name_.offsets_[last_label_ - 1] - name_.offsets_[first_label_] + 1;
} else {
*len = name_.offsets_[last_label_] - name_.offsets_[first_label_];
}
return (&name_.ndata_[name_.offsets_[first_label_]]);
}
bool
LabelSequence::equals(const LabelSequence& other, bool case_sensitive) const {
size_t len, other_len;
const char* data = getData(&len);
const char* other_data = other.getData(&other_len);
if (len != other_len) {
return (false);
}
if (case_sensitive) {
return (strncasecmp(data, other_data, len) == 0);
} else {
return (strncmp(data, other_data, len) == 0);
}
}
void
LabelSequence::stripLeft(size_t i) {
if (i >= getLabelCount()) {
isc_throw(OutOfRange, "Cannot strip to zero or less labels; " << i <<
" (labelcount: " << getLabelCount() << ")");
}
first_label_ += i;
}
void
LabelSequence::stripRight(size_t i) {
if (i >= getLabelCount()) {
isc_throw(OutOfRange, "Cannot strip to zero or less labels; " << i <<
" (labelcount: " << getLabelCount() << ")");
}
last_label_ -= i;
}
bool
LabelSequence::isAbsolute() const {
return (last_label_ == name_.offsets_.size());
}
} // end namespace dns
} // end namespace isc
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __LABELSEQUENCE_H
#define __LABELSEQUENCE_H 1
#include <dns/name.h>
#include <util/buffer.h>
namespace isc {
namespace dns {
/// \brief Light-weight Accessor to Name object
///
/// The purpose of this class is to easily match Names and parts of Names,
/// without needing to copy the underlying data on each label strip.
///
/// It can only work on existing Name objects, and the Name object MUST
/// remain in scope during the entire lifetime of its associated
/// LabelSequence(s).
///
/// Upon creation of a LabelSequence, it records the offsets of the
/// labels in the wireformat data of the Name. When stripLeft() or
/// stripRight() is called on the LabelSequence, no changes in the
/// Name's data occur, but the internal pointers of the
/// LabelSequence are modified.
///
/// LabelSequences can be compared to other LabelSequences, and their
/// data can be requested (which then points to part of the original
/// data of the associated Name object).
///
class LabelSequence {
public:
/// \brief Constructs a LabelSequence for the given name
///
/// \note The associated Name MUST remain in scope during the lifetime
/// of this LabelSequence, since getData() refers to data from the
/// Name object (the only data the LabelSequence stores are pointers
/// to the labels in the Name object).
///
/// \param name The Name to construct a LabelSequence for
LabelSequence(const Name& name): name_(name),
first_label_(0),
last_label_(name.getLabelCount())
{}
/// \brief Return the wire-format data for this LabelSequence
///
/// The data, is returned as a pointer to the original wireformat
/// data of the original Name object, and the given len value is
/// set to the number of octets that match this labelsequence.
///
/// \note The data pointed to is only valid if the original Name
/// object is still in scope
///
/// \param len Pointer to a size_t where the length of the data
/// will be stored (in number of octets)
/// \return Pointer to the wire-format data of this label sequence
const char* getData(size_t* len) const;
/// \brief Compares two label sequences.
///
/// Performs a (optionally case-insensitive) comparison between this
/// LabelSequence and another LabelSequence.
///
/// \param other The LabelSequence to compare with
/// \param case_sensitive If true, comparison is case-insensitive
/// \return true if The label sequences consist are the same length,
/// and contain the same data.
bool equals(const LabelSequence& other, bool case_sensitive = false) const;
/// \brief Remove labels from the front of this LabelSequence
///
/// \note No actual memory is changed, this operation merely updates the
/// internal pointers based on the offsets in the Name object.
///
/// \exeption OutOfRange if i is greater than or equal to the number
/// of labels currently pointed to by this LabelSequence
///
/// \param i The number of labels to remove.
void stripLeft(size_t i);
/// \brief Remove labels from the end of this LabelSequence
///
/// \note No actual memory is changed, this operation merely updates the
/// internal pointers based on the offsets in the Name object.
///
/// \exeption OutOfRange if i is greater than or equal to the number
/// of labels currently pointed to by this LabelSequence
///
/// \param i The number of labels to remove.
void stripRight(size_t i);
/// \brief Returns the current number of labels for this LabelSequence
///
/// \return The number of labels
size_t getLabelCount() const { return last_label_ - first_label_; }
/// \brief Returns the original Name object associated with this
/// LabelSequence
///
/// While the Name should still be in scope during the lifetime of
/// the LabelSequence, it can still be useful to have access to it,
/// for instance in helper functions that are only passed the
/// LabelSequence itself.
///
/// \return Reference to the original Name object
const Name& getName() const { return name_; }
/// \brief Checks whether the label sequence is absolute
///
/// \return true if the last label is the root label
bool isAbsolute() const;
private:
const Name& name_;
size_t first_label_;
size_t last_label_;
};
} // end namespace dns
} // end namespace isc
#endif
......@@ -210,6 +210,11 @@ private:
/// names as a special case.
///
class Name {
// LabelSequences use knowledge about the internal data structure
// of this class for efficiency (they use the offsets_ vector and
// the ndata_ string)
friend class LabelSequence;
///
/// \name Constructors and Destructor
///
......@@ -298,6 +303,7 @@ public:
}
return (ndata_[pos]);
}
/// \brief Gets the length of the <code>Name</code> in its wire format.
///
/// This method never throws an exception.
......
......@@ -19,6 +19,7 @@ if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = unittest_util.h unittest_util.cc
run_unittests_SOURCES += edns_unittest.cc
run_unittests_SOURCES += labelsequence_unittest.cc
run_unittests_SOURCES += messagerenderer_unittest.cc
run_unittests_SOURCES += name_unittest.cc
run_unittests_SOURCES += nsec3hash_unittest.cc
......
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dns/labelsequence.h>
#include <exceptions/exceptions.h>
#include <gtest/gtest.h>
using namespace isc::dns;
class LabelSequenceTest : public ::testing::Test {
public:
LabelSequenceTest() : n1("example.org"), n2("example.com"),
n3("example.org"), n4("foo.bar.test.example"),
n5("example.ORG"), n6("ExAmPlE.org"),
n7("."), n8("foo.example.org.bar"),
ls1(n1), ls2(n2), ls3(n3), ls4(n4), ls5(n5),
ls6(n6), ls7(n7), ls8(n8)
{};
// Need to keep names in scope for at least the lifetime of
// the labelsequences
Name n1, n2, n3, n4, n5, n6, n7, n8;
LabelSequence ls1, ls2, ls3, ls4, ls5, ls6, ls7, ls8;
};
// Basic equality tests
TEST_F(LabelSequenceTest, equals_sensitive) {
EXPECT_TRUE(ls1.equals(ls1));
EXPECT_FALSE(ls1.equals(ls2));
EXPECT_TRUE(ls1.equals(ls3));
EXPECT_FALSE(ls1.equals(ls4));
EXPECT_FALSE(ls1.equals(ls5));
EXPECT_FALSE(ls1.equals(ls6));
EXPECT_FALSE(ls1.equals(ls7));
EXPECT_FALSE(ls1.equals(ls8));
EXPECT_FALSE(ls2.equals(ls1));
EXPECT_TRUE(ls2.equals(ls2));
EXPECT_FALSE(ls2.equals(ls3));
EXPECT_FALSE(ls2.equals(ls4));
EXPECT_FALSE(ls2.equals(ls5));
EXPECT_FALSE(ls2.equals(ls6));
EXPECT_FALSE(ls2.equals(ls7));
EXPECT_FALSE(ls2.equals(ls8));
EXPECT_FALSE(ls4.equals(ls1));
EXPECT_FALSE(ls4.equals(ls2));
EXPECT_FALSE(ls4.equals(ls3));
EXPECT_TRUE(ls4.equals(ls4));
EXPECT_FALSE(ls4.equals(ls5));
EXPECT_FALSE(ls4.equals(ls6));
EXPECT_FALSE(ls4.equals(ls7));
EXPECT_FALSE(ls4.equals(ls8));
EXPECT_FALSE(ls5.equals(ls1));
EXPECT_FALSE(ls5.equals(ls2));
EXPECT_FALSE(ls5.equals(ls3));
EXPECT_FALSE(ls5.equals(ls4));
EXPECT_TRUE(ls5.equals(ls5));
EXPECT_FALSE(ls5.equals(ls6));
EXPECT_FALSE(ls5.equals(ls7));
EXPECT_FALSE(ls5.equals(ls8));
}
TEST_F(LabelSequenceTest, equals_insensitive) {
EXPECT_TRUE(ls1.equals(ls1, true));
EXPECT_FALSE(ls1.equals(ls2, true));
EXPECT_TRUE(ls1.equals(ls3, true));
EXPECT_FALSE(ls1.equals(ls4, true));
EXPECT_TRUE(ls1.equals(ls5, true));
EXPECT_TRUE(ls1.equals(ls6, true));
EXPECT_FALSE(ls1.equals(ls7, true));
EXPECT_FALSE(ls2.equals(ls1, true));
EXPECT_TRUE(ls2.equals(ls2, true));
EXPECT_FALSE(ls2.equals(ls3, true));
EXPECT_FALSE(ls2.equals(ls4, true));
EXPECT_FALSE(ls2.equals(ls5, true));
EXPECT_FALSE(ls2.equals(ls6, true));
EXPECT_FALSE(ls2.equals(ls7, true));
EXPECT_TRUE(ls3.equals(ls1, true));
EXPECT_FALSE(ls3.equals(ls2, true));
EXPECT_TRUE(ls3.equals(ls3, true));
EXPECT_FALSE(ls3.equals(ls4, true));
EXPECT_TRUE(ls3.equals(ls5, true));
EXPECT_TRUE(ls3.equals(ls6, true));
EXPECT_FALSE(ls3.equals(ls7, true));
EXPECT_FALSE(ls4.equals(ls1, true));
EXPECT_FALSE(ls4.equals(ls2, true));
EXPECT_FALSE(ls4.equals(ls3, true));
EXPECT_TRUE(ls4.equals(ls4, true));
EXPECT_FALSE(ls4.equals(ls5, true));
EXPECT_FALSE(ls4.equals(ls6, true));
EXPECT_FALSE(ls4.equals(ls7, true));
EXPECT_TRUE(ls5.equals(ls1, true));
EXPECT_FALSE(ls5.equals(ls2, true));
EXPECT_TRUE(ls5.equals(ls3, true));
EXPECT_FALSE(ls5.equals(ls4, true));
EXPECT_TRUE(ls5.equals(ls5, true));
EXPECT_TRUE(ls5.equals(ls6, true));
EXPECT_FALSE(ls5.equals(ls7, true));
}
void
getDataCheck(const char* expected_data, size_t expected_len,
const LabelSequence& ls)
{
size_t len;
const char* data = ls.getData(&len);
ASSERT_EQ(expected_len, len) << "Expected data: " << expected_data <<
" name: " << ls.getName().toText();
for (size_t i = 0; i < len; ++i) {
EXPECT_EQ(expected_data[i], data[i]) << "Difference at pos " << i <<
": Expected data: " <<
expected_data <<
" name: " <<
ls.getName().toText();;
}
}
TEST_F(LabelSequenceTest, getData) {
getDataCheck("\007example\003org\000", 13, ls1);
getDataCheck("\007example\003com\000", 13, ls2);
getDataCheck("\007example\003org\000", 13, ls3);
getDataCheck("\003foo\003bar\004test\007example\000", 22, ls4);
getDataCheck("\007example\003ORG\000", 13, ls5);
getDataCheck("\007ExAmPlE\003org\000", 13, ls6);
getDataCheck("\000", 1, ls7);
};
TEST_F(LabelSequenceTest, stripLeft) {
EXPECT_TRUE(ls1.equals(ls3));
ls1.stripLeft(0);
getDataCheck("\007example\003org\000", 13, ls1);
EXPECT_TRUE(ls1.equals(ls3));
ls1.stripLeft(1);
getDataCheck("\003org\000", 5, ls1);
EXPECT_FALSE(ls1.equals(ls3));
ls1.stripLeft(1);
getDataCheck("\000", 1, ls1);
EXPECT_TRUE(ls1.equals(ls7));
ls2.stripLeft(2);
getDataCheck("\000", 1, ls2);
EXPECT_TRUE(ls2.equals(ls7));
}
TEST_F(LabelSequenceTest, stripRight) {
EXPECT_TRUE(ls1.equals(ls3));
ls1.stripRight(1);
getDataCheck("\007example\003org", 12, ls1);
EXPECT_FALSE(ls1.equals(ls3));
ls1.stripRight(1);
getDataCheck("\007example", 8, ls1);
EXPECT_FALSE(ls1.equals(ls3));
ASSERT_FALSE(ls1.equals(ls2));
ls2.stripRight(2);
getDataCheck("\007example", 8, ls2);
EXPECT_TRUE(ls1.equals(ls2));
}
TEST_F(LabelSequenceTest, stripOutOfRange) {
EXPECT_THROW(ls1.stripLeft(100), isc::OutOfRange);
EXPECT_THROW(ls1.stripLeft(5), isc::OutOfRange);
EXPECT_THROW(ls1.stripLeft(4), isc::OutOfRange);
EXPECT_THROW(ls1.stripLeft(3), isc::OutOfRange);
getDataCheck("\007example\003org\000", 13, ls1);
EXPECT_THROW(ls1.stripRight(100), isc::OutOfRange);
EXPECT_THROW(ls1.stripRight(5), isc::OutOfRange);
EXPECT_THROW(ls1.stripRight(4), isc::OutOfRange);
EXPECT_THROW(ls1.stripRight(3), isc::OutOfRange);
getDataCheck("\007example\003org\000", 13, ls1);
}
TEST_F(LabelSequenceTest, getLabelCount) {
EXPECT_EQ(3, ls1.getLabelCount());
ls1.stripLeft(0);
EXPECT_EQ(3, ls1.getLabelCount());
ls1.stripLeft(1);
EXPECT_EQ(2, ls1.getLabelCount());
ls1.stripLeft(1);
EXPECT_EQ(1, ls1.getLabelCount());
EXPECT_EQ(3, ls2.getLabelCount());
ls2.stripRight(1);
EXPECT_EQ(2, ls2.getLabelCount());
ls2.stripRight(1);
EXPECT_EQ(1, ls2.getLabelCount());
EXPECT_EQ(3, ls3.getLabelCount());
ls3.stripRight(2);
EXPECT_EQ(1, ls3.getLabelCount());
EXPECT_EQ(5, ls4.getLabelCount());
ls4.stripRight(3);
EXPECT_EQ(2, ls4.getLabelCount());
EXPECT_EQ(3, ls5.getLabelCount());
ls5.stripLeft(2);
EXPECT_EQ(1, ls5.getLabelCount());
}
TEST_F(LabelSequenceTest, comparePart) {
EXPECT_FALSE(ls1.equals(ls8));
// strip root label from example.org.
ls1.stripRight(1);
// strip foo from foo.example.org.bar.
ls8.stripLeft(1);
// strip bar. (i.e. bar and root) too
ls8.stripRight(2);
EXPECT_TRUE(ls1.equals(ls8));
// Data comparison
size_t len;
const char* data = ls1.getData(&len);
getDataCheck(data, len, ls8);
}
TEST_F(LabelSequenceTest, isAbsolute) {
ASSERT_TRUE(ls1.isAbsolute());
ls1.stripLeft(1);
ASSERT_TRUE(ls1.isAbsolute());
ls1.stripRight(1);
ASSERT_FALSE(ls1.isAbsolute());
ASSERT_TRUE(ls2.isAbsolute());
ls2.stripRight(1);
ASSERT_FALSE(ls2.isAbsolute());
ASSERT_TRUE(ls3.isAbsolute());
ls3.stripLeft(2);
ASSERT_TRUE(ls3.isAbsolute());
}
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