messagerenderer.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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. #ifndef __MESSAGERENDERER_H
  15. #define __MESSAGERENDERER_H 1
  16. #include <util/buffer.h>
  17. namespace isc {
  18. namespace dns {
  19. // forward declarations
  20. class Name;
  21. /// \brief The \c AbstractMessageRenderer class is an abstract base class
  22. /// that provides common interfaces for rendering a DNS message into a buffer
  23. /// in wire format.
  24. ///
  25. /// A specific derived class of \c AbstractMessageRenderer (we call it
  26. /// a renderer class hereafter) is simply responsible for name compression at
  27. /// least in the current design. A renderer class object (conceptually)
  28. /// manages the positions of names rendered in some sort of buffer and uses
  29. /// that information to render subsequent names with compression.
  30. ///
  31. /// A renderer 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 details of this class.
  34. ///
  35. /// By default any (derived) renderer class object is associated with
  36. /// an internal buffer, and subsequent write operations will be performed
  37. /// on that buffer. The rendering result can be retrieved via the
  38. /// \c getData() method.
  39. ///
  40. /// If an application wants a separate buffer can be (normally temporarily)
  41. /// set for rendering operations via the \c setBuffer() method. In that case,
  42. /// it is generally expected that all rendering operations are performed via
  43. /// that object. If the application modifies the buffer in
  44. /// parallel with the renderer, the result will be undefined.
  45. ///
  46. /// Note to developers: we introduced a separate class for name compression
  47. /// because previous benchmark with BIND9 showed compression affects overall
  48. /// response performance very much. By having a separate class dedicated for
  49. /// this purpose, we'll be able to change the internal implementation of name
  50. /// compression in the future without affecting other part of the API and
  51. /// implementation.
  52. ///
  53. /// In addition, by introducing a class hierarchy from
  54. /// \c AbstractMessageRenderer, we allow an application to use a customized
  55. /// renderer class for specific purposes. For example, a high performance
  56. /// DNS server may want to use an optimized renderer class assuming some
  57. /// specific underlying data representation.
  58. ///
  59. /// \note Some functions (like writeUint8) are not virtual. It is because
  60. /// it is hard to imagine any version of message renderer that would
  61. /// do anything else than just putting the data into a buffer, so we
  62. /// provide a default implementation and having them virtual would only
  63. /// hurt the performance with no real gain. If it would happen a different
  64. /// implementation is really needed, we can make them virtual in future.
  65. /// The only one that is virtual is writeName and it's because this
  66. /// function is much more complicated, therefore there's a lot of space
  67. /// for different implementations or behaviours.
  68. class AbstractMessageRenderer {
  69. public:
  70. /// \brief Compression mode constants.
  71. ///
  72. /// The \c CompressMode enum type represents the name compression mode
  73. /// for renderer classes.
  74. /// \c CASE_INSENSITIVE means compress names in case-insensitive manner;
  75. /// \c CASE_SENSITIVE means compress names in case-sensitive manner.
  76. /// By default, a renderer compresses names in case-insensitive
  77. /// manner.
  78. /// Compression mode can be dynamically modified by the
  79. /// \c setCompressMode() method.
  80. /// The mode can be changed even in the middle of rendering, although this
  81. /// is not an intended usage. In this case the names already compressed
  82. /// are intact; only names being compressed after the mode change are
  83. /// affected by the change.
  84. /// If a renderer class object is reinitialized by the \c clear()
  85. /// method, the compression mode will be reset to the default, which is
  86. /// \c CASE_INSENSITIVE
  87. ///
  88. /// One specific case where case-sensitive compression is required is
  89. /// AXFR as described in draft-ietf-dnsext-axfr-clarify. A primary
  90. /// authoritative DNS server implementation using this API would specify
  91. /// \c CASE_SENSITIVE before rendering outgoing AXFR messages.
  92. ///
  93. enum CompressMode {
  94. CASE_INSENSITIVE, //!< Compress names case-insensitive manner (default)
  95. CASE_SENSITIVE //!< Compress names case-sensitive manner
  96. };
  97. protected:
  98. ///
  99. /// \name Constructors and Destructor
  100. //@{
  101. /// \brief The default constructor.
  102. ///
  103. /// This is intentionally defined as \c protected as this base class should
  104. /// never be instantiated (except as part of a derived class).
  105. AbstractMessageRenderer();
  106. public:
  107. /// \brief The destructor.
  108. virtual ~AbstractMessageRenderer() {}
  109. //@}
  110. protected:
  111. /// \brief Return the output buffer we render into.
  112. const isc::util::OutputBuffer& getBuffer() const { return (*buffer_); }
  113. isc::util::OutputBuffer& getBuffer() { return (*buffer_); }
  114. private:
  115. /// \brief Local (default) buffer to store data.
  116. isc::util::OutputBuffer local_buffer_;
  117. /// \brief Buffer to store data.
  118. ///
  119. /// Note that the class interface ensures this pointer is never NULL;
  120. /// it either refers to \c local_buffer_ or to an application-supplied
  121. /// buffer by \c setBuffer().
  122. ///
  123. /// It was decided that there's no need to have this in every subclass,
  124. /// at least not now, and this reduces code size and gives compiler a
  125. /// better chance to optimise.
  126. isc::util::OutputBuffer* buffer_;
  127. public:
  128. ///
  129. /// \name Getter Methods
  130. ///
  131. //@{
  132. /// \brief Return a pointer to the head of the data stored in the internal
  133. /// buffer.
  134. ///
  135. /// This method works exactly same as the same method of the \c OutputBuffer
  136. /// class; all notes for \c OutputBuffer apply.
  137. const void* getData() const {
  138. return (buffer_->getData());
  139. }
  140. /// \brief Return the length of data written in the internal buffer.
  141. size_t getLength() const {
  142. return (buffer_->getLength());
  143. }
  144. /// \brief Return whether truncation has occurred while rendering.
  145. ///
  146. /// Once the return value of this method is \c true, it doesn't make sense
  147. /// to try rendering more data, although this class itself doesn't reject
  148. /// the attempt.
  149. ///
  150. /// This method never throws an exception.
  151. ///
  152. /// \return true if truncation has occurred; otherwise \c false.
  153. virtual bool isTruncated() const = 0;
  154. /// \brief Return the maximum length of rendered data that can fit in the
  155. /// corresponding DNS message without truncation.
  156. ///
  157. /// This method never throws an exception.
  158. ///
  159. /// \return The maximum length in bytes.
  160. virtual size_t getLengthLimit() const = 0;
  161. /// \brief Return the compression mode of the renderer class object.
  162. ///
  163. /// This method never throws an exception.
  164. ///
  165. /// \return The current compression mode.
  166. virtual CompressMode getCompressMode() const = 0;
  167. //@}
  168. ///
  169. /// \name Setter Methods
  170. ///
  171. //@{
  172. /// \brief Set or reset a temporary output buffer.
  173. ///
  174. /// This method can be used for an application that manages an output
  175. /// buffer separately from the message renderer and wants to keep reusing
  176. /// the renderer. When the renderer is associated with the default buffer
  177. /// and the given pointer is non NULL, the given buffer will be
  178. /// (temporarily) used for subsequent message rendering; if the renderer
  179. /// is associated with a temporary buffer and the given pointer is NULL,
  180. /// the renderer will be reset with the default buffer. In the latter
  181. /// case any additional resources (possibly specific to a derived renderer
  182. /// class) will be cleared, but the temporary buffer is kept as the latest
  183. /// state (which would normally store the rendering result).
  184. ///
  185. /// This method imposes some restrictions to prevent accidental misuse
  186. /// that could cause disruption such as dereferencing an invalid object.
  187. /// First, a temporary buffer must not be set when the associated buffer
  188. /// is in use, that is, any data are stored in the buffer. Also, the
  189. /// default buffer cannot be "reset"; when NULL is specified a temporary
  190. /// buffer must have been set beforehand. If these conditions aren't met
  191. /// an isc::InvalidParameter exception will be thrown. This method is
  192. /// exception free otherwise.
  193. ///
  194. /// \throw isc::InvalidParameter A restrictions of the method usage isn't
  195. /// met.
  196. ///
  197. /// \param buffer A pointer to a temporary output buffer or NULL for reset
  198. /// it.
  199. void setBuffer(isc::util::OutputBuffer* buffer);
  200. /// \brief Mark the renderer to indicate truncation has occurred while
  201. /// rendering.
  202. ///
  203. /// This method never throws an exception.
  204. virtual void setTruncated() = 0;
  205. /// \brief Set the maximum length of rendered data that can fit in the
  206. /// corresponding DNS message without truncation.
  207. ///
  208. /// This method never throws an exception.
  209. ///
  210. /// \param len The maximum length in bytes.
  211. virtual void setLengthLimit(size_t len) = 0;
  212. /// \brief Set the compression mode of the renderer class object.
  213. ///
  214. /// This method never throws an exception.
  215. ///
  216. /// \param mode A \c CompressMode value representing the compression mode.
  217. virtual void setCompressMode(CompressMode mode) = 0;
  218. //@}
  219. ///
  220. /// \name Methods for writing data into the internal buffer.
  221. ///
  222. //@{
  223. /// \brief Insert a specified length of gap at the end of the buffer.
  224. ///
  225. /// The caller should not assume any particular value to be inserted.
  226. /// This method is provided as a shortcut to make a hole in the buffer
  227. /// that is to be filled in later, e.g, by \ref writeUint16At().
  228. ///
  229. /// \param len The length of the gap to be inserted in bytes.
  230. void skip(size_t len) {
  231. buffer_->skip(len);
  232. }
  233. /// \brief Trim the specified length of data from the end of the internal
  234. /// buffer.
  235. ///
  236. /// This method is provided for such cases as DNS message truncation.
  237. ///
  238. /// The specified length must not exceed the current data size of the
  239. /// buffer; otherwise an exception of class \c isc::OutOfRange will
  240. /// be thrown.
  241. ///
  242. /// \param len The length of data that should be trimmed.
  243. void trim(size_t len) {
  244. buffer_->trim(len);
  245. }
  246. /// \brief Clear the internal buffer and other internal resources.
  247. ///
  248. /// This method can be used to re-initialize and reuse the renderer
  249. /// without constructing a new one.
  250. virtual void clear();
  251. /// \brief Write an unsigned 8-bit integer into the internal buffer.
  252. ///
  253. /// \param data The 8-bit integer to be written into the internal buffer.
  254. void writeUint8(const uint8_t data) {
  255. buffer_->writeUint8(data);
  256. }
  257. /// \brief Write an unsigned 16-bit integer in host byte order into the
  258. /// internal buffer in network byte order.
  259. ///
  260. /// \param data The 16-bit integer to be written into the buffer.
  261. void writeUint16(uint16_t data) {
  262. buffer_->writeUint16(data);
  263. }
  264. /// \brief Write an unsigned 16-bit integer in host byte order at the
  265. /// specified position of the internal buffer in network byte order.
  266. ///
  267. /// The buffer must have a sufficient room to store the given data at the
  268. /// given position, that is, <code>pos + 2 < getLength()</code>;
  269. /// otherwise an exception of class \c isc::dns::InvalidBufferPosition will
  270. /// be thrown.
  271. /// Note also that this method never extends the internal buffer.
  272. ///
  273. /// \param data The 16-bit integer to be written into the internal buffer.
  274. /// \param pos The beginning position in the buffer to write the data.
  275. void writeUint16At(uint16_t data, size_t pos) {
  276. buffer_->writeUint16At(data, pos);
  277. }
  278. /// \brief Write an unsigned 32-bit integer in host byte order into the
  279. /// internal buffer in network byte order.
  280. ///
  281. /// \param data The 32-bit integer to be written into the buffer.
  282. void writeUint32(uint32_t data) {
  283. buffer_->writeUint32(data);
  284. }
  285. /// \brief Copy an arbitrary length of data into the internal buffer
  286. /// of the renderer object.
  287. ///
  288. /// No conversion on the copied data is performed.
  289. ///
  290. /// \param data A pointer to the data to be copied into the internal buffer.
  291. /// \param len The length of the data in bytes.
  292. void writeData(const void *data, size_t len) {
  293. buffer_->writeData(data, len);
  294. }
  295. /// \brief Write a \c Name object into the internal buffer in wire format,
  296. /// with or without name compression.
  297. ///
  298. /// If the optional parameter \c compress is \c true, this method tries to
  299. /// compress the \c name if possible, searching the entire message that has
  300. /// been rendered. Otherwise name compression is omitted. Its default
  301. /// value is \c true.
  302. ///
  303. /// Note: even if \c compress is \c true, the position of the \c name (and
  304. /// possibly its ancestor names) in the message is recorded and may be used
  305. /// for compressing subsequent names.
  306. ///
  307. /// \param name A \c Name object to be written.
  308. /// \param compress A boolean indicating whether to enable name compression.
  309. virtual void writeName(const Name& name, bool compress = true) = 0;
  310. //@}
  311. };
  312. /// The \c MessageRenderer is a concrete derived class of
  313. /// \c AbstractMessageRenderer as a general purpose implementation of the
  314. /// renderer interfaces.
  315. ///
  316. /// A \c MessageRenderer object is constructed with a \c OutputBuffer
  317. /// object, which is the buffer into which the rendered %data will be written.
  318. /// Normally the buffer is expected to be empty on construction, but it doesn't
  319. /// have to be so; the renderer object will start rendering from the
  320. /// end of the buffer at the time of construction. However, if the
  321. /// pre-existing portion of the buffer contains DNS names, these names won't
  322. /// be considered for name compression.
  323. class MessageRenderer : public AbstractMessageRenderer {
  324. public:
  325. using AbstractMessageRenderer::CASE_INSENSITIVE;
  326. using AbstractMessageRenderer::CASE_SENSITIVE;
  327. /// \brief Constructor from an output buffer.
  328. MessageRenderer();
  329. virtual ~MessageRenderer();
  330. virtual bool isTruncated() const;
  331. virtual size_t getLengthLimit() const;
  332. virtual CompressMode getCompressMode() const;
  333. virtual void setTruncated();
  334. virtual void setLengthLimit(size_t len);
  335. /// This implementation does not allow this call in the middle of
  336. /// rendering (i.e. after at least one name is rendered) due to
  337. /// restriction specific to the internal implementation. Such attempts
  338. /// will result in an \c isc::InvalidParameter exception.
  339. ///
  340. /// This shouldn't be too restrictive in practice; there's no known
  341. /// practical case for such a mixed compression policy in a single
  342. /// message.
  343. virtual void setCompressMode(CompressMode mode);
  344. virtual void clear();
  345. virtual void writeName(const Name& name, bool compress = true);
  346. private:
  347. struct MessageRendererImpl;
  348. MessageRendererImpl* impl_;
  349. };
  350. }
  351. }
  352. #endif // __MESSAGERENDERER_H
  353. // Local Variables:
  354. // mode: c++
  355. // End: