1 // 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 #include <string> 11 12 #include "quiche/quic/platform/api/quic_export.h" 13 #include "quiche/quic/platform/api/quic_logging.h" 14 15 namespace quic { 16 17 // QuicPacketNumber can either initialized or uninitialized. An initialized 18 // packet number is simply an ordinal number. A sentinel value is used to 19 // represent an uninitialized packet number. 20 class QUICHE_EXPORT QuicPacketNumber { 21 public: 22 // Construct an uninitialized packet number. QuicPacketNumber()23 constexpr QuicPacketNumber() : packet_number_(UninitializedPacketNumber()) {} 24 25 // Construct a packet number from uint64_t. |packet_number| cannot equal the 26 // sentinel value. QuicPacketNumber(uint64_t packet_number)27 explicit constexpr QuicPacketNumber(uint64_t packet_number) 28 : packet_number_(packet_number) { 29 QUICHE_DCHECK_NE(UninitializedPacketNumber(), packet_number) 30 << "Use default constructor for uninitialized packet number"; 31 } 32 33 // The sentinel value representing an uninitialized packet number. UninitializedPacketNumber()34 static constexpr uint64_t UninitializedPacketNumber() { 35 return std::numeric_limits<uint64_t>::max(); 36 } 37 38 // Packet number becomes uninitialized after calling this function. 39 void Clear(); 40 41 // Updates this packet number to be |new_value| if it is greater than current 42 // value. 43 void UpdateMax(QuicPacketNumber new_value); 44 45 // REQUIRES: IsInitialized() == true. 46 uint64_t Hash() const; 47 48 // Converts packet number to uint64_t. 49 // REQUIRES: IsInitialized() == true. 50 uint64_t ToUint64() const; 51 52 // Returns true if packet number is considered initialized. 53 bool IsInitialized() const; 54 55 // REQUIRES: IsInitialized() == true && ToUint64() < 56 // numeric_limits<uint64_t>::max() - 1. 57 QuicPacketNumber& operator++(); 58 QuicPacketNumber operator++(int); 59 // REQUIRES: IsInitialized() == true && ToUint64() >= 1. 60 QuicPacketNumber& operator--(); 61 QuicPacketNumber operator--(int); 62 63 // REQUIRES: IsInitialized() == true && numeric_limits<uint64_t>::max() - 64 // ToUint64() > |delta|. 65 QuicPacketNumber& operator+=(uint64_t delta); 66 // REQUIRES: IsInitialized() == true && ToUint64() >= |delta|. 67 QuicPacketNumber& operator-=(uint64_t delta); 68 69 // Human-readable representation suitable for logging. 70 std::string ToString() const; 71 72 QUICHE_EXPORT friend std::ostream& operator<<(std::ostream& os, 73 const QuicPacketNumber& p); 74 75 private: 76 // All following operators REQUIRE operands.Initialized() == true. 77 friend inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs); 78 friend inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs); 79 friend inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs); 80 friend inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs); 81 friend inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs); 82 friend inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs); 83 84 // REQUIRES: numeric_limits<uint64_t>::max() - lhs.ToUint64() > |delta|. 85 friend inline QuicPacketNumber operator+(QuicPacketNumber lhs, 86 uint64_t delta); 87 // REQUIRES: lhs.ToUint64() >= |delta|. 88 friend inline QuicPacketNumber operator-(QuicPacketNumber lhs, 89 uint64_t delta); 90 // REQUIRES: lhs >= rhs. 91 friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs); 92 93 uint64_t packet_number_; 94 }; 95 96 class QUICHE_EXPORT QuicPacketNumberHash { 97 public: operator()98 uint64_t operator()(QuicPacketNumber packet_number) const noexcept { 99 return packet_number.Hash(); 100 } 101 }; 102 103 inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs) { 104 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) 105 << lhs << " vs. " << rhs; 106 return lhs.packet_number_ == rhs.packet_number_; 107 } 108 109 inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs) { 110 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) 111 << lhs << " vs. " << rhs; 112 return lhs.packet_number_ != rhs.packet_number_; 113 } 114 115 inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs) { 116 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) 117 << lhs << " vs. " << rhs; 118 return lhs.packet_number_ < rhs.packet_number_; 119 } 120 121 inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs) { 122 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) 123 << lhs << " vs. " << rhs; 124 return lhs.packet_number_ <= rhs.packet_number_; 125 } 126 127 inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs) { 128 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) 129 << lhs << " vs. " << rhs; 130 return lhs.packet_number_ > rhs.packet_number_; 131 } 132 133 inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs) { 134 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) 135 << lhs << " vs. " << rhs; 136 return lhs.packet_number_ >= rhs.packet_number_; 137 } 138 139 inline QuicPacketNumber operator+(QuicPacketNumber lhs, uint64_t delta) { 140 #ifndef NDEBUG 141 QUICHE_DCHECK(lhs.IsInitialized()); 142 QUICHE_DCHECK_GT(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), 143 delta); 144 #endif 145 return QuicPacketNumber(lhs.packet_number_ + delta); 146 } 147 148 inline QuicPacketNumber operator-(QuicPacketNumber lhs, uint64_t delta) { 149 #ifndef NDEBUG 150 QUICHE_DCHECK(lhs.IsInitialized()); 151 QUICHE_DCHECK_GE(lhs.ToUint64(), delta); 152 #endif 153 return QuicPacketNumber(lhs.packet_number_ - delta); 154 } 155 156 inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs) { 157 QUICHE_DCHECK(lhs.IsInitialized() && rhs.IsInitialized() && lhs >= rhs) 158 << lhs << " vs. " << rhs; 159 return lhs.packet_number_ - rhs.packet_number_; 160 } 161 162 } // namespace quic 163 164 #endif // QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_ 165