/* * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_ #define NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_ #include #include #include #include "net/dcsctp/common/internal_types.h" #include "rtc_base/numerics/sequence_number_unwrapper.h" namespace dcsctp { // UnwrappedSequenceNumber handles wrapping sequence numbers and unwraps them to // an int64_t value space, to allow wrapped sequence numbers to be easily // compared for ordering. // // Sequence numbers are expected to be monotonically increasing, but they do not // need to be unwrapped in order, as long as the difference to the previous one // is not larger than half the range of the wrapped sequence number. // // The WrappedType must be a webrtc::StrongAlias type. template class UnwrappedSequenceNumber { public: static_assert( !std::numeric_limits::is_signed, "The wrapped type must be unsigned"); static_assert( std::numeric_limits::max() < std::numeric_limits::max(), "The wrapped type must be less than the int64_t value space"); // The unwrapper is a sort of factory and converts wrapped sequence numbers to // unwrapped ones. class Unwrapper { public: Unwrapper() = default; Unwrapper(const Unwrapper&) = default; Unwrapper& operator=(const Unwrapper&) = default; // Given a wrapped `value`, and with knowledge of its current last seen // largest number, will return a value that can be compared using normal // operators, such as less-than, greater-than etc. // // This will also update the Unwrapper's state, to track the last seen // largest value. UnwrappedSequenceNumber Unwrap(WrappedType value) { return UnwrappedSequenceNumber(unwrapper_.Unwrap(*value)); } // Similar to `Unwrap`, but will not update the Unwrappers's internal state. UnwrappedSequenceNumber PeekUnwrap(WrappedType value) const { return UnwrappedSequenceNumber( unwrapper_.PeekUnwrap(*value)); } // Resets the Unwrapper to its pristine state. Used when a sequence number // is to be reset to zero. void Reset() { unwrapper_.Reset(); } private: webrtc::SeqNumUnwrapper unwrapper_; }; // Returns the wrapped value this type represents. WrappedType Wrap() const { return static_cast(value_ % kValueLimit); } template friend H AbslHashValue(H state, const UnwrappedSequenceNumber& hash) { return H::combine(std::move(state), hash.value_); } bool operator==(const UnwrappedSequenceNumber& other) const { return value_ == other.value_; } bool operator!=(const UnwrappedSequenceNumber& other) const { return value_ != other.value_; } bool operator<(const UnwrappedSequenceNumber& other) const { return value_ < other.value_; } bool operator>(const UnwrappedSequenceNumber& other) const { return value_ > other.value_; } bool operator>=(const UnwrappedSequenceNumber& other) const { return value_ >= other.value_; } bool operator<=(const UnwrappedSequenceNumber& other) const { return value_ <= other.value_; } // Const accessors for underlying value. constexpr const int64_t* operator->() const { return &value_; } constexpr const int64_t& operator*() const& { return value_; } constexpr const int64_t&& operator*() const&& { return std::move(value_); } constexpr const int64_t& value() const& { return value_; } constexpr const int64_t&& value() const&& { return std::move(value_); } constexpr explicit operator const int64_t&() const& { return value_; } // Increments the value. void Increment() { ++value_; } // Returns the next value relative to this sequence number. UnwrappedSequenceNumber next_value() const { return UnwrappedSequenceNumber(value_ + 1); } // Returns a new sequence number based on `value`, and adding `delta` (which // may be negative). static UnwrappedSequenceNumber AddTo( UnwrappedSequenceNumber value, int delta) { return UnwrappedSequenceNumber(value.value_ + delta); } // Returns the absolute difference between `lhs` and `rhs`. static typename WrappedType::UnderlyingType Difference( UnwrappedSequenceNumber lhs, UnwrappedSequenceNumber rhs) { return (lhs.value_ > rhs.value_) ? (lhs.value_ - rhs.value_) : (rhs.value_ - lhs.value_); } private: explicit UnwrappedSequenceNumber(int64_t value) : value_(value) {} static constexpr int64_t kValueLimit = static_cast(1) << std::numeric_limits::digits; int64_t value_; }; // Unwrapped Transmission Sequence Numbers (TSN) using UnwrappedTSN = UnwrappedSequenceNumber; // Unwrapped Stream Sequence Numbers (SSN) using UnwrappedSSN = UnwrappedSequenceNumber; // Unwrapped Message Identifier (MID) using UnwrappedMID = UnwrappedSequenceNumber; } // namespace dcsctp #endif // NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_