rrset.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. // $Id$
  15. #include <algorithm>
  16. #include <string>
  17. #include <vector>
  18. #include <boost/shared_ptr.hpp>
  19. #include <dns/buffer.h>
  20. #include <dns/messagerenderer.h>
  21. #include <dns/name.h>
  22. #include <dns/rrclass.h>
  23. #include <dns/rrtype.h>
  24. #include <dns/rrttl.h>
  25. #include <dns/rrset.h>
  26. using namespace std;
  27. using namespace isc::dns;
  28. using namespace isc::dns::rdata;
  29. namespace isc {
  30. namespace dns {
  31. void
  32. AbstractRRset::addRdata(const Rdata& rdata) {
  33. addRdata(createRdata(getType(), getClass(), rdata));
  34. }
  35. string
  36. AbstractRRset::toText() const {
  37. string s;
  38. RdataIteratorPtr it = getRdataIterator();
  39. if (it->isLast()) {
  40. isc_throw(EmptyRRset, "ToText() is attempted for an empty RRset");
  41. }
  42. do {
  43. s += getName().toText() + " " + getTTL().toText() + " " +
  44. getClass().toText() + " " + getType().toText() + " " +
  45. it->getCurrent().toText() + "\n";
  46. it->next();
  47. } while (!it->isLast());
  48. return (s);
  49. }
  50. namespace {
  51. template <typename T>
  52. inline unsigned int
  53. rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) {
  54. unsigned int n = 0;
  55. RdataIteratorPtr it = rrset.getRdataIterator();
  56. if (it->isLast()) {
  57. isc_throw(EmptyRRset, "ToWire() is attempted for an empty RRset");
  58. }
  59. // sort the set of Rdata based on rrset-order and sortlist, and possible
  60. // other options. Details to be considered.
  61. do {
  62. const size_t pos0 = output.getLength();
  63. assert(pos0 < 65536);
  64. rrset.getName().toWire(output);
  65. rrset.getType().toWire(output);
  66. rrset.getClass().toWire(output);
  67. rrset.getTTL().toWire(output);
  68. const size_t pos = output.getLength();
  69. output.skip(sizeof(uint16_t)); // leave the space for RDLENGTH
  70. it->getCurrent().toWire(output);
  71. output.writeUint16At(output.getLength() - pos - sizeof(uint16_t), pos);
  72. if (limit > 0 && output.getLength() > limit) {
  73. // truncation is needed
  74. output.trim(output.getLength() - pos0);
  75. return (n);
  76. }
  77. it->next();
  78. ++n;
  79. } while (!it->isLast());
  80. return (n);
  81. }
  82. }
  83. unsigned int
  84. AbstractRRset::toWire(OutputBuffer& buffer) const {
  85. return (rrsetToWire<OutputBuffer>(*this, buffer, 0));
  86. }
  87. unsigned int
  88. AbstractRRset::toWire(MessageRenderer& renderer) const {
  89. const unsigned int rrs_written = rrsetToWire<MessageRenderer>(
  90. *this, renderer, renderer.getLengthLimit());
  91. if (getRdataCount() > rrs_written) {
  92. renderer.setTruncated();
  93. }
  94. return (rrs_written);
  95. }
  96. ostream&
  97. operator<<(ostream& os, const AbstractRRset& rrset) {
  98. os << rrset.toText();
  99. return (os);
  100. }
  101. /// \brief This encapsulates the actual implementation of the \c BasicRRset
  102. /// class. It's hidden from applications.
  103. class BasicRRsetImpl {
  104. public:
  105. BasicRRsetImpl(const Name& name, const RRClass& rrclass,
  106. const RRType& rrtype, const RRTTL& ttl) :
  107. name_(name), rrclass_(rrclass), rrtype_(rrtype), ttl_(ttl) {}
  108. Name name_;
  109. RRClass rrclass_;
  110. RRType rrtype_;
  111. RRTTL ttl_;
  112. // XXX: "list" is not a good name: It in fact isn't a list; more conceptual
  113. // name than a data structure name is generally better. But since this
  114. // is only used in the internal implementation we'll live with it.
  115. vector<ConstRdataPtr> rdatalist_;
  116. };
  117. BasicRRset::BasicRRset(const Name& name, const RRClass& rrclass,
  118. const RRType& rrtype, const RRTTL& ttl)
  119. {
  120. impl_ = new BasicRRsetImpl(name, rrclass, rrtype, ttl);
  121. }
  122. BasicRRset::~BasicRRset() {
  123. delete impl_;
  124. }
  125. void
  126. BasicRRset::addRdata(ConstRdataPtr rdata) {
  127. impl_->rdatalist_.push_back(rdata);
  128. }
  129. void
  130. BasicRRset::addRdata(const Rdata& rdata) {
  131. AbstractRRset::addRdata(rdata);
  132. }
  133. unsigned int
  134. BasicRRset::getRdataCount() const {
  135. return (impl_->rdatalist_.size());
  136. }
  137. const Name&
  138. BasicRRset::getName() const {
  139. return (impl_->name_);
  140. }
  141. const RRClass&
  142. BasicRRset::getClass() const {
  143. return (impl_->rrclass_);
  144. }
  145. const RRType&
  146. BasicRRset::getType() const {
  147. return (impl_->rrtype_);
  148. }
  149. const RRTTL&
  150. BasicRRset::getTTL() const {
  151. return (impl_->ttl_);
  152. }
  153. void
  154. BasicRRset::setName(const Name& name) {
  155. impl_->name_ = name;
  156. }
  157. void
  158. BasicRRset::setTTL(const RRTTL& ttl) {
  159. impl_->ttl_ = ttl;
  160. }
  161. string
  162. BasicRRset::toText() const {
  163. return (AbstractRRset::toText());
  164. }
  165. unsigned int
  166. BasicRRset::toWire(OutputBuffer& buffer) const {
  167. return (AbstractRRset::toWire(buffer));
  168. }
  169. unsigned int
  170. BasicRRset::toWire(MessageRenderer& renderer) const {
  171. return (AbstractRRset::toWire(renderer));
  172. }
  173. RRset::RRset(const Name& name, const RRClass& rrclass,
  174. const RRType& rrtype, const RRTTL& ttl) :
  175. BasicRRset(name, rrclass, rrtype, ttl)
  176. {
  177. rrsig_ = RRsetPtr();
  178. }
  179. RRset::~RRset() {}
  180. namespace {
  181. class BasicRdataIterator : public RdataIterator {
  182. private:
  183. BasicRdataIterator() {}
  184. public:
  185. BasicRdataIterator(const std::vector<rdata::ConstRdataPtr>& datavector) :
  186. datavector_(&datavector), it_(datavector_->begin())
  187. {}
  188. ~BasicRdataIterator() {}
  189. virtual void first() { it_ = datavector_->begin(); }
  190. virtual void next() { ++it_; }
  191. virtual const rdata::Rdata& getCurrent() const { return (**it_); }
  192. virtual bool isLast() const { return (it_ == datavector_->end()); }
  193. private:
  194. const std::vector<rdata::ConstRdataPtr>* datavector_;
  195. std::vector<rdata::ConstRdataPtr>::const_iterator it_;
  196. };
  197. }
  198. RdataIteratorPtr
  199. BasicRRset::getRdataIterator() const {
  200. return (RdataIteratorPtr(new BasicRdataIterator(impl_->rdatalist_)));
  201. }
  202. }
  203. }