|
@@ -1,296 +0,0 @@
|
|
-// 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 DATASRC_MEMORY_RDATA_READER_H
|
|
|
|
-#define DATASRC_MEMORY_RDATA_READER_H 1
|
|
|
|
-
|
|
|
|
-#include <datasrc/memory/rdata_field.h>
|
|
|
|
-
|
|
|
|
-#include <boost/function.hpp>
|
|
|
|
-
|
|
|
|
-#include <dns/labelsequence.h>
|
|
|
|
-#include <dns/name.h>
|
|
|
|
-
|
|
|
|
-namespace isc {
|
|
|
|
-// Some forward declarations
|
|
|
|
-namespace dns{
|
|
|
|
-class RRClass;
|
|
|
|
-class RRType;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-namespace datasrc {
|
|
|
|
-namespace memory {
|
|
|
|
-
|
|
|
|
-/// \brief Class to read serialized rdata
|
|
|
|
-///
|
|
|
|
-/// This class allows you to read the data encoded by RdataEncoder.
|
|
|
|
-/// It is rather low-level -- it provides sequence of data fields
|
|
|
|
-/// and names. It does not give you convenient Rdata or RRset class.
|
|
|
|
-///
|
|
|
|
-/// It allows two types of operation. First one is by providing callbacks
|
|
|
|
-/// to the constructor and then iterating by repeatedly calling next(), or
|
|
|
|
-/// calling iterate() once. The callbacks are then called with each part of
|
|
|
|
-/// the data.
|
|
|
|
-///
|
|
|
|
-/// \code
|
|
|
|
-/// void handleLabel(const dns::LabelSequence& label, unsigned int flags) {
|
|
|
|
-/// ...
|
|
|
|
-/// }
|
|
|
|
-/// void handleData(const uint8_t* data, size_t size) {
|
|
|
|
-/// ...
|
|
|
|
-/// }
|
|
|
|
-///
|
|
|
|
-/// RdataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
|
|
|
|
-/// handleLabel, handleData);
|
|
|
|
-/// reader.iterate();
|
|
|
|
-/// \endcode
|
|
|
|
-///
|
|
|
|
-/// The other way is to use the return value of next() and loop through
|
|
|
|
-/// it manually. It has the inconvenience of having the type condition, but
|
|
|
|
-/// the code is in one place. The used way is matter of personal preferrence,
|
|
|
|
-/// there's no much difference on the technical side.
|
|
|
|
-///
|
|
|
|
-/// \code
|
|
|
|
-/// RdataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
|
|
|
|
-/// &handleLabel, handleData);
|
|
|
|
-/// RdataReader::Result data;
|
|
|
|
-/// while (data = reader.next()) {
|
|
|
|
-/// switch (data.type()) {
|
|
|
|
-/// case RdataReader::NAME:
|
|
|
|
-/// ...
|
|
|
|
-/// break;
|
|
|
|
-/// case RdataReader::DATA:
|
|
|
|
-/// ...
|
|
|
|
-/// break;
|
|
|
|
-/// default: assert(0); // Can not happen
|
|
|
|
-/// }
|
|
|
|
-/// }
|
|
|
|
-/// \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.
|
|
|
|
-/// If this is not the case, all the kinds of pointer hell might get loose.
|
|
|
|
-class RdataReader2 {
|
|
|
|
-public:
|
|
|
|
- /// \brief Function called on each name encountered in the data.
|
|
|
|
- typedef boost::function<void(const dns::LabelSequence&, unsigned)>
|
|
|
|
- NameAction;
|
|
|
|
-
|
|
|
|
- /// \brief Function called on each data field in the data.
|
|
|
|
- typedef boost::function<void(const uint8_t*, size_t)> DataAction;
|
|
|
|
-
|
|
|
|
- /// \brief a NameAction that does nothing.
|
|
|
|
- ///
|
|
|
|
- /// This is a NameAction function that does nothing. It is used
|
|
|
|
- /// as a default in the constructor.
|
|
|
|
- static void emptyNameAction(const dns::LabelSequence& label,
|
|
|
|
- unsigned attributes);
|
|
|
|
-
|
|
|
|
- /// \brief a DataAction that does nothing.
|
|
|
|
- ///
|
|
|
|
- /// This is a DataAction function that does nothing. It is used
|
|
|
|
- /// as a default in the constructor.
|
|
|
|
- static void emptyDataAction(const uint8_t* data, size_t size);
|
|
|
|
-
|
|
|
|
- /// \brief Constructor
|
|
|
|
- ///
|
|
|
|
- /// This constructs the reader on top of some serialized data.
|
|
|
|
- /// It does not copy the data, you have to make sure the data
|
|
|
|
- /// is valid for the whole life of this object and that they
|
|
|
|
- /// don't change.
|
|
|
|
- ///
|
|
|
|
- /// \param rrclass The class the encoded rdata belongs to.
|
|
|
|
- /// \param rrtype The type of the encode rdata.
|
|
|
|
- /// \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.
|
|
|
|
- RdataReader2(const dns::RRClass& rrclass, const dns::RRType& rrtype,
|
|
|
|
- const uint8_t* data, size_t rdata_count, size_t sig_count,
|
|
|
|
- const NameAction& name_action = &emptyNameAction,
|
|
|
|
- const DataAction& data_action = &emptyDataAction);
|
|
|
|
-
|
|
|
|
- /// \brief The type of data returned from this iteration.
|
|
|
|
- enum DataType {
|
|
|
|
- NAME, ///< This iteration returns domain label
|
|
|
|
- DATA, ///< This iteration returns unstructuder data
|
|
|
|
- END ///< No more data to return
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- /// \brief Data from one iteration
|
|
|
|
- ///
|
|
|
|
- /// Each time you call next() or nextSig(), it returns some data.
|
|
|
|
- /// This holds the data.
|
|
|
|
- ///
|
|
|
|
- /// It is valid only for as long as the RdataReader that returned it.
|
|
|
|
- ///
|
|
|
|
- /// All the methods can be called under any circumstances. However,
|
|
|
|
- /// if the required property is not valid for the given type (eg.
|
|
|
|
- /// when calling size() on type() == NAME), it returns some "empty"
|
|
|
|
- /// value (0, NULL, or the like).
|
|
|
|
- class Result {
|
|
|
|
- public:
|
|
|
|
- /// \brief Default constructor
|
|
|
|
- ///
|
|
|
|
- /// It creates an empty result (with no data) of type END.
|
|
|
|
- Result() :
|
|
|
|
- // TODO: Do we maybe want to have a static one to copy
|
|
|
|
- // instead of constructing new one from the root Name?
|
|
|
|
- label_(dns::Name::ROOT_NAME()),
|
|
|
|
- data_(NULL),
|
|
|
|
- size_(0),
|
|
|
|
- type_(END),
|
|
|
|
- compressible_(false),
|
|
|
|
- additional_(false)
|
|
|
|
- {}
|
|
|
|
-
|
|
|
|
- /// \brief Constructor from a domain label
|
|
|
|
- ///
|
|
|
|
- /// Creates the NAME type result. Used internally from RdataReader.
|
|
|
|
- ///
|
|
|
|
- /// \param label The label to hold
|
|
|
|
- /// \param attributes The attributes, as stored by the serialized
|
|
|
|
- /// data.
|
|
|
|
- Result(const dns::LabelSequence& label, unsigned attributes);
|
|
|
|
-
|
|
|
|
- /// \brief Constructor from data
|
|
|
|
- ///
|
|
|
|
- /// Creates the DATA type result. Used internally from RdataReader.
|
|
|
|
- ///
|
|
|
|
- /// \param data The data pointer to hold.
|
|
|
|
- /// \param size The size to hold.
|
|
|
|
- Result(const uint8_t* data, size_t size);
|
|
|
|
-
|
|
|
|
- /// \brief The type of data returned.
|
|
|
|
- DataType type() const { return (type_); }
|
|
|
|
-
|
|
|
|
- /// \brief The raw data.
|
|
|
|
- ///
|
|
|
|
- /// This is only valid if type() == DATA.
|
|
|
|
- const uint8_t* data() const { return (data_); }
|
|
|
|
-
|
|
|
|
- /// \brief The size of the raw data.
|
|
|
|
- ///
|
|
|
|
- /// This is the number of bytes the data takes. It is valid only
|
|
|
|
- /// if type() == DATA.
|
|
|
|
- size_t size() const { return (size_); }
|
|
|
|
-
|
|
|
|
- /// \brief The domain label.
|
|
|
|
- ///
|
|
|
|
- /// This holds the domain label. It is only valid if type() == NAME.
|
|
|
|
- const dns::LabelSequence& label() const { return (label_); }
|
|
|
|
-
|
|
|
|
- /// \brief Is the name in label() compressible?
|
|
|
|
- ///
|
|
|
|
- /// This is valid only if type() == NAME.
|
|
|
|
- bool compressible() const { return (compressible_); }
|
|
|
|
-
|
|
|
|
- /// \brief Does the name expect additional processing?
|
|
|
|
- ///
|
|
|
|
- /// This is valid only if type() == NAME.
|
|
|
|
- bool additional() const { return (additional_); }
|
|
|
|
-
|
|
|
|
- /// \brief If there are data returned.
|
|
|
|
- ///
|
|
|
|
- /// This returns if there are any data at all returned. This is
|
|
|
|
- /// equivalent to action != END, but it allows for more convenient
|
|
|
|
- /// code of a loop through the data.
|
|
|
|
- operator bool() const {
|
|
|
|
- return (type() != END);
|
|
|
|
- }
|
|
|
|
- private:
|
|
|
|
- dns::LabelSequence label_;
|
|
|
|
- const uint8_t* data_;
|
|
|
|
- size_t size_;
|
|
|
|
- DataType type_;
|
|
|
|
- bool compressible_;
|
|
|
|
- bool additional_;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- /// \brief Step to next piece of data.
|
|
|
|
- ///
|
|
|
|
- /// This returns the next available data. Also, the apropriate hook
|
|
|
|
- /// (name_action or data_action, depending on the data type) as passed
|
|
|
|
- /// to the constructor is called.
|
|
|
|
- ///
|
|
|
|
- /// If there are no more data, a Result with type END is returned and
|
|
|
|
- /// no callback is called.
|
|
|
|
- Result next();
|
|
|
|
-
|
|
|
|
- /// \brief Call next() until the end.
|
|
|
|
- ///
|
|
|
|
- /// This is just convenience method to iterate through all the data.
|
|
|
|
- /// It calls next until it reaches the end (it does not rewind before,
|
|
|
|
- /// therefore if you already called next() yourself, it does not start
|
|
|
|
- /// at the beginning).
|
|
|
|
- ///
|
|
|
|
- /// The method only makes sense if you set the callbacks in constructor.
|
|
|
|
- void iterate();
|
|
|
|
-
|
|
|
|
- /// \brief Step to next piece of RRSig data.
|
|
|
|
- ///
|
|
|
|
- /// This is almost the same as next(), but it iterates through the
|
|
|
|
- /// associated RRSig data, not the data for the given RRType.
|
|
|
|
- Result nextSig();
|
|
|
|
-
|
|
|
|
- /// \brief Iterate through all RRSig data.
|
|
|
|
- ///
|
|
|
|
- /// This is almost the same as iterate(), but it iterates through the
|
|
|
|
- /// RRSig data instead.
|
|
|
|
- void iterateSig();
|
|
|
|
-
|
|
|
|
- /// \brief Rewind the iterator to the beginnig of data.
|
|
|
|
- ///
|
|
|
|
- /// The following next() and nextSig() will start iterating from the
|
|
|
|
- /// beginning again.
|
|
|
|
- void rewind();
|
|
|
|
-
|
|
|
|
- /// \brief Returns the size of associated data.
|
|
|
|
- ///
|
|
|
|
- /// This should be the same as the return value of
|
|
|
|
- /// RdataEncoder::getStorageLength() for the same set of data.
|
|
|
|
- /// The intended use of this method is to tell the caller the size of
|
|
|
|
- /// data that were possibly dynamically allocated so that the caller can
|
|
|
|
- /// use it for deallocation.
|
|
|
|
- ///
|
|
|
|
- /// This method only uses the parameters given at the construction of the
|
|
|
|
- /// object, and does not rely on or modify other mutable states.
|
|
|
|
- /// In practice, when the caller wants to call this method, that would be
|
|
|
|
- /// the only purpose of that RdataReader object (although it doesn't have
|
|
|
|
- /// to be so).
|
|
|
|
- size_t getSize() const;
|
|
|
|
-private:
|
|
|
|
- const NameAction name_action_;
|
|
|
|
- const DataAction data_action_;
|
|
|
|
- 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
|
|
|
|
- // Will be computed during the normal RR iteration
|
|
|
|
- const uint8_t* sigs_;
|
|
|
|
- // The positions in data.
|
|
|
|
- size_t data_pos_, spec_pos_, length_pos_;
|
|
|
|
- size_t sig_pos_, sig_data_pos_;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-}
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#endif
|
|
|