Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,2 @@
boivie@webrtc.org
orphis@webrtc.org

View file

@ -0,0 +1,22 @@
/*
* 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.
*/
#include "net/dcsctp/common/handover_testing.h"
namespace dcsctp {
namespace {
// Default transformer function does nothing - dcSCTP does not implement
// state serialization that could be tested by setting
// `g_handover_state_transformer_for_test`.
void NoTransformation(DcSctpSocketHandoverState*) {}
} // namespace
void (*g_handover_state_transformer_for_test)(DcSctpSocketHandoverState*) =
NoTransformation;
} // namespace dcsctp

View file

@ -0,0 +1,29 @@
/*
* 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_HANDOVER_TESTING_H_
#define NET_DCSCTP_COMMON_HANDOVER_TESTING_H_
#include "net/dcsctp/public/dcsctp_handover_state.h"
namespace dcsctp {
// This global function is to facilitate testing of the socket handover state
// (`DcSctpSocketHandoverState`) serialization. dcSCTP library users have to
// implement state serialization if it's needed. To test the serialization one
// can set a custom `g_handover_state_transformer_for_test` at startup, link to
// the dcSCTP tests and run the resulting binary. Custom function can serialize
// and deserialize the passed state. All dcSCTP handover tests call
// `g_handover_state_transformer_for_test`. If some part of the state is
// serialized incorrectly or is forgotten, high chance that it will fail the
// tests.
extern void (*g_handover_state_transformer_for_test)(
DcSctpSocketHandoverState*);
} // namespace dcsctp
#endif // NET_DCSCTP_COMMON_HANDOVER_TESTING_H_

View file

@ -0,0 +1,49 @@
/*
* 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_INTERNAL_TYPES_H_
#define NET_DCSCTP_COMMON_INTERNAL_TYPES_H_
#include <functional>
#include <utility>
#include "net/dcsctp/public/types.h"
#include "rtc_base/strong_alias.h"
namespace dcsctp {
// Stream Sequence Number (SSN)
using SSN = webrtc::StrongAlias<class SSNTag, uint16_t>;
// Message Identifier (MID)
using MID = webrtc::StrongAlias<class MIDTag, uint32_t>;
// Fragment Sequence Number (FSN)
using FSN = webrtc::StrongAlias<class FSNTag, uint32_t>;
// Transmission Sequence Number (TSN)
using TSN = webrtc::StrongAlias<class TSNTag, uint32_t>;
// Reconfiguration Request Sequence Number
using ReconfigRequestSN =
webrtc::StrongAlias<class ReconfigRequestSNTag, uint32_t>;
// Verification Tag, used for packet validation.
using VerificationTag = webrtc::StrongAlias<class VerificationTagTag, uint32_t>;
// Tie Tag, used as a nonce when connecting.
using TieTag = webrtc::StrongAlias<class TieTagTag, uint64_t>;
// An ID for every outgoing message, to correlate outgoing data chunks with the
// message it was carved from.
using OutgoingMessageId =
webrtc::StrongAlias<class OutgoingMessageIdTag, uint32_t>;
} // namespace dcsctp
#endif // NET_DCSCTP_COMMON_INTERNAL_TYPES_H_

View file

@ -0,0 +1,36 @@
/*
* 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_MATH_H_
#define NET_DCSCTP_COMMON_MATH_H_
namespace dcsctp {
// Rounds up `val` to the nearest value that is divisible by four. Frequently
// used to e.g. pad chunks or parameters to an even 32-bit offset.
template <typename IntType>
IntType RoundUpTo4(IntType val) {
return (val + 3) & ~3;
}
// Similarly, rounds down `val` to the nearest value that is divisible by four.
template <typename IntType>
IntType RoundDownTo4(IntType val) {
return val & ~3;
}
// Returns true if `val` is divisible by four.
template <typename IntType>
bool IsDivisibleBy4(IntType val) {
return (val & 3) == 0;
}
} // namespace dcsctp
#endif // NET_DCSCTP_COMMON_MATH_H_

View file

@ -0,0 +1,116 @@
/*
* 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.
*/
#include "net/dcsctp/common/math.h"
#include "test/gmock.h"
namespace dcsctp {
namespace {
TEST(MathUtilTest, CanRoundUpTo4) {
// Signed numbers
EXPECT_EQ(RoundUpTo4(static_cast<int>(-5)), -4);
EXPECT_EQ(RoundUpTo4(static_cast<int>(-4)), -4);
EXPECT_EQ(RoundUpTo4(static_cast<int>(-3)), 0);
EXPECT_EQ(RoundUpTo4(static_cast<int>(-2)), 0);
EXPECT_EQ(RoundUpTo4(static_cast<int>(-1)), 0);
EXPECT_EQ(RoundUpTo4(static_cast<int>(0)), 0);
EXPECT_EQ(RoundUpTo4(static_cast<int>(1)), 4);
EXPECT_EQ(RoundUpTo4(static_cast<int>(2)), 4);
EXPECT_EQ(RoundUpTo4(static_cast<int>(3)), 4);
EXPECT_EQ(RoundUpTo4(static_cast<int>(4)), 4);
EXPECT_EQ(RoundUpTo4(static_cast<int>(5)), 8);
EXPECT_EQ(RoundUpTo4(static_cast<int>(6)), 8);
EXPECT_EQ(RoundUpTo4(static_cast<int>(7)), 8);
EXPECT_EQ(RoundUpTo4(static_cast<int>(8)), 8);
EXPECT_EQ(RoundUpTo4(static_cast<int64_t>(10000000000)), 10000000000);
EXPECT_EQ(RoundUpTo4(static_cast<int64_t>(10000000001)), 10000000004);
// Unsigned numbers
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(0)), 0u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(1)), 4u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(2)), 4u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(3)), 4u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(4)), 4u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(5)), 8u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(6)), 8u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(7)), 8u);
EXPECT_EQ(RoundUpTo4(static_cast<unsigned int>(8)), 8u);
EXPECT_EQ(RoundUpTo4(static_cast<uint64_t>(10000000000)), 10000000000u);
EXPECT_EQ(RoundUpTo4(static_cast<uint64_t>(10000000001)), 10000000004u);
}
TEST(MathUtilTest, CanRoundDownTo4) {
// Signed numbers
EXPECT_EQ(RoundDownTo4(static_cast<int>(-5)), -8);
EXPECT_EQ(RoundDownTo4(static_cast<int>(-4)), -4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(-3)), -4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(-2)), -4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(-1)), -4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(0)), 0);
EXPECT_EQ(RoundDownTo4(static_cast<int>(1)), 0);
EXPECT_EQ(RoundDownTo4(static_cast<int>(2)), 0);
EXPECT_EQ(RoundDownTo4(static_cast<int>(3)), 0);
EXPECT_EQ(RoundDownTo4(static_cast<int>(4)), 4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(5)), 4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(6)), 4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(7)), 4);
EXPECT_EQ(RoundDownTo4(static_cast<int>(8)), 8);
EXPECT_EQ(RoundDownTo4(static_cast<int64_t>(10000000000)), 10000000000);
EXPECT_EQ(RoundDownTo4(static_cast<int64_t>(10000000001)), 10000000000);
// Unsigned numbers
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(0)), 0u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(1)), 0u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(2)), 0u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(3)), 0u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(4)), 4u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(5)), 4u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(6)), 4u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(7)), 4u);
EXPECT_EQ(RoundDownTo4(static_cast<unsigned int>(8)), 8u);
EXPECT_EQ(RoundDownTo4(static_cast<uint64_t>(10000000000)), 10000000000u);
EXPECT_EQ(RoundDownTo4(static_cast<uint64_t>(10000000001)), 10000000000u);
}
TEST(MathUtilTest, IsDivisibleBy4) {
// Signed numbers
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(-4)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(-3)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(-2)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(-1)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(0)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(1)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(2)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(3)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(4)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(5)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(6)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(7)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<int>(8)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<int64_t>(10000000000)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<int64_t>(10000000001)), false);
// Unsigned numbers
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(0)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(1)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(2)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(3)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(4)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(5)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(6)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(7)), false);
EXPECT_EQ(IsDivisibleBy4(static_cast<unsigned int>(8)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<uint64_t>(10000000000)), true);
EXPECT_EQ(IsDivisibleBy4(static_cast<uint64_t>(10000000001)), false);
}
} // namespace
} // namespace dcsctp

View file

@ -0,0 +1,156 @@
/*
* 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 <cstdint>
#include <limits>
#include <utility>
#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 <typename WrappedType>
class UnwrappedSequenceNumber {
public:
static_assert(
!std::numeric_limits<typename WrappedType::UnderlyingType>::is_signed,
"The wrapped type must be unsigned");
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");
// 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<WrappedType> Unwrap(WrappedType value) {
return UnwrappedSequenceNumber<WrappedType>(unwrapper_.Unwrap(*value));
}
// Similar to `Unwrap`, but will not update the Unwrappers's internal state.
UnwrappedSequenceNumber<WrappedType> PeekUnwrap(WrappedType value) const {
return UnwrappedSequenceNumber<WrappedType>(
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<typename WrappedType::UnderlyingType> unwrapper_;
};
// Returns the wrapped value this type represents.
WrappedType Wrap() const {
return static_cast<WrappedType>(value_ % kValueLimit);
}
template <typename H>
friend H AbslHashValue(H state,
const UnwrappedSequenceNumber<WrappedType>& hash) {
return H::combine(std::move(state), hash.value_);
}
bool operator==(const UnwrappedSequenceNumber<WrappedType>& other) const {
return value_ == other.value_;
}
bool operator!=(const UnwrappedSequenceNumber<WrappedType>& other) const {
return value_ != other.value_;
}
bool operator<(const UnwrappedSequenceNumber<WrappedType>& other) const {
return value_ < other.value_;
}
bool operator>(const UnwrappedSequenceNumber<WrappedType>& other) const {
return value_ > other.value_;
}
bool operator>=(const UnwrappedSequenceNumber<WrappedType>& other) const {
return value_ >= other.value_;
}
bool operator<=(const UnwrappedSequenceNumber<WrappedType>& 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<WrappedType> next_value() const {
return UnwrappedSequenceNumber<WrappedType>(value_ + 1);
}
// Returns a new sequence number based on `value`, and adding `delta` (which
// may be negative).
static UnwrappedSequenceNumber<WrappedType> AddTo(
UnwrappedSequenceNumber<WrappedType> value,
int delta) {
return UnwrappedSequenceNumber<WrappedType>(value.value_ + delta);
}
// Returns the absolute difference between `lhs` and `rhs`.
static typename WrappedType::UnderlyingType Difference(
UnwrappedSequenceNumber<WrappedType> lhs,
UnwrappedSequenceNumber<WrappedType> 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<int64_t>(1)
<< std::numeric_limits<typename WrappedType::UnderlyingType>::digits;
int64_t value_;
};
// Unwrapped Transmission Sequence Numbers (TSN)
using UnwrappedTSN = UnwrappedSequenceNumber<TSN>;
// Unwrapped Stream Sequence Numbers (SSN)
using UnwrappedSSN = UnwrappedSequenceNumber<SSN>;
// Unwrapped Message Identifier (MID)
using UnwrappedMID = UnwrappedSequenceNumber<MID>;
} // namespace dcsctp
#endif // NET_DCSCTP_COMMON_SEQUENCE_NUMBERS_H_

View file

@ -0,0 +1,461 @@
/*
* 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.
*/
#include "net/dcsctp/fuzzers/dcsctp_fuzzers.h"
#include <string>
#include <utility>
#include <vector>
#include "net/dcsctp/common/math.h"
#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
#include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
#include "net/dcsctp/packet/chunk/data_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
#include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
#include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
#include "net/dcsctp/public/dcsctp_message.h"
#include "net/dcsctp/public/types.h"
#include "net/dcsctp/socket/dcsctp_socket.h"
#include "net/dcsctp/socket/state_cookie.h"
#include "rtc_base/logging.h"
namespace dcsctp {
namespace dcsctp_fuzzers {
namespace {
static constexpr int kRandomValue = FuzzerCallbacks::kRandomValue;
static constexpr size_t kMinInputLength = 5;
static constexpr size_t kMaxInputLength = 1024;
// A starting state for the socket, when fuzzing.
enum class StartingState : int {
kConnectNotCalled,
// When socket initiating Connect
kConnectCalled,
kReceivedInitAck,
kReceivedCookieAck,
// When socket initiating Shutdown
kShutdownCalled,
kReceivedShutdownAck,
// When peer socket initiated Connect
kReceivedInit,
kReceivedCookieEcho,
// When peer initiated Shutdown
kReceivedShutdown,
kReceivedShutdownComplete,
kNumberOfStates,
};
// State about the current fuzzing iteration
class FuzzState {
public:
explicit FuzzState(rtc::ArrayView<const uint8_t> data) : data_(data) {}
uint8_t GetByte() {
uint8_t value = 0;
if (offset_ < data_.size()) {
value = data_[offset_];
++offset_;
}
return value;
}
TSN GetNextTSN() { return TSN(tsn_++); }
MID GetNextMID() { return MID(mid_++); }
bool empty() const { return offset_ >= data_.size(); }
private:
uint32_t tsn_ = kRandomValue;
uint32_t mid_ = 0;
rtc::ArrayView<const uint8_t> data_;
size_t offset_ = 0;
};
void SetSocketState(DcSctpSocketInterface& socket,
FuzzerCallbacks& socket_cb,
StartingState state) {
// We'll use another temporary peer socket for the establishment.
FuzzerCallbacks peer_cb;
DcSctpSocket peer("peer", peer_cb, nullptr, {});
switch (state) {
case StartingState::kConnectNotCalled:
return;
case StartingState::kConnectCalled:
socket.Connect();
return;
case StartingState::kReceivedInitAck:
socket.Connect();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT_ACK
return;
case StartingState::kReceivedCookieAck:
socket.Connect();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT_ACK
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // COOKIE_ECHO
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // COOKIE_ACK
return;
case StartingState::kShutdownCalled:
socket.Connect();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT_ACK
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // COOKIE_ECHO
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // COOKIE_ACK
socket.Shutdown();
return;
case StartingState::kReceivedShutdownAck:
socket.Connect();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT_ACK
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // COOKIE_ECHO
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // COOKIE_ACK
socket.Shutdown();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // SHUTDOWN
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // SHUTDOWN_ACK
return;
case StartingState::kReceivedInit:
peer.Connect();
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT
return;
case StartingState::kReceivedCookieEcho:
peer.Connect();
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT_ACK
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // COOKIE_ECHO
return;
case StartingState::kReceivedShutdown:
socket.Connect();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT_ACK
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // COOKIE_ECHO
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // COOKIE_ACK
peer.Shutdown();
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // SHUTDOWN
return;
case StartingState::kReceivedShutdownComplete:
socket.Connect();
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // INIT
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // INIT_ACK
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // COOKIE_ECHO
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // COOKIE_ACK
peer.Shutdown();
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // SHUTDOWN
peer.ReceivePacket(socket_cb.ConsumeSentPacket()); // SHUTDOWN_ACK
socket.ReceivePacket(peer_cb.ConsumeSentPacket()); // SHUTDOWN_COMPLETE
return;
case StartingState::kNumberOfStates:
RTC_CHECK(false);
return;
}
}
void MakeDataChunk(FuzzState& state, SctpPacket::Builder& b) {
DataChunk::Options options;
options.is_unordered = IsUnordered(state.GetByte() != 0);
options.is_beginning = Data::IsBeginning(state.GetByte() != 0);
options.is_end = Data::IsEnd(state.GetByte() != 0);
b.Add(DataChunk(state.GetNextTSN(), StreamID(state.GetByte()),
SSN(state.GetByte()), PPID(53), std::vector<uint8_t>(10),
options));
}
void MakeInitChunk(FuzzState& state, SctpPacket::Builder& b) {
Parameters::Builder builder;
builder.Add(ForwardTsnSupportedParameter());
b.Add(InitChunk(VerificationTag(kRandomValue), 10000, 1000, 1000,
TSN(kRandomValue), builder.Build()));
}
void MakeInitAckChunk(FuzzState& state, SctpPacket::Builder& b) {
Parameters::Builder builder;
builder.Add(ForwardTsnSupportedParameter());
uint8_t state_cookie[] = {1, 2, 3, 4, 5};
Parameters::Builder params_builder =
Parameters::Builder().Add(StateCookieParameter(state_cookie));
b.Add(InitAckChunk(VerificationTag(kRandomValue), 10000, 1000, 1000,
TSN(kRandomValue), builder.Build()));
}
void MakeSackChunk(FuzzState& state, SctpPacket::Builder& b) {
std::vector<SackChunk::GapAckBlock> gap_ack_blocks;
uint16_t last_end = 0;
while (gap_ack_blocks.size() < 20) {
uint8_t delta_start = state.GetByte();
if (delta_start < 0x80) {
break;
}
uint8_t delta_end = state.GetByte();
uint16_t start = last_end + delta_start;
uint16_t end = start + delta_end;
last_end = end;
gap_ack_blocks.emplace_back(start, end);
}
TSN cum_ack_tsn(kRandomValue + state.GetByte());
b.Add(SackChunk(cum_ack_tsn, 10000, std::move(gap_ack_blocks), {}));
}
void MakeHeartbeatRequestChunk(FuzzState& state, SctpPacket::Builder& b) {
uint8_t info[] = {1, 2, 3, 4, 5};
b.Add(HeartbeatRequestChunk(
Parameters::Builder().Add(HeartbeatInfoParameter(info)).Build()));
}
void MakeHeartbeatAckChunk(FuzzState& state, SctpPacket::Builder& b) {
std::vector<uint8_t> info(8);
b.Add(HeartbeatRequestChunk(
Parameters::Builder().Add(HeartbeatInfoParameter(info)).Build()));
}
void MakeAbortChunk(FuzzState& state, SctpPacket::Builder& b) {
b.Add(AbortChunk(
/*filled_in_verification_tag=*/true,
Parameters::Builder().Add(UserInitiatedAbortCause("Fuzzing")).Build()));
}
void MakeErrorChunk(FuzzState& state, SctpPacket::Builder& b) {
b.Add(ErrorChunk(
Parameters::Builder().Add(ProtocolViolationCause("Fuzzing")).Build()));
}
void MakeCookieEchoChunk(FuzzState& state, SctpPacket::Builder& b) {
std::vector<uint8_t> cookie(StateCookie::kCookieSize);
b.Add(CookieEchoChunk(cookie));
}
void MakeCookieAckChunk(FuzzState& state, SctpPacket::Builder& b) {
b.Add(CookieAckChunk());
}
void MakeShutdownChunk(FuzzState& state, SctpPacket::Builder& b) {
b.Add(ShutdownChunk(state.GetNextTSN()));
}
void MakeShutdownAckChunk(FuzzState& state, SctpPacket::Builder& b) {
b.Add(ShutdownAckChunk());
}
void MakeShutdownCompleteChunk(FuzzState& state, SctpPacket::Builder& b) {
b.Add(ShutdownCompleteChunk(false));
}
void MakeReConfigChunk(FuzzState& state, SctpPacket::Builder& b) {
std::vector<StreamID> streams = {StreamID(state.GetByte())};
Parameters::Builder params_builder =
Parameters::Builder().Add(OutgoingSSNResetRequestParameter(
ReconfigRequestSN(kRandomValue), ReconfigRequestSN(kRandomValue),
state.GetNextTSN(), streams));
b.Add(ReConfigChunk(params_builder.Build()));
}
void MakeForwardTsnChunk(FuzzState& state, SctpPacket::Builder& b) {
std::vector<ForwardTsnChunk::SkippedStream> skipped_streams;
for (;;) {
uint8_t stream = state.GetByte();
if (skipped_streams.size() > 20 || stream < 0x80) {
break;
}
skipped_streams.emplace_back(StreamID(stream), SSN(state.GetByte()));
}
b.Add(ForwardTsnChunk(state.GetNextTSN(), std::move(skipped_streams)));
}
void MakeIDataChunk(FuzzState& state, SctpPacket::Builder& b) {
DataChunk::Options options;
options.is_unordered = IsUnordered(state.GetByte() != 0);
options.is_beginning = Data::IsBeginning(state.GetByte() != 0);
options.is_end = Data::IsEnd(state.GetByte() != 0);
b.Add(IDataChunk(state.GetNextTSN(), StreamID(state.GetByte()),
state.GetNextMID(), PPID(53), FSN(0),
std::vector<uint8_t>(10), options));
}
void MakeIForwardTsnChunk(FuzzState& state, SctpPacket::Builder& b) {
std::vector<ForwardTsnChunk::SkippedStream> skipped_streams;
for (;;) {
uint8_t stream = state.GetByte();
if (skipped_streams.size() > 20 || stream < 0x80) {
break;
}
skipped_streams.emplace_back(StreamID(stream), SSN(state.GetByte()));
}
b.Add(IForwardTsnChunk(state.GetNextTSN(), std::move(skipped_streams)));
}
class RandomFuzzedChunk : public Chunk {
public:
explicit RandomFuzzedChunk(FuzzState& state) : state_(state) {}
void SerializeTo(std::vector<uint8_t>& out) const override {
size_t bytes = state_.GetByte();
for (size_t i = 0; i < bytes; ++i) {
out.push_back(state_.GetByte());
}
}
std::string ToString() const override { return std::string("RANDOM_FUZZED"); }
private:
FuzzState& state_;
};
void MakeChunkWithRandomContent(FuzzState& state, SctpPacket::Builder& b) {
b.Add(RandomFuzzedChunk(state));
}
std::vector<uint8_t> GeneratePacket(FuzzState& state) {
DcSctpOptions options;
// Setting a fixed limit to not be dependent on the defaults, which may
// change.
options.mtu = 2048;
SctpPacket::Builder builder(VerificationTag(kRandomValue), options);
// The largest expected serialized chunk, as created by fuzzers.
static constexpr size_t kMaxChunkSize = 256;
for (int i = 0; i < 5 && builder.bytes_remaining() > kMaxChunkSize; ++i) {
switch (state.GetByte()) {
case 1:
MakeDataChunk(state, builder);
break;
case 2:
MakeInitChunk(state, builder);
break;
case 3:
MakeInitAckChunk(state, builder);
break;
case 4:
MakeSackChunk(state, builder);
break;
case 5:
MakeHeartbeatRequestChunk(state, builder);
break;
case 6:
MakeHeartbeatAckChunk(state, builder);
break;
case 7:
MakeAbortChunk(state, builder);
break;
case 8:
MakeErrorChunk(state, builder);
break;
case 9:
MakeCookieEchoChunk(state, builder);
break;
case 10:
MakeCookieAckChunk(state, builder);
break;
case 11:
MakeShutdownChunk(state, builder);
break;
case 12:
MakeShutdownAckChunk(state, builder);
break;
case 13:
MakeShutdownCompleteChunk(state, builder);
break;
case 14:
MakeReConfigChunk(state, builder);
break;
case 15:
MakeForwardTsnChunk(state, builder);
break;
case 16:
MakeIDataChunk(state, builder);
break;
case 17:
MakeIForwardTsnChunk(state, builder);
break;
case 18:
MakeChunkWithRandomContent(state, builder);
break;
default:
break;
}
}
std::vector<uint8_t> packet = builder.Build();
return packet;
}
} // namespace
void FuzzSocket(DcSctpSocketInterface& socket,
FuzzerCallbacks& cb,
rtc::ArrayView<const uint8_t> data) {
if (data.size() < kMinInputLength || data.size() > kMaxInputLength) {
return;
}
if (data[0] >= static_cast<int>(StartingState::kNumberOfStates)) {
return;
}
// Set the socket in a specified valid starting state
SetSocketState(socket, cb, static_cast<StartingState>(data[0]));
FuzzState state(data.subview(1));
while (!state.empty()) {
switch (state.GetByte()) {
case 1:
// Generate a valid SCTP packet (based on fuzz data) and "receive it".
socket.ReceivePacket(GeneratePacket(state));
break;
case 2:
socket.Connect();
break;
case 3:
socket.Shutdown();
break;
case 4:
socket.Close();
break;
case 5: {
StreamID streams[] = {StreamID(state.GetByte())};
socket.ResetStreams(streams);
} break;
case 6: {
uint8_t flags = state.GetByte();
SendOptions options;
options.unordered = IsUnordered(flags & 0x01);
options.max_retransmissions =
(flags & 0x02) != 0 ? absl::make_optional(0) : absl::nullopt;
options.lifecycle_id = LifecycleId(42);
size_t payload_exponent = (flags >> 2) % 16;
size_t payload_size = static_cast<size_t>(1) << payload_exponent;
socket.Send(DcSctpMessage(StreamID(state.GetByte()), PPID(53),
std::vector<uint8_t>(payload_size)),
options);
break;
}
case 7: {
// Expire an active timeout/timer.
uint8_t timeout_idx = state.GetByte();
absl::optional<TimeoutID> timeout_id = cb.ExpireTimeout(timeout_idx);
if (timeout_id.has_value()) {
socket.HandleTimeout(*timeout_id);
}
break;
}
default:
break;
}
}
}
} // namespace dcsctp_fuzzers
} // namespace dcsctp

