dcsctp: UnwrappedSequenceNumber use StrongAlias
As this library will only use StrongAlias types for all its sequence numbers, the UnwrappedSequenceNumber class should use those types and not the primitive underlying types (e.g. uint32_t). This makes e.g. Unwrap() return a strong type, which is preferred. Bug: webrtc:12614 Change-Id: Icd0900c643a1988d1a3bbf49d87b4d4d1bbfbf1f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/213663 Commit-Queue: Victor Boivie <boivie@webrtc.org> Reviewed-by: Tommi <tommi@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33651}
This commit is contained in:
parent
471fc8c329
commit
83c726f3e5
@ -14,6 +14,8 @@
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "net/dcsctp/common/internal_types.h"
|
||||
|
||||
namespace dcsctp {
|
||||
|
||||
// UnwrappedSequenceNumber handles wrapping sequence numbers and unwraps them to
|
||||
@ -23,12 +25,16 @@ namespace dcsctp {
|
||||
// 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 StrongAlias type.
|
||||
template <typename WrappedType>
|
||||
class UnwrappedSequenceNumber {
|
||||
public:
|
||||
static_assert(!std::numeric_limits<WrappedType>::is_signed,
|
||||
static_assert(
|
||||
!std::numeric_limits<typename WrappedType::UnderlyingType>::is_signed,
|
||||
"The wrapped type must be unsigned");
|
||||
static_assert(std::numeric_limits<WrappedType>::max() <
|
||||
static_assert(
|
||||
std::numeric_limits<typename WrappedType::UnderlyingType>::max() <
|
||||
std::numeric_limits<int64_t>::max(),
|
||||
"The wrapped type must be less than the int64_t value space");
|
||||
|
||||
@ -70,8 +76,9 @@ class UnwrappedSequenceNumber {
|
||||
|
||||
private:
|
||||
static int64_t Delta(WrappedType value, WrappedType prev_value) {
|
||||
static constexpr WrappedType kBreakpoint = kValueLimit / 2;
|
||||
WrappedType diff = value - prev_value;
|
||||
static constexpr typename WrappedType::UnderlyingType kBreakpoint =
|
||||
kValueLimit / 2;
|
||||
typename WrappedType::UnderlyingType diff = *value - *prev_value;
|
||||
diff %= kValueLimit;
|
||||
if (diff < kBreakpoint) {
|
||||
return static_cast<int64_t>(diff);
|
||||
@ -124,26 +131,28 @@ class UnwrappedSequenceNumber {
|
||||
}
|
||||
|
||||
// Compares the difference between two sequence numbers.
|
||||
WrappedType Difference(UnwrappedSequenceNumber<WrappedType> other) const {
|
||||
typename WrappedType::UnderlyingType Difference(
|
||||
UnwrappedSequenceNumber<WrappedType> other) const {
|
||||
return value_ - other.value_;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit UnwrappedSequenceNumber(int64_t value) : value_(value) {}
|
||||
static constexpr int64_t kValueLimit =
|
||||
static_cast<int64_t>(1) << std::numeric_limits<WrappedType>::digits;
|
||||
static_cast<int64_t>(1)
|
||||
<< std::numeric_limits<typename WrappedType::UnderlyingType>::digits;
|
||||
|
||||
int64_t value_;
|
||||
};
|
||||
|
||||
// Unwrapped Transmission Sequence Numbers (TSN)
|
||||
using UnwrappedTSN = UnwrappedSequenceNumber<uint32_t>;
|
||||
using UnwrappedTSN = UnwrappedSequenceNumber<TSN>;
|
||||
|
||||
// Unwrapped Stream Sequence Numbers (SSN)
|
||||
using UnwrappedSSN = UnwrappedSequenceNumber<uint16_t>;
|
||||
using UnwrappedSSN = UnwrappedSequenceNumber<SSN>;
|
||||
|
||||
// Unwrapped Message Identifier (MID)
|
||||
using UnwrappedMID = UnwrappedSequenceNumber<uint32_t>;
|
||||
using UnwrappedMID = UnwrappedSequenceNumber<MID>;
|
||||
|
||||
} // namespace dcsctp
|
||||
|
||||
|
||||
@ -14,15 +14,16 @@
|
||||
namespace dcsctp {
|
||||
namespace {
|
||||
|
||||
using TestSequence = UnwrappedSequenceNumber<uint16_t>;
|
||||
using Wrapped = StrongAlias<class WrappedTag, uint16_t>;
|
||||
using TestSequence = UnwrappedSequenceNumber<Wrapped>;
|
||||
|
||||
TEST(SequenceNumbersTest, SimpleUnwrapping) {
|
||||
TestSequence::Unwrapper unwrapper;
|
||||
|
||||
TestSequence s0 = unwrapper.Unwrap(0);
|
||||
TestSequence s1 = unwrapper.Unwrap(1);
|
||||
TestSequence s2 = unwrapper.Unwrap(2);
|
||||
TestSequence s3 = unwrapper.Unwrap(3);
|
||||
TestSequence s0 = unwrapper.Unwrap(Wrapped(0));
|
||||
TestSequence s1 = unwrapper.Unwrap(Wrapped(1));
|
||||
TestSequence s2 = unwrapper.Unwrap(Wrapped(2));
|
||||
TestSequence s3 = unwrapper.Unwrap(Wrapped(3));
|
||||
|
||||
EXPECT_LT(s0, s1);
|
||||
EXPECT_LT(s0, s2);
|
||||
@ -55,10 +56,10 @@ TEST(SequenceNumbersTest, SimpleUnwrapping) {
|
||||
TEST(SequenceNumbersTest, MidValueUnwrapping) {
|
||||
TestSequence::Unwrapper unwrapper;
|
||||
|
||||
TestSequence s0 = unwrapper.Unwrap(0x7FFE);
|
||||
TestSequence s1 = unwrapper.Unwrap(0x7FFF);
|
||||
TestSequence s2 = unwrapper.Unwrap(0x8000);
|
||||
TestSequence s3 = unwrapper.Unwrap(0x8001);
|
||||
TestSequence s0 = unwrapper.Unwrap(Wrapped(0x7FFE));
|
||||
TestSequence s1 = unwrapper.Unwrap(Wrapped(0x7FFF));
|
||||
TestSequence s2 = unwrapper.Unwrap(Wrapped(0x8000));
|
||||
TestSequence s3 = unwrapper.Unwrap(Wrapped(0x8001));
|
||||
|
||||
EXPECT_LT(s0, s1);
|
||||
EXPECT_LT(s0, s2);
|
||||
@ -91,10 +92,10 @@ TEST(SequenceNumbersTest, MidValueUnwrapping) {
|
||||
TEST(SequenceNumbersTest, WrappedUnwrapping) {
|
||||
TestSequence::Unwrapper unwrapper;
|
||||
|
||||
TestSequence s0 = unwrapper.Unwrap(0xFFFE);
|
||||
TestSequence s1 = unwrapper.Unwrap(0xFFFF);
|
||||
TestSequence s2 = unwrapper.Unwrap(0x0000);
|
||||
TestSequence s3 = unwrapper.Unwrap(0x0001);
|
||||
TestSequence s0 = unwrapper.Unwrap(Wrapped(0xFFFE));
|
||||
TestSequence s1 = unwrapper.Unwrap(Wrapped(0xFFFF));
|
||||
TestSequence s2 = unwrapper.Unwrap(Wrapped(0x0000));
|
||||
TestSequence s3 = unwrapper.Unwrap(Wrapped(0x0001));
|
||||
|
||||
EXPECT_LT(s0, s1);
|
||||
EXPECT_LT(s0, s2);
|
||||
@ -127,12 +128,12 @@ TEST(SequenceNumbersTest, WrappedUnwrapping) {
|
||||
TEST(SequenceNumbersTest, WrapAroundAFewTimes) {
|
||||
TestSequence::Unwrapper unwrapper;
|
||||
|
||||
TestSequence s0 = unwrapper.Unwrap(0);
|
||||
TestSequence s0 = unwrapper.Unwrap(Wrapped(0));
|
||||
TestSequence prev = s0;
|
||||
|
||||
for (uint32_t i = 1; i < 65536 * 3; i++) {
|
||||
uint16_t wrapped = static_cast<uint16_t>(i);
|
||||
TestSequence si = unwrapper.Unwrap(wrapped);
|
||||
TestSequence si = unwrapper.Unwrap(Wrapped(wrapped));
|
||||
|
||||
EXPECT_LT(s0, si);
|
||||
EXPECT_LT(prev, si);
|
||||
@ -143,11 +144,11 @@ TEST(SequenceNumbersTest, WrapAroundAFewTimes) {
|
||||
TEST(SequenceNumbersTest, IncrementIsSameAsWrapped) {
|
||||
TestSequence::Unwrapper unwrapper;
|
||||
|
||||
TestSequence s0 = unwrapper.Unwrap(0);
|
||||
TestSequence s0 = unwrapper.Unwrap(Wrapped(0));
|
||||
|
||||
for (uint32_t i = 1; i < 65536 * 2; i++) {
|
||||
uint16_t wrapped = static_cast<uint16_t>(i);
|
||||
TestSequence si = unwrapper.Unwrap(wrapped);
|
||||
TestSequence si = unwrapper.Unwrap(Wrapped(wrapped));
|
||||
|
||||
s0.Increment();
|
||||
EXPECT_EQ(s0, si);
|
||||
@ -159,12 +160,12 @@ TEST(SequenceNumbersTest, UnwrappingLargerNumberIsAlwaysLarger) {
|
||||
|
||||
for (uint32_t i = 1; i < 65536 * 2; i++) {
|
||||
uint16_t wrapped = static_cast<uint16_t>(i);
|
||||
TestSequence si = unwrapper.Unwrap(wrapped);
|
||||
TestSequence si = unwrapper.Unwrap(Wrapped(wrapped));
|
||||
|
||||
EXPECT_GT(unwrapper.Unwrap(wrapped + 1), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(wrapped + 5), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(wrapped + 10), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(wrapped + 100), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(Wrapped(wrapped + 1)), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(Wrapped(wrapped + 5)), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(Wrapped(wrapped + 10)), si);
|
||||
EXPECT_GT(unwrapper.Unwrap(Wrapped(wrapped + 100)), si);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,12 +174,12 @@ TEST(SequenceNumbersTest, UnwrappingSmallerNumberIsAlwaysSmaller) {
|
||||
|
||||
for (uint32_t i = 1; i < 65536 * 2; i++) {
|
||||
uint16_t wrapped = static_cast<uint16_t>(i);
|
||||
TestSequence si = unwrapper.Unwrap(wrapped);
|
||||
TestSequence si = unwrapper.Unwrap(Wrapped(wrapped));
|
||||
|
||||
EXPECT_LT(unwrapper.Unwrap(wrapped - 1), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(wrapped - 5), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(wrapped - 10), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(wrapped - 100), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(Wrapped(wrapped - 1)), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(Wrapped(wrapped - 5)), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(Wrapped(wrapped - 10)), si);
|
||||
EXPECT_LT(unwrapper.Unwrap(Wrapped(wrapped - 100)), si);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,11 +20,12 @@ namespace dcsctp {
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:base/types/strong_alias.h
|
||||
// as the API (and internals) are using type-safe integral identifiers, but this
|
||||
// library can't depend on that file. The ostream operator has been removed
|
||||
// per WebRTC library conventions.
|
||||
// per WebRTC library conventions, and the underlying type is exposed.
|
||||
|
||||
template <typename TagType, typename UnderlyingType>
|
||||
template <typename TagType, typename TheUnderlyingType>
|
||||
class StrongAlias {
|
||||
public:
|
||||
using UnderlyingType = TheUnderlyingType;
|
||||
constexpr StrongAlias() = default;
|
||||
constexpr explicit StrongAlias(const UnderlyingType& v) : value_(v) {}
|
||||
constexpr explicit StrongAlias(UnderlyingType&& v) noexcept
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user