summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_number.h
blob: 8d6b1b63a5d728670619321f2e20c314ee987901 (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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
#define QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_

#include <limits>
#include <ostream>
#include <string>

#include "quiche/quic/platform/api/quic_export.h"
#include "quiche/quic/platform/api/quic_logging.h"

namespace quic {

// QuicPacketNumber can either initialized or uninitialized. An initialized
// packet number is simply an ordinal number. A sentinel value is used to
// represent an uninitialized packet number.
class QUIC_EXPORT_PRIVATE QuicPacketNumber {
 public:
  // Construct an uninitialized packet number.
  constexpr QuicPacketNumber() : packet_number_(UninitializedPacketNumber()) {}

  // Construct a packet number from uint64_t. |packet_number| cannot equal the
  // sentinel value.
  explicit constexpr QuicPacketNumber(uint64_t packet_number)
      : packet_number_(packet_number) {
    QUICHE_DCHECK_NE(UninitializedPacketNumber(), packet_number)
        << "Use default constructor for uninitialized packet number";
  }

  // The sentinel value representing an uninitialized packet number.
  static constexpr uint64_t UninitializedPacketNumber() {
    return std::numeric_limits<uint64_t>::max();
  }

  // Packet number becomes uninitialized after calling this function.
  void Clear();

  // Updates this packet number to be |new_value| if it is greater than current
  // value.
  void UpdateMax(QuicPacketNumber new_value);

  // REQUIRES: IsInitialized() == true.
  uint64_t Hash() const;

  // Converts packet number to uint64_t.
  // REQUIRES: IsInitialized() == true.
  uint64_t ToUint64() const;

  // Returns true if packet number is considered initialized.
  bool IsInitialized() const;

  // REQUIRES: IsInitialized() == true && ToUint64() <
  // numeric_limits<uint64_t>::max() - 1.
  QuicPacketNumber& operator++();
  QuicPacketNumber operator++(int);
  // REQUIRES: IsInitialized() == true && ToUint64() >= 1.
  QuicPacketNumber& operator--();
  QuicPacketNumber operator--(int);

  // REQUIRES: IsInitialized() == true && numeric_limits<uint64_t>::max() -
  // ToUint64() > |delta|.
  QuicPacketNumber& operator+=(uint64_t delta);
  // REQUIRES: IsInitialized() == true && ToUint64() >= |delta|.
  QuicPacketNumber& operator-=(uint64_t delta);

  // Human-readable representation suitable for logging.
  std::string ToString() const;

  QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
      std::ostream& os, const QuicPacketNumber& p);

 private:
  // All following operators REQUIRE operands.Initialized() == true.
  friend inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs);
  friend inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs);
  friend inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs);
  friend inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs);
  friend inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs);
  friend inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs);

  // REQUIRES: numeric_limits<uint64_t>::max() - lhs.ToUint64() > |delta|.
  friend inline QuicPacketNumber operator+(QuicPacketNumber lhs,
                                           uint64_t delta);
  // REQUIRES: lhs.ToUint64() >= |delta|.
  friend inline QuicPacketNumber operator-(QuicPacketNumber lhs,
                                           uint64_t delta);
  // REQUIRES: lhs >= rhs.
  friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs);

  uint64_t packet_number_;
};

class QUIC_EXPORT_PRIVATE QuicPacketNumberHash {
 public:
  uint64_t operator()(QuicPacketNumber packet_number) const noexcept {
    return packet_number.Hash();
  }
};

inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ == rhs.packet_number_;
}

inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ != rhs.packet_number_;
}

inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ < rhs.packet_number_;
}

inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ <= rhs.packet_number_;
}

inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ > rhs.packet_number_;
}

inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized())
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ >= rhs.packet_number_;
}

inline QuicPacketNumber operator+(QuicPacketNumber lhs, uint64_t delta) {
#ifndef NDEBUG
  QUICHE_DCHECK(lhs.IsInitialized());
  QUICHE_DCHECK_GT(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(),
                   delta);
#endif
  return QuicPacketNumber(lhs.packet_number_ + delta);
}

inline QuicPacketNumber operator-(QuicPacketNumber lhs, uint64_t delta) {
#ifndef NDEBUG
  QUICHE_DCHECK(lhs.IsInitialized());
  QUICHE_DCHECK_GE(lhs.ToUint64(), delta);
#endif
  return QuicPacketNumber(lhs.packet_number_ - delta);
}

inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs) {
  QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized() && lhs >= rhs)
      << lhs << " vs. " << rhs;
  return lhs.packet_number_ - rhs.packet_number_;
}

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_