summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/net/dcsctp/packet
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/net/dcsctp/packet')
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/BUILD.gn331
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader.h99
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader_test.cc43
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer.h103
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer_test.cc48
-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
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk_validators.cc87
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk_validators.h33
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/chunk_validators_test.cc161
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/crc32c.cc29
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/crc32c.h24
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/crc32c_test.cc58
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/data.h103
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.cc45
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h50
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause_test.cc35
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.cc83
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.h38
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.cc45
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h48
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause_test.cc35
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.cc60
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h56
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause_test.cc36
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.cc90
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h60
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause_test.cc59
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.cc57
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.h53
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause_test.cc36
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.cc44
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.h48
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause_test.cc34
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.cc65
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.h56
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause_test.cc61
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.cc58
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h59
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause_test.cc41
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.cc57
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.h54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause_test.cc35
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.cc64
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h59
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause_test.cc37
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.cc54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h60
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause_test.cc39
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.cc53
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.h60
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause_test.cc39
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.cc67
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.h56
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause_test.cc62
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.cc68
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h63
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter_test.cc38
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.cc67
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h63
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter_test.cc38
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.cc45
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h49
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter_test.cc34
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.cc60
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.h54
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.cc89
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h66
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter_test.cc42
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.cc101
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h78
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter_test.cc47
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.cc96
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.h96
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/parameter_test.cc53
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.cc152
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.h92
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter_test.cc68
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.cc60
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h59
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter_test.cc37
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.cc51
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.h55
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter_test.cc40
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.cc65
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.h62
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter_test.cc42
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc184
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/sctp_packet.h121
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc342
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/tlv_trait.cc46
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/tlv_trait.h165
-rw-r--r--third_party/libwebrtc/net/dcsctp/packet/tlv_trait_test.cc133
146 files changed, 10261 insertions, 0 deletions
diff --git a/third_party/libwebrtc/net/dcsctp/packet/BUILD.gn b/third_party/libwebrtc/net/dcsctp/packet/BUILD.gn
new file mode 100644
index 0000000000..08bdb0f5a5
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/BUILD.gn
@@ -0,0 +1,331 @@
+# 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.
+
+import("../../../webrtc.gni")
+
+group("packet") {
+ deps = [ ":bounded_io" ]
+}
+
+rtc_source_set("bounded_io") {
+ deps = [
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ ]
+ sources = [
+ "bounded_byte_reader.h",
+ "bounded_byte_writer.h",
+ ]
+}
+
+rtc_library("tlv_trait") {
+ deps = [
+ ":bounded_io",
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings:strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+ sources = [
+ "tlv_trait.cc",
+ "tlv_trait.h",
+ ]
+}
+
+rtc_source_set("data") {
+ deps = [
+ "../../../rtc_base:checks",
+ "../common:internal_types",
+ "../public:types",
+ ]
+ sources = [ "data.h" ]
+}
+
+rtc_library("crc32c") {
+ deps = [
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "//third_party/crc32c",
+ ]
+ sources = [
+ "crc32c.cc",
+ "crc32c.h",
+ ]
+}
+
+rtc_library("parameter") {
+ deps = [
+ ":bounded_io",
+ ":data",
+ ":tlv_trait",
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ "../../../rtc_base:stringutils",
+ "../common:internal_types",
+ "../common:math",
+ "../common:str_join",
+ "../public:types",
+ ]
+ sources = [
+ "parameter/add_incoming_streams_request_parameter.cc",
+ "parameter/add_incoming_streams_request_parameter.h",
+ "parameter/add_outgoing_streams_request_parameter.cc",
+ "parameter/add_outgoing_streams_request_parameter.h",
+ "parameter/forward_tsn_supported_parameter.cc",
+ "parameter/forward_tsn_supported_parameter.h",
+ "parameter/heartbeat_info_parameter.cc",
+ "parameter/heartbeat_info_parameter.h",
+ "parameter/incoming_ssn_reset_request_parameter.cc",
+ "parameter/incoming_ssn_reset_request_parameter.h",
+ "parameter/outgoing_ssn_reset_request_parameter.cc",
+ "parameter/outgoing_ssn_reset_request_parameter.h",
+ "parameter/parameter.cc",
+ "parameter/parameter.h",
+ "parameter/reconfiguration_response_parameter.cc",
+ "parameter/reconfiguration_response_parameter.h",
+ "parameter/ssn_tsn_reset_request_parameter.cc",
+ "parameter/ssn_tsn_reset_request_parameter.h",
+ "parameter/state_cookie_parameter.cc",
+ "parameter/state_cookie_parameter.h",
+ "parameter/supported_extensions_parameter.cc",
+ "parameter/supported_extensions_parameter.h",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("error_cause") {
+ deps = [
+ ":data",
+ ":parameter",
+ ":tlv_trait",
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ "../../../rtc_base:stringutils",
+ "../common:internal_types",
+ "../common:math",
+ "../common:str_join",
+ "../packet:bounded_io",
+ "../public:types",
+ ]
+ sources = [
+ "error_cause/cookie_received_while_shutting_down_cause.cc",
+ "error_cause/cookie_received_while_shutting_down_cause.h",
+ "error_cause/error_cause.cc",
+ "error_cause/error_cause.h",
+ "error_cause/invalid_mandatory_parameter_cause.cc",
+ "error_cause/invalid_mandatory_parameter_cause.h",
+ "error_cause/invalid_stream_identifier_cause.cc",
+ "error_cause/invalid_stream_identifier_cause.h",
+ "error_cause/missing_mandatory_parameter_cause.cc",
+ "error_cause/missing_mandatory_parameter_cause.h",
+ "error_cause/no_user_data_cause.cc",
+ "error_cause/no_user_data_cause.h",
+ "error_cause/out_of_resource_error_cause.cc",
+ "error_cause/out_of_resource_error_cause.h",
+ "error_cause/protocol_violation_cause.cc",
+ "error_cause/protocol_violation_cause.h",
+ "error_cause/restart_of_an_association_with_new_address_cause.cc",
+ "error_cause/restart_of_an_association_with_new_address_cause.h",
+ "error_cause/stale_cookie_error_cause.cc",
+ "error_cause/stale_cookie_error_cause.h",
+ "error_cause/unrecognized_chunk_type_cause.cc",
+ "error_cause/unrecognized_chunk_type_cause.h",
+ "error_cause/unrecognized_parameter_cause.cc",
+ "error_cause/unrecognized_parameter_cause.h",
+ "error_cause/unresolvable_address_cause.cc",
+ "error_cause/unresolvable_address_cause.h",
+ "error_cause/user_initiated_abort_cause.cc",
+ "error_cause/user_initiated_abort_cause.h",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("chunk") {
+ deps = [
+ ":data",
+ ":error_cause",
+ ":parameter",
+ ":tlv_trait",
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ "../../../rtc_base:stringutils",
+ "../common:math",
+ "../common:str_join",
+ "../packet:bounded_io",
+ ]
+ sources = [
+ "chunk/abort_chunk.cc",
+ "chunk/abort_chunk.h",
+ "chunk/chunk.cc",
+ "chunk/chunk.h",
+ "chunk/cookie_ack_chunk.cc",
+ "chunk/cookie_ack_chunk.h",
+ "chunk/cookie_echo_chunk.cc",
+ "chunk/cookie_echo_chunk.h",
+ "chunk/data_chunk.cc",
+ "chunk/data_chunk.h",
+ "chunk/data_common.h",
+ "chunk/error_chunk.cc",
+ "chunk/error_chunk.h",
+ "chunk/forward_tsn_chunk.cc",
+ "chunk/forward_tsn_chunk.h",
+ "chunk/forward_tsn_common.h",
+ "chunk/heartbeat_ack_chunk.cc",
+ "chunk/heartbeat_ack_chunk.h",
+ "chunk/heartbeat_request_chunk.cc",
+ "chunk/heartbeat_request_chunk.h",
+ "chunk/idata_chunk.cc",
+ "chunk/idata_chunk.h",
+ "chunk/iforward_tsn_chunk.cc",
+ "chunk/iforward_tsn_chunk.h",
+ "chunk/init_ack_chunk.cc",
+ "chunk/init_ack_chunk.h",
+ "chunk/init_chunk.cc",
+ "chunk/init_chunk.h",
+ "chunk/reconfig_chunk.cc",
+ "chunk/reconfig_chunk.h",
+ "chunk/sack_chunk.cc",
+ "chunk/sack_chunk.h",
+ "chunk/shutdown_ack_chunk.cc",
+ "chunk/shutdown_ack_chunk.h",
+ "chunk/shutdown_chunk.cc",
+ "chunk/shutdown_chunk.h",
+ "chunk/shutdown_complete_chunk.cc",
+ "chunk/shutdown_complete_chunk.h",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("chunk_validators") {
+ deps = [
+ ":chunk",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ ]
+ sources = [
+ "chunk_validators.cc",
+ "chunk_validators.h",
+ ]
+}
+
+rtc_library("sctp_packet") {
+ deps = [
+ ":bounded_io",
+ ":chunk",
+ ":crc32c",
+ "../../../api:array_view",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:logging",
+ "../../../rtc_base:stringutils",
+ "../common:internal_types",
+ "../common:math",
+ "../public:types",
+ ]
+ sources = [
+ "sctp_packet.cc",
+ "sctp_packet.h",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory:memory",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+if (rtc_include_tests) {
+ rtc_library("dcsctp_packet_unittests") {
+ testonly = true
+
+ deps = [
+ ":bounded_io",
+ ":chunk",
+ ":chunk_validators",
+ ":crc32c",
+ ":error_cause",
+ ":parameter",
+ ":sctp_packet",
+ ":tlv_trait",
+ "../../../api:array_view",
+ "../../../rtc_base:buffer",
+ "../../../rtc_base:checks",
+ "../../../rtc_base:gunit_helpers",
+ "../../../test:test_support",
+ "../common:internal_types",
+ "../common:math",
+ "../public:types",
+ "../testing:testing_macros",
+ ]
+ sources = [
+ "bounded_byte_reader_test.cc",
+ "bounded_byte_writer_test.cc",
+ "chunk/abort_chunk_test.cc",
+ "chunk/cookie_ack_chunk_test.cc",
+ "chunk/cookie_echo_chunk_test.cc",
+ "chunk/data_chunk_test.cc",
+ "chunk/error_chunk_test.cc",
+ "chunk/forward_tsn_chunk_test.cc",
+ "chunk/heartbeat_ack_chunk_test.cc",
+ "chunk/heartbeat_request_chunk_test.cc",
+ "chunk/idata_chunk_test.cc",
+ "chunk/iforward_tsn_chunk_test.cc",
+ "chunk/init_ack_chunk_test.cc",
+ "chunk/init_chunk_test.cc",
+ "chunk/reconfig_chunk_test.cc",
+ "chunk/sack_chunk_test.cc",
+ "chunk/shutdown_ack_chunk_test.cc",
+ "chunk/shutdown_chunk_test.cc",
+ "chunk/shutdown_complete_chunk_test.cc",
+ "chunk_validators_test.cc",
+ "crc32c_test.cc",
+ "error_cause/cookie_received_while_shutting_down_cause_test.cc",
+ "error_cause/invalid_mandatory_parameter_cause_test.cc",
+ "error_cause/invalid_stream_identifier_cause_test.cc",
+ "error_cause/missing_mandatory_parameter_cause_test.cc",
+ "error_cause/no_user_data_cause_test.cc",
+ "error_cause/out_of_resource_error_cause_test.cc",
+ "error_cause/protocol_violation_cause_test.cc",
+ "error_cause/restart_of_an_association_with_new_address_cause_test.cc",
+ "error_cause/stale_cookie_error_cause_test.cc",
+ "error_cause/unrecognized_chunk_type_cause_test.cc",
+ "error_cause/unrecognized_parameter_cause_test.cc",
+ "error_cause/unresolvable_address_cause_test.cc",
+ "error_cause/user_initiated_abort_cause_test.cc",
+ "parameter/add_incoming_streams_request_parameter_test.cc",
+ "parameter/add_outgoing_streams_request_parameter_test.cc",
+ "parameter/forward_tsn_supported_parameter_test.cc",
+ "parameter/incoming_ssn_reset_request_parameter_test.cc",
+ "parameter/outgoing_ssn_reset_request_parameter_test.cc",
+ "parameter/parameter_test.cc",
+ "parameter/reconfiguration_response_parameter_test.cc",
+ "parameter/ssn_tsn_reset_request_parameter_test.cc",
+ "parameter/state_cookie_parameter_test.cc",
+ "parameter/supported_extensions_parameter_test.cc",
+ "sctp_packet_test.cc",
+ "tlv_trait_test.cc",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+ }
+}
diff --git a/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader.h b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader.h
new file mode 100644
index 0000000000..603ed6ac33
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
+#define NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
+
+#include <cstdint>
+
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// TODO(boivie): These generic functions - and possibly this entire class -
+// could be a candidate to have added to rtc_base/. They should use compiler
+// intrinsics as well.
+namespace internal {
+// Loads a 8-bit unsigned word at `data`.
+inline uint8_t LoadBigEndian8(const uint8_t* data) {
+ return data[0];
+}
+
+// Loads a 16-bit unsigned word at `data`.
+inline uint16_t LoadBigEndian16(const uint8_t* data) {
+ return (data[0] << 8) | data[1];
+}
+
+// Loads a 32-bit unsigned word at `data`.
+inline uint32_t LoadBigEndian32(const uint8_t* data) {
+ return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+}
+} // namespace internal
+
+// BoundedByteReader wraps an ArrayView and divides it into two parts; A fixed
+// size - which is the template parameter - and a variable size, which is what
+// remains in `data` after the `FixedSize`.
+//
+// The BoundedByteReader provides methods to load/read big endian numbers from
+// the FixedSize portion of the buffer, and these are read with static bounds
+// checking, to avoid out-of-bounds accesses without a run-time penalty.
+//
+// The variable sized portion can either be used to create sub-readers, which
+// themselves would provide compile-time bounds-checking, or the entire variable
+// sized portion can be retrieved as an ArrayView.
+template <int FixedSize>
+class BoundedByteReader {
+ public:
+ explicit BoundedByteReader(rtc::ArrayView<const uint8_t> data) : data_(data) {
+ RTC_CHECK(data.size() >= FixedSize);
+ }
+
+ template <size_t offset>
+ uint8_t Load8() const {
+ static_assert(offset + sizeof(uint8_t) <= FixedSize, "Out-of-bounds");
+ return internal::LoadBigEndian8(&data_[offset]);
+ }
+
+ template <size_t offset>
+ uint16_t Load16() const {
+ static_assert(offset + sizeof(uint16_t) <= FixedSize, "Out-of-bounds");
+ static_assert((offset % sizeof(uint16_t)) == 0, "Unaligned access");
+ return internal::LoadBigEndian16(&data_[offset]);
+ }
+
+ template <size_t offset>
+ uint32_t Load32() const {
+ static_assert(offset + sizeof(uint32_t) <= FixedSize, "Out-of-bounds");
+ static_assert((offset % sizeof(uint32_t)) == 0, "Unaligned access");
+ return internal::LoadBigEndian32(&data_[offset]);
+ }
+
+ template <size_t SubSize>
+ BoundedByteReader<SubSize> sub_reader(size_t variable_offset) const {
+ RTC_CHECK(FixedSize + variable_offset + SubSize <= data_.size());
+
+ rtc::ArrayView<const uint8_t> sub_span =
+ data_.subview(FixedSize + variable_offset, SubSize);
+ return BoundedByteReader<SubSize>(sub_span);
+ }
+
+ size_t variable_data_size() const { return data_.size() - FixedSize; }
+
+ rtc::ArrayView<const uint8_t> variable_data() const {
+ return data_.subview(FixedSize, data_.size() - FixedSize);
+ }
+
+ private:
+ const rtc::ArrayView<const uint8_t> data_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_BOUNDED_BYTE_READER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader_test.cc b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader_test.cc
new file mode 100644
index 0000000000..2fb4a86785
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_reader_test.cc
@@ -0,0 +1,43 @@
+/*
+ * 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/bounded_byte_reader.h"
+
+#include "api/array_view.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(BoundedByteReaderTest, CanLoadData) {
+ uint8_t data[14] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4};
+
+ BoundedByteReader<8> reader(data);
+ EXPECT_EQ(reader.variable_data_size(), 6U);
+ EXPECT_EQ(reader.Load32<0>(), 0x01020304U);
+ EXPECT_EQ(reader.Load32<4>(), 0x05060708U);
+ EXPECT_EQ(reader.Load16<4>(), 0x0506U);
+ EXPECT_EQ(reader.Load8<4>(), 0x05U);
+ EXPECT_EQ(reader.Load8<5>(), 0x06U);
+
+ BoundedByteReader<6> sub = reader.sub_reader<6>(0);
+ EXPECT_EQ(sub.Load16<0>(), 0x0900U);
+ EXPECT_EQ(sub.Load32<0>(), 0x09000102U);
+ EXPECT_EQ(sub.Load16<4>(), 0x0304U);
+
+ EXPECT_THAT(reader.variable_data(), ElementsAre(9, 0, 1, 2, 3, 4));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer.h b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer.h
new file mode 100644
index 0000000000..d754549e4f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef NET_DCSCTP_PACKET_BOUNDED_BYTE_WRITER_H_
+#define NET_DCSCTP_PACKET_BOUNDED_BYTE_WRITER_H_
+
+#include <algorithm>
+
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// TODO(boivie): These generic functions - and possibly this entire class -
+// could be a candidate to have added to rtc_base/. They should use compiler
+// intrinsics as well.
+namespace internal {
+// Stores a 8-bit unsigned word at `data`.
+inline void StoreBigEndian8(uint8_t* data, uint8_t val) {
+ data[0] = val;
+}
+
+// Stores a 16-bit unsigned word at `data`.
+inline void StoreBigEndian16(uint8_t* data, uint16_t val) {
+ data[0] = val >> 8;
+ data[1] = val;
+}
+
+// Stores a 32-bit unsigned word at `data`.
+inline void StoreBigEndian32(uint8_t* data, uint32_t val) {
+ data[0] = val >> 24;
+ data[1] = val >> 16;
+ data[2] = val >> 8;
+ data[3] = val;
+}
+} // namespace internal
+
+// BoundedByteWriter wraps an ArrayView and divides it into two parts; A fixed
+// size - which is the template parameter - and a variable size, which is what
+// remains in `data` after the `FixedSize`.
+//
+// The BoundedByteWriter provides methods to write big endian numbers to the
+// FixedSize portion of the buffer, and these are written with static bounds
+// checking, to avoid out-of-bounds accesses without a run-time penalty.
+//
+// The variable sized portion can either be used to create sub-writers, which
+// themselves would provide compile-time bounds-checking, or data can be copied
+// to it.
+template <int FixedSize>
+class BoundedByteWriter {
+ public:
+ explicit BoundedByteWriter(rtc::ArrayView<uint8_t> data) : data_(data) {
+ RTC_CHECK(data.size() >= FixedSize);
+ }
+
+ template <size_t offset>
+ void Store8(uint8_t value) {
+ static_assert(offset + sizeof(uint8_t) <= FixedSize, "Out-of-bounds");
+ internal::StoreBigEndian8(&data_[offset], value);
+ }
+
+ template <size_t offset>
+ void Store16(uint16_t value) {
+ static_assert(offset + sizeof(uint16_t) <= FixedSize, "Out-of-bounds");
+ static_assert((offset % sizeof(uint16_t)) == 0, "Unaligned access");
+ internal::StoreBigEndian16(&data_[offset], value);
+ }
+
+ template <size_t offset>
+ void Store32(uint32_t value) {
+ static_assert(offset + sizeof(uint32_t) <= FixedSize, "Out-of-bounds");
+ static_assert((offset % sizeof(uint32_t)) == 0, "Unaligned access");
+ internal::StoreBigEndian32(&data_[offset], value);
+ }
+
+ template <size_t SubSize>
+ BoundedByteWriter<SubSize> sub_writer(size_t variable_offset) {
+ RTC_CHECK(FixedSize + variable_offset + SubSize <= data_.size());
+
+ return BoundedByteWriter<SubSize>(
+ data_.subview(FixedSize + variable_offset, SubSize));
+ }
+
+ void CopyToVariableData(rtc::ArrayView<const uint8_t> source) {
+ size_t copy_size = std::min(source.size(), data_.size() - FixedSize);
+ if (source.data() == nullptr || copy_size == 0) {
+ return;
+ }
+ memcpy(data_.data() + FixedSize, source.data(), copy_size);
+ }
+
+ private:
+ rtc::ArrayView<uint8_t> data_;
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_BOUNDED_BYTE_WRITER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer_test.cc b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer_test.cc
new file mode 100644
index 0000000000..3cea0a2f7c
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/bounded_byte_writer_test.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+
+#include <vector>
+
+#include "api/array_view.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(BoundedByteWriterTest, CanWriteData) {
+ std::vector<uint8_t> data(14);
+
+ BoundedByteWriter<8> writer(data);
+ writer.Store32<0>(0x01020304);
+ writer.Store16<4>(0x0506);
+ writer.Store8<6>(0x07);
+ writer.Store8<7>(0x08);
+
+ uint8_t variable_data[] = {0, 0, 0, 0, 3, 0};
+ writer.CopyToVariableData(variable_data);
+
+ BoundedByteWriter<6> sub = writer.sub_writer<6>(0);
+ sub.Store32<0>(0x09000000);
+ sub.Store16<2>(0x0102);
+
+ BoundedByteWriter<2> sub2 = writer.sub_writer<2>(4);
+ sub2.Store8<1>(0x04);
+
+ EXPECT_THAT(data, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4));
+}
+
+} // namespace
+} // namespace dcsctp
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
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk_validators.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk_validators.cc
new file mode 100644
index 0000000000..48d351827e
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk_validators.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/chunk_validators.h"
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "net/dcsctp/packet/chunk/sack_chunk.h"
+#include "rtc_base/logging.h"
+
+namespace dcsctp {
+
+SackChunk ChunkValidators::Clean(SackChunk&& sack) {
+ if (Validate(sack)) {
+ return std::move(sack);
+ }
+
+ RTC_DLOG(LS_WARNING) << "Received SACK is malformed; cleaning it";
+
+ std::vector<SackChunk::GapAckBlock> gap_ack_blocks;
+ gap_ack_blocks.reserve(sack.gap_ack_blocks().size());
+
+ // First: Only keep blocks that are sane
+ for (const SackChunk::GapAckBlock& gap_ack_block : sack.gap_ack_blocks()) {
+ if (gap_ack_block.end > gap_ack_block.start) {
+ gap_ack_blocks.emplace_back(gap_ack_block);
+ }
+ }
+
+ // Not more than at most one remaining? Exit early.
+ if (gap_ack_blocks.size() <= 1) {
+ return SackChunk(sack.cumulative_tsn_ack(), sack.a_rwnd(),
+ std::move(gap_ack_blocks), sack.duplicate_tsns());
+ }
+
+ // Sort the intervals by their start value, to aid in the merging below.
+ absl::c_sort(gap_ack_blocks, [&](const SackChunk::GapAckBlock& a,
+ const SackChunk::GapAckBlock& b) {
+ return a.start < b.start;
+ });
+
+ // Merge overlapping ranges.
+ std::vector<SackChunk::GapAckBlock> merged;
+ merged.reserve(gap_ack_blocks.size());
+ merged.push_back(gap_ack_blocks[0]);
+
+ for (size_t i = 1; i < gap_ack_blocks.size(); ++i) {
+ if (merged.back().end + 1 >= gap_ack_blocks[i].start) {
+ merged.back().end = std::max(merged.back().end, gap_ack_blocks[i].end);
+ } else {
+ merged.push_back(gap_ack_blocks[i]);
+ }
+ }
+
+ return SackChunk(sack.cumulative_tsn_ack(), sack.a_rwnd(), std::move(merged),
+ sack.duplicate_tsns());
+}
+
+bool ChunkValidators::Validate(const SackChunk& sack) {
+ if (sack.gap_ack_blocks().empty()) {
+ return true;
+ }
+
+ // Ensure that gap-ack-blocks are sorted, has an "end" that is not before
+ // "start" and are non-overlapping and non-adjacent.
+ uint16_t prev_end = 0;
+ for (const SackChunk::GapAckBlock& gap_ack_block : sack.gap_ack_blocks()) {
+ if (gap_ack_block.end < gap_ack_block.start) {
+ return false;
+ }
+ if (gap_ack_block.start <= (prev_end + 1)) {
+ return false;
+ }
+ prev_end = gap_ack_block.end;
+ }
+ return true;
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk_validators.h b/third_party/libwebrtc/net/dcsctp/packet/chunk_validators.h
new file mode 100644
index 0000000000..b11848a162
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk_validators.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_CHUNK_VALIDATORS_H_
+#define NET_DCSCTP_PACKET_CHUNK_VALIDATORS_H_
+
+#include "net/dcsctp/packet/chunk/sack_chunk.h"
+
+namespace dcsctp {
+// Validates and cleans SCTP chunks.
+class ChunkValidators {
+ public:
+ // Given a SackChunk, will return `true` if it's valid, and `false` if not.
+ static bool Validate(const SackChunk& sack);
+
+ // Given a SackChunk, it will return a cleaned and validated variant of it.
+ // RFC4960 doesn't say anything about validity of SACKs or if the Gap ACK
+ // blocks must be sorted, and non-overlapping. While they always are in
+ // well-behaving implementations, this can't be relied on.
+ //
+ // This method internally calls `Validate`, which means that you can always
+ // pass a SackChunk to this method (valid or not), and use the results.
+ static SackChunk Clean(SackChunk&& sack);
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_CHUNK_VALIDATORS_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/chunk_validators_test.cc b/third_party/libwebrtc/net/dcsctp/packet/chunk_validators_test.cc
new file mode 100644
index 0000000000..d59fd4ec48
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/chunk_validators_test.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/chunk_validators.h"
+
+#include <utility>
+
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+
+TEST(ChunkValidatorsTest, NoGapAckBlocksAreValid) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ /*gap_ack_blocks=*/{}, {});
+
+ EXPECT_TRUE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+ EXPECT_THAT(clean.gap_ack_blocks(), IsEmpty());
+}
+
+TEST(ChunkValidatorsTest, OneValidAckBlock) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(2, 3)}, {});
+
+ EXPECT_TRUE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(2, 3)));
+}
+
+TEST(ChunkValidatorsTest, TwoValidAckBlocks) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(5, 6)},
+ {});
+
+ EXPECT_TRUE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+ EXPECT_THAT(
+ clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(5, 6)));
+}
+
+TEST(ChunkValidatorsTest, OneInvalidAckBlock) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456, {SackChunk::GapAckBlock(1, 2)}, {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ // It's not strictly valid, but due to the renegable nature of gap ack blocks,
+ // the cum_ack_tsn can't simply be moved.
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(1, 2)));
+}
+
+TEST(ChunkValidatorsTest, RemovesInvalidGapAckBlockFromSack) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(2, 3), SackChunk::GapAckBlock(6, 4)},
+ {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(2, 3)));
+}
+
+TEST(ChunkValidatorsTest, SortsGapAckBlocksInOrder) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(6, 7), SackChunk::GapAckBlock(3, 4)},
+ {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_THAT(
+ clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(6, 7)));
+}
+
+TEST(ChunkValidatorsTest, MergesAdjacentBlocks) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(5, 6)},
+ {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(3, 6)));
+}
+
+TEST(ChunkValidatorsTest, MergesOverlappingByOne) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(3, 4), SackChunk::GapAckBlock(4, 5)},
+ {});
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(3, 5)));
+}
+
+TEST(ChunkValidatorsTest, MergesOverlappingByMore) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(3, 10), SackChunk::GapAckBlock(4, 5)},
+ {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(3, 10)));
+}
+
+TEST(ChunkValidatorsTest, MergesBlocksStartingWithSameStartOffset) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(3, 7), SackChunk::GapAckBlock(3, 5),
+ SackChunk::GapAckBlock(3, 9)},
+ {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(3, 9)));
+}
+
+TEST(ChunkValidatorsTest, MergesBlocksPartiallyOverlapping) {
+ SackChunk sack(TSN(123), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(3, 7), SackChunk::GapAckBlock(5, 9)},
+ {});
+
+ EXPECT_FALSE(ChunkValidators::Validate(sack));
+
+ SackChunk clean = ChunkValidators::Clean(std::move(sack));
+
+ EXPECT_THAT(clean.gap_ack_blocks(),
+ ElementsAre(SackChunk::GapAckBlock(3, 9)));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/crc32c.cc b/third_party/libwebrtc/net/dcsctp/packet/crc32c.cc
new file mode 100644
index 0000000000..e3f0dc1d19
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/crc32c.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/crc32c.h"
+
+#include <cstdint>
+
+#include "third_party/crc32c/src/include/crc32c/crc32c.h"
+
+namespace dcsctp {
+
+uint32_t GenerateCrc32C(rtc::ArrayView<const uint8_t> data) {
+ uint32_t crc32c = crc32c_value(data.data(), data.size());
+
+ // Byte swapping for little endian byte order:
+ uint8_t byte0 = crc32c;
+ uint8_t byte1 = crc32c >> 8;
+ uint8_t byte2 = crc32c >> 16;
+ uint8_t byte3 = crc32c >> 24;
+ crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
+ return crc32c;
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/crc32c.h b/third_party/libwebrtc/net/dcsctp/packet/crc32c.h
new file mode 100644
index 0000000000..a969e1b26b
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/crc32c.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_CRC32C_H_
+#define NET_DCSCTP_PACKET_CRC32C_H_
+
+#include <cstdint>
+
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// Generates the CRC32C checksum of `data`.
+uint32_t GenerateCrc32C(rtc::ArrayView<const uint8_t> data);
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_CRC32C_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/crc32c_test.cc b/third_party/libwebrtc/net/dcsctp/packet/crc32c_test.cc
new file mode 100644
index 0000000000..0821c4ef75
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/crc32c_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/crc32c.h"
+
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+constexpr std::array<const uint8_t, 0> kEmpty = {};
+constexpr std::array<const uint8_t, 1> kZero = {0};
+constexpr std::array<const uint8_t, 4> kManyZeros = {0, 0, 0, 0};
+constexpr std::array<const uint8_t, 4> kShort = {1, 2, 3, 4};
+constexpr std::array<const uint8_t, 8> kLong = {1, 2, 3, 4, 5, 6, 7, 8};
+// https://tools.ietf.org/html/rfc3720#appendix-B.4
+constexpr std::array<const uint8_t, 32> k32Zeros = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+constexpr std::array<const uint8_t, 32> k32Ones = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+constexpr std::array<const uint8_t, 32> k32Incrementing = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
+constexpr std::array<const uint8_t, 32> k32Decrementing = {
+ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+constexpr std::array<const uint8_t, 48> kISCSICommandPDU = {
+ 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+TEST(Crc32Test, TestVectors) {
+ EXPECT_EQ(GenerateCrc32C(kEmpty), 0U);
+ EXPECT_EQ(GenerateCrc32C(kZero), 0x51537d52U);
+ EXPECT_EQ(GenerateCrc32C(kManyZeros), 0xc74b6748U);
+ EXPECT_EQ(GenerateCrc32C(kShort), 0xf48c3029U);
+ EXPECT_EQ(GenerateCrc32C(kLong), 0x811f8946U);
+ // https://tools.ietf.org/html/rfc3720#appendix-B.4
+ EXPECT_EQ(GenerateCrc32C(k32Zeros), 0xaa36918aU);
+ EXPECT_EQ(GenerateCrc32C(k32Ones), 0x43aba862U);
+ EXPECT_EQ(GenerateCrc32C(k32Incrementing), 0x4e79dd46U);
+ EXPECT_EQ(GenerateCrc32C(k32Decrementing), 0x5cdb3f11U);
+ EXPECT_EQ(GenerateCrc32C(kISCSICommandPDU), 0x563a96d9U);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/data.h b/third_party/libwebrtc/net/dcsctp/packet/data.h
new file mode 100644
index 0000000000..c1754ed59a
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/data.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_DATA_H_
+#define NET_DCSCTP_PACKET_DATA_H_
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/public/types.h"
+
+namespace dcsctp {
+
+// Represents data that is either received and extracted from a DATA/I-DATA
+// chunk, or data that is supposed to be sent, and wrapped in a DATA/I-DATA
+// chunk (depending on peer capabilities).
+//
+// The data wrapped in this structure is actually the same as the DATA/I-DATA
+// chunk (actually the union of them), but to avoid having all components be
+// aware of the implementation details of the different chunks, this abstraction
+// is used instead. A notable difference is also that it doesn't carry a
+// Transmission Sequence Number (TSN), as that is not known when a chunk is
+// created (assigned late, just when sending), and that the TSNs in DATA/I-DATA
+// are wrapped numbers, and within the library, unwrapped sequence numbers are
+// preferably used.
+struct Data {
+ // Indicates if a chunk is the first in a fragmented message and maps to the
+ // "beginning" flag in DATA/I-DATA chunk.
+ using IsBeginning = webrtc::StrongAlias<class IsBeginningTag, bool>;
+
+ // Indicates if a chunk is the last in a fragmented message and maps to the
+ // "end" flag in DATA/I-DATA chunk.
+ using IsEnd = webrtc::StrongAlias<class IsEndTag, bool>;
+
+ Data(StreamID stream_id,
+ SSN ssn,
+ MID message_id,
+ FSN fsn,
+ PPID ppid,
+ std::vector<uint8_t> payload,
+ IsBeginning is_beginning,
+ IsEnd is_end,
+ IsUnordered is_unordered)
+ : stream_id(stream_id),
+ ssn(ssn),
+ message_id(message_id),
+ fsn(fsn),
+ ppid(ppid),
+ payload(std::move(payload)),
+ is_beginning(is_beginning),
+ is_end(is_end),
+ is_unordered(is_unordered) {}
+
+ // Move-only, to avoid accidental copies.
+ Data(Data&& other) = default;
+ Data& operator=(Data&& other) = default;
+
+ // Creates a copy of this `Data` object.
+ Data Clone() const {
+ return Data(stream_id, ssn, message_id, fsn, ppid, payload, is_beginning,
+ is_end, is_unordered);
+ }
+
+ // The size of this data, which translates to the size of its payload.
+ size_t size() const { return payload.size(); }
+
+ // Stream Identifier.
+ StreamID stream_id;
+
+ // Stream Sequence Number (SSN), per stream, for ordered chunks. Defined by
+ // RFC4960 and used only in DATA chunks (not I-DATA).
+ SSN ssn;
+
+ // Message Identifier (MID) per stream and ordered/unordered. Defined by
+ // RFC8260, and used together with options.is_unordered and stream_id to
+ // uniquely identify a message. Used only in I-DATA chunks (not DATA).
+ MID message_id;
+ // Fragment Sequence Number (FSN) per stream and ordered/unordered, as above.
+ FSN fsn;
+
+ // Payload Protocol Identifier (PPID).
+ PPID ppid;
+
+ // The actual data payload.
+ std::vector<uint8_t> payload;
+
+ // If this data represents the first, last or a middle chunk.
+ IsBeginning is_beginning;
+ IsEnd is_end;
+ // If this data is sent/received unordered.
+ IsUnordered is_unordered;
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_DATA_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.cc
new file mode 100644
index 0000000000..ef67c2a49f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.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/error_cause/cookie_received_while_shutting_down_cause.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.10
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=10 | Cause Length=4 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int CookieReceivedWhileShuttingDownCause::kType;
+
+absl::optional<CookieReceivedWhileShuttingDownCause>
+CookieReceivedWhileShuttingDownCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ if (!ParseTLV(data).has_value()) {
+ return absl::nullopt;
+ }
+ return CookieReceivedWhileShuttingDownCause();
+}
+
+void CookieReceivedWhileShuttingDownCause::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ AllocateTLV(out);
+}
+
+std::string CookieReceivedWhileShuttingDownCause::ToString() const {
+ return "Cookie Received While Shutting Down";
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h
new file mode 100644
index 0000000000..362f181fba
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_COOKIE_RECEIVED_WHILE_SHUTTING_DOWN_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_COOKIE_RECEIVED_WHILE_SHUTTING_DOWN_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.10
+struct CookieReceivedWhileShuttingDownCauseConfig : public ParameterConfig {
+ static constexpr int kType = 10;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class CookieReceivedWhileShuttingDownCause
+ : public Parameter,
+ public TLVTrait<CookieReceivedWhileShuttingDownCauseConfig> {
+ public:
+ static constexpr int kType =
+ CookieReceivedWhileShuttingDownCauseConfig::kType;
+
+ CookieReceivedWhileShuttingDownCause() {}
+
+ static absl::optional<CookieReceivedWhileShuttingDownCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_COOKIE_RECEIVED_WHILE_SHUTTING_DOWN_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause_test.cc
new file mode 100644
index 0000000000..afb8364c32
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause_test.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(CookieReceivedWhileShuttingDownCauseTest, SerializeAndDeserialize) {
+ CookieReceivedWhileShuttingDownCause parameter;
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ CookieReceivedWhileShuttingDownCause deserialized,
+ CookieReceivedWhileShuttingDownCause::Parse(serialized));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.cc
new file mode 100644
index 0000000000..dcd07472ed
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.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/error_cause/error_cause.h"
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/math.h"
+#include "net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h"
+#include "net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h"
+#include "net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h"
+#include "net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h"
+#include "net/dcsctp/packet/error_cause/no_user_data_cause.h"
+#include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
+#include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
+#include "net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h"
+#include "net/dcsctp/packet/error_cause/stale_cookie_error_cause.h"
+#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
+#include "net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h"
+#include "net/dcsctp/packet/error_cause/unresolvable_address_cause.h"
+#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+template <class ErrorCause>
+bool ParseAndPrint(ParameterDescriptor descriptor, rtc::StringBuilder& sb) {
+ if (descriptor.type == ErrorCause::kType) {
+ absl::optional<ErrorCause> p = ErrorCause::Parse(descriptor.data);
+ if (p.has_value()) {
+ sb << p->ToString();
+ } else {
+ sb << "Failed to parse error cause of type " << ErrorCause::kType;
+ }
+ return true;
+ }
+ return false;
+}
+
+std::string ErrorCausesToString(const Parameters& parameters) {
+ rtc::StringBuilder sb;
+
+ std::vector<ParameterDescriptor> descriptors = parameters.descriptors();
+ for (size_t i = 0; i < descriptors.size(); ++i) {
+ if (i > 0) {
+ sb << "\n";
+ }
+
+ const ParameterDescriptor& d = descriptors[i];
+ if (!ParseAndPrint<InvalidStreamIdentifierCause>(d, sb) &&
+ !ParseAndPrint<MissingMandatoryParameterCause>(d, sb) &&
+ !ParseAndPrint<StaleCookieErrorCause>(d, sb) &&
+ !ParseAndPrint<OutOfResourceErrorCause>(d, sb) &&
+ !ParseAndPrint<UnresolvableAddressCause>(d, sb) &&
+ !ParseAndPrint<UnrecognizedChunkTypeCause>(d, sb) &&
+ !ParseAndPrint<InvalidMandatoryParameterCause>(d, sb) &&
+ !ParseAndPrint<UnrecognizedParametersCause>(d, sb) &&
+ !ParseAndPrint<NoUserDataCause>(d, sb) &&
+ !ParseAndPrint<CookieReceivedWhileShuttingDownCause>(d, sb) &&
+ !ParseAndPrint<RestartOfAnAssociationWithNewAddressesCause>(d, sb) &&
+ !ParseAndPrint<UserInitiatedAbortCause>(d, sb) &&
+ !ParseAndPrint<ProtocolViolationCause>(d, sb)) {
+ sb << "Unhandled parameter of type: " << d.type;
+ }
+ }
+
+ return sb.Release();
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.h
new file mode 100644
index 0000000000..fa2bf81478
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/error_cause.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_ERROR_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_ERROR_CAUSE_H_
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <iosfwd>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "absl/algorithm/container.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// Converts the Error Causes in `parameters` to a human readable string,
+// to be used in error reporting and logging.
+std::string ErrorCausesToString(const Parameters& parameters);
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_ERROR_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.cc
new file mode 100644
index 0000000000..0187544226
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.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/error_cause/invalid_mandatory_parameter_cause.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.7
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=7 | Cause Length=4 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int InvalidMandatoryParameterCause::kType;
+
+absl::optional<InvalidMandatoryParameterCause>
+InvalidMandatoryParameterCause::Parse(rtc::ArrayView<const uint8_t> data) {
+ if (!ParseTLV(data).has_value()) {
+ return absl::nullopt;
+ }
+ return InvalidMandatoryParameterCause();
+}
+
+void InvalidMandatoryParameterCause::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ AllocateTLV(out);
+}
+
+std::string InvalidMandatoryParameterCause::ToString() const {
+ return "Invalid Mandatory Parameter";
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h
new file mode 100644
index 0000000000..e192b5a42f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_MANDATORY_PARAMETER_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_MANDATORY_PARAMETER_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.7
+struct InvalidMandatoryParameterCauseConfig : public ParameterConfig {
+ static constexpr int kType = 7;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class InvalidMandatoryParameterCause
+ : public Parameter,
+ public TLVTrait<InvalidMandatoryParameterCauseConfig> {
+ public:
+ static constexpr int kType = InvalidMandatoryParameterCauseConfig::kType;
+
+ InvalidMandatoryParameterCause() {}
+
+ static absl::optional<InvalidMandatoryParameterCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_MANDATORY_PARAMETER_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause_test.cc
new file mode 100644
index 0000000000..3d532d09b1
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause_test.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/invalid_mandatory_parameter_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(InvalidMandatoryParameterCauseTest, SerializeAndDeserialize) {
+ InvalidMandatoryParameterCause parameter;
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ InvalidMandatoryParameterCause deserialized,
+ InvalidMandatoryParameterCause::Parse(serialized));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.cc
new file mode 100644
index 0000000000..b2ddd6f4ef
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.1
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=1 | Cause Length=8 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Stream Identifier | (Reserved) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int InvalidStreamIdentifierCause::kType;
+
+absl::optional<InvalidStreamIdentifierCause>
+InvalidStreamIdentifierCause::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+
+ StreamID stream_id(reader->Load16<4>());
+ return InvalidStreamIdentifierCause(stream_id);
+}
+
+void InvalidStreamIdentifierCause::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+
+ writer.Store16<4>(*stream_id_);
+}
+
+std::string InvalidStreamIdentifierCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Invalid Stream Identifier, stream_id=" << *stream_id_;
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.h
new file mode 100644
index 0000000000..b7dfe177b8
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.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_ERROR_CAUSE_INVALID_STREAM_IDENTIFIER_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_STREAM_IDENTIFIER_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "net/dcsctp/public/types.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.1
+struct InvalidStreamIdentifierCauseConfig : public ParameterConfig {
+ static constexpr int kType = 1;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class InvalidStreamIdentifierCause
+ : public Parameter,
+ public TLVTrait<InvalidStreamIdentifierCauseConfig> {
+ public:
+ static constexpr int kType = InvalidStreamIdentifierCauseConfig::kType;
+
+ explicit InvalidStreamIdentifierCause(StreamID stream_id)
+ : stream_id_(stream_id) {}
+
+ static absl::optional<InvalidStreamIdentifierCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ StreamID stream_id() const { return stream_id_; }
+
+ private:
+ StreamID stream_id_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_INVALID_STREAM_IDENTIFIER_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause_test.cc
new file mode 100644
index 0000000000..a282ce5ee8
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/invalid_stream_identifier_cause_test.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/invalid_stream_identifier_cause.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(InvalidStreamIdentifierCauseTest, SerializeAndDeserialize) {
+ InvalidStreamIdentifierCause parameter(StreamID(1));
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(InvalidStreamIdentifierCause deserialized,
+ InvalidStreamIdentifierCause::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.stream_id(), 1);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.cc
new file mode 100644
index 0000000000..b89f86e43e
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h"
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/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.10.2
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=2 | Cause Length=8+N*2 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Number of missing params=N |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Missing Param Type #1 | Missing Param Type #2 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Missing Param Type #N-1 | Missing Param Type #N |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int MissingMandatoryParameterCause::kType;
+
+absl::optional<MissingMandatoryParameterCause>
+MissingMandatoryParameterCause::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+
+ uint32_t count = reader->Load32<4>();
+ if (reader->variable_data_size() / kMissingParameterSize != count) {
+ RTC_DLOG(LS_WARNING) << "Invalid number of missing parameters";
+ return absl::nullopt;
+ }
+
+ std::vector<uint16_t> missing_parameter_types;
+ missing_parameter_types.reserve(count);
+ for (uint32_t i = 0; i < count; ++i) {
+ BoundedByteReader<kMissingParameterSize> sub_reader =
+ reader->sub_reader<kMissingParameterSize>(i * kMissingParameterSize);
+
+ missing_parameter_types.push_back(sub_reader.Load16<0>());
+ }
+ return MissingMandatoryParameterCause(missing_parameter_types);
+}
+
+void MissingMandatoryParameterCause::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ size_t variable_size =
+ missing_parameter_types_.size() * kMissingParameterSize;
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
+
+ writer.Store32<4>(missing_parameter_types_.size());
+
+ for (size_t i = 0; i < missing_parameter_types_.size(); ++i) {
+ BoundedByteWriter<kMissingParameterSize> sub_writer =
+ writer.sub_writer<kMissingParameterSize>(i * kMissingParameterSize);
+
+ sub_writer.Store16<0>(missing_parameter_types_[i]);
+ }
+}
+
+std::string MissingMandatoryParameterCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Missing Mandatory Parameter, missing_parameter_types="
+ << StrJoin(missing_parameter_types_, ",");
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h
new file mode 100644
index 0000000000..4435424295
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_MISSING_MANDATORY_PARAMETER_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_MISSING_MANDATORY_PARAMETER_CAUSE_H_
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.2
+struct MissingMandatoryParameterCauseConfig : public ParameterConfig {
+ static constexpr int kType = 2;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr size_t kVariableLengthAlignment = 2;
+};
+
+class MissingMandatoryParameterCause
+ : public Parameter,
+ public TLVTrait<MissingMandatoryParameterCauseConfig> {
+ public:
+ static constexpr int kType = MissingMandatoryParameterCauseConfig::kType;
+
+ explicit MissingMandatoryParameterCause(
+ rtc::ArrayView<const uint16_t> missing_parameter_types)
+ : missing_parameter_types_(missing_parameter_types.begin(),
+ missing_parameter_types.end()) {}
+
+ static absl::optional<MissingMandatoryParameterCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ rtc::ArrayView<const uint16_t> missing_parameter_types() const {
+ return missing_parameter_types_;
+ }
+
+ private:
+ static constexpr size_t kMissingParameterSize = 2;
+ std::vector<uint16_t> missing_parameter_types_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_MISSING_MANDATORY_PARAMETER_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause_test.cc
new file mode 100644
index 0000000000..1c526ff0e2
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause_test.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/missing_mandatory_parameter_cause.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;
+using ::testing::IsEmpty;
+
+TEST(MissingMandatoryParameterCauseTest, SerializeAndDeserialize) {
+ uint16_t parameter_types[] = {1, 2, 3};
+ MissingMandatoryParameterCause parameter(parameter_types);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ MissingMandatoryParameterCause deserialized,
+ MissingMandatoryParameterCause::Parse(serialized));
+
+ EXPECT_THAT(deserialized.missing_parameter_types(), ElementsAre(1, 2, 3));
+}
+
+TEST(MissingMandatoryParameterCauseTest, HandlesDeserializeZeroParameters) {
+ uint8_t serialized[] = {0, 2, 0, 8, 0, 0, 0, 0};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ MissingMandatoryParameterCause deserialized,
+ MissingMandatoryParameterCause::Parse(serialized));
+
+ EXPECT_THAT(deserialized.missing_parameter_types(), IsEmpty());
+}
+
+TEST(MissingMandatoryParameterCauseTest, HandlesOverflowParameterCount) {
+ // 0x80000004 * 2 = 2**32 + 8 -> if overflow, would validate correctly.
+ uint8_t serialized[] = {0, 2, 0, 8, 0x80, 0x00, 0x00, 0x04};
+
+ EXPECT_FALSE(MissingMandatoryParameterCause::Parse(serialized).has_value());
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.cc
new file mode 100644
index 0000000000..2853915b0c
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/no_user_data_cause.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.9
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=9 | Cause Length=8 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / TSN value /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int NoUserDataCause::kType;
+
+absl::optional<NoUserDataCause> NoUserDataCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ TSN tsn(reader->Load32<4>());
+ return NoUserDataCause(tsn);
+}
+
+void NoUserDataCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+ writer.Store32<4>(*tsn_);
+}
+
+std::string NoUserDataCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "No User Data, tsn=" << *tsn_;
+ return sb.Release();
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.h
new file mode 100644
index 0000000000..1087dcc97c
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause.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_ERROR_CAUSE_NO_USER_DATA_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_NO_USER_DATA_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.9
+struct NoUserDataCauseConfig : public ParameterConfig {
+ static constexpr int kType = 9;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class NoUserDataCause : public Parameter,
+ public TLVTrait<NoUserDataCauseConfig> {
+ public:
+ static constexpr int kType = NoUserDataCauseConfig::kType;
+
+ explicit NoUserDataCause(TSN tsn) : tsn_(tsn) {}
+
+ static absl::optional<NoUserDataCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ TSN tsn() const { return tsn_; }
+
+ private:
+ TSN tsn_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_NO_USER_DATA_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause_test.cc
new file mode 100644
index 0000000000..0a535bf4fa
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/no_user_data_cause_test.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/no_user_data_cause.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(NoUserDataCauseTest, SerializeAndDeserialize) {
+ NoUserDataCause parameter(TSN(123));
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(NoUserDataCause deserialized,
+ NoUserDataCause::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.tsn(), 123u);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.cc
new file mode 100644
index 0000000000..e5c7c0e787
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.4
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=4 | Cause Length=4 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int OutOfResourceErrorCause::kType;
+
+absl::optional<OutOfResourceErrorCause> OutOfResourceErrorCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ if (!ParseTLV(data).has_value()) {
+ return absl::nullopt;
+ }
+ return OutOfResourceErrorCause();
+}
+
+void OutOfResourceErrorCause::SerializeTo(std::vector<uint8_t>& out) const {
+ AllocateTLV(out);
+}
+
+std::string OutOfResourceErrorCause::ToString() const {
+ return "Out Of Resource";
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.h
new file mode 100644
index 0000000000..fc798ca4ac
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_OUT_OF_RESOURCE_ERROR_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_OUT_OF_RESOURCE_ERROR_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.4
+struct OutOfResourceParameterConfig : public ParameterConfig {
+ static constexpr int kType = 4;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class OutOfResourceErrorCause : public Parameter,
+ public TLVTrait<OutOfResourceParameterConfig> {
+ public:
+ static constexpr int kType = OutOfResourceParameterConfig::kType;
+
+ OutOfResourceErrorCause() {}
+
+ static absl::optional<OutOfResourceErrorCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_OUT_OF_RESOURCE_ERROR_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause_test.cc
new file mode 100644
index 0000000000..501fc201cd
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/out_of_resource_error_cause_test.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(OutOfResourceErrorCauseTest, SerializeAndDeserialize) {
+ OutOfResourceErrorCause parameter;
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(OutOfResourceErrorCause deserialized,
+ OutOfResourceErrorCause::Parse(serialized));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.cc
new file mode 100644
index 0000000000..1b8d423afb
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.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/error_cause/protocol_violation_cause.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.13
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=13 | Cause Length=Variable |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / Additional Information /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int ProtocolViolationCause::kType;
+
+absl::optional<ProtocolViolationCause> ProtocolViolationCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ return ProtocolViolationCause(
+ std::string(reinterpret_cast<const char*>(reader->variable_data().data()),
+ reader->variable_data().size()));
+}
+
+void ProtocolViolationCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer =
+ AllocateTLV(out, additional_information_.size());
+ writer.CopyToVariableData(rtc::MakeArrayView(
+ reinterpret_cast<const uint8_t*>(additional_information_.data()),
+ additional_information_.size()));
+}
+
+std::string ProtocolViolationCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Protocol Violation, additional_information="
+ << additional_information_;
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.h
new file mode 100644
index 0000000000..3081e1f28c
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause.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_ERROR_CAUSE_PROTOCOL_VIOLATION_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_PROTOCOL_VIOLATION_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.13
+struct ProtocolViolationCauseConfig : public ParameterConfig {
+ static constexpr int kType = 13;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class ProtocolViolationCause : public Parameter,
+ public TLVTrait<ProtocolViolationCauseConfig> {
+ public:
+ static constexpr int kType = ProtocolViolationCauseConfig::kType;
+
+ explicit ProtocolViolationCause(absl::string_view additional_information)
+ : additional_information_(additional_information) {}
+
+ static absl::optional<ProtocolViolationCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ absl::string_view additional_information() const {
+ return additional_information_;
+ }
+
+ private:
+ std::string additional_information_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_PROTOCOL_VIOLATION_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause_test.cc
new file mode 100644
index 0000000000..902d867091
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/protocol_violation_cause_test.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.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::SizeIs;
+
+TEST(ProtocolViolationCauseTest, EmptyReason) {
+ Parameters causes =
+ Parameters::Builder().Add(ProtocolViolationCause("")).Build();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(Parameters deserialized,
+ Parameters::Parse(causes.data()));
+ ASSERT_THAT(deserialized.descriptors(), SizeIs(1));
+ EXPECT_EQ(deserialized.descriptors()[0].type, ProtocolViolationCause::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ ProtocolViolationCause cause,
+ ProtocolViolationCause::Parse(deserialized.descriptors()[0].data));
+
+ EXPECT_EQ(cause.additional_information(), "");
+}
+
+TEST(ProtocolViolationCauseTest, SetReason) {
+ Parameters causes = Parameters::Builder()
+ .Add(ProtocolViolationCause("Reason goes here"))
+ .Build();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(Parameters deserialized,
+ Parameters::Parse(causes.data()));
+ ASSERT_THAT(deserialized.descriptors(), SizeIs(1));
+ EXPECT_EQ(deserialized.descriptors()[0].type, ProtocolViolationCause::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ ProtocolViolationCause cause,
+ ProtocolViolationCause::Parse(deserialized.descriptors()[0].data));
+
+ EXPECT_EQ(cause.additional_information(), "Reason goes here");
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.cc
new file mode 100644
index 0000000000..abe5de6211
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.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/error_cause/restart_of_an_association_with_new_address_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.11
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=11 | Cause Length=Variable |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / New Address TLVs /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int RestartOfAnAssociationWithNewAddressesCause::kType;
+
+absl::optional<RestartOfAnAssociationWithNewAddressesCause>
+RestartOfAnAssociationWithNewAddressesCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ return RestartOfAnAssociationWithNewAddressesCause(reader->variable_data());
+}
+
+void RestartOfAnAssociationWithNewAddressesCause::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer =
+ AllocateTLV(out, new_address_tlvs_.size());
+ writer.CopyToVariableData(new_address_tlvs_);
+}
+
+std::string RestartOfAnAssociationWithNewAddressesCause::ToString() const {
+ return "Restart of an Association with New Addresses";
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h
new file mode 100644
index 0000000000..a1cccdc8a1
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESS_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESS_CAUSE_H_
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.11
+struct RestartOfAnAssociationWithNewAddressesCauseConfig
+ : public ParameterConfig {
+ static constexpr int kType = 11;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class RestartOfAnAssociationWithNewAddressesCause
+ : public Parameter,
+ public TLVTrait<RestartOfAnAssociationWithNewAddressesCauseConfig> {
+ public:
+ static constexpr int kType =
+ RestartOfAnAssociationWithNewAddressesCauseConfig::kType;
+
+ explicit RestartOfAnAssociationWithNewAddressesCause(
+ rtc::ArrayView<const uint8_t> new_address_tlvs)
+ : new_address_tlvs_(new_address_tlvs.begin(), new_address_tlvs.end()) {}
+
+ static absl::optional<RestartOfAnAssociationWithNewAddressesCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ rtc::ArrayView<const uint8_t> new_address_tlvs() const {
+ return new_address_tlvs_;
+ }
+
+ private:
+ std::vector<uint8_t> new_address_tlvs_;
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESS_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause_test.cc
new file mode 100644
index 0000000000..b8ab8b6803
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause_test.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/restart_of_an_association_with_new_address_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "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(RestartOfAnAssociationWithNewAddressesCauseTest, SerializeAndDeserialize) {
+ uint8_t data[] = {1, 2, 3};
+ RestartOfAnAssociationWithNewAddressesCause parameter(data);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ RestartOfAnAssociationWithNewAddressesCause deserialized,
+ RestartOfAnAssociationWithNewAddressesCause::Parse(serialized));
+
+ EXPECT_THAT(deserialized.new_address_tlvs(), ElementsAre(1, 2, 3));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.cc
new file mode 100644
index 0000000000..d77d8488f1
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/stale_cookie_error_cause.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.3
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=3 | Cause Length=8 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Measure of Staleness (usec.) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int StaleCookieErrorCause::kType;
+
+absl::optional<StaleCookieErrorCause> StaleCookieErrorCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ uint32_t staleness_us = reader->Load32<4>();
+ return StaleCookieErrorCause(staleness_us);
+}
+
+void StaleCookieErrorCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+ writer.Store32<4>(staleness_us_);
+}
+
+std::string StaleCookieErrorCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Stale Cookie Error, staleness_us=" << staleness_us_;
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.h
new file mode 100644
index 0000000000..d8b7b5b5bd
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause.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_ERROR_CAUSE_STALE_COOKIE_ERROR_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_STALE_COOKIE_ERROR_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.3
+struct StaleCookieParameterConfig : public ParameterConfig {
+ static constexpr int kType = 3;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class StaleCookieErrorCause : public Parameter,
+ public TLVTrait<StaleCookieParameterConfig> {
+ public:
+ static constexpr int kType = StaleCookieParameterConfig::kType;
+
+ explicit StaleCookieErrorCause(uint32_t staleness_us)
+ : staleness_us_(staleness_us) {}
+
+ static absl::optional<StaleCookieErrorCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ uint16_t staleness_us() const { return staleness_us_; }
+
+ private:
+ uint32_t staleness_us_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_STALE_COOKIE_ERROR_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause_test.cc
new file mode 100644
index 0000000000..c0d1ac1c58
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/stale_cookie_error_cause_test.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/stale_cookie_error_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(StaleCookieErrorCauseTest, SerializeAndDeserialize) {
+ StaleCookieErrorCause parameter(123);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(StaleCookieErrorCause deserialized,
+ StaleCookieErrorCause::Parse(serialized));
+
+ EXPECT_EQ(deserialized.staleness_us(), 123);
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.cc
new file mode 100644
index 0000000000..04b960d992
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.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/error_cause/unrecognized_chunk_type_cause.h"
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.6
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=6 | Cause Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / Unrecognized Chunk /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int UnrecognizedChunkTypeCause::kType;
+
+absl::optional<UnrecognizedChunkTypeCause> UnrecognizedChunkTypeCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ std::vector<uint8_t> unrecognized_chunk(reader->variable_data().begin(),
+ reader->variable_data().end());
+ return UnrecognizedChunkTypeCause(std::move(unrecognized_chunk));
+}
+
+void UnrecognizedChunkTypeCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer =
+ AllocateTLV(out, unrecognized_chunk_.size());
+ writer.CopyToVariableData(unrecognized_chunk_);
+}
+
+std::string UnrecognizedChunkTypeCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Unrecognized Chunk Type, chunk_type=";
+ if (!unrecognized_chunk_.empty()) {
+ sb << static_cast<int>(unrecognized_chunk_[0]);
+ } else {
+ sb << "<missing>";
+ }
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h
new file mode 100644
index 0000000000..26d3d3b8f9
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_CHUNK_TYPE_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_CHUNK_TYPE_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.6
+struct UnrecognizedChunkTypeCauseConfig : public ParameterConfig {
+ static constexpr int kType = 6;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class UnrecognizedChunkTypeCause
+ : public Parameter,
+ public TLVTrait<UnrecognizedChunkTypeCauseConfig> {
+ public:
+ static constexpr int kType = UnrecognizedChunkTypeCauseConfig::kType;
+
+ explicit UnrecognizedChunkTypeCause(std::vector<uint8_t> unrecognized_chunk)
+ : unrecognized_chunk_(std::move(unrecognized_chunk)) {}
+
+ static absl::optional<UnrecognizedChunkTypeCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ rtc::ArrayView<const uint8_t> unrecognized_chunk() const {
+ return unrecognized_chunk_;
+ }
+
+ private:
+ std::vector<uint8_t> unrecognized_chunk_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_CHUNK_TYPE_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause_test.cc
new file mode 100644
index 0000000000..baff852f40
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause_test.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
+
+#include <cstdint>
+#include <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(UnrecognizedChunkTypeCauseTest, SerializeAndDeserialize) {
+ UnrecognizedChunkTypeCause parameter({1, 2, 3});
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(UnrecognizedChunkTypeCause deserialized,
+ UnrecognizedChunkTypeCause::Parse(serialized));
+
+ EXPECT_THAT(deserialized.unrecognized_chunk(), ElementsAre(1, 2, 3));
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.cc
new file mode 100644
index 0000000000..80001a9eae
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.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/error_cause/unrecognized_parameter_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.8
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=8 | Cause Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / Unrecognized Parameters /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int UnrecognizedParametersCause::kType;
+
+absl::optional<UnrecognizedParametersCause> UnrecognizedParametersCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ return UnrecognizedParametersCause(reader->variable_data());
+}
+
+void UnrecognizedParametersCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer =
+ AllocateTLV(out, unrecognized_parameters_.size());
+ writer.CopyToVariableData(unrecognized_parameters_);
+}
+
+std::string UnrecognizedParametersCause::ToString() const {
+ return "Unrecognized Parameters";
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h
new file mode 100644
index 0000000000..ebec5ed4c3
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_PARAMETER_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_PARAMETER_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.8
+struct UnrecognizedParametersCauseConfig : public ParameterConfig {
+ static constexpr int kType = 8;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class UnrecognizedParametersCause
+ : public Parameter,
+ public TLVTrait<UnrecognizedParametersCauseConfig> {
+ public:
+ static constexpr int kType = UnrecognizedParametersCauseConfig::kType;
+
+ explicit UnrecognizedParametersCause(
+ rtc::ArrayView<const uint8_t> unrecognized_parameters)
+ : unrecognized_parameters_(unrecognized_parameters.begin(),
+ unrecognized_parameters.end()) {}
+
+ static absl::optional<UnrecognizedParametersCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ rtc::ArrayView<const uint8_t> unrecognized_parameters() const {
+ return unrecognized_parameters_;
+ }
+
+ private:
+ std::vector<uint8_t> unrecognized_parameters_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_UNRECOGNIZED_PARAMETER_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause_test.cc
new file mode 100644
index 0000000000..0449599ca6
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unrecognized_parameter_cause_test.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/unrecognized_parameter_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "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(UnrecognizedParametersCauseTest, SerializeAndDeserialize) {
+ uint8_t unrecognized_parameters[] = {1, 2, 3};
+ UnrecognizedParametersCause parameter(unrecognized_parameters);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(UnrecognizedParametersCause deserialized,
+ UnrecognizedParametersCause::Parse(serialized));
+
+ EXPECT_THAT(deserialized.unrecognized_parameters(), ElementsAre(1, 2, 3));
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.cc
new file mode 100644
index 0000000000..8108d31aa7
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/unresolvable_address_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.5
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=5 | Cause Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / Unresolvable Address /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int UnresolvableAddressCause::kType;
+
+absl::optional<UnresolvableAddressCause> UnresolvableAddressCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ return UnresolvableAddressCause(reader->variable_data());
+}
+
+void UnresolvableAddressCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer =
+ AllocateTLV(out, unresolvable_address_.size());
+ writer.CopyToVariableData(unresolvable_address_);
+}
+
+std::string UnresolvableAddressCause::ToString() const {
+ return "Unresolvable Address";
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.h
new file mode 100644
index 0000000000..c63b3779ef
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_ERROR_CAUSE_UNRESOLVABLE_ADDRESS_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_UNRESOLVABLE_ADDRESS_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.5
+struct UnresolvableAddressCauseConfig : public ParameterConfig {
+ static constexpr int kType = 5;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class UnresolvableAddressCause
+ : public Parameter,
+ public TLVTrait<UnresolvableAddressCauseConfig> {
+ public:
+ static constexpr int kType = UnresolvableAddressCauseConfig::kType;
+
+ explicit UnresolvableAddressCause(
+ rtc::ArrayView<const uint8_t> unresolvable_address)
+ : unresolvable_address_(unresolvable_address.begin(),
+ unresolvable_address.end()) {}
+
+ static absl::optional<UnresolvableAddressCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ rtc::ArrayView<const uint8_t> unresolvable_address() const {
+ return unresolvable_address_;
+ }
+
+ private:
+ std::vector<uint8_t> unresolvable_address_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_UNRESOLVABLE_ADDRESS_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause_test.cc
new file mode 100644
index 0000000000..688730e6b3
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/unresolvable_address_cause_test.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/unresolvable_address_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "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(UnresolvableAddressCauseTest, SerializeAndDeserialize) {
+ uint8_t unresolvable_address[] = {1, 2, 3};
+ UnresolvableAddressCause parameter(unresolvable_address);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(UnresolvableAddressCause deserialized,
+ UnresolvableAddressCause::Parse(serialized));
+
+ EXPECT_THAT(deserialized.unresolvable_address(), ElementsAre(1, 2, 3));
+}
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.cc
new file mode 100644
index 0000000000..da99aacbfa
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.12
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Cause Code=12 | Cause Length=Variable |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / Upper Layer Abort Reason /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int UserInitiatedAbortCause::kType;
+
+absl::optional<UserInitiatedAbortCause> UserInitiatedAbortCause::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ if (reader->variable_data().empty()) {
+ return UserInitiatedAbortCause("");
+ }
+ return UserInitiatedAbortCause(
+ std::string(reinterpret_cast<const char*>(reader->variable_data().data()),
+ reader->variable_data().size()));
+}
+
+void UserInitiatedAbortCause::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer =
+ AllocateTLV(out, upper_layer_abort_reason_.size());
+ writer.CopyToVariableData(rtc::MakeArrayView(
+ reinterpret_cast<const uint8_t*>(upper_layer_abort_reason_.data()),
+ upper_layer_abort_reason_.size()));
+}
+
+std::string UserInitiatedAbortCause::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "User-Initiated Abort, reason=" << upper_layer_abort_reason_;
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.h b/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.h
new file mode 100644
index 0000000000..9eb16657b4
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause.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_ERROR_CAUSE_USER_INITIATED_ABORT_CAUSE_H_
+#define NET_DCSCTP_PACKET_ERROR_CAUSE_USER_INITIATED_ABORT_CAUSE_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.10.12
+struct UserInitiatedAbortCauseConfig : public ParameterConfig {
+ static constexpr int kType = 12;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class UserInitiatedAbortCause : public Parameter,
+ public TLVTrait<UserInitiatedAbortCauseConfig> {
+ public:
+ static constexpr int kType = UserInitiatedAbortCauseConfig::kType;
+
+ explicit UserInitiatedAbortCause(absl::string_view upper_layer_abort_reason)
+ : upper_layer_abort_reason_(upper_layer_abort_reason) {}
+
+ static absl::optional<UserInitiatedAbortCause> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ absl::string_view upper_layer_abort_reason() const {
+ return upper_layer_abort_reason_;
+ }
+
+ private:
+ std::string upper_layer_abort_reason_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_ERROR_CAUSE_USER_INITIATED_ABORT_CAUSE_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause_test.cc b/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause_test.cc
new file mode 100644
index 0000000000..250959e3df
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/error_cause/user_initiated_abort_cause_test.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/error_cause/user_initiated_abort_cause.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/packet/error_cause/error_cause.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::SizeIs;
+
+TEST(UserInitiatedAbortCauseTest, EmptyReason) {
+ Parameters causes =
+ Parameters::Builder().Add(UserInitiatedAbortCause("")).Build();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(Parameters deserialized,
+ Parameters::Parse(causes.data()));
+ ASSERT_THAT(deserialized.descriptors(), SizeIs(1));
+ EXPECT_EQ(deserialized.descriptors()[0].type, UserInitiatedAbortCause::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UserInitiatedAbortCause cause,
+ UserInitiatedAbortCause::Parse(deserialized.descriptors()[0].data));
+
+ EXPECT_EQ(cause.upper_layer_abort_reason(), "");
+}
+
+TEST(UserInitiatedAbortCauseTest, SetReason) {
+ Parameters causes = Parameters::Builder()
+ .Add(UserInitiatedAbortCause("User called Close"))
+ .Build();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(Parameters deserialized,
+ Parameters::Parse(causes.data()));
+ ASSERT_THAT(deserialized.descriptors(), SizeIs(1));
+ EXPECT_EQ(deserialized.descriptors()[0].type, UserInitiatedAbortCause::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UserInitiatedAbortCause cause,
+ UserInitiatedAbortCause::Parse(deserialized.descriptors()[0].data));
+
+ EXPECT_EQ(cause.upper_layer_abort_reason(), "User called Close");
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.cc
new file mode 100644
index 0000000000..c33e3e11f6
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.6
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 18 | Parameter Length = 12 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Request Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Number of new streams | Reserved |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int AddIncomingStreamsRequestParameter::kType;
+
+absl::optional<AddIncomingStreamsRequestParameter>
+AddIncomingStreamsRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ ReconfigRequestSN request_sequence_number(reader->Load32<4>());
+ uint16_t nbr_of_new_streams = reader->Load16<8>();
+
+ return AddIncomingStreamsRequestParameter(request_sequence_number,
+ nbr_of_new_streams);
+}
+
+void AddIncomingStreamsRequestParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+ writer.Store32<4>(*request_sequence_number_);
+ writer.Store16<8>(nbr_of_new_streams_);
+}
+
+std::string AddIncomingStreamsRequestParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Add Incoming Streams Request, req_seq_nbr="
+ << *request_sequence_number();
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h
new file mode 100644
index 0000000000..3859eb3f7e
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.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_PARAMETER_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.6
+struct AddIncomingStreamsRequestParameterConfig : ParameterConfig {
+ static constexpr int kType = 18;
+ static constexpr size_t kHeaderSize = 12;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class AddIncomingStreamsRequestParameter
+ : public Parameter,
+ public TLVTrait<AddIncomingStreamsRequestParameterConfig> {
+ public:
+ static constexpr int kType = AddIncomingStreamsRequestParameterConfig::kType;
+
+ explicit AddIncomingStreamsRequestParameter(
+ ReconfigRequestSN request_sequence_number,
+ uint16_t nbr_of_new_streams)
+ : request_sequence_number_(request_sequence_number),
+ nbr_of_new_streams_(nbr_of_new_streams) {}
+
+ static absl::optional<AddIncomingStreamsRequestParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ ReconfigRequestSN request_sequence_number() const {
+ return request_sequence_number_;
+ }
+ uint16_t nbr_of_new_streams() const { return nbr_of_new_streams_; }
+
+ private:
+ ReconfigRequestSN request_sequence_number_;
+ uint16_t nbr_of_new_streams_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter_test.cc
new file mode 100644
index 0000000000..a29257a8f8
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_incoming_streams_request_parameter_test.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.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(AddIncomingStreamsRequestParameterTest, SerializeAndDeserialize) {
+ AddIncomingStreamsRequestParameter parameter(ReconfigRequestSN(1), 2);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ AddIncomingStreamsRequestParameter deserialized,
+ AddIncomingStreamsRequestParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.request_sequence_number(), 1u);
+ EXPECT_EQ(deserialized.nbr_of_new_streams(), 2u);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.cc
new file mode 100644
index 0000000000..4787ee9718
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.5
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 17 | Parameter Length = 12 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Request Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Number of new streams | Reserved |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int AddOutgoingStreamsRequestParameter::kType;
+
+absl::optional<AddOutgoingStreamsRequestParameter>
+AddOutgoingStreamsRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ ReconfigRequestSN request_sequence_number(reader->Load32<4>());
+ uint16_t nbr_of_new_streams = reader->Load16<8>();
+
+ return AddOutgoingStreamsRequestParameter(request_sequence_number,
+ nbr_of_new_streams);
+}
+
+void AddOutgoingStreamsRequestParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+ writer.Store32<4>(*request_sequence_number_);
+ writer.Store16<8>(nbr_of_new_streams_);
+}
+
+std::string AddOutgoingStreamsRequestParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Add Outgoing Streams Request, req_seq_nbr="
+ << *request_sequence_number();
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h
new file mode 100644
index 0000000000..01e8f91cfa
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.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_PARAMETER_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.5
+struct AddOutgoingStreamsRequestParameterConfig : ParameterConfig {
+ static constexpr int kType = 17;
+ static constexpr size_t kHeaderSize = 12;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class AddOutgoingStreamsRequestParameter
+ : public Parameter,
+ public TLVTrait<AddOutgoingStreamsRequestParameterConfig> {
+ public:
+ static constexpr int kType = AddOutgoingStreamsRequestParameterConfig::kType;
+
+ explicit AddOutgoingStreamsRequestParameter(
+ ReconfigRequestSN request_sequence_number,
+ uint16_t nbr_of_new_streams)
+ : request_sequence_number_(request_sequence_number),
+ nbr_of_new_streams_(nbr_of_new_streams) {}
+
+ static absl::optional<AddOutgoingStreamsRequestParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ ReconfigRequestSN request_sequence_number() const {
+ return request_sequence_number_;
+ }
+ uint16_t nbr_of_new_streams() const { return nbr_of_new_streams_; }
+
+ private:
+ ReconfigRequestSN request_sequence_number_;
+ uint16_t nbr_of_new_streams_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter_test.cc
new file mode 100644
index 0000000000..d0303b1ba8
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter_test.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.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(AddOutgoingStreamsRequestParameterTest, SerializeAndDeserialize) {
+ AddOutgoingStreamsRequestParameter parameter(ReconfigRequestSN(1), 2);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ AddOutgoingStreamsRequestParameter deserialized,
+ AddOutgoingStreamsRequestParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.request_sequence_number(), 1u);
+ EXPECT_EQ(deserialized.nbr_of_new_streams(), 2u);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.cc
new file mode 100644
index 0000000000..7dd8e1923f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.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/parameter/forward_tsn_supported_parameter.h"
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc3758#section-3.1
+
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 49152 | Parameter Length = 4 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int ForwardTsnSupportedParameter::kType;
+
+absl::optional<ForwardTsnSupportedParameter>
+ForwardTsnSupportedParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ if (!ParseTLV(data).has_value()) {
+ return absl::nullopt;
+ }
+ return ForwardTsnSupportedParameter();
+}
+
+void ForwardTsnSupportedParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ AllocateTLV(out);
+}
+
+std::string ForwardTsnSupportedParameter::ToString() const {
+ return "Forward TSN Supported";
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h
new file mode 100644
index 0000000000..d4cff4ac21
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_PARAMETER_FORWARD_TSN_SUPPORTED_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_FORWARD_TSN_SUPPORTED_PARAMETER_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc3758#section-3.1
+struct ForwardTsnSupportedParameterConfig : ParameterConfig {
+ static constexpr int kType = 49152;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class ForwardTsnSupportedParameter
+ : public Parameter,
+ public TLVTrait<ForwardTsnSupportedParameterConfig> {
+ public:
+ static constexpr int kType = ForwardTsnSupportedParameterConfig::kType;
+
+ ForwardTsnSupportedParameter() {}
+
+ static absl::optional<ForwardTsnSupportedParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_FORWARD_TSN_SUPPORTED_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter_test.cc
new file mode 100644
index 0000000000..fb4f983fae
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/forward_tsn_supported_parameter_test.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(ForwardTsnSupportedParameterTest, SerializeAndDeserialize) {
+ ForwardTsnSupportedParameter parameter;
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(ForwardTsnSupportedParameter deserialized,
+ ForwardTsnSupportedParameter::Parse(serialized));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.cc
new file mode 100644
index 0000000000..918976d305
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.5
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Type = 4 | Chunk Flags | Heartbeat Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// \ \
+// / Heartbeat Information TLV (Variable-Length) /
+// \ \
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int HeartbeatInfoParameter::kType;
+
+absl::optional<HeartbeatInfoParameter> HeartbeatInfoParameter::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ return HeartbeatInfoParameter(reader->variable_data());
+}
+
+void HeartbeatInfoParameter::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, info_.size());
+ writer.CopyToVariableData(info_);
+}
+
+std::string HeartbeatInfoParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Heartbeat Info parameter (info_length=" << info_.size() << ")";
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.h
new file mode 100644
index 0000000000..ec503a94b2
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/heartbeat_info_parameter.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_PARAMETER_HEARTBEAT_INFO_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_HEARTBEAT_INFO_PARAMETER_H_
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.5
+struct HeartbeatInfoParameterConfig : ParameterConfig {
+ static constexpr int kType = 1;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class HeartbeatInfoParameter : public Parameter,
+ public TLVTrait<HeartbeatInfoParameterConfig> {
+ public:
+ static constexpr int kType = HeartbeatInfoParameterConfig::kType;
+
+ explicit HeartbeatInfoParameter(rtc::ArrayView<const uint8_t> info)
+ : info_(info.begin(), info.end()) {}
+
+ static absl::optional<HeartbeatInfoParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ rtc::ArrayView<const uint8_t> info() const { return info_; }
+
+ private:
+ std::vector<uint8_t> info_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_HEARTBEAT_INFO_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.cc
new file mode 100644
index 0000000000..6191adfe9d
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.2
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 14 | Parameter Length = 8 + 2 * N |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Request Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Stream Number 1 (optional) | Stream Number 2 (optional) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / ...... /
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Stream Number N-1 (optional) | Stream Number N (optional) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int IncomingSSNResetRequestParameter::kType;
+
+absl::optional<IncomingSSNResetRequestParameter>
+IncomingSSNResetRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+
+ ReconfigRequestSN request_sequence_number(reader->Load32<4>());
+
+ size_t stream_count = reader->variable_data_size() / kStreamIdSize;
+ std::vector<StreamID> stream_ids;
+ stream_ids.reserve(stream_count);
+ for (size_t i = 0; i < stream_count; ++i) {
+ BoundedByteReader<kStreamIdSize> sub_reader =
+ reader->sub_reader<kStreamIdSize>(i * kStreamIdSize);
+
+ stream_ids.push_back(StreamID(sub_reader.Load16<0>()));
+ }
+
+ return IncomingSSNResetRequestParameter(request_sequence_number,
+ std::move(stream_ids));
+}
+
+void IncomingSSNResetRequestParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ size_t variable_size = stream_ids_.size() * kStreamIdSize;
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
+
+ writer.Store32<4>(*request_sequence_number_);
+
+ for (size_t i = 0; i < stream_ids_.size(); ++i) {
+ BoundedByteWriter<kStreamIdSize> sub_writer =
+ writer.sub_writer<kStreamIdSize>(i * kStreamIdSize);
+ sub_writer.Store16<0>(*stream_ids_[i]);
+ }
+}
+
+std::string IncomingSSNResetRequestParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Incoming SSN Reset Request, req_seq_nbr="
+ << *request_sequence_number();
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h
new file mode 100644
index 0000000000..18963efafc
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.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_PARAMETER_INCOMING_SSN_RESET_REQUEST_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_INCOMING_SSN_RESET_REQUEST_PARAMETER_H_
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/public/types.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.2
+struct IncomingSSNResetRequestParameterConfig : ParameterConfig {
+ static constexpr int kType = 14;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr size_t kVariableLengthAlignment = 2;
+};
+
+class IncomingSSNResetRequestParameter
+ : public Parameter,
+ public TLVTrait<IncomingSSNResetRequestParameterConfig> {
+ public:
+ static constexpr int kType = IncomingSSNResetRequestParameterConfig::kType;
+
+ explicit IncomingSSNResetRequestParameter(
+ ReconfigRequestSN request_sequence_number,
+ std::vector<StreamID> stream_ids)
+ : request_sequence_number_(request_sequence_number),
+ stream_ids_(std::move(stream_ids)) {}
+
+ static absl::optional<IncomingSSNResetRequestParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ ReconfigRequestSN request_sequence_number() const {
+ return request_sequence_number_;
+ }
+ rtc::ArrayView<const StreamID> stream_ids() const { return stream_ids_; }
+
+ private:
+ static constexpr size_t kStreamIdSize = sizeof(uint16_t);
+
+ ReconfigRequestSN request_sequence_number_;
+ std::vector<StreamID> stream_ids_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_INCOMING_SSN_RESET_REQUEST_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter_test.cc
new file mode 100644
index 0000000000..17793f6638
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter_test.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
+
+#include <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(IncomingSSNResetRequestParameterTest, SerializeAndDeserialize) {
+ IncomingSSNResetRequestParameter parameter(
+ ReconfigRequestSN(1), {StreamID(2), StreamID(3), StreamID(4)});
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ IncomingSSNResetRequestParameter deserialized,
+ IncomingSSNResetRequestParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.request_sequence_number(), 1u);
+ EXPECT_THAT(deserialized.stream_ids(),
+ ElementsAre(StreamID(2), StreamID(3), StreamID(4)));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.cc
new file mode 100644
index 0000000000..c25a2426be
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.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/parameter/outgoing_ssn_reset_request_parameter.h"
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "net/dcsctp/public/types.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.1
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 13 | Parameter Length = 16 + 2 * N |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Request Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Response Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Sender's Last Assigned TSN |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Stream Number 1 (optional) | Stream Number 2 (optional) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// / ...... /
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Stream Number N-1 (optional) | Stream Number N (optional) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int OutgoingSSNResetRequestParameter::kType;
+
+absl::optional<OutgoingSSNResetRequestParameter>
+OutgoingSSNResetRequestParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+
+ ReconfigRequestSN request_sequence_number(reader->Load32<4>());
+ ReconfigRequestSN response_sequence_number(reader->Load32<8>());
+ TSN sender_last_assigned_tsn(reader->Load32<12>());
+
+ size_t stream_count = reader->variable_data_size() / kStreamIdSize;
+ std::vector<StreamID> stream_ids;
+ stream_ids.reserve(stream_count);
+ for (size_t i = 0; i < stream_count; ++i) {
+ BoundedByteReader<kStreamIdSize> sub_reader =
+ reader->sub_reader<kStreamIdSize>(i * kStreamIdSize);
+
+ stream_ids.push_back(StreamID(sub_reader.Load16<0>()));
+ }
+
+ return OutgoingSSNResetRequestParameter(
+ request_sequence_number, response_sequence_number,
+ sender_last_assigned_tsn, std::move(stream_ids));
+}
+
+void OutgoingSSNResetRequestParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ size_t variable_size = stream_ids_.size() * kStreamIdSize;
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
+
+ writer.Store32<4>(*request_sequence_number_);
+ writer.Store32<8>(*response_sequence_number_);
+ writer.Store32<12>(*sender_last_assigned_tsn_);
+
+ for (size_t i = 0; i < stream_ids_.size(); ++i) {
+ BoundedByteWriter<kStreamIdSize> sub_writer =
+ writer.sub_writer<kStreamIdSize>(i * kStreamIdSize);
+ sub_writer.Store16<0>(*stream_ids_[i]);
+ }
+}
+
+std::string OutgoingSSNResetRequestParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Outgoing SSN Reset Request, req_seq_nbr=" << *request_sequence_number()
+ << ", resp_seq_nbr=" << *response_sequence_number()
+ << ", sender_last_asg_tsn=" << *sender_last_assigned_tsn();
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h
new file mode 100644
index 0000000000..6eb44e079f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_PARAMETER_OUTGOING_SSN_RESET_REQUEST_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_OUTGOING_SSN_RESET_REQUEST_PARAMETER_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "net/dcsctp/public/types.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.1
+struct OutgoingSSNResetRequestParameterConfig : ParameterConfig {
+ static constexpr int kType = 13;
+ static constexpr size_t kHeaderSize = 16;
+ static constexpr size_t kVariableLengthAlignment = 2;
+};
+
+class OutgoingSSNResetRequestParameter
+ : public Parameter,
+ public TLVTrait<OutgoingSSNResetRequestParameterConfig> {
+ public:
+ static constexpr int kType = OutgoingSSNResetRequestParameterConfig::kType;
+
+ explicit OutgoingSSNResetRequestParameter(
+ ReconfigRequestSN request_sequence_number,
+ ReconfigRequestSN response_sequence_number,
+ TSN sender_last_assigned_tsn,
+ std::vector<StreamID> stream_ids)
+ : request_sequence_number_(request_sequence_number),
+ response_sequence_number_(response_sequence_number),
+ sender_last_assigned_tsn_(sender_last_assigned_tsn),
+ stream_ids_(std::move(stream_ids)) {}
+
+ static absl::optional<OutgoingSSNResetRequestParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ ReconfigRequestSN request_sequence_number() const {
+ return request_sequence_number_;
+ }
+ ReconfigRequestSN response_sequence_number() const {
+ return response_sequence_number_;
+ }
+ TSN sender_last_assigned_tsn() const { return sender_last_assigned_tsn_; }
+ rtc::ArrayView<const StreamID> stream_ids() const { return stream_ids_; }
+
+ private:
+ static constexpr size_t kStreamIdSize = sizeof(uint16_t);
+
+ ReconfigRequestSN request_sequence_number_;
+ ReconfigRequestSN response_sequence_number_;
+ TSN sender_last_assigned_tsn_;
+ std::vector<StreamID> stream_ids_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_OUTGOING_SSN_RESET_REQUEST_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter_test.cc
new file mode 100644
index 0000000000..dae73c2fba
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter_test.cc
@@ -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.
+ */
+#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
+
+#include <cstdint>
+#include <type_traits>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/public/types.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+
+TEST(OutgoingSSNResetRequestParameterTest, SerializeAndDeserialize) {
+ OutgoingSSNResetRequestParameter parameter(
+ ReconfigRequestSN(1), ReconfigRequestSN(2), TSN(3),
+ {StreamID(4), StreamID(5), StreamID(6)});
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ OutgoingSSNResetRequestParameter deserialized,
+ OutgoingSSNResetRequestParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.request_sequence_number(), 1u);
+ EXPECT_EQ(*deserialized.response_sequence_number(), 2u);
+ EXPECT_EQ(*deserialized.sender_last_assigned_tsn(), 3u);
+ EXPECT_THAT(deserialized.stream_ids(),
+ ElementsAre(StreamID(4), StreamID(5), StreamID(6)));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.cc
new file mode 100644
index 0000000000..b3b2bffef7
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/parameter.h"
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/math.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/parameter/add_incoming_streams_request_parameter.h"
+#include "net/dcsctp/packet/parameter/add_outgoing_streams_request_parameter.h"
+#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
+#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
+#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
+#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
+#include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
+#include "net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h"
+#include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
+#include "net/dcsctp/packet/parameter/supported_extensions_parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+constexpr size_t kParameterHeaderSize = 4;
+
+Parameters::Builder& Parameters::Builder::Add(const Parameter& p) {
+ // https://tools.ietf.org/html/rfc4960#section-3.2.1
+ // "If the length of the parameter is not a multiple of 4 bytes, the sender
+ // pads the parameter at the end (i.e., after the Parameter Value field) with
+ // all zero bytes."
+ if (data_.size() % 4 != 0) {
+ data_.resize(RoundUpTo4(data_.size()));
+ }
+
+ p.SerializeTo(data_);
+ return *this;
+}
+
+std::vector<ParameterDescriptor> Parameters::descriptors() const {
+ rtc::ArrayView<const uint8_t> span(data_);
+ std::vector<ParameterDescriptor> result;
+ while (!span.empty()) {
+ BoundedByteReader<kParameterHeaderSize> header(span);
+ uint16_t type = header.Load16<0>();
+ uint16_t length = header.Load16<2>();
+ result.emplace_back(type, span.subview(0, length));
+ size_t length_with_padding = RoundUpTo4(length);
+ if (length_with_padding > span.size()) {
+ break;
+ }
+ span = span.subview(length_with_padding);
+ }
+ return result;
+}
+
+absl::optional<Parameters> Parameters::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ // Validate the parameter descriptors
+ rtc::ArrayView<const uint8_t> span(data);
+ while (!span.empty()) {
+ if (span.size() < kParameterHeaderSize) {
+ RTC_DLOG(LS_WARNING) << "Insufficient parameter length";
+ return absl::nullopt;
+ }
+ BoundedByteReader<kParameterHeaderSize> header(span);
+ uint16_t length = header.Load16<2>();
+ if (length < kParameterHeaderSize || length > span.size()) {
+ RTC_DLOG(LS_WARNING) << "Invalid parameter length field";
+ return absl::nullopt;
+ }
+ size_t length_with_padding = RoundUpTo4(length);
+ if (length_with_padding > span.size()) {
+ break;
+ }
+ span = span.subview(length_with_padding);
+ }
+ return Parameters(std::vector<uint8_t>(data.begin(), data.end()));
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.h
new file mode 100644
index 0000000000..e8fa67c8f7
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_PARAMETER_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_PARAMETER_H_
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "absl/algorithm/container.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+class Parameter {
+ public:
+ Parameter() {}
+ virtual ~Parameter() = default;
+
+ Parameter(const Parameter& other) = default;
+ Parameter& operator=(const Parameter& other) = default;
+
+ virtual void SerializeTo(std::vector<uint8_t>& out) const = 0;
+ virtual std::string ToString() const = 0;
+};
+
+struct ParameterDescriptor {
+ ParameterDescriptor(uint16_t type, rtc::ArrayView<const uint8_t> data)
+ : type(type), data(data) {}
+ uint16_t type;
+ rtc::ArrayView<const uint8_t> data;
+};
+
+class Parameters {
+ public:
+ class Builder {
+ public:
+ Builder() {}
+ Builder& Add(const Parameter& p);
+ Parameters Build() { return Parameters(std::move(data_)); }
+
+ private:
+ std::vector<uint8_t> data_;
+ };
+
+ static absl::optional<Parameters> Parse(rtc::ArrayView<const uint8_t> data);
+
+ Parameters() {}
+ Parameters(Parameters&& other) = default;
+ Parameters& operator=(Parameters&& other) = default;
+
+ rtc::ArrayView<const uint8_t> data() const { return data_; }
+ std::vector<ParameterDescriptor> descriptors() const;
+
+ template <typename P>
+ absl::optional<P> get() const {
+ static_assert(std::is_base_of<Parameter, P>::value,
+ "Template parameter not derived from Parameter");
+ for (const auto& p : descriptors()) {
+ if (p.type == P::kType) {
+ return P::Parse(p.data);
+ }
+ }
+ return absl::nullopt;
+ }
+
+ private:
+ explicit Parameters(std::vector<uint8_t> data) : data_(std::move(data)) {}
+ std::vector<uint8_t> data_;
+};
+
+struct ParameterConfig {
+ static constexpr int kTypeSizeInBytes = 2;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter_test.cc
new file mode 100644
index 0000000000..467e324592
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/parameter_test.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/parameter.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/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(ParameterTest, SerializeDeserializeParameter) {
+ Parameters parameters =
+ Parameters::Builder()
+ .Add(OutgoingSSNResetRequestParameter(ReconfigRequestSN(123),
+ ReconfigRequestSN(456),
+ TSN(789), {StreamID(42)}))
+ .Build();
+
+ rtc::ArrayView<const uint8_t> serialized = parameters.data();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(Parameters parsed, Parameters::Parse(serialized));
+ auto descriptors = parsed.descriptors();
+ ASSERT_THAT(descriptors, SizeIs(1));
+ EXPECT_THAT(descriptors[0].type, OutgoingSSNResetRequestParameter::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ OutgoingSSNResetRequestParameter parsed_param,
+ OutgoingSSNResetRequestParameter::Parse(descriptors[0].data));
+ EXPECT_EQ(*parsed_param.request_sequence_number(), 123u);
+ EXPECT_EQ(*parsed_param.response_sequence_number(), 456u);
+ EXPECT_EQ(*parsed_param.sender_last_assigned_tsn(), 789u);
+ EXPECT_THAT(parsed_param.stream_ids(), ElementsAre(StreamID(42)));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.cc
new file mode 100644
index 0000000000..fafb204acc
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.4
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 16 | Parameter Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Response Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Result |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Sender's Next TSN (optional) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Receiver's Next TSN (optional) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int ReconfigurationResponseParameter::kType;
+
+absl::string_view ToString(ReconfigurationResponseParameter::Result result) {
+ switch (result) {
+ case ReconfigurationResponseParameter::Result::kSuccessNothingToDo:
+ return "Success: nothing to do";
+ case ReconfigurationResponseParameter::Result::kSuccessPerformed:
+ return "Success: performed";
+ case ReconfigurationResponseParameter::Result::kDenied:
+ return "Denied";
+ case ReconfigurationResponseParameter::Result::kErrorWrongSSN:
+ return "Error: wrong ssn";
+ case ReconfigurationResponseParameter::Result::
+ kErrorRequestAlreadyInProgress:
+ return "Error: request already in progress";
+ case ReconfigurationResponseParameter::Result::kErrorBadSequenceNumber:
+ return "Error: bad sequence number";
+ case ReconfigurationResponseParameter::Result::kInProgress:
+ return "In progress";
+ }
+}
+
+absl::optional<ReconfigurationResponseParameter>
+ReconfigurationResponseParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+
+ ReconfigRequestSN response_sequence_number(reader->Load32<4>());
+ Result result;
+ uint32_t result_nbr = reader->Load32<8>();
+ switch (result_nbr) {
+ case 0:
+ result = ReconfigurationResponseParameter::Result::kSuccessNothingToDo;
+ break;
+ case 1:
+ result = ReconfigurationResponseParameter::Result::kSuccessPerformed;
+ break;
+ case 2:
+ result = ReconfigurationResponseParameter::Result::kDenied;
+ break;
+ case 3:
+ result = ReconfigurationResponseParameter::Result::kErrorWrongSSN;
+ break;
+ case 4:
+ result = ReconfigurationResponseParameter::Result::
+ kErrorRequestAlreadyInProgress;
+ break;
+ case 5:
+ result =
+ ReconfigurationResponseParameter::Result::kErrorBadSequenceNumber;
+ break;
+ case 6:
+ result = ReconfigurationResponseParameter::Result::kInProgress;
+ break;
+ default:
+ RTC_DLOG(LS_WARNING) << "Invalid reconfig response result: "
+ << result_nbr;
+ return absl::nullopt;
+ }
+
+ if (reader->variable_data().empty()) {
+ return ReconfigurationResponseParameter(response_sequence_number, result);
+ } else if (reader->variable_data_size() != kNextTsnHeaderSize) {
+ RTC_DLOG(LS_WARNING) << "Invalid parameter size";
+ return absl::nullopt;
+ }
+
+ BoundedByteReader<kNextTsnHeaderSize> sub_reader =
+ reader->sub_reader<kNextTsnHeaderSize>(0);
+
+ TSN sender_next_tsn(sub_reader.Load32<0>());
+ TSN receiver_next_tsn(sub_reader.Load32<4>());
+
+ return ReconfigurationResponseParameter(response_sequence_number, result,
+ sender_next_tsn, receiver_next_tsn);
+}
+
+void ReconfigurationResponseParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ size_t variable_size =
+ (sender_next_tsn().has_value() ? kNextTsnHeaderSize : 0);
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, variable_size);
+
+ writer.Store32<4>(*response_sequence_number_);
+ uint32_t result_nbr =
+ static_cast<std::underlying_type<Result>::type>(result_);
+ writer.Store32<8>(result_nbr);
+
+ if (sender_next_tsn().has_value()) {
+ BoundedByteWriter<kNextTsnHeaderSize> sub_writer =
+ writer.sub_writer<kNextTsnHeaderSize>(0);
+
+ sub_writer.Store32<0>(sender_next_tsn_.has_value() ? **sender_next_tsn_
+ : 0);
+ sub_writer.Store32<4>(receiver_next_tsn_.has_value() ? **receiver_next_tsn_
+ : 0);
+ }
+}
+
+std::string ReconfigurationResponseParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Re-configuration Response, resp_seq_nbr="
+ << *response_sequence_number();
+ return sb.Release();
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.h
new file mode 100644
index 0000000000..c5a68acb33
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_PARAMETER_RECONFIGURATION_RESPONSE_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_RECONFIGURATION_RESPONSE_PARAMETER_H_
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.4
+struct ReconfigurationResponseParameterConfig : ParameterConfig {
+ static constexpr int kType = 16;
+ static constexpr size_t kHeaderSize = 12;
+ static constexpr size_t kVariableLengthAlignment = 4;
+};
+
+class ReconfigurationResponseParameter
+ : public Parameter,
+ public TLVTrait<ReconfigurationResponseParameterConfig> {
+ public:
+ static constexpr int kType = ReconfigurationResponseParameterConfig::kType;
+
+ enum class Result {
+ kSuccessNothingToDo = 0,
+ kSuccessPerformed = 1,
+ kDenied = 2,
+ kErrorWrongSSN = 3,
+ kErrorRequestAlreadyInProgress = 4,
+ kErrorBadSequenceNumber = 5,
+ kInProgress = 6,
+ };
+
+ ReconfigurationResponseParameter(ReconfigRequestSN response_sequence_number,
+ Result result)
+ : response_sequence_number_(response_sequence_number),
+ result_(result),
+ sender_next_tsn_(absl::nullopt),
+ receiver_next_tsn_(absl::nullopt) {}
+
+ explicit ReconfigurationResponseParameter(
+ ReconfigRequestSN response_sequence_number,
+ Result result,
+ TSN sender_next_tsn,
+ TSN receiver_next_tsn)
+ : response_sequence_number_(response_sequence_number),
+ result_(result),
+ sender_next_tsn_(sender_next_tsn),
+ receiver_next_tsn_(receiver_next_tsn) {}
+
+ static absl::optional<ReconfigurationResponseParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ ReconfigRequestSN response_sequence_number() const {
+ return response_sequence_number_;
+ }
+ Result result() const { return result_; }
+ absl::optional<TSN> sender_next_tsn() const { return sender_next_tsn_; }
+ absl::optional<TSN> receiver_next_tsn() const { return receiver_next_tsn_; }
+
+ private:
+ static constexpr size_t kNextTsnHeaderSize = 8;
+ ReconfigRequestSN response_sequence_number_;
+ Result result_;
+ absl::optional<TSN> sender_next_tsn_;
+ absl::optional<TSN> receiver_next_tsn_;
+};
+
+absl::string_view ToString(ReconfigurationResponseParameter::Result result);
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_RECONFIGURATION_RESPONSE_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter_test.cc
new file mode 100644
index 0000000000..8125d93cd0
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/reconfiguration_response_parameter_test.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(ReconfigurationResponseParameterTest, SerializeAndDeserializeFirstForm) {
+ ReconfigurationResponseParameter parameter(
+ ReconfigRequestSN(1),
+ ReconfigurationResponseParameter::Result::kSuccessPerformed);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ ReconfigurationResponseParameter deserialized,
+ ReconfigurationResponseParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.response_sequence_number(), 1u);
+ EXPECT_EQ(deserialized.result(),
+ ReconfigurationResponseParameter::Result::kSuccessPerformed);
+ EXPECT_EQ(deserialized.sender_next_tsn(), absl::nullopt);
+ EXPECT_EQ(deserialized.receiver_next_tsn(), absl::nullopt);
+}
+
+TEST(ReconfigurationResponseParameterTest,
+ SerializeAndDeserializeFirstFormSecondForm) {
+ ReconfigurationResponseParameter parameter(
+ ReconfigRequestSN(1),
+ ReconfigurationResponseParameter::Result::kSuccessPerformed, TSN(2),
+ TSN(3));
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ ReconfigurationResponseParameter deserialized,
+ ReconfigurationResponseParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.response_sequence_number(), 1u);
+ EXPECT_EQ(deserialized.result(),
+ ReconfigurationResponseParameter::Result::kSuccessPerformed);
+ EXPECT_TRUE(deserialized.sender_next_tsn().has_value());
+ EXPECT_EQ(**deserialized.sender_next_tsn(), 2u);
+ EXPECT_TRUE(deserialized.receiver_next_tsn().has_value());
+ EXPECT_EQ(**deserialized.receiver_next_tsn(), 3u);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.cc
new file mode 100644
index 0000000000..d656e0db8f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.3
+
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 15 | Parameter Length = 8 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Re-configuration Request Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int SSNTSNResetRequestParameter::kType;
+
+absl::optional<SSNTSNResetRequestParameter> SSNTSNResetRequestParameter::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ ReconfigRequestSN request_sequence_number(reader->Load32<4>());
+
+ return SSNTSNResetRequestParameter(request_sequence_number);
+}
+
+void SSNTSNResetRequestParameter::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out);
+ writer.Store32<4>(*request_sequence_number_);
+}
+
+std::string SSNTSNResetRequestParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "SSN/TSN Reset Request, req_seq_nbr=" << *request_sequence_number();
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h
new file mode 100644
index 0000000000..e31d7ebe8f
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef NET_DCSCTP_PACKET_PARAMETER_SSN_TSN_RESET_REQUEST_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_SSN_TSN_RESET_REQUEST_PARAMETER_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc6525#section-4.3
+struct SSNTSNResetRequestParameterConfig : ParameterConfig {
+ static constexpr int kType = 15;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr size_t kVariableLengthAlignment = 0;
+};
+
+class SSNTSNResetRequestParameter
+ : public Parameter,
+ public TLVTrait<SSNTSNResetRequestParameterConfig> {
+ public:
+ static constexpr int kType = SSNTSNResetRequestParameterConfig::kType;
+
+ explicit SSNTSNResetRequestParameter(
+ ReconfigRequestSN request_sequence_number)
+ : request_sequence_number_(request_sequence_number) {}
+
+ static absl::optional<SSNTSNResetRequestParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ ReconfigRequestSN request_sequence_number() const {
+ return request_sequence_number_;
+ }
+
+ private:
+ ReconfigRequestSN request_sequence_number_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_SSN_TSN_RESET_REQUEST_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter_test.cc
new file mode 100644
index 0000000000..eeb973cbcb
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter_test.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/ssn_tsn_reset_request_parameter.h"
+
+#include <stdint.h>
+
+#include <type_traits>
+#include <vector>
+
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+
+TEST(SSNTSNResetRequestParameterTest, SerializeAndDeserialize) {
+ SSNTSNResetRequestParameter parameter(ReconfigRequestSN(1));
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SSNTSNResetRequestParameter deserialized,
+ SSNTSNResetRequestParameter::Parse(serialized));
+
+ EXPECT_EQ(*deserialized.request_sequence_number(), 1u);
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.cc
new file mode 100644
index 0000000000..9777aa6667
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.3.1
+
+constexpr int StateCookieParameter::kType;
+
+absl::optional<StateCookieParameter> StateCookieParameter::Parse(
+ rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+ return StateCookieParameter(reader->variable_data());
+}
+
+void StateCookieParameter::SerializeTo(std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, data_.size());
+ writer.CopyToVariableData(data_);
+}
+
+std::string StateCookieParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "State Cookie parameter (cookie_length=" << data_.size() << ")";
+ return sb.Release();
+}
+
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.h
new file mode 100644
index 0000000000..f4355495e2
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter.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_PARAMETER_STATE_COOKIE_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_STATE_COOKIE_PARAMETER_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc4960#section-3.3.3.1
+struct StateCookieParameterConfig : ParameterConfig {
+ static constexpr int kType = 7;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class StateCookieParameter : public Parameter,
+ public TLVTrait<StateCookieParameterConfig> {
+ public:
+ static constexpr int kType = StateCookieParameterConfig::kType;
+
+ explicit StateCookieParameter(rtc::ArrayView<const uint8_t> data)
+ : data_(data.begin(), data.end()) {}
+
+ static absl::optional<StateCookieParameter> 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> data() const { return data_; }
+
+ private:
+ std::vector<uint8_t> data_;
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_STATE_COOKIE_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter_test.cc
new file mode 100644
index 0000000000..bcca38b586
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/state_cookie_parameter_test.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/state_cookie_parameter.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(StateCookieParameterTest, SerializeAndDeserialize) {
+ uint8_t cookie[] = {1, 2, 3};
+ StateCookieParameter parameter(cookie);
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(StateCookieParameter deserialized,
+ StateCookieParameter::Parse(serialized));
+
+ EXPECT_THAT(deserialized.data(), ElementsAre(1, 2, 3));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.cc
new file mode 100644
index 0000000000..6a8fb214de
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.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/parameter/supported_extensions_parameter.h"
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#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/strings/string_builder.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc5061#section-4.2.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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Parameter Type = 0x8008 | Parameter Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | CHUNK TYPE 1 | CHUNK TYPE 2 | CHUNK TYPE 3 | CHUNK TYPE 4 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | .... |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | CHUNK TYPE N | PAD | PAD | PAD |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+constexpr int SupportedExtensionsParameter::kType;
+
+absl::optional<SupportedExtensionsParameter>
+SupportedExtensionsParameter::Parse(rtc::ArrayView<const uint8_t> data) {
+ absl::optional<BoundedByteReader<kHeaderSize>> reader = ParseTLV(data);
+ if (!reader.has_value()) {
+ return absl::nullopt;
+ }
+
+ std::vector<uint8_t> chunk_types(reader->variable_data().begin(),
+ reader->variable_data().end());
+ return SupportedExtensionsParameter(std::move(chunk_types));
+}
+
+void SupportedExtensionsParameter::SerializeTo(
+ std::vector<uint8_t>& out) const {
+ BoundedByteWriter<kHeaderSize> writer = AllocateTLV(out, chunk_types_.size());
+ writer.CopyToVariableData(chunk_types_);
+}
+
+std::string SupportedExtensionsParameter::ToString() const {
+ rtc::StringBuilder sb;
+ sb << "Supported Extensions (" << StrJoin(chunk_types_, ", ") << ")";
+ return sb.Release();
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.h b/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.h
new file mode 100644
index 0000000000..5689fd8035
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter.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_PARAMETER_SUPPORTED_EXTENSIONS_PARAMETER_H_
+#define NET_DCSCTP_PACKET_PARAMETER_SUPPORTED_EXTENSIONS_PARAMETER_H_
+#include <stddef.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+
+namespace dcsctp {
+
+// https://tools.ietf.org/html/rfc5061#section-4.2.7
+struct SupportedExtensionsParameterConfig : ParameterConfig {
+ static constexpr int kType = 0x8008;
+ static constexpr size_t kHeaderSize = 4;
+ static constexpr size_t kVariableLengthAlignment = 1;
+};
+
+class SupportedExtensionsParameter
+ : public Parameter,
+ public TLVTrait<SupportedExtensionsParameterConfig> {
+ public:
+ static constexpr int kType = SupportedExtensionsParameterConfig::kType;
+
+ explicit SupportedExtensionsParameter(std::vector<uint8_t> chunk_types)
+ : chunk_types_(std::move(chunk_types)) {}
+
+ static absl::optional<SupportedExtensionsParameter> Parse(
+ rtc::ArrayView<const uint8_t> data);
+
+ void SerializeTo(std::vector<uint8_t>& out) const override;
+ std::string ToString() const override;
+
+ bool supports(uint8_t chunk_type) const {
+ return std::find(chunk_types_.begin(), chunk_types_.end(), chunk_type) !=
+ chunk_types_.end();
+ }
+
+ rtc::ArrayView<const uint8_t> chunk_types() const { return chunk_types_; }
+
+ private:
+ std::vector<uint8_t> chunk_types_;
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_PARAMETER_SUPPORTED_EXTENSIONS_PARAMETER_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter_test.cc b/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter_test.cc
new file mode 100644
index 0000000000..c870af2e70
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/parameter/supported_extensions_parameter_test.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "net/dcsctp/packet/parameter/supported_extensions_parameter.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(SupportedExtensionsParameterTest, SerializeAndDeserialize) {
+ SupportedExtensionsParameter parameter({1, 2, 3});
+
+ std::vector<uint8_t> serialized;
+ parameter.SerializeTo(serialized);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SupportedExtensionsParameter deserialized,
+ SupportedExtensionsParameter::Parse(serialized));
+
+ EXPECT_THAT(deserialized.chunk_types(), ElementsAre(1, 2, 3));
+ EXPECT_TRUE(deserialized.supports(1));
+ EXPECT_TRUE(deserialized.supports(2));
+ EXPECT_TRUE(deserialized.supports(3));
+ EXPECT_FALSE(deserialized.supports(4));
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc
new file mode 100644
index 0000000000..cc66235122
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.cc
@@ -0,0 +1,184 @@
+/*
+ * 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/sctp_packet.h"
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "net/dcsctp/common/math.h"
+#include "net/dcsctp/packet/bounded_byte_reader.h"
+#include "net/dcsctp/packet/bounded_byte_writer.h"
+#include "net/dcsctp/packet/chunk/chunk.h"
+#include "net/dcsctp/packet/crc32c.h"
+#include "net/dcsctp/public/dcsctp_options.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/strings/string_format.h"
+
+namespace dcsctp {
+namespace {
+constexpr size_t kMaxUdpPacketSize = 65535;
+constexpr size_t kChunkTlvHeaderSize = 4;
+constexpr size_t kExpectedDescriptorCount = 4;
+} // namespace
+
+/*
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Port Number | Destination Port Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Verification Tag |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+SctpPacket::Builder::Builder(VerificationTag verification_tag,
+ const DcSctpOptions& options)
+ : verification_tag_(verification_tag),
+ source_port_(options.local_port),
+ dest_port_(options.remote_port),
+ max_packet_size_(RoundDownTo4(options.mtu)) {}
+
+SctpPacket::Builder& SctpPacket::Builder::Add(const Chunk& chunk) {
+ if (out_.empty()) {
+ out_.reserve(max_packet_size_);
+ out_.resize(SctpPacket::kHeaderSize);
+ BoundedByteWriter<kHeaderSize> buffer(out_);
+ buffer.Store16<0>(source_port_);
+ buffer.Store16<2>(dest_port_);
+ buffer.Store32<4>(*verification_tag_);
+ // Checksum is at offset 8 - written when calling Build();
+ }
+ RTC_DCHECK(IsDivisibleBy4(out_.size()));
+
+ chunk.SerializeTo(out_);
+ if (out_.size() % 4 != 0) {
+ out_.resize(RoundUpTo4(out_.size()));
+ }
+
+ RTC_DCHECK(out_.size() <= max_packet_size_)
+ << "Exceeded max size, data=" << out_.size()
+ << ", max_size=" << max_packet_size_;
+ return *this;
+}
+
+size_t SctpPacket::Builder::bytes_remaining() const {
+ if (out_.empty()) {
+ // The packet header (CommonHeader) hasn't been written yet:
+ return max_packet_size_ - kHeaderSize;
+ } else if (out_.size() > max_packet_size_) {
+ RTC_DCHECK_NOTREACHED() << "Exceeded max size, data=" << out_.size()
+ << ", max_size=" << max_packet_size_;
+ return 0;
+ }
+ return max_packet_size_ - out_.size();
+}
+
+std::vector<uint8_t> SctpPacket::Builder::Build() {
+ std::vector<uint8_t> out;
+ out_.swap(out);
+
+ if (!out.empty()) {
+ uint32_t crc = GenerateCrc32C(out);
+ BoundedByteWriter<kHeaderSize>(out).Store32<8>(crc);
+ }
+
+ RTC_DCHECK(out.size() <= max_packet_size_)
+ << "Exceeded max size, data=" << out.size()
+ << ", max_size=" << max_packet_size_;
+
+ return out;
+}
+
+absl::optional<SctpPacket> SctpPacket::Parse(
+ rtc::ArrayView<const uint8_t> data,
+ bool disable_checksum_verification) {
+ if (data.size() < kHeaderSize + kChunkTlvHeaderSize ||
+ data.size() > kMaxUdpPacketSize) {
+ RTC_DLOG(LS_WARNING) << "Invalid packet size";
+ return absl::nullopt;
+ }
+
+ BoundedByteReader<kHeaderSize> reader(data);
+
+ CommonHeader common_header;
+ common_header.source_port = reader.Load16<0>();
+ common_header.destination_port = reader.Load16<2>();
+ common_header.verification_tag = VerificationTag(reader.Load32<4>());
+ common_header.checksum = reader.Load32<8>();
+
+ // Create a copy of the packet, which will be held by this object.
+ std::vector<uint8_t> data_copy =
+ std::vector<uint8_t>(data.begin(), data.end());
+
+ // Verify the checksum. The checksum field must be zero when that's done.
+ BoundedByteWriter<kHeaderSize>(data_copy).Store32<8>(0);
+ uint32_t calculated_checksum = GenerateCrc32C(data_copy);
+ if (!disable_checksum_verification &&
+ calculated_checksum != common_header.checksum) {
+ RTC_DLOG(LS_WARNING) << rtc::StringFormat(
+ "Invalid packet checksum, packet_checksum=0x%08x, "
+ "calculated_checksum=0x%08x",
+ common_header.checksum, calculated_checksum);
+ return absl::nullopt;
+ }
+ // Restore the checksum in the header.
+ BoundedByteWriter<kHeaderSize>(data_copy).Store32<8>(common_header.checksum);
+
+ // Validate and parse the chunk headers in the message.
+ /*
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Chunk Type | Chunk Flags | Chunk Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+ std::vector<ChunkDescriptor> descriptors;
+ descriptors.reserve(kExpectedDescriptorCount);
+ rtc::ArrayView<const uint8_t> descriptor_data =
+ rtc::ArrayView<const uint8_t>(data_copy).subview(kHeaderSize);
+ while (!descriptor_data.empty()) {
+ if (descriptor_data.size() < kChunkTlvHeaderSize) {
+ RTC_DLOG(LS_WARNING) << "Too small chunk";
+ return absl::nullopt;
+ }
+ BoundedByteReader<kChunkTlvHeaderSize> chunk_header(descriptor_data);
+ uint8_t type = chunk_header.Load8<0>();
+ uint8_t flags = chunk_header.Load8<1>();
+ uint16_t length = chunk_header.Load16<2>();
+ uint16_t padded_length = RoundUpTo4(length);
+ if (padded_length > descriptor_data.size()) {
+ RTC_DLOG(LS_WARNING) << "Too large chunk. length=" << length
+ << ", remaining=" << descriptor_data.size();
+ return absl::nullopt;
+ } else if (padded_length < kChunkTlvHeaderSize) {
+ RTC_DLOG(LS_WARNING) << "Too small chunk. length=" << length;
+ return absl::nullopt;
+ }
+ descriptors.emplace_back(type, flags,
+ descriptor_data.subview(0, padded_length));
+ descriptor_data = descriptor_data.subview(padded_length);
+ }
+
+ // Note that iterators (and pointer) are guaranteed to be stable when moving a
+ // std::vector, and `descriptors` have pointers to within `data_copy`.
+ return SctpPacket(common_header, std::move(data_copy),
+ std::move(descriptors));
+}
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.h b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.h
new file mode 100644
index 0000000000..4c6234e0c9
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet.h
@@ -0,0 +1,121 @@
+/*
+ * 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_SCTP_PACKET_H_
+#define NET_DCSCTP_PACKET_SCTP_PACKET_H_
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.h"
+#include "net/dcsctp/packet/chunk/chunk.h"
+#include "net/dcsctp/public/dcsctp_options.h"
+
+namespace dcsctp {
+
+// The "Common Header", which every SCTP packet starts with, and is described in
+// https://tools.ietf.org/html/rfc4960#section-3.1.
+struct CommonHeader {
+ uint16_t source_port;
+ uint16_t destination_port;
+ VerificationTag verification_tag;
+ uint32_t checksum;
+};
+
+// Represents an immutable (received or to-be-sent) SCTP packet.
+class SctpPacket {
+ public:
+ static constexpr size_t kHeaderSize = 12;
+
+ struct ChunkDescriptor {
+ ChunkDescriptor(uint8_t type,
+ uint8_t flags,
+ rtc::ArrayView<const uint8_t> data)
+ : type(type), flags(flags), data(data) {}
+ uint8_t type;
+ uint8_t flags;
+ rtc::ArrayView<const uint8_t> data;
+ };
+
+ SctpPacket(SctpPacket&& other) = default;
+ SctpPacket& operator=(SctpPacket&& other) = default;
+ SctpPacket(const SctpPacket&) = delete;
+ SctpPacket& operator=(const SctpPacket&) = delete;
+
+ // Used for building SctpPacket, as those are immutable.
+ class Builder {
+ public:
+ Builder(VerificationTag verification_tag, const DcSctpOptions& options);
+
+ Builder(Builder&& other) = default;
+ Builder& operator=(Builder&& other) = default;
+
+ // Adds a chunk to the to-be-built SCTP packet.
+ Builder& Add(const Chunk& chunk);
+
+ // The number of bytes remaining in the packet for chunk storage until the
+ // packet reaches its maximum size.
+ size_t bytes_remaining() const;
+
+ // Indicates if any packets have been added to the builder.
+ bool empty() const { return out_.empty(); }
+
+ // Returns the payload of the build SCTP packet. The Builder will be cleared
+ // after having called this function, and can be used to build a new packet.
+ std::vector<uint8_t> Build();
+
+ private:
+ VerificationTag verification_tag_;
+ uint16_t source_port_;
+ uint16_t dest_port_;
+ // The maximum packet size is always even divisible by four, as chunks are
+ // always padded to a size even divisible by four.
+ size_t max_packet_size_;
+ std::vector<uint8_t> out_;
+ };
+
+ // Parses `data` as an SCTP packet and returns it if it validates.
+ static absl::optional<SctpPacket> Parse(
+ rtc::ArrayView<const uint8_t> data,
+ bool disable_checksum_verification = false);
+
+ // Returns the SCTP common header.
+ const CommonHeader& common_header() const { return common_header_; }
+
+ // Returns the chunks (types and offsets) within the packet.
+ rtc::ArrayView<const ChunkDescriptor> descriptors() const {
+ return descriptors_;
+ }
+
+ private:
+ SctpPacket(const CommonHeader& common_header,
+ std::vector<uint8_t> data,
+ std::vector<ChunkDescriptor> descriptors)
+ : common_header_(common_header),
+ data_(std::move(data)),
+ descriptors_(std::move(descriptors)) {}
+
+ CommonHeader common_header_;
+
+ // As the `descriptors_` refer to offset within data, and since SctpPacket is
+ // movable, `data` needs to be pointer stable, which it is according to
+ // http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#2321
+ std::vector<uint8_t> data_;
+ // The chunks and their offsets within `data_ `.
+ std::vector<ChunkDescriptor> descriptors_;
+};
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_SCTP_PACKET_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc
new file mode 100644
index 0000000000..7438315eec
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/sctp_packet_test.cc
@@ -0,0 +1,342 @@
+/*
+ * 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/sctp_packet.h"
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+#include "api/array_view.h"
+#include "net/dcsctp/common/internal_types.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/data_chunk.h"
+#include "net/dcsctp/packet/chunk/init_chunk.h"
+#include "net/dcsctp/packet/chunk/sack_chunk.h"
+#include "net/dcsctp/packet/error_cause/error_cause.h"
+#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
+#include "net/dcsctp/packet/parameter/parameter.h"
+#include "net/dcsctp/packet/tlv_trait.h"
+#include "net/dcsctp/public/dcsctp_options.h"
+#include "net/dcsctp/testing/testing_macros.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::SizeIs;
+
+constexpr VerificationTag kVerificationTag = VerificationTag(0x12345678);
+
+TEST(SctpPacketTest, DeserializeSimplePacketFromCapture) {
+ /*
+ Stream Control Transmission Protocol, Src Port: 5000 (5000), Dst Port: 5000
+ (5000) Source port: 5000 Destination port: 5000 Verification tag: 0x00000000
+ [Association index: 1]
+ Checksum: 0xaa019d33 [unverified]
+ [Checksum Status: Unverified]
+ INIT chunk (Outbound streams: 1000, inbound streams: 1000)
+ Chunk type: INIT (1)
+ Chunk flags: 0x00
+ Chunk length: 90
+ Initiate tag: 0x0eddca08
+ Advertised receiver window credit (a_rwnd): 131072
+ Number of outbound streams: 1000
+ Number of inbound streams: 1000
+ Initial TSN: 1426601527
+ 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: c5a86155090e6f420050634cc8d6b908dfd53e17c99cb143…
+ 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) Chunk padding: 0000
+ */
+
+ uint8_t data[] = {
+ 0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x01, 0x9d, 0x33,
+ 0x01, 0x00, 0x00, 0x5a, 0x0e, 0xdd, 0xca, 0x08, 0x00, 0x02, 0x00, 0x00,
+ 0x03, 0xe8, 0x03, 0xe8, 0x55, 0x08, 0x36, 0x37, 0x80, 0x00, 0x00, 0x04,
+ 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80,
+ 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0xc5, 0xa8, 0x61, 0x55,
+ 0x09, 0x0e, 0x6f, 0x42, 0x00, 0x50, 0x63, 0x4c, 0xc8, 0xd6, 0xb9, 0x08,
+ 0xdf, 0xd5, 0x3e, 0x17, 0xc9, 0x9c, 0xb1, 0x43, 0x28, 0x4e, 0xaf, 0x64,
+ 0x68, 0x2a, 0xc2, 0x97, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(data));
+ EXPECT_EQ(packet.common_header().source_port, 5000);
+ EXPECT_EQ(packet.common_header().destination_port, 5000);
+ EXPECT_EQ(packet.common_header().verification_tag, VerificationTag(0));
+ EXPECT_EQ(packet.common_header().checksum, 0xaa019d33);
+
+ EXPECT_THAT(packet.descriptors(), SizeIs(1));
+ EXPECT_EQ(packet.descriptors()[0].type, InitChunk::kType);
+ ASSERT_HAS_VALUE_AND_ASSIGN(InitChunk init,
+ InitChunk::Parse(packet.descriptors()[0].data));
+ EXPECT_EQ(init.initial_tsn(), TSN(1426601527));
+}
+
+TEST(SctpPacketTest, DeserializePacketWithTwoChunks) {
+ /*
+ Stream Control Transmission Protocol, Src Port: 1234 (1234),
+ Dst Port: 4321 (4321)
+ Source port: 1234
+ Destination port: 4321
+ Verification tag: 0x697e3a4e
+ [Association index: 3]
+ Checksum: 0xc06e8b36 [unverified]
+ [Checksum Status: Unverified]
+ COOKIE_ACK chunk
+ Chunk type: COOKIE_ACK (11)
+ Chunk flags: 0x00
+ Chunk length: 4
+ SACK chunk (Cumulative TSN: 2930332242, a_rwnd: 131072,
+ gaps: 0, duplicate TSNs: 0)
+ Chunk type: SACK (3)
+ Chunk flags: 0x00
+ Chunk length: 16
+ Cumulative TSN ACK: 2930332242
+ Advertised receiver window credit (a_rwnd): 131072
+ Number of gap acknowledgement blocks: 0
+ Number of duplicated TSNs: 0
+ */
+
+ uint8_t data[] = {0x04, 0xd2, 0x10, 0xe1, 0x69, 0x7e, 0x3a, 0x4e,
+ 0xc0, 0x6e, 0x8b, 0x36, 0x0b, 0x00, 0x00, 0x04,
+ 0x03, 0x00, 0x00, 0x10, 0xae, 0xa9, 0x52, 0x52,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(data));
+ EXPECT_EQ(packet.common_header().source_port, 1234);
+ EXPECT_EQ(packet.common_header().destination_port, 4321);
+ EXPECT_EQ(packet.common_header().verification_tag,
+ VerificationTag(0x697e3a4eu));
+ EXPECT_EQ(packet.common_header().checksum, 0xc06e8b36u);
+
+ EXPECT_THAT(packet.descriptors(), SizeIs(2));
+ EXPECT_EQ(packet.descriptors()[0].type, CookieAckChunk::kType);
+ EXPECT_EQ(packet.descriptors()[1].type, SackChunk::kType);
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ CookieAckChunk cookie_ack,
+ CookieAckChunk::Parse(packet.descriptors()[0].data));
+ ASSERT_HAS_VALUE_AND_ASSIGN(SackChunk sack,
+ SackChunk::Parse(packet.descriptors()[1].data));
+}
+
+TEST(SctpPacketTest, DeserializePacketWithWrongChecksum) {
+ /*
+ Stream Control Transmission Protocol, Src Port: 5000 (5000),
+ Dst Port: 5000 (5000)
+ Source port: 5000
+ Destination port: 5000
+ Verification tag: 0x0eddca08
+ [Association index: 1]
+ Checksum: 0x2a81f531 [unverified]
+ [Checksum Status: Unverified]
+ SACK chunk (Cumulative TSN: 1426601536, a_rwnd: 131072,
+ gaps: 0, duplicate TSNs: 0)
+ Chunk type: SACK (3)
+ Chunk flags: 0x00
+ Chunk length: 16
+ Cumulative TSN ACK: 1426601536
+ Advertised receiver window credit (a_rwnd): 131072
+ Number of gap acknowledgement blocks: 0
+ Number of duplicated TSNs: 0
+ */
+
+ uint8_t data[] = {0x13, 0x88, 0x13, 0x88, 0x0e, 0xdd, 0xca, 0x08, 0x2a, 0x81,
+ 0xf5, 0x31, 0x03, 0x00, 0x00, 0x10, 0x55, 0x08, 0x36, 0x40,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ EXPECT_FALSE(SctpPacket::Parse(data).has_value());
+}
+
+TEST(SctpPacketTest, DeserializePacketDontValidateChecksum) {
+ /*
+ Stream Control Transmission Protocol, Src Port: 5000 (5000),
+ Dst Port: 5000 (5000)
+ Source port: 5000
+ Destination port: 5000
+ Verification tag: 0x0eddca08
+ [Association index: 1]
+ Checksum: 0x2a81f531 [unverified]
+ [Checksum Status: Unverified]
+ SACK chunk (Cumulative TSN: 1426601536, a_rwnd: 131072,
+ gaps: 0, duplicate TSNs: 0)
+ Chunk type: SACK (3)
+ Chunk flags: 0x00
+ Chunk length: 16
+ Cumulative TSN ACK: 1426601536
+ Advertised receiver window credit (a_rwnd): 131072
+ Number of gap acknowledgement blocks: 0
+ Number of duplicated TSNs: 0
+ */
+
+ uint8_t data[] = {0x13, 0x88, 0x13, 0x88, 0x0e, 0xdd, 0xca, 0x08, 0x2a, 0x81,
+ 0xf5, 0x31, 0x03, 0x00, 0x00, 0x10, 0x55, 0x08, 0x36, 0x40,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ SctpPacket packet,
+ SctpPacket::Parse(data, /*disable_checksum_verification=*/true));
+ EXPECT_EQ(packet.common_header().source_port, 5000);
+ EXPECT_EQ(packet.common_header().destination_port, 5000);
+ EXPECT_EQ(packet.common_header().verification_tag,
+ VerificationTag(0x0eddca08u));
+ EXPECT_EQ(packet.common_header().checksum, 0x2a81f531u);
+}
+
+TEST(SctpPacketTest, SerializeAndDeserializeSingleChunk) {
+ SctpPacket::Builder b(kVerificationTag, {});
+ InitChunk init(/*initiate_tag=*/VerificationTag(123), /*a_rwnd=*/456,
+ /*nbr_outbound_streams=*/65535,
+ /*nbr_inbound_streams=*/65534, /*initial_tsn=*/TSN(789),
+ /*parameters=*/Parameters());
+
+ b.Add(init);
+ std::vector<uint8_t> serialized = b.Build();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(serialized));
+
+ EXPECT_EQ(packet.common_header().verification_tag, kVerificationTag);
+
+ ASSERT_THAT(packet.descriptors(), SizeIs(1));
+ EXPECT_EQ(packet.descriptors()[0].type, InitChunk::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(InitChunk deserialized,
+ InitChunk::Parse(packet.descriptors()[0].data));
+ EXPECT_EQ(deserialized.initiate_tag(), VerificationTag(123));
+ 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(789));
+}
+
+TEST(SctpPacketTest, SerializeAndDeserializeThreeChunks) {
+ SctpPacket::Builder b(kVerificationTag, {});
+ b.Add(SackChunk(/*cumulative_tsn_ack=*/TSN(999), /*a_rwnd=*/456,
+ {SackChunk::GapAckBlock(2, 3)},
+ /*duplicate_tsns=*/{TSN(1), TSN(2), TSN(3)}));
+ b.Add(DataChunk(TSN(123), StreamID(456), SSN(789), PPID(9090),
+ /*payload=*/{1, 2, 3, 4, 5},
+ /*options=*/{}));
+ b.Add(DataChunk(TSN(124), StreamID(654), SSN(987), PPID(909),
+ /*payload=*/{5, 4, 3, 3, 1},
+ /*options=*/{}));
+
+ std::vector<uint8_t> serialized = b.Build();
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(serialized));
+
+ EXPECT_EQ(packet.common_header().verification_tag, kVerificationTag);
+
+ ASSERT_THAT(packet.descriptors(), SizeIs(3));
+ EXPECT_EQ(packet.descriptors()[0].type, SackChunk::kType);
+ EXPECT_EQ(packet.descriptors()[1].type, DataChunk::kType);
+ EXPECT_EQ(packet.descriptors()[2].type, DataChunk::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SackChunk sack,
+ SackChunk::Parse(packet.descriptors()[0].data));
+ EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(999));
+ EXPECT_EQ(sack.a_rwnd(), 456u);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(DataChunk data1,
+ DataChunk::Parse(packet.descriptors()[1].data));
+ EXPECT_EQ(data1.tsn(), TSN(123));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(DataChunk data2,
+ DataChunk::Parse(packet.descriptors()[2].data));
+ EXPECT_EQ(data2.tsn(), TSN(124));
+}
+
+TEST(SctpPacketTest, ParseAbortWithEmptyCause) {
+ SctpPacket::Builder b(kVerificationTag, {});
+ b.Add(AbortChunk(
+ /*filled_in_verification_tag=*/true,
+ Parameters::Builder().Add(UserInitiatedAbortCause("")).Build()));
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(b.Build()));
+
+ EXPECT_EQ(packet.common_header().verification_tag, kVerificationTag);
+
+ ASSERT_THAT(packet.descriptors(), SizeIs(1));
+ EXPECT_EQ(packet.descriptors()[0].type, AbortChunk::kType);
+
+ ASSERT_HAS_VALUE_AND_ASSIGN(AbortChunk abort,
+ AbortChunk::Parse(packet.descriptors()[0].data));
+ ASSERT_HAS_VALUE_AND_ASSIGN(
+ UserInitiatedAbortCause cause,
+ abort.error_causes().get<UserInitiatedAbortCause>());
+ EXPECT_EQ(cause.upper_layer_abort_reason(), "");
+}
+
+TEST(SctpPacketTest, DetectPacketWithZeroSizeChunk) {
+ uint8_t data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0a, 0x0a, 0x5c,
+ 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00};
+
+ EXPECT_FALSE(SctpPacket::Parse(data, true).has_value());
+}
+
+TEST(SctpPacketTest, ReturnsCorrectSpaceAvailableToStayWithinMTU) {
+ DcSctpOptions options;
+ options.mtu = 1191;
+
+ SctpPacket::Builder builder(VerificationTag(123), options);
+
+ // Chunks will be padded to an even 4 bytes, so the maximum packet size should
+ // be rounded down.
+ const size_t kMaxPacketSize = RoundDownTo4(options.mtu);
+ EXPECT_EQ(kMaxPacketSize, 1188u);
+
+ const size_t kSctpHeaderSize = 12;
+ EXPECT_EQ(builder.bytes_remaining(), kMaxPacketSize - kSctpHeaderSize);
+ EXPECT_EQ(builder.bytes_remaining(), 1176u);
+
+ // Add a smaller packet first.
+ DataChunk::Options data_options;
+
+ std::vector<uint8_t> payload1(183);
+ builder.Add(
+ DataChunk(TSN(1), StreamID(1), SSN(0), PPID(53), payload1, data_options));
+
+ size_t chunk1_size = RoundUpTo4(DataChunk::kHeaderSize + payload1.size());
+ EXPECT_EQ(builder.bytes_remaining(),
+ kMaxPacketSize - kSctpHeaderSize - chunk1_size);
+ EXPECT_EQ(builder.bytes_remaining(), 976u); // Hand-calculated.
+
+ std::vector<uint8_t> payload2(957);
+ builder.Add(
+ DataChunk(TSN(1), StreamID(1), SSN(0), PPID(53), payload2, data_options));
+
+ size_t chunk2_size = RoundUpTo4(DataChunk::kHeaderSize + payload2.size());
+ EXPECT_EQ(builder.bytes_remaining(),
+ kMaxPacketSize - kSctpHeaderSize - chunk1_size - chunk2_size);
+ EXPECT_EQ(builder.bytes_remaining(), 0u); // Hand-calculated.
+}
+
+} // namespace
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/tlv_trait.cc b/third_party/libwebrtc/net/dcsctp/packet/tlv_trait.cc
new file mode 100644
index 0000000000..493b6a4613
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/tlv_trait.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/tlv_trait.h"
+
+#include "rtc_base/logging.h"
+
+namespace dcsctp {
+namespace tlv_trait_impl {
+void ReportInvalidSize(size_t actual_size, size_t expected_size) {
+ RTC_DLOG(LS_WARNING) << "Invalid size (" << actual_size
+ << ", expected minimum " << expected_size << " bytes)";
+}
+
+void ReportInvalidType(int actual_type, int expected_type) {
+ RTC_DLOG(LS_WARNING) << "Invalid type (" << actual_type << ", expected "
+ << expected_type << ")";
+}
+
+void ReportInvalidFixedLengthField(size_t value, size_t expected) {
+ RTC_DLOG(LS_WARNING) << "Invalid length field (" << value << ", expected "
+ << expected << " bytes)";
+}
+
+void ReportInvalidVariableLengthField(size_t value, size_t available) {
+ RTC_DLOG(LS_WARNING) << "Invalid length field (" << value << ", available "
+ << available << " bytes)";
+}
+
+void ReportInvalidPadding(size_t padding_bytes) {
+ RTC_DLOG(LS_WARNING) << "Invalid padding (" << padding_bytes << " bytes)";
+}
+
+void ReportInvalidLengthMultiple(size_t length, size_t alignment) {
+ RTC_DLOG(LS_WARNING) << "Invalid length field (" << length
+ << ", expected an even multiple of " << alignment
+ << " bytes)";
+}
+} // namespace tlv_trait_impl
+} // namespace dcsctp
diff --git a/third_party/libwebrtc/net/dcsctp/packet/tlv_trait.h b/third_party/libwebrtc/net/dcsctp/packet/tlv_trait.h
new file mode 100644
index 0000000000..a3c728efd7
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/tlv_trait.h
@@ -0,0 +1,165 @@
+/*
+ * 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_TLV_TRAIT_H_
+#define NET_DCSCTP_PACKET_TLV_TRAIT_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#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"
+
+namespace dcsctp {
+namespace tlv_trait_impl {
+// Logging functions, only to be used by TLVTrait, which is a templated class.
+void ReportInvalidSize(size_t actual_size, size_t expected_size);
+void ReportInvalidType(int actual_type, int expected_type);
+void ReportInvalidFixedLengthField(size_t value, size_t expected);
+void ReportInvalidVariableLengthField(size_t value, size_t available);
+void ReportInvalidPadding(size_t padding_bytes);
+void ReportInvalidLengthMultiple(size_t length, size_t alignment);
+} // namespace tlv_trait_impl
+
+// Various entities in SCTP are padded data blocks, with a type and length
+// field at fixed offsets, all stored in a 4-byte header.
+//
+// See e.g. https://tools.ietf.org/html/rfc4960#section-3.2 and
+// https://tools.ietf.org/html/rfc4960#section-3.2.1
+//
+// These are helper classes for writing and parsing that data, which in SCTP is
+// called Type-Length-Value, or TLV.
+//
+// This templated class is configurable - a struct passed in as template
+// parameter with the following expected members:
+// * kType - The type field's value
+// * kTypeSizeInBytes - The type field's width in bytes.
+// Either 1 or 2.
+// * kHeaderSize - The fixed size header
+// * kVariableLengthAlignment - The size alignment on the variable data. Set
+// to zero (0) if no variable data is used.
+//
+// This class is to be used as a trait
+// (https://en.wikipedia.org/wiki/Trait_(computer_programming)) that adds a few
+// public and protected members and which a class inherits from when it
+// represents a type-length-value object.
+template <typename Config>
+class TLVTrait {
+ private:
+ static constexpr size_t kTlvHeaderSize = 4;
+
+ protected:
+ static constexpr size_t kHeaderSize = Config::kHeaderSize;
+
+ static_assert(Config::kTypeSizeInBytes == 1 || Config::kTypeSizeInBytes == 2,
+ "kTypeSizeInBytes must be 1 or 2");
+ static_assert(Config::kHeaderSize >= kTlvHeaderSize,
+ "HeaderSize must be >= 4 bytes");
+ static_assert((Config::kHeaderSize % 4 == 0),
+ "kHeaderSize must be an even multiple of 4 bytes");
+ static_assert((Config::kVariableLengthAlignment == 0 ||
+ Config::kVariableLengthAlignment == 1 ||
+ Config::kVariableLengthAlignment == 2 ||
+ Config::kVariableLengthAlignment == 4 ||
+ Config::kVariableLengthAlignment == 8),
+ "kVariableLengthAlignment must be an allowed value");
+
+ // Validates the data with regards to size, alignment and type.
+ // If valid, returns a bounded buffer.
+ static absl::optional<BoundedByteReader<Config::kHeaderSize>> ParseTLV(
+ rtc::ArrayView<const uint8_t> data) {
+ if (data.size() < Config::kHeaderSize) {
+ tlv_trait_impl::ReportInvalidSize(data.size(), Config::kHeaderSize);
+ return absl::nullopt;
+ }
+ BoundedByteReader<kTlvHeaderSize> tlv_header(data);
+
+ const int type = (Config::kTypeSizeInBytes == 1)
+ ? tlv_header.template Load8<0>()
+ : tlv_header.template Load16<0>();
+
+ if (type != Config::kType) {
+ tlv_trait_impl::ReportInvalidType(type, Config::kType);
+ return absl::nullopt;
+ }
+ const uint16_t length = tlv_header.template Load16<2>();
+ if (Config::kVariableLengthAlignment == 0) {
+ // Don't expect any variable length data at all.
+ if (length != Config::kHeaderSize || data.size() != Config::kHeaderSize) {
+ tlv_trait_impl::ReportInvalidFixedLengthField(length,
+ Config::kHeaderSize);
+ return absl::nullopt;
+ }
+ } else {
+ // Expect variable length data - verify its size alignment.
+ if (length > data.size() || length < Config::kHeaderSize) {
+ tlv_trait_impl::ReportInvalidVariableLengthField(length, data.size());
+ return absl::nullopt;
+ }
+ const size_t padding = data.size() - length;
+ if (padding > 3) {
+ // https://tools.ietf.org/html/rfc4960#section-3.2
+ // "This padding MUST NOT be more than 3 bytes in total"
+ tlv_trait_impl::ReportInvalidPadding(padding);
+ return absl::nullopt;
+ }
+ if (!ValidateLengthAlignment(length, Config::kVariableLengthAlignment)) {
+ tlv_trait_impl::ReportInvalidLengthMultiple(
+ length, Config::kVariableLengthAlignment);
+ return absl::nullopt;
+ }
+ }
+ return BoundedByteReader<Config::kHeaderSize>(data.subview(0, length));
+ }
+
+ // Allocates space for data with a static header size, as defined by
+ // `Config::kHeaderSize` and a variable footer, as defined by `variable_size`
+ // (which may be 0) and writes the type and length in the header.
+ static BoundedByteWriter<Config::kHeaderSize> AllocateTLV(
+ std::vector<uint8_t>& out,
+ size_t variable_size = 0) {
+ const size_t offset = out.size();
+ const size_t size = Config::kHeaderSize + variable_size;
+ out.resize(offset + size);
+
+ BoundedByteWriter<kTlvHeaderSize> tlv_header(
+ rtc::ArrayView<uint8_t>(out.data() + offset, kTlvHeaderSize));
+ if (Config::kTypeSizeInBytes == 1) {
+ tlv_header.template Store8<0>(static_cast<uint8_t>(Config::kType));
+ } else {
+ tlv_header.template Store16<0>(Config::kType);
+ }
+ tlv_header.template Store16<2>(size);
+
+ return BoundedByteWriter<Config::kHeaderSize>(
+ rtc::ArrayView<uint8_t>(out.data() + offset, size));
+ }
+
+ private:
+ static bool ValidateLengthAlignment(uint16_t length, size_t alignment) {
+ // This is to avoid MSVC believing there could be a "mod by zero", when it
+ // certainly can't.
+ if (alignment == 0) {
+ return true;
+ }
+ return (length % alignment) == 0;
+ }
+};
+
+} // namespace dcsctp
+
+#endif // NET_DCSCTP_PACKET_TLV_TRAIT_H_
diff --git a/third_party/libwebrtc/net/dcsctp/packet/tlv_trait_test.cc b/third_party/libwebrtc/net/dcsctp/packet/tlv_trait_test.cc
new file mode 100644
index 0000000000..a0dd1a1136
--- /dev/null
+++ b/third_party/libwebrtc/net/dcsctp/packet/tlv_trait_test.cc
@@ -0,0 +1,133 @@
+/*
+ * 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/tlv_trait.h"
+
+#include <vector>
+
+#include "api/array_view.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+
+namespace dcsctp {
+namespace {
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+
+struct OneByteTypeConfig {
+ static constexpr int kTypeSizeInBytes = 1;
+ static constexpr int kType = 0x49;
+ static constexpr size_t kHeaderSize = 12;
+ static constexpr int kVariableLengthAlignment = 4;
+};
+
+class OneByteChunk : public TLVTrait<OneByteTypeConfig> {
+ public:
+ static constexpr size_t kVariableSize = 4;
+
+ void SerializeTo(std::vector<uint8_t>& out) {
+ BoundedByteWriter<OneByteTypeConfig::kHeaderSize> writer =
+ AllocateTLV(out, kVariableSize);
+ writer.Store32<4>(0x01020304);
+ writer.Store16<8>(0x0506);
+ writer.Store16<10>(0x0708);
+
+ uint8_t variable_data[kVariableSize] = {0xDE, 0xAD, 0xBE, 0xEF};
+ writer.CopyToVariableData(rtc::ArrayView<const uint8_t>(variable_data));
+ }
+
+ static absl::optional<BoundedByteReader<OneByteTypeConfig::kHeaderSize>>
+ Parse(rtc::ArrayView<const uint8_t> data) {
+ return ParseTLV(data);
+ }
+};
+
+TEST(TlvDataTest, CanWriteOneByteTypeTlvs) {
+ std::vector<uint8_t> out;
+ OneByteChunk().SerializeTo(out);
+
+ EXPECT_THAT(out, SizeIs(OneByteTypeConfig::kHeaderSize +
+ OneByteChunk::kVariableSize));
+ EXPECT_THAT(out, ElementsAre(0x49, 0x00, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0xDE, 0xAD, 0xBE, 0xEF));
+}
+
+TEST(TlvDataTest, CanReadOneByteTypeTlvs) {
+ uint8_t data[] = {0x49, 0x00, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0xDE, 0xAD, 0xBE, 0xEF};
+
+ absl::optional<BoundedByteReader<OneByteTypeConfig::kHeaderSize>> reader =
+ OneByteChunk::Parse(data);
+ ASSERT_TRUE(reader.has_value());
+ EXPECT_EQ(reader->Load32<4>(), 0x01020304U);
+ EXPECT_EQ(reader->Load16<8>(), 0x0506U);
+ EXPECT_EQ(reader->Load16<10>(), 0x0708U);
+ EXPECT_THAT(reader->variable_data(), ElementsAre(0xDE, 0xAD, 0xBE, 0xEF));
+}
+
+struct TwoByteTypeConfig {
+ static constexpr int kTypeSizeInBytes = 2;
+ static constexpr int kType = 31337;
+ static constexpr size_t kHeaderSize = 8;
+ static constexpr int kVariableLengthAlignment = 2;
+};
+
+class TwoByteChunk : public TLVTrait<TwoByteTypeConfig> {
+ public:
+ static constexpr size_t kVariableSize = 8;
+
+ void SerializeTo(std::vector<uint8_t>& out) {
+ BoundedByteWriter<TwoByteTypeConfig::kHeaderSize> writer =
+ AllocateTLV(out, kVariableSize);
+ writer.Store32<4>(0x01020304U);
+
+ uint8_t variable_data[] = {0x05, 0x06, 0x07, 0x08, 0xDE, 0xAD, 0xBE, 0xEF};
+ writer.CopyToVariableData(rtc::ArrayView<const uint8_t>(variable_data));
+ }
+
+ static absl::optional<BoundedByteReader<TwoByteTypeConfig::kHeaderSize>>
+ Parse(rtc::ArrayView<const uint8_t> data) {
+ return ParseTLV(data);
+ }
+};
+
+TEST(TlvDataTest, CanWriteTwoByteTypeTlvs) {
+ std::vector<uint8_t> out;
+
+ TwoByteChunk().SerializeTo(out);
+
+ EXPECT_THAT(out, SizeIs(TwoByteTypeConfig::kHeaderSize +
+ TwoByteChunk::kVariableSize));
+ EXPECT_THAT(out, ElementsAre(0x7A, 0x69, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0xDE, 0xAD, 0xBE, 0xEF));
+}
+
+TEST(TlvDataTest, CanReadTwoByteTypeTlvs) {
+ uint8_t data[] = {0x7A, 0x69, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0xDE, 0xAD, 0xBE, 0xEF};
+
+ absl::optional<BoundedByteReader<TwoByteTypeConfig::kHeaderSize>> reader =
+ TwoByteChunk::Parse(data);
+ EXPECT_TRUE(reader.has_value());
+ EXPECT_EQ(reader->Load32<4>(), 0x01020304U);
+ EXPECT_THAT(reader->variable_data(),
+ ElementsAre(0x05, 0x06, 0x07, 0x08, 0xDE, 0xAD, 0xBE, 0xEF));
+}
+
+TEST(TlvDataTest, CanHandleInvalidLengthSmallerThanFixedSize) {
+ // Has 'length=6', which is below the kHeaderSize of 8.
+ uint8_t data[] = {0x7A, 0x69, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04};
+
+ EXPECT_FALSE(TwoByteChunk::Parse(data).has_value());
+}
+
+} // namespace
+} // namespace dcsctp