Browse Source

more detailed description for the rdata and generic rdata classes

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-dnsrdata2@808 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 15 years ago
parent
commit
d8412e1da7
1 changed files with 248 additions and 17 deletions
  1. 248 17
      src/lib/dns/cpp/rdata.h

+ 248 - 17
src/lib/dns/cpp/rdata.h

@@ -21,8 +21,6 @@
 
 #include <boost/shared_ptr.hpp>
 
-#include "name.h"
-
 namespace isc {
 namespace dns {
 class InputBuffer;
@@ -65,7 +63,13 @@ public:
         isc::Exception(file, line, what) {}
 };
 
+// Forward declaration to define RdataPtr.
 class Rdata;
+
+///
+/// The \c RdataPtr type is a pointer-like type, pointing to an
+/// object of some concrete derived class of \c Rdata.
+///
 typedef boost::shared_ptr<Rdata> RdataPtr;
 
 /// \brief Possible maximum length of RDATA, which is the maximum unsigned
@@ -76,55 +80,281 @@ const size_t MAX_RDLENGTH = 65535;
 /// RDATA as defined in RFC1035, not including the 1-byte length field.
 const unsigned int MAX_CHARSTRING_LEN = 255;
 
-/// Abstract RDATA class
+/// \brief The \c Rdata class is an abstract base class that provides
+/// a set of common interfaces to manipulate concrete RDATA objects.
+///
+/// Generally, a separate derived class directly inherited from the base
+/// \c Rdata class is defined for each well known RDATA.
+/// Each of such classes will define the common logic based on the
+/// corresponding protocol standard.
+///
+/// Since some types of RRs are class specific and the corresponding RDATA
+/// may have different semantics (e.g. type A for class IN and type A for
+/// class CH have different representations and semantics), we separate
+/// \c Rdata derived classes for such RR types in different namespaces.
+/// The namespace of types specific to a class is named the lower-cased class
+/// name; for example, RDATA of class IN-specific types are defined in the
+/// \c in namespace, and RDATA of class CH-specific types are defined in
+/// the \c ch namespace, and so on.
+/// The derived classes are named using the RR type name (upper cased) such as
+/// \c A or \c AAAA.
+/// Thus RDATA of type A RR for class IN and CH are defined as \c in::A and
+/// \c ch::A, respectively.
+/// Many other RR types are class independent; the derived \c Rdata classes
+/// for such RR types are defined in the \c generic namespace.  Examples are
+/// \c generic::NS and \c generic::SOA.
+///
+/// If applications need to refer to these derived classes, it is generally
+/// recommended to prepend at least some part of the namespace because the
+/// same class name can be used in different namespaces.
+/// So, instead of doing
+/// \code using namespace isc::dns::rdata::in;
+/// A& rdata_type_a; \endcode
+/// it is advisable to prepend at least \c in from the namespace:
+/// \code using namespace isc::dns::rdata;
+/// in::A& rdata_type_a; \endcode
+///
+/// In many cases, however, an application doesn't have to care about such
+/// derived classes.
+/// For instance, to parse an incoming DNS message an application wouldn't
+/// have to perform type specific operation unless the application is
+/// specifically concerned about a particular type.
+/// So, this API generally handles \c Rdata in a polymorphic way through
+/// a pointer or reference to this base abstract class.
 class Rdata {
+    ///
+    /// \name Constructors and Destructor
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.  Concrete classes should generally specialize their
+    /// own versions of these methods.
+    //@{
 protected:
+    /// 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).  In many
+    /// cases, the derived class wouldn't define a public default constructor
+    /// either, because an \c Rdata object without concrete data isn't
+    /// meaningful.
     Rdata() {}
 private:
-    /// Copy constructor is intentionally private.  Concrete classes should
-    /// generally specialize their own versions of copy constructor.
     Rdata(const Rdata& source);
     void operator=(const Rdata& source);
 public:
+    /// The destructor.
     virtual ~Rdata() {};
+    //@}
 
     ///
     /// \name Converter methods
     ///
     //@{
+    /// \brief Convert an \c Rdata to a string.
+    ///
+    /// This method returns a \c std::string object representing the \c Rdata.
+    ///
+    /// This is a pure virtual method without the definition; the actual
+    /// representation is specific to each derived concrete class and
+    /// should be explicitly defined in the derived class.
+    ///
+    /// \return A string representation of \c Rdata.
     virtual std::string toText() const = 0;
+    /// \brief Render the \c Rdata in the wire format into a buffer.
+    ///
+    /// This is a pure virtual method without the definition; the actual
+    /// conversion is specific to each derived concrete class and
+    /// should be explicitly defined in the derived class.
+    ///
+    /// \param buffer An output buffer to store the wire data.
     virtual void toWire(OutputBuffer& buffer) const = 0;
+    /// \brief Render the \c Rdata in the wire format into a
+    /// \c MessageRenderer object.
+    ///
+    /// This is a pure virtual method without the definition; the actual
+    /// conversion is specific to each derived concrete class and
+    /// should be explicitly defined in the derived class.
+    ///
+    /// \param renderer DNS message rendering context that encapsulates the
+    /// output buffer in which the \c Rdata is to be stored.
     virtual void toWire(MessageRenderer& renderer) const = 0;
     //@}
 
-    /// Note about implementation choice: the current implementation relies on
-    /// dynamic_cast to ensure that the \c other is the same concrete Rdata
-    /// class as \c this object.  Alternatively, we could first convert the
-    /// data into wire-format and compare the pair as opaque data.  This would
-    /// be more polymorphic, but might involve significant overhead, especially
-    /// for a large size of RDATA.
+    ///
+    /// \name Comparison method
+    ///
+    //@{
+    /// \brief Compare two instances of \c Rdata.
+    ///
+    /// This method compares \c this and the \c other Rdata objects
+    /// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+    /// the result as an integer.
+    ///
+    /// This is a pure virtual method without the definition; the actual
+    /// comparison logic is specific to each derived concrete class and
+    /// should be explicitly defined in the derived class.
+    ///
+    /// Specific implementations of this method must confirm that \c this
+    /// and the \c other are objects of the same concrete derived class of
+    /// \c Rdata.  This is normally done by \c dynamic_cast in the
+    /// implementation.  It also means if the assumption doesn't met
+    /// an exception of class \c std::bad_cast will be thrown.
+    ///
+    /// Here is an implementation choice: instead of relying on
+    /// \c dynamic_cast, we could first convert the data into wire-format
+    /// and compare the pair as opaque data.  This would be more polymorphic,
+    /// but might involve significant overhead, especially for a large size
+    /// of RDATA.
+    ///
+    /// \param other the right-hand operand to compare against.
+    /// \return < 0 if \c this would be sorted before \c other.
+    /// \return 0 if \c this is identical to \c other in terms of sorting order.
+    /// \return > 0 if \c this would be sorted after \c other.
     virtual int compare(const Rdata& other) const = 0;
+    //@}
 };
 
 namespace generic {
+
+/// \brief The \c GenericImpl class is the actual implementation of the
+/// \c generic::Generic class.
+///
+/// The implementation is hidden from applications.  This approach requires
+/// dynamic memory allocation on construction, copy, or assignment, but
+/// we believe it should be acceptable as "unknown" RDATA should be pretty
+/// rare.
 struct GenericImpl;
 
+/// \brief The \c generic::Generic class represents generic "unknown" RDATA.
+///
+/// This class is used as a placeholder for all non well-known type of RDATA.
+/// By definition, the stored data is regarded as opaque binary without
+/// assuming any structure.
 class Generic : public Rdata {
 public:
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    //@{
+    /// \brief Constructor from a string.
+    ///
+    /// This method constructs a \c generic::Generic object from a textual
+    /// representation as defined in RFC3597.
+    ///
+    /// If \c rdata_string isn't a valid textual representation of this type
+    /// of RDATA, an exception of class \c InvalidRdataText or
+    /// \c InvalidRdataLength will be thrown.
+    /// If resource allocation to store the data fails, a corresponding standard
+    /// exception will be thrown.
+    ///
+    /// \param rdata_string A string of textual representation of generic
+    /// RDATA.
     explicit Generic(const std::string& rdata_string);
-    explicit Generic(InputBuffer& buffer, size_t rdata_len);
+    ///
+    /// \brief Constructor from wire-format data.
+    ///
+    /// The \c buffer parameter normally stores a complete DNS message
+    /// containing the generic RDATA to be constructed.
+    /// The current read position of the buffer points to the head of the
+    /// data.
+    ///
+    /// This method reads \c rdata_len bytes from the \c buffer, and internally
+    /// stores the data as an opaque byte sequence.
+    ///
+    /// \c rdata_len must not exceed \c MAX_RDLENGTH; otherwise, an exception
+    /// of class \c InvalidRdataLength will be thrown.
+    /// If resource allocation to hold the data fails, a corresponding standard
+    /// exception will be thrown; if the \c buffer doesn't contain \c rdata_len
+    /// bytes of unread data, an exception of class \c InvalidBufferPosition
+    /// will be thrown.
+    ///
+    /// \param buffer A reference to an \c InputBuffer object storing the
+    /// \c Rdata to parse.
+    /// \param rdata_len The length in buffer of the \c Rdata.  In bytes.
+    Generic(InputBuffer& buffer, size_t rdata_len);
+    ///
+    /// \brief The destructor.
     virtual ~Generic();
+    ///
+    /// \brief The copy constructor.
+    ///
+    /// If resource allocation to copy the data fails, a corresponding standard
+    /// exception will be thrown.
+    ///
+    /// \param source A reference to a \c generic::Generic object to copy from.
     Generic(const Generic& source);
+    ///
+    /// \brief The assignment operator.
+    ///
+    /// If resource allocation to copy the data fails, a corresponding standard
+    /// exception will be thrown.
+    ///
+    /// \param source A reference to a \c generic::Generic object to copy from.
     Generic& operator=(const Generic& source);
+    //@}
+    ///
+    /// \name Converter methods
+    ///
+    //@{
+    /// \brief Convert an \c generic::Generic object to a string.
+    ///
+    /// This method converts a generic "unknown" RDATA object into a textual
+    /// representation of such unknown data as defined in RFC3597.
+    ///
+    /// If resource allocation to copy the data fails, a corresponding standard
+    /// exception will be thrown.
+    ///
+    /// \return A string representation of \c generic::Generic.
     virtual std::string toText() const;
+    ///
+    /// \brief Render the \c generic::Generic in the wire format into a buffer.
+    ///
+    /// This will require \c rdata_len bytes of remaining capacity in the
+    /// \c buffer.  If this is not the case and resource allocation for the
+    /// necessary memory space fails, a corresponding standard exception will
+    /// be thrown.
+    ///
+    /// \param buffer An output buffer to store the wire data.
     virtual void toWire(OutputBuffer& buffer) const;
+    /// \brief Render the \c generic::Generic in the wire format into a
+    /// \c MessageRenderer object.
+    ///
+    /// This will require \c rdata_len bytes of remaining capacity in the
+    /// \c buffer.  If this is not the case and resource allocation for the
+    /// necessary memory space fails, a corresponding standard exception will
+    /// be thrown.
+    ///
+    /// \param renderer DNS message rendering context that encapsulates the
+    /// output buffer in which the \c Generic object is to be stored.
     virtual void toWire(MessageRenderer& renderer) const;
+    //@}
+    ///
+    /// \name Comparison method
     ///
-    /// Note: the comparison is RR type/class agnostic: this method doesn't
-    /// check whether the two Rdata objects to compare are of the comparable
-    /// RR type/class.  The caller must ensure this condition.
+    //@{
+    /// \brief Compare two instances of \c generic::Generic objects.
+    ///
+    /// As defined in RFC4034, this method simply compares the wire-format
+    /// representations of the two objects as left-justified unsigned octet
+    /// sequences.
     ///
+    /// The object referenced by \c other must have been instantiated as
+    /// a c generic::Generic class object; otherwise, an exception of class
+    /// \c std::bad_cast will be thrown.
+    /// Note that the comparison is RR type/class agnostic: this method doesn't
+    /// check whether the two \c Rdata objects to compare are of the comparable
+    /// RR type/class.  For example, \c this object may come from an \c RRset
+    /// of \c RRType x, and the \c other may come from a different \c RRset
+    /// of \c RRType y (where x != y).  This situation would be considered a
+    /// bug, but this method cannot detect this type of error.
+    /// The caller must ensure this condition.
+    ///
+    /// \param other the right-hand operand to compare against.
+    /// \return < 0 if \c this would be sorted before \c other.
+    /// \return 0 if \c this is identical to \c other in terms of sorting order.
+    /// \return > 0 if \c this would be sorted after \c other.
     virtual int compare(const Rdata& other) const;
+    //@}
 private:
     GenericImpl* impl_;
 };
@@ -143,8 +373,7 @@ private:
 /// \param rdata The \c Generic 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 Generic& rdata);
+std::ostream& operator<<(std::ostream& os, const Generic& rdata);
 } // end of namespace "generic"
 
 //
@@ -172,6 +401,8 @@ operator<<(std::ostream& os, const Generic& rdata);
 /// respectively, then it would create a new \c RdataPtr object as follows:
 /// \code RdataPtr rdata = createRdata(RRType(type_txt), RRClass(class_txt),
 ///                              nsname_txt); \endcode
+/// On success, \c rdata will point to an object of the \c generic::NS class
+/// that internally holds a domain name of "ns.example.com."
 ///
 /// Internally, these functions uses the corresponding
 /// \c RRParamRegistry::createRdata methods of the \c RRParamRegistry.