View file

@ -0,0 +1,119 @@
/*
* 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_FUZZERS_DCSCTP_FUZZERS_H_
#define NET_DCSCTP_FUZZERS_DCSCTP_FUZZERS_H_
#include <deque>
#include <memory>
#include <set>
#include <vector>
#include "api/array_view.h"
#include "api/task_queue/task_queue_base.h"
#include "net/dcsctp/public/dcsctp_socket.h"
namespace dcsctp {
namespace dcsctp_fuzzers {
// A fake timeout used during fuzzing.
class FuzzerTimeout : public Timeout {
public:
explicit FuzzerTimeout(std::set<TimeoutID>& active_timeouts)
: active_timeouts_(active_timeouts) {}
void Start(DurationMs duration_ms, TimeoutID timeout_id) override {
// Start is only allowed to be called on stopped or expired timeouts.
if (timeout_id_.has_value()) {
// It has been started before, but maybe it expired. Ensure that it's not
// running at least.
RTC_DCHECK(active_timeouts_.find(*timeout_id_) == active_timeouts_.end());
}
timeout_id_ = timeout_id;
RTC_DCHECK(active_timeouts_.insert(timeout_id).second);
}
void Stop() override {
// Stop is only allowed to be called on active timeouts. Not stopped or
// expired.
RTC_DCHECK(timeout_id_.has_value());
RTC_DCHECK(active_timeouts_.erase(*timeout_id_) == 1);
timeout_id_ = absl::nullopt;
}
// A set of all active timeouts, managed by `FuzzerCallbacks`.
std::set<TimeoutID>& active_timeouts_;
// If present, the timout is active and will expire reported as `timeout_id`.
absl::optional<TimeoutID> timeout_id_;
};
class FuzzerCallbacks : public DcSctpSocketCallbacks {
public:
static constexpr int kRandomValue = 42;
void SendPacket(rtc::ArrayView<const uint8_t> data) override {
sent_packets_.emplace_back(std::vector<uint8_t>(data.begin(), data.end()));
}
std::unique_ptr<Timeout> CreateTimeout(
webrtc::TaskQueueBase::DelayPrecision precision) override {
// The fuzzer timeouts don't implement |precision|.
return std::make_unique<FuzzerTimeout>(active_timeouts_);
}
webrtc::Timestamp Now() override { return webrtc::Timestamp::Millis(42); }
uint32_t GetRandomInt(uint32_t low, uint32_t high) override {
return kRandomValue;
}
void OnMessageReceived(DcSctpMessage message) override {}
void OnError(ErrorKind error, absl::string_view message) override {}
void OnAborted(ErrorKind error, absl::string_view message) override {}
void OnConnected() override {}
void OnClosed() override {}
void OnConnectionRestarted() override {}
void OnStreamsResetFailed(rtc::ArrayView<const StreamID> outgoing_streams,
absl::string_view reason) override {}
void OnStreamsResetPerformed(
rtc::ArrayView<const StreamID> outgoing_streams) override {}
void OnIncomingStreamsReset(
rtc::ArrayView<const StreamID> incoming_streams) override {}
std::vector<uint8_t> ConsumeSentPacket() {
if (sent_packets_.empty()) {
return {};
}
std::vector<uint8_t> ret = sent_packets_.front();
sent_packets_.pop_front();
return ret;
}
// Given an index among the active timeouts, will expire that one.
absl::optional<TimeoutID> ExpireTimeout(size_t index) {
if (index < active_timeouts_.size()) {
auto it = active_timeouts_.begin();
std::advance(it, index);
TimeoutID timeout_id = *it;
active_timeouts_.erase(it);
return timeout_id;
}
return absl::nullopt;
}
private:
// Needs to be ordered, to allow fuzzers to expire timers.
std::set<TimeoutID> active_timeouts_;
std::deque<std::vector<uint8_t>> sent_packets_;
};
// Given some fuzzing `data` will send packets to the socket as well as calling
// API methods.
void FuzzSocket(DcSctpSocketInterface& socket,
FuzzerCallbacks& cb,
rtc::ArrayView<const uint8_t> data);
} // namespace dcsctp_fuzzers
} // namespace dcsctp
#endif // NET_DCSCTP_FUZZERS_DCSCTP_FUZZERS_H_

View file

@ -0,0 +1,99 @@
/*
* 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_PACKET_BOUNDED_BYTE_READER_H_
#define NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
#include <cstdint>
#include "api/array_view.h"
namespace dcsctp {
// TODO(boivie): These generic functions - and possibly this entire class -
// could be a candidate to have added to rtc_base/. They should use compiler
// intrinsics as well.
namespace internal {
// Loads a 8-bit unsigned word at `data`.
inline uint8_t LoadBigEndian8(const uint8_t* data) {
return data[0];
}
// Loads a 16-bit unsigned word at `data`.
inline uint16_t LoadBigEndian16(const uint8_t* data) {
return (data[0] << 8) | data[1];
}
// Loads a 32-bit unsigned word at `data`.
inline uint32_t LoadBigEndian32(const uint8_t* data) {
return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
}
} // namespace internal
// BoundedByteReader wraps an ArrayView and divides it into two parts; A fixed
// size - which is the template parameter - and a variable size, which is what
// remains in `data` after the `FixedSize`.
//
// The BoundedByteReader provides methods to load/read big endian numbers from
// the FixedSize portion of the buffer, and these are read with static bounds
// checking, to avoid out-of-bounds accesses without a run-time penalty.
//
// The variable sized portion can either be used to create sub-readers, which
// themselves would provide compile-time bounds-checking, or the entire variable
// sized portion can be retrieved as an ArrayView.
template <int FixedSize>
class BoundedByteReader {
public:
explicit BoundedByteReader(rtc::ArrayView<const uint8_t> data) : data_(data) {
RTC_CHECK(data.size() >= FixedSize);
}
template <size_t offset>
uint8_t Load8() const {
static_assert(offset + sizeof(uint8_t) <= FixedSize, "Out-of-bounds");
return internal::LoadBigEndian8(&data_[offset]);
}
template <size_t offset>
uint16_t Load16() const {
static_assert(offset + sizeof(uint16_t) <= FixedSize, "Out-of-bounds");
static_assert((offset % sizeof(uint16_t)) == 0, "Unaligned access");
return internal::LoadBigEndian16(&data_[offset]);
}
template <size_t offset>
uint32_t Load32() const {
static_assert(offset + sizeof(uint32_t) <= FixedSize, "Out-of-bounds");
static_assert((offset % sizeof(uint32_t)) == 0, "Unaligned access");
return internal::LoadBigEndian32(&data_[offset]);
}
template <size_t SubSize>
BoundedByteReader<SubSize> sub_reader(size_t variable_offset) const {
RTC_CHECK(FixedSize + variable_offset + SubSize <= data_.size());
rtc::ArrayView<const uint8_t> sub_span =
data_.subview(FixedSize + variable_offset, SubSize);
return BoundedByteReader<SubSize>(sub_span);
}
size_t variable_data_size() const { return data_.size() - FixedSize; }
rtc::ArrayView<const uint8_t> variable_data() const {
return data_.subview(FixedSize, data_.size() - FixedSize);
}
private:
const rtc::ArrayView<const uint8_t> data_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_

View file

@ -0,0 +1,103 @@
/*
* 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_PACKET_BOUNDED_BYTE_WRITER_H_
#define NET_DCSCTP_PACKET_BOUNDED_BYTE_WRITER_H_
#include <algorithm>
#include "api/array_view.h"
namespace dcsctp {
// TODO(boivie): These generic functions - and possibly this entire class -
// could be a candidate to have added to rtc_base/. They should use compiler
// intrinsics as well.
namespace internal {
// Stores a 8-bit unsigned word at `data`.
inline void StoreBigEndian8(uint8_t* data, uint8_t val) {
data[0] = val;
}
// Stores a 16-bit unsigned word at `data`.
inline void StoreBigEndian16(uint8_t* data, uint16_t val) {
data[0] = val >> 8;
data[1] = val;
}
// Stores a 32-bit unsigned word at `data`.
inline void StoreBigEndian32(uint8_t* data, uint32_t val) {
data[0] = val >> 24;
data[1] = val >> 16;
data[2] = val >> 8;
data[3] = val;
}
} // namespace internal
// BoundedByteWriter wraps an ArrayView and divides it into two parts; A fixed
// size - which is the template parameter - and a variable size, which is what
// remains in `data` after the `FixedSize`.
//
// The BoundedByteWriter provides methods to write big endian numbers to the
// FixedSize portion of the buffer, and these are written with static bounds
// checking, to avoid out-of-bounds accesses without a run-time penalty.
//
// The variable sized portion can either be used to create sub-writers, which
// themselves would provide compile-time bounds-checking, or data can be copied
// to it.
template <int FixedSize>
class BoundedByteWriter {
public:
explicit BoundedByteWriter(rtc::ArrayView<uint8_t> data) : data_(data) {
RTC_CHECK(data.size() >= FixedSize);
}
template <size_t offset>
void Store8(uint8_t value) {
static_assert(offset + sizeof(uint8_t) <= FixedSize, "Out-of-bounds");
internal::StoreBigEndian8(&data_[offset], value);
}
template <size_t offset>
void Store16(uint16_t value) {
static_assert(offset + sizeof(uint16_t) <= FixedSize, "Out-of-bounds");
static_assert((offset % sizeof(uint16_t)) == 0, "Unaligned access");
internal::StoreBigEndian16(&data_[offset], value);
}
template <size_t offset>
void Store32(uint32_t value) {
static_assert(offset + sizeof(uint32_t) <= FixedSize, "Out-of-bounds");
static_assert((offset % sizeof(uint32_t)) == 0, "Unaligned access");
internal::StoreBigEndian32(&data_[offset], value);
}
template <size_t SubSize>
BoundedByteWriter<SubSize> sub_writer(size_t variable_offset) {
RTC_CHECK(FixedSize + variable_offset + SubSize <= data_.size());
return BoundedByteWriter<SubSize>(
data_.subview(FixedSize + variable_offset, SubSize));
}
void CopyToVariableData(rtc::ArrayView<const uint8_t> source) {
size_t copy_size = std::min(source.size(), data_.size() - FixedSize);
if (source.data() == nullptr || copy_size == 0) {
return;
}
memcpy(data_.data() + FixedSize, source.data(), copy_size);
}
private:
rtc::ArrayView<uint8_t> data_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_BOUNDED_BYTE_WRITER_H_

View file

@ -0,0 +1,65 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/abort_chunk.h"
#include <stdint.h>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.7
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 6 |Reserved |T| Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / zero or more Error Causes /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int AbortChunk::kType;
absl::optional<AbortChunk> AbortChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
absl::optional<Parameters> error_causes =
Parameters::Parse(reader->variable_data());
if (!error_causes.has_value()) {
return absl::nullopt;
}
uint8_t flags = reader->Load8<1>();
bool filled_in_verification_tag = (flags & (1 << kFlagsBitT)) == 0;
return AbortChunk(filled_in_verification_tag, *std::move(error_causes));
}
void AbortChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> error_causes = error_causes_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, error_causes.size());
writer.Store8<1>(filled_in_verification_tag_ ? 0 : (1 << kFlagsBitT));
writer.CopyToVariableData(error_causes);
}
std::string AbortChunk::ToString() const {
return "ABORT";
}
} // namespace dcsctp

View file

@ -0,0 +1,64 @@
/*
* 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_PACKET_CHUNK_ABORT_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_ABORT_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.7
struct AbortChunkConfig : ChunkConfig {
static constexpr int kType = 6;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class AbortChunk : public Chunk, public TLVTrait<AbortChunkConfig> {
public:
static constexpr int kType = AbortChunkConfig::kType;
AbortChunk(bool filled_in_verification_tag, Parameters error_causes)
: filled_in_verification_tag_(filled_in_verification_tag),
error_causes_(std::move(error_causes)) {}
AbortChunk(AbortChunk&& other) = default;
AbortChunk& operator=(AbortChunk&& other) = default;
static absl::optional<AbortChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
bool filled_in_verification_tag() const {
return filled_in_verification_tag_;
}
const Parameters& error_causes() const { return error_causes_; }
private:
static constexpr int kFlagsBitT = 0;
bool filled_in_verification_tag_;
Parameters error_causes_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_ABORT_CHUNK_H_

View file

@ -0,0 +1,85 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/chunk.h"
#include <cstdint>
#include <memory>
#include <utility>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/common/math.h"
#include "net/dcsctp/packet/chunk/abort_chunk.h"
#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
#include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
#include "net/dcsctp/packet/chunk/data_chunk.h"
#include "net/dcsctp/packet/chunk/error_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
#include "net/dcsctp/packet/chunk/heartbeat_request_chunk.h"
#include "net/dcsctp/packet/chunk/idata_chunk.h"
#include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/init_ack_chunk.h"
#include "net/dcsctp/packet/chunk/init_chunk.h"
#include "net/dcsctp/packet/chunk/reconfig_chunk.h"
#include "net/dcsctp/packet/chunk/sack_chunk.h"
#include "net/dcsctp/packet/chunk/shutdown_ack_chunk.h"
#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
#include "net/dcsctp/packet/chunk/shutdown_complete_chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
template <class Chunk>
bool ParseAndPrint(uint8_t chunk_type,
rtc::ArrayView<const uint8_t> data,
rtc::StringBuilder& sb) {
if (chunk_type == Chunk::kType) {
absl::optional<Chunk> c = Chunk::Parse(data);
if (c.has_value()) {
sb << c->ToString();
} else {
sb << "Failed to parse chunk of type " << chunk_type;
}
return true;
}
return false;
}
std::string DebugConvertChunkToString(rtc::ArrayView<const uint8_t> data) {
rtc::StringBuilder sb;
if (data.empty()) {
sb << "Failed to parse chunk due to empty data";
} else {
uint8_t chunk_type = data[0];
if (!ParseAndPrint<DataChunk>(chunk_type, data, sb) &&
!ParseAndPrint<InitChunk>(chunk_type, data, sb) &&
!ParseAndPrint<InitAckChunk>(chunk_type, data, sb) &&
!ParseAndPrint<SackChunk>(chunk_type, data, sb) &&
!ParseAndPrint<HeartbeatRequestChunk>(chunk_type, data, sb) &&
!ParseAndPrint<HeartbeatAckChunk>(chunk_type, data, sb) &&
!ParseAndPrint<AbortChunk>(chunk_type, data, sb) &&
!ParseAndPrint<ErrorChunk>(chunk_type, data, sb) &&
!ParseAndPrint<CookieEchoChunk>(chunk_type, data, sb) &&
!ParseAndPrint<CookieAckChunk>(chunk_type, data, sb) &&
!ParseAndPrint<ShutdownChunk>(chunk_type, data, sb) &&
!ParseAndPrint<ShutdownAckChunk>(chunk_type, data, sb) &&
!ParseAndPrint<ShutdownCompleteChunk>(chunk_type, data, sb) &&
!ParseAndPrint<ReConfigChunk>(chunk_type, data, sb) &&
!ParseAndPrint<ForwardTsnChunk>(chunk_type, data, sb) &&
!ParseAndPrint<IDataChunk>(chunk_type, data, sb) &&
!ParseAndPrint<IForwardTsnChunk>(chunk_type, data, sb)) {
sb << "Unhandled chunk type: " << static_cast<int>(chunk_type);
}
}
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,63 @@
/*
* 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_PACKET_CHUNK_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_CHUNK_H_
#include <stddef.h>
#include <sys/types.h>
#include <cstdint>
#include <iterator>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/data.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// Base class for all SCTP chunks
class Chunk {
public:
Chunk() {}
virtual ~Chunk() = default;
// Chunks can contain data payloads that shouldn't be copied unnecessarily.
Chunk(Chunk&& other) = default;
Chunk& operator=(Chunk&& other) = default;
Chunk(const Chunk&) = delete;
Chunk& operator=(const Chunk&) = delete;
// Serializes the chunk to `out`, growing it as necessary.
virtual void SerializeTo(std::vector<uint8_t>& out) const = 0;
// Returns a human readable description of this chunk and its parameters.
virtual std::string ToString() const = 0;
};
// Introspects the chunk in `data` and returns a human readable textual
// representation of it, to be used in debugging.
std::string DebugConvertChunkToString(rtc::ArrayView<const uint8_t> data);
struct ChunkConfig {
static constexpr int kTypeSizeInBytes = 1;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_CHUNK_H_

View file

@ -0,0 +1,46 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
#include <stdint.h>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.12
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 11 |Chunk Flags | Length = 4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int CookieAckChunk::kType;
absl::optional<CookieAckChunk> CookieAckChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
if (!ParseTLV(data).has_value()) {
return absl::nullopt;
}
return CookieAckChunk();
}
void CookieAckChunk::SerializeTo(std::vector<uint8_t>& out) const {
AllocateTLV(out);
}
std::string CookieAckChunk::ToString() const {
return "COOKIE-ACK";
}
} // namespace dcsctp

View file

@ -0,0 +1,46 @@
/*
* 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_PACKET_CHUNK_COOKIE_ACK_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_COOKIE_ACK_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.12
struct CookieAckChunkConfig : ChunkConfig {
static constexpr int kType = 11;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class CookieAckChunk : public Chunk, public TLVTrait<CookieAckChunkConfig> {
public:
static constexpr int kType = CookieAckChunkConfig::kType;
CookieAckChunk() {}
static absl::optional<CookieAckChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_COOKIE_ACK_CHUNK_H_

View file

@ -0,0 +1,54 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.11
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 10 |Chunk Flags | Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / Cookie /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int CookieEchoChunk::kType;
absl::optional<CookieEchoChunk> CookieEchoChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
return CookieEchoChunk(reader->variable_data());
}
void CookieEchoChunk::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, cookie_.size());
writer.CopyToVariableData(cookie_);
}
std::string CookieEchoChunk::ToString() const {
return "COOKIE-ECHO";
}
} // namespace dcsctp

View file

@ -0,0 +1,53 @@
/*
* 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_PACKET_CHUNK_COOKIE_ECHO_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_COOKIE_ECHO_CHUNK_H_
#include <stddef.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.11
struct CookieEchoChunkConfig : ChunkConfig {
static constexpr int kType = 10;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class CookieEchoChunk : public Chunk, public TLVTrait<CookieEchoChunkConfig> {
public:
static constexpr int kType = CookieEchoChunkConfig::kType;
explicit CookieEchoChunk(rtc::ArrayView<const uint8_t> cookie)
: cookie_(cookie.begin(), cookie.end()) {}
static absl::optional<CookieEchoChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint8_t> cookie() const { return cookie_; }
private:
std::vector<uint8_t> cookie_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_COOKIE_ECHO_CHUNK_H_

View file

@ -0,0 +1,101 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/data_chunk.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/chunk/data_common.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 0 | Reserved|U|B|E| Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Identifier S | Stream Sequence Number n |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Payload Protocol Identifier |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / User Data (seq n of Stream S) /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int DataChunk::kType;
absl::optional<DataChunk> DataChunk::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
uint8_t flags = reader->Load8<1>();
TSN tsn(reader->Load32<4>());
StreamID stream_identifier(reader->Load16<8>());
SSN ssn(reader->Load16<10>());
PPID ppid(reader->Load32<12>());
Options options;
options.is_end = Data::IsEnd((flags & (1 << kFlagsBitEnd)) != 0);
options.is_beginning =
Data::IsBeginning((flags & (1 << kFlagsBitBeginning)) != 0);
options.is_unordered = IsUnordered((flags & (1 << kFlagsBitUnordered)) != 0);
options.immediate_ack =
ImmediateAckFlag((flags & (1 << kFlagsBitImmediateAck)) != 0);
return DataChunk(tsn, stream_identifier, ssn, ppid,
std::vector<uint8_t>(reader->variable_data().begin(),
reader->variable_data().end()),
options);
}
void DataChunk::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, payload().size());
writer.Store8<1>(
(*options().is_end ? (1 << kFlagsBitEnd) : 0) |
(*options().is_beginning ? (1 << kFlagsBitBeginning) : 0) |
(*options().is_unordered ? (1 << kFlagsBitUnordered) : 0) |
(*options().immediate_ack ? (1 << kFlagsBitImmediateAck) : 0));
writer.Store32<4>(*tsn());
writer.Store16<8>(*stream_id());
writer.Store16<10>(*ssn());
writer.Store32<12>(*ppid());
writer.CopyToVariableData(payload());
}
std::string DataChunk::ToString() const {
rtc::StringBuilder sb;
sb << "DATA, type=" << (options().is_unordered ? "unordered" : "ordered")
<< "::"
<< (*options().is_beginning && *options().is_end ? "complete"
: *options().is_beginning ? "first"
: *options().is_end ? "last"
: "middle")
<< ", tsn=" << *tsn() << ", sid=" << *stream_id() << ", ssn=" << *ssn()
<< ", ppid=" << *ppid() << ", length=" << payload().size();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,70 @@
/*
* 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_PACKET_CHUNK_DATA_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_DATA_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/chunk/data_common.h"
#include "net/dcsctp/packet/data.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.1
struct DataChunkConfig : ChunkConfig {
static constexpr int kType = 0;
static constexpr size_t kHeaderSize = 16;
static constexpr size_t kVariableLengthAlignment = 1;
};
class DataChunk : public AnyDataChunk, public TLVTrait<DataChunkConfig> {
public:
static constexpr int kType = DataChunkConfig::kType;
// Exposed to allow the retransmission queue to make room for the correct
// header size.
static constexpr size_t kHeaderSize = DataChunkConfig::kHeaderSize;
DataChunk(TSN tsn,
StreamID stream_id,
SSN ssn,
PPID ppid,
std::vector<uint8_t> payload,
const Options& options)
: AnyDataChunk(tsn,
stream_id,
ssn,
MID(0),
FSN(0),
ppid,
std::move(payload),
options) {}
DataChunk(TSN tsn, Data&& data, bool immediate_ack)
: AnyDataChunk(tsn, std::move(data), immediate_ack) {}
static absl::optional<DataChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_DATA_CHUNK_H_

View file

@ -0,0 +1,97 @@
/*
* 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_PACKET_CHUNK_DATA_COMMON_H_
#define NET_DCSCTP_PACKET_CHUNK_DATA_COMMON_H_
#include <stdint.h>
#include <utility>
#include <vector>
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/data.h"
namespace dcsctp {
// Base class for DataChunk and IDataChunk
class AnyDataChunk : public Chunk {
public:
// Represents the "immediate ack" flag on DATA/I-DATA, from RFC7053.
using ImmediateAckFlag = webrtc::StrongAlias<class ImmediateAckFlagTag, bool>;
// Data chunk options.
// See https://tools.ietf.org/html/rfc4960#section-3.3.1
struct Options {
Data::IsEnd is_end = Data::IsEnd(false);
Data::IsBeginning is_beginning = Data::IsBeginning(false);
IsUnordered is_unordered = IsUnordered(false);
ImmediateAckFlag immediate_ack = ImmediateAckFlag(false);
};
TSN tsn() const { return tsn_; }
Options options() const {
Options options;
options.is_end = data_.is_end;
options.is_beginning = data_.is_beginning;
options.is_unordered = data_.is_unordered;
options.immediate_ack = immediate_ack_;
return options;
}
StreamID stream_id() const { return data_.stream_id; }
SSN ssn() const { return data_.ssn; }
MID mid() const { return data_.mid; }
FSN fsn() const { return data_.fsn; }
PPID ppid() const { return data_.ppid; }
rtc::ArrayView<const uint8_t> payload() const { return data_.payload; }
// Extracts the Data from the chunk, as a destructive action.
Data extract() && { return std::move(data_); }
AnyDataChunk(TSN tsn,
StreamID stream_id,
SSN ssn,
MID mid,
FSN fsn,
PPID ppid,
std::vector<uint8_t> payload,
const Options& options)
: tsn_(tsn),
data_(stream_id,
ssn,
mid,
fsn,
ppid,
std::move(payload),
options.is_beginning,
options.is_end,
options.is_unordered),
immediate_ack_(options.immediate_ack) {}
AnyDataChunk(TSN tsn, Data data, bool immediate_ack)
: tsn_(tsn), data_(std::move(data)), immediate_ack_(immediate_ack) {}
protected:
// Bits in `flags` header field.
static constexpr int kFlagsBitEnd = 0;
static constexpr int kFlagsBitBeginning = 1;
static constexpr int kFlagsBitUnordered = 2;
static constexpr int kFlagsBitImmediateAck = 3;
private:
TSN tsn_;
Data data_;
ImmediateAckFlag immediate_ack_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_DATA_COMMON_H_

View file

@ -0,0 +1,62 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/error_chunk.h"
#include <stdint.h>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 9 | Chunk Flags | Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / one or more Error Causes /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ErrorChunk::kType;
absl::optional<ErrorChunk> ErrorChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
absl::optional<Parameters> error_causes =
Parameters::Parse(reader->variable_data());
if (!error_causes.has_value()) {
return absl::nullopt;
}
return ErrorChunk(*std::move(error_causes));
}
void ErrorChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> error_causes = error_causes_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, error_causes.size());
writer.CopyToVariableData(error_causes);
}
std::string ErrorChunk::ToString() const {
return "ERROR";
}
} // namespace dcsctp

View file

@ -0,0 +1,57 @@
/*
* 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_PACKET_CHUNK_ERROR_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_ERROR_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10
struct ErrorChunkConfig : ChunkConfig {
static constexpr int kType = 9;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 4;
};
class ErrorChunk : public Chunk, public TLVTrait<ErrorChunkConfig> {
public:
static constexpr int kType = ErrorChunkConfig::kType;
explicit ErrorChunk(Parameters error_causes)
: error_causes_(std::move(error_causes)) {}
ErrorChunk(ErrorChunk&& other) = default;
ErrorChunk& operator=(ErrorChunk&& other) = default;
static absl::optional<ErrorChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
const Parameters& error_causes() const { return error_causes_; }
private:
Parameters error_causes_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_ERROR_CHUNK_H_

View file

@ -0,0 +1,95 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc3758#section-3.2
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 192 | Flags = 0x00 | Length = Variable |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | New Cumulative TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream-1 | Stream Sequence-1 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ /
// / \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream-N | Stream Sequence-N |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ForwardTsnChunk::kType;
absl::optional<ForwardTsnChunk> ForwardTsnChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
TSN new_cumulative_tsn(reader->Load32<4>());
size_t streams_skipped =
reader->variable_data_size() / kSkippedStreamBufferSize;
std::vector<SkippedStream> skipped_streams;
skipped_streams.reserve(streams_skipped);
for (size_t i = 0; i < streams_skipped; ++i) {
BoundedByteReader<kSkippedStreamBufferSize> sub_reader =
reader->sub_reader<kSkippedStreamBufferSize>(i *
kSkippedStreamBufferSize);
StreamID stream_id(sub_reader.Load16<0>());
SSN ssn(sub_reader.Load16<2>());
skipped_streams.emplace_back(stream_id, ssn);
}
return ForwardTsnChunk(new_cumulative_tsn, std::move(skipped_streams));
}
void ForwardTsnChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const SkippedStream> skipped = skipped_streams();
size_t variable_size = skipped.size() * kSkippedStreamBufferSize;
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(*new_cumulative_tsn());
for (size_t i = 0; i < skipped.size(); ++i) {
BoundedByteWriter<kSkippedStreamBufferSize> sub_writer =
writer.sub_writer<kSkippedStreamBufferSize>(i *
kSkippedStreamBufferSize);
sub_writer.Store16<0>(*skipped[i].stream_id);
sub_writer.Store16<2>(*skipped[i].ssn);
}
}
std::string ForwardTsnChunk::ToString() const {
rtc::StringBuilder sb;
sb << "FORWARD-TSN, new_cumulative_tsn=" << *new_cumulative_tsn();
for (const auto& skipped : skipped_streams()) {
sb << ", skip " << skipped.stream_id.value() << ":" << *skipped.ssn;
}
return sb.str();
}
} // namespace dcsctp

View file

@ -0,0 +1,55 @@
/*
* 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_PACKET_CHUNK_FORWARD_TSN_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_FORWARD_TSN_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc3758#section-3.2
struct ForwardTsnChunkConfig : ChunkConfig {
static constexpr int kType = 192;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 4;
};
class ForwardTsnChunk : public AnyForwardTsnChunk,
public TLVTrait<ForwardTsnChunkConfig> {
public:
static constexpr int kType = ForwardTsnChunkConfig::kType;
ForwardTsnChunk(TSN new_cumulative_tsn,
std::vector<SkippedStream> skipped_streams)
: AnyForwardTsnChunk(new_cumulative_tsn, std::move(skipped_streams)) {}
static absl::optional<ForwardTsnChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
private:
static constexpr size_t kSkippedStreamBufferSize = 4;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_FORWARD_TSN_CHUNK_H_

View file

@ -0,0 +1,63 @@
/*
* 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_PACKET_CHUNK_FORWARD_TSN_COMMON_H_
#define NET_DCSCTP_PACKET_CHUNK_FORWARD_TSN_COMMON_H_
#include <stdint.h>
#include <utility>
#include <vector>
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
namespace dcsctp {
// Base class for both ForwardTsnChunk and IForwardTsnChunk
class AnyForwardTsnChunk : public Chunk {
public:
struct SkippedStream {
SkippedStream(StreamID stream_id, SSN ssn)
: stream_id(stream_id), ssn(ssn), unordered(false), mid(0) {}
SkippedStream(IsUnordered unordered, StreamID stream_id, MID mid)
: stream_id(stream_id), ssn(0), unordered(unordered), mid(mid) {}
StreamID stream_id;
// Set for FORWARD_TSN
SSN ssn;
// Set for I-FORWARD_TSN
IsUnordered unordered;
MID mid;
bool operator==(const SkippedStream& other) const {
return stream_id == other.stream_id && ssn == other.ssn &&
unordered == other.unordered && mid == other.mid;
}
};
AnyForwardTsnChunk(TSN new_cumulative_tsn,
std::vector<SkippedStream> skipped_streams)
: new_cumulative_tsn_(new_cumulative_tsn),
skipped_streams_(std::move(skipped_streams)) {}
TSN new_cumulative_tsn() const { return new_cumulative_tsn_; }
rtc::ArrayView<const SkippedStream> skipped_streams() const {
return skipped_streams_;
}
private:
TSN new_cumulative_tsn_;
std::vector<SkippedStream> skipped_streams_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_FORWARD_TSN_COMMON_H_

View file

@ -0,0 +1,63 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
#include <stdint.h>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.6
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 5 | Chunk Flags | Heartbeat Ack Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Heartbeat Information TLV (Variable-Length) /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int HeartbeatAckChunk::kType;
absl::optional<HeartbeatAckChunk> HeartbeatAckChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
absl::optional<Parameters> parameters =
Parameters::Parse(reader->variable_data());
if (!parameters.has_value()) {
return absl::nullopt;
}
return HeartbeatAckChunk(*std::move(parameters));
}
void HeartbeatAckChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> parameters = parameters_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, parameters.size());
writer.CopyToVariableData(parameters);
}
std::string HeartbeatAckChunk::ToString() const {
return "HEARTBEAT-ACK";
}
} // namespace dcsctp

View file

@ -0,0 +1,63 @@
/*
* 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_PACKET_CHUNK_HEARTBEAT_ACK_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_HEARTBEAT_ACK_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.6
struct HeartbeatAckChunkConfig : ChunkConfig {
static constexpr int kType = 5;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class HeartbeatAckChunk : public Chunk,
public TLVTrait<HeartbeatAckChunkConfig> {
public:
static constexpr int kType = HeartbeatAckChunkConfig::kType;
explicit HeartbeatAckChunk(Parameters parameters)
: parameters_(std::move(parameters)) {}
HeartbeatAckChunk(HeartbeatAckChunk&& other) = default;
HeartbeatAckChunk& operator=(HeartbeatAckChunk&& other) = default;
static absl::optional<HeartbeatAckChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
const Parameters& parameters() const { return parameters_; }
absl::optional<HeartbeatInfoParameter> info() const {
return parameters_.get<HeartbeatInfoParameter>();
}
private:
Parameters parameters_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_HEARTBEAT_ACK_CHUNK_H_

View file

@ -0,0 +1,64 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/heartbeat_request_chunk.h"
#include <stdint.h>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.5
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 4 | Chunk Flags | Heartbeat Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Heartbeat Information TLV (Variable-Length) /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int HeartbeatRequestChunk::kType;
absl::optional<HeartbeatRequestChunk> HeartbeatRequestChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
absl::optional<Parameters> parameters =
Parameters::Parse(reader->variable_data());
if (!parameters.has_value()) {
return absl::nullopt;
}
return HeartbeatRequestChunk(*std::move(parameters));
}
void HeartbeatRequestChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> parameters = parameters_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, parameters.size());
writer.CopyToVariableData(parameters);
}
std::string HeartbeatRequestChunk::ToString() const {
return "HEARTBEAT";
}
} // namespace dcsctp

View file

@ -0,0 +1,62 @@
/*
* 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_PACKET_CHUNK_HEARTBEAT_REQUEST_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_HEARTBEAT_REQUEST_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.5
struct HeartbeatRequestChunkConfig : ChunkConfig {
static constexpr int kType = 4;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class HeartbeatRequestChunk : public Chunk,
public TLVTrait<HeartbeatRequestChunkConfig> {
public:
static constexpr int kType = HeartbeatRequestChunkConfig::kType;
explicit HeartbeatRequestChunk(Parameters parameters)
: parameters_(std::move(parameters)) {}
HeartbeatRequestChunk(HeartbeatRequestChunk&& other) = default;
HeartbeatRequestChunk& operator=(HeartbeatRequestChunk&& other) = default;
static absl::optional<HeartbeatRequestChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
const Parameters& parameters() const { return parameters_; }
Parameters extract_parameters() && { return std::move(parameters_); }
absl::optional<HeartbeatInfoParameter> info() const {
return parameters_.get<HeartbeatInfoParameter>();
}
private:
Parameters parameters_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_HEARTBEAT_REQUEST_CHUNK_H_

View file

@ -0,0 +1,111 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/idata_chunk.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/chunk/data_common.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc8260#section-2.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 64 | Res |I|U|B|E| Length = Variable |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Identifier | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Message Identifier |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Payload Protocol Identifier / Fragment Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / User Data /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int IDataChunk::kType;
absl::optional<IDataChunk> IDataChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
uint8_t flags = reader->Load8<1>();
TSN tsn(reader->Load32<4>());
StreamID stream_identifier(reader->Load16<8>());
MID mid(reader->Load32<12>());
uint32_t ppid_or_fsn = reader->Load32<16>();
Options options;
options.is_end = Data::IsEnd((flags & (1 << kFlagsBitEnd)) != 0);
options.is_beginning =
Data::IsBeginning((flags & (1 << kFlagsBitBeginning)) != 0);
options.is_unordered = IsUnordered((flags & (1 << kFlagsBitUnordered)) != 0);
options.immediate_ack =
ImmediateAckFlag((flags & (1 << kFlagsBitImmediateAck)) != 0);
return IDataChunk(tsn, stream_identifier, mid,
PPID(options.is_beginning ? ppid_or_fsn : 0),
FSN(options.is_beginning ? 0 : ppid_or_fsn),
std::vector<uint8_t>(reader->variable_data().begin(),
reader->variable_data().end()),
options);
}
void IDataChunk::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, payload().size());
writer.Store8<1>(
(*options().is_end ? (1 << kFlagsBitEnd) : 0) |
(*options().is_beginning ? (1 << kFlagsBitBeginning) : 0) |
(*options().is_unordered ? (1 << kFlagsBitUnordered) : 0) |
(*options().immediate_ack ? (1 << kFlagsBitImmediateAck) : 0));
writer.Store32<4>(*tsn());
writer.Store16<8>(*stream_id());
writer.Store32<12>(*mid());
writer.Store32<16>(options().is_beginning ? *ppid() : *fsn());
writer.CopyToVariableData(payload());
}
std::string IDataChunk::ToString() const {
rtc::StringBuilder sb;
sb << "I-DATA, type=" << (options().is_unordered ? "unordered" : "ordered")
<< "::"
<< (*options().is_beginning && *options().is_end ? "complete"
: *options().is_beginning ? "first"
: *options().is_end ? "last"
: "middle")
<< ", tsn=" << *tsn() << ", stream_id=" << *stream_id()
<< ", mid=" << *mid();
if (*options().is_beginning) {
sb << ", ppid=" << *ppid();
} else {
sb << ", fsn=" << *fsn();
}
sb << ", length=" << payload().size();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,70 @@
/*
* 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_PACKET_CHUNK_IDATA_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_IDATA_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/chunk/data_common.h"
#include "net/dcsctp/packet/data.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc8260#section-2.1
struct IDataChunkConfig : ChunkConfig {
static constexpr int kType = 64;
static constexpr size_t kHeaderSize = 20;
static constexpr size_t kVariableLengthAlignment = 1;
};
class IDataChunk : public AnyDataChunk, public TLVTrait<IDataChunkConfig> {
public:
static constexpr int kType = IDataChunkConfig::kType;
// Exposed to allow the retransmission queue to make room for the correct
// header size.
static constexpr size_t kHeaderSize = IDataChunkConfig::kHeaderSize;
IDataChunk(TSN tsn,
StreamID stream_id,
MID mid,
PPID ppid,
FSN fsn,
std::vector<uint8_t> payload,
const Options& options)
: AnyDataChunk(tsn,
stream_id,
SSN(0),
mid,
fsn,
ppid,
std::move(payload),
options) {}
explicit IDataChunk(TSN tsn, Data&& data, bool immediate_ack)
: AnyDataChunk(tsn, std::move(data), immediate_ack) {}
static absl::optional<IDataChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_IDATA_CHUNK_H_

View file

@ -0,0 +1,104 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc8260#section-2.3.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 194 | Flags = 0x00 | Length = Variable |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | New Cumulative TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Identifier | Reserved |U|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Message Identifier |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Identifier | Reserved |U|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Message Identifier |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int IForwardTsnChunk::kType;
absl::optional<IForwardTsnChunk> IForwardTsnChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
TSN new_cumulative_tsn(reader->Load32<4>());
size_t streams_skipped =
reader->variable_data_size() / kSkippedStreamBufferSize;
std::vector<SkippedStream> skipped_streams;
skipped_streams.reserve(streams_skipped);
size_t offset = 0;
for (size_t i = 0; i < streams_skipped; ++i) {
BoundedByteReader<kSkippedStreamBufferSize> sub_reader =
reader->sub_reader<kSkippedStreamBufferSize>(offset);
StreamID stream_id(sub_reader.Load16<0>());
IsUnordered unordered(sub_reader.Load8<3>() & 0x01);
MID mid(sub_reader.Load32<4>());
skipped_streams.emplace_back(unordered, stream_id, mid);
offset += kSkippedStreamBufferSize;
}
RTC_DCHECK(offset == reader->variable_data_size());
return IForwardTsnChunk(new_cumulative_tsn, std::move(skipped_streams));
}
void IForwardTsnChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const SkippedStream> skipped = skipped_streams();
size_t variable_size = skipped.size() * kSkippedStreamBufferSize;
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(*new_cumulative_tsn());
size_t offset = 0;
for (size_t i = 0; i < skipped.size(); ++i) {
BoundedByteWriter<kSkippedStreamBufferSize> sub_writer =
writer.sub_writer<kSkippedStreamBufferSize>(offset);
sub_writer.Store16<0>(*skipped[i].stream_id);
sub_writer.Store8<3>(skipped[i].unordered ? 1 : 0);
sub_writer.Store32<4>(*skipped[i].mid);
offset += kSkippedStreamBufferSize;
}
RTC_DCHECK(offset == variable_size);
}
std::string IForwardTsnChunk::ToString() const {
rtc::StringBuilder sb;
sb << "I-FORWARD-TSN, new_cumulative_tsn=" << *new_cumulative_tsn();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,54 @@
/*
* 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_PACKET_CHUNK_IFORWARD_TSN_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_IFORWARD_TSN_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc8260#section-2.3.1
struct IForwardTsnChunkConfig : ChunkConfig {
static constexpr int kType = 194;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 8;
};
class IForwardTsnChunk : public AnyForwardTsnChunk,
public TLVTrait<IForwardTsnChunkConfig> {
public:
static constexpr int kType = IForwardTsnChunkConfig::kType;
IForwardTsnChunk(TSN new_cumulative_tsn,
std::vector<SkippedStream> skipped_streams)
: AnyForwardTsnChunk(new_cumulative_tsn, std::move(skipped_streams)) {}
static absl::optional<IForwardTsnChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
private:
static constexpr size_t kSkippedStreamBufferSize = 8;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_IFORWARD_TSN_CHUNK_H_

View file

@ -0,0 +1,86 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/init_ack_chunk.h"
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_format.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.3
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 2 | Chunk Flags | Chunk Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Initiate Tag |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Advertised Receiver Window Credit |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Number of Outbound Streams | Number of Inbound Streams |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Initial TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Optional/Variable-Length Parameters /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int InitAckChunk::kType;
absl::optional<InitAckChunk> InitAckChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
VerificationTag initiate_tag(reader->Load32<4>());
uint32_t a_rwnd = reader->Load32<8>();
uint16_t nbr_outbound_streams = reader->Load16<12>();
uint16_t nbr_inbound_streams = reader->Load16<14>();
TSN initial_tsn(reader->Load32<16>());
absl::optional<Parameters> parameters =
Parameters::Parse(reader->variable_data());
if (!parameters.has_value()) {
return absl::nullopt;
}
return InitAckChunk(initiate_tag, a_rwnd, nbr_outbound_streams,
nbr_inbound_streams, initial_tsn, *std::move(parameters));
}
void InitAckChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> parameters = parameters_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, parameters.size());
writer.Store32<4>(*initiate_tag_);
writer.Store32<8>(a_rwnd_);
writer.Store16<12>(nbr_outbound_streams_);
writer.Store16<14>(nbr_inbound_streams_);
writer.Store32<16>(*initial_tsn_);
writer.CopyToVariableData(parameters);
}
std::string InitAckChunk::ToString() const {
return rtc::StringFormat("INIT_ACK, initiate_tag=0x%0x, initial_tsn=%u",
*initiate_tag(), *initial_tsn());
}
} // namespace dcsctp

View file

@ -0,0 +1,77 @@
/*
* 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_PACKET_CHUNK_INIT_ACK_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_INIT_ACK_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.3
struct InitAckChunkConfig : ChunkConfig {
static constexpr int kType = 2;
static constexpr size_t kHeaderSize = 20;
static constexpr size_t kVariableLengthAlignment = 1;
};
class InitAckChunk : public Chunk, public TLVTrait<InitAckChunkConfig> {
public:
static constexpr int kType = InitAckChunkConfig::kType;
InitAckChunk(VerificationTag initiate_tag,
uint32_t a_rwnd,
uint16_t nbr_outbound_streams,
uint16_t nbr_inbound_streams,
TSN initial_tsn,
Parameters parameters)
: initiate_tag_(initiate_tag),
a_rwnd_(a_rwnd),
nbr_outbound_streams_(nbr_outbound_streams),
nbr_inbound_streams_(nbr_inbound_streams),
initial_tsn_(initial_tsn),
parameters_(std::move(parameters)) {}
InitAckChunk(InitAckChunk&& other) = default;
InitAckChunk& operator=(InitAckChunk&& other) = default;
static absl::optional<InitAckChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
VerificationTag initiate_tag() const { return initiate_tag_; }
uint32_t a_rwnd() const { return a_rwnd_; }
uint16_t nbr_outbound_streams() const { return nbr_outbound_streams_; }
uint16_t nbr_inbound_streams() const { return nbr_inbound_streams_; }
TSN initial_tsn() const { return initial_tsn_; }
const Parameters& parameters() const { return parameters_; }
private:
VerificationTag initiate_tag_;
uint32_t a_rwnd_;
uint16_t nbr_outbound_streams_;
uint16_t nbr_inbound_streams_;
TSN initial_tsn_;
Parameters parameters_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_INIT_ACK_CHUNK_H_

View file

@ -0,0 +1,88 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/init_chunk.h"
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_format.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.2
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 1 | Chunk Flags | Chunk Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Initiate Tag |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Advertised Receiver Window Credit (a_rwnd) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Number of Outbound Streams | Number of Inbound Streams |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Initial TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Optional/Variable-Length Parameters /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int InitChunk::kType;
absl::optional<InitChunk> InitChunk::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
VerificationTag initiate_tag(reader->Load32<4>());
uint32_t a_rwnd = reader->Load32<8>();
uint16_t nbr_outbound_streams = reader->Load16<12>();
uint16_t nbr_inbound_streams = reader->Load16<14>();
TSN initial_tsn(reader->Load32<16>());
absl::optional<Parameters> parameters =
Parameters::Parse(reader->variable_data());
if (!parameters.has_value()) {
return absl::nullopt;
}
return InitChunk(initiate_tag, a_rwnd, nbr_outbound_streams,
nbr_inbound_streams, initial_tsn, *std::move(parameters));
}
void InitChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> parameters = parameters_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, parameters.size());
writer.Store32<4>(*initiate_tag_);
writer.Store32<8>(a_rwnd_);
writer.Store16<12>(nbr_outbound_streams_);
writer.Store16<14>(nbr_inbound_streams_);
writer.Store32<16>(*initial_tsn_);
writer.CopyToVariableData(parameters);
}
std::string InitChunk::ToString() const {
return rtc::StringFormat("INIT, initiate_tag=0x%0x, initial_tsn=%u",
*initiate_tag(), *initial_tsn());
}
} // namespace dcsctp

View file

@ -0,0 +1,77 @@
/*
* 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_PACKET_CHUNK_INIT_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_INIT_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.2
struct InitChunkConfig : ChunkConfig {
static constexpr int kType = 1;
static constexpr size_t kHeaderSize = 20;
static constexpr size_t kVariableLengthAlignment = 1;
};
class InitChunk : public Chunk, public TLVTrait<InitChunkConfig> {
public:
static constexpr int kType = InitChunkConfig::kType;
InitChunk(VerificationTag initiate_tag,
uint32_t a_rwnd,
uint16_t nbr_outbound_streams,
uint16_t nbr_inbound_streams,
TSN initial_tsn,
Parameters parameters)
: initiate_tag_(initiate_tag),
a_rwnd_(a_rwnd),
nbr_outbound_streams_(nbr_outbound_streams),
nbr_inbound_streams_(nbr_inbound_streams),
initial_tsn_(initial_tsn),
parameters_(std::move(parameters)) {}
InitChunk(InitChunk&& other) = default;
InitChunk& operator=(InitChunk&& other) = default;
static absl::optional<InitChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
VerificationTag initiate_tag() const { return initiate_tag_; }
uint32_t a_rwnd() const { return a_rwnd_; }
uint16_t nbr_outbound_streams() const { return nbr_outbound_streams_; }
uint16_t nbr_inbound_streams() const { return nbr_inbound_streams_; }
TSN initial_tsn() const { return initial_tsn_; }
const Parameters& parameters() const { return parameters_; }
private:
VerificationTag initiate_tag_;
uint32_t a_rwnd_;
uint16_t nbr_outbound_streams_;
uint16_t nbr_inbound_streams_;
TSN initial_tsn_;
Parameters parameters_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_INIT_CHUNK_H_

View file

@ -0,0 +1,69 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/reconfig_chunk.h"
#include <stdint.h>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-3.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 130 | Chunk Flags | Chunk Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Re-configuration Parameter /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Re-configuration Parameter (optional) /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ReConfigChunk::kType;
absl::optional<ReConfigChunk> ReConfigChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
absl::optional<Parameters> parameters =
Parameters::Parse(reader->variable_data());
if (!parameters.has_value()) {
return absl::nullopt;
}
return ReConfigChunk(*std::move(parameters));
}
void ReConfigChunk::SerializeTo(std::vector<uint8_t>& out) const {
rtc::ArrayView<const uint8_t> parameters = parameters_.data();
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, parameters.size());
writer.CopyToVariableData(parameters);
}
std::string ReConfigChunk::ToString() const {
return "RE-CONFIG";
}
} // namespace dcsctp

View file

@ -0,0 +1,56 @@
/*
* 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_PACKET_CHUNK_RECONFIG_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_RECONFIG_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-3.1
struct ReConfigChunkConfig : ChunkConfig {
static constexpr int kType = 130;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class ReConfigChunk : public Chunk, public TLVTrait<ReConfigChunkConfig> {
public:
static constexpr int kType = ReConfigChunkConfig::kType;
explicit ReConfigChunk(Parameters parameters)
: parameters_(std::move(parameters)) {}
static absl::optional<ReConfigChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
const Parameters& parameters() const { return parameters_; }
Parameters extract_parameters() { return std::move(parameters_); }
private:
Parameters parameters_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_RECONFIG_CHUNK_H_

View file

@ -0,0 +1,155 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/sack_chunk.h"
#include <stddef.h>
#include <cstdint>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/str_join.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.4
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 3 |Chunk Flags | Chunk Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cumulative TSN Ack |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Advertised Receiver Window Credit (a_rwnd) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Number of Gap Ack Blocks = N | Number of Duplicate TSNs = X |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Gap Ack Block #1 Start | Gap Ack Block #1 End |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / /
// \ ... \
// / /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Gap Ack Block #N Start | Gap Ack Block #N End |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Duplicate TSN 1 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / /
// \ ... \
// / /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Duplicate TSN X |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int SackChunk::kType;
absl::optional<SackChunk> SackChunk::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
TSN tsn_ack(reader->Load32<4>());
uint32_t a_rwnd = reader->Load32<8>();
uint16_t nbr_of_gap_blocks = reader->Load16<12>();
uint16_t nbr_of_dup_tsns = reader->Load16<14>();
if (reader->variable_data_size() != nbr_of_gap_blocks * kGapAckBlockSize +
nbr_of_dup_tsns * kDupTsnBlockSize) {
RTC_DLOG(LS_WARNING) << "Invalid number of gap blocks or duplicate TSNs";
return absl::nullopt;
}
std::vector<GapAckBlock> gap_ack_blocks;
gap_ack_blocks.reserve(nbr_of_gap_blocks);
size_t offset = 0;
for (int i = 0; i < nbr_of_gap_blocks; ++i) {
BoundedByteReader<kGapAckBlockSize> sub_reader =
reader->sub_reader<kGapAckBlockSize>(offset);
uint16_t start = sub_reader.Load16<0>();
uint16_t end = sub_reader.Load16<2>();
gap_ack_blocks.emplace_back(start, end);
offset += kGapAckBlockSize;
}
std::set<TSN> duplicate_tsns;
for (int i = 0; i < nbr_of_dup_tsns; ++i) {
BoundedByteReader<kDupTsnBlockSize> sub_reader =
reader->sub_reader<kDupTsnBlockSize>(offset);
duplicate_tsns.insert(TSN(sub_reader.Load32<0>()));
offset += kDupTsnBlockSize;
}
RTC_DCHECK(offset == reader->variable_data_size());
return SackChunk(tsn_ack, a_rwnd, gap_ack_blocks, duplicate_tsns);
}
void SackChunk::SerializeTo(std::vector<uint8_t>& out) const {
int nbr_of_gap_blocks = gap_ack_blocks_.size();
int nbr_of_dup_tsns = duplicate_tsns_.size();
size_t variable_size =
nbr_of_gap_blocks * kGapAckBlockSize + nbr_of_dup_tsns * kDupTsnBlockSize;
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(*cumulative_tsn_ack_);
writer.Store32<8>(a_rwnd_);
writer.Store16<12>(nbr_of_gap_blocks);
writer.Store16<14>(nbr_of_dup_tsns);
size_t offset = 0;
for (int i = 0; i < nbr_of_gap_blocks; ++i) {
BoundedByteWriter<kGapAckBlockSize> sub_writer =
writer.sub_writer<kGapAckBlockSize>(offset);
sub_writer.Store16<0>(gap_ack_blocks_[i].start);
sub_writer.Store16<2>(gap_ack_blocks_[i].end);
offset += kGapAckBlockSize;
}
for (TSN tsn : duplicate_tsns_) {
BoundedByteWriter<kDupTsnBlockSize> sub_writer =
writer.sub_writer<kDupTsnBlockSize>(offset);
sub_writer.Store32<0>(*tsn);
offset += kDupTsnBlockSize;
}
RTC_DCHECK(offset == variable_size);
}
std::string SackChunk::ToString() const {
rtc::StringBuilder sb;
sb << "SACK, cum_ack_tsn=" << *cumulative_tsn_ack()
<< ", a_rwnd=" << a_rwnd();
for (const GapAckBlock& gap : gap_ack_blocks_) {
uint32_t first = *cumulative_tsn_ack_ + gap.start;
uint32_t last = *cumulative_tsn_ack_ + gap.end;
sb << ", gap=" << first << "--" << last;
}
if (!duplicate_tsns_.empty()) {
sb << ", dup_tsns="
<< StrJoin(duplicate_tsns(), ",",
[](rtc::StringBuilder& sb, TSN tsn) { sb << *tsn; });
}
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,80 @@
/*
* 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_PACKET_CHUNK_SACK_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_SACK_CHUNK_H_
#include <stddef.h>
#include <cstdint>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.4
struct SackChunkConfig : ChunkConfig {
static constexpr int kType = 3;
static constexpr size_t kHeaderSize = 16;
static constexpr size_t kVariableLengthAlignment = 4;
};
class SackChunk : public Chunk, public TLVTrait<SackChunkConfig> {
public:
static constexpr int kType = SackChunkConfig::kType;
struct GapAckBlock {
GapAckBlock(uint16_t start, uint16_t end) : start(start), end(end) {}
uint16_t start;
uint16_t end;
bool operator==(const GapAckBlock& other) const {
return start == other.start && end == other.end;
}
};
SackChunk(TSN cumulative_tsn_ack,
uint32_t a_rwnd,
std::vector<GapAckBlock> gap_ack_blocks,
std::set<TSN> duplicate_tsns)
: cumulative_tsn_ack_(cumulative_tsn_ack),
a_rwnd_(a_rwnd),
gap_ack_blocks_(std::move(gap_ack_blocks)),
duplicate_tsns_(std::move(duplicate_tsns)) {}
static absl::optional<SackChunk> Parse(rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
TSN cumulative_tsn_ack() const { return cumulative_tsn_ack_; }
uint32_t a_rwnd() const { return a_rwnd_; }
rtc::ArrayView<const GapAckBlock> gap_ack_blocks() const {
return gap_ack_blocks_;
}
const std::set<TSN>& duplicate_tsns() const { return duplicate_tsns_; }
private:
static constexpr size_t kGapAckBlockSize = 4;
static constexpr size_t kDupTsnBlockSize = 4;
const TSN cumulative_tsn_ack_;
const uint32_t a_rwnd_;
std::vector<GapAckBlock> gap_ack_blocks_;
std::set<TSN> duplicate_tsns_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_SACK_CHUNK_H_

View file

@ -0,0 +1,46 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/shutdown_ack_chunk.h"
#include <stdint.h>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.9
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 8 |Chunk Flags | Length = 4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ShutdownAckChunk::kType;
absl::optional<ShutdownAckChunk> ShutdownAckChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
if (!ParseTLV(data).has_value()) {
return absl::nullopt;
}
return ShutdownAckChunk();
}
void ShutdownAckChunk::SerializeTo(std::vector<uint8_t>& out) const {
AllocateTLV(out);
}
std::string ShutdownAckChunk::ToString() const {
return "SHUTDOWN-ACK";
}
} // namespace dcsctp

View file

@ -0,0 +1,47 @@
/*
* 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_PACKET_CHUNK_SHUTDOWN_ACK_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_SHUTDOWN_ACK_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.9
struct ShutdownAckChunkConfig : ChunkConfig {
static constexpr int kType = 8;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class ShutdownAckChunk : public Chunk, public TLVTrait<ShutdownAckChunkConfig> {
public:
static constexpr int kType = ShutdownAckChunkConfig::kType;
ShutdownAckChunk() {}
static absl::optional<ShutdownAckChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_SHUTDOWN_ACK_CHUNK_H_

View file

@ -0,0 +1,55 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.8
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 7 | Chunk Flags | Length = 8 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cumulative TSN Ack |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ShutdownChunk::kType;
absl::optional<ShutdownChunk> ShutdownChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
TSN cumulative_tsn_ack(reader->Load32<4>());
return ShutdownChunk(cumulative_tsn_ack);
}
void ShutdownChunk::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store32<4>(*cumulative_tsn_ack_);
}
std::string ShutdownChunk::ToString() const {
return "SHUTDOWN";
}
} // namespace dcsctp

View file

@ -0,0 +1,53 @@
/*
* 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_PACKET_CHUNK_SHUTDOWN_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_SHUTDOWN_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.8
struct ShutdownChunkConfig : ChunkConfig {
static constexpr int kType = 7;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 0;
};
class ShutdownChunk : public Chunk, public TLVTrait<ShutdownChunkConfig> {
public:
static constexpr int kType = ShutdownChunkConfig::kType;
explicit ShutdownChunk(TSN cumulative_tsn_ack)
: cumulative_tsn_ack_(cumulative_tsn_ack) {}
static absl::optional<ShutdownChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
TSN cumulative_tsn_ack() const { return cumulative_tsn_ack_; }
private:
TSN cumulative_tsn_ack_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_SHUTDOWN_CHUNK_H_

View file

@ -0,0 +1,54 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk/shutdown_complete_chunk.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.13
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 14 |Reserved |T| Length = 4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ShutdownCompleteChunk::kType;
absl::optional<ShutdownCompleteChunk> ShutdownCompleteChunk::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
uint8_t flags = reader->Load8<1>();
bool tag_reflected = (flags & (1 << kFlagsBitT)) != 0;
return ShutdownCompleteChunk(tag_reflected);
}
void ShutdownCompleteChunk::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store8<1>(tag_reflected_ ? (1 << kFlagsBitT) : 0);
}
std::string ShutdownCompleteChunk::ToString() const {
return "SHUTDOWN-COMPLETE";
}
} // namespace dcsctp

View file

@ -0,0 +1,54 @@
/*
* 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_PACKET_CHUNK_SHUTDOWN_COMPLETE_CHUNK_H_
#define NET_DCSCTP_PACKET_CHUNK_SHUTDOWN_COMPLETE_CHUNK_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.13
struct ShutdownCompleteChunkConfig : ChunkConfig {
static constexpr int kType = 14;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class ShutdownCompleteChunk : public Chunk,
public TLVTrait<ShutdownCompleteChunkConfig> {
public:
static constexpr int kType = ShutdownCompleteChunkConfig::kType;
explicit ShutdownCompleteChunk(bool tag_reflected)
: tag_reflected_(tag_reflected) {}
static absl::optional<ShutdownCompleteChunk> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
bool tag_reflected() const { return tag_reflected_; }
private:
static constexpr int kFlagsBitT = 0;
bool tag_reflected_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_SHUTDOWN_COMPLETE_CHUNK_H_

View file

@ -0,0 +1,87 @@
/*
* 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.
*/
#include "net/dcsctp/packet/chunk_validators.h"
#include <algorithm>
#include <utility>
#include <vector>
#include "net/dcsctp/packet/chunk/sack_chunk.h"
#include "rtc_base/logging.h"
namespace dcsctp {
SackChunk ChunkValidators::Clean(SackChunk&& sack) {
if (Validate(sack)) {
return std::move(sack);
}
RTC_DLOG(LS_WARNING) << "Received SACK is malformed; cleaning it";
std::vector<SackChunk::GapAckBlock> gap_ack_blocks;
gap_ack_blocks.reserve(sack.gap_ack_blocks().size());
// First: Only keep blocks that are sane
for (const SackChunk::GapAckBlock& gap_ack_block : sack.gap_ack_blocks()) {
if (gap_ack_block.end > gap_ack_block.start) {
gap_ack_blocks.emplace_back(gap_ack_block);
}
}
// Not more than at most one remaining? Exit early.
if (gap_ack_blocks.size() <= 1) {
return SackChunk(sack.cumulative_tsn_ack(), sack.a_rwnd(),
std::move(gap_ack_blocks), sack.duplicate_tsns());
}
// Sort the intervals by their start value, to aid in the merging below.
absl::c_sort(gap_ack_blocks, [&](const SackChunk::GapAckBlock& a,
const SackChunk::GapAckBlock& b) {
return a.start < b.start;
});
// Merge overlapping ranges.
std::vector<SackChunk::GapAckBlock> merged;
merged.reserve(gap_ack_blocks.size());
merged.push_back(gap_ack_blocks[0]);
for (size_t i = 1; i < gap_ack_blocks.size(); ++i) {
if (merged.back().end + 1 >= gap_ack_blocks[i].start) {
merged.back().end = std::max(merged.back().end, gap_ack_blocks[i].end);
} else {
merged.push_back(gap_ack_blocks[i]);
}
}
return SackChunk(sack.cumulative_tsn_ack(), sack.a_rwnd(), std::move(merged),
sack.duplicate_tsns());
}
bool ChunkValidators::Validate(const SackChunk& sack) {
if (sack.gap_ack_blocks().empty()) {
return true;
}
// Ensure that gap-ack-blocks are sorted, has an "end" that is not before
// "start" and are non-overlapping and non-adjacent.
uint16_t prev_end = 0;
for (const SackChunk::GapAckBlock& gap_ack_block : sack.gap_ack_blocks()) {
if (gap_ack_block.end < gap_ack_block.start) {
return false;
}
if (gap_ack_block.start <= (prev_end + 1)) {
return false;
}
prev_end = gap_ack_block.end;
}
return true;
}
} // namespace dcsctp

