| // 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 "quic/platform/api/quic_export.h" |
| #include "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_ |