blob: 6797e3c5989d0c95cc4a440263c25161145f4aca [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
6#define QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
7
8#include <limits>
9#include <ostream>
10
11#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
16
17namespace quic {
18
19// QuicPacketNumber can either initialized or uninitialized. An initialized
20// packet number is simply an ordinal number. A sentinel value is used to
21// represent an uninitialized packet number.
22class QUIC_EXPORT_PRIVATE QuicPacketNumber {
23 public:
24 // Construct an uninitialized packet number.
25 QuicPacketNumber();
26 // Construct a packet number from uint64_t. |packet_number| cannot equal the
27 // sentinel value.
28 explicit QuicPacketNumber(uint64_t packet_number);
29
30 // Packet number becomes uninitialized after calling this function.
31 void Clear();
32
33 // REQUIRES: IsInitialized() == true.
34 uint64_t Hash() const;
35
36 // Converts packet number to uint64_t.
37 // REQUIRES: IsInitialized() == true.
38 uint64_t ToUint64() const;
39
40 // Returns true if packet number is considered initialized.
41 bool IsInitialized() const;
42
43 // REQUIRES: IsInitialized() == true && ToUint64() <
44 // numeric_limits<uint64_t>::max() - 1.
45 QuicPacketNumber& operator++();
46 QuicPacketNumber operator++(int);
47 // REQUIRES: IsInitialized() == true && ToUint64() >= 1.
48 QuicPacketNumber& operator--();
49 QuicPacketNumber operator--(int);
50
51 // REQUIRES: IsInitialized() == true && numeric_limits<uint64_t>::max() -
52 // ToUint64() > |delta|.
53 QuicPacketNumber& operator+=(uint64_t delta);
54 // REQUIRES: IsInitialized() == true && ToUint64() >= |delta|.
55 QuicPacketNumber& operator-=(uint64_t delta);
56
57 QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
58 std::ostream& os,
59 const QuicPacketNumber& p);
60
61 private:
62 // All following operators REQUIRE operands.Initialized() == true.
63 friend inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs);
64 friend inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs);
65 friend inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs);
66 friend inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs);
67 friend inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs);
68 friend inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs);
69
70 // REQUIRES: numeric_limits<uint64_t>::max() - lhs.ToUint64() > |delta|.
71 friend inline QuicPacketNumber operator+(QuicPacketNumber lhs,
72 uint64_t delta);
73 // REQUIRES: lhs.ToUint64() >= |delta|.
74 friend inline QuicPacketNumber operator-(QuicPacketNumber lhs,
75 uint64_t delta);
76 // REQUIRES: lhs >= rhs.
77 friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs);
78
79 // The sentinel value representing an uninitialized packet number.
80 static uint64_t UninitializedPacketNumber();
81
82 uint64_t packet_number_;
83};
84
85class QuicPacketNumberHash {
86 public:
87 uint64_t operator()(QuicPacketNumber packet_number) const noexcept {
88 return packet_number.Hash();
89 }
90};
91
92inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs) {
93 DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
94 return lhs.packet_number_ == rhs.packet_number_;
95}
96
97inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
98 DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
99 return lhs.packet_number_ != rhs.packet_number_;
100}
101
102inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs) {
103 DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
104 return lhs.packet_number_ < rhs.packet_number_;
105}
106
107inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
108 DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
109 return lhs.packet_number_ <= rhs.packet_number_;
110}
111
112inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs) {
113 DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
114 return lhs.packet_number_ > rhs.packet_number_;
115}
116
117inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
118 DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
119 return lhs.packet_number_ >= rhs.packet_number_;
120}
121
122inline QuicPacketNumber operator+(QuicPacketNumber lhs, uint64_t delta) {
123#ifndef NDEBUG
124 DCHECK(lhs.IsInitialized());
125 if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
126 DCHECK_GT(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), delta);
127 } else {
128 DCHECK_GE(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), delta);
129 }
130#endif
131 return QuicPacketNumber(lhs.packet_number_ + delta);
132}
133
134inline QuicPacketNumber operator-(QuicPacketNumber lhs, uint64_t delta) {
135#ifndef NDEBUG
136 DCHECK(lhs.IsInitialized());
137 if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
138 DCHECK_GE(lhs.ToUint64(), delta);
139 } else {
140 DCHECK_GT(lhs.ToUint64(), delta);
141 }
142#endif
143 return QuicPacketNumber(lhs.packet_number_ - delta);
144}
145
146inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs) {
147 DCHECK(lhs.IsInitialized() && rhs.IsInitialized() && lhs >= rhs)
148 << lhs << " vs. " << rhs;
149 return lhs.packet_number_ - rhs.packet_number_;
150}
151
152} // namespace quic
153
154#endif // QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_