View file

@ -0,0 +1,33 @@
/*
* 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_PACKET_CHUNK_VALIDATORS_H_
#define NET_DCSCTP_PACKET_CHUNK_VALIDATORS_H_
#include "net/dcsctp/packet/chunk/sack_chunk.h"
namespace dcsctp {
// Validates and cleans SCTP chunks.
class ChunkValidators {
public:
// Given a SackChunk, will return `true` if it's valid, and `false` if not.
static bool Validate(const SackChunk& sack);
// Given a SackChunk, it will return a cleaned and validated variant of it.
// RFC4960 doesn't say anything about validity of SACKs or if the Gap ACK
// blocks must be sorted, and non-overlapping. While they always are in
// well-behaving implementations, this can't be relied on.
//
// This method internally calls `Validate`, which means that you can always
// pass a SackChunk to this method (valid or not), and use the results.
static SackChunk Clean(SackChunk&& sack);
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CHUNK_VALIDATORS_H_

View file

@ -0,0 +1,29 @@
/*
* 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.
*/
#include "net/dcsctp/packet/crc32c.h"
#include <cstdint>
#include "third_party/crc32c/src/include/crc32c/crc32c.h"
namespace dcsctp {
uint32_t GenerateCrc32C(rtc::ArrayView<const uint8_t> data) {
uint32_t crc32c = crc32c_value(data.data(), data.size());
// Byte swapping for little endian byte order:
uint8_t byte0 = crc32c;
uint8_t byte1 = crc32c >> 8;
uint8_t byte2 = crc32c >> 16;
uint8_t byte3 = crc32c >> 24;
crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
return crc32c;
}
} // namespace dcsctp

