|
@@ -22,148 +22,657 @@
|
|
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
|
|
+#include <exceptions/exceptions.h>
|
|
|
+
|
|
|
#include "rdata.h"
|
|
|
|
|
|
namespace isc {
|
|
|
namespace dns {
|
|
|
|
|
|
+///
|
|
|
+/// \brief A standard DNS module exception that is thrown if an RRset object
|
|
|
+/// does not contain any RDATA where required.
|
|
|
+///
|
|
|
+class EmptyRRset : public Exception {
|
|
|
+public:
|
|
|
+ EmptyRRset(const char* file, size_t line, const char* what) :
|
|
|
+ isc::Exception(file, line, what) {}
|
|
|
+};
|
|
|
+
|
|
|
+// forward declarations
|
|
|
class Name;
|
|
|
class RRType;
|
|
|
class RRClass;
|
|
|
class RRTTL;
|
|
|
class OututBuffer;
|
|
|
class MessageRenderer;
|
|
|
-
|
|
|
class AbstractRRset;
|
|
|
-typedef boost::shared_ptr<AbstractRRset> RRsetPtr;
|
|
|
class BasicRRset;
|
|
|
-typedef BasicRRset RRset;
|
|
|
+class RdataIterator;
|
|
|
class BasicRRsetImpl;
|
|
|
|
|
|
-class RdataIterator;
|
|
|
+/// \brief A pointer-like type pointing to an \c AbstractRRset object.
|
|
|
+///
|
|
|
+/// This type is commonly used as an argument of various functions defined
|
|
|
+/// in this library in order to handle RRsets in a polymorphic manner.
|
|
|
+typedef boost::shared_ptr<AbstractRRset> RRsetPtr;
|
|
|
+
|
|
|
+/// \brief A pointer-like type pointing to an (immutable) \c AbstractRRset
|
|
|
+/// object.
|
|
|
+///
|
|
|
+/// This type is commonly used as an argument of various functions defined
|
|
|
+/// in this library in order to handle RRsets in a polymorphic manner.
|
|
|
+typedef boost::shared_ptr<const AbstractRRset> ConstRRsetPtr;
|
|
|
+
|
|
|
+/// \brief A convenient abbreviation for the most generic derived RRset class.
|
|
|
+typedef BasicRRset RRset;
|
|
|
+
|
|
|
+/// \brief A pointer-like type point to an \c RdataIterator object.
|
|
|
typedef boost::shared_ptr<RdataIterator> RdataIteratorPtr;
|
|
|
|
|
|
-/// \brief TBD
|
|
|
+/// \brief The \c AbstractRRset class is an abstract base class that
|
|
|
+/// models a DNS RRset.
|
|
|
///
|
|
|
-/// An \c RRset object models an RRset as described in the DNS standard:
|
|
|
-/// a set of DNS resource records (RRs) of the same type and class.
|
|
|
+/// An object of (a specific derived class of) \c AbstractRRset
|
|
|
+/// models an RRset as described in the DNS standard:
|
|
|
+/// A set of DNS resource records (RRs) of the same type and class.
|
|
|
/// The standard requires the TTL of all RRs in an RRset be the same;
|
|
|
/// this class follows that requirement.
|
|
|
-/// Note about duplication: we probably don't enforce the RDATA is unique
|
|
|
-/// as a class responsibility - but may revisit the decision.
|
|
|
+
|
|
|
+/// Note about duplicate RDATA: RFC2181 states that it's meaningless that an
|
|
|
+/// RRset contains two identical RRs and that name servers should suppress
|
|
|
+/// such duplicates.
|
|
|
+/// This class is not responsible for ensuring this requirement: For example,
|
|
|
+/// \c addRdata() method doesn't check if there's already RDATA identical
|
|
|
+/// to the one being added.
|
|
|
+/// This is because such checks can be expensive, and it's often easy to
|
|
|
+/// ensure the uniqueness requirement at the %data preparation phase
|
|
|
+/// (e.g. when loading a zone).
|
|
|
+/// When parsing an incoming DNS message, the uniqueness may not be guaranteed,
|
|
|
+/// so the application needs to detect and ignore any duplicate RDATA
|
|
|
+/// (the \c Message class of this library should provide this responsibility).
|
|
|
///
|
|
|
-// This is a primary class internally used in our major software such as name
|
|
|
-// servers.
|
|
|
-//
|
|
|
-// Note about terminology: there has been a discussion at the IETF namedroppers
|
|
|
-// ML about RRset vs RRSet (case of "s"). While RFC2181 uses the latter,
|
|
|
-// many other RFCs use the former, and most of the list members who showed
|
|
|
-// their opinion seem to prefer RRset. We follow that preference in this
|
|
|
-// implementation.
|
|
|
-//
|
|
|
-// Open Issues:
|
|
|
-// - add more set-like operations, e.g, merge?
|
|
|
-// - add a "sort" method? "search(find)" method?
|
|
|
-// - BIND9 libdns has some special DNSSEC-related methods
|
|
|
-// such as addnoqname(), addclosest(). do we need these?
|
|
|
-// - need to check duplicate rdata in addrdata()?
|
|
|
-// - need a comparison method? if so, should it compare
|
|
|
-// rdata's as a set or as a list (compare each rdata one
|
|
|
-// by one)? ldns has ldns_rr_list_compare(), which takes
|
|
|
-// the latter approach (assuming the caller sorts the lists
|
|
|
-// beforehand?).
|
|
|
-// - do we need to allow the user to remove specific Rdata?
|
|
|
-/// Looking at the BIND9 code, don't see the strong need for this at the
|
|
|
-/// moment.
|
|
|
+/// Another point to note is that \c AbstractRRset and its derived classes
|
|
|
+/// allow an object to have an empty set of RDATA.
|
|
|
+/// Even though there's no corresponding notion in the protocol specification,
|
|
|
+/// it would be more intuitive for a container-like %data structure
|
|
|
+/// to allow an empty set.
|
|
|
+///
|
|
|
+/// Since \c AbstractRRset is an abstract class, it is generally used
|
|
|
+/// via a pointer (or pointer like object) or a reference.
|
|
|
+/// In particular, \c RRsetPtr, a pointer like type for \c AbstractRRset,
|
|
|
+/// is used for polymorphic RRset operations throughout this library.
|
|
|
///
|
|
|
+/// The \c AbstractRRset class is also intended to be a major customization
|
|
|
+/// point. For example, a high performance server implementation may want
|
|
|
+/// to define an optimized "pre-compiled" RRset and provide an optimized
|
|
|
+/// implementation of the \c toWire() method.
|
|
|
+///
|
|
|
+/// Note about design choice: In BIND9, a set of RDATA with a common tuple
|
|
|
+/// of RR class, RR type, and TTL was represented in a structure named
|
|
|
+/// \c rdataset. Unlike the RRset classes, an \c rdataset did not contain
|
|
|
+/// the information of the owner name.
|
|
|
+/// This might be advantageous if we want to handle "RRsets", that is,
|
|
|
+/// a set of different types of RRset for the same owner name, because
|
|
|
+/// a single "name" structure can be used for multiple RRsets, minimizing
|
|
|
+/// %data copy and memory footprint.
|
|
|
+/// On the other hand, it's inconvenient for API users since in many cases
|
|
|
+/// a pair of name and an \c rdataset must be maintained. It's also counter
|
|
|
+/// intuitive in implementing protocol operations as an RRset is often used
|
|
|
+/// as an atomic entity in DNS protocols while an \c rdataset is a component
|
|
|
+/// of an RRset.
|
|
|
+///
|
|
|
+/// We have therefore defined the notion of RRset explicitly in our initial
|
|
|
+/// API design. We believe memory footprint is not a big concern because
|
|
|
+/// RRsets are generally expected to be used as temporary objects, e.g.
|
|
|
+/// while parsing or constructing a DNS message, or searching a DNS %data
|
|
|
+/// source; for longer term purposes such as in-memory %data source entries,
|
|
|
+/// the corresponding %data would be represented in a different, memory
|
|
|
+/// optimized format. As for the concern about %data copy, we believe
|
|
|
+/// it can be mitigated by using copy-efficient implementation for the
|
|
|
+/// \c Name class implementation, such as reference counted objects.
|
|
|
+/// Later, We plan to perform benchmark tests later to see if this assumption
|
|
|
+/// is valid and to revisit the design if necessary.
|
|
|
+///
|
|
|
+/// Note about terminology: there has been a discussion at the IETF
|
|
|
+/// namedroppers ML about RRset vs RRSet (case of "s")
|
|
|
+/// [http://ops.ietf.org/lists/namedroppers/namedroppers.2009/msg02737.html].
|
|
|
+/// While RFC2181 uses the latter, many other RFCs use the former,
|
|
|
+/// and most of the list members who showed their opinion seem to prefer
|
|
|
+/// "RRset". We follow that preference in this implementation.
|
|
|
+///
|
|
|
+/// The current design of \c AbstractRRset is still in flux.
|
|
|
+/// There are many open questions in design details:
|
|
|
+/// - support more set-like operations, e.g, merge two RRsets of the same
|
|
|
+/// type?
|
|
|
+/// - more convenient methods or non member utility functions, e.g.
|
|
|
+/// "sort" and "search(find)" method?
|
|
|
+/// - what about comparing two RRsets of the same type? If we need this,
|
|
|
+/// should it compare rdata's as a set or as a list (i.e. compare
|
|
|
+/// each %rdata one by one or as a whole)? c.f. NLnet Labs'
|
|
|
+/// <a href="http://www.nlnetlabs.nl/projects/ldns/doc/index.html">ldns</a>
|
|
|
+/// has \c ldns_rr_list_compare(), which takes the latter approach
|
|
|
+/// (seemingly assuming the caller sorts the lists beforehand).
|
|
|
+/// - BIND9 libdns has some special DNSSEC-related methods
|
|
|
+/// such as \c addnoqname() or \c addclosest(). Do we need these?
|
|
|
+/// (Probably not. We wouldn't want to make the class design too
|
|
|
+/// monolithic.)
|
|
|
+/// - Do we need to allow the user to remove specific Rdata?
|
|
|
+/// Probably not, according to the current usage of the BIND9 code.
|
|
|
class AbstractRRset {
|
|
|
+ ///
|
|
|
+ /// \name Constructors and Destructor
|
|
|
+ ///
|
|
|
+ /// Note: The copy constructor and the assignment operator are intentionally
|
|
|
+ /// defined as private to make it explicit that this is a pure base class.
|
|
|
+ //@{
|
|
|
+private:
|
|
|
+ AbstractRRset(const AbstractRRset& source);
|
|
|
+ AbstractRRset& operator=(const AbstractRRset& source);
|
|
|
+protected:
|
|
|
+ /// \brief The default constructor.
|
|
|
+ ///
|
|
|
+ /// This is intentionally defined as \c protected as this base class should
|
|
|
+ /// never be instantiated (except as part of a derived class).
|
|
|
+ AbstractRRset() {}
|
|
|
public:
|
|
|
+ /// The destructor.
|
|
|
virtual ~AbstractRRset() {}
|
|
|
- virtual std::string toText() const;
|
|
|
- /// Note: perhaps we may want to add more arguments to convey optional
|
|
|
- /// information such as an "rrset-order" policy.
|
|
|
- /// no name compression, no truncation
|
|
|
- virtual unsigned int toWire(OutputBuffer& buffer) const;
|
|
|
- /// name compression when necessary, taking into account truncation
|
|
|
- virtual unsigned int toWire(MessageRenderer& renderer) const;
|
|
|
+ //@}
|
|
|
+
|
|
|
+ ///
|
|
|
+ /// \name Getter and Setter Methods
|
|
|
+ ///
|
|
|
+ /// These methods are generally expected to be exception free, but it's
|
|
|
+ /// not guaranteed at the interface level;
|
|
|
+ /// for example, some performance optimized derived class may manage
|
|
|
+ /// the information corresponding to the class "attributes" to get or set,
|
|
|
+ /// and may require dynamic memory allocation to execute the method.
|
|
|
+ /// Consult the derived class description to see if a specific derived
|
|
|
+ /// \c RRset class may throw an exception from these methods.
|
|
|
+ ///
|
|
|
+ /// Note that setter methods are not provided for \c RRClass and
|
|
|
+ /// \c RRType. This is intentional. Since the format and semantics of
|
|
|
+ /// \c Rdata are dependent on the RR type (and RR class for some RR types),
|
|
|
+ /// allowing dynamically modify these attributes can easily lead to a
|
|
|
+ /// bug where the RDATA and type and/or class become inconsistent.
|
|
|
+ /// We want to avoid that situation by restricting the access.
|
|
|
+ //@{
|
|
|
+ /// \brief Returns the number of \c Rdata objects contained in the \c RRset.
|
|
|
+ ///
|
|
|
+ /// Note that an \c RRset with an empty set of \c Rdata can exist, so
|
|
|
+ /// this method may return 0.
|
|
|
+ ///
|
|
|
+ /// \return The number of \c Rdata objects contained.
|
|
|
virtual unsigned int getRdataCount() const = 0;
|
|
|
+
|
|
|
+ /// \brief Returns the owner name of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c Name class object corresponding to the
|
|
|
+ /// \c RRset owner name.
|
|
|
virtual const Name& getName() const = 0;
|
|
|
+
|
|
|
+ /// \brief Returns the RR Class of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c RRClass class object corresponding to the
|
|
|
+ /// RR class of the \c RRset.
|
|
|
virtual const RRClass& getClass() const = 0;
|
|
|
+
|
|
|
+ /// \brief Returns the RR Type of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c RRType class object corresponding to the
|
|
|
+ /// RR type of the \c RRset.
|
|
|
virtual const RRType& getType() const = 0;
|
|
|
+
|
|
|
+ /// \brief Returns the TTL of the RRset.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c RRTTL class object corresponding to the
|
|
|
+ /// TTL of the \c RRset.
|
|
|
virtual const RRTTL& getTTL() const = 0;
|
|
|
+
|
|
|
+ /// \brief Updates the owner name of the \c RRset.
|
|
|
///
|
|
|
- /// once constructed, only TTL and the set of Rdata can be modified,
|
|
|
- /// so \c setTTL() is the only explicit setter method.
|
|
|
+ /// \param name A reference to a \c RRTTL class object to be copied as the
|
|
|
+ /// new TTL.
|
|
|
+ virtual void setName(const Name& name) = 0;
|
|
|
+
|
|
|
+ /// \brief Updates the TTL of the \c RRset.
|
|
|
///
|
|
|
+ /// \param ttl A reference to a \c RRTTL class object to be copied as the
|
|
|
+ /// new TTL.
|
|
|
virtual void setTTL(const RRTTL& ttl) = 0;
|
|
|
+ //@}
|
|
|
|
|
|
///
|
|
|
- /// \name RDATA manipulation methods
|
|
|
+ /// \name Converter Methods
|
|
|
+ ///
|
|
|
+ /// These methods have the default implementation that can be reused by
|
|
|
+ /// derived classes.
|
|
|
+ /// Since they are defined as pure virtual, derived classes
|
|
|
+ /// that want to reuse the default implementation must explicitly
|
|
|
+ /// invoke their base class version (see the description for
|
|
|
+ /// <code>addRdata(const rdata::Rdata&)</code>).
|
|
|
///
|
|
|
+ /// Design Note: the default implementations are defined only using
|
|
|
+ /// other public methods of the \c AbstractRRset class, and could be
|
|
|
+ /// implemented as non member functions (as some C++ textbooks suggest).
|
|
|
+ /// However, since derived classes may want to provide customized versions
|
|
|
+ /// (especially of the \c toWire() method for performance reasons)
|
|
|
+ /// we chose to define them as virtual functions, and, as a result,
|
|
|
+ /// member functions.
|
|
|
//@{
|
|
|
- virtual void addRdata(const rdata::RdataPtr rdata) = 0;
|
|
|
- /// This method has the default implementation.
|
|
|
- /// Note: since concrete classes would define the pure virtual version
|
|
|
- /// of \c addRdata(), they'll need to declare the use of this method
|
|
|
- /// to avoid name hiding (unless they redefine this method):
|
|
|
- /// \code class CustomizedRRset : public AbstractRRset {
|
|
|
- /// public:
|
|
|
- /// using AbstractRRset::addRdata;
|
|
|
- /// ...
|
|
|
- /// }; \endcode
|
|
|
- virtual void addRdata(const rdata::Rdata& rdata);
|
|
|
+ /// \brief Convert the RRset to a string.
|
|
|
+ ///
|
|
|
+ /// Unlike other similar methods of this library, this method terminates
|
|
|
+ /// the resulting string with a trailing newline character.
|
|
|
+ /// (following the BIND9 convention)
|
|
|
+ ///
|
|
|
+ /// The RRset must contain some RDATA; otherwise, an exception of class
|
|
|
+ /// \c EmptyRRset will be thrown.
|
|
|
+ /// If resource allocation fails, a corresponding standard exception
|
|
|
+ /// will be thrown.
|
|
|
+ /// The default implementation may throw other exceptions if the
|
|
|
+ /// \c toText() method of the RDATA objects throws.
|
|
|
+ /// If a derived class of \c AbstractRRset overrides the default
|
|
|
+ /// implementation, the derived version may throw its own exceptions.
|
|
|
+ ///
|
|
|
+ /// Open issue: We may want to support multiple output formats as
|
|
|
+ /// BIND9 does. For example, we might want to allow omitting the owner
|
|
|
+ /// name when possible in the context of zone dump. This is a future
|
|
|
+ /// TODO item.
|
|
|
+ ///
|
|
|
+ /// \param rrset A reference to a (derived class of) \c AbstractRRset object
|
|
|
+ /// whose content is to be converted.
|
|
|
+ /// \return A string representation of the RRset.
|
|
|
+ virtual std::string toText() const = 0;
|
|
|
+
|
|
|
+ /// \brief Render the RRset in the wire format with name compression and
|
|
|
+ /// truncation handling.
|
|
|
+ ///
|
|
|
+ /// This method compresses the owner name of the RRset and domain names
|
|
|
+ /// used in RDATA that should be compressed.
|
|
|
+ /// In addition, this method detects the case where rendering the entire
|
|
|
+ /// RRset would cause truncation, and handles the case appropriately
|
|
|
+ /// (this is a TODO item, and not implemented in this version).
|
|
|
+ ///
|
|
|
+ /// Note: perhaps we may want to add more arguments to convey optional
|
|
|
+ /// information such as an "rrset-order" policy or how to handle truncation
|
|
|
+ /// case. This is a TODO item.
|
|
|
+ ///
|
|
|
+ /// If resource allocation fails, a corresponding standard exception
|
|
|
+ /// will be thrown.
|
|
|
+ /// The RRset must contain some RDATA; otherwise, an exception of class
|
|
|
+ /// \c EmptyRRset will be thrown.
|
|
|
+ /// The default implementation may throw other exceptions if the
|
|
|
+ /// \c toWire() method of the RDATA objects throws.
|
|
|
+ /// If a derived class of \c AbstractRRset overrides the default
|
|
|
+ /// implementation, the derived version may throw its own exceptions.
|
|
|
+ ///
|
|
|
+ /// \param renderer DNS message rendering context that encapsulates the
|
|
|
+ /// output buffer and name compression information.
|
|
|
+ /// \return The number of RRs rendered. If the truncation is necessary
|
|
|
+ /// this value may be different from the number of RDATA objects contained
|
|
|
+ /// in the RRset.
|
|
|
+ virtual unsigned int toWire(MessageRenderer& renderer) const = 0;
|
|
|
+
|
|
|
+ /// \brief Render the RRset in the wire format without any compression.
|
|
|
+ ///
|
|
|
+ /// See the other toWire() description about possible exceptions.
|
|
|
+ ///
|
|
|
+ /// \param buffer An output buffer to store the wire data.
|
|
|
+ /// \return The number of RRs rendered.
|
|
|
+ virtual unsigned int toWire(OutputBuffer& buffer) const = 0;
|
|
|
+ //@}
|
|
|
+
|
|
|
+ ///
|
|
|
+ /// \name RDATA Manipulation Methods
|
|
|
+ ///
|
|
|
+ //@{
|
|
|
+ /// \brief Add an RDATA to the RRset (pointer version).
|
|
|
+ ///
|
|
|
+ /// This method adds the given RDATA (as a pointer-like type to a
|
|
|
+ /// derived class object of \c rdata::Rdata) to the \c RRset.
|
|
|
+ ///
|
|
|
+ /// \param rdata A pointer (like) type of \c rdata::RdataPtr to be added
|
|
|
+ /// to the \c RRset.
|
|
|
+ virtual void addRdata(rdata::ConstRdataPtr rdata) = 0;
|
|
|
+
|
|
|
+ /// \brief Add an RDATA to the RRset (reference version).
|
|
|
+ ///
|
|
|
+ /// This method adds the given RDATA (as a reference to a
|
|
|
+ /// derived class object of \c rdata::Rdata) to the \c RRset.
|
|
|
+ ///
|
|
|
+ /// This method has the default implementation that can be reused by
|
|
|
+ /// derived classes.
|
|
|
+ /// Since this method is defined as pure virtual, derived classes
|
|
|
+ /// that want to reuse the default implementation must explicitly
|
|
|
+ /// invoke this base class version.
|
|
|
+ /// For example, if the class \c CustomizedRRset, a derived class of
|
|
|
+ /// \c AbstractRRset, wants to reuse the default implementation of
|
|
|
+ /// \c %addRdata() (reference version), it would be defined as follows:
|
|
|
+ /// \code void
|
|
|
+ /// CustomizedRRset::addRdata(const rdata::Rdata& rdata)
|
|
|
+ /// {
|
|
|
+ /// AbstractRRset::addRdata(rdata);
|
|
|
+ /// }
|
|
|
+ /// \endcode
|
|
|
+ ///
|
|
|
+ /// This method is more strictly typed than the pointer version:
|
|
|
+ /// If \c %rdata does not refer to the appropriate derived
|
|
|
+ /// \c Rdata class
|
|
|
+ /// for the \c RRType for this \c RRset, it throws an exception of class
|
|
|
+ /// \c std::bad_cast.
|
|
|
+ /// If resource allocation fails, a corresponding standard exception
|
|
|
+ /// will be thrown.
|
|
|
+ /// The RRset must contain some RDATA; otherwise, an exception of class
|
|
|
+ /// \c EmptyRRset will be thrown.
|
|
|
+ /// The default implementation may throw other exceptions if the
|
|
|
+ /// \c toWire() method of the RDATA objects throws.
|
|
|
+ /// If a derived class of \c AbstractRRset overrides the default
|
|
|
+ /// implementation, the derived version may throw its own exceptions.
|
|
|
+ ///
|
|
|
+ /// The default implementation simply constructs an \c rdata::RdataPtr
|
|
|
+ /// object from a newly allocated RDATA object copying from parameter
|
|
|
+ /// \c rdata, and calls the other version of
|
|
|
+ /// \c addRdata(const rdata::RdataPtr).
|
|
|
+ /// So it is inherently less efficient than the other version.
|
|
|
+ /// Still, this version would offer a more intuitive interface and is
|
|
|
+ /// provided as such.
|
|
|
+ ///
|
|
|
+ /// \param rdata A reference to a \c rdata::RdataPtr (derived) class
|
|
|
+ /// object, a copy of which is to be added to the \c RRset.
|
|
|
+ virtual void addRdata(const rdata::Rdata& rdata) = 0;
|
|
|
+
|
|
|
+ /// \brief Return an iterator to go through all RDATA stored in the
|
|
|
+ /// \c RRset.
|
|
|
+ ///
|
|
|
+ /// Using the design pattern terminology, \c getRdataIterator()
|
|
|
+ /// is an example of a <em>factory method</em>.
|
|
|
+ ///
|
|
|
+ /// Whether this method throws an exception depends on the actual
|
|
|
+ /// implementation of the derived \c AbstractRRset class, but in general
|
|
|
+ /// it will involve resource allocation and can throw a standard exception
|
|
|
+ /// if it fails.
|
|
|
+ ///
|
|
|
+ /// \return A pointer-like object pointing to the derived \c RdataIterator
|
|
|
+ /// object.
|
|
|
virtual RdataIteratorPtr getRdataIterator() const = 0;
|
|
|
//@}
|
|
|
};
|
|
|
|
|
|
+/// \brief The \c RdataIterator class is an abstract base class that
|
|
|
+/// provides an interface for accessing RDATA objects stored in an RRset.
|
|
|
+///
|
|
|
+/// While different derived classes of \c AbstractRRset may maintain the RDATA
|
|
|
+/// objects in different ways, the \c RdataIterator class provides a
|
|
|
+/// unified interface to iterate over the RDATA objects in a polymorphic
|
|
|
+/// manner.
|
|
|
+///
|
|
|
+/// Each derived class of \c AbstractRRset is expected to provide a concrete
|
|
|
+/// derived class of \c RdataIterator, and each derived \c RdataIterator
|
|
|
+/// class implements the unified interface in a way specific to the
|
|
|
+/// implementation of the corresponding derived \c AbstractRRset class.
|
|
|
+/// Using the design pattern terminology, this is a typical example of
|
|
|
+/// the \e Iterator pattern.
|
|
|
+///
|
|
|
+/// The RDATA objects stored in the \c RRset are considered to form
|
|
|
+/// a unidirectional list from the \c RdataIterator point of view (while
|
|
|
+/// the actual implementation in the derived \c RRset may not use a list).
|
|
|
+/// We call this unidirectional list the <em>%rdata list</em>.
|
|
|
+///
|
|
|
+/// An \c RdataIterator object internally (and conceptually) holds a
|
|
|
+/// <em>%rdata cursor</em>, which points to a specific item of the %rdata list.
|
|
|
+///
|
|
|
+/// Note about design choice: as is clear from the interface, \c RdataIterator
|
|
|
+/// is not compatible with the standard iterator classes.
|
|
|
+/// Although it would be useful (for example, we could then use STL algorithms)
|
|
|
+/// and is not necessarily impossible, it would make the iterator implementation
|
|
|
+/// much more complicated.
|
|
|
+/// For instance, any standard iterator must be assignable and
|
|
|
+/// copy-constructible.
|
|
|
+/// So we'd need to implement \c RdataIterator::operator=() in a polymorphic
|
|
|
+/// way. This will require non-trivial implementation tricks.
|
|
|
+/// We believe the simplified iterator interface as provided by the
|
|
|
+/// \c RdataIterator class is sufficient in practice:
|
|
|
+/// Most applications will simply go through the RDATA objects contained in
|
|
|
+/// an RRset, examining (and possibly using) each object, as one path
|
|
|
+/// operation.
|
|
|
class RdataIterator {
|
|
|
+ ///
|
|
|
+ /// \name Constructors and Destructor
|
|
|
+ ///
|
|
|
+ /// Note: The copy constructor and the assignment operator are intentionally
|
|
|
+ /// defined as private to make it explicit that this is a pure base class.
|
|
|
+ //@{
|
|
|
+protected:
|
|
|
+ /// \brief The default constructor.
|
|
|
+ ///
|
|
|
+ /// This is intentionally defined as \c protected as this base class should
|
|
|
+ /// never be instantiated (except as part of a derived class).
|
|
|
+ RdataIterator() {}
|
|
|
public:
|
|
|
+ /// \brief Destructor
|
|
|
virtual ~RdataIterator() {}
|
|
|
+private:
|
|
|
+ RdataIterator(const RdataIterator& source);
|
|
|
+ RdataIterator& operator=(const RdataIterator& source);
|
|
|
+ //@}
|
|
|
+
|
|
|
+public:
|
|
|
+ /// \brief Move the %rdata cursor to the first RDATA in the %rdata list
|
|
|
+ /// (if any).
|
|
|
+ ///
|
|
|
+ /// This method can safely be called multiple times, even after moving
|
|
|
+ /// the %rdata cursor forward by the \c next() method.
|
|
|
+ ///
|
|
|
+ /// This method should never throw an exception.
|
|
|
virtual void first() = 0;
|
|
|
+
|
|
|
+ /// \brief Move the %rdata cursor to the next RDATA in the %rdata list
|
|
|
+ /// (if any).
|
|
|
+ ///
|
|
|
+ /// This method should never throw an exception.
|
|
|
virtual void next() = 0;
|
|
|
+
|
|
|
+ /// \brief Return the current \c Rdata corresponding to the %rdata cursor.
|
|
|
+ ///
|
|
|
+ /// \return A reference to an \c rdata::::Rdata object corresponding
|
|
|
+ /// to the %rdata cursor.
|
|
|
virtual const rdata::Rdata& getCurrent() const = 0;
|
|
|
+
|
|
|
+ /// \brief Return true iff the %rdata cursor has reached the end of the
|
|
|
+ /// %rdata list.
|
|
|
+ ///
|
|
|
+ /// Once this method returns \c true, the behavior of any subsequent
|
|
|
+ /// call to \c next() or \c getCurrent() is undefined.
|
|
|
+ /// Likewise, the result of \c isLast() call followed by such undefined
|
|
|
+ /// operations is also undefined.
|
|
|
+ ///
|
|
|
+ /// This method should never throw an exception.
|
|
|
+ ///
|
|
|
+ /// \return \c true if the %rdata cursor has reached the end of the
|
|
|
+ /// %rdata list; otherwise \c false.
|
|
|
virtual bool isLast() const = 0;
|
|
|
};
|
|
|
|
|
|
-/// Straightforward RRset implementation.
|
|
|
+/// \brief The \c BasicRRset class is a concrete derived class of
|
|
|
+/// \c AbstractRRset that defines a straightforward RRset implementation.
|
|
|
+///
|
|
|
/// designed to be as portable as possible. performance is a secondary
|
|
|
/// concern for this class.
|
|
|
+///
|
|
|
+/// We'd use the default implementations for the toWire()
|
|
|
+/// variants as defined in the base class. These are not fully optimized
|
|
|
+/// for performance, but, again, it's a secondary goal for this generic
|
|
|
+/// class.
|
|
|
class BasicRRset : public AbstractRRset {
|
|
|
+ ///
|
|
|
+ /// \name Constructors and Destructor
|
|
|
+ ///
|
|
|
+ /// Note: The copy constructor and the assignment operator are intentionally
|
|
|
+ /// defined as private. The intended use case wouldn't require copies of
|
|
|
+ /// a \c BasicRRset object; once created, it would normally be used
|
|
|
+ /// as a \c const object (via references).
|
|
|
+ //@{
|
|
|
private:
|
|
|
BasicRRset(const BasicRRset& source);
|
|
|
- void operator=(const BasicRRset& source);
|
|
|
+ BasicRRset& operator=(const BasicRRset& source);
|
|
|
public:
|
|
|
+ /// \brief Constructor from (mostly) fixed parameters of the RRset.
|
|
|
+ ///
|
|
|
+ /// This constructor is normally expected to be exception free, but
|
|
|
+ /// copying the name may involve resource allocation, and if it fails
|
|
|
+ /// the corresponding standard exception will be thrown.
|
|
|
+ ///
|
|
|
+ /// \param name The owner name of the RRset.
|
|
|
+ /// \param rrclass The RR class of the RRset.
|
|
|
+ /// \param rrtype The RR type of the RRset.
|
|
|
+ /// \param ttl The TTL of the RRset.
|
|
|
explicit BasicRRset(const Name& name, const RRClass& rrclass,
|
|
|
const RRType& rrtype, const RRTTL& ttl);
|
|
|
+ /// \brief The destructor.
|
|
|
virtual ~BasicRRset();
|
|
|
+ //@}
|
|
|
+
|
|
|
///
|
|
|
- /// See the note for the base class version.
|
|
|
+ /// \name Getter and Setter Methods
|
|
|
///
|
|
|
- using AbstractRRset::addRdata;
|
|
|
- virtual void addRdata(const rdata::RdataPtr rdata);
|
|
|
+ //@{
|
|
|
+ /// \brief Returns the number of \c Rdata objects contained in the \c RRset.
|
|
|
///
|
|
|
- /// We'd use the default implementations for toText() and toWire()
|
|
|
- /// variants as defined in the base class. These are not fully optimized
|
|
|
- /// for performance, but, again, it's a secondary goal for this generic
|
|
|
- /// class.
|
|
|
+ /// This method never throws an exception.
|
|
|
+ ///
|
|
|
+ /// \return The number of \c Rdata objects contained.
|
|
|
+ virtual unsigned int getRdataCount() const;
|
|
|
|
|
|
+ /// \brief Returns the owner name of the \c RRset.
|
|
|
///
|
|
|
- /// \name Getter and setter methods
|
|
|
+ /// This method never throws an exception.
|
|
|
///
|
|
|
- //@{
|
|
|
- virtual unsigned int getRdataCount() const;
|
|
|
+ /// \return A reference to a \c Name class object corresponding to the
|
|
|
+ /// \c RRset owner name.
|
|
|
virtual const Name& getName() const;
|
|
|
+
|
|
|
+ /// \brief Returns the RR Class of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// This method never throws an exception.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c RRClass class object corresponding to the
|
|
|
+ /// RR class of the \c RRset.
|
|
|
virtual const RRClass& getClass() const;
|
|
|
+
|
|
|
+ /// \brief Returns the RR Type of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// This method never throws an exception.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c RRType class object corresponding to the
|
|
|
+ /// RR type of the \c RRset.
|
|
|
virtual const RRType& getType() const;
|
|
|
+
|
|
|
+ /// \brief Returns the TTL of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// This method never throws an exception.
|
|
|
+ ///
|
|
|
+ /// \return A reference to a \c RRTTL class object corresponding to the
|
|
|
+ /// TTL of the \c RRset.
|
|
|
virtual const RRTTL& getTTL() const;
|
|
|
+
|
|
|
+ /// \brief Updates the owner name of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// This method normally does not throw an exception, but could throw
|
|
|
+ /// some standard exception on resource allocation failure if the
|
|
|
+ /// internal copy of the \c name involves resource allocation and it
|
|
|
+ /// fails.
|
|
|
+ ///
|
|
|
+ /// \param name A reference to a \c RRTTL class object to be copied as the
|
|
|
+ /// new TTL.
|
|
|
+ virtual void setName(const Name& name);
|
|
|
+
|
|
|
+ /// \brief Updates the TTL of the \c RRset.
|
|
|
+ ///
|
|
|
+ /// This method never throws an exception.
|
|
|
+ ///
|
|
|
+ /// \param ttl A reference to a \c RRTTL class object to be copied as the
|
|
|
+ /// new TTL.
|
|
|
virtual void setTTL(const RRTTL& ttl);
|
|
|
//@}
|
|
|
+
|
|
|
+ ///
|
|
|
+ /// \name Converter Methods
|
|
|
+ ///
|
|
|
+ //@{
|
|
|
+ /// \brief Convert the RRset to a string.
|
|
|
+ ///
|
|
|
+ /// This method simply uses the default implementation.
|
|
|
+ /// See \c AbstractRRset::toText().
|
|
|
+ virtual std::string toText() const;
|
|
|
+
|
|
|
+ /// \brief Render the RRset in the wire format with name compression and
|
|
|
+ /// truncation handling.
|
|
|
+ ///
|
|
|
+ /// This method simply uses the default implementation.
|
|
|
+ /// See \c AbstractRRset::toWire(MessageRenderer&)const.
|
|
|
+ virtual unsigned int toWire(MessageRenderer& renderer) const;
|
|
|
+
|
|
|
+ /// \brief Render the RRset in the wire format without any compression.
|
|
|
+ ///
|
|
|
+ /// This method simply uses the default implementation.
|
|
|
+ /// See \c AbstractRRset::toWire(OutputBuffer&)const.
|
|
|
+ virtual unsigned int toWire(OutputBuffer& buffer) const;
|
|
|
+ //@}
|
|
|
+
|
|
|
///
|
|
|
+ /// \name RDATA manipulation methods
|
|
|
+ ///
|
|
|
+ //@{
|
|
|
+ /// \brief Add an RDATA to the RRset (pointer version).
|
|
|
+ ///
|
|
|
+ /// This method is normally expected to be exception free, but it may
|
|
|
+ /// involve resource allocation, and if it fails the corresponding
|
|
|
+ /// standard exception will be thrown.
|
|
|
+ ///
|
|
|
+ /// \param rdata A pointer (like) type of \c rdata::RdataPtr to be added
|
|
|
+ /// to the \c BasicRRset.
|
|
|
+ virtual void addRdata(rdata::ConstRdataPtr rdata);
|
|
|
+
|
|
|
+ /// \brief Add an RDATA to the RRset (reference version).
|
|
|
+ ///
|
|
|
+ /// This method simply uses the default implementation.
|
|
|
+ /// See \c AbstractRRset::addRdata(const rdata::Rdata&).
|
|
|
+ virtual void addRdata(const rdata::Rdata& rdata);
|
|
|
+
|
|
|
+ /// \brief Return an iterator to go through all RDATA stored in the
|
|
|
+ /// \c BasicRRset.
|
|
|
+ ///
|
|
|
+ /// This is a concrete derived implementation of
|
|
|
+ /// \c AbstractRRset::getRdataIterator().
|
|
|
+ ///
|
|
|
+ /// This method dynamically allocates resources. If it fails it will
|
|
|
+ /// throw the corresponding standard exception.
|
|
|
+ /// The iterator methods for the \c BasicRRset class are exception free.
|
|
|
+ ///
|
|
|
+ /// \return A pointer-like object pointing to the derived \c RdataIterator
|
|
|
+ /// object for the \c BasicRRset class.
|
|
|
virtual RdataIteratorPtr getRdataIterator() const;
|
|
|
+ //@}
|
|
|
private:
|
|
|
BasicRRsetImpl* impl_;
|
|
|
};
|
|
|
|
|
|
+/// \brief Insert the \c RRset as a string into stream.
|
|
|
+///
|
|
|
+/// This method convert the \c rrset into a string and inserts it into the
|
|
|
+/// output stream \c os.
|
|
|
+///
|
|
|
+/// This function overloads the global \c operator<< to behave as described in
|
|
|
+/// \c %ostream::%operator<< but applied to RRset objects.
|
|
|
+///
|
|
|
+/// \param os A \c std::ostream object on which the insertion operation is
|
|
|
+/// performed.
|
|
|
+/// \param rrset A reference to a (derived class of) \c AbstractRRset object
|
|
|
+/// output by the operation.
|
|
|
+/// \return A reference to the same \c std::ostream object referenced by
|
|
|
+/// parameter \c os after the insertion operation.
|
|
|
std::ostream& operator<<(std::ostream& os, const AbstractRRset& rrset);
|
|
|
} // end of namespace dns
|
|
|
} // end of namespace isc
|