Branch data Line data Source code
1 : : // Copyright (C) 2009 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 __NAME_H
16 : : #define __NAME_H 1
17 : :
18 : : #include <stdint.h>
19 : :
20 : : #include <string>
21 : : #include <vector>
22 : :
23 : : #include <exceptions/exceptions.h>
24 : :
25 : : namespace isc {
26 : : namespace util {
27 : : class InputBuffer;
28 : : class OutputBuffer;
29 : : }
30 : :
31 : : namespace dns {
32 : : class AbstractMessageRenderer;
33 : :
34 : : ///
35 : : /// \brief Base class for name parser exceptions.
36 : : ///
37 : 52 : class NameParserException : public Exception {
38 : : public:
39 : : NameParserException(const char* file, size_t line, const char* what) :
40 [ + - ][ # # ]: 52 : isc::Exception(file, line, what) {}
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
41 : : };
42 : :
43 : : ///
44 : : /// \brief A standard DNS module exception that is thrown if the name parser
45 : : /// encounters an empty label in the middle of a name.
46 : : ///
47 : 20 : class EmptyLabel : public NameParserException {
48 : : public:
49 : : EmptyLabel(const char* file, size_t line, const char* what) :
50 : 40 : NameParserException(file, line, what) {}
51 : : };
52 : :
53 : : ///
54 : : /// \brief A standard DNS module exception that is thrown if the name parser
55 : : /// encounters too long a name.
56 : : ///
57 : 6 : class TooLongName : public NameParserException {
58 : : public:
59 : : TooLongName(const char* file, size_t line, const char* what) :
60 : 12 : NameParserException(file, line, what) {}
61 : : };
62 : :
63 : : ///
64 : : /// \brief A standard DNS module exception that is thrown if the name parser
65 : : /// encounters too long a label.
66 : : ///
67 : 13 : class TooLongLabel : public NameParserException {
68 : : public:
69 : : TooLongLabel(const char* file, size_t line, const char* what) :
70 : 26 : NameParserException(file, line, what) {}
71 : : };
72 : :
73 : : ///
74 : : /// \brief A standard DNS module exception that is thrown if the name parser
75 : : /// encounters an obsolete or incomplete label type. In effect "obsolete" only
76 : : /// applies to bitstring labels, which would begin with "\[". Incomplete cases
77 : : /// include an incomplete escaped sequence such as "\12".
78 : : ///
79 : 3 : class BadLabelType : public NameParserException {
80 : : public:
81 : : BadLabelType(const char* file, size_t line, const char* what) :
82 : 6 : NameParserException(file, line, what) {}
83 : : };
84 : :
85 : : ///
86 : : /// \brief A standard DNS module exception that is thrown if the name parser
87 : : /// fails to decode a "\"-escaped sequence.
88 : : ///
89 : 5 : class BadEscape : public NameParserException {
90 : : public:
91 : : BadEscape(const char* file, size_t line, const char* what) :
92 : 10 : NameParserException(file, line, what) {}
93 : : };
94 : :
95 : : ///
96 : : /// \brief A standard DNS module exception that is thrown if the name parser
97 : : /// finds the input (string or wire-format %data) is incomplete.
98 : : ///
99 : : /// An attempt of constructing a name from an empty string will trigger this
100 : : /// exception.
101 : : ///
102 : 5 : class IncompleteName : public NameParserException {
103 : : public:
104 : : IncompleteName(const char* file, size_t line, const char* what) :
105 : 10 : NameParserException(file, line, what) {}
106 : : };
107 : :
108 : : ///
109 : : /// This is a supplemental class used only as a return value of Name::compare().
110 : : /// It encapsulate a tuple of the comparison: ordering, number of common labels,
111 : : /// and relationship as follows:
112 : : /// - ordering: relative ordering under the DNSSEC order relation
113 : : /// - labels: the number of common significant labels of the two names being
114 : : /// compared
115 : : /// - relationship: see NameComparisonResult::NameRelation
116 : : ///
117 : : class NameComparisonResult {
118 : : public:
119 : : /// The relation of two names under comparison.
120 : : /// Its semantics for the case of
121 : : /// <code>name1->compare(name2)</code> (where name1 and name2 are instances
122 : : /// of the Name class) is as follows:
123 : : /// - SUPERDOMAIN: name1 properly contains name2; name2 is a proper
124 : : /// subdomain of name1
125 : : /// - SUBDOMAIN: name1 is a proper subdomain of name2
126 : : /// - EQUAL: name1 and name2 are equal
127 : : /// - COMMONANCESTOR: name1 and name2 share a common ancestor
128 : : ///
129 : : /// Note that in our implementation there's always a hierarchical
130 : : /// relationship between any two names since all names are absolute and
131 : : /// they at least share the trailing empty label.
132 : : /// So, for example, the relationship between "com." and "net." is
133 : : /// "commonancestor". This may be counter intuitive and inconvenient, but
134 : : /// we'll keep this design at the moment until we decide whether and how to
135 : : /// handle "non absolute" names (see the description of the \c Name class).
136 : : /// If we want to (re)introduce the notion of non absolute names, we'll
137 : : /// want to distinguish "com" and "com.", and the current definition would
138 : : /// be more compatible for that purpose.
139 : : /// If, on the other hand, we finally decide we really don't need that
140 : : /// notion, we'll probably reconsider the design here, too.
141 : : enum NameRelation {
142 : : SUPERDOMAIN = 0,
143 : : SUBDOMAIN = 1,
144 : : EQUAL = 2,
145 : : COMMONANCESTOR = 3
146 : : };
147 : :
148 : : ///
149 : : /// \name Constructors and Destructor
150 : : ///
151 : : //@{
152 : : /// \brief Constructor from a comparison tuple
153 : : ///
154 : : /// This constructor simply initializes the object in the straightforward
155 : : /// way.
156 : : NameComparisonResult(int order, unsigned int nlabels,
157 : : NameRelation relation) :
158 : 204879 : order_(order), nlabels_(nlabels), relation_(relation) {}
159 : : //@}
160 : :
161 : : ///
162 : : /// \name Getter Methods
163 : : ///
164 : : //@{
165 : : /// Returns the ordering of the comparison result
166 : 0 : int getOrder() const { return (order_); }
167 : : /// Returns the number of common labels of the comparison result
168 : 0 : unsigned int getCommonLabels() const { return (nlabels_); }
169 : : /// Returns the NameRelation of the comparison result
170 : 0 : NameRelation getRelation() const { return (relation_); }
171 : : //@}
172 : : private:
173 : : int order_;
174 : : unsigned int nlabels_;
175 : : NameRelation relation_;
176 : : };
177 : :
178 : : ///
179 : : /// The \c Name class encapsulates DNS names.
180 : : ///
181 : : /// It provides interfaces to construct a name from string or wire-format %data,
182 : : /// transform a name into a string or wire-format %data, compare two names, get
183 : : /// access to various properties of a name, etc.
184 : : ///
185 : : /// Notes to developers: Internally, a name object maintains the name %data
186 : : /// in wire format as an instance of \c std::string. Since many string
187 : : /// implementations adopt copy-on-write %data sharing, we expect this approach
188 : : /// will make copying a name less expensive in typical cases. If this is
189 : : /// found to be a significant performance bottleneck later, we may reconsider
190 : : /// the internal representation or perhaps the API.
191 : : ///
192 : : /// A name object also maintains a vector of offsets (\c offsets_ member),
193 : : /// each of which is the offset to a label of the name: The n-th element of
194 : : /// the vector specifies the offset to the n-th label. For example, if the
195 : : /// object represents "www.example.com", the elements of the offsets vector
196 : : /// are 0, 4, 12, and 16. Note that the offset to the trailing dot (16) is
197 : : /// included. In the BIND9 DNS library from which this implementation is
198 : : /// derived, the offsets are optional, probably due to performance
199 : : /// considerations (in fact, offsets can always be calculated from the name
200 : : /// %data, and in that sense are redundant). In our implementation, however,
201 : : /// we always build and maintain the offsets. We believe we need more low
202 : : /// level, specialized %data structure and interface where we really need to
203 : : /// pursue performance, and would rather keep this generic API and
204 : : /// implementation simpler.
205 : : ///
206 : : /// While many other DNS APIs introduce an "absolute or relative"
207 : : /// attribute of names as defined in RFC1035, names are always "absolute" in
208 : : /// the initial design of this API.
209 : : /// In fact, separating absolute and relative would confuse API users
210 : : /// unnecessarily. For example, it's not so intuitive to consider the
211 : : /// comparison result of an absolute name with a relative name.
212 : : /// We've looked into how the concept of absolute names is used in BIND9,
213 : : /// and found that in many cases names are generally absolute.
214 : : /// The only reasonable case of separating absolute and relative is in a master
215 : : /// file parser, where a relative name must be a complete name with an "origin"
216 : : /// name, which must be absolute. So, in this initial design, we chose a
217 : : /// simpler approach: the API generally handles names as absolute; when we
218 : : /// introduce a parser of master files, we'll introduce the notion of relative
219 : : /// names as a special case.
220 : : ///
221 [ + - ][ + + ]: 537958 : class Name {
[ + - + ]
[ + - ]
222 : : // LabelSequences use knowledge about the internal data structure
223 : : // of this class for efficiency (they use the offsets_ vector and
224 : : // the ndata_ string)
225 : : friend class LabelSequence;
226 : :
227 : : ///
228 : : /// \name Constructors and Destructor
229 : : ///
230 : : //@{
231 : : private:
232 : : /// The default constructor
233 : : ///
234 : : /// This is used internally in the class implementation, but at least at
235 : : /// the moment defined as private because it will construct an incomplete
236 : : /// object in that it doesn't have any labels. We may reconsider this
237 : : /// design choice as we see more applications of the class.
238 : 96195 : Name() : length_(0), labelcount_(0) {}
239 : : public:
240 : : /// Constructor from a string
241 : : ///
242 : : /// If the given string does not represent a valid DNS name, an exception
243 : : /// of class \c EmptyLabel, \c TooLongLabel, \c BadLabelType, \c BadEscape,
244 : : /// \c TooLongName, or \c IncompleteName will be thrown.
245 : : /// In addition, if resource allocation for the new name fails, a
246 : : /// corresponding standard exception will be thrown.
247 : : ///
248 : : /// \param namestr A string representation of the name to be constructed.
249 : : /// \param downcase Whether to convert upper case alphabets to lower case.
250 : : explicit Name(const std::string& namestr, bool downcase = false);
251 : : /// Constructor from wire-format %data.
252 : : ///
253 : : /// The \c buffer parameter normally stores a complete DNS message
254 : : /// containing the name to be constructed. The current read position of
255 : : /// the buffer points to the head of the name.
256 : : ///
257 : : /// The input %data may or may not be compressed; if it's compressed, this
258 : : /// method will automatically decompress it.
259 : : ///
260 : : /// If the given %data does not represent a valid DNS name, an exception
261 : : /// of class \c DNSMessageFORMERR will be thrown.
262 : : /// In addition, if resource allocation for the new name fails, a
263 : : /// corresponding standard exception will be thrown.
264 : : ///
265 : : /// \param buffer A buffer storing the wire format %data.
266 : : /// \param downcase Whether to convert upper case alphabets to lower case.
267 : : explicit Name(isc::util::InputBuffer& buffer, bool downcase = false);
268 : : ///
269 : : /// We use the default copy constructor intentionally.
270 : : //@}
271 : : /// We use the default copy assignment operator intentionally.
272 : : ///
273 : :
274 : : ///
275 : : /// \name Getter Methods
276 : : ///
277 : : //@{
278 : : /// \brief Provides one-byte name %data in wire format at the specified
279 : : /// position.
280 : : ///
281 : : /// This method returns the unsigned 8-bit value of wire-format \c Name
282 : : /// %data at the given position from the head.
283 : : ///
284 : : /// For example, if \c n is a \c Name object for "example.com",
285 : : /// \c n.at(3) would return \c 'a', and \c n.at(7) would return \c 'e'.
286 : : /// Note that \c n.at(0) would be 7 (decimal), the label length of
287 : : /// "example", instead of \c 'e', because it returns a %data portion
288 : : /// in wire-format. Likewise, \c n.at(8) would return 3 (decimal)
289 : : /// instead of <code>'.'</code>
290 : : ///
291 : : /// This method would be useful for an application to examine the
292 : : /// wire-format name %data without dumping the %data into a buffer,
293 : : /// which would involve %data copies and would be less efficient.
294 : : /// One common usage of this method would be something like this:
295 : : /// \code for (size_t i = 0; i < name.getLength(); ++i) {
296 : : /// uint8_t c = name.at(i);
297 : : /// // do something with c
298 : : /// } \endcode
299 : : ///
300 : : /// Parameter \c pos must be in the valid range of the name %data, that is,
301 : : /// must be less than \c Name.getLength(). Otherwise, an exception of
302 : : /// class \c OutOfRange will be thrown.
303 : : /// This method never throws an exception in other ways.
304 : : ///
305 : : /// \param pos The position in the wire format name %data to be returned.
306 : : /// \return An unsigned 8-bit integer corresponding to the name %data
307 : : /// at the position of \c pos.
308 : 84422 : uint8_t at(size_t pos) const
309 : : {
310 [ + + ]: 84422 : if (pos >= length_) {
311 [ + - ]: 6 : isc_throw(OutOfRange, "Out of range access in Name::at()");
312 : : }
313 : 84419 : return (ndata_[pos]);
314 : : }
315 : :
316 : : /// \brief Gets the length of the <code>Name</code> in its wire format.
317 : : ///
318 : : /// This method never throws an exception.
319 : : ///
320 : : /// \return the length (the number of octets in wire format) of the
321 : : /// <code>Name</code>
322 : 0 : size_t getLength() const { return (length_); }
323 : :
324 : : /// \brief Returns the number of labels contained in the <code>Name</code>.
325 : : ///
326 : : /// Note that an empty label (corresponding to a trailing '.') is counted
327 : : /// as a single label, so the return value of this method must be >0.
328 : : ///
329 : : /// This method never throws an exception.
330 : : ///
331 : : /// \return the number of labels
332 : 0 : unsigned int getLabelCount() const { return (labelcount_); }
333 : : //@}
334 : :
335 : : ///
336 : : /// \name Converter methods
337 : : ///
338 : : //@{
339 : : /// \brief Convert the Name to a string.
340 : : ///
341 : : /// This method returns a <code>std::string</code> object representing the
342 : : /// Name as a string. Unless <code>omit_final_dot</code> is
343 : : /// <code>true</code>, the returned string ends with a dot '.'; the default
344 : : /// is <code>false</code>. The default value of this parameter is
345 : : /// <code>true</code>; converted names will have a trailing dot by default.
346 : : ///
347 : : /// This function assumes the name is in proper uncompressed wire format.
348 : : /// If it finds an unexpected label character including compression pointer,
349 : : /// an exception of class \c BadLabelType will be thrown.
350 : : /// In addition, if resource allocation for the result string fails, a
351 : : /// corresponding standard exception will be thrown.
352 : : //
353 : : /// \param omit_final_dot whether to omit the trailing dot in the output.
354 : : /// \return a string representation of the <code>Name</code>.
355 : : std::string toText(bool omit_final_dot = false) const;
356 : :
357 : : /// \brief Render the <code>Name</code> in the wire format with compression.
358 : : ///
359 : : /// This method dumps the Name in wire format with help of \c renderer,
360 : : /// which encapsulates output buffer and name compression algorithm to
361 : : /// render the name.
362 : : ///
363 : : /// If resource allocation in rendering process fails, a corresponding
364 : : /// standard exception will be thrown.
365 : : ///
366 : : /// \param renderer DNS message rendering context that encapsulates the
367 : : /// output buffer and name compression information.
368 : : void toWire(AbstractMessageRenderer& renderer) const;
369 : :
370 : : /// \brief Render the <code>Name</code> in the wire format without
371 : : /// compression.
372 : : ///
373 : : /// If resource allocation in rendering process fails, a corresponding
374 : : /// standard exception will be thrown. This can be avoided by preallocating
375 : : /// a sufficient size of \c buffer. Specifically, if
376 : : /// <code>buffer.getCapacity() - buffer.getLength() >= Name::MAX_WIRE</code>
377 : : /// then this method should not throw an exception.
378 : : ///
379 : : /// \param buffer An output buffer to store the wire %data.
380 : : void toWire(isc::util::OutputBuffer& buffer) const;
381 : : //@}
382 : :
383 : : ///
384 : : /// \name Comparison methods
385 : : ///
386 : : //@{
387 : : /// \brief Compare two <code>Name</code>s.
388 : : ///
389 : : /// This method compares the <code>Name</code> and <code>other</code> and
390 : : /// returns the result in the form of a <code>NameComparisonResult</code>
391 : : /// object.
392 : : ///
393 : : /// Note that this is case-insensitive comparison.
394 : : ///
395 : : /// This method never throws an exception.
396 : : ///
397 : : /// \param other the right-hand operand to compare against.
398 : : /// \return a <code>NameComparisonResult</code> object representing the
399 : : /// comparison result.
400 : : NameComparisonResult compare(const Name& other) const;
401 : :
402 : : /// \brief Return true iff two names are equal.
403 : : ///
404 : : /// Semantically this could be implemented based on the result of the
405 : : /// \c compare() method, but the actual implementation uses different code
406 : : /// that simply performs character-by-character comparison (case
407 : : /// insensitive for the name label parts) on the two names. This is because
408 : : /// it would be much faster and the simple equality check would be pretty
409 : : /// common.
410 : : ///
411 : : /// This method never throws an exception.
412 : : ///
413 : : /// \param other the <code>Name</code> object to compare against.
414 : : /// \return true if the two names are equal; otherwise false.
415 : : bool equals(const Name& other) const;
416 : :
417 : : /// Same as equals()
418 [ + - ][ + - ]: 12275 : bool operator==(const Name& other) const { return (equals(other)); }
[ + - ][ + - ]
[ + - ][ # # ]
[ + + ][ + + ]
[ + ][ - ]
[ + - + ][ - ]
[ + - ][ + - ]
419 : :
420 : : /// \brief Return true iff two names are not equal.
421 : : ///
422 : : /// This method simply negates the result of \c equal() method, and in that
423 : : /// sense it's redundant. The separate method is provided just for
424 : : /// convenience.
425 [ + + ][ + - ]: 12575 : bool nequals(const Name& other) const { return (!(equals(other))); }
[ - ][ + - ]
[ + - ][ + - ]
[ + - ]
426 : :
427 : : /// Same as nequals()
428 : : bool operator!=(const Name& other) const { return (nequals(other)); }
429 : :
430 : : /// \brief Less-than or equal comparison for Name against <code>other</code>
431 : : ///
432 : : /// The comparison is based on the result of the \c compare() method.
433 : : ///
434 : : /// This method never throws an exception.
435 : : ///
436 : : /// \param other the <code>Name</code> object to compare against.
437 : : /// \return true if <code>compare(other).getOrder() <= 0</code>;
438 : : /// otherwise false.
439 : : bool leq(const Name& other) const;
440 : :
441 : : /// Same as leq()
442 : 6 : bool operator<=(const Name& other) const { return (leq(other)); }
443 : :
444 : : /// \brief Greater-than or equal comparison for Name against
445 : : /// <code>other</code>
446 : : ///
447 : : /// The comparison is based on the result of the \c compare() method.
448 : : ///
449 : : /// This method never throws an exception.
450 : : ///
451 : : /// \param other the <code>Name</code> object to compare against.
452 : : /// \return true if <code>compare(other).getOrder() >= 0</code>;
453 : : /// otherwise false.
454 : : bool geq(const Name& other) const;
455 : :
456 : : /// Same as geq()
457 : 6 : bool operator>=(const Name& other) const { return (geq(other)); }
458 : :
459 : : /// \brief Less-than comparison for Name against <code>other</code>
460 : : ///
461 : : /// The comparison is based on the result of the \c compare() method.
462 : : ///
463 : : /// This method never throws an exception.
464 : : ///
465 : : /// \param other the <code>Name</code> object to compare against.
466 : : /// \return true if <code>compare(other).getOrder() < 0</code>;
467 : : /// otherwise false.
468 : : bool lthan(const Name& other) const;
469 : :
470 : : /// Same as lthan()
471 [ # # ][ + - ]: 44378 : bool operator<(const Name& other) const { return (lthan(other)); }
[ + - ]
472 : :
473 : : /// \brief Greater-than comparison for Name against <code>other</code>
474 : : ///
475 : : /// The comparison is based on the result of the \c compare() method.
476 : : ////
477 : : /// This method never throws an exception.
478 : : ///
479 : : /// \param other the <code>Name</code> object to compare against.
480 : : /// \return true if <code>compare(other).getOrder() > 0</code>;
481 : : /// otherwise false.
482 : : bool gthan(const Name& other) const;
483 : :
484 : : /// Same as gthan()
485 [ + - ][ + - ]: 8 : bool operator>(const Name& other) const { return (gthan(other)); }
486 : : //@}
487 : :
488 : : ///
489 : : /// \name Transformer methods
490 : : ///
491 : : //@{
492 : : /// \brief Extract a specified subpart of Name.
493 : : ///
494 : : /// <code>name.split(first, n)</code> constructs a new name starting from
495 : : /// the <code>first</code>-th label of the \c name, and subsequent \c n
496 : : /// labels including the \c first one. Since names in this current
497 : : /// implementation are always "absolute", if the specified range doesn't
498 : : /// contain the trailing dot of the original \c name, then a dot will be
499 : : /// appended to the resulting name. As a result, the number of labels
500 : : /// will be <code>n + 1</code>, rather than \c n. For example,
501 : : /// when \c n is <code>Name("www.example.com")</code>,
502 : : /// both <code>n.split(1, 2)</code> and <code>n.split(1, 3)</code>
503 : : /// will produce a name corresponding to "example.com.", which has 3 labels.
504 : : /// Note also that labels are counted from 0, and so <code>first = 1</code>
505 : : /// in this example specified the label "example", not "www".
506 : : ///
507 : : /// Parameter \c n must be larger than 0, and the range specified by
508 : : /// \c first and \c n must not exceed the valid range of the original name;
509 : : /// otherwise, an exception of class \c OutOfRange will be thrown.
510 : : ///
511 : : /// Note to developers: we may want to have different versions (signatures)
512 : : /// of this method. For example, we want to split the Name based on a given
513 : : /// suffix name.
514 : : ///
515 : : /// \param first The start position (in labels) of the extracted name
516 : : /// \param n Number of labels of the extracted name
517 : : /// \return A new Name object based on the Name containing <code>n</code>
518 : : /// labels including and following the <code>first</code> label.
519 : : Name split(unsigned int first, unsigned int n) const;
520 : :
521 : : /// \brief Extract a specified super domain name of Name.
522 : : ///
523 : : /// This function constructs a new \c Name object that is a super domain
524 : : /// of \c this name.
525 : : /// The new name is \c level labels upper than \c this name.
526 : : /// For example, when \c name is www.example.com,
527 : : /// <code>name.split(1)</code> will return a \c Name object for example.com.
528 : : /// \c level can be 0, in which case this method returns a copy of
529 : : /// \c this name.
530 : : /// The possible maximum value for \c level is
531 : : /// <code>this->getLabelCount()-1</code>, in which case this method
532 : : /// returns a root name.
533 : : ///
534 : : /// One common expected usage of this method is to iterate over super
535 : : /// domains of a given name, label by label, as shown in the following
536 : : /// sample code:
537 : : /// \code // if name is www.example.com...
538 : : /// for (int i = 0; i < name.getLabelCount(); ++i) {
539 : : /// Name upper_name(name.split(i));
540 : : /// // upper_name'll be www.example.com., example.com., com., and then .
541 : : /// }
542 : : /// \endcode
543 : : ///
544 : : /// \c level must be smaller than the number of labels of \c this name;
545 : : /// otherwise an exception of class \c OutOfRange will be thrown.
546 : : /// In addition, if resource allocation for the new name fails, a
547 : : /// corresponding standard exception will be thrown.
548 : : ///
549 : : /// Note to developers: probably as easily imagined, this method is a
550 : : /// simple wrapper to one usage of the other
551 : : /// <code>split(unsigned int, unsigned int) const</code> method and is
552 : : /// redundant in some sense.
553 : : /// We provide the "redundant" method for convenience, however, because
554 : : /// the expected usage shown above seems to be common, and the parameters
555 : : /// to the other \c split(unsigned int, unsigned int) const to implement
556 : : /// it may not be very intuitive.
557 : : ///
558 : : /// We are also aware that it is generally discouraged to add a public
559 : : /// member function that could be implemented using other member functions.
560 : : /// We considered making it a non member function, but we could not come
561 : : /// up with an intuitive function name to represent the specific service.
562 : : /// Some other BIND 10 developers argued, probably partly because of the
563 : : /// counter intuitive function name, a different signature of \c split
564 : : /// would be better to improve code readability.
565 : : /// While that may be a matter of personal preference, we accepted the
566 : : /// argument. One major goal of public APIs like this is wider acceptance
567 : : /// from internal/external developers, so unless there is a clear advantage
568 : : /// it would be better to respect the preference of the API users.
569 : : ///
570 : : /// Since this method doesn't have to be a member function in other way,
571 : : /// it is intentionally implemented only using public interfaces of the
572 : : /// \c Name class; it doesn't refer to private members of the class even if
573 : : /// it could.
574 : : /// This way we hope we can avoid damaging the class encapsulation,
575 : : /// which is a major drawback of public member functions.
576 : : /// As such if and when this "method" has to be extended, it should be
577 : : /// implemented without the privilege of being a member function unless
578 : : /// there is a very strong reason to do so. In particular a minor
579 : : /// performance advantage shouldn't justify that approach.
580 : : ///
581 : : /// \param level The number of labels to be removed from \c this name to
582 : : /// create the super domain name.
583 : : /// (0 <= \c level < <code>this->getLabelCount()</code>)
584 : : /// \return A new \c Name object to be created.
585 : : Name split(unsigned int level) const;
586 : :
587 : : /// \brief Reverse the labels of a name
588 : : ///
589 : : /// This method reverses the labels of a name. For example, if
590 : : /// \c this is "www.example.com.", this method will return
591 : : /// "com.example.www." (This is useful because DNSSEC sort order
592 : : /// is equivalent to a lexical sort of label-reversed names.)
593 : : Name reverse() const;
594 : :
595 : : /// \brief Concatenate two names.
596 : : ///
597 : : /// This method appends \c suffix to \c this Name. The trailing dot of
598 : : /// \c this Name will be removed. For example, if \c this is "www."
599 : : /// and \c suffix is "example.com.", a successful return of this method
600 : : /// will be a name of "www.example.com."
601 : : ///
602 : : ///The resulting length of the concatenated name must not exceed
603 : : /// \c Name::MAX_WIRE; otherwise an exception of class
604 : : /// \c TooLongName will be thrown.
605 : : ///
606 : : /// \param suffix a Name object to be appended to the Name.
607 : : /// \return a new Name object concatenating \c suffix to \c this Name.
608 : : Name concatenate(const Name& suffix) const;
609 : :
610 : : /// \brief Downcase all upper case alphabet characters in the name.
611 : : ///
612 : : /// This method modifies the calling object so that it can perform the
613 : : /// conversion as fast as possible and can be exception free.
614 : : ///
615 : : /// The return value of this version of \c downcase() is a reference to
616 : : /// the calling object (i.e., \c *this) so that the caller can use the
617 : : /// result of downcasing in a single line. For example, if variable
618 : : /// \c n is a \c Name class object possibly containing upper case
619 : : /// characters, and \c b is an \c OutputBuffer class object, then the
620 : : /// following code will dump the name in wire format to \c b with
621 : : /// downcasing upper case characters:
622 : : ///
623 : : /// \code n.downcase().toWire(b); \endcode
624 : : ///
625 : : /// Since this method modifies the calling object, a \c const name object
626 : : /// cannot call it. If \c n is a \c const Name class object, it must first
627 : : /// be copied to a different object and the latter must be used for the
628 : : /// downcase modification.
629 : : ///
630 : : /// \return A reference to the calling object with being downcased.
631 : : Name& downcase();
632 : : //@}
633 : :
634 : : ///
635 : : /// \name Testing methods
636 : : ///
637 : : //@{
638 : : /// \brief Test if this is a wildcard name.
639 : : ///
640 : : /// \return \c true if the least significant label of this Name is
641 : : /// <code>'*'</code>; otherwise \c false.
642 : : bool isWildcard() const;
643 : : //@}
644 : :
645 : : ///
646 : : /// \name Protocol constants
647 : : ///
648 : : //@{
649 : : /// \brief Max allowable length of domain names.
650 : : static const size_t MAX_WIRE = 255;
651 : :
652 : : /// \brief Max allowable labels of domain names.
653 : : ///
654 : : /// This is <code>ceil(MAX_WIRE / 2)</code>, and is equal to the number of
655 : : /// labels of name "a.a.a.a....a." (127 "a"'s and trailing dot).
656 : : static const size_t MAX_LABELS = 128;
657 : :
658 : : /// \brief Max allowable length of labels of a domain name.
659 : : static const size_t MAX_LABELLEN = 63;
660 : :
661 : : /// \brief Max possible pointer value for name compression.
662 : : ///
663 : : /// This is the highest number of 14-bit unsigned integer. Name compression
664 : : /// pointers are identified as a 2-byte value starting with the upper two
665 : : /// bit being 11.
666 : : static const uint16_t MAX_COMPRESS_POINTER = 0x3fff;
667 : : /// \brief A 8-bit masked value indicating a start of compression pointer.
668 : : static const uint16_t COMPRESS_POINTER_MARK8 = 0xc0;
669 : : /// \brief A 16-bit masked value indicating a start of compression pointer.
670 : : static const uint16_t COMPRESS_POINTER_MARK16 = 0xc000;
671 : : //@}
672 : :
673 : : ///
674 : : /// \name Well-known name constants
675 : : ///
676 : : //@{
677 : : /// \brief Root name (i.e. ".").
678 : : static const Name& ROOT_NAME();
679 : : //@}
680 : :
681 : : private:
682 : : std::string ndata_;
683 : : std::vector<unsigned char> offsets_;
684 : : unsigned int length_;
685 : : unsigned int labelcount_;
686 : : };
687 : :
688 : : inline const Name&
689 : 985 : Name::ROOT_NAME() {
690 [ + + ][ + - ]: 985 : static Name root_name(".");
[ + - ][ + - ]
691 : 985 : return (root_name);
692 : : }
693 : :
694 : : ///
695 : : /// \brief Insert the name as a string into stream.
696 : : ///
697 : : /// This method convert the \c name into a string and inserts it into the
698 : : /// output stream \c os.
699 : : ///
700 : : /// This function overloads the global operator<< to behave as described in
701 : : /// ostream::operator<< but applied to \c Name objects.
702 : : ///
703 : : /// \param os A \c std::ostream object on which the insertion operation is
704 : : /// performed.
705 : : /// \param name The \c Name object output by the operation.
706 : : /// \return A reference to the same \c std::ostream object referenced by
707 : : /// parameter \c os after the insertion operation.
708 : : std::ostream&
709 : : operator<<(std::ostream& os, const Name& name);
710 : : }
711 : : }
712 : : #endif // __NAME_H
713 : :
714 : : // Local Variables:
715 : : // mode: c++
716 : : // End:
|