View file

@ -0,0 +1,24 @@
/*
* 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_PACKET_CRC32C_H_
#define NET_DCSCTP_PACKET_CRC32C_H_
#include <cstdint>
#include "api/array_view.h"
namespace dcsctp {
// Generates the CRC32C checksum of `data`.
uint32_t GenerateCrc32C(rtc::ArrayView<const uint8_t> data);
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_CRC32C_H_

View file

@ -0,0 +1,103 @@
/*
* 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_PACKET_DATA_H_
#define NET_DCSCTP_PACKET_DATA_H_
#include <cstdint>
#include <utility>
#include <vector>
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/public/types.h"
namespace dcsctp {
// Represents data that is either received and extracted from a DATA/I-DATA
// chunk, or data that is supposed to be sent, and wrapped in a DATA/I-DATA
// chunk (depending on peer capabilities).
//
// The data wrapped in this structure is actually the same as the DATA/I-DATA
// chunk (actually the union of them), but to avoid having all components be
// aware of the implementation details of the different chunks, this abstraction
// is used instead. A notable difference is also that it doesn't carry a
// Transmission Sequence Number (TSN), as that is not known when a chunk is
// created (assigned late, just when sending), and that the TSNs in DATA/I-DATA
// are wrapped numbers, and within the library, unwrapped sequence numbers are
// preferably used.
struct Data {
// Indicates if a chunk is the first in a fragmented message and maps to the
// "beginning" flag in DATA/I-DATA chunk.
using IsBeginning = webrtc::StrongAlias<class IsBeginningTag, bool>;
// Indicates if a chunk is the last in a fragmented message and maps to the
// "end" flag in DATA/I-DATA chunk.
using IsEnd = webrtc::StrongAlias<class IsEndTag, bool>;
Data(StreamID stream_id,
SSN ssn,
MID mid,
FSN fsn,
PPID ppid,
std::vector<uint8_t> payload,
IsBeginning is_beginning,
IsEnd is_end,
IsUnordered is_unordered)
: stream_id(stream_id),
ssn(ssn),
mid(mid),
fsn(fsn),
ppid(ppid),
payload(std::move(payload)),
is_beginning(is_beginning),
is_end(is_end),
is_unordered(is_unordered) {}
// Move-only, to avoid accidental copies.
Data(Data&& other) = default;
Data& operator=(Data&& other) = default;
// Creates a copy of this `Data` object.
Data Clone() const {
return Data(stream_id, ssn, mid, fsn, ppid, payload, is_beginning, is_end,
is_unordered);
}
// The size of this data, which translates to the size of its payload.
size_t size() const { return payload.size(); }
// Stream Identifier.
StreamID stream_id;
// Stream Sequence Number (SSN), per stream, for ordered chunks. Defined by
// RFC4960 and used only in DATA chunks (not I-DATA).
SSN ssn;
// Message Identifier (MID) per stream and ordered/unordered. Defined by
// RFC8260, and used together with options.is_unordered and stream_id to
// uniquely identify a message. Used only in I-DATA chunks (not DATA).
MID mid;
// Fragment Sequence Number (FSN) per stream and ordered/unordered, as above.
FSN fsn;
// Payload Protocol Identifier (PPID).
PPID ppid;
// The actual data payload.
std::vector<uint8_t> payload;
// If this data represents the first, last or a middle chunk.
IsBeginning is_beginning;
IsEnd is_end;
// If this data is sent/received unordered.
IsUnordered is_unordered;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_DATA_H_

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h"
#include <stdint.h>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.10
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=10 | Cause Length=4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int CookieReceivedWhileShuttingDownCause::kType;
absl::optional<CookieReceivedWhileShuttingDownCause>
CookieReceivedWhileShuttingDownCause::Parse(
rtc::ArrayView<const uint8_t> data) {
if (!ParseTLV(data).has_value()) {
return absl::nullopt;
}
return CookieReceivedWhileShuttingDownCause();
}
void CookieReceivedWhileShuttingDownCause::SerializeTo(
std::vector<uint8_t>& out) const {
AllocateTLV(out);
}
std::string CookieReceivedWhileShuttingDownCause::ToString() const {
return "Cookie Received While Shutting Down";
}
} // namespace dcsctp

View file

@ -0,0 +1,50 @@
/*
* 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_PACKET_ERROR_CAUSE_COOKIE_RECEIVED_WHILE_SHUTTING_DOWN_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_COOKIE_RECEIVED_WHILE_SHUTTING_DOWN_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.10
struct CookieReceivedWhileShuttingDownCauseConfig : public ParameterConfig {
static constexpr int kType = 10;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class CookieReceivedWhileShuttingDownCause
: public Parameter,
public TLVTrait<CookieReceivedWhileShuttingDownCauseConfig> {
public:
static constexpr int kType =
CookieReceivedWhileShuttingDownCauseConfig::kType;
CookieReceivedWhileShuttingDownCause() {}
static absl::optional<CookieReceivedWhileShuttingDownCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_COOKIE_RECEIVED_WHILE_SHUTTING_DOWN_CAUSE_H_

View file

@ -0,0 +1,83 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include <stddef.h>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/common/math.h"
#include "net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h"
#include "net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h"
#include "net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h"
#include "net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h"
#include "net/dcsctp/packet/error_cause/no_user_data_cause.h"
#include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
#include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
#include "net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h"
#include "net/dcsctp/packet/error_cause/stale_cookie_error_cause.h"
#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
#include "net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h"
#include "net/dcsctp/packet/error_cause/unresolvable_address_cause.h"
#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
template <class ErrorCause>
bool ParseAndPrint(ParameterDescriptor descriptor, rtc::StringBuilder& sb) {
if (descriptor.type == ErrorCause::kType) {
absl::optional<ErrorCause> p = ErrorCause::Parse(descriptor.data);
if (p.has_value()) {
sb << p->ToString();
} else {
sb << "Failed to parse error cause of type " << ErrorCause::kType;
}
return true;
}
return false;
}
std::string ErrorCausesToString(const Parameters& parameters) {
rtc::StringBuilder sb;
std::vector<ParameterDescriptor> descriptors = parameters.descriptors();
for (size_t i = 0; i < descriptors.size(); ++i) {
if (i > 0) {
sb << "\n";
}
const ParameterDescriptor& d = descriptors[i];
if (!ParseAndPrint<InvalidStreamIdentifierCause>(d, sb) &&
!ParseAndPrint<MissingMandatoryParameterCause>(d, sb) &&
!ParseAndPrint<StaleCookieErrorCause>(d, sb) &&
!ParseAndPrint<OutOfResourceErrorCause>(d, sb) &&
!ParseAndPrint<UnresolvableAddressCause>(d, sb) &&
!ParseAndPrint<UnrecognizedChunkTypeCause>(d, sb) &&
!ParseAndPrint<InvalidMandatoryParameterCause>(d, sb) &&
!ParseAndPrint<UnrecognizedParametersCause>(d, sb) &&
!ParseAndPrint<NoUserDataCause>(d, sb) &&
!ParseAndPrint<CookieReceivedWhileShuttingDownCause>(d, sb) &&
!ParseAndPrint<RestartOfAnAssociationWithNewAddressesCause>(d, sb) &&
!ParseAndPrint<UserInitiatedAbortCause>(d, sb) &&
!ParseAndPrint<ProtocolViolationCause>(d, sb)) {
sb << "Unhandled parameter of type: " << d.type;
}
}
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,38 @@
/*
* 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_PACKET_ERROR_CAUSE_ERROR_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_ERROR_CAUSE_H_
#include <stddef.h>
#include <cstdint>
#include <iosfwd>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// Converts the Error Causes in `parameters` to a human readable string,
// to be used in error reporting and logging.
std::string ErrorCausesToString(const Parameters& parameters);
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_ERROR_CAUSE_H_

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h"
#include <stdint.h>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.7
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=7 | Cause Length=4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int InvalidMandatoryParameterCause::kType;
absl::optional<InvalidMandatoryParameterCause>
InvalidMandatoryParameterCause::Parse(rtc::ArrayView<const uint8_t> data) {
if (!ParseTLV(data).has_value()) {
return absl::nullopt;
}
return InvalidMandatoryParameterCause();
}
void InvalidMandatoryParameterCause::SerializeTo(
std::vector<uint8_t>& out) const {
AllocateTLV(out);
}
std::string InvalidMandatoryParameterCause::ToString() const {
return "Invalid Mandatory Parameter";
}
} // namespace dcsctp

View file

@ -0,0 +1,48 @@
/*
* 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_PACKET_ERROR_CAUSE_INVALID_MANDATORY_PARAMETER_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_MANDATORY_PARAMETER_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.7
struct InvalidMandatoryParameterCauseConfig : public ParameterConfig {
static constexpr int kType = 7;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class InvalidMandatoryParameterCause
: public Parameter,
public TLVTrait<InvalidMandatoryParameterCauseConfig> {
public:
static constexpr int kType = InvalidMandatoryParameterCauseConfig::kType;
InvalidMandatoryParameterCause() {}
static absl::optional<InvalidMandatoryParameterCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_MANDATORY_PARAMETER_CAUSE_H_

View file

@ -0,0 +1,60 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=1 | Cause Length=8 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Identifier | (Reserved) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int InvalidStreamIdentifierCause::kType;
absl::optional<InvalidStreamIdentifierCause>
InvalidStreamIdentifierCause::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
StreamID stream_id(reader->Load16<4>());
return InvalidStreamIdentifierCause(stream_id);
}
void InvalidStreamIdentifierCause::SerializeTo(
std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store16<4>(*stream_id_);
}
std::string InvalidStreamIdentifierCause::ToString() const {
rtc::StringBuilder sb;
sb << "Invalid Stream Identifier, stream_id=" << *stream_id_;
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,56 @@
/*
* 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_PACKET_ERROR_CAUSE_INVALID_STREAM_IDENTIFIER_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_STREAM_IDENTIFIER_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "net/dcsctp/public/types.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.1
struct InvalidStreamIdentifierCauseConfig : public ParameterConfig {
static constexpr int kType = 1;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 0;
};
class InvalidStreamIdentifierCause
: public Parameter,
public TLVTrait<InvalidStreamIdentifierCauseConfig> {
public:
static constexpr int kType = InvalidStreamIdentifierCauseConfig::kType;
explicit InvalidStreamIdentifierCause(StreamID stream_id)
: stream_id_(stream_id) {}
static absl::optional<InvalidStreamIdentifierCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
StreamID stream_id() const { return stream_id_; }
private:
StreamID stream_id_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_STREAM_IDENTIFIER_CAUSE_H_

View file

@ -0,0 +1,90 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h"
#include <stddef.h>
#include <cstdint>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/str_join.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.2
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=2 | Cause Length=8+N*2 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Number of missing params=N |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Missing Param Type #1 | Missing Param Type #2 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Missing Param Type #N-1 | Missing Param Type #N |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int MissingMandatoryParameterCause::kType;
absl::optional<MissingMandatoryParameterCause>
MissingMandatoryParameterCause::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
uint32_t count = reader->Load32<4>();
if (reader->variable_data_size() / kMissingParameterSize != count) {
RTC_DLOG(LS_WARNING) << "Invalid number of missing parameters";
return absl::nullopt;
}
std::vector<uint16_t> missing_parameter_types;
missing_parameter_types.reserve(count);
for (uint32_t i = 0; i < count; ++i) {
BoundedByteReader<kMissingParameterSize> sub_reader =
reader->sub_reader<kMissingParameterSize>(i * kMissingParameterSize);
missing_parameter_types.push_back(sub_reader.Load16<0>());
}
return MissingMandatoryParameterCause(missing_parameter_types);
}
void MissingMandatoryParameterCause::SerializeTo(
std::vector<uint8_t>& out) const {
size_t variable_size =
missing_parameter_types_.size() * kMissingParameterSize;
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(missing_parameter_types_.size());
for (size_t i = 0; i < missing_parameter_types_.size(); ++i) {
BoundedByteWriter<kMissingParameterSize> sub_writer =
writer.sub_writer<kMissingParameterSize>(i * kMissingParameterSize);
sub_writer.Store16<0>(missing_parameter_types_[i]);
}
}
std::string MissingMandatoryParameterCause::ToString() const {
rtc::StringBuilder sb;
sb << "Missing Mandatory Parameter, missing_parameter_types="
<< webrtc::StrJoin(missing_parameter_types_, ",");
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,60 @@
/*
* 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_PACKET_ERROR_CAUSE_MISSING_MANDATORY_PARAMETER_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_MISSING_MANDATORY_PARAMETER_CAUSE_H_
#include <stddef.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.2
struct MissingMandatoryParameterCauseConfig : public ParameterConfig {
static constexpr int kType = 2;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 2;
};
class MissingMandatoryParameterCause
: public Parameter,
public TLVTrait<MissingMandatoryParameterCauseConfig> {
public:
static constexpr int kType = MissingMandatoryParameterCauseConfig::kType;
explicit MissingMandatoryParameterCause(
rtc::ArrayView<const uint16_t> missing_parameter_types)
: missing_parameter_types_(missing_parameter_types.begin(),
missing_parameter_types.end()) {}
static absl::optional<MissingMandatoryParameterCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint16_t> missing_parameter_types() const {
return missing_parameter_types_;
}
private:
static constexpr size_t kMissingParameterSize = 2;
std::vector<uint16_t> missing_parameter_types_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_MISSING_MANDATORY_PARAMETER_CAUSE_H_

View file

@ -0,0 +1,57 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/no_user_data_cause.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.9
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=9 | Cause Length=8 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / TSN value /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int NoUserDataCause::kType;
absl::optional<NoUserDataCause> NoUserDataCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
TSN tsn(reader->Load32<4>());
return NoUserDataCause(tsn);
}
void NoUserDataCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store32<4>(*tsn_);
}
std::string NoUserDataCause::ToString() const {
rtc::StringBuilder sb;
sb << "No User Data, tsn=" << *tsn_;
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,53 @@
/*
* 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_PACKET_ERROR_CAUSE_NO_USER_DATA_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_NO_USER_DATA_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.9
struct NoUserDataCauseConfig : public ParameterConfig {
static constexpr int kType = 9;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 0;
};
class NoUserDataCause : public Parameter,
public TLVTrait<NoUserDataCauseConfig> {
public:
static constexpr int kType = NoUserDataCauseConfig::kType;
explicit NoUserDataCause(TSN tsn) : tsn_(tsn) {}
static absl::optional<NoUserDataCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
TSN tsn() const { return tsn_; }
private:
TSN tsn_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_NO_USER_DATA_CAUSE_H_

View file

@ -0,0 +1,44 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
#include <stdint.h>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.4
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=4 | Cause Length=4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int OutOfResourceErrorCause::kType;
absl::optional<OutOfResourceErrorCause> OutOfResourceErrorCause::Parse(
rtc::ArrayView<const uint8_t> data) {
if (!ParseTLV(data).has_value()) {
return absl::nullopt;
}
return OutOfResourceErrorCause();
}
void OutOfResourceErrorCause::SerializeTo(std::vector<uint8_t>& out) const {
AllocateTLV(out);
}
std::string OutOfResourceErrorCause::ToString() const {
return "Out Of Resource";
}
} // namespace dcsctp

View file

@ -0,0 +1,48 @@
/*
* 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_PACKET_ERROR_CAUSE_OUT_OF_RESOURCE_ERROR_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_OUT_OF_RESOURCE_ERROR_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.4
struct OutOfResourceParameterConfig : public ParameterConfig {
static constexpr int kType = 4;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class OutOfResourceErrorCause : public Parameter,
public TLVTrait<OutOfResourceParameterConfig> {
public:
static constexpr int kType = OutOfResourceParameterConfig::kType;
OutOfResourceErrorCause() {}
static absl::optional<OutOfResourceErrorCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_OUT_OF_RESOURCE_ERROR_CAUSE_H_

View file

@ -0,0 +1,65 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.13
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=13 | Cause Length=Variable |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / Additional Information /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ProtocolViolationCause::kType;
absl::optional<ProtocolViolationCause> ProtocolViolationCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
return ProtocolViolationCause(
std::string(reinterpret_cast<const char*>(reader->variable_data().data()),
reader->variable_data().size()));
}
void ProtocolViolationCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer =
AllocateTLV(out, additional_information_.size());
writer.CopyToVariableData(rtc::MakeArrayView(
reinterpret_cast<const uint8_t*>(additional_information_.data()),
additional_information_.size()));
}
std::string ProtocolViolationCause::ToString() const {
rtc::StringBuilder sb;
sb << "Protocol Violation, additional_information="
<< additional_information_;
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,56 @@
/*
* 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_PACKET_ERROR_CAUSE_PROTOCOL_VIOLATION_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_PROTOCOL_VIOLATION_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.13
struct ProtocolViolationCauseConfig : public ParameterConfig {
static constexpr int kType = 13;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class ProtocolViolationCause : public Parameter,
public TLVTrait<ProtocolViolationCauseConfig> {
public:
static constexpr int kType = ProtocolViolationCauseConfig::kType;
explicit ProtocolViolationCause(absl::string_view additional_information)
: additional_information_(additional_information) {}
static absl::optional<ProtocolViolationCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
absl::string_view additional_information() const {
return additional_information_;
}
private:
std::string additional_information_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_PROTOCOL_VIOLATION_CAUSE_H_

View file

@ -0,0 +1,58 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.11
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=11 | Cause Length=Variable |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / New Address TLVs /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int RestartOfAnAssociationWithNewAddressesCause::kType;
absl::optional<RestartOfAnAssociationWithNewAddressesCause>
RestartOfAnAssociationWithNewAddressesCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
return RestartOfAnAssociationWithNewAddressesCause(reader->variable_data());
}
void RestartOfAnAssociationWithNewAddressesCause::SerializeTo(
std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer =
AllocateTLV(out, new_address_tlvs_.size());
writer.CopyToVariableData(new_address_tlvs_);
}
std::string RestartOfAnAssociationWithNewAddressesCause::ToString() const {
return "Restart of an Association with New Addresses";
}
} // namespace dcsctp

View file

@ -0,0 +1,59 @@
/*
* 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_PACKET_ERROR_CAUSE_RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESS_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESS_CAUSE_H_
#include <stddef.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.11
struct RestartOfAnAssociationWithNewAddressesCauseConfig
: public ParameterConfig {
static constexpr int kType = 11;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class RestartOfAnAssociationWithNewAddressesCause
: public Parameter,
public TLVTrait<RestartOfAnAssociationWithNewAddressesCauseConfig> {
public:
static constexpr int kType =
RestartOfAnAssociationWithNewAddressesCauseConfig::kType;
explicit RestartOfAnAssociationWithNewAddressesCause(
rtc::ArrayView<const uint8_t> new_address_tlvs)
: new_address_tlvs_(new_address_tlvs.begin(), new_address_tlvs.end()) {}
static absl::optional<RestartOfAnAssociationWithNewAddressesCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint8_t> new_address_tlvs() const {
return new_address_tlvs_;
}
private:
std::vector<uint8_t> new_address_tlvs_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESS_CAUSE_H_

View file

@ -0,0 +1,57 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/stale_cookie_error_cause.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.3
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=3 | Cause Length=8 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Measure of Staleness (usec.) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int StaleCookieErrorCause::kType;
absl::optional<StaleCookieErrorCause> StaleCookieErrorCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
uint32_t staleness_us = reader->Load32<4>();
return StaleCookieErrorCause(staleness_us);
}
void StaleCookieErrorCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store32<4>(staleness_us_);
}
std::string StaleCookieErrorCause::ToString() const {
rtc::StringBuilder sb;
sb << "Stale Cookie Error, staleness_us=" << staleness_us_;
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,54 @@
/*
* 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_PACKET_ERROR_CAUSE_STALE_COOKIE_ERROR_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_STALE_COOKIE_ERROR_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.3
struct StaleCookieParameterConfig : public ParameterConfig {
static constexpr int kType = 3;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 0;
};
class StaleCookieErrorCause : public Parameter,
public TLVTrait<StaleCookieParameterConfig> {
public:
static constexpr int kType = StaleCookieParameterConfig::kType;
explicit StaleCookieErrorCause(uint32_t staleness_us)
: staleness_us_(staleness_us) {}
static absl::optional<StaleCookieErrorCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
uint16_t staleness_us() const { return staleness_us_; }
private:
uint32_t staleness_us_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_STALE_COOKIE_ERROR_CAUSE_H_

View file

@ -0,0 +1,64 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.6
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=6 | Cause Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / Unrecognized Chunk /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int UnrecognizedChunkTypeCause::kType;
absl::optional<UnrecognizedChunkTypeCause> UnrecognizedChunkTypeCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
std::vector<uint8_t> unrecognized_chunk(reader->variable_data().begin(),
reader->variable_data().end());
return UnrecognizedChunkTypeCause(std::move(unrecognized_chunk));
}
void UnrecognizedChunkTypeCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer =
AllocateTLV(out, unrecognized_chunk_.size());
writer.CopyToVariableData(unrecognized_chunk_);
}
std::string UnrecognizedChunkTypeCause::ToString() const {
rtc::StringBuilder sb;
sb << "Unrecognized Chunk Type, chunk_type=";
if (!unrecognized_chunk_.empty()) {
sb << static_cast<int>(unrecognized_chunk_[0]);
} else {
sb << "<missing>";
}
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,59 @@
/*
* 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_PACKET_ERROR_CAUSE_UNRECOGNIZED_CHUNK_TYPE_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_CHUNK_TYPE_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.6
struct UnrecognizedChunkTypeCauseConfig : public ParameterConfig {
static constexpr int kType = 6;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class UnrecognizedChunkTypeCause
: public Parameter,
public TLVTrait<UnrecognizedChunkTypeCauseConfig> {
public:
static constexpr int kType = UnrecognizedChunkTypeCauseConfig::kType;
explicit UnrecognizedChunkTypeCause(std::vector<uint8_t> unrecognized_chunk)
: unrecognized_chunk_(std::move(unrecognized_chunk)) {}
static absl::optional<UnrecognizedChunkTypeCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint8_t> unrecognized_chunk() const {
return unrecognized_chunk_;
}
private:
std::vector<uint8_t> unrecognized_chunk_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_CHUNK_TYPE_CAUSE_H_

View file

@ -0,0 +1,54 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.8
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=8 | Cause Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / Unrecognized Parameters /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int UnrecognizedParametersCause::kType;
absl::optional<UnrecognizedParametersCause> UnrecognizedParametersCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
return UnrecognizedParametersCause(reader->variable_data());
}
void UnrecognizedParametersCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer =
AllocateTLV(out, unrecognized_parameters_.size());
writer.CopyToVariableData(unrecognized_parameters_);
}
std::string UnrecognizedParametersCause::ToString() const {
return "Unrecognized Parameters";
}
} // namespace dcsctp

View file

@ -0,0 +1,60 @@
/*
* 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_PACKET_ERROR_CAUSE_UNRECOGNIZED_PARAMETER_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_PARAMETER_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.8
struct UnrecognizedParametersCauseConfig : public ParameterConfig {
static constexpr int kType = 8;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class UnrecognizedParametersCause
: public Parameter,
public TLVTrait<UnrecognizedParametersCauseConfig> {
public:
static constexpr int kType = UnrecognizedParametersCauseConfig::kType;
explicit UnrecognizedParametersCause(
rtc::ArrayView<const uint8_t> unrecognized_parameters)
: unrecognized_parameters_(unrecognized_parameters.begin(),
unrecognized_parameters.end()) {}
static absl::optional<UnrecognizedParametersCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint8_t> unrecognized_parameters() const {
return unrecognized_parameters_;
}
private:
std::vector<uint8_t> unrecognized_parameters_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_PARAMETER_CAUSE_H_

View file

@ -0,0 +1,53 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/unresolvable_address_cause.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.5
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=5 | Cause Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / Unresolvable Address /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int UnresolvableAddressCause::kType;
absl::optional<UnresolvableAddressCause> UnresolvableAddressCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
return UnresolvableAddressCause(reader->variable_data());
}
void UnresolvableAddressCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer =
AllocateTLV(out, unresolvable_address_.size());
writer.CopyToVariableData(unresolvable_address_);
}
std::string UnresolvableAddressCause::ToString() const {
return "Unresolvable Address";
}
} // namespace dcsctp

View file

@ -0,0 +1,60 @@
/*
* 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_PACKET_ERROR_CAUSE_UNRESOLVABLE_ADDRESS_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_UNRESOLVABLE_ADDRESS_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.5
struct UnresolvableAddressCauseConfig : public ParameterConfig {
static constexpr int kType = 5;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class UnresolvableAddressCause
: public Parameter,
public TLVTrait<UnresolvableAddressCauseConfig> {
public:
static constexpr int kType = UnresolvableAddressCauseConfig::kType;
explicit UnresolvableAddressCause(
rtc::ArrayView<const uint8_t> unresolvable_address)
: unresolvable_address_(unresolvable_address.begin(),
unresolvable_address.end()) {}
static absl::optional<UnresolvableAddressCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint8_t> unresolvable_address() const {
return unresolvable_address_;
}
private:
std::vector<uint8_t> unresolvable_address_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_UNRESOLVABLE_ADDRESS_CAUSE_H_

View file

@ -0,0 +1,67 @@
/*
* 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.
*/
#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.12
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cause Code=12 | Cause Length=Variable |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / Upper Layer Abort Reason /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int UserInitiatedAbortCause::kType;
absl::optional<UserInitiatedAbortCause> UserInitiatedAbortCause::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
if (reader->variable_data().empty()) {
return UserInitiatedAbortCause("");
}
return UserInitiatedAbortCause(
std::string(reinterpret_cast<const char*>(reader->variable_data().data()),
reader->variable_data().size()));
}
void UserInitiatedAbortCause::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer =
AllocateTLV(out, upper_layer_abort_reason_.size());
writer.CopyToVariableData(rtc::MakeArrayView(
reinterpret_cast<const uint8_t*>(upper_layer_abort_reason_.data()),
upper_layer_abort_reason_.size()));
}
std::string UserInitiatedAbortCause::ToString() const {
rtc::StringBuilder sb;
sb << "User-Initiated Abort, reason=" << upper_layer_abort_reason_;
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,56 @@
/*
* 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_PACKET_ERROR_CAUSE_USER_INITIATED_ABORT_CAUSE_H_
#define NET_DCSCTP_PACKET_ERROR_CAUSE_USER_INITIATED_ABORT_CAUSE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.10.12
struct UserInitiatedAbortCauseConfig : public ParameterConfig {
static constexpr int kType = 12;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class UserInitiatedAbortCause : public Parameter,
public TLVTrait<UserInitiatedAbortCauseConfig> {
public:
static constexpr int kType = UserInitiatedAbortCauseConfig::kType;
explicit UserInitiatedAbortCause(absl::string_view upper_layer_abort_reason)
: upper_layer_abort_reason_(upper_layer_abort_reason) {}
static absl::optional<UserInitiatedAbortCause> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
absl::string_view upper_layer_abort_reason() const {
return upper_layer_abort_reason_;
}
private:
std::string upper_layer_abort_reason_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_USER_INITIATED_ABORT_CAUSE_H_

View file

@ -0,0 +1,68 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.6
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 18 | Parameter Length = 12 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Request Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Number of new streams | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int AddIncomingStreamsRequestParameter::kType;
absl::optional<AddIncomingStreamsRequestParameter>
AddIncomingStreamsRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
ReconfigRequestSN request_sequence_number(reader->Load32<4>());
uint16_t nbr_of_new_streams = reader->Load16<8>();
return AddIncomingStreamsRequestParameter(request_sequence_number,
nbr_of_new_streams);
}
void AddIncomingStreamsRequestParameter::SerializeTo(
std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store32<4>(*request_sequence_number_);
writer.Store16<8>(nbr_of_new_streams_);
}
std::string AddIncomingStreamsRequestParameter::ToString() const {
rtc::StringBuilder sb;
sb << "Add Incoming Streams Request, req_seq_nbr="
<< *request_sequence_number();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,63 @@
/*
* 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_PACKET_PARAMETER_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.6
struct AddIncomingStreamsRequestParameterConfig : ParameterConfig {
static constexpr int kType = 18;
static constexpr size_t kHeaderSize = 12;
static constexpr size_t kVariableLengthAlignment = 0;
};
class AddIncomingStreamsRequestParameter
: public Parameter,
public TLVTrait<AddIncomingStreamsRequestParameterConfig> {
public:
static constexpr int kType = AddIncomingStreamsRequestParameterConfig::kType;
explicit AddIncomingStreamsRequestParameter(
ReconfigRequestSN request_sequence_number,
uint16_t nbr_of_new_streams)
: request_sequence_number_(request_sequence_number),
nbr_of_new_streams_(nbr_of_new_streams) {}
static absl::optional<AddIncomingStreamsRequestParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
ReconfigRequestSN request_sequence_number() const {
return request_sequence_number_;
}
uint16_t nbr_of_new_streams() const { return nbr_of_new_streams_; }
private:
ReconfigRequestSN request_sequence_number_;
uint16_t nbr_of_new_streams_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_H_

View file

@ -0,0 +1,67 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.5
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 17 | Parameter Length = 12 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Request Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Number of new streams | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int AddOutgoingStreamsRequestParameter::kType;
absl::optional<AddOutgoingStreamsRequestParameter>
AddOutgoingStreamsRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
ReconfigRequestSN request_sequence_number(reader->Load32<4>());
uint16_t nbr_of_new_streams = reader->Load16<8>();
return AddOutgoingStreamsRequestParameter(request_sequence_number,
nbr_of_new_streams);
}
void AddOutgoingStreamsRequestParameter::SerializeTo(
std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store32<4>(*request_sequence_number_);
writer.Store16<8>(nbr_of_new_streams_);
}
std::string AddOutgoingStreamsRequestParameter::ToString() const {
rtc::StringBuilder sb;
sb << "Add Outgoing Streams Request, req_seq_nbr="
<< *request_sequence_number();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,63 @@
/*
* 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_PACKET_PARAMETER_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.5
struct AddOutgoingStreamsRequestParameterConfig : ParameterConfig {
static constexpr int kType = 17;
static constexpr size_t kHeaderSize = 12;
static constexpr size_t kVariableLengthAlignment = 0;
};
class AddOutgoingStreamsRequestParameter
: public Parameter,
public TLVTrait<AddOutgoingStreamsRequestParameterConfig> {
public:
static constexpr int kType = AddOutgoingStreamsRequestParameterConfig::kType;
explicit AddOutgoingStreamsRequestParameter(
ReconfigRequestSN request_sequence_number,
uint16_t nbr_of_new_streams)
: request_sequence_number_(request_sequence_number),
nbr_of_new_streams_(nbr_of_new_streams) {}
static absl::optional<AddOutgoingStreamsRequestParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
ReconfigRequestSN request_sequence_number() const {
return request_sequence_number_;
}
uint16_t nbr_of_new_streams() const { return nbr_of_new_streams_; }
private:
ReconfigRequestSN request_sequence_number_;
uint16_t nbr_of_new_streams_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_H_

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
#include <stdint.h>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc3758#section-3.1
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 49152 | Parameter Length = 4 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ForwardTsnSupportedParameter::kType;
absl::optional<ForwardTsnSupportedParameter>
ForwardTsnSupportedParameter::Parse(rtc::ArrayView<const uint8_t> data) {
if (!ParseTLV(data).has_value()) {
return absl::nullopt;
}
return ForwardTsnSupportedParameter();
}
void ForwardTsnSupportedParameter::SerializeTo(
std::vector<uint8_t>& out) const {
AllocateTLV(out);
}
std::string ForwardTsnSupportedParameter::ToString() const {
return "Forward TSN Supported";
}
} // namespace dcsctp

View file

@ -0,0 +1,49 @@
/*
* 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_PACKET_PARAMETER_FORWARD_TSN_SUPPORTED_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_FORWARD_TSN_SUPPORTED_PARAMETER_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc3758#section-3.1
struct ForwardTsnSupportedParameterConfig : ParameterConfig {
static constexpr int kType = 49152;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 0;
};
class ForwardTsnSupportedParameter
: public Parameter,
public TLVTrait<ForwardTsnSupportedParameterConfig> {
public:
static constexpr int kType = ForwardTsnSupportedParameterConfig::kType;
ForwardTsnSupportedParameter() {}
static absl::optional<ForwardTsnSupportedParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_FORWARD_TSN_SUPPORTED_PARAMETER_H_

View file

@ -0,0 +1,60 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.5
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type = 4 | Chunk Flags | Heartbeat Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// \ \
// / Heartbeat Information TLV (Variable-Length) /
// \ \
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int HeartbeatInfoParameter::kType;
absl::optional<HeartbeatInfoParameter> HeartbeatInfoParameter::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
return HeartbeatInfoParameter(reader->variable_data());
}
void HeartbeatInfoParameter::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, info_.size());
writer.CopyToVariableData(info_);
}
std::string HeartbeatInfoParameter::ToString() const {
rtc::StringBuilder sb;
sb << "Heartbeat Info parameter (info_length=" << info_.size() << ")";
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,54 @@
/*
* 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_PACKET_PARAMETER_HEARTBEAT_INFO_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_HEARTBEAT_INFO_PARAMETER_H_
#include <stddef.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc4960#section-3.3.5
struct HeartbeatInfoParameterConfig : ParameterConfig {
static constexpr int kType = 1;
static constexpr size_t kHeaderSize = 4;
static constexpr size_t kVariableLengthAlignment = 1;
};
class HeartbeatInfoParameter : public Parameter,
public TLVTrait<HeartbeatInfoParameterConfig> {
public:
static constexpr int kType = HeartbeatInfoParameterConfig::kType;
explicit HeartbeatInfoParameter(rtc::ArrayView<const uint8_t> info)
: info_(info.begin(), info.end()) {}
static absl::optional<HeartbeatInfoParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
rtc::ArrayView<const uint8_t> info() const { return info_; }
private:
std::vector<uint8_t> info_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_HEARTBEAT_INFO_PARAMETER_H_

View file

@ -0,0 +1,89 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
#include <stddef.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.2
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 14 | Parameter Length = 8 + 2 * N |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Request Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Number 1 (optional) | Stream Number 2 (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / ...... /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Number N-1 (optional) | Stream Number N (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int IncomingSSNResetRequestParameter::kType;
absl::optional<IncomingSSNResetRequestParameter>
IncomingSSNResetRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
ReconfigRequestSN request_sequence_number(reader->Load32<4>());
size_t stream_count = reader->variable_data_size() / kStreamIdSize;
std::vector<StreamID> stream_ids;
stream_ids.reserve(stream_count);
for (size_t i = 0; i < stream_count; ++i) {
BoundedByteReader<kStreamIdSize> sub_reader =
reader->sub_reader<kStreamIdSize>(i * kStreamIdSize);
stream_ids.push_back(StreamID(sub_reader.Load16<0>()));
}
return IncomingSSNResetRequestParameter(request_sequence_number,
std::move(stream_ids));
}
void IncomingSSNResetRequestParameter::SerializeTo(
std::vector<uint8_t>& out) const {
size_t variable_size = stream_ids_.size() * kStreamIdSize;
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(*request_sequence_number_);
for (size_t i = 0; i < stream_ids_.size(); ++i) {
BoundedByteWriter<kStreamIdSize> sub_writer =
writer.sub_writer<kStreamIdSize>(i * kStreamIdSize);
sub_writer.Store16<0>(*stream_ids_[i]);
}
}
std::string IncomingSSNResetRequestParameter::ToString() const {
rtc::StringBuilder sb;
sb << "Incoming SSN Reset Request, req_seq_nbr="
<< *request_sequence_number();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,66 @@
/*
* 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_PACKET_PARAMETER_INCOMING_SSN_RESET_REQUEST_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_INCOMING_SSN_RESET_REQUEST_PARAMETER_H_
#include <stddef.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/public/types.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.2
struct IncomingSSNResetRequestParameterConfig : ParameterConfig {
static constexpr int kType = 14;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 2;
};
class IncomingSSNResetRequestParameter
: public Parameter,
public TLVTrait<IncomingSSNResetRequestParameterConfig> {
public:
static constexpr int kType = IncomingSSNResetRequestParameterConfig::kType;
explicit IncomingSSNResetRequestParameter(
ReconfigRequestSN request_sequence_number,
std::vector<StreamID> stream_ids)
: request_sequence_number_(request_sequence_number),
stream_ids_(std::move(stream_ids)) {}
static absl::optional<IncomingSSNResetRequestParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
ReconfigRequestSN request_sequence_number() const {
return request_sequence_number_;
}
rtc::ArrayView<const StreamID> stream_ids() const { return stream_ids_; }
private:
static constexpr size_t kStreamIdSize = sizeof(uint16_t);
ReconfigRequestSN request_sequence_number_;
std::vector<StreamID> stream_ids_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_INCOMING_SSN_RESET_REQUEST_PARAMETER_H_

View file

@ -0,0 +1,101 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
#include <stddef.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "net/dcsctp/public/types.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 13 | Parameter Length = 16 + 2 * N |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Request Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Response Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Sender's Last Assigned TSN |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Number 1 (optional) | Stream Number 2 (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// / ...... /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Stream Number N-1 (optional) | Stream Number N (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int OutgoingSSNResetRequestParameter::kType;
absl::optional<OutgoingSSNResetRequestParameter>
OutgoingSSNResetRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
ReconfigRequestSN request_sequence_number(reader->Load32<4>());
ReconfigRequestSN response_sequence_number(reader->Load32<8>());
TSN sender_last_assigned_tsn(reader->Load32<12>());
size_t stream_count = reader->variable_data_size() / kStreamIdSize;
std::vector<StreamID> stream_ids;
stream_ids.reserve(stream_count);
for (size_t i = 0; i < stream_count; ++i) {
BoundedByteReader<kStreamIdSize> sub_reader =
reader->sub_reader<kStreamIdSize>(i * kStreamIdSize);
stream_ids.push_back(StreamID(sub_reader.Load16<0>()));
}
return OutgoingSSNResetRequestParameter(
request_sequence_number, response_sequence_number,
sender_last_assigned_tsn, std::move(stream_ids));
}
void OutgoingSSNResetRequestParameter::SerializeTo(
std::vector<uint8_t>& out) const {
size_t variable_size = stream_ids_.size() * kStreamIdSize;
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(*request_sequence_number_);
writer.Store32<8>(*response_sequence_number_);
writer.Store32<12>(*sender_last_assigned_tsn_);
for (size_t i = 0; i < stream_ids_.size(); ++i) {
BoundedByteWriter<kStreamIdSize> sub_writer =
writer.sub_writer<kStreamIdSize>(i * kStreamIdSize);
sub_writer.Store16<0>(*stream_ids_[i]);
}
}
std::string OutgoingSSNResetRequestParameter::ToString() const {
rtc::StringBuilder sb;
sb << "Outgoing SSN Reset Request, req_seq_nbr=" << *request_sequence_number()
<< ", resp_seq_nbr=" << *response_sequence_number()
<< ", sender_last_asg_tsn=" << *sender_last_assigned_tsn();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,78 @@
/*
* 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_PACKET_PARAMETER_OUTGOING_SSN_RESET_REQUEST_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_OUTGOING_SSN_RESET_REQUEST_PARAMETER_H_
#include <stddef.h>
#include <stdint.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "net/dcsctp/public/types.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.1
struct OutgoingSSNResetRequestParameterConfig : ParameterConfig {
static constexpr int kType = 13;
static constexpr size_t kHeaderSize = 16;
static constexpr size_t kVariableLengthAlignment = 2;
};
class OutgoingSSNResetRequestParameter
: public Parameter,
public TLVTrait<OutgoingSSNResetRequestParameterConfig> {
public:
static constexpr int kType = OutgoingSSNResetRequestParameterConfig::kType;
explicit OutgoingSSNResetRequestParameter(
ReconfigRequestSN request_sequence_number,
ReconfigRequestSN response_sequence_number,
TSN sender_last_assigned_tsn,
std::vector<StreamID> stream_ids)
: request_sequence_number_(request_sequence_number),
response_sequence_number_(response_sequence_number),
sender_last_assigned_tsn_(sender_last_assigned_tsn),
stream_ids_(std::move(stream_ids)) {}
static absl::optional<OutgoingSSNResetRequestParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
ReconfigRequestSN request_sequence_number() const {
return request_sequence_number_;
}
ReconfigRequestSN response_sequence_number() const {
return response_sequence_number_;
}
TSN sender_last_assigned_tsn() const { return sender_last_assigned_tsn_; }
rtc::ArrayView<const StreamID> stream_ids() const { return stream_ids_; }
private:
static constexpr size_t kStreamIdSize = sizeof(uint16_t);
ReconfigRequestSN request_sequence_number_;
ReconfigRequestSN response_sequence_number_;
TSN sender_last_assigned_tsn_;
std::vector<StreamID> stream_ids_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_OUTGOING_SSN_RESET_REQUEST_PARAMETER_H_

View file

@ -0,0 +1,96 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/parameter.h"
#include <stddef.h>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/memory/memory.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/common/math.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h"
#include "net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h"
#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
#include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
#include "net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h"
#include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
#include "net/dcsctp/packet/parameter/supported_extensions_parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
constexpr size_t kParameterHeaderSize = 4;
Parameters::Builder& Parameters::Builder::Add(const Parameter& p) {
// https://tools.ietf.org/html/rfc4960#section-3.2.1
// "If the length of the parameter is not a multiple of 4 bytes, the sender
// pads the parameter at the end (i.e., after the Parameter Value field) with
// all zero bytes."
if (data_.size() % 4 != 0) {
data_.resize(RoundUpTo4(data_.size()));
}
p.SerializeTo(data_);
return *this;
}
std::vector<ParameterDescriptor> Parameters::descriptors() const {
rtc::ArrayView<const uint8_t> span(data_);
std::vector<ParameterDescriptor> result;
while (!span.empty()) {
BoundedByteReader<kParameterHeaderSize> header(span);
uint16_t type = header.Load16<0>();
uint16_t length = header.Load16<2>();
result.emplace_back(type, span.subview(0, length));
size_t length_with_padding = RoundUpTo4(length);
if (length_with_padding > span.size()) {
break;
}
span = span.subview(length_with_padding);
}
return result;
}
absl::optional<Parameters> Parameters::Parse(
rtc::ArrayView<const uint8_t> data) {
// Validate the parameter descriptors
rtc::ArrayView<const uint8_t> span(data);
while (!span.empty()) {
if (span.size() < kParameterHeaderSize) {
RTC_DLOG(LS_WARNING) << "Insufficient parameter length";
return absl::nullopt;
}
BoundedByteReader<kParameterHeaderSize> header(span);
uint16_t length = header.Load16<2>();
if (length < kParameterHeaderSize || length > span.size()) {
RTC_DLOG(LS_WARNING) << "Invalid parameter length field";
return absl::nullopt;
}
size_t length_with_padding = RoundUpTo4(length);
if (length_with_padding > span.size()) {
break;
}
span = span.subview(length_with_padding);
}
return Parameters(std::vector<uint8_t>(data.begin(), data.end()));
}
} // namespace dcsctp

View file

@ -0,0 +1,96 @@
/*
* 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_PACKET_PARAMETER_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_PARAMETER_H_
#include <stddef.h>
#include <algorithm>
#include <cstdint>
#include <iterator>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
class Parameter {
public:
Parameter() {}
virtual ~Parameter() = default;
Parameter(const Parameter& other) = default;
Parameter& operator=(const Parameter& other) = default;
virtual void SerializeTo(std::vector<uint8_t>& out) const = 0;
virtual std::string ToString() const = 0;
};
struct ParameterDescriptor {
ParameterDescriptor(uint16_t type, rtc::ArrayView<const uint8_t> data)
: type(type), data(data) {}
uint16_t type;
rtc::ArrayView<const uint8_t> data;
};
class Parameters {
public:
class Builder {
public:
Builder() {}
Builder& Add(const Parameter& p);
Parameters Build() { return Parameters(std::move(data_)); }
private:
std::vector<uint8_t> data_;
};
static absl::optional<Parameters> Parse(rtc::ArrayView<const uint8_t> data);
Parameters() {}
Parameters(Parameters&& other) = default;
Parameters& operator=(Parameters&& other) = default;
rtc::ArrayView<const uint8_t> data() const { return data_; }
std::vector<ParameterDescriptor> descriptors() const;
template <typename P>
absl::optional<P> get() const {
static_assert(std::is_base_of<Parameter, P>::value,
"Template parameter not derived from Parameter");
for (const auto& p : descriptors()) {
if (p.type == P::kType) {
return P::Parse(p.data);
}
}
return absl::nullopt;
}
private:
explicit Parameters(std::vector<uint8_t> data) : data_(std::move(data)) {}
std::vector<uint8_t> data_;
};
struct ParameterConfig {
static constexpr int kTypeSizeInBytes = 2;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_PARAMETER_H_

View file

@ -0,0 +1,152 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.4
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 16 | Parameter Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Response Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Result |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Sender's Next TSN (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Receiver's Next TSN (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int ReconfigurationResponseParameter::kType;
absl::string_view ToString(ReconfigurationResponseParameter::Result result) {
switch (result) {
case ReconfigurationResponseParameter::Result::kSuccessNothingToDo:
return "Success: nothing to do";
case ReconfigurationResponseParameter::Result::kSuccessPerformed:
return "Success: performed";
case ReconfigurationResponseParameter::Result::kDenied:
return "Denied";
case ReconfigurationResponseParameter::Result::kErrorWrongSSN:
return "Error: wrong ssn";
case ReconfigurationResponseParameter::Result::
kErrorRequestAlreadyInProgress:
return "Error: request already in progress";
case ReconfigurationResponseParameter::Result::kErrorBadSequenceNumber:
return "Error: bad sequence number";
case ReconfigurationResponseParameter::Result::kInProgress:
return "In progress";
}
}
absl::optional<ReconfigurationResponseParameter>
ReconfigurationResponseParameter::Parse(rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
ReconfigRequestSN response_sequence_number(reader->Load32<4>());
Result result;
uint32_t result_nbr = reader->Load32<8>();
switch (result_nbr) {
case 0:
result = ReconfigurationResponseParameter::Result::kSuccessNothingToDo;
break;
case 1:
result = ReconfigurationResponseParameter::Result::kSuccessPerformed;
break;
case 2:
result = ReconfigurationResponseParameter::Result::kDenied;
break;
case 3:
result = ReconfigurationResponseParameter::Result::kErrorWrongSSN;
break;
case 4:
result = ReconfigurationResponseParameter::Result::
kErrorRequestAlreadyInProgress;
break;
case 5:
result =
ReconfigurationResponseParameter::Result::kErrorBadSequenceNumber;
break;
case 6:
result = ReconfigurationResponseParameter::Result::kInProgress;
break;
default:
RTC_DLOG(LS_WARNING) << "Invalid reconfig response result: "
<< result_nbr;
return absl::nullopt;
}
if (reader->variable_data().empty()) {
return ReconfigurationResponseParameter(response_sequence_number, result);
} else if (reader->variable_data_size() != kNextTsnHeaderSize) {
RTC_DLOG(LS_WARNING) << "Invalid parameter size";
return absl::nullopt;
}
BoundedByteReader<kNextTsnHeaderSize> sub_reader =
reader->sub_reader<kNextTsnHeaderSize>(0);
TSN sender_next_tsn(sub_reader.Load32<0>());
TSN receiver_next_tsn(sub_reader.Load32<4>());
return ReconfigurationResponseParameter(response_sequence_number, result,
sender_next_tsn, receiver_next_tsn);
}
void ReconfigurationResponseParameter::SerializeTo(
std::vector<uint8_t>& out) const {
size_t variable_size =
(sender_next_tsn().has_value() ? kNextTsnHeaderSize : 0);
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
writer.Store32<4>(*response_sequence_number_);
uint32_t result_nbr =
static_cast<std::underlying_type<Result>::type>(result_);
writer.Store32<8>(result_nbr);
if (sender_next_tsn().has_value()) {
BoundedByteWriter<kNextTsnHeaderSize> sub_writer =
writer.sub_writer<kNextTsnHeaderSize>(0);
sub_writer.Store32<0>(sender_next_tsn_.has_value() ? **sender_next_tsn_
: 0);
sub_writer.Store32<4>(receiver_next_tsn_.has_value() ? **receiver_next_tsn_
: 0);
}
}
std::string ReconfigurationResponseParameter::ToString() const {
rtc::StringBuilder sb;
sb << "Re-configuration Response, resp_seq_nbr="
<< *response_sequence_number();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,92 @@
/*
* 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_PACKET_PARAMETER_RECONFIGURATION_RESPONSE_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_RECONFIGURATION_RESPONSE_PARAMETER_H_
#include <stddef.h>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.4
struct ReconfigurationResponseParameterConfig : ParameterConfig {
static constexpr int kType = 16;
static constexpr size_t kHeaderSize = 12;
static constexpr size_t kVariableLengthAlignment = 4;
};
class ReconfigurationResponseParameter
: public Parameter,
public TLVTrait<ReconfigurationResponseParameterConfig> {
public:
static constexpr int kType = ReconfigurationResponseParameterConfig::kType;
enum class Result {
kSuccessNothingToDo = 0,
kSuccessPerformed = 1,
kDenied = 2,
kErrorWrongSSN = 3,
kErrorRequestAlreadyInProgress = 4,
kErrorBadSequenceNumber = 5,
kInProgress = 6,
};
ReconfigurationResponseParameter(ReconfigRequestSN response_sequence_number,
Result result)
: response_sequence_number_(response_sequence_number),
result_(result),
sender_next_tsn_(absl::nullopt),
receiver_next_tsn_(absl::nullopt) {}
explicit ReconfigurationResponseParameter(
ReconfigRequestSN response_sequence_number,
Result result,
TSN sender_next_tsn,
TSN receiver_next_tsn)
: response_sequence_number_(response_sequence_number),
result_(result),
sender_next_tsn_(sender_next_tsn),
receiver_next_tsn_(receiver_next_tsn) {}
static absl::optional<ReconfigurationResponseParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
ReconfigRequestSN response_sequence_number() const {
return response_sequence_number_;
}
Result result() const { return result_; }
absl::optional<TSN> sender_next_tsn() const { return sender_next_tsn_; }
absl::optional<TSN> receiver_next_tsn() const { return receiver_next_tsn_; }
private:
static constexpr size_t kNextTsnHeaderSize = 8;
ReconfigRequestSN response_sequence_number_;
Result result_;
absl::optional<TSN> sender_next_tsn_;
absl::optional<TSN> receiver_next_tsn_;
};
absl::string_view ToString(ReconfigurationResponseParameter::Result result);
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_RECONFIGURATION_RESPONSE_PARAMETER_H_

View file

@ -0,0 +1,60 @@
/*
* 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.
*/
#include "net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h"
#include <stdint.h>
#include <string>
#include <type_traits>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "rtc_base/strings/string_builder.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.3
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Parameter Type = 15 | Parameter Length = 8 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Re-configuration Request Sequence Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
constexpr int SSNTSNResetRequestParameter::kType;
absl::optional<SSNTSNResetRequestParameter> SSNTSNResetRequestParameter::Parse(
rtc::ArrayView<const uint8_t> data) {
absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
if (!reader.has_value()) {
return absl::nullopt;
}
ReconfigRequestSN request_sequence_number(reader->Load32<4>());
return SSNTSNResetRequestParameter(request_sequence_number);
}
void SSNTSNResetRequestParameter::SerializeTo(std::vector<uint8_t>& out) const {
BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
writer.Store32<4>(*request_sequence_number_);
}
std::string SSNTSNResetRequestParameter::ToString() const {
rtc::StringBuilder sb;
sb << "SSN/TSN Reset Request, req_seq_nbr=" << *request_sequence_number();
return sb.Release();
}
} // namespace dcsctp

