1 // Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef RRTTL_H
8 #define RRTTL_H 1
9 
10 #include <dns/exceptions.h>
11 
12 #include <boost/optional.hpp>
13 
14 #include <stdint.h>
15 
16 namespace isc {
17 namespace util {
18 class InputBuffer;
19 class OutputBuffer;
20 }
21 
22 namespace dns {
23 
24 // forward declarations
25 class AbstractMessageRenderer;
26 
27 ///
28 /// \brief A standard DNS module exception that is thrown if an RRTTL object
29 /// is being constructed from an unrecognized string.
30 ///
31 class InvalidRRTTL : public DNSTextError {
32 public:
InvalidRRTTL(const char * file,size_t line,const char * what)33     InvalidRRTTL(const char* file, size_t line, const char* what) :
34         DNSTextError(file, line, what) {}
35 };
36 
37 ///
38 /// \brief A standard DNS module exception that is thrown if an RRTTL object
39 /// is being constructed from a incomplete (too short) wire-format data.
40 ///
41 class IncompleteRRTTL : public isc::dns::Exception {
42 public:
IncompleteRRTTL(const char * file,size_t line,const char * what)43     IncompleteRRTTL(const char* file, size_t line, const char* what) :
44         isc::dns::Exception(file, line, what) {}
45 };
46 
47 ///
48 /// The \c RRTTL class encapsulates TTLs used in DNS resource records.
49 ///
50 /// This is a straightforward class; an \c RRTTL object simply maintains a
51 /// 32-bit unsigned integer corresponding to the TTL value.  The main purpose
52 /// of this class is to provide convenient interfaces to convert a textual
53 /// representation into the integer TTL value and vice versa, and to handle
54 /// wire-format representations.
55 class RRTTL {
56 public:
57     ///
58     /// \name Constructors, Factory and Destructor
59     ///
60     /// Note: We use the default copy constructor and the default copy
61     /// assignment operator intentionally.
62     //@{
63     /// Constructor from an integer TTL value.
64     ///
65     /// This constructor never throws an exception.
66     ///
67     /// \param ttlval An 32-bit integer of the RRTTL.
RRTTL(uint32_t ttlval)68     explicit RRTTL(uint32_t ttlval) : ttlval_(ttlval) {}
69 
70     /// Constructor from a string.
71     ///
72     /// It accepts either a decimal number, specifying number of seconds. Or,
73     /// it can be given a sequence of numbers and units, like "2H" (meaning
74     /// two hours), "1W3D" (one week and 3 days). The allowed units are W
75     /// (week), D (day), H (hour), M (minute) and S (second). They can be also
76     /// specified in lower-case. No further restrictions are checked (so they
77     /// can be specified in arbitrary order and even things like "1D1D" can
78     /// be used to specify two days).
79     ///
80     /// \param ttlstr A string representation of the \c RRTTL.
81     ///
82     /// \throw InvalidRRTTL in case the string is not recognized as valid
83     ///     TTL representation.
84     explicit RRTTL(const std::string& ttlstr);
85 
86     /// Constructor from wire-format data.
87     ///
88     /// The \c buffer parameter normally stores a complete DNS message
89     /// containing the RRTTL to be constructed.  The current read position of
90     /// the buffer points to the head of the type.
91     ///
92     /// If the given data does not large enough to contain a 16-bit integer,
93     /// an exception of class \c IncompleteRRTTL will be thrown.
94     ///
95     /// \param buffer A buffer storing the wire format data.
96     explicit RRTTL(isc::util::InputBuffer& buffer);
97 
98     /// A separate factory of RRTTL from text.
99     ///
100     /// This static method is similar to the constructor that takes a string
101     /// object, but works as a factory and reports parsing failure in the
102     /// form of the return value.  Normally the constructor version should
103     /// suffice, but in some cases the caller may have to expect mixture of
104     /// valid and invalid input, and may want to minimize the overhead of
105     /// possible exception handling.   This version is provided for such
106     /// purpose.
107     ///
108     /// If the given text represents a valid RRTTL, it returns a pointer
109     /// to a new RRTTL object. If the given text does not represent a
110     /// valid RRTTL, it returns \c NULL..
111     ///
112     /// One main purpose of this function is to minimize the overhead
113     /// when the given text does not represent a valid RR TTL.  For this
114     /// reason this function intentionally omits the capability of delivering
115     /// a detailed reason for the parse failure, such as in the \c want()
116     /// string when exception is thrown from the constructor (it will
117     /// internally require a creation of string object, which is relatively
118     /// expensive).  If such detailed information is necessary, the constructor
119     /// version should be used to catch the resulting exception.
120     ///
121     /// This function never throws the \c InvalidRRTTL exception.
122     ///
123     /// \param ttlstr A string representation of the \c RRTTL.
124     /// \return A new RRTTL object for the given text or a \c NULL value.
125     static RRTTL* createFromText(const std::string& ttlstr);
126     ///
127     //@}
128 
129     ///
130     /// \name Converter methods
131     ///
132     //@{
133     /// \brief Convert the \c RRTTL to a string.
134     ///
135     /// This version of implementation simply converts the TTL value into the
136     /// numeric textual representation.  We may introduce more human-readable
137     /// format depending on the context in future versions.
138     ///
139     /// If resource allocation in rendering process fails, a corresponding
140     /// standard exception will be thrown.
141     ///
142     /// \return A string representation of the \c RRTTL.
143     const std::string toText() const;
144     /// \brief Render the \c RRTTL in the wire format.
145     ///
146     /// This method renders the TTL value in network byte order via \c renderer,
147     /// which encapsulates output buffer and other rendering contexts.
148     ///
149     /// If resource allocation in rendering process fails, a corresponding
150     /// standard exception will be thrown.
151     ///
152     /// \param renderer DNS message rendering context that encapsulates the
153     /// output buffer in which the RRTTL is to be stored.
154     void toWire(AbstractMessageRenderer& renderer) const;
155     /// \brief Render the \c RRTTL in the wire format.
156     ///
157     /// This method renders the TTL value in network byte order into the
158     /// \c buffer.
159     ///
160     /// If resource allocation in rendering process fails, a corresponding
161     /// standard exception will be thrown.
162     ///
163     /// \param buffer An output buffer to store the wire data.
164     void toWire(isc::util::OutputBuffer& buffer) const;
165     //@}
166 
167     ///
168     /// \name Getter Methods
169     ///
170     //@{
171     /// \brief Returns the TTL value as a 32-bit unsigned integer.
172     ///
173     /// This method never throws an exception.
174     ///
175     /// \return An 32-bit integer corresponding to the RRTTL.
getValue()176     uint32_t getValue() const { return (ttlval_); }
177     //@}
178 
179     ///
180     /// \name Comparison methods
181     ///
182     /// Comparison between two \c RRTTL objects is performed in a
183     /// straightforward way, that is, comparing the corresponding TTL values
184     /// (which is the result of the \c getValue() method) as 32-bit unsigned
185     /// integers.
186     //@{
187     /// \brief Return true iff two RRTTLs are equal.
188     ///
189     /// This method never throws an exception.
190     ///
191     /// \param other the \c RRTTL object to compare against.
equals(const RRTTL & other)192     bool equals(const RRTTL& other) const
193     { return (ttlval_ == other.ttlval_); }
194     /// \brief Same as \c equals().
195     bool operator==(const RRTTL& other) const
196     { return (ttlval_ == other.ttlval_); }
197     /// \brief Return true iff two RRTTLs are not equal.
198     ///
199     /// This method never throws an exception.
200     ///
201     /// \param other the \c RRTTL object to compare against.
nequals(const RRTTL & other)202     bool nequals(const RRTTL& other) const
203     { return (ttlval_ != other.ttlval_); }
204     /// \brief Same as \c nequals().
205     bool operator!=(const RRTTL& other) const
206     { return (ttlval_ != other.ttlval_); }
207     /// \brief Less-than or equal comparison for RRTTL against \c other.
208     ///
209     /// This method never throws an exception.
210     ///
211     /// \param other the \c RRTTL object to compare against.
212     /// \return true if \c this RRTTL is less than or equal to the \c other;
213     /// otherwise false.
leq(const RRTTL & other)214     bool leq(const RRTTL& other) const
215     { return (ttlval_ <= other.ttlval_); }
216 
217     /// Same as \c leq()
218     bool operator<=(const RRTTL& other) const
219     { return (ttlval_ <= other.ttlval_); }
220 
221     /// \brief Greater-than or equal comparison for RRTTL against \c other.
222     ///
223     /// This method never throws an exception.
224     ///
225     /// \param other the \c RRTTL object to compare against.
226     /// \return true if \c this RRTTL is greater than or equal to the \c other;
227     /// otherwise false.
geq(const RRTTL & other)228     bool geq(const RRTTL& other) const
229     { return (ttlval_ >= other.ttlval_); }
230 
231     /// Same as \c geq()
232     bool operator>=(const RRTTL& other) const
233     { return (ttlval_ >= other.ttlval_); }
234 
235     /// \brief Less-than comparison for RRTTL against \c other.
236     ///
237     /// This method never throws an exception.
238     ///
239     /// \param other the \c RRTTL object to compare against.
240     /// \return true if \c this RRTTL is less than the \c other;
241     /// otherwise false.
lthan(const RRTTL & other)242     bool lthan(const RRTTL& other) const
243     { return (ttlval_ < other.ttlval_); }
244 
245     /// Same as \c lthan()
246     bool operator<(const RRTTL& other) const
247     { return (ttlval_ < other.ttlval_); }
248 
249     /// \brief Greater-than comparison for RRTTL against \c other.
250     ///
251     /// This method never throws an exception.
252     ///
253     /// \param other the \c RRTTL object to compare against.
254     /// \return true if \c this RRTTL is greater than the \c other;
255     /// otherwise false.
gthan(const RRTTL & other)256     bool gthan(const RRTTL& other) const
257     { return (ttlval_ > other.ttlval_); }
258 
259     /// Same as \c gthan()
260     bool operator>(const RRTTL& other) const
261     { return (ttlval_ > other.ttlval_); }
262     //@}
263 
264     ///
265     /// \name Protocol constants
266     ///
267     //@{
268     /// \brief The TTL of the max allowable value, per RFC2181 Section 8.
269     ///
270     /// The max value is the largest unsigned 31 bit integer, 2^31-1.
271     ///
272     /// \note At the moment an RRTTL object can have a value larger than
273     /// this limit.  We may revisit it in a future version.
MAX_TTL()274     static const RRTTL& MAX_TTL() {
275         static const RRTTL max_ttl(0x7fffffff);
276         return (max_ttl);
277     }
278     //@}
279 
280 private:
281     uint32_t ttlval_;
282 };
283 
284 ///
285 /// \brief Insert the \c RRTTL as a string into stream.
286 ///
287 /// This method convert the \c rrttl into a string and inserts it into the
288 /// output stream \c os.
289 ///
290 /// This function overloads the global operator<< to behave as described in
291 /// ostream::operator<< but applied to \c RRTTL objects.
292 ///
293 /// \param os A \c std::ostream object on which the insertion operation is
294 /// performed.
295 /// \param rrttl The \c RRTTL object output by the operation.
296 /// \return A reference to the same \c std::ostream object referenced by
297 /// parameter \c os after the insertion operation.
298 std::ostream&
299 operator<<(std::ostream& os, const RRTTL& rrttl);
300 }
301 }
302 #endif  // RRTTL_H
303 
304 // Local Variables:
305 // mode: c++
306 // End:
307