BIND 10 trac2096, updated. fdd121bda3753d43f9e322d79b5ad6e8b49064e1 [2096] Implementation of the reader
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Aug 9 13:15:02 UTC 2012
The branch, trac2096 has been updated
via fdd121bda3753d43f9e322d79b5ad6e8b49064e1 (commit)
via c49d19491e9d93a5908afe667beeba4bcfcc8af3 (commit)
via 909df7ac12941253014a4dafb33c4574989999da (commit)
from 6694e40b41ac8909ead7ec6e59bc23ca310573d7 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit fdd121bda3753d43f9e322d79b5ad6e8b49064e1
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Thu Aug 9 15:13:42 2012 +0200
[2096] Implementation of the reader
The tests don't pass, for some reason, but it seems there are less
failures than before. There would probably be some off-by-something
error somewhere.
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/memory/rdata_encoder.h | 32 ------
src/lib/datasrc/memory/rdata_reader.cc | 107 +++++++++++++++++++-
src/lib/datasrc/memory/rdata_reader.h | 27 +++++
.../memory/tests/rdata_serialization_unittest.cc | 27 +++--
4 files changed, 144 insertions(+), 49 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory/rdata_encoder.h b/src/lib/datasrc/memory/rdata_encoder.h
index 1fb2997..cf1f522 100644
--- a/src/lib/datasrc/memory/rdata_encoder.h
+++ b/src/lib/datasrc/memory/rdata_encoder.h
@@ -266,38 +266,6 @@ private:
RdataEncoderImpl* impl_;
};
-// We use the following quick-hack version of "foreach"
-// operators until we implement the complete versions. The plan is to
-// update the test cases that use these functions with the complete
-// functions/classes, and then remove the entire namespace.
-namespace testing {
-// Callbacks used in foreachRdataField.
-typedef boost::function<void(const dns::LabelSequence&,
- RdataNameAttributes)> NameCallback;
-typedef boost::function<void(const uint8_t*, size_t)> DataCallback;
-
-// Iterate over each field (in terms of the internal encoding) of each
-// RDATA stored in encoded_data, and call the given callback for each
-// data (for domain name fields, name_callback will be called; for
-// normal data fields data_callback will be called). rdata_count is
-// the number of RDATAs. If the encoded data contain variable-length
-// data fields, varlen_list should store a sequence of their lengths,
-// in the order of the appearance.
-void foreachRdataField(dns::RRClass rrclass, dns::RRType rrtype,
- size_t rdata_count,
- const std::vector<uint8_t>& encoded_data,
- const std::vector<uint16_t>& varlen_list,
- NameCallback name_callback, DataCallback data_callback);
-
-// Iterate over each RRSIG stored in encoded_data, and call the given
-// callback for each. rrsiglen_list should store a sequence of their lengths,
-// in the order of the appearance. Its size is the number of RRSIGs.
-// The list can be empty, in which case this function does nothing.
-void foreachRRSig(const std::vector<uint8_t>& encoded_data,
- const std::vector<uint16_t>& rrsiglen_list,
- DataCallback data_callback);
-}
-
} // namespace memory
} // namespace datasrc
} // namespace isc
diff --git a/src/lib/datasrc/memory/rdata_reader.cc b/src/lib/datasrc/memory/rdata_reader.cc
index 2bba63f..a099e81 100644
--- a/src/lib/datasrc/memory/rdata_reader.cc
+++ b/src/lib/datasrc/memory/rdata_reader.cc
@@ -14,12 +14,14 @@
#include "rdata_reader.h"
+using namespace isc::dns;
+
namespace isc {
namespace datasrc {
namespace memory {
void
-RdataReader::emptyNameAction(const dns::LabelSequence&, unsigned) {
+RdataReader::emptyNameAction(const LabelSequence&, unsigned) {
// Do nothing here. On purpose, it's not unfinished.
}
@@ -28,7 +30,7 @@ RdataReader::emptyDataAction(const uint8_t*, size_t) {
// Do nothing here. On purpose, it's not unfinished.
}
-RdataReader::Result::Result(const dns::LabelSequence& label,
+RdataReader::Result::Result(const LabelSequence& label,
unsigned attributes) :
label_(label),
data_(NULL),
@@ -39,7 +41,7 @@ RdataReader::Result::Result(const dns::LabelSequence& label,
{}
RdataReader::Result::Result(const uint8_t* data, size_t size) :
- label_(dns::Name::ROOT_NAME()),
+ label_(Name::ROOT_NAME()),
data_(data),
size_(size),
type_(DATA),
@@ -47,6 +49,105 @@ RdataReader::Result::Result(const uint8_t* data, size_t size) :
additional_(false)
{}
+const uint8_t*
+RdataReader::findSigs() const {
+ // Validate the lengths - we want to make sure all the lengths
+ // fit. The base would be the beginning of all the data.
+ const uint8_t* const
+ base(static_cast<const uint8_t*>(static_cast<const void*>(lengths_)));
+ if (base + size_ < data_) {
+ isc_throw(isc::BadValue, "Size won't even hold all the length fields");
+ }
+ // It is easier to look from the end than from the beginning -
+ // this way we just need to sum all the sig lenghs together.
+ size_t sum(0);
+ for (size_t i(0); i < sig_count_; ++ i) {
+ sum += lengths_[var_count_total_ + i];
+ }
+ const uint8_t* const result(data_ + size_ - sum);
+ // Validate the signatures fit.
+ if (result < data_) {
+ isc_throw(isc::BadValue, "Size won't even hold all the RRSigs");
+ }
+ return (result);
+}
+
+RdataReader::RdataReader(const RRClass& rrclass, const RRType& rrtype,
+ size_t size, const uint8_t* data,
+ size_t rdata_count, size_t sig_count,
+ const NameAction& name_action,
+ const DataAction& data_action) :
+ name_action_(name_action),
+ data_action_(data_action),
+ size_(size),
+ spec_(getRdataEncodeSpec(rrclass, rrtype)),
+ var_count_total_(spec_.varlen_count * rdata_count),
+ sig_count_(sig_count),
+ spec_count_(spec_.field_count * rdata_count),
+ // The casts, well, C++ decided it doesn't like completely valid
+ // and explicitly allowed cast in C, so we need to fool it through
+ // void.
+ lengths_(static_cast<const uint16_t*>(
+ static_cast<const void*>(data))), // The lenghts are stored first
+ // And the data just after all the lengths
+ data_(data + (var_count_total_ + sig_count_) * sizeof(uint16_t)),
+ sigs_(findSigs())
+{
+ rewind();
+}
+
+void
+RdataReader::rewind() {
+ data_pos_ = 0;
+ spec_pos_ = 0;
+ length_pos_ = 0;
+ sig_data_pos_ = 0;
+ sig_pos_ = 0;
+}
+
+RdataReader::Result
+RdataReader::next() {
+ // TODO: Add checks we are in the valid part of memory
+ if (spec_pos_ < spec_count_) {
+ const RdataFieldSpec& spec(spec_.fields[(spec_pos_ ++) %
+ spec_.field_count]);
+ if (spec.type == RdataFieldSpec::DOMAIN_NAME) {
+ const LabelSequence sequence(&data_[data_pos_]);
+ data_pos_ += sequence.getSerializedLength();
+ name_action_(sequence, spec.name_attributes);
+ return (Result(sequence, spec.name_attributes));
+ } else {
+ const size_t length(spec.type == RdataFieldSpec::FIXEDLEN_DATA ?
+ spec.fixeddata_len : lengths_[length_pos_ ++]);
+ Result result(&data_[data_pos_], length);
+ data_pos_ += length;
+ data_action_(result.data(), result.size());
+ return (result);
+ }
+ } else {
+ return (Result());
+ }
+}
+
+RdataReader::Result
+RdataReader::nextSig() {
+ // We ensured the whole block of signatures is in the valid block,
+ // so we don't need any checking here.
+ if (sig_pos_ < sig_count_) {
+ // Extract the result
+ Result result(sigs_ + sig_data_pos_, lengths_[var_count_total_ +
+ sig_pos_]);
+ // Move the position of iterator.
+ sig_data_pos_ += lengths_[var_count_total_ + sig_pos_];
+ sig_pos_ ++;
+ // Call the callback
+ data_action_(result.data(), result.size());
+ return (result);
+ } else {
+ return (Result());
+ }
+}
+
}
}
}
diff --git a/src/lib/datasrc/memory/rdata_reader.h b/src/lib/datasrc/memory/rdata_reader.h
index aa13206..88d56fe 100644
--- a/src/lib/datasrc/memory/rdata_reader.h
+++ b/src/lib/datasrc/memory/rdata_reader.h
@@ -77,6 +77,12 @@ namespace memory {
/// }
/// }
/// \endcode
+///
+/// \note It is caller's responsibility to pass valid data here. This means
+/// the data returned by RdataEncoder and the corresponding class and type.
+/// The reader tries to detect some of the inconsistencies, but it's
+/// not perfect. Also, if anything throws, it is improper use of the class
+/// and the class might be in inconsistent or unknown state.
class RdataReader {
public:
/// \brief Function called on each name encountered in the data.
@@ -108,10 +114,14 @@ public:
/// \param rrtype The type of the encode rdata.
/// \param size Number of bytes the data have in serialized form.
/// \param data The actual data.
+ /// \param rdata_count The number of Rdata encoded in the data.
+ /// \param sig_count The number of RRSig rdata bundled with the data.
/// \param name_action The callback to be called on each encountered name.
/// \param data_action The callback to be called on each data chunk.
+ /// \throw isc::BadValue if mismatch of size and counts is detected.
RdataReader(const dns::RRClass& rrclass, const dns::RRType& rrtype,
size_t size, const uint8_t* data,
+ size_t rdata_count, size_t sig_count,
const NameAction& name_action = &emptyNameAction,
const DataAction& data_action = &emptyDataAction);
@@ -245,6 +255,23 @@ public:
///
/// This just returns whatever was passed to the constructor as size.
size_t getSize() const;
+private:
+ const NameAction name_action_;
+ const DataAction data_action_;
+ const size_t size_;
+ const RdataEncodeSpec& spec_;
+ // Total number of var-length fields, count of signatures
+ const size_t var_count_total_, sig_count_, spec_count_;
+ // Pointer to the beginning of length fields
+ const uint16_t* const lengths_;
+ // Pointer to the beginning of the data (after the lengths)
+ const uint8_t* const data_;
+ // Pointer to the first data signature
+ const uint8_t* const sigs_;
+ const uint8_t* findSigs() const;
+ // The positions in data.
+ size_t data_pos_, spec_pos_, length_pos_;
+ size_t sig_pos_, sig_data_pos_;
};
}
diff --git a/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc b/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc
index 2032a87..3ecf935 100644
--- a/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc
+++ b/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc
@@ -47,7 +47,6 @@
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::datasrc::memory;
-using namespace isc::datasrc::memory::testing;
using isc::util::unittests::matchWireData;
using std::string;
@@ -193,8 +192,8 @@ public:
size_t rdata_count,
const vector<uint8_t>& encoded_data,
const vector<uint16_t>& varlen_list,
- NameCallback name_callback,
- DataCallback data_callback)
+ RdataReader::NameAction name_callback,
+ RdataReader::DataAction data_callback)
{
const RdataEncodeSpec& encode_spec = getRdataEncodeSpec(rrclass,
rrtype);
@@ -243,7 +242,7 @@ public:
static void foreachRRSig(const vector<uint8_t>& encoded_data,
const vector<uint16_t>& rrsiglen_list,
- DataCallback data_callback)
+ RdataReader::DataAction data_callback)
{
size_t rrsig_totallen = 0;
for (vector<uint16_t>::const_iterator it = rrsiglen_list.begin();
@@ -318,12 +317,12 @@ class NextDecoder {
public:
static void decode(const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype,
- size_t, size_t, size_t,
+ size_t rdata_count, size_t sig_count, size_t,
const vector<uint8_t>& encoded_data,
MessageRenderer& renderer)
{
RdataReader reader(rrclass, rrtype, encoded_data.size(),
- &encoded_data[0]);
+ &encoded_data[0], rdata_count, sig_count);
RdataReader::Result field;
while (field = reader.next()) {
switch (field.type()) {
@@ -357,12 +356,12 @@ class CallbackDecoder {
public:
static void decode(const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype,
- size_t, size_t, size_t,
+ size_t rdata_count, size_t sig_count, size_t,
const vector<uint8_t>& encoded_data,
MessageRenderer& renderer)
{
RdataReader reader(rrclass, rrtype, encoded_data.size(),
- &encoded_data[0],
+ &encoded_data[0], rdata_count, sig_count,
boost::bind(renderNameField, &renderer,
additionalRequired(rrtype), _1, _2),
boost::bind(renderDataField, &renderer, _1, _2));
@@ -377,12 +376,12 @@ class IterateDecoder {
public:
static void decode(const isc::dns::RRClass& rrclass,
const isc::dns::RRType& rrtype,
- size_t, size_t, size_t,
+ size_t rdata_count, size_t sig_count, size_t,
const vector<uint8_t>& encoded_data,
MessageRenderer& renderer)
{
RdataReader reader(rrclass, rrtype, encoded_data.size(),
- &encoded_data[0],
+ &encoded_data[0], rdata_count, sig_count,
boost::bind(renderNameField, &renderer,
additionalRequired(rrtype), _1, _2),
boost::bind(renderDataField, &renderer, _1, _2));
@@ -702,7 +701,7 @@ TEST_F(RdataSerializationTest, readerResult) {
EXPECT_TRUE(compressible.label().equals(seq));
EXPECT_TRUE(compressible);
EXPECT_TRUE(compressible.compressible());
- EXPECT_FALSE(empty.additional());
+ EXPECT_FALSE(compressible.additional());
RdataReader::Result incompressible(seq, NAMEATTR_ADDITIONAL);
EXPECT_EQ(RdataReader::NAME, incompressible.type());
EXPECT_EQ(NULL, incompressible.data());
@@ -710,7 +709,7 @@ TEST_F(RdataSerializationTest, readerResult) {
EXPECT_TRUE(incompressible.label().equals(seq));
EXPECT_TRUE(incompressible);
EXPECT_FALSE(incompressible.compressible());
- EXPECT_TRUE(empty.additional());
+ EXPECT_TRUE(incompressible.additional());
// Constructor from data
uint8_t byte;
RdataReader::Result data(&byte, 1);
@@ -718,8 +717,8 @@ TEST_F(RdataSerializationTest, readerResult) {
EXPECT_EQ(&byte, data.data());
EXPECT_EQ(1, data.size());
EXPECT_TRUE(data.label().equals(LabelSequence(Name::ROOT_NAME())));
- EXPECT_FALSE(data);
+ EXPECT_TRUE(data);
EXPECT_FALSE(data.compressible());
- EXPECT_FALSE(empty.additional());
+ EXPECT_FALSE(data.additional());
}
}
More information about the bind10-changes
mailing list