View file

@ -0,0 +1,59 @@
/*
* 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_PACKET_PARAMETER_SSN_TSN_RESET_REQUEST_PARAMETER_H_
#define NET_DCSCTP_PACKET_PARAMETER_SSN_TSN_RESET_REQUEST_PARAMETER_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/tlv_trait.h"
namespace dcsctp {
// https://tools.ietf.org/html/rfc6525#section-4.3
struct SSNTSNResetRequestParameterConfig : ParameterConfig {
static constexpr int kType = 15;
static constexpr size_t kHeaderSize = 8;
static constexpr size_t kVariableLengthAlignment = 0;
};
class SSNTSNResetRequestParameter
: public Parameter,
public TLVTrait<SSNTSNResetRequestParameterConfig> {
public:
static constexpr int kType = SSNTSNResetRequestParameterConfig::kType;
explicit SSNTSNResetRequestParameter(
ReconfigRequestSN request_sequence_number)
: request_sequence_number_(request_sequence_number) {}
static absl::optional<SSNTSNResetRequestParameter> Parse(
rtc::ArrayView<const uint8_t> data);
void SerializeTo(std::vector<uint8_t>& out) const override;
std::string ToString() const override;
ReconfigRequestSN request_sequence_number() const {
return request_sequence_number_;
}
private:
ReconfigRequestSN request_sequence_number_;
};
} // namespace dcsctp
#endif // NET_DCSCTP_PACKET_PARAMETER_SSN_TSN_RESET_REQUEST_PARAMETER_H_

Some files were not shown because too many files have changed in this diff Show more