Branch data Line data Source code
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 : :
15 : : #include <algorithm>
16 : : #include <string>
17 : : #include <vector>
18 : :
19 : : #include <boost/shared_ptr.hpp>
20 : :
21 : : #include <util/buffer.h>
22 : : #include <dns/messagerenderer.h>
23 : : #include <dns/name.h>
24 : : #include <dns/rrclass.h>
25 : : #include <dns/rrtype.h>
26 : : #include <dns/rrttl.h>
27 : : #include <dns/rrset.h>
28 : :
29 : : using namespace std;
30 : : using namespace isc::dns;
31 : : using namespace isc::util;
32 : : using namespace isc::dns::rdata;
33 : :
34 : : namespace isc {
35 : : namespace dns {
36 : : void
37 : 8965 : AbstractRRset::addRdata(const Rdata& rdata) {
38 [ + - ]: 17928 : addRdata(createRdata(getType(), getClass(), rdata));
39 : 8963 : }
40 : :
41 : : string
42 : 4305 : AbstractRRset::toText() const {
43 : 3 : string s;
44 [ + - ]: 4305 : RdataIteratorPtr it = getRdataIterator();
45 : :
46 [ + - ][ + + ]: 4305 : if (it->isLast()) {
47 [ + - ][ + - ]: 4308 : isc_throw(EmptyRRset, "ToText() is attempted for an empty RRset");
48 : : }
49 : :
50 [ + + ]: 4859 : do {
51 [ + - ][ + - ]: 14577 : s += getName().toText() + " " + getTTL().toText() + " " +
52 [ + - ][ + - ]: 19436 : getClass().toText() + " " + getType().toText() + " " +
53 [ + - ][ + - ]: 34013 : it->getCurrent().toText() + "\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
54 [ + - ]: 4859 : it->next();
55 [ + - ]: 4859 : } while (!it->isLast());
56 : :
57 : 4302 : return (s);
58 : : }
59 : :
60 : : namespace {
61 : : template <typename T>
62 : : inline unsigned int
63 : 674 : rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) {
64 : 674 : unsigned int n = 0;
65 : 674 : RdataIteratorPtr it = rrset.getRdataIterator();
66 : :
67 [ + - ]: 674 : if (it->isLast()) {
[ + + + - ]
[ + + ]
68 [ + - ][ + - ]: 681 : isc_throw(EmptyRRset, "ToWire() is attempted for an empty RRset");
[ + - ][ + - ]
69 : : }
70 : :
71 : : // sort the set of Rdata based on rrset-order and sortlist, and possible
72 : : // other options. Details to be considered.
73 [ + + ][ + + ]: 696 : do {
74 : 708 : const size_t pos0 = output.getLength();
75 [ - + ][ - + ]: 708 : assert(pos0 < 65536);
76 : :
77 [ + - ][ + - ]: 708 : rrset.getName().toWire(output);
[ + - ][ + - ]
78 [ + - ][ + - ]: 708 : rrset.getType().toWire(output);
[ + - ][ + - ]
79 [ + - ][ + - ]: 708 : rrset.getClass().toWire(output);
[ + - ][ + - ]
80 [ + - ][ + - ]: 708 : rrset.getTTL().toWire(output);
[ + - ][ + - ]
81 : :
82 : 708 : const size_t pos = output.getLength();
83 [ + - ]: 68 : output.skip(sizeof(uint16_t)); // leave the space for RDLENGTH
84 [ + - ][ + - ]: 708 : it->getCurrent().toWire(output);
[ + - ][ + - ]
85 [ + - ]: 68 : output.writeUint16At(output.getLength() - pos - sizeof(uint16_t), pos);
86 : :
87 [ + - ][ + + ]: 708 : if (limit > 0 && output.getLength() > limit) {
[ + + ][ - + ]
[ # # ][ - + ]
88 : : // truncation is needed
89 [ # # ]: 0 : output.trim(output.getLength() - pos0);
90 : : return (n);
91 : : }
92 : :
93 [ + - ][ + - ]: 696 : it->next();
94 [ + - ][ + - ]: 696 : ++n;
95 : : } while (!it->isLast());
96 : :
97 : : return (n);
98 : : }
99 : : }
100 : :
101 : : unsigned int
102 : 68 : AbstractRRset::toWire(OutputBuffer& buffer) const {
103 : 68 : return (rrsetToWire<OutputBuffer>(*this, buffer, 0));
104 : : }
105 : :
106 : : unsigned int
107 : 606 : AbstractRRset::toWire(AbstractMessageRenderer& renderer) const {
108 : : const unsigned int rrs_written = rrsetToWire<AbstractMessageRenderer>(
109 : 606 : *this, renderer, renderer.getLengthLimit());
110 [ + + ]: 602 : if (getRdataCount() > rrs_written) {
111 : 12 : renderer.setTruncated();
112 : : }
113 : 602 : return (rrs_written);
114 : : }
115 : :
116 : : bool
117 : 389 : AbstractRRset::isSameKind(const AbstractRRset& other) const {
118 : : // Compare classes last as they're likely to be identical. Compare
119 : : // names late in the list too, as these are expensive. So we compare
120 : : // types first, names second and classes last.
121 : 389 : return (getType() == other.getType() &&
122 : 81 : getName() == other.getName() &&
123 [ + + + + ]: 470 : getClass() == other.getClass());
[ + + ]
124 : : }
125 : :
126 : : ostream&
127 : 432 : operator<<(ostream& os, const AbstractRRset& rrset) {
128 [ + - ]: 432 : os << rrset.toText();
129 : 432 : return (os);
130 : : }
131 : :
132 : : /// \brief This encapsulates the actual implementation of the \c BasicRRset
133 : : /// class. It's hidden from applications.
134 : 24688 : class BasicRRsetImpl {
135 : : public:
136 : : BasicRRsetImpl(const Name& name, const RRClass& rrclass,
137 : : const RRType& rrtype, const RRTTL& ttl) :
138 : 49388 : name_(name), rrclass_(rrclass), rrtype_(rrtype), ttl_(ttl) {}
139 : : Name name_;
140 : : RRClass rrclass_;
141 : : RRType rrtype_;
142 : : RRTTL ttl_;
143 : : // XXX: "list" is not a good name: It in fact isn't a list; more conceptual
144 : : // name than a data structure name is generally better. But since this
145 : : // is only used in the internal implementation we'll live with it.
146 : : vector<ConstRdataPtr> rdatalist_;
147 : : };
148 : :
149 : 24694 : BasicRRset::BasicRRset(const Name& name, const RRClass& rrclass,
150 : 49388 : const RRType& rrtype, const RRTTL& ttl)
151 : : {
152 [ + - ]: 24694 : impl_ = new BasicRRsetImpl(name, rrclass, rrtype, ttl);
153 : 24694 : }
154 : :
155 : 24688 : BasicRRset::~BasicRRset() {
156 [ + - ]: 49376 : delete impl_;
157 : 24688 : }
158 : :
159 : : void
160 : 30652 : BasicRRset::addRdata(ConstRdataPtr rdata) {
161 : 30652 : impl_->rdatalist_.push_back(rdata);
162 : 30652 : }
163 : :
164 : : void
165 : 8965 : BasicRRset::addRdata(const Rdata& rdata) {
166 : 8965 : AbstractRRset::addRdata(rdata);
167 : 8963 : }
168 : :
169 : : unsigned int
170 : 6928 : BasicRRset::getRdataCount() const {
171 : 6928 : return (impl_->rdatalist_.size());
172 : : }
173 : :
174 : : const Name&
175 : 53623 : BasicRRset::getName() const {
176 : 53623 : return (impl_->name_);
177 : : }
178 : :
179 : : const RRClass&
180 : 33628 : BasicRRset::getClass() const {
181 : 33628 : return (impl_->rrclass_);
182 : : }
183 : :
184 : : const RRType&
185 : 102614 : BasicRRset::getType() const {
186 : 102614 : return (impl_->rrtype_);
187 : : }
188 : :
189 : : const RRTTL&
190 : 20339 : BasicRRset::getTTL() const {
191 : 20339 : return (impl_->ttl_);
192 : : }
193 : :
194 : : void
195 : 18 : BasicRRset::setName(const Name& name) {
196 : 18 : impl_->name_ = name;
197 : 18 : }
198 : :
199 : : void
200 : 374 : BasicRRset::setTTL(const RRTTL& ttl) {
201 : 374 : impl_->ttl_ = ttl;
202 : 374 : }
203 : :
204 : : string
205 : 4305 : BasicRRset::toText() const {
206 : 4305 : return (AbstractRRset::toText());
207 : : }
208 : :
209 : : unsigned int
210 : 68 : BasicRRset::toWire(OutputBuffer& buffer) const {
211 : 68 : return (AbstractRRset::toWire(buffer));
212 : : }
213 : :
214 : : unsigned int
215 : 606 : BasicRRset::toWire(AbstractMessageRenderer& renderer) const {
216 : 606 : return (AbstractRRset::toWire(renderer));
217 : : }
218 : :
219 : 24694 : RRset::RRset(const Name& name, const RRClass& rrclass,
220 : : const RRType& rrtype, const RRTTL& ttl) :
221 : 24694 : BasicRRset(name, rrclass, rrtype, ttl)
222 : : {
223 [ + - ]: 24694 : rrsig_ = RRsetPtr();
224 : 24694 : }
225 : :
226 : 49286 : RRset::~RRset() {}
227 : :
228 : : namespace {
229 : : class BasicRdataIterator : public RdataIterator {
230 : : private:
231 : : BasicRdataIterator() {}
232 : : public:
233 : : BasicRdataIterator(const std::vector<rdata::ConstRdataPtr>& datavector) :
234 : 44787 : datavector_(&datavector), it_(datavector_->begin())
235 : : {}
236 : 14929 : ~BasicRdataIterator() {}
237 : 1890 : virtual void first() { it_ = datavector_->begin(); }
238 : 16453 : virtual void next() { ++it_; }
239 : 18906 : virtual const rdata::Rdata& getCurrent() const { return (**it_); }
240 : 32168 : virtual bool isLast() const { return (it_ == datavector_->end()); }
241 : : private:
242 : : const std::vector<rdata::ConstRdataPtr>* datavector_;
243 : : std::vector<rdata::ConstRdataPtr>::const_iterator it_;
244 : : };
245 : : }
246 : :
247 : : RdataIteratorPtr
248 : 14929 : BasicRRset::getRdataIterator() const {
249 : 29858 : return (RdataIteratorPtr(new BasicRdataIterator(impl_->rdatalist_)));
250 : : }
251 : : }
252 : 144 : }
|