diff options
Diffstat (limited to 'src/lib/dns/rrparamregistry.h')
-rw-r--r-- | src/lib/dns/rrparamregistry.h | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/src/lib/dns/rrparamregistry.h b/src/lib/dns/rrparamregistry.h new file mode 100644 index 0000000..27e8a4f --- /dev/null +++ b/src/lib/dns/rrparamregistry.h @@ -0,0 +1,545 @@ +// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef RRPARAMREGISTRY_H +#define RRPARAMREGISTRY_H 1 + +#include <string> + +#include <stdint.h> + +#include <boost/shared_ptr.hpp> + +#include <dns/exceptions.h> + +#include <dns/rdata.h> + +namespace isc { +namespace dns { + +// forward declarations +struct RRParamRegistryImpl; + +/// +/// \brief A standard DNS module exception that is thrown if a new RR type is +/// being registered with a different type string. +/// +class RRTypeExists : public isc::dns::Exception { +public: + RRTypeExists(const char* file, size_t line, const char* what) : + isc::dns::Exception(file, line, what) {} +}; + +/// +/// \brief A standard DNS module exception that is thrown if a new RR class is +/// being registered with a different type string. +/// +class RRClassExists : public isc::dns::Exception { +public: + RRClassExists(const char* file, size_t line, const char* what) : + isc::dns::Exception(file, line, what) {} +}; + +namespace rdata { +/// \brief The \c AbstractRdataFactory class is an abstract base class to +/// encapsulate a set of Rdata factory methods in a polymorphic way. +/// +/// An external developer who wants to introduce a new or experimental RR type +/// is expected to define a corresponding derived class of \c +/// AbstractRdataFactory and register it via \c RRParamRegistry. +/// +/// Other users of this API normally do not have to care about this class +/// or its derived classes; this class is generally intended to be used +/// as an internal utility of the API implementation. +class AbstractRdataFactory { + /// + /// \name Constructors and Destructor + /// + //@{ +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). + AbstractRdataFactory() {} +public: + /// The destructor. + virtual ~AbstractRdataFactory() {}; + //@} + + /// + /// \name Factory methods for polymorphic creation. + /// + //@{ + + /// \brief Create RDATA from a string. + /// + /// This method creates from a string an \c Rdata object of specific class + /// corresponding to the specific derived class of \c AbstractRdataFactory. + /// + /// \param rdata_str A string of textual representation of the \c Rdata. + /// \return An \c RdataPtr object pointing to the created \c Rdata object. + virtual RdataPtr create(const std::string& rdata_str) const = 0; + + /// \brief Create RDATA from wire-format data. + /// + /// This method creates from wire-format binary data an \c Rdata object + /// of specific class corresponding to the specific derived class of + /// \c AbstractRdataFactory. + /// + /// \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. + /// \return An \c RdataPtr object pointing to the created \c Rdata object. + virtual RdataPtr create(isc::util::InputBuffer& buffer, size_t rdata_len) const = 0; + + /// \brief Create RDATA from another \c Rdata object of the same type. + /// + /// This method creates an \c Rdata object of specific class corresponding + /// to the specific derived class of \c AbstractRdataFactory, copying the + /// content of the given \c Rdata, \c source. + /// + /// \c source must be an object of the concrete derived class corresponding + /// to the specific derived class of \c AbstractRdataFactory; + /// otherwise, an exception of class \c std::bad_cast will be thrown. + /// + /// \param source A reference to an \c Rdata object whose content is to + /// be copied to the created \c Rdata object. + /// \return An \c RdataPtr object pointing to the created \c Rdata object. + virtual RdataPtr create(const rdata::Rdata& source) const = 0; + + /// \brief Create RDATA using MasterLexer. + /// + /// This version of the method defines the entry point of factory + /// of a specific RR type and class for \c RRParamRegistry::createRdata() + /// that uses \c MasterLexer. See its description for the expected + /// behavior and meaning of the parameters. + virtual RdataPtr create(MasterLexer& lexer, const Name* origin, + MasterLoader::Options options, + MasterLoaderCallbacks& callbacks) const = 0; + //@} +}; + +/// +/// The \c RdataFactoryPtr type is a pointer-like type, pointing to an +/// object of some concrete derived class of \c AbstractRdataFactory. +/// +typedef boost::shared_ptr<AbstractRdataFactory> RdataFactoryPtr; +} // end of namespace rdata + +/// +/// The \c RRParamRegistry class represents a registry of parameters to +/// manipulate DNS resource records (RRs). +/// +/// A \c RRParamRegistry class object stores a mapping between RR types or +/// classes and their textual representations. It will also have knowledge of +/// how to create an RDATA object for a specific pair of RR type and class +/// (not implemented in this version). +/// +/// Normal applications that only handle standard DNS protocols won't have to +/// care about this class. This is mostly an internal class to the DNS library +/// to manage standard parameters. Some advanced applications may still need +/// to use this class explicitly. For example, if an application wants to +/// define and use an experimental non-standard RR type, it may want to register +/// related protocol parameters for its convenience. This class is designed to +/// allow such usage without modifying the library source code or rebuilding +/// the library. +/// +/// It is assumed that at most one instance of this class can exist so that +/// the application uses the consistent set of registered parameters. To ensure +/// this, this class is designed and implemented as a "singleton class": the +/// constructor is intentionally private, and applications must get access to +/// the single instance via the \c getRegistry() static member function. +/// +/// In the current implementation, access to the singleton \c RRParamRegistry +/// object is not thread safe. +/// The application should ensure that multiple threads don't race in the +/// first invocation of \c getRegistry(), and, if the registry needs to +/// be changed dynamically, read and write operations are performed +/// exclusively. +/// Since this class should be static in common usage this restriction would +/// be acceptable in practice. +/// In the future, we may extend the implementation so that multiple threads can +/// get access to the registry fully concurrently without any restriction. +/// +/// Note: the implementation of this class is incomplete: we should at least +/// add RDATA related parameters. This will be done in a near future version, +/// at which point some of method signatures will be changed. +class RRParamRegistry { + /// + /// \name Constructors and Destructor + /// + /// These are intentionally hidden (see the class description). + //@{ +private: + RRParamRegistry(); + RRParamRegistry(const RRParamRegistry& orig); + ~RRParamRegistry(); + //@} +public: + /// + /// \brief Return the singleton instance of \c RRParamRegistry. + /// + /// This method is a unified access point to the singleton instance of + /// the RR parameter registry (\c RRParamRegistry). + /// On first invocation it internally constructs an instance of the + /// \c RRParamRegistry class and returns a reference to it. + /// This is a static object inside this method and will remain valid + /// throughout the rest of the application lifetime. + /// On subsequent calls this method simply returns a reference to the + /// singleton object. + /// + /// If resource allocation fails in the first invocation, + /// a corresponding standard exception will be thrown. + /// This method never fails otherwise. In particular, this method + /// doesn't throw an exception once the singleton instance is constructed. + /// + /// \return A reference to the singleton instance of \c RRParamRegistry. + static RRParamRegistry& getRegistry(); + + /// + /// \name Registry Update Methods + /// + //@{ + /// + /// \brief Add a set of parameters for a pair of RR type and class. + /// + /// This method adds to the registry a specified set of RR parameters, + /// including mappings between type/class codes and their textual + /// representations. + /// + /// Regarding the mappings between textual representations and integer + /// codes, this method behaves in the same way as \c addType() and + /// \c addClass(). That is, it ignores any overriding attempt as + /// long as the mapping is the same; otherwise the corresponding exception + /// will be thrown. + /// + /// This method provides the strong exception guarantee: unless an + /// exception is thrown the entire specified set of parameters must be + /// stored in the registry; if this method throws an exception the + /// registry will remain in the state before this method is called. + /// + /// \param type_string The textual representation of the RR type. + /// \param type_code The integer code of the RR type. + /// \param class_string The textual representation of the RR class. + /// \param class_code The integer code of the RR class. + /// \param rdata_factory An \c RdataFactoryPtr object pointing to a + /// concrete RDATA factory. + void add(const std::string& type_string, uint16_t type_code, + const std::string& class_string, uint16_t class_code, + rdata::RdataFactoryPtr rdata_factory); + + /// \brief Add a set of parameters for a class-independent RR type. + /// + /// This method behaves as exactly same as the other \c add method except + /// that it handles class-independent types (such as NS, CNAME, or SOA). + /// + /// \param type_string The textual representation of the RR type. + /// \param type_code The integer code of the RR type. + /// \param rdata_factory An \c RdataFactoryPtr object pointing to a + /// concrete RDATA factory. + void add(const std::string& type_string, uint16_t type_code, + rdata::RdataFactoryPtr rdata_factory); + + /// \brief Add mappings between RR type code and textual representation. + /// + /// This method adds a mapping from the type code of an RR to its textual + /// representation and the reverse mapping in the registry. + /// + /// If the given RR type is already registered with the same textual + /// representation, this method simply ignores the duplicate mapping; + /// if the given type is registered and a new pair with a different + /// textual representation is being added,an exception of class + /// \c RRTypeExist will be thrown. + /// To replace an existing mapping with a different textual representation, + /// the existing one must be removed by the \c removeType() method + /// beforehand. + /// + /// In addition, if resource allocation for the new mapping entries fails, + /// a corresponding standard exception will be thrown. + /// + /// This method provides the strong exception guarantee: unless an exception + /// is thrown the specified mappings must be stored in the registry + /// (although it may be an already existing one) on completion of the + /// method; if this method throws an exception the registry will remain + /// in the state before this method is called. + /// + /// \param type_string The textual representation of the RR type. + /// \param type_code The integer code of the RR type. + /// \return \c true if a new mapping is added to the repository; \c false + /// if the same mapping is already registered. + bool addType(const std::string& type_string, uint16_t type_code); + + /// \brief Remove mappings between RR type code and textual representation + /// for a given type. + /// + /// This method can safely be called whether or not the specified mappings + /// exist in the registry. If not, this method simply ignores the attempt + /// and returns \c false. + /// + /// This method never throws an exception. + /// + /// \param type_code The integer code of the RR type. + /// \return \c true if mappings for the specified RR type exists and is + /// removed; \c false if no such mapping is in the registry. + bool removeType(uint16_t type_code); + + /// \brief Add mappings between RR class code and textual representation. + /// + /// This method adds a mapping from the class code of an RR to its textual + /// representation and the reverse mapping in the registry. + /// + /// If the given RR class is already registered with the same textual + /// representation, this method simply ignores the duplicate mapping; + /// if the given class is registered and a new pair with a different + /// textual representation is being added,an exception of class + /// \c RRClassExist will be thrown. + /// To replace an existing mapping with a different textual representation, + /// the existing one must be removed by the \c removeClass() method + /// beforehand. + /// + /// In addition, if resource allocation for the new mapping entries fails, + /// a corresponding standard exception will be thrown. + /// + /// This method provides the strong exception guarantee: unless an exception + /// is thrown the specified mappings must be stored in the registry + /// (although it may be an already existing one) on completion of the + /// method; if this method throws an exception the registry will remain + /// in the state before this method is called. + /// + /// \param class_string The textual representation of the RR class. + /// \param class_code The integer code of the RR class. + /// \return \c true if a new mapping is added to the repository; \c false + /// if the same mapping is already registered. + bool addClass(const std::string& class_string, uint16_t class_code); + + /// \brief Remove mappings between RR class code and textual representation + /// for a given class. + /// + /// This method can safely be called whether or not the specified mappings + /// exist in the registry. If not, this method simply ignores the attempt + /// and returns \c false. + /// + /// This method never throws an exception. + /// + /// \param class_code The integer code of the RR class. + /// \return \c true if mappings for the specified RR type exists and is + /// removed; \c false if no such mapping is in the registry. + bool removeClass(uint16_t class_code); + + /// \brief Remove registered RDATA factory for the given pair of \c RRType + /// and \c RRClass. + /// + /// This method can safely be called whether or not the specified factory + /// object exist in the registry. If not, this method simply ignores the + /// attempt and returns \c false. + /// + /// This method never throws an exception. + /// + /// \param rrtype An \c RRType object specifying the type/class pair. + /// \param rrclass An \c RRClass object specifying the type/class pair. + /// \return \c true if a factory object for the specified RR type/class + /// pair exists and is removed; \c false if no such object is in the + /// registry. + bool removeRdataFactory(const RRType& rrtype, const RRClass& rrclass); + + /// \brief Remove registered RDATA factory for the given pair of \c RRType + /// and \c RRClass. + /// + /// This method can safely be called whether or not the specified factory + /// object exist in the registry. If not, this method simply ignores the + /// attempt and returns \c false. + /// + /// This method never throws an exception. + /// + /// \param rrtype An \c RRType object specifying the type/class pair. + /// \return \c true if a factory object for the specified RR type/class + /// pair exists and is removed; \c false if no such object is in the + /// registry. + bool removeRdataFactory(const RRType& rrtype); + //@} + + /// + /// \name Parameter Conversion Methods + /// + //@{ + /// \brief Convert a textual representation of an RR type to the + /// corresponding 16-bit integer code. + /// + /// This method searches the \c RRParamRegistry for the mapping from + /// the given textual representation of RR type to the corresponding + /// integer code. If a mapping is found, it returns true with the + /// associated type code in \c type_code; otherwise, if the given + /// string is in the form of "TYPEnnnn", it returns true with the + /// corresponding number as the type code in \c type_code; + /// otherwise, it returns false and \c type_code is untouched. + /// + /// It returns \c false and avoids throwing an exception in the case + /// of an error to avoid the exception overhead in some situations. + /// + /// \param type_string The textual representation of the RR type. + /// \param type_code Returns the RR type code in this argument. + /// \return true if conversion is successful, false otherwise. + bool textToTypeCode(const std::string& type_string, + uint16_t& type_code) const; + + /// \brief Convert type code into its textual representation. + /// + /// This method searches the \c RRParamRegistry for the mapping from the + /// given RR type code to its textual representation. + /// If a mapping is found, it returns (a copy of) the associated string; + /// otherwise, this method creates a new string in the form of "TYPEnnnn" + /// where "nnnn" is the decimal representation of the type code, and + /// returns the new string. + /// + /// If resource allocation for the returned string fails, + /// a corresponding standard exception will be thrown. + /// This method never fails otherwise. + /// + /// \param type_code The integer code of the RR type. + /// \return A textual representation of the RR type for code \c type_code. + std::string codeToTypeText(uint16_t type_code) const; + + /// \brief Convert a textual representation of an RR class to the + /// corresponding 16-bit integer code. + /// + /// This method searches the \c RRParamRegistry for the mapping from + /// the given textual representation of RR class to the + /// corresponding integer code. If a mapping is found, it returns + /// true with the associated class code in \c class_code; otherwise, + /// if the given string is in the form of "CLASSnnnn", it returns + /// true with the corresponding number as the class code in + /// \c class_code; otherwise, it returns false and \c class_code is + /// untouched. + /// + /// It returns \c false and avoids throwing an exception in the case + /// of an error to avoid the exception overhead in some situations. + /// + /// \param class_string The textual representation of the RR class. + /// \param class_code Returns the RR class code in this argument. + /// \return true if conversion is successful, false otherwise. + bool textToClassCode(const std::string& class_string, + uint16_t& class_code) const; + + /// \brief Convert class code into its textual representation. + /// + /// This method searches the \c RRParamRegistry for the mapping from the + /// given RR class code to its textual representation. + /// If a mapping is found, it returns (a copy of) the associated string; + /// otherwise, this method creates a new string in the form of "CLASSnnnn" + /// where "nnnn" is the decimal representation of the class code, and + /// returns the new string. + /// + /// If resource allocation for the returned string fails, + /// a corresponding standard exception will be thrown. + /// This method never fails otherwise. + /// + /// \param class_code The integer code of the RR class. + /// \return A textual representation of the RR class for code \c class_code. + std::string codeToClassText(uint16_t class_code) const; + //@} + + /// + /// \name RDATA Factories + /// + /// This set of methods provide a unified interface to create an + /// \c rdata::Rdata object in a parameterized polymorphic way, + /// that is, these methods take a pair of \c RRType and \c RRClass + /// objects and data specific to that pair, and create an object of + /// the corresponding concrete derived class of \c rdata::Rdata. + /// + /// These methods first search the \c RRParamRegistry for a factory + /// method (a member of a concrete derived class of + /// \c AbstractRdataFactory) for the given RR type and class pair. + /// If the search fails, they then search for a factory method for + /// the given type ignoring the class, in case a RRClass independent + /// factory method is registered. + /// If it still fails, these methods assume the RDATA is of an "unknown" + /// type, and creates a new object by calling a constructor of the + /// \c rdata::generic::Generic class. + /// + //@{ + /// \brief Create RDATA of a given pair of RR type and class from a string. + /// + /// This method creates from a string an \c Rdata object of the given pair + /// of RR type and class. + /// + /// \param rrtype An \c RRType object specifying the type/class pair. + /// \param rrclass An \c RRClass object specifying the type/class pair. + /// \param rdata_string A string of textual representation of the \c Rdata. + /// \return An \c rdata::RdataPtr object pointing to the created \c Rdata + /// object. + rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, + const std::string& rdata_string); + /// \brief Create RDATA of a given pair of RR type and class from + /// wire-format data. + /// + /// This method creates from wire-format binary data an \c Rdata object + /// of the given pair of RR type and class. + /// + /// \param rrtype An \c RRType object specifying the type/class pair. + /// \param rrclass An \c RRClass object specifying the type/class pair. + /// \param buffer A reference to an \c InputBuffer object storing the + /// \c Rdata to parse. + /// \param len The length in buffer of the \c Rdata. In bytes. + /// \return An \c rdata::RdataPtr object pointing to the created \c Rdata + /// object. + rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, + isc::util::InputBuffer& buffer, size_t len); + /// \brief Create RDATA of a given pair of RR type and class, copying + /// of another RDATA of same kind. + /// + /// This method creates an \c Rdata object of the given pair of + /// RR type and class, copying the content of the given \c Rdata, + /// \c source. + /// + /// \c source must be an object of the concrete derived class of + /// \c rdata::Rdata for the given pair of RR type and class; + /// otherwise, an exception of class \c std::bad_cast will be thrown. + /// In case the \c RRParamRegistry doesn't have a factory method for + /// the given pair and it is assumed to be of an "unknown" type, + /// \c source must reference an object of class + /// \c rdata::generic::Generic; otherwise, an exception of class + /// \c std::bad_cast will be thrown. + /// + /// \param rrtype An \c RRType object specifying the type/class pair. + /// \param rrclass An \c RRClass object specifying the type/class pair. + /// \param source A reference to an \c rdata::Rdata object whose content + /// is to be copied to the created \c rdata::Rdata object. + /// \return An \c rdata::RdataPtr object pointing to the created + /// \c rdata::Rdata object. + rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, + const rdata::Rdata& source); + + /// \brief Create RDATA using MasterLexer + /// + /// This method is expected to be used as the underlying implementation + /// of the same signature of \c rdata::createRdata(). One main + /// difference is that this method is only responsible for constructing + /// the Rdata; it doesn't update the lexer to reach the end of line or + /// file or doesn't care about whether there's an extra (garbage) token + /// after the textual RDATA representation. Another difference is that + /// this method can throw on error and never returns a NULL pointer. + /// + /// For other details and parameters, see the description of + /// \c rdata::createRdata(). + rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, + MasterLexer& lexer, const Name* origin, + MasterLoader::Options options, + MasterLoaderCallbacks& callbacks); + //@} + +private: + RRParamRegistryImpl* impl_; +}; + +} +} +#endif // RRPARAMREGISTRY_H + +// Local Variables: +// mode: c++ +// End: |