summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/net/dcsctp/packet/chunk
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/net/dcsctp/packet/chunk')
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.cc65
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.h64
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk_test.cc83
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.cc85
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.h63
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.cc46
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.h46
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk_test.cc49
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.cc54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.h53
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk_test.cc58
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.cc101
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.h70
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk_test.cc74
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/data_common.h97
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.cc62
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.h57
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk_test.cc66
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.cc95
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.h55
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk_test.cc64
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_common.h66
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.cc63
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.h63
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk_test.cc79
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.cc64
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.h62
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk_test.cc79
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.cc111
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.h70
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk_test.cc123
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.cc104
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.h54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk_test.cc73
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.cc86
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.h77
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk_test.cc127
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.cc88
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.h77
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk_test.cc113
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.cc69
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.h56
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk_test.cc94
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.cc155
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.h80
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk_test.cc84
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.cc46
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.h47
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk_test.cc45
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.cc55
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.h53
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk_test.cc50
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.cc54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.h54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk_test.cc45
55 files changed, 3973 insertions, 0 deletions
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.cc
new file mode 100644
index 0000000000..8348eb96a9
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.h
new file mode 100644
index 0000000000..1408a75e80
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk_test.cc
new file mode 100644
index 0000000000..c1f3a4d5b9
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/abort_chunk_test.cc
@@ -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/chunk/abort_chunk.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(AbortChunkTest, FromCapture) {
+ /*
+ ABORT chunk
+ Chunk type: ABORT (6)
+ Chunk flags: 0x00
+ Chunk length: 8
+ User initiated ABORT cause
+ */
+
+ uint8_t data[] = {0x06, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(AbortChunk chunk, AbortChunk::Parse(data));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UserInitiatedAbortCause cause,
+ chunk.error_causes().get<UserInitiatedAbortCause>());
+
+ EXPECT_EQ(cause.upper_layer_abort_reason(), "");
+}
+
+TEST(AbortChunkTest, SerializeAndDeserialize) {
+ AbortChunk chunk(/*filled_in_verification_tag=*/true,
+ Parameters::Builder()
+ .Add(UserInitiatedAbortCause("Close called"))
+ .Build());
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(AbortChunk deserialized,
+ AbortChunk::Parse(serialized));
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UserInitiatedAbortCause cause,
+ deserialized.error_causes().get<UserInitiatedAbortCause>());
+
+ EXPECT_EQ(cause.upper_layer_abort_reason(), "Close called");
+}
+
+// Validates that AbortChunk doesn't make any alignment assumptions.
+TEST(AbortChunkTest, SerializeAndDeserializeOneChar) {
+ AbortChunk chunk(
+ /*filled_in_verification_tag=*/true,
+ Parameters::Builder().Add(UserInitiatedAbortCause("!")).Build());
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(AbortChunk deserialized,
+ AbortChunk::Parse(serialized));
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UserInitiatedAbortCause cause,
+ deserialized.error_causes().get<UserInitiatedAbortCause>());
+
+ EXPECT_EQ(cause.upper_layer_abort_reason(), "!");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.cc
new file mode 100644
index 0000000000..832ab82288
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.h
new file mode 100644
index 0000000000..687aa1daa1
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.cc
new file mode 100644
index 0000000000..4839969ccf
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.h
new file mode 100644
index 0000000000..f7d4a33f7d
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk_test.cc
new file mode 100644
index 0000000000..3f560c6fef
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_ack_chunk_test.cc
@@ -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.
+ */
+#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(CookieAckChunkTest, FromCapture) {
+ /*
+ COOKIE_ACK chunk
+ Chunk type: COOKIE_ACK (11)
+ Chunk flags: 0x00
+ Chunk length: 4
+ */
+
+ uint8_t data[] = {0x0b, 0x00, 0x00, 0x04};
+
+ EXPECT_TRUE(CookieAckChunk::Parse(data).has_value());
+}
+
+TEST(CookieAckChunkTest, SerializeAndDeserialize) {
+ CookieAckChunk chunk;
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(CookieAckChunk deserialized,
+ CookieAckChunk::Parse(serialized));
+ EXPECT_EQ(deserialized.ToString(), "COOKIE-ACK");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.cc
new file mode 100644
index 0000000000..a01d0b13c4
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.h
new file mode 100644
index 0000000000..8cb80527f8
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk_test.cc
new file mode 100644
index 0000000000..d06e0a6439
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/cookie_echo_chunk_test.cc
@@ -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/chunk/cookie_echo_chunk.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(CookieEchoChunkTest, FromCapture) {
+ /*
+ COOKIE_ECHO chunk (Cookie length: 256 bytes)
+ Chunk type: COOKIE_ECHO (10)
+ Chunk flags: 0x00
+ Chunk length: 260
+ Cookie: 12345678
+ */
+
+ uint8_t data[] = {0x0a, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(CookieEchoChunk chunk,
+ CookieEchoChunk::Parse(data));
+
+ EXPECT_THAT(chunk.cookie(), ElementsAre(0x12, 0x34, 0x56, 0x78));
+}
+
+TEST(CookieEchoChunkTest, SerializeAndDeserialize) {
+ uint8_t cookie[] = {1, 2, 3, 4};
+ CookieEchoChunk chunk(cookie);
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(CookieEchoChunk deserialized,
+ CookieEchoChunk::Parse(serialized));
+
+ EXPECT_THAT(deserialized.cookie(), ElementsAre(1, 2, 3, 4));
+ EXPECT_EQ(deserialized.ToString(), "COOKIE-ECHO");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.cc
new file mode 100644
index 0000000000..769be2db91
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.h
new file mode 100644
index 0000000000..12bb05f2c4
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk_test.cc
new file mode 100644
index 0000000000..def99ceb23
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_chunk_test.cc
@@ -0,0 +1,74 @@
+/*
+ * 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 <cstdint>
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(DataChunkTest, FromCapture) {
+ /*
+ DATA chunk(ordered, complete segment, TSN: 1426601532, SID: 2, SSN: 1,
+ PPID: 53, payload length: 4 bytes)
+ Chunk type: DATA (0)
+ Chunk flags: 0x03
+ Chunk length: 20
+ Transmission sequence number: 1426601532
+ Stream identifier: 0x0002
+ Stream sequence number: 1
+ Payload protocol identifier: WebRTC Binary (53)
+ */
+
+ uint8_t data[] = {0x00, 0x03, 0x00, 0x14, 0x55, 0x08, 0x36, 0x3c, 0x00, 0x02,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x35, 0x00, 0x01, 0x02, 0x03};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(DataChunk chunk, DataChunk::Parse(data));
+ EXPECT_EQ(*chunk.tsn(), 1426601532u);
+ EXPECT_EQ(*chunk.stream_id(), 2u);
+ EXPECT_EQ(*chunk.ssn(), 1u);
+ EXPECT_EQ(*chunk.ppid(), 53u);
+ EXPECT_TRUE(*chunk.options().is_beginning);
+ EXPECT_TRUE(*chunk.options().is_end);
+ EXPECT_FALSE(*chunk.options().is_unordered);
+ EXPECT_FALSE(*chunk.options().immediate_ack);
+ EXPECT_THAT(chunk.payload(), ElementsAre(0x0, 0x1, 0x2, 0x3));
+}
+
+TEST(DataChunkTest, SerializeAndDeserialize) {
+ DataChunk chunk(TSN(123), StreamID(456), SSN(789), PPID(9090),
+ /*payload=*/{1, 2, 3, 4, 5},
+ /*options=*/{});
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(DataChunk deserialized,
+ DataChunk::Parse(serialized));
+ EXPECT_EQ(*chunk.tsn(), 123u);
+ EXPECT_EQ(*chunk.stream_id(), 456u);
+ EXPECT_EQ(*chunk.ssn(), 789u);
+ EXPECT_EQ(*chunk.ppid(), 9090u);
+ EXPECT_THAT(chunk.payload(), ElementsAre(1, 2, 3, 4, 5));
+
+ EXPECT_EQ(deserialized.ToString(),
+ "DATA, type=ordered::middle, tsn=123, sid=456, ssn=789, ppid=9090, "
+ "length=5");
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/data_common.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_common.h
new file mode 100644
index 0000000000..b67efeee1e
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/data_common.h
@@ -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 message_id() const { return data_.message_id; }
+ 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 message_id,
+ FSN fsn,
+ PPID ppid,
+ std::vector<uint8_t> payload,
+ const Options& options)
+ : tsn_(tsn),
+ data_(stream_id,
+ ssn,
+ message_id,
+ 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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.cc
new file mode 100644
index 0000000000..baac0c5588
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.h
new file mode 100644
index 0000000000..96122cff6a
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk_test.cc
new file mode 100644
index 0000000000..f2b8be1edc
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/error_chunk_test.cc
@@ -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.
+ */
+#include "net/dcsctp/packet/chunk/error_chunk.h"
+
+#include <cstdint>
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(ErrorChunkTest, FromCapture) {
+ /*
+ ERROR chunk
+ Chunk type: ERROR (9)
+ Chunk flags: 0x00
+ Chunk length: 12
+ Unrecognized chunk type cause (Type: 73 (unknown))
+ */
+
+ uint8_t data[] = {0x09, 0x00, 0x00, 0x0c, 0x00, 0x06,
+ 0x00, 0x08, 0x49, 0x00, 0x00, 0x04};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ErrorChunk chunk, ErrorChunk::Parse(data));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UnrecognizedChunkTypeCause cause,
+ chunk.error_causes().get<UnrecognizedChunkTypeCause>());
+
+ EXPECT_THAT(cause.unrecognized_chunk(), ElementsAre(0x49, 0x00, 0x00, 0x04));
+}
+
+TEST(ErrorChunkTest, SerializeAndDeserialize) {
+ ErrorChunk chunk(Parameters::Builder()
+ .Add(UnrecognizedChunkTypeCause({1, 2, 3, 4}))
+ .Build());
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ErrorChunk deserialized,
+ ErrorChunk::Parse(serialized));
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UnrecognizedChunkTypeCause cause,
+ deserialized.error_causes().get<UnrecognizedChunkTypeCause>());
+
+ EXPECT_THAT(cause.unrecognized_chunk(), ElementsAre(1, 2, 3, 4));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.cc
new file mode 100644
index 0000000000..e432114c50
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.h
new file mode 100644
index 0000000000..b9ef666f41
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk_test.cc
new file mode 100644
index 0000000000..51f97f2396
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_chunk_test.cc
@@ -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/forward_tsn_chunk.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(ForwardTsnChunkTest, FromCapture) {
+ /*
+ FORWARD_TSN chunk(Cumulative TSN: 1905748778)
+ Chunk type: FORWARD_TSN (192)
+ Chunk flags: 0x00
+ Chunk length: 8
+ New cumulative TSN: 1905748778
+ */
+
+ uint8_t data[] = {0xc0, 0x00, 0x00, 0x08, 0x71, 0x97, 0x6b, 0x2a};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ForwardTsnChunk chunk,
+ ForwardTsnChunk::Parse(data));
+ EXPECT_EQ(*chunk.new_cumulative_tsn(), 1905748778u);
+}
+
+TEST(ForwardTsnChunkTest, SerializeAndDeserialize) {
+ ForwardTsnChunk chunk(
+ TSN(123), {ForwardTsnChunk::SkippedStream(StreamID(1), SSN(23)),
+ ForwardTsnChunk::SkippedStream(StreamID(42), SSN(99))});
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ForwardTsnChunk deserialized,
+ ForwardTsnChunk::Parse(serialized));
+ EXPECT_EQ(*deserialized.new_cumulative_tsn(), 123u);
+ EXPECT_THAT(
+ deserialized.skipped_streams(),
+ ElementsAre(ForwardTsnChunk::SkippedStream(StreamID(1), SSN(23)),
+ ForwardTsnChunk::SkippedStream(StreamID(42), SSN(99))));
+
+ EXPECT_EQ(deserialized.ToString(),
+ "FORWARD-TSN, new_cumulative_tsn=123, skip 1:23, skip 42:99");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_common.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_common.h
new file mode 100644
index 0000000000..37bd2aafff
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/forward_tsn_common.h
@@ -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_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), message_id(0) {}
+ SkippedStream(IsUnordered unordered, StreamID stream_id, MID message_id)
+ : stream_id(stream_id),
+ ssn(0),
+ unordered(unordered),
+ message_id(message_id) {}
+
+ StreamID stream_id;
+
+ // Set for FORWARD_TSN
+ SSN ssn;
+
+ // Set for I-FORWARD_TSN
+ IsUnordered unordered;
+ MID message_id;
+
+ bool operator==(const SkippedStream& other) const {
+ return stream_id == other.stream_id && ssn == other.ssn &&
+ unordered == other.unordered && message_id == other.message_id;
+ }
+ };
+
+ 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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.cc
new file mode 100644
index 0000000000..3cbcd09c75
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.h
new file mode 100644
index 0000000000..a6479f78b0
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk_test.cc
new file mode 100644
index 0000000000..e4d0dd1489
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_ack_chunk_test.cc
@@ -0,0 +1,79 @@
+/*
+ * 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 "api/array_view.h"
+#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(HeartbeatAckChunkTest, FromCapture) {
+ /*
+ HEARTBEAT_ACK chunk (Information: 40 bytes)
+ Chunk type: HEARTBEAT_ACK (5)
+ Chunk flags: 0x00
+ Chunk length: 44
+ Heartbeat info parameter (Information: 36 bytes)
+ Parameter type: Heartbeat info (0x0001)
+ Parameter length: 40
+ Heartbeat information: ad2436603726070000000000000000007b1000000100…
+ */
+
+ uint8_t data[] = {0x05, 0x00, 0x00, 0x2c, 0x00, 0x01, 0x00, 0x28, 0xad,
+ 0x24, 0x36, 0x60, 0x37, 0x26, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x10, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatAckChunk chunk,
+ HeartbeatAckChunk::Parse(data));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatInfoParameter info, chunk.info());
+
+ EXPECT_THAT(
+ info.info(),
+ ElementsAre(0xad, 0x24, 0x36, 0x60, 0x37, 0x26, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x10, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+}
+
+TEST(HeartbeatAckChunkTest, SerializeAndDeserialize) {
+ uint8_t info_data[] = {1, 2, 3, 4};
+ Parameters parameters =
+ Parameters::Builder().Add(HeartbeatInfoParameter(info_data)).Build();
+ HeartbeatAckChunk chunk(std::move(parameters));
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatAckChunk deserialized,
+ HeartbeatAckChunk::Parse(serialized));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatInfoParameter info, deserialized.info());
+
+ EXPECT_THAT(info.info(), ElementsAre(1, 2, 3, 4));
+
+ EXPECT_EQ(deserialized.ToString(), "HEARTBEAT-ACK");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.cc
new file mode 100644
index 0000000000..d759d6b16d
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.h
new file mode 100644
index 0000000000..fe2ce19504
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk_test.cc
new file mode 100644
index 0000000000..94911fe28b
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/heartbeat_request_chunk_test.cc
@@ -0,0 +1,79 @@
+/*
+ * 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 "api/array_view.h"
+#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(HeartbeatRequestChunkTest, FromCapture) {
+ /*
+ HEARTBEAT chunk (Information: 40 bytes)
+ Chunk type: HEARTBEAT (4)
+ Chunk flags: 0x00
+ Chunk length: 44
+ Heartbeat info parameter (Information: 36 bytes)
+ Parameter type: Heartbeat info (0x0001)
+ Parameter length: 40
+ Heartbeat information: ad2436603726070000000000000000007b10000001…
+ */
+
+ uint8_t data[] = {0x04, 0x00, 0x00, 0x2c, 0x00, 0x01, 0x00, 0x28, 0xad,
+ 0x24, 0x36, 0x60, 0x37, 0x26, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x10, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatRequestChunk chunk,
+ HeartbeatRequestChunk::Parse(data));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatInfoParameter info, chunk.info());
+
+ EXPECT_THAT(
+ info.info(),
+ ElementsAre(0xad, 0x24, 0x36, 0x60, 0x37, 0x26, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x10, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+}
+
+TEST(HeartbeatRequestChunkTest, SerializeAndDeserialize) {
+ uint8_t info_data[] = {1, 2, 3, 4};
+ Parameters parameters =
+ Parameters::Builder().Add(HeartbeatInfoParameter(info_data)).Build();
+ HeartbeatRequestChunk chunk(std::move(parameters));
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatRequestChunk deserialized,
+ HeartbeatRequestChunk::Parse(serialized));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatInfoParameter info, deserialized.info());
+
+ EXPECT_THAT(info.info(), ElementsAre(1, 2, 3, 4));
+
+ EXPECT_EQ(deserialized.ToString(), "HEARTBEAT");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.cc
new file mode 100644
index 0000000000..378c527909
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.cc
@@ -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 message_id(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, message_id,
+ 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>(*message_id());
+ 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()
+ << ", message_id=" << *message_id();
+
+ if (*options().is_beginning) {
+ sb << ", ppid=" << *ppid();
+ } else {
+ sb << ", fsn=" << *fsn();
+ }
+ sb << ", length=" << payload().size();
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.h
new file mode 100644
index 0000000000..8cdf2a1fc4
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk.h
@@ -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 message_id,
+ PPID ppid,
+ FSN fsn,
+ std::vector<uint8_t> payload,
+ const Options& options)
+ : AnyDataChunk(tsn,
+ stream_id,
+ SSN(0),
+ message_id,
+ 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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk_test.cc
new file mode 100644
index 0000000000..fea492d71e
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/idata_chunk_test.cc
@@ -0,0 +1,123 @@
+/*
+ * 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 <cstdint>
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(IDataChunkTest, AtBeginningFromCapture) {
+ /*
+ I_DATA chunk(ordered, first segment, TSN: 2487901653, SID: 1, MID: 0,
+ payload length: 1180 bytes)
+ Chunk type: I_DATA (64)
+ Chunk flags: 0x02
+ Chunk length: 1200
+ Transmission sequence number: 2487901653
+ Stream identifier: 0x0001
+ Reserved: 0
+ Message identifier: 0
+ Payload protocol identifier: WebRTC Binary (53)
+ Reassembled Message in frame: 39
+ */
+
+ uint8_t data[] = {0x40, 0x02, 0x00, 0x15, 0x94, 0x4a, 0x5d, 0xd5,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(IDataChunk chunk, IDataChunk::Parse(data));
+ EXPECT_EQ(*chunk.tsn(), 2487901653);
+ EXPECT_EQ(*chunk.stream_id(), 1);
+ EXPECT_EQ(*chunk.message_id(), 0u);
+ EXPECT_EQ(*chunk.ppid(), 53u);
+ EXPECT_EQ(*chunk.fsn(), 0u); // Not provided (so set to zero)
+}
+
+TEST(IDataChunkTest, AtBeginningSerializeAndDeserialize) {
+ IDataChunk::Options options;
+ options.is_beginning = Data::IsBeginning(true);
+ IDataChunk chunk(TSN(123), StreamID(456), MID(789), PPID(53), FSN(0), {1},
+ options);
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(IDataChunk deserialized,
+ IDataChunk::Parse(serialized));
+ EXPECT_EQ(*deserialized.tsn(), 123u);
+ EXPECT_EQ(*deserialized.stream_id(), 456u);
+ EXPECT_EQ(*deserialized.message_id(), 789u);
+ EXPECT_EQ(*deserialized.ppid(), 53u);
+ EXPECT_EQ(*deserialized.fsn(), 0u);
+
+ EXPECT_EQ(deserialized.ToString(),
+ "I-DATA, type=ordered::first, tsn=123, stream_id=456, "
+ "message_id=789, ppid=53, length=1");
+}
+
+TEST(IDataChunkTest, InMiddleFromCapture) {
+ /*
+ I_DATA chunk(ordered, last segment, TSN: 2487901706, SID: 3, MID: 1,
+ FSN: 8, payload length: 560 bytes)
+ Chunk type: I_DATA (64)
+ Chunk flags: 0x01
+ Chunk length: 580
+ Transmission sequence number: 2487901706
+ Stream identifier: 0x0003
+ Reserved: 0
+ Message identifier: 1
+ Fragment sequence number: 8
+ Reassembled SCTP Fragments (10000 bytes, 9 fragments):
+ */
+
+ uint8_t data[] = {0x40, 0x01, 0x00, 0x15, 0x94, 0x4a, 0x5e, 0x0a,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(IDataChunk chunk, IDataChunk::Parse(data));
+ EXPECT_EQ(*chunk.tsn(), 2487901706);
+ EXPECT_EQ(*chunk.stream_id(), 3u);
+ EXPECT_EQ(*chunk.message_id(), 1u);
+ EXPECT_EQ(*chunk.ppid(), 0u); // Not provided (so set to zero)
+ EXPECT_EQ(*chunk.fsn(), 8u);
+}
+
+TEST(IDataChunkTest, InMiddleSerializeAndDeserialize) {
+ IDataChunk chunk(TSN(123), StreamID(456), MID(789), PPID(0), FSN(101112),
+ {1, 2, 3}, /*options=*/{});
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(IDataChunk deserialized,
+ IDataChunk::Parse(serialized));
+ EXPECT_EQ(*deserialized.tsn(), 123u);
+ EXPECT_EQ(*deserialized.stream_id(), 456u);
+ EXPECT_EQ(*deserialized.message_id(), 789u);
+ EXPECT_EQ(*deserialized.ppid(), 0u);
+ EXPECT_EQ(*deserialized.fsn(), 101112u);
+ EXPECT_THAT(deserialized.payload(), ElementsAre(1, 2, 3));
+
+ EXPECT_EQ(deserialized.ToString(),
+ "I-DATA, type=ordered::middle, tsn=123, stream_id=456, "
+ "message_id=789, fsn=101112, length=3");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.cc
new file mode 100644
index 0000000000..a647a8bf8a
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.cc
@@ -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 message_id(sub_reader.Load32<4>());
+ skipped_streams.emplace_back(unordered, stream_id, message_id);
+ 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].message_id);
+ 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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.h
new file mode 100644
index 0000000000..54d23f7a83
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk_test.cc
new file mode 100644
index 0000000000..6a89433be1
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/iforward_tsn_chunk_test.cc
@@ -0,0 +1,73 @@
+/*
+ * 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 <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(IForwardTsnChunkTest, FromCapture) {
+ /*
+ I_FORWARD_TSN chunk(Cumulative TSN: 3094631148)
+ Chunk type: I_FORWARD_TSN (194)
+ Chunk flags: 0x00
+ Chunk length: 16
+ New cumulative TSN: 3094631148
+ Stream identifier: 1
+ Flags: 0x0000
+ Message identifier: 2
+ */
+
+ uint8_t data[] = {0xc2, 0x00, 0x00, 0x10, 0xb8, 0x74, 0x52, 0xec,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(IForwardTsnChunk chunk,
+ IForwardTsnChunk::Parse(data));
+ EXPECT_EQ(*chunk.new_cumulative_tsn(), 3094631148u);
+ EXPECT_THAT(chunk.skipped_streams(),
+ ElementsAre(IForwardTsnChunk::SkippedStream(
+ IsUnordered(false), StreamID(1), MID(2))));
+}
+
+TEST(IForwardTsnChunkTest, SerializeAndDeserialize) {
+ IForwardTsnChunk chunk(
+ TSN(123), {IForwardTsnChunk::SkippedStream(IsUnordered(false),
+ StreamID(1), MID(23)),
+ IForwardTsnChunk::SkippedStream(IsUnordered(true),
+ StreamID(42), MID(99))});
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(IForwardTsnChunk deserialized,
+ IForwardTsnChunk::Parse(serialized));
+ EXPECT_EQ(*deserialized.new_cumulative_tsn(), 123u);
+ EXPECT_THAT(deserialized.skipped_streams(),
+ ElementsAre(IForwardTsnChunk::SkippedStream(IsUnordered(false),
+ StreamID(1), MID(23)),
+ IForwardTsnChunk::SkippedStream(
+ IsUnordered(true), StreamID(42), MID(99))));
+
+ EXPECT_EQ(deserialized.ToString(), "I-FORWARD-TSN, new_cumulative_tsn=123");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.cc
new file mode 100644
index 0000000000..c7ef9da1f1
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.h
new file mode 100644
index 0000000000..6fcf64b2eb
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk_test.cc
new file mode 100644
index 0000000000..184ade747d
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_ack_chunk_test.cc
@@ -0,0 +1,127 @@
+/*
+ * 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 <utility>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
+#include "net/dcsctp/packet/parameter/supported_extensions_parameter.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(InitAckChunkTest, FromCapture) {
+ /*
+ INIT_ACK chunk (Outbound streams: 1000, inbound streams: 2048)
+ Chunk type: INIT_ACK (2)
+ Chunk flags: 0x00
+ Chunk length: 292
+ Initiate tag: 0x579c2f98
+ Advertised receiver window credit (a_rwnd): 131072
+ Number of outbound streams: 1000
+ Number of inbound streams: 2048
+ Initial TSN: 1670811335
+ Forward TSN supported parameter
+ Parameter type: Forward TSN supported (0xc000)
+ Parameter length: 4
+ Supported Extensions parameter (Supported types: FORWARD_TSN, RE_CONFIG)
+ Parameter type: Supported Extensions (0x8008)
+ Parameter length: 6
+ Supported chunk type: FORWARD_TSN (192)
+ Supported chunk type: RE_CONFIG (130)
+ Parameter padding: 0000
+ State cookie parameter (Cookie length: 256 bytes)
+ Parameter type: State cookie (0x0007)
+ Parameter length: 260
+ State cookie: 4b414d452d42534420312e310000000096b8386000000000…
+ */
+
+ uint8_t data[] = {
+ 0x02, 0x00, 0x01, 0x24, 0x57, 0x9c, 0x2f, 0x98, 0x00, 0x02, 0x00, 0x00,
+ 0x03, 0xe8, 0x08, 0x00, 0x63, 0x96, 0x8e, 0xc7, 0xc0, 0x00, 0x00, 0x04,
+ 0x80, 0x08, 0x00, 0x06, 0xc0, 0x82, 0x00, 0x00, 0x00, 0x07, 0x01, 0x04,
+ 0x4b, 0x41, 0x4d, 0x45, 0x2d, 0x42, 0x53, 0x44, 0x20, 0x31, 0x2e, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x96, 0xb8, 0x38, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x52, 0x5a, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xea, 0x00, 0x00,
+ 0xb5, 0xaa, 0x19, 0xea, 0x31, 0xef, 0xa4, 0x2b, 0x90, 0x16, 0x7a, 0xde,
+ 0x57, 0x9c, 0x2f, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5a, 0xde, 0x7a, 0x16, 0x90,
+ 0x00, 0x02, 0x00, 0x00, 0x03, 0xe8, 0x03, 0xe8, 0x25, 0x0d, 0x37, 0xe8,
+ 0x80, 0x00, 0x00, 0x04, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09,
+ 0xc0, 0x0f, 0xc1, 0x80, 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24,
+ 0xab, 0x31, 0x44, 0x62, 0x12, 0x1a, 0x15, 0x13, 0xfd, 0x5a, 0x5f, 0x69,
+ 0xef, 0xaa, 0x06, 0xe9, 0xab, 0xd7, 0x48, 0xcc, 0x3b, 0xd1, 0x4b, 0x60,
+ 0xed, 0x7f, 0xa6, 0x44, 0xce, 0x4d, 0xd2, 0xad, 0x80, 0x04, 0x00, 0x06,
+ 0x00, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00,
+ 0x02, 0x00, 0x01, 0x24, 0x57, 0x9c, 0x2f, 0x98, 0x00, 0x02, 0x00, 0x00,
+ 0x03, 0xe8, 0x08, 0x00, 0x63, 0x96, 0x8e, 0xc7, 0xc0, 0x00, 0x00, 0x04,
+ 0x80, 0x08, 0x00, 0x06, 0xc0, 0x82, 0x00, 0x00, 0x51, 0x95, 0x01, 0x88,
+ 0x0d, 0x80, 0x7b, 0x19, 0xe7, 0xf9, 0xc6, 0x18, 0x5c, 0x4a, 0xbf, 0x39,
+ 0x32, 0xe5, 0x63, 0x8e};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(InitAckChunk chunk, InitAckChunk::Parse(data));
+
+ EXPECT_EQ(chunk.initiate_tag(), VerificationTag(0x579c2f98u));
+ EXPECT_EQ(chunk.a_rwnd(), 131072u);
+ EXPECT_EQ(chunk.nbr_outbound_streams(), 1000u);
+ EXPECT_EQ(chunk.nbr_inbound_streams(), 2048u);
+ EXPECT_EQ(chunk.initial_tsn(), TSN(1670811335u));
+ EXPECT_TRUE(
+ chunk.parameters().get<ForwardTsnSupportedParameter>().has_value());
+ EXPECT_TRUE(
+ chunk.parameters().get<SupportedExtensionsParameter>().has_value());
+ EXPECT_TRUE(chunk.parameters().get<StateCookieParameter>().has_value());
+}
+
+TEST(InitAckChunkTest, SerializeAndDeserialize) {
+ uint8_t state_cookie[] = {1, 2, 3, 4, 5};
+ Parameters parameters =
+ Parameters::Builder().Add(StateCookieParameter(state_cookie)).Build();
+ InitAckChunk chunk(VerificationTag(123), /*a_rwnd=*/456,
+ /*nbr_outbound_streams=*/65535,
+ /*nbr_inbound_streams=*/65534, /*initial_tsn=*/TSN(789),
+ /*parameters=*/std::move(parameters));
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(InitAckChunk deserialized,
+ InitAckChunk::Parse(serialized));
+
+ EXPECT_EQ(chunk.initiate_tag(), VerificationTag(123u));
+ EXPECT_EQ(chunk.a_rwnd(), 456u);
+ EXPECT_EQ(chunk.nbr_outbound_streams(), 65535u);
+ EXPECT_EQ(chunk.nbr_inbound_streams(), 65534u);
+ EXPECT_EQ(chunk.initial_tsn(), TSN(789u));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ StateCookieParameter cookie,
+ deserialized.parameters().get<StateCookieParameter>());
+ EXPECT_THAT(cookie.data(), ElementsAre(1, 2, 3, 4, 5));
+ EXPECT_EQ(deserialized.ToString(),
+ "INIT_ACK, initiate_tag=0x7b, initial_tsn=789");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.cc
new file mode 100644
index 0000000000..8030107072
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.h
new file mode 100644
index 0000000000..38f9994caa
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk_test.cc
new file mode 100644
index 0000000000..bd36d6fdf8
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/init_chunk_test.cc
@@ -0,0 +1,113 @@
+/*
+ * 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 <type_traits>
+#include <vector>
+
+#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/parameter/supported_extensions_parameter.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(InitChunkTest, FromCapture) {
+ /*
+ INIT chunk (Outbound streams: 1000, inbound streams: 1000)
+ Chunk type: INIT (1)
+ Chunk flags: 0x00
+ Chunk length: 90
+ Initiate tag: 0xde7a1690
+ Advertised receiver window credit (a_rwnd): 131072
+ Number of outbound streams: 1000
+ Number of inbound streams: 1000
+ Initial TSN: 621623272
+ ECN parameter
+ Parameter type: ECN (0x8000)
+ Parameter length: 4
+ Forward TSN supported parameter
+ Parameter type: Forward TSN supported (0xc000)
+ Parameter length: 4
+ Supported Extensions parameter (Supported types: FORWARD_TSN, AUTH,
+ ASCONF, ASCONF_ACK, RE_CONFIG) Parameter type: Supported Extensions (0x8008)
+ Parameter length: 9
+ Supported chunk type: FORWARD_TSN (192)
+ Supported chunk type: AUTH (15)
+ Supported chunk type: ASCONF (193)
+ Supported chunk type: ASCONF_ACK (128)
+ Supported chunk type: RE_CONFIG (130)
+ Parameter padding: 000000
+ Random parameter
+ Parameter type: Random (0x8002)
+ Parameter length: 36
+ Random number: ab314462121a1513fd5a5f69efaa06e9abd748cc3bd14b60…
+ Requested HMAC Algorithm parameter (Supported HMACs: SHA-1)
+ Parameter type: Requested HMAC Algorithm (0x8004)
+ Parameter length: 6
+ HMAC identifier: SHA-1 (1)
+ Parameter padding: 0000
+ Authenticated Chunk list parameter (Chunk types to be authenticated:
+ ASCONF_ACK, ASCONF) Parameter type: Authenticated Chunk list (0x8003)
+ Parameter length: 6
+ Chunk type: ASCONF_ACK (128)
+ Chunk type: ASCONF (193)
+ */
+
+ uint8_t data[] = {
+ 0x01, 0x00, 0x00, 0x5a, 0xde, 0x7a, 0x16, 0x90, 0x00, 0x02, 0x00, 0x00,
+ 0x03, 0xe8, 0x03, 0xe8, 0x25, 0x0d, 0x37, 0xe8, 0x80, 0x00, 0x00, 0x04,
+ 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80,
+ 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0xab, 0x31, 0x44, 0x62,
+ 0x12, 0x1a, 0x15, 0x13, 0xfd, 0x5a, 0x5f, 0x69, 0xef, 0xaa, 0x06, 0xe9,
+ 0xab, 0xd7, 0x48, 0xcc, 0x3b, 0xd1, 0x4b, 0x60, 0xed, 0x7f, 0xa6, 0x44,
+ 0xce, 0x4d, 0xd2, 0xad, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(InitChunk chunk, InitChunk::Parse(data));
+
+ EXPECT_EQ(chunk.initiate_tag(), VerificationTag(0xde7a1690));
+ EXPECT_EQ(chunk.a_rwnd(), 131072u);
+ EXPECT_EQ(chunk.nbr_outbound_streams(), 1000u);
+ EXPECT_EQ(chunk.nbr_inbound_streams(), 1000u);
+ EXPECT_EQ(chunk.initial_tsn(), TSN(621623272u));
+ EXPECT_TRUE(
+ chunk.parameters().get<ForwardTsnSupportedParameter>().has_value());
+ EXPECT_TRUE(
+ chunk.parameters().get<SupportedExtensionsParameter>().has_value());
+}
+
+TEST(InitChunkTest, SerializeAndDeserialize) {
+ InitChunk chunk(VerificationTag(123), /*a_rwnd=*/456,
+ /*nbr_outbound_streams=*/65535,
+ /*nbr_inbound_streams=*/65534, /*initial_tsn=*/TSN(789),
+ /*parameters=*/Parameters::Builder().Build());
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(InitChunk deserialized,
+ InitChunk::Parse(serialized));
+
+ EXPECT_EQ(deserialized.initiate_tag(), VerificationTag(123u));
+ EXPECT_EQ(deserialized.a_rwnd(), 456u);
+ EXPECT_EQ(deserialized.nbr_outbound_streams(), 65535u);
+ EXPECT_EQ(deserialized.nbr_inbound_streams(), 65534u);
+ EXPECT_EQ(deserialized.initial_tsn(), TSN(789u));
+ EXPECT_EQ(deserialized.ToString(),
+ "INIT, initiate_tag=0x7b, initial_tsn=789");
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.cc
new file mode 100644
index 0000000000..f39f3b619f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.h
new file mode 100644
index 0000000000..9d2539a515
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk_test.cc
new file mode 100644
index 0000000000..dbf40ff8c0
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/reconfig_chunk_test.cc
@@ -0,0 +1,94 @@
+/*
+ * 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 <cstdint>
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+
+TEST(ReConfigChunkTest, FromCapture) {
+ /*
+ RE_CONFIG chunk
+ Chunk type: RE_CONFIG (130)
+ Chunk flags: 0x00
+ Chunk length: 22
+ Outgoing SSN reset request parameter
+ Parameter type: Outgoing SSN reset request (0x000d)
+ Parameter length: 18
+ Re-configuration request sequence number: 2270550051
+ Re-configuration response sequence number: 1905748638
+ Senders last assigned TSN: 2270550066
+ Stream Identifier: 6
+ Chunk padding: 0000
+ */
+
+ uint8_t data[] = {0x82, 0x00, 0x00, 0x16, 0x00, 0x0d, 0x00, 0x12,
+ 0x87, 0x55, 0xd8, 0x23, 0x71, 0x97, 0x6a, 0x9e,
+ 0x87, 0x55, 0xd8, 0x32, 0x00, 0x06, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ReConfigChunk chunk, ReConfigChunk::Parse(data));
+
+ const Parameters& parameters = chunk.parameters();
+ EXPECT_THAT(parameters.descriptors(), SizeIs(1));
+ ParameterDescriptor desc = parameters.descriptors()[0];
+ ASSERT_EQ(desc.type, OutgoingSSNResetRequestParameter::kType);
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ OutgoingSSNResetRequestParameter req,
+ OutgoingSSNResetRequestParameter::Parse(desc.data));
+ EXPECT_EQ(*req.request_sequence_number(), 2270550051u);
+ EXPECT_EQ(*req.response_sequence_number(), 1905748638u);
+ EXPECT_EQ(*req.sender_last_assigned_tsn(), 2270550066u);
+ EXPECT_THAT(req.stream_ids(), ElementsAre(StreamID(6)));
+}
+
+TEST(ReConfigChunkTest, SerializeAndDeserialize) {
+ Parameters::Builder params_builder =
+ Parameters::Builder().Add(OutgoingSSNResetRequestParameter(
+ ReconfigRequestSN(123), ReconfigRequestSN(456), TSN(789),
+ {StreamID(42), StreamID(43)}));
+
+ ReConfigChunk chunk(params_builder.Build());
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ReConfigChunk deserialized,
+ ReConfigChunk::Parse(serialized));
+
+ const Parameters& parameters = deserialized.parameters();
+ EXPECT_THAT(parameters.descriptors(), SizeIs(1));
+ ParameterDescriptor desc = parameters.descriptors()[0];
+ ASSERT_EQ(desc.type, OutgoingSSNResetRequestParameter::kType);
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ OutgoingSSNResetRequestParameter req,
+ OutgoingSSNResetRequestParameter::Parse(desc.data));
+ EXPECT_EQ(*req.request_sequence_number(), 123u);
+ EXPECT_EQ(*req.response_sequence_number(), 456u);
+ EXPECT_EQ(*req.sender_last_assigned_tsn(), 789u);
+ EXPECT_THAT(req.stream_ids(), ElementsAre(StreamID(42), StreamID(43)));
+
+ EXPECT_EQ(deserialized.ToString(), "RE-CONFIG");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.cc
new file mode 100644
index 0000000000..d80e430082
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.cc
@@ -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/common/str_join.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/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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.h
new file mode 100644
index 0000000000..e6758fa332
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk_test.cc
new file mode 100644
index 0000000000..9122945308
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/sack_chunk_test.cc
@@ -0,0 +1,84 @@
+/*
+ * 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 <cstdint>
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(SackChunkTest, FromCapture) {
+ /*
+ SACK chunk (Cumulative TSN: 916312075, a_rwnd: 126323,
+ gaps: 2, duplicate TSNs: 1)
+ Chunk type: SACK (3)
+ Chunk flags: 0x00
+ Chunk length: 28
+ Cumulative TSN ACK: 916312075
+ Advertised receiver window credit (a_rwnd): 126323
+ Number of gap acknowledgement blocks: 2
+ Number of duplicated TSNs: 1
+ Gap Acknowledgement for TSN 916312077 to 916312081
+ Gap Acknowledgement for TSN 916312083 to 916312083
+ [Number of TSNs in gap acknowledgement blocks: 6]
+ Duplicate TSN: 916312081
+
+ */
+
+ uint8_t data[] = {0x03, 0x00, 0x00, 0x1c, 0x36, 0x9d, 0xd0, 0x0b, 0x00, 0x01,
+ 0xed, 0x73, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x06,
+ 0x00, 0x08, 0x00, 0x08, 0x36, 0x9d, 0xd0, 0x11};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SackChunk chunk, SackChunk::Parse(data));
+
+ TSN cum_ack_tsn(916312075);
+ EXPECT_EQ(chunk.cumulative_tsn_ack(), cum_ack_tsn);
+ EXPECT_EQ(chunk.a_rwnd(), 126323u);
+ EXPECT_THAT(
+ chunk.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(
+ static_cast<uint16_t>(916312077 - *cum_ack_tsn),
+ static_cast<uint16_t>(916312081 - *cum_ack_tsn)),
+ SackChunk::GapAckBlock(
+ static_cast<uint16_t>(916312083 - *cum_ack_tsn),
+ static_cast<uint16_t>(916312083 - *cum_ack_tsn))));
+ EXPECT_THAT(chunk.duplicate_tsns(), ElementsAre(TSN(916312081)));
+}
+
+TEST(SackChunkTest, SerializeAndDeserialize) {
+ SackChunk chunk(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(2, 3)},
+ {TSN(1), TSN(2), TSN(3)});
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SackChunk deserialized,
+ SackChunk::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.cumulative_tsn_ack(), 123u);
+ EXPECT_EQ(deserialized.a_rwnd(), 456u);
+ EXPECT_THAT(deserialized.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(2, 3)));
+ EXPECT_THAT(deserialized.duplicate_tsns(),
+ ElementsAre(TSN(1), TSN(2), TSN(3)));
+
+ EXPECT_EQ(deserialized.ToString(),
+ "SACK, cum_ack_tsn=123, a_rwnd=456, gap=125--126, dup_tsns=1,2,3");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.cc
new file mode 100644
index 0000000000..d42aceead4
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.h
new file mode 100644
index 0000000000..29c1a98be6
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk_test.cc
new file mode 100644
index 0000000000..ef04ea9892
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_ack_chunk_test.cc
@@ -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/chunk/shutdown_ack_chunk.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(ShutdownAckChunkTest, FromCapture) {
+ /*
+ SHUTDOWN_ACK chunk
+ Chunk type: SHUTDOWN_ACK (8)
+ Chunk flags: 0x00
+ Chunk length: 4
+ */
+
+ uint8_t data[] = {0x08, 0x00, 0x00, 0x04};
+
+ EXPECT_TRUE(ShutdownAckChunk::Parse(data).has_value());
+}
+
+TEST(ShutdownAckChunkTest, SerializeAndDeserialize) {
+ ShutdownAckChunk chunk;
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ EXPECT_TRUE(ShutdownAckChunk::Parse(serialized).has_value());
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.cc
new file mode 100644
index 0000000000..59f806f7f7
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.h
new file mode 100644
index 0000000000..8148cca286
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk_test.cc
new file mode 100644
index 0000000000..16d147ca83
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_chunk_test.cc
@@ -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.
+ */
+#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+
+namespace dcsctp {
+namespace {
+TEST(ShutdownChunkTest, FromCapture) {
+ /*
+ SHUTDOWN chunk (Cumulative TSN ack: 101831101)
+ Chunk type: SHUTDOWN (7)
+ Chunk flags: 0x00
+ Chunk length: 8
+ Cumulative TSN Ack: 101831101
+ */
+
+ uint8_t data[] = {0x07, 0x00, 0x00, 0x08, 0x06, 0x11, 0xd1, 0xbd};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ShutdownChunk chunk, ShutdownChunk::Parse(data));
+ EXPECT_EQ(chunk.cumulative_tsn_ack(), TSN(101831101u));
+}
+
+TEST(ShutdownChunkTest, SerializeAndDeserialize) {
+ ShutdownChunk chunk(TSN(12345678));
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ShutdownChunk deserialized,
+ ShutdownChunk::Parse(serialized));
+
+ EXPECT_EQ(deserialized.cumulative_tsn_ack(), TSN(12345678u));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.cc
new file mode 100644
index 0000000000..3f54857437
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.cc
@@ -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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.h b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.h
new file mode 100644
index 0000000000..46d28e88dc
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk.h
@@ -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_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk_test.cc
new file mode 100644
index 0000000000..253900d5cd
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk/shutdown_complete_chunk_test.cc
@@ -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/chunk/shutdown_complete_chunk.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(ShutdownCompleteChunkTest, FromCapture) {
+ /*
+ SHUTDOWN_COMPLETE chunk
+ Chunk type: SHUTDOWN_COMPLETE (14)
+ Chunk flags: 0x00
+ Chunk length: 4
+ */
+
+ uint8_t data[] = {0x0e, 0x00, 0x00, 0x04};
+
+ EXPECT_TRUE(ShutdownCompleteChunk::Parse(data).has_value());
+}
+
+TEST(ShutdownCompleteChunkTest, SerializeAndDeserialize) {
+ ShutdownCompleteChunk chunk(/*tag_reflected=*/false);
+
+ std::vector<uint8_t> serialized;
+ chunk.SerializeTo(serialized);
+
+ EXPECT_TRUE(ShutdownCompleteChunk::Parse(serialized).has_value());
+}
+
+} // namespace
+} // namespace dcsctp