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 : : #ifndef __QUESTION_H
16 : : #define __QUESTION_H 1
17 : :
18 : : #include <iostream>
19 : : #include <string>
20 : :
21 : : #include <boost/shared_ptr.hpp>
22 : :
23 : : #include <dns/name.h>
24 : : #include <dns/rrclass.h>
25 : : #include <dns/rrtype.h>
26 : :
27 : : namespace isc {
28 : : namespace util {
29 : : class InputBuffer;
30 : : class OutputBuffer;
31 : : }
32 : :
33 : : namespace dns {
34 : :
35 : : class AbstractMessageRenderer;
36 : : class Question;
37 : :
38 : : /// \brief A pointer-like type pointing to an \c Question object.
39 : : typedef boost::shared_ptr<Question> QuestionPtr;
40 : :
41 : : /// \brief A pointer-like type pointing to an (immutable) \c Question object.
42 : : typedef boost::shared_ptr<const Question> ConstQuestionPtr;
43 : :
44 : : /// \brief The \c Question class encapsulates the common search key of DNS
45 : : /// lookup, consisting of owner name, RR type and RR class.
46 : : ///
47 : : /// The primarily intended use case of this class is an entry of the question
48 : : /// section of DNS messages.
49 : : /// This could also be used as a general purpose lookup key, e.g., in a
50 : : /// custom implementation of DNS database.
51 : : ///
52 : : /// In this initial implementation, the \c Question class is defined as
53 : : /// a <em>concrete class</em>; it's not expected to be inherited by
54 : : /// a user-defined customized class.
55 : : /// It may be worth noting that it's different from the design of the
56 : : /// RRset classes (\c AbstractRRset and its derived classes).
57 : : /// The RRset classes form an inheritance hierarchy from the base abstract
58 : : /// class.
59 : : /// This may look odd in that an "RRset" and "Question" are similar from the
60 : : /// protocol point of view: Both are used as a semantics unit of DNS messages;
61 : : /// both share the same set of components (name, RR type and RR class).
62 : : ///
63 : : /// In fact, BIND9 didn't introduce a separate data structure for Questions,
64 : : /// and use the same \c "rdataset" structure for both RRsets and Questions.
65 : : /// We could take the same approach, but chose to adopt the different design.
66 : : /// One reason for that is because a Question and an RRset are still
67 : : /// different, and a Question might not be cleanly defined, e.g., if it were
68 : : /// a derived class of some "RRset-like" class.
69 : : /// For example, we couldn't give a reasonable semantics for \c %getTTL() or
70 : : /// \c %setTTL() methods for a Question, since it's not associated with the
71 : : /// TTL.
72 : : /// In fact, the BIND9 implementation ended up often separating the case where
73 : : /// a \c "rdataset" is from the Question section of a DNS message and the
74 : : /// case where it comes from other sections.
75 : : /// If we cannot treat them completely transparently anyway, separating the
76 : : /// class (type) would make more sense because we can exploit compilation
77 : : /// time type checks.
78 : : ///
79 : : /// On the other hand, we do not expect a strong need for customizing the
80 : : /// \c Question class, unlike the RRset.
81 : : /// Handling the "Question" section of a DNS message is relatively a
82 : : /// simple work comparing to RRset-involved operations, so a unified
83 : : /// straightforward implementation should suffice for any use cases
84 : : /// including performance sensitive ones.
85 : : ///
86 : : /// We may, however, still want to have a customized version of Question
87 : : /// for, e.g, highly optimized behavior, and may revisit this design choice
88 : : /// as we have more experience with this implementation.
89 : : ///
90 : : /// One disadvantage of defining RRsets and Questions as unrelated classes
91 : : /// is that we cannot handle them in a polymorphic way.
92 : : /// For example, we might want to iterate over DNS message sections and
93 : : /// render the data in the wire format, whether it's an RRset or a Question.
94 : : /// If a \c Question were a derived class of some common RRset-like class,
95 : : /// we could do this by calling <code>rrset_or_question->%toWire()</code>.
96 : : /// But the actual design doesn't allow this approach, which may require
97 : : /// duplicate code for almost the same operation.
98 : : /// To mitigate this problem, we intentionally used the same names
99 : : /// with the same signature for some common methods of \c Question and
100 : : /// \c AbstractRRset such as \c %getName() or \c %toWire().
101 : : /// So the user class may use a template function that is applicable to both
102 : : /// \c Question and \c RRset to avoid writing duplicate code logic.
103 [ # + ][ + - ]: 5196 : class Question {
[ + - ][ + - ]
[ - ][ + - ]
[ # # ][ + ]
[ + - ]
104 : : ///
105 : : /// \name Constructors and Destructor
106 : : ///
107 : : /// We use the default versions of destructor, copy constructor,
108 : : /// and assignment operator.
109 : : ///
110 : : /// The default constructor is hidden as a result of defining the other
111 : : /// constructors. This is intentional; we don't want to allow a
112 : : /// \c Question object to be constructed with an invalid state.
113 : : //@{
114 : : public:
115 : : /// \brief Constructor from wire-format data.
116 : : ///
117 : : /// It simply constructs a set of \c Name, \c RRType, and \c RRClass
118 : : /// object from the \c buffer in this order, and constructs a
119 : : /// \c Question object in a straightforward way.
120 : : ///
121 : : /// It may throw an exception if the construction of these component
122 : : /// classes fails.
123 : : ///
124 : : /// \param buffer A buffer storing the wire format data.
125 : : Question(isc::util::InputBuffer& buffer);
126 : :
127 : : /// \brief Constructor from fixed parameters of the \c Question.
128 : : ///
129 : : /// This constructor is basically expected to be exception free, but
130 : : /// copying the name may involve resource allocation, and if it fails
131 : : /// the corresponding standard exception will be thrown.
132 : : ///
133 : : /// \param name The owner name of the \c Question.
134 : : /// \param rrclass The RR class of the \c Question.
135 : : /// \param rrtype The RR type of the \c Question.
136 : 269 : Question(const Name& name, const RRClass& rrclass, const RRType& rrtype) :
137 [ + - ][ + - ]: 3052 : name_(name), rrtype_(rrtype), rrclass_(rrclass)
[ + - ][ + - ]
[ + - + -
+ - + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
138 : 269 : {}
139 : : //@}
140 : :
141 : : ///
142 : : /// \name Getter Methods
143 : : ///
144 : : //@{
145 : : /// \brief Returns the owner name of the \c Question.
146 : : ///
147 : : /// This method never throws an exception.
148 : : ///
149 : : /// \return A reference to a \c Name class object corresponding to the
150 : : /// \c Question owner name.
151 : : const Name& getName() const { return (name_); }
152 : :
153 : : /// \brief Returns the RR Class of the \c Question.
154 : : ///
155 : : /// This method never throws an exception.
156 : : ///
157 : : /// \return A reference to a \c RRClass class object corresponding to the
158 : : /// RR class of the \c Question.
159 : : const RRType& getType() const { return (rrtype_); }
160 : :
161 : : /// \brief Returns the RR Type of the \c Question.
162 : : ///
163 : : /// This method never throws an exception.
164 : : ///
165 : : /// \return A reference to a \c RRType class object corresponding to the
166 : : /// RR type of the \c Question.
167 : : const RRClass& getClass() const { return (rrclass_); }
168 : : //@}
169 : :
170 : : ///
171 : : /// \name Converter Methods
172 : : ///
173 : : //@{
174 : : /// \brief Convert the Question to a string.
175 : : ///
176 : : /// Unlike other similar methods of this library, this method terminates
177 : : /// the resulting string with a trailing newline character
178 : : /// (following the BIND9 convention).
179 : : ///
180 : : /// This method simply calls the \c %toText() methods of the corresponding
181 : : /// \c Name, \c RRType and \c RRClass classes for this \c Question, and
182 : : /// these methods may throw an exception.
183 : : /// In particular, if resource allocation fails, a corresponding standard
184 : : /// exception will be thrown.
185 : : ///
186 : : /// \return A string representation of the \c Question.
187 : : std::string toText() const;
188 : :
189 : : /// \brief Render the Question in the wire format with name compression.
190 : : ///
191 : : /// This method simply calls the \c %toWire() methods of the corresponding
192 : : /// \c Name, \c RRType and \c RRClass classes for this \c Question, and
193 : : /// these methods may throw an exception.
194 : : /// In particular, if resource allocation fails, a corresponding standard
195 : : /// exception will be thrown.
196 : : ///
197 : : /// This method returns 1, which is the number of "questions" contained
198 : : /// in the \c Question.
199 : : /// This is a meaningless value, but is provided to be consistent with
200 : : /// the corresponding method of \c AbstractRRset (see the detailed
201 : : /// class description).
202 : : ///
203 : : /// The owner name will be compressed if possible, although it's an
204 : : /// unlikely event in practice because the Question section a DNS
205 : : /// message normally doesn't contain multiple question entries and
206 : : /// it's located right after the Header section.
207 : : /// Nevertheless, \c renderer records the information of the owner name
208 : : /// so that it can be pointed by other RRs in other sections (which is
209 : : /// more likely to happen).
210 : : ///
211 : : /// It could be possible, though very rare in practice, that
212 : : /// an attempt to render a Question may cause truncation
213 : : /// (when the Question section contains a large number of entries).
214 : : /// In such a case this method avoid the rendering and indicate the
215 : : /// truncation in the \c renderer. This method returns 0 in this case.
216 : : ///
217 : : /// \param renderer DNS message rendering context that encapsulates the
218 : : /// output buffer and name compression information.
219 : : ///
220 : : /// \return 1 on success; 0 if it causes truncation
221 : : unsigned int toWire(AbstractMessageRenderer& renderer) const;
222 : :
223 : : /// \brief Render the Question in the wire format without name compression.
224 : : ///
225 : : /// This method behaves like the render version except it doesn't compress
226 : : /// the owner name.
227 : : /// See \c toWire(AbstractMessageRenderer& renderer)const.
228 : : ///
229 : : /// \param buffer An output buffer to store the wire data.
230 : : /// \return 1
231 : : unsigned int toWire(isc::util::OutputBuffer& buffer) const;
232 : : //@}
233 : :
234 : : ///
235 : : /// \name Comparison Operators
236 : : ///
237 : : //@{
238 : : /// A "less than" operator is needed for this class so it can
239 : : /// function as an index to std::map.
240 : 16 : bool operator <(const Question& rhs) const {
241 : 4509 : return (rrclass_ < rhs.rrclass_ ||
242 : 4379 : (rrclass_ == rhs.rrclass_ &&
243 : 4347 : (rrtype_ < rhs.rrtype_ ||
244 [ + + ][ + + ]: 5722 : (rrtype_ == rhs.rrtype_ && (name_ < rhs.name_)))));
[ + + ]
[ + + + + ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
245 : : }
246 : :
247 : : /// Equality operator. Primarily used to compare the question section in
248 : : /// a response to that in the query.
249 : : ///
250 : : /// \param rhs Question to compare against
251 : : /// \return true if name, class and type are equal, false otherwise
252 : 16 : bool operator==(const Question& rhs) const {
253 : 172 : return ((rrclass_ == rhs.rrclass_) && (rrtype_ == rhs.rrtype_) &&
254 [ + + ]: 167 : (name_ == rhs.name_));
[ + + + + ]
[ + - ][ + - ]
[ - + ]
255 : : }
256 : :
257 : : /// Inequality operator. Primarily used to compare the question section in
258 : : /// a response to that in the query.
259 : : ///
260 : : /// \param rhs Question to compare against
261 : : /// \return true if one or more of the name, class and type do not match,
262 : : /// false otherwise.
263 : 8 : bool operator!=(const Question& rhs) const {
264 : 8 : return (!operator==(rhs));
265 : : }
266 : : //@}
267 : :
268 : : private:
269 : : Name name_;
270 : : RRType rrtype_;
271 : : RRClass rrclass_;
272 : : };
273 : :
274 : : /// \brief Insert the \c Question as a string into stream.
275 : : ///
276 : : /// This method convert the \c question into a string and inserts it into the
277 : : /// output stream \c os.
278 : : ///
279 : : /// This function overloads the global \c operator<< to behave as described in
280 : : /// \c %ostream::%operator<< but applied to Question objects.
281 : : ///
282 : : /// \param os A \c std::ostream object on which the insertion operation is
283 : : /// performed.
284 : : /// \param question A reference to a \c Question object output by the
285 : : /// operation.
286 : : /// \return A reference to the same \c std::ostream object referenced by
287 : : /// parameter \c os after the insertion operation.
288 : : std::ostream& operator<<(std::ostream& os, const Question& question);
289 : : } // end of namespace dns
290 : : } // end of namespace isc
291 : : #endif // __QUESTION_H
292 : :
293 : : // Local Variables:
294 : : // mode: c++
295 : : // End:
|