messagerenderer.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // $Id$
  15. #ifndef __MESSAGERENDERER_H
  16. #define __MESSAGERENDERER_H 1
  17. namespace isc {
  18. namespace dns {
  19. // forward declarations
  20. class OutputBuffer;
  21. class Name;
  22. ///
  23. /// \brief The \c MessageRenderer class encapsulates implementation details
  24. /// of rendering a DNS message into a buffer in wire format.
  25. ///
  26. /// In effect, it's simply responsible for name compression at least in the
  27. /// current implementation. A \c MessageRenderer class object manages the
  28. /// positions of names rendered in a buffer and uses that information to render
  29. /// subsequent names with compression.
  30. ///
  31. /// This class is mainly intended to be used as a helper for a more
  32. /// comprehensive \c Message class internally; normal applications won't have
  33. /// to care about this class.
  34. ///
  35. /// A \c MessageRenderer class object is constructed with a \c OutputBuffer
  36. /// object, which is the buffer into which the rendered %data will be written.
  37. /// Normally the buffer is expected to be empty on construction, but it doesn't
  38. /// have to be so; the \c MessageRenderer object will start rendering from the
  39. /// end of the buffer at the time of construction. However, if the
  40. /// pre-existing portion of the buffer contains DNS names, these names won't
  41. /// be considered for name compression.
  42. ///
  43. /// Once a \c MessageRenderer object is constructed with a buffer, it is
  44. /// generally expected that all rendering operations are performed via the
  45. /// \c MessageRenderer object. If the application modifies the buffer in
  46. /// parallel with the \c MessageRenderer, the result will be undefined.
  47. ///
  48. /// Note to developers: we introduced a separate class for name compression
  49. /// because previous benchmark with BIND9 showed compression affects overall
  50. /// response performance very much. By having a separate class dedicated for
  51. /// this purpose, we'll be able to change the internal implementation of name
  52. /// compression in the future without affecting other part of the API and
  53. /// implementation. For the same reason, we adopt the "pimpl" idiom in the
  54. /// class definition (i.e., using a pointer to a \c MessageRendererImpl class,
  55. /// which is defined with the class implementation, not in the header file):
  56. /// we may want to modify the compression implementation without modifying the
  57. /// header file thereby requesting rebuild the package.
  58. ///
  59. /// Furthermore, we may eventually want to allow other developers to develop
  60. /// and use their own compression implementation. Should such a case become
  61. /// realistic, we may want to make the \c MessageRendererImpl class an abstract
  62. /// base class and let concrete derived classes have their own implementations.
  63. /// At the moment we don't the strong need for it, so we rather avoid over
  64. /// abstraction and keep the definition simpler.
  65. class MessageRenderer {
  66. public:
  67. /// \brief Compression mode constants.
  68. ///
  69. /// The \c CompressMode enum type represents the name compression mode
  70. /// for the \c MessageRenderer.
  71. /// \c CASE_INSENSITIVE means compress names in case-insensitive manner;
  72. /// \c CASE_SENSITIVE means compress names in case-sensitive manner.
  73. /// By default, \c MessageRenderer compresses names in case-insensitive
  74. /// manner.
  75. /// Compression mode can be dynamically modified by the
  76. /// \c setCompressMode() method.
  77. /// The mode can be changed even in the middle of rendering, although this
  78. /// is not an intended usage. In this case the names already compressed
  79. /// are intact; only names being compressed after the mode change are
  80. /// affected by the change.
  81. /// If the internal \c MessageRenderer is reinitialized by the \c clear()
  82. /// method, the compression mode will be reset to the default, which is
  83. /// \c CASE_INSENSITIVE
  84. ///
  85. /// One specific case where case-sensitive compression is required is
  86. /// AXFR as described in draft-ietf-dnsext-axfr-clarify. A primary
  87. /// authoritative DNS server implementation using this API would specify
  88. /// \c CASE_SENSITIVE before rendering outgoing AXFR messages.
  89. ///
  90. enum CompressMode {
  91. CASE_INSENSITIVE, //!< Compress names case-insensitive manner (default)
  92. CASE_SENSITIVE //!< Compress names case-sensitive manner
  93. };
  94. public:
  95. ///
  96. /// \name Constructors and Destructor
  97. //@{
  98. /// \brief Constructor from an output buffer.
  99. ///
  100. /// \param buffer An \c OutputBuffer object to which wire format data is
  101. /// written.
  102. MessageRenderer(OutputBuffer& buffer);
  103. /// \brief The destructor.
  104. ///
  105. /// The destructor does nothing on the given \c buffer on construction;
  106. /// in fact, it is expected that the user will use the resulting buffer
  107. /// for some post rendering purposes (e.g., send the data to the network).
  108. /// It's user's responsibility to do any necessary cleanup for the
  109. /// \c buffer.
  110. ~MessageRenderer();
  111. //@}
  112. ///
  113. /// \name Getter Methods
  114. ///
  115. //@{
  116. /// \brief Return a pointer to the head of the data stored in the internal
  117. /// buffer.
  118. ///
  119. /// This method works exactly same as the same method of the \c OutputBuffer
  120. /// class; all notes for \c OutputBuffer apply.
  121. const void* getData() const;
  122. /// \brief Return the length of data written in the internal buffer.
  123. size_t getLength() const;
  124. /// \brief Return whether truncation has occurred while rendering.
  125. ///
  126. /// Once the return value of this method is \c true, it doesn't make sense
  127. /// to try rendering more data, although this class itself doesn't reject
  128. /// the attempt.
  129. ///
  130. /// This method never throws an exception.
  131. ///
  132. /// \return true if truncation has occurred; otherwise \c false.
  133. bool isTruncated() const;
  134. /// \brief Return the maximum length of rendered data that can fit in the
  135. /// corresponding DNS message without truncation.
  136. ///
  137. /// This method never throws an exception.
  138. ///
  139. /// \return The maximum length in bytes.
  140. size_t getLengthLimit() const;
  141. /// \brief Return the compression mode of the \c MessageRenderer.
  142. ///
  143. /// This method never throws an exception.
  144. ///
  145. /// \return The current compression mode.
  146. CompressMode getCompressMode() const;
  147. //@}
  148. ///
  149. /// \name Setter Methods
  150. ///
  151. //@{
  152. /// \brief Mark the renderer to indicate truncation has occurred while
  153. /// rendering.
  154. ///
  155. /// This method never throws an exception.
  156. void setTruncated();
  157. /// \brief Set the maximum length of rendered data that can fit in the
  158. /// corresponding DNS message without truncation.
  159. ///
  160. /// This method never throws an exception.
  161. ///
  162. /// \param len The maximum length in bytes.
  163. void setLengthLimit(size_t len);
  164. /// \brief Set the compression mode of the \c MessageRenderer.
  165. ///
  166. /// This method never throws an exception.
  167. ///
  168. /// \param mode A \c CompressMode value representing the compression mode.
  169. void setCompressMode(CompressMode mode);
  170. //@}
  171. ///
  172. /// \name Methods for writing data into the internal buffer.
  173. ///
  174. //@{
  175. /// \brief Insert a specified length of gap at the end of the buffer.
  176. ///
  177. /// The caller should not assume any particular value to be inserted.
  178. /// This method is provided as a shortcut to make a hole in the buffer
  179. /// that is to be filled in later, e.g, by \ref writeUint16At().
  180. ///
  181. /// \param len The length of the gap to be inserted in bytes.
  182. void skip(size_t len);
  183. /// \brief Trim the specified length of data from the end of the internal
  184. /// buffer.
  185. ///
  186. /// This method is provided for such cases as DNS message truncation.
  187. ///
  188. /// The specified length must not exceed the current data size of the
  189. /// buffer; otherwise an exception of class \c isc::OutOfRange will
  190. /// be thrown.
  191. ///
  192. /// \param len The length of data that should be trimmed.
  193. void trim(size_t len);
  194. /// \brief Clear the internal buffer and other internal resources.
  195. ///
  196. /// This method can be used to re-initialize and reuse the renderer
  197. /// without constructing a new one.
  198. void clear();
  199. /// \brief Write an unsigned 8-bit integer into the internal buffer.
  200. ///
  201. /// \param data The 8-bit integer to be written into the internal buffer.
  202. void writeUint8(uint8_t data);
  203. /// \brief Write an unsigned 16-bit integer in host byte order into the
  204. /// internal buffer in network byte order.
  205. ///
  206. /// \param data The 16-bit integer to be written into the buffer.
  207. void writeUint16(uint16_t data);
  208. /// \brief Write an unsigned 16-bit integer in host byte order at the
  209. /// specified position of the internal buffer in network byte order.
  210. ///
  211. /// The buffer must have a sufficient room to store the given data at the
  212. /// given position, that is, <code>pos + 2 < getLength()</code>;
  213. /// otherwise an exception of class \c isc::dns::InvalidBufferPosition will
  214. /// be thrown.
  215. /// Note also that this method never extends the internal buffer.
  216. ///
  217. /// \param data The 16-bit integer to be written into the internal buffer.
  218. /// \param pos The beginning position in the buffer to write the data.
  219. void writeUint16At(uint16_t data, size_t pos);
  220. /// \brief Write an unsigned 32-bit integer in host byte order into the
  221. /// internal buffer in network byte order.
  222. ///
  223. /// \param data The 32-bit integer to be written into the buffer.
  224. void writeUint32(uint32_t data);
  225. /// \brief Copy an arbitrary length of data into the internal buffer
  226. /// of the \c MessageRenderer.
  227. ///
  228. /// No conversion on the copied data is performed.
  229. ///
  230. /// \param data A pointer to the data to be copied into the internal buffer.
  231. /// \param len The length of the data in bytes.
  232. void writeData(const void *data, size_t len);
  233. //@}
  234. ///
  235. /// \name Rendering Methods
  236. ///
  237. //@{
  238. /// \brief Write a \c Name object into the internal buffer in wire format,
  239. /// with or without name compression.
  240. ///
  241. /// If the optional parameter \c compress is \c true, this method tries to
  242. /// compress the \c name if possible, searching the entire message that has
  243. /// been rendered. Otherwise name compression is omitted. Its default
  244. /// value is \c true.
  245. ///
  246. /// Note: even if \c compress is \c true, the position of the \c name (and
  247. /// possibly its ancestor names) in the message is recorded and may be used
  248. /// for compressing subsequent names.
  249. ///
  250. /// \param name A \c Name object to be written.
  251. /// \param compress A boolean indicating whether to enable name compression.
  252. void writeName(const Name& name, bool compress = true);
  253. private:
  254. struct MessageRendererImpl;
  255. MessageRendererImpl* impl_;
  256. };
  257. }
  258. }
  259. #endif // __MESSAGERENDERER_H
  260. // Local Variables:
  261. // mode: c++
  262. // End: