123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- // Copyright (C) 2009 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.
- // $Id$
- #ifndef __MESSAGERENDERER_H
- #define __MESSAGERENDERER_H 1
- namespace isc {
- namespace dns {
- // forward declarations
- class OutputBuffer;
- class Name;
- ///
- /// \brief The \c MessageRenderer class encapsulates implementation details
- /// of rendering a DNS message into a buffer in wire format.
- ///
- /// In effect, it's simply responsible for name compression at least in the
- /// current implementation. A \c MessageRenderer class object manages the
- /// positions of names rendered in a buffer and uses that information to render
- /// subsequent names with compression.
- ///
- /// This class is mainly intended to be used as a helper for a more
- /// comprehensive \c Message class internally; normal applications won't have
- /// to care about this class.
- ///
- /// A \c MessageRenderer class object is constructed with a \c OutputBuffer
- /// object, which is the buffer into which the rendered %data will be written.
- /// Normally the buffer is expected to be empty on construction, but it doesn't
- /// have to be so; the \c MessageRenderer object will start rendering from the
- /// end of the buffer at the time of construction. However, if the
- /// pre-existing portion of the buffer contains DNS names, these names won't
- /// be considered for name compression.
- ///
- /// Once a \c MessageRenderer object is constructed with a buffer, it is
- /// generally expected that all rendering operations are performed via the
- /// \c MessageRenderer object. If the application modifies the buffer in
- /// parallel with the \c MessageRenderer, the result will be undefined.
- ///
- /// Note to developers: we introduced a separate class for name compression
- /// because previous benchmark with BIND9 showed compression affects overall
- /// response performance very much. By having a separate class dedicated for
- /// this purpose, we'll be able to change the internal implementation of name
- /// compression in the future without affecting other part of the API and
- /// implementation. For the same reason, we adopt the "pimpl" idiom in the
- /// class definition (i.e., using a pointer to a \c MessageRendererImpl class,
- /// which is defined with the class implementation, not in the header file):
- /// we may want to modify the compression implementation without modifying the
- /// header file thereby requesting rebuild the package.
- ///
- /// Furthermore, we may eventually want to allow other developers to develop
- /// and use their own compression implementation. Should such a case become
- /// realistic, we may want to make the \c MessageRendererImpl class an abstract
- /// base class and let concrete derived classes have their own implementations.
- /// At the moment we don't the strong need for it, so we rather avoid over
- /// abstraction and keep the definition simpler.
- class MessageRenderer {
- public:
- /// \brief Compression mode constants.
- ///
- /// The \c CompressMode enum type represents the name compression mode
- /// for the \c MessageRenderer.
- /// \c CASE_INSENSITIVE means compress names in case-insensitive manner;
- /// \c CASE_SENSITIVE means compress names in case-sensitive manner.
- /// By default, \c MessageRenderer compresses names in case-insensitive
- /// manner.
- /// Compression mode can be dynamically modified by the
- /// \c setCompressMode() method.
- /// The mode can be changed even in the middle of rendering, although this
- /// is not an intended usage. In this case the names already compressed
- /// are intact; only names being compressed after the mode change are
- /// affected by the change.
- /// If the internal \c MessageRenderer is reinitialized by the \c clear()
- /// method, the compression mode will be reset to the default, which is
- /// \c CASE_INSENSITIVE
- ///
- /// One specific case where case-sensitive compression is required is
- /// AXFR as described in draft-ietf-dnsext-axfr-clarify. A primary
- /// authoritative DNS server implementation using this API would specify
- /// \c CASE_SENSITIVE before rendering outgoing AXFR messages.
- ///
- enum CompressMode {
- CASE_INSENSITIVE, //!< Compress names case-insensitive manner (default)
- CASE_SENSITIVE //!< Compress names case-sensitive manner
- };
- public:
- ///
- /// \name Constructors and Destructor
- //@{
- /// \brief Constructor from an output buffer.
- ///
- /// \param buffer An \c OutputBuffer object to which wire format data is
- /// written.
- MessageRenderer(OutputBuffer& buffer);
- /// \brief The destructor.
- ///
- /// The destructor does nothing on the given \c buffer on construction;
- /// in fact, it is expected that the user will use the resulting buffer
- /// for some post rendering purposes (e.g., send the data to the network).
- /// It's user's responsibility to do any necessary cleanup for the
- /// \c buffer.
- ~MessageRenderer();
- //@}
- ///
- /// \name Getter Methods
- ///
- //@{
- /// \brief Return a pointer to the head of the data stored in the internal
- /// buffer.
- ///
- /// This method works exactly same as the same method of the \c OutputBuffer
- /// class; all notes for \c OutputBuffer apply.
- const void* getData() const;
- /// \brief Return the length of data written in the internal buffer.
- size_t getLength() const;
- /// \brief Return whether truncation has occurred while rendering.
- ///
- /// Once the return value of this method is \c true, it doesn't make sense
- /// to try rendering more data, although this class itself doesn't reject
- /// the attempt.
- ///
- /// This method never throws an exception.
- ///
- /// \return true if truncation has occurred; otherwise \c false.
- bool isTruncated() const;
- /// \brief Return the maximum length of rendered data that can fit in the
- /// corresponding DNS message without truncation.
- ///
- /// This method never throws an exception.
- ///
- /// \return The maximum length in bytes.
- size_t getLengthLimit() const;
- /// \brief Return the compression mode of the \c MessageRenderer.
- ///
- /// This method never throws an exception.
- ///
- /// \return The current compression mode.
- CompressMode getCompressMode() const;
- //@}
- ///
- /// \name Setter Methods
- ///
- //@{
- /// \brief Mark the renderer to indicate truncation has occurred while
- /// rendering.
- ///
- /// This method never throws an exception.
- void setTruncated();
- /// \brief Set the maximum length of rendered data that can fit in the
- /// corresponding DNS message without truncation.
- ///
- /// This method never throws an exception.
- ///
- /// \param len The maximum length in bytes.
- void setLengthLimit(size_t len);
- /// \brief Set the compression mode of the \c MessageRenderer.
- ///
- /// This method never throws an exception.
- ///
- /// \param mode A \c CompressMode value representing the compression mode.
- void setCompressMode(CompressMode mode);
- //@}
- ///
- /// \name Methods for writing data into the internal buffer.
- ///
- //@{
- /// \brief Insert a specified length of gap at the end of the buffer.
- ///
- /// The caller should not assume any particular value to be inserted.
- /// This method is provided as a shortcut to make a hole in the buffer
- /// that is to be filled in later, e.g, by \ref writeUint16At().
- ///
- /// \param len The length of the gap to be inserted in bytes.
- void skip(size_t len);
- /// \brief Trim the specified length of data from the end of the internal
- /// buffer.
- ///
- /// This method is provided for such cases as DNS message truncation.
- ///
- /// The specified length must not exceed the current data size of the
- /// buffer; otherwise an exception of class \c isc::OutOfRange will
- /// be thrown.
- ///
- /// \param len The length of data that should be trimmed.
- void trim(size_t len);
- /// \brief Clear the internal buffer and other internal resources.
- ///
- /// This method can be used to re-initialize and reuse the renderer
- /// without constructing a new one.
- void clear();
- /// \brief Write an unsigned 8-bit integer into the internal buffer.
- ///
- /// \param data The 8-bit integer to be written into the internal buffer.
- void writeUint8(uint8_t data);
- /// \brief Write an unsigned 16-bit integer in host byte order into the
- /// internal buffer in network byte order.
- ///
- /// \param data The 16-bit integer to be written into the buffer.
- void writeUint16(uint16_t data);
- /// \brief Write an unsigned 16-bit integer in host byte order at the
- /// specified position of the internal buffer in network byte order.
- ///
- /// The buffer must have a sufficient room to store the given data at the
- /// given position, that is, <code>pos + 2 < getLength()</code>;
- /// otherwise an exception of class \c isc::dns::InvalidBufferPosition will
- /// be thrown.
- /// Note also that this method never extends the internal buffer.
- ///
- /// \param data The 16-bit integer to be written into the internal buffer.
- /// \param pos The beginning position in the buffer to write the data.
- void writeUint16At(uint16_t data, size_t pos);
- /// \brief Write an unsigned 32-bit integer in host byte order into the
- /// internal buffer in network byte order.
- ///
- /// \param data The 32-bit integer to be written into the buffer.
- void writeUint32(uint32_t data);
- /// \brief Copy an arbitrary length of data into the internal buffer
- /// of the \c MessageRenderer.
- ///
- /// No conversion on the copied data is performed.
- ///
- /// \param data A pointer to the data to be copied into the internal buffer.
- /// \param len The length of the data in bytes.
- void writeData(const void *data, size_t len);
- //@}
- ///
- /// \name Rendering Methods
- ///
- //@{
- /// \brief Write a \c Name object into the internal buffer in wire format,
- /// with or without name compression.
- ///
- /// If the optional parameter \c compress is \c true, this method tries to
- /// compress the \c name if possible, searching the entire message that has
- /// been rendered. Otherwise name compression is omitted. Its default
- /// value is \c true.
- ///
- /// Note: even if \c compress is \c true, the position of the \c name (and
- /// possibly its ancestor names) in the message is recorded and may be used
- /// for compressing subsequent names.
- ///
- /// \param name A \c Name object to be written.
- /// \param compress A boolean indicating whether to enable name compression.
- void writeName(const Name& name, bool compress = true);
- private:
- struct MessageRendererImpl;
- MessageRendererImpl* impl_;
- };
- }
- }
- #endif // __MESSAGERENDERER_H
- // Local Variables:
- // mode: c++
- // End:
|