1 /* 2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 #ifndef NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_ 11 #define NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_ 12 13 #include <cstdint> 14 #include <limits> 15 #include <utility> 16 17 #include "net/dcsctp/common/internal_types.h" 18 19 namespace dcsctp { 20 21 // UnwrappedSequenceNumber handles wrapping sequence numbers and unwraps them to 22 // an int64_t value space, to allow wrapped sequence numbers to be easily 23 // compared for ordering. 24 // 25 // Sequence numbers are expected to be monotonically increasing, but they do not 26 // need to be unwrapped in order, as long as the difference to the previous one 27 // is not larger than half the range of the wrapped sequence number. 28 // 29 // The WrappedType must be a webrtc::StrongAlias type. 30 template <typename WrappedType> 31 class UnwrappedSequenceNumber { 32 public: 33 static_assert( 34 !std::numeric_limits<typename WrappedType::UnderlyingType>::is_signed, 35 "The wrapped type must be unsigned"); 36 static_assert( 37 std::numeric_limits<typename WrappedType::UnderlyingType>::max() < 38 std::numeric_limits<int64_t>::max(), 39 "The wrapped type must be less than the int64_t value space"); 40 41 // The unwrapper is a sort of factory and converts wrapped sequence numbers to 42 // unwrapped ones. 43 class Unwrapper { 44 public: Unwrapper()45 Unwrapper() : largest_(kValueLimit) {} 46 Unwrapper(const Unwrapper&) = default; 47 Unwrapper& operator=(const Unwrapper&) = default; 48 49 // Given a wrapped `value`, and with knowledge of its current last seen 50 // largest number, will return a value that can be compared using normal 51 // operators, such as less-than, greater-than etc. 52 // 53 // This will also update the Unwrapper's state, to track the last seen 54 // largest value. Unwrap(WrappedType value)55 UnwrappedSequenceNumber<WrappedType> Unwrap(WrappedType value) { 56 WrappedType wrapped_largest = 57 static_cast<WrappedType>(largest_ % kValueLimit); 58 int64_t result = largest_ + Delta(value, wrapped_largest); 59 if (largest_ < result) { 60 largest_ = result; 61 } 62 return UnwrappedSequenceNumber<WrappedType>(result); 63 } 64 65 // Similar to `Unwrap`, but will not update the Unwrappers's internal state. PeekUnwrap(WrappedType value)66 UnwrappedSequenceNumber<WrappedType> PeekUnwrap(WrappedType value) const { 67 WrappedType uint32_largest = 68 static_cast<WrappedType>(largest_ % kValueLimit); 69 int64_t result = largest_ + Delta(value, uint32_largest); 70 return UnwrappedSequenceNumber<WrappedType>(result); 71 } 72 73 // Resets the Unwrapper to its pristine state. Used when a sequence number 74 // is to be reset to zero. Reset()75 void Reset() { largest_ = kValueLimit; } 76 77 private: Delta(WrappedType value,WrappedType prev_value)78 static int64_t Delta(WrappedType value, WrappedType prev_value) { 79 static constexpr typename WrappedType::UnderlyingType kBreakpoint = 80 kValueLimit / 2; 81 typename WrappedType::UnderlyingType diff = *value - *prev_value; 82 diff %= kValueLimit; 83 if (diff < kBreakpoint) { 84 return static_cast<int64_t>(diff); 85 } 86 return static_cast<int64_t>(diff) - kValueLimit; 87 } 88 89 int64_t largest_; 90 }; 91 92 // Returns the wrapped value this type represents. Wrap()93 WrappedType Wrap() const { 94 return static_cast<WrappedType>(value_ % kValueLimit); 95 } 96 97 template <typename H> AbslHashValue(H state,const UnwrappedSequenceNumber<WrappedType> & hash)98 friend H AbslHashValue(H state, 99 const UnwrappedSequenceNumber<WrappedType>& hash) { 100 return H::combine(std::move(state), hash.value_); 101 } 102 103 bool operator==(const UnwrappedSequenceNumber<WrappedType>& other) const { 104 return value_ == other.value_; 105 } 106 bool operator!=(const UnwrappedSequenceNumber<WrappedType>& other) const { 107 return value_ != other.value_; 108 } 109 bool operator<(const UnwrappedSequenceNumber<WrappedType>& other) const { 110 return value_ < other.value_; 111 } 112 bool operator>(const UnwrappedSequenceNumber<WrappedType>& other) const { 113 return value_ > other.value_; 114 } 115 bool operator>=(const UnwrappedSequenceNumber<WrappedType>& other) const { 116 return value_ >= other.value_; 117 } 118 bool operator<=(const UnwrappedSequenceNumber<WrappedType>& other) const { 119 return value_ <= other.value_; 120 } 121 122 // Increments the value. Increment()123 void Increment() { ++value_; } 124 125 // Returns the next value relative to this sequence number. next_value()126 UnwrappedSequenceNumber<WrappedType> next_value() const { 127 return UnwrappedSequenceNumber<WrappedType>(value_ + 1); 128 } 129 130 // Returns a new sequence number based on `value`, and adding `delta` (which 131 // may be negative). AddTo(UnwrappedSequenceNumber<WrappedType> value,int delta)132 static UnwrappedSequenceNumber<WrappedType> AddTo( 133 UnwrappedSequenceNumber<WrappedType> value, 134 int delta) { 135 return UnwrappedSequenceNumber<WrappedType>(value.value_ + delta); 136 } 137 138 // Returns the absolute difference between `lhs` and `rhs`. Difference(UnwrappedSequenceNumber<WrappedType> lhs,UnwrappedSequenceNumber<WrappedType> rhs)139 static typename WrappedType::UnderlyingType Difference( 140 UnwrappedSequenceNumber<WrappedType> lhs, 141 UnwrappedSequenceNumber<WrappedType> rhs) { 142 return (lhs.value_ > rhs.value_) ? (lhs.value_ - rhs.value_) 143 : (rhs.value_ - lhs.value_); 144 } 145 146 private: UnwrappedSequenceNumber(int64_t value)147 explicit UnwrappedSequenceNumber(int64_t value) : value_(value) {} 148 static constexpr int64_t kValueLimit = 149 static_cast<int64_t>(1) 150 << std::numeric_limits<typename WrappedType::UnderlyingType>::digits; 151 152 int64_t value_; 153 }; 154 155 // Unwrapped Transmission Sequence Numbers (TSN) 156 using UnwrappedTSN = UnwrappedSequenceNumber<TSN>; 157 158 // Unwrapped Stream Sequence Numbers (SSN) 159 using UnwrappedSSN = UnwrappedSequenceNumber<SSN>; 160 161 // Unwrapped Message Identifier (MID) 162 using UnwrappedMID = UnwrappedSequenceNumber<MID>; 163 164 } // namespace dcsctp 165 166 #endif // NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_ 167