rdatafields.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // Copyright (C) 2010 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 RDATAFIELDS_H
  15. #define RDATAFIELDS_H 1
  16. #include <stdint.h>
  17. #include <cstddef>
  18. namespace isc {
  19. namespace util {
  20. class OutputBuffer;
  21. }
  22. namespace dns {
  23. class AbstractMessageRenderer;
  24. namespace rdata {
  25. class Rdata;
  26. /// A low-level, RR type-independent representation of DNS RDATA.
  27. ///
  28. /// <b>Purpose of the Class</b>
  29. ///
  30. /// This class intends to help "serialization" of the content of RDATA
  31. /// in a space-efficient manner. Specific derived classes of \c Rdata
  32. /// focus on the convenience of accessing RDATA fields for RR type-specific
  33. /// protocol operations, and can be inefficient in terms of space.
  34. /// For example, a DNS character string may be internally represented as a
  35. /// \c std::string object with all of the overhead of the richer class.
  36. /// If an application needs to maintain a very large number of RRs and it
  37. /// does not have to perform RR specific operation so often, it may make more
  38. /// sense to store the data in memory in a lower-level but space efficient
  39. /// form.
  40. ///
  41. /// Another purpose of this class is to improve rendering performance for
  42. /// RDATA. If the only requirement were space efficiency, it would be just
  43. /// sufficient to convert the \c RDATA into a binary sequence in the wire
  44. /// format. However, to render the data in a DNS message, we'd have to
  45. /// re-construct a corresponding \c Rdata object in the case where name
  46. /// compression is necessary. This is not desirable, and this class is
  47. /// provided to avoid such unnecessary overhead.
  48. ///
  49. /// <b>Data Format</b>
  50. ///
  51. /// To meet these goals, this class helps convert an \c Rdata object into
  52. /// two pieces of information: Wire-format representation of the \c Rdata
  53. /// and associated meta information for efficient rendering.
  54. ///
  55. /// Specifically, it maintains the wire-format data as a sequence of typed
  56. /// fields. The types are:
  57. /// - Compressible name: a domain name as an RDATA field that can be compressed
  58. /// - Incompressible name: a domain name as an RDATA field that cannot be
  59. /// compressed
  60. /// - Other data: any other fields of RDATA, which should be treated as opaque
  61. ///
  62. /// (See also the description of \c RdataFields::Type)
  63. /// Whether a name can or cannot be compressed is determined according to
  64. /// RFC3597.
  65. ///
  66. /// A "other data" field may not always correspond to a single RDATA field.
  67. /// A \c RdataFields field (of other data) is just a contiguous region of the
  68. /// wire-format data that does not involve name compression.
  69. /// For example, the SOA RDATA begins with two "compressible" names followed
  70. /// by 5 32-bit fields.
  71. /// In \c RdataFields the last 5 fields would be considered a single 20-byte
  72. /// field.
  73. ///
  74. /// Each \c RdataFields field is identified by the \c FieldSpec structure,
  75. /// which provides the type and length of the field.
  76. /// An \c RdataFields object internally maintains a sequence of \c FieldSpec
  77. /// objects in a form of plain C-style array, which can be referenced via
  78. /// a pointer returned by the \c getFieldSpecData() method.
  79. /// The \c \c FieldSpec for a specific field can also be retrieved by the
  80. /// \c getFieldSpec() method.
  81. ///
  82. /// The following diagram shows the internal memory representation of
  83. /// an SOA RDATA in the form of \c RdataFields object and how an application
  84. /// can get access to the memory region.
  85. /** \verbatim
  86. accessible via |0 getDataLength() bytes
  87. getData()----------> <MNAME><RNAME><Rest of the data>
  88. <---------- 3 * sizeof(FieldSpec) bytes ------------->
  89. getFieldSpecData()-> { compressible name { compressible name { other data
  90. len: MNAME-len } len: RNAME-len } len: 20 }
  91. \endverbatim
  92. */
  93. /// where MNAME and RNAME are wire format representations of the MNAME and
  94. /// RNAME fields of the SOA RDATA, respectively, and "Rest of the data"
  95. /// encodes the remaining 20 bytes of the RDATA in network byte order.
  96. ///
  97. /// <b>Usage of the Class</b>
  98. ///
  99. /// One major and common use case of the \c RdataFields class is to convert
  100. /// a \c Rdata object (possibly given from a DNS message or some configuration
  101. /// source such as a zone file) in the serialized format and store a copy of
  102. /// the data somewhere in memory. The following code sample implements this
  103. /// scenario:
  104. /// \code // assume "rdata" is a reference type to Rdata
  105. /// const RdataFields fields(rdata);
  106. /// const unsigned int fields_size = fields.getFieldDataSize();
  107. /// memcpy(some_place, fields.getFieldSpecData(), fields_size);
  108. /// const size_t data_length = fields.getDataLength();
  109. /// memcpy(other_place, fields.getData(), data_length);
  110. /// // (fields_size and data_length should be stored somewhere, too)
  111. /// \endcode
  112. ///
  113. /// Another typical usage is to render the stored data in the wire format
  114. /// as efficiently as possible. The following code is an example of such
  115. /// usage:
  116. /// \code // assume "renderer" is of type MessageRenderer
  117. /// // retrieve data_length and fields_size from the storage
  118. /// RdataFields(some_place, fields_size, other_place,
  119. /// data_length).toWire(renderer);
  120. /// \endcode
  121. ///
  122. /// <b>Notes to Users</b>
  123. ///
  124. /// The main purposes of this class is to help efficient operation
  125. /// for some (limited classes of) performance sensitive application.
  126. /// For this reason the interface and implementation rely on relatively
  127. /// lower-level, riskier primitives such as passing around bare pointers.
  128. ///
  129. /// It is therefore discouraged to use this class for general purpose
  130. /// applications that do not need to maximize performance in terms of either
  131. /// memory footprint or rendering speed.
  132. /// All functionality provided by this class can be achieved via higher level
  133. /// interfaces such as the \c Rdata class variants.
  134. /// Normal applications should use those interfaces.
  135. ///
  136. /// The data format is public information so that an application can examine
  137. /// and use selected parts of data. For example, an application may want to
  138. /// encode domain names in RDATA in a different way while storing the other
  139. /// data in a separate place.
  140. /// However, at this moment the format is still in flux, and it may not
  141. /// be compatible with future versions (see below).
  142. ///
  143. /// <b>Development Notes</b>
  144. ///
  145. /// We should conduct benchmark tests to measure rendering performance.
  146. ///
  147. /// The current implementation needs to re-construct name objects from
  148. /// compressible and incompressible name fields as wire-format data.
  149. /// This is not efficient, and we'll probably want to improve this in a
  150. /// future version. One possibility is to store offset information as well
  151. /// as the name data (at the cost of increasing memory footprint), and
  152. /// to use the pair of data for faster rendering.
  153. class RdataFields {
  154. public:
  155. /// Types of \c RdataFields fields.
  156. ///
  157. /// \c COMPRESSIBLE_NAME and \c INCOMPRESSIBLE_NAME represent a domain
  158. /// name used as a field of an RDATA that can and cannot be compressed
  159. /// per RFC3597.
  160. /// \c DATA means all other types of fields.
  161. enum Type {
  162. DATA, ///< Plain data.
  163. COMPRESSIBLE_NAME, ///< A domain name subject to name compression.
  164. INCOMPRESSIBLE_NAME ///< A domain name that shouldn't be compressed.
  165. };
  166. /// Structure that specifies a single \c RdataFields field.
  167. ///
  168. /// This is a straightforward pair of the type and length of a single
  169. /// \c RdataFields field.
  170. ///
  171. /// In some cases an application may want to do deeper inspection of
  172. /// some \c RdataFields field(s). For example, an application may want
  173. /// to construct a \c Name object for each domain name field of an RDATA
  174. /// and use it for some special purpose.
  175. /// The \c FieldSpec structure provides necessary parameters to get access
  176. /// to a specific \c RdataFields field.
  177. ///
  178. /// The following code snippet implements the above example scenario:
  179. /// \code // assume "fields" is of type RdataFields
  180. /// size_t offset = 0;
  181. /// for (int i = 0; i < fields.getFieldCount(); ++i) {
  182. /// const FieldSpec spec = fields.getFieldSpec(i);
  183. /// if (spec.type == RdataFields::COMPRESSIBLE_NAME ||
  184. /// spec.type == RdataFields::INCOMPRESSIBLE_NAME) {
  185. /// InputBuffer ibuffer(fields.getData() + offset, spec.len);
  186. /// Name name(ibuffer);
  187. /// // do something with name
  188. /// }
  189. /// offset += spec.len;
  190. /// } \endcode
  191. ///
  192. /// Note that the offset is not included in \c FieldSpec.
  193. /// This is because such deeper inspection would be a relatively rare
  194. /// operation while it is desirable to keep this structure as small as
  195. /// possible for the purpose of space efficiency.
  196. /// Also, if and when an application wants to look into a specific field,
  197. /// it would be quite likely that the application iterates over all fields
  198. /// and does something special for selected fields like the above example.
  199. /// In that case the application can easily and efficiently identify the
  200. /// necessary offset, again, as shown in the above code example.
  201. ///
  202. /// \todo We might find that 16bits per field is generally too much and
  203. /// squeeze the two bit type into it as well, having 14bit length
  204. /// (in the rare case of having too long field, it could be split into
  205. /// multiple ones). That would save 2 bytes per item (one for the type,
  206. /// one for padding).
  207. struct FieldSpec {
  208. FieldSpec(Type type_param, uint16_t len_param) :
  209. type(type_param), len(len_param)
  210. {}
  211. Type type; ///< The type of the field.
  212. uint16_t len; ///< The length of the field in bytes.
  213. };
  214. ///
  215. /// \name Constructors and Destructor.
  216. ///
  217. /// \b Note:
  218. /// The copy constructor and the assignment operator are intentionally
  219. /// defined as private, making this class non copyable.
  220. //@{
  221. private:
  222. RdataFields(const RdataFields& source);
  223. RdataFields& operator=(const RdataFields& source);
  224. public:
  225. /// Constructor from Rdata.
  226. ///
  227. /// This constructor converts the data of a given \c Rdata object into
  228. /// an \c RdataFields object so that the resulting data can be stored
  229. /// in memory in a space-efficient way.
  230. ///
  231. /// It makes a local copy of the original data and dynamically allocates
  232. /// necessary memory, so is not very efficient.
  233. /// The basic idea is to perform the expensive conversion once and keep
  234. /// using the result as long as possible to improve overall performance
  235. /// in a longer term.
  236. ///
  237. /// If the internal resource allocation fails, a corresponding standard
  238. /// exception will be thrown.
  239. /// The current implementation of this constructor internally calls
  240. /// the <code>Rdata::toWire(AbstractMessageRenderer&) const</code> method
  241. /// for the conversion.
  242. /// If that method throws an exception it will be propagated to the caller
  243. /// of this constructor.
  244. ///
  245. /// \param rdata The RDATA for which the \c RdataFields to be constructed.
  246. RdataFields(const Rdata& rdata);
  247. /// Constructor from field parameters.
  248. ///
  249. /// The intended usage of this version of constructor is to form a
  250. /// structured representation of \c RDATA encoded by the other
  251. /// constructor so that the resulting object can be used for subsequent
  252. /// operations such as rendering in the wire format.
  253. /// This version is intended to be efficient by not making any copy
  254. /// of variable length data or expensive data inspection.
  255. ///
  256. /// This constructor is basically exception free, except against bogus
  257. /// input parameters.
  258. /// Specifically, the parameters must meet the following conditions;
  259. /// otherwise an exception of class \c InvalidParameter will be thrown.
  260. /// - \c fields can be \c NULL if and only if \c nfields is 0
  261. /// - \c data can be \c NULL if and only if \c data_length is 0
  262. /// - the sum of the lengths of \c fields entries must be equal to
  263. /// \c data_length
  264. ///
  265. /// This constructor assumes that the memory region pointed by \c data (if
  266. /// non \c NULL) is encoded as a sequence of valid \c RdataFields fields,
  267. /// and does not perform deep inspection on each field.
  268. /// In particular, for fields of type \c COMPRESSIBLE_NAME or
  269. /// \c INCOMPRESSIBLE_NAME, this constructor assumes the corresponding
  270. /// memory region is a valid representation of domain name.
  271. /// Otherwise, a subsequent method call such as
  272. /// <code>toWire(AbstractMessageRenderer&) const</code>
  273. /// may trigger an unexpected exception. It also expects the fields reside
  274. /// on address that is valid for them (eg. it has valid alignment), see
  275. /// getFieldSpecData() for details.
  276. ///
  277. /// It is the caller's responsibility to ensure this assumption.
  278. /// In general, this constructor is expected to be used for serialized data
  279. /// generated by the other constructor from a valid \c Rdata.
  280. /// The result is not guaranteed if the data is generated in any other
  281. /// ways.
  282. ///
  283. /// The resulting \c RdataFields object does not maintain a copy of
  284. /// \c fields or \c data. It is the caller's responsibility to ensure
  285. /// the memory regions pointed to by these parameters are valid and intact
  286. /// as long as the \c RdataFields object is used.
  287. ///
  288. /// \param fields An array of \c FieldSpec entries. This can be \c NULL.
  289. /// \param fields_length The total length of the \c fields.
  290. /// \param data A pointer to memory region for the entire RDATA. This can
  291. /// be NULL.
  292. /// \param data_length The length of \c data in bytes.
  293. RdataFields(const void* fields, const unsigned int fields_length,
  294. const void* data, const size_t data_length);
  295. /// The destructor.
  296. ~RdataFields();
  297. //@}
  298. ///
  299. /// \name Getter Methods
  300. ///
  301. //@{
  302. /// \brief Return the length of the entire RDATA encoded in the
  303. /// \c RdataFields in bytes.
  304. ///
  305. /// This method never throws an exception.
  306. unsigned int getDataLength() const { return (data_length_); }
  307. /// \brief Return a pointer to the RDATA encoded in the \c RdataFields.
  308. ///
  309. /// The RdataFields holds ownership of the data.
  310. ///
  311. /// This method never throws an exception.
  312. const void* getData() const { return (data_); }
  313. /// \brief Return the number of bytes the buffer returned by
  314. /// getFieldSpecData() will occupy.
  315. ///
  316. /// This method never throws an exception.
  317. unsigned int getFieldSpecDataSize() const { return (nfields_ *
  318. sizeof (*fields_)); }
  319. /// \brief Return the number of specs fields.
  320. ///
  321. /// It specifies the range of parameter for getFieldSpec().
  322. ///
  323. /// This method never throws.
  324. unsigned int getFieldCount() const { return (nfields_); }
  325. /// \brief Return a pointer to a sequence of \c FieldSpec for the
  326. /// \c RdataFields.
  327. ///
  328. /// This should be treated as an opaque internal representation you can
  329. /// just store off somewhere and use it to construct a new RdataFields.
  330. /// from it. If you are really interested, you can typecast it to
  331. /// FieldSpec * (which is what it really is internally).
  332. ///
  333. /// The RdataFields holds ownership of the data.
  334. ///
  335. /// \note You should, however, be aware of alignment issues. The pointer
  336. /// you pass to the constructor must be an address where the FieldSpec
  337. /// can live. If you store it at a wrong address (eg. even one with
  338. /// current implementation on most architectures), it might lead bad
  339. /// things from slow access to SIGBUS. The easiest way is not to
  340. /// interleave the fields with data from getData(). It is OK to place
  341. /// all the fields first (even from multiple RdataFields) and then
  342. /// place all the data after them.
  343. ///
  344. /// This method never throws an exception.
  345. const void* getFieldSpecData() const {
  346. return (fields_);
  347. }
  348. /// \brief Return the specification of the field identified by the given
  349. /// index.
  350. ///
  351. /// \c field_id is the field index, which must be in the range of
  352. /// <code>[0, getFieldCount())</code>. 0 means the first field, and
  353. /// <code>getFieldCount()-1</code> means the last.
  354. ///
  355. /// If the given index is not in the valid range, an exception of class
  356. /// \c OutOfRange will be thrown.
  357. /// This method never throws an exception otherwise.
  358. ///
  359. /// \param field_id The index of an \c RdataFields field to be returned.
  360. /// \return A \c FieldSpec structure that contains the information of
  361. /// the \c field_id-th field.
  362. FieldSpec getFieldSpec(const unsigned int field_id) const;
  363. //@}
  364. ///
  365. /// \name Converter Methods
  366. ///
  367. //@{
  368. /// \brief Render the RdataFields in the wire format with name compression.
  369. ///
  370. /// This method may require resource allocation in \c renderer.
  371. /// If it fails, a corresponding standard exception will be thrown.
  372. /// It should not throw any other exception as long as the \c RdataFields
  373. /// object was constructed from valid parameters (see the description of
  374. /// constructors). The result is not guaranteed if it's constructed in
  375. /// any other ways.
  376. ///
  377. /// \param renderer DNS message rendering context that encapsulates the
  378. /// output buffer and name compression information.
  379. void toWire(AbstractMessageRenderer& renderer) const;
  380. /// \brief Render the RdataFields in the wire format without name
  381. /// compression.
  382. ///
  383. /// This method may require resource allocation in \c buffer.
  384. /// If it fails, a corresponding standard exception will be thrown.
  385. ///
  386. /// \param buffer An output buffer to store the wire data.
  387. void toWire(isc::util::OutputBuffer& buffer) const;
  388. //@}
  389. private:
  390. const FieldSpec* fields_;
  391. unsigned int nfields_;
  392. const uint8_t* data_;
  393. size_t data_length_;
  394. // hide further details within the implementation and don't create vectors
  395. // every time we don't need them.
  396. struct RdataFieldsDetail;
  397. RdataFieldsDetail* detail_;
  398. };
  399. }
  400. }
  401. }
  402. #endif // RDATAFIELDS_H
  403. // Local Variables:
  404. // mode: c++
  405. // End: