rdata_reader.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Copyright (C) 2012 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 DATASRC_MEMORY_RDATA_READER_H
  15. #define DATASRC_MEMORY_RDATA_READER_H 1
  16. #include "rdata_field.h"
  17. #include <boost/function.hpp>
  18. #include <dns/labelsequence.h>
  19. #include <dns/name.h>
  20. namespace isc {
  21. // Some forward declarations
  22. namespace dns{
  23. class RRClass;
  24. class RRType;
  25. }
  26. namespace datasrc {
  27. namespace memory {
  28. /// \brief Class to read serialized rdata
  29. ///
  30. /// This class allows you to read the data encoded by RdataEncoder.
  31. /// It is rather low-level -- it provides sequence of data fields.
  32. /// Each field is either opaque data, passed as a pointer and length,
  33. /// or a name, in the form of dns::LabelSequence (which is always
  34. /// absolute) and attributes.
  35. ///
  36. /// Conceptually, these fields correspond to consecutive regions in
  37. /// wire-format representation of the RDATA, varying the type of above
  38. /// two cases depending on whether the region corresponds to a domain
  39. /// name or other data. For example, for an MX RDATA the field
  40. /// sequence will be
  41. /// - 2 bytes of opaque data (which corresponds to the MX preference)
  42. /// - a domain name (which corresponds to the MX name)
  43. ///
  44. /// If the encoded data contain multiple MX RDATAs, the same type of
  45. /// sequence continues for the number of RDATAs. Note that the opaque
  46. /// data field does not always corresponds to a specific RDATA field
  47. /// as is the 2-byte preference field of MX. For example, the field
  48. /// sequence for an SOA RDATA in terms of RdataEncoder will be:
  49. /// - a domain name (which corresponds to the SOA MNAME)
  50. /// - a domain name (which corresponds to the SOA RNAME)
  51. /// - 20 bytes of opaque data (for the rest of fields)
  52. ///
  53. /// So, if you want to construct a general purpose dns::Rdata object
  54. /// from the field sequence, you'll need to build the complete
  55. /// wire-format data, and then construct a dns::Rdata object from it.
  56. ///
  57. /// To use it, contstruct it with the data you got from RDataEncoder,
  58. /// provide it with callbacks and then iterate through the data.
  59. /// The callbacks are called with the data fields contained in the
  60. /// data.
  61. ///
  62. /// \code
  63. /// void handleName(const dns::LabelSequence& labels, unsigned int flags) {
  64. /// ...
  65. /// }
  66. /// void handleData(const void* data, size_t size) {
  67. /// ...
  68. /// }
  69. ///
  70. /// RdataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
  71. /// &handleName, &handleData);
  72. /// reader.iterate();
  73. /// \endcode
  74. ///
  75. /// \note It is caller's responsibility to pass valid data here. This means
  76. /// the data returned by RdataEncoder and the corresponding class and type.
  77. /// If this is not the case, all the kinds of pointer hell might get loose.
  78. class RdataReader {
  79. public:
  80. /// \brief Function called on each name encountered in the data.
  81. typedef boost::function<void(const dns::LabelSequence&,
  82. RdataNameAttributes)> NameAction;
  83. /// \brief Function called on each data field in the data.
  84. typedef boost::function<void(const void*, size_t)> DataAction;
  85. /// \brief Constructor
  86. ///
  87. /// This constructs the reader on top of some serialized data.
  88. /// It does not copy the data, you have to make sure the data
  89. /// is valid for the whole life of this object and that they
  90. /// don't change.
  91. ///
  92. /// \param rrclass The class the encoded rdata belongs to.
  93. /// \param rrtype The type of the encode rdata.
  94. /// \param data The actual data.
  95. /// \param rdata_count The number of Rdata encoded in the data.
  96. /// \param sig_count The number of RRSig rdata bundled with the data.
  97. /// \param name_action The callback to be called on each encountered name.
  98. /// \param data_action The callback to be called on each data chunk.
  99. RdataReader(const dns::RRClass& rrclass, const dns::RRType& rrtype,
  100. const void* data, size_t rdata_count, size_t sig_count,
  101. const NameAction& name_action, const DataAction& data_action);
  102. /// \brief Result of next() and nextSig()
  103. ///
  104. /// This specifies if there's any boundary in the data at the
  105. /// place where the corresponding call to next() or nextSig()
  106. /// finished.
  107. enum Boundary {
  108. NO_BOUNDARY, ///< It is in the middle of Rdata
  109. RDATA_BOUNDARY, ///< At the end of single Rdata
  110. RRSET_BOUNDARY ///< At the end of the RRset (past the end)
  111. };
  112. /// \brief Step to next data field.
  113. ///
  114. /// Iterate over the next field and call appropriate hook (name_action
  115. /// or data_action, depending on the type) as passed to the constructor.
  116. ///
  117. /// \return It returns NO_BOUNDARY if the next call to next() will process
  118. /// data of the same rdata as this one. RDATA_BOUNDARY is returned when
  119. /// this field is the last of the current rdata. If there are no more
  120. /// data to process, no hook is called and RRSET_BOUNDARY is returned.
  121. /// Therefore, at the end of the whole data, once it processes the last
  122. /// field and returns RDATA_BOUNDARY and then it returns RRSET_BOUNDARY
  123. /// on the next call.
  124. Boundary next();
  125. /// \brief Call next() until the end.
  126. ///
  127. /// This is just convenience method to iterate through all the data.
  128. /// It calls next until it reaches the end (it does not rewind beforehand,
  129. /// therefore if you already called next() yourself, it does not start
  130. /// at the beginning).
  131. void iterate() {
  132. while (next() != RRSET_BOUNDARY) {}
  133. }
  134. /// \brief Call next() until the end of current rdata.
  135. ///
  136. /// This is a convenience method to iterate until the end of current
  137. /// rdata. Notice this may cause more than one field being processed,
  138. /// as some rrtypes are more complex.
  139. ///
  140. /// \return If there was Rdata to iterate through.
  141. bool iterateRdata() {
  142. while (true) {
  143. switch (next()) {
  144. case NO_BOUNDARY: break;
  145. case RDATA_BOUNDARY: return (true);
  146. case RRSET_BOUNDARY: return (false);
  147. }
  148. }
  149. }
  150. /// \brief Step to next field of RRSig data.
  151. ///
  152. /// This is almost the same as next(), but it iterates through the
  153. /// associated RRSig data, not the data for the given RRType.
  154. Boundary nextSig();
  155. /// \brief Iterate through all RRSig data.
  156. ///
  157. /// This is almost the same as iterate(), but it iterates through the
  158. /// RRSig data instead.
  159. void iterateAllSigs() {
  160. while (nextSig() != RRSET_BOUNDARY) {}
  161. }
  162. /// \brief Iterate through the current RRSig Rdata.
  163. ///
  164. /// This is almote the same as iterateRdata, except it is for single
  165. /// signature Rdata.
  166. ///
  167. /// In practice, this should process one DATA field.
  168. bool iterateSingleSig() {
  169. while (true) {
  170. switch (nextSig()) {
  171. case NO_BOUNDARY: break;
  172. case RDATA_BOUNDARY: return (true);
  173. case RRSET_BOUNDARY: return (false);
  174. }
  175. }
  176. }
  177. /// \brief Rewind the iterator to the beginnig of data.
  178. ///
  179. /// The following next() and nextSig() will start iterating from the
  180. /// beginning again.
  181. void rewind();
  182. /// \brief Returns the size of associated data.
  183. ///
  184. /// This should be the same as the return value of
  185. /// RdataEncoder::getStorageLength() for the same set of data.
  186. /// The intended use of this method is to tell the caller the size of
  187. /// data that were possibly dynamically allocated so that the caller can
  188. /// use it for deallocation.
  189. ///
  190. /// This method only uses the parameters given at the construction of the
  191. /// object, and does not rely on or modify other mutable states.
  192. /// In practice, when the caller wants to call this method, that would be
  193. /// the only purpose of that RdataReader object (although it doesn't have
  194. /// to be so).
  195. size_t getSize() const;
  196. private:
  197. const NameAction name_action_;
  198. const DataAction data_action_;
  199. const RdataEncodeSpec& spec_;
  200. // Total number of var-length fields, count of signatures
  201. const size_t var_count_total_, sig_count_, spec_count_;
  202. // Pointer to the beginning of length fields
  203. const uint16_t* const lengths_;
  204. // Pointer to the beginning of the data (after the lengths)
  205. const uint8_t* const data_;
  206. // Pointer to the first data signature
  207. // Will be computed during the normal RR iteration
  208. const uint8_t* sigs_;
  209. // The positions in data.
  210. size_t data_pos_, spec_pos_, length_pos_;
  211. size_t sig_pos_, sig_data_pos_;
  212. Boundary nextInternal(const NameAction& name_action,
  213. const DataAction& data_action);
  214. };
  215. }
  216. }
  217. }
  218. #endif