summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/serial.h
blob: 7c7e3381b0a46f265ba19dbb11cc06d5a342bfb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (C) 2011-2015,2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef SERIAL_H
#define SERIAL_H 1

#include <stdint.h>
#include <iostream>

namespace isc {
namespace dns {

/// The maximum difference between two serial numbers. If the (plain uint32_t)
/// difference between two serials is greater than this number, the smaller one
/// is considered greater.
const uint32_t MAX_SERIAL_INCREMENT = 2147483647;

/// Maximum value a serial can have, used in + operator.
const uint64_t MAX_SERIAL_VALUE = 4294967296ull;

/// \brief This class defines DNS serial numbers and serial arithmetic.
///
/// DNS Serial number are in essence unsigned 32-bits numbers, with one
/// catch; they should be compared using sequence space arithmetic.
/// So given that they are 32-bits; as soon as the difference between two
/// serial numbers is greater than 2147483647 (2^31 - 1), the lower number
/// (in plain comparison) is considered the higher one.
///
/// In order to do this as transparently as possible, these numbers are
/// stored in the Serial class, which overrides the basic comparison operators.
///
/// In this specific context, these operations are called 'serial number
/// arithmetic', and they are defined in RFC 1982.
///
/// \note RFC 1982 defines everything based on the value SERIAL_BITS. Since
/// the serial number has a fixed length of 32 bits, the values we use are
/// hard-coded, and not computed based on variable bit lengths.
class Serial {
public:
    /// \brief Constructor with value
    ///
    /// \param value The uint32_t value of the serial
    explicit Serial(uint32_t value) : value_(value) {}

    /// \brief Copy constructor
    Serial(const Serial& other) : value_(other.getValue()) {}

    /// \brief Direct assignment from other Serial
    ///
    /// \param other The Serial to assign the value from
    Serial& operator=(const Serial& other) {
        value_ = other.getValue();
        return (*this);
    }

    /// \brief Direct assignment from value
    ///
    /// \param value the uint32_t value to assign
    void operator=(uint32_t value) { value_ = value; }

    /// \brief Returns the uint32_t representation of this serial value
    ///
    /// \return The uint32_t value of this Serial
    uint32_t getValue() const { return (value_); }

    /// \brief Returns true if the serial values are equal
    ///
    /// \return True if the values are equal
    bool operator==(const Serial& other) const;

    /// \brief Returns true if the serial values are not equal
    ///
    /// \return True if the values are not equal
    bool operator!=(const Serial& other) const;

    /// \brief Returns true if the serial value of this serial is smaller than
    /// the other, according to serial arithmetic as described in RFC 1982
    ///
    /// \param other The Serial to compare to
    ///
    /// \return True if this is smaller than the given value
    bool operator<(const Serial& other) const;

    /// \brief Returns true if the serial value of this serial is equal to or
    /// smaller than the other, according to serial arithmetic as described
    /// in RFC 1982
    ///
    /// \param other The Serial to compare to
    ///
    /// \return True if this is smaller than or equal to the given value
    bool operator<=(const Serial& other) const;

    /// \brief Returns true if the serial value of this serial is greater than
    /// the other, according to serial arithmetic as described in RFC 1982
    ///
    /// \param other The Serial to compare to
    ///
    /// \return True if this is greater than the given value
    bool operator>(const Serial& other) const;

    /// \brief Returns true if the serial value of this serial is equal to or
    /// greater than the other, according to serial arithmetic as described in
    /// RFC 1982
    ///
    /// \param other The Serial to compare to
    ///
    /// \return True if this is greater than or equal to the given value
    bool operator>=(const Serial& other) const;

    /// \brief Adds the given value to the serial number. If this would make
    /// the number greater than 2^32-1, it is 'wrapped'.
    /// \note According to the specification, an addition greater than
    /// MAX_SERIAL_INCREMENT is undefined. We do NOT catch this error (so as not
    /// to raise exceptions), but this behaviour remains undefined.
    ///
    /// \param other The Serial to add
    ///
    /// \return The result of the addition
    Serial operator+(const Serial& other) const;

    /// \brief Adds the given value to the serial number. If this would make
    /// the number greater than 2^32-1, it is 'wrapped'.
    ///
    /// \note According to the specification, an addition greater than
    /// MAX_SERIAL_INCREMENT is undefined. We do NOT catch this error (so as not
    /// to raise exceptions), but this behaviour remains undefined.
    ///
    /// \param other_val The uint32_t value to add
    ///
    /// \return The result of the addition
    Serial operator+(uint32_t other_val) const;

private:
    uint32_t value_;
};

/// \brief Helper operator for output streams, writes the value to the stream
///
/// \param os The ostream to write to
/// \param serial The Serial to write
/// \return the output stream
std::ostream& operator<<(std::ostream& os, const Serial& serial);

} // end namespace dns
} // end namespace isc

#endif // SERIAL_H