mediasoup 3.21.0 → 3.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +1882 -0
  2. package/node/lib/test/test-Consumer.js +111 -0
  3. package/node/lib/test/test-Producer.js +54 -0
  4. package/npm-scripts.mjs +0 -5
  5. package/package.json +9 -8
  6. package/worker/fuzzer/src/RTC/SCTP/association/FuzzerStateCookie.cpp +4 -6
  7. package/worker/include/RTC/NEW_RTCP/packet/ByePacket.hpp +165 -0
  8. package/worker/include/RTC/NEW_RTCP/packet/CompoundPacket.hpp +183 -0
  9. package/worker/include/RTC/NEW_RTCP/packet/Packet.hpp +354 -0
  10. package/worker/include/RTC/NEW_RTCP/packet/TODO_NEW_RTCP.md +17 -0
  11. package/worker/include/RTC/RTP/Codecs/Tools.hpp +2 -0
  12. package/worker/include/RTC/Router.hpp +4 -4
  13. package/worker/include/RTC/SCTP/association/Capabilities.hpp +73 -0
  14. package/worker/include/RTC/SCTP/association/NegotiatedCapabilities.hpp +7 -9
  15. package/worker/include/RTC/SCTP/association/StateCookie.hpp +38 -28
  16. package/worker/include/RTC/SCTP/packet/Chunk.hpp +11 -7
  17. package/worker/include/RTC/SCTP/packet/ErrorCause.hpp +11 -4
  18. package/worker/include/RTC/SCTP/packet/Packet.hpp +1 -1
  19. package/worker/include/RTC/SCTP/packet/Parameter.hpp +11 -4
  20. package/worker/include/RTC/SCTP/packet/TLV.hpp +2 -2
  21. package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +2 -2
  22. package/worker/include/RTC/Transport.hpp +10 -10
  23. package/worker/include/Worker.hpp +4 -4
  24. package/worker/meson.build +7 -0
  25. package/worker/scripts/clang-scripts.mjs +54 -0
  26. package/worker/src/RTC/Consumer.cpp +22 -4
  27. package/worker/src/RTC/NEW_RTCP/packet/ByePacket.cpp +266 -0
  28. package/worker/src/RTC/NEW_RTCP/packet/CompoundPacket.cpp +219 -0
  29. package/worker/src/RTC/NEW_RTCP/packet/Packet.cpp +222 -0
  30. package/worker/src/RTC/RTP/Codecs/H264.cpp +3 -0
  31. package/worker/src/RTC/RTP/Codecs/VP8.cpp +3 -0
  32. package/worker/src/RTC/Router.cpp +14 -14
  33. package/worker/src/RTC/SCTP/association/Association.cpp +23 -11
  34. package/worker/src/RTC/SCTP/association/Capabilities.cpp +87 -0
  35. package/worker/src/RTC/SCTP/association/NegotiatedCapabilities.cpp +20 -40
  36. package/worker/src/RTC/SCTP/association/StateCookie.cpp +54 -32
  37. package/worker/src/RTC/SCTP/packet/Chunk.cpp +18 -18
  38. package/worker/src/RTC/SCTP/packet/ErrorCause.cpp +18 -18
  39. package/worker/src/RTC/SCTP/packet/Packet.cpp +2 -0
  40. package/worker/src/RTC/SCTP/packet/Parameter.cpp +18 -18
  41. package/worker/src/RTC/SCTP/packet/TLV.cpp +27 -25
  42. package/worker/src/RTC/SCTP/packet/parameters/StateCookieParameter.cpp +2 -2
  43. package/worker/src/RTC/SvcProducerStreamManager.cpp +4 -1
  44. package/worker/src/RTC/Transport.cpp +42 -30
  45. package/worker/src/Worker.cpp +10 -10
  46. package/worker/test/include/RTC/ICE/iceCommon.hpp +1 -1
  47. package/worker/test/include/RTC/RTCP/rtcpCommon.hpp +58 -0
  48. package/worker/test/include/RTC/RTP/rtpCommon.hpp +1 -1
  49. package/worker/test/src/RTC/NEW_RTCP/packet/TestByePacket.cpp +302 -0
  50. package/worker/test/src/RTC/NEW_RTCP/rtcpCommon.cpp +29 -0
  51. package/worker/test/src/RTC/RTP/TestPacket.cpp +17 -15
  52. package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +3 -3
  53. package/worker/test/src/RTC/SCTP/association/TestCapabilities.cpp +99 -0
  54. package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +14 -16
  55. package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +198 -102
  56. package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +11 -10
@@ -0,0 +1,87 @@
1
+ #define MS_CLASS "RTC::SCTP::Capabilities"
2
+ // #define MS_LOG_DEV_LEVEL 3
3
+
4
+ #include "RTC/SCTP/association/Capabilities.hpp"
5
+ #include "Logger.hpp"
6
+ #include "RTC/SCTP/packet/Chunk.hpp"
7
+ #include "RTC/SCTP/packet/parameters/ForwardTsnSupportedParameter.hpp"
8
+ #include "RTC/SCTP/packet/parameters/SupportedExtensionsParameter.hpp"
9
+
10
+ namespace RTC
11
+ {
12
+ namespace SCTP
13
+ {
14
+ /* Class methods. */
15
+
16
+ Capabilities Capabilities::Factory(const AnyInitChunk* remoteChunk)
17
+ {
18
+ MS_TRACE();
19
+
20
+ Capabilities capabilities{};
21
+
22
+ const auto* remoteSupportedExtensionsParameter =
23
+ remoteChunk->template GetFirstParameterOfType<SupportedExtensionsParameter>();
24
+ const auto* remoteForwardTsnSupportedParameter =
25
+ remoteChunk->template GetFirstParameterOfType<ForwardTsnSupportedParameter>();
26
+ const auto* remoteZeroChecksumAcceptableParameter =
27
+ remoteChunk->template GetFirstParameterOfType<ZeroChecksumAcceptableParameter>();
28
+
29
+ // Streams announced by the remote endpoint in its INIT or INIT-ACK chunk.
30
+ capabilities.maxOutboundStreams = remoteChunk->GetNumberOfOutboundStreams();
31
+ capabilities.maxInboundStreams = remoteChunk->GetNumberOfInboundStreams();
32
+
33
+ // Remote announces Partial Reliability Extension support via
34
+ // Forward-TSN-Supported parameter or via Supported Extensions parameter.
35
+ capabilities.partialReliability =
36
+ remoteForwardTsnSupportedParameter ||
37
+ (remoteSupportedExtensionsParameter &&
38
+ remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::FORWARD_TSN));
39
+
40
+ // Remote announces Message Interleaving support via Supported Extensions
41
+ // parameter.
42
+ capabilities.messageInterleaving =
43
+ remoteSupportedExtensionsParameter &&
44
+ remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::I_DATA) &&
45
+ remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::I_FORWARD_TSN);
46
+
47
+ // Remote announces Stream Re-Configuration support via Supported
48
+ // Extensions parameter.
49
+ capabilities.reConfig =
50
+ remoteSupportedExtensionsParameter &&
51
+ remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::RE_CONFIG);
52
+
53
+ // Alternate Error Detection Method for Zero Checksum announced by the
54
+ // remote endpoint (NONE if not announced).
55
+ capabilities.zeroChecksumAlternateErrorDetectionMethod =
56
+ remoteZeroChecksumAcceptableParameter
57
+ ? remoteZeroChecksumAcceptableParameter->GetAlternateErrorDetectionMethod()
58
+ : ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::NONE;
59
+
60
+ // NOTE: No need to std::move(). Copy elision (RVO) is used for free in GCC
61
+ // and clang in C++17 or higher.
62
+ return capabilities;
63
+ }
64
+
65
+ /* Instance methods. */
66
+
67
+ void Capabilities::Dump(int indentation) const
68
+ {
69
+ MS_TRACE();
70
+
71
+ MS_DUMP_CLEAN(indentation, "<SCTP::Capabilities>");
72
+ MS_DUMP_CLEAN(indentation, " max outbound streams: %" PRIu16, this->maxOutboundStreams);
73
+ MS_DUMP_CLEAN(indentation, " max inbound streams: %" PRIu16, this->maxInboundStreams);
74
+ MS_DUMP_CLEAN(indentation, " partial reliability: %s", this->partialReliability ? "yes" : "no");
75
+ MS_DUMP_CLEAN(
76
+ indentation, " message interleaving: %s", this->messageInterleaving ? "yes" : "no");
77
+ MS_DUMP_CLEAN(indentation, " re-config: %s", this->reConfig ? "yes" : "no");
78
+ MS_DUMP_CLEAN(
79
+ indentation,
80
+ " zero checksum alternate error detection method: %s",
81
+ ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethodToString(
82
+ this->zeroChecksumAlternateErrorDetectionMethod)
83
+ .c_str());
84
+ MS_DUMP_CLEAN(indentation, "</SCTP::Capabilities>");
85
+ }
86
+ } // namespace SCTP
87
+ } // namespace RTC
@@ -3,8 +3,6 @@
3
3
 
4
4
  #include "RTC/SCTP/association/NegotiatedCapabilities.hpp"
5
5
  #include "Logger.hpp"
6
- #include "RTC/SCTP/packet/parameters/ForwardTsnSupportedParameter.hpp"
7
- #include "RTC/SCTP/packet/parameters/SupportedExtensionsParameter.hpp"
8
6
  #include "RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp"
9
7
 
10
8
  namespace RTC
@@ -14,55 +12,39 @@ namespace RTC
14
12
  /* Class methods. */
15
13
 
16
14
  NegotiatedCapabilities NegotiatedCapabilities::Factory(
17
- const SctpOptions& sctpOptions, const AnyInitChunk* remoteChunk)
15
+ const SctpOptions& sctpOptions, const Capabilities& remoteCapabilities)
18
16
  {
19
17
  MS_TRACE();
20
18
 
21
19
  NegotiatedCapabilities negotiatedCapabilities{};
22
20
 
23
- const auto* remoteSupportedExtensionsParameter =
24
- remoteChunk->template GetFirstParameterOfType<SupportedExtensionsParameter>();
25
- const auto* remoteForwardTsnSupportedParameter =
26
- remoteChunk->template GetFirstParameterOfType<ForwardTsnSupportedParameter>();
27
- const auto* remoteZeroChecksumAcceptableParameter =
28
- remoteChunk->template GetFirstParameterOfType<ZeroChecksumAcceptableParameter>();
21
+ negotiatedCapabilities.maxOutboundStreams =
22
+ std::min(sctpOptions.announcedMaxOutboundStreams, remoteCapabilities.maxInboundStreams);
29
23
 
30
- negotiatedCapabilities.negotiatedMaxOutboundStreams =
31
- std::min(sctpOptions.announcedMaxOutboundStreams, remoteChunk->GetNumberOfInboundStreams());
24
+ negotiatedCapabilities.maxInboundStreams =
25
+ std::min(sctpOptions.announcedMaxInboundStreams, remoteCapabilities.maxOutboundStreams);
32
26
 
33
- negotiatedCapabilities.negotiatedMaxInboundStreams =
34
- std::min(sctpOptions.announcedMaxInboundStreams, remoteChunk->GetNumberOfOutboundStreams());
35
-
36
- // Partial Reliability Extension is negotiated if we desire it and
37
- // peer announces support via Forward-TSN-Supported Parameter or via
38
- // Supported extensions parameter.
27
+ // Partial Reliability Extension is negotiated if we desire it and the
28
+ // remote announces support for it.
39
29
  negotiatedCapabilities.partialReliability =
40
- sctpOptions.enablePartialReliability &&
41
- (remoteForwardTsnSupportedParameter ||
42
- (remoteSupportedExtensionsParameter &&
43
- remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::FORWARD_TSN)));
30
+ sctpOptions.enablePartialReliability && remoteCapabilities.partialReliability;
44
31
 
45
- // Message Interleaving is negotiated if we desire it and peer
46
- // announces support via Supported Extensions parameter.
32
+ // Message Interleaving is negotiated if we desire it and the remote
33
+ // announces support for it.
47
34
  negotiatedCapabilities.messageInterleaving =
48
- sctpOptions.enableMessageInterleaving && remoteSupportedExtensionsParameter &&
49
- remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::I_DATA) &&
50
- remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::I_FORWARD_TSN);
35
+ sctpOptions.enableMessageInterleaving && remoteCapabilities.messageInterleaving;
51
36
 
52
- // Stream Re-Configuration is negotiated if peer announces support via
53
- // Supported extensions parameter.
54
- negotiatedCapabilities.reConfig =
55
- remoteSupportedExtensionsParameter &&
56
- remoteSupportedExtensionsParameter->IncludesChunkType(Chunk::ChunkType::RE_CONFIG);
37
+ // Stream Re-Configuration is negotiated if the remote announces support
38
+ // for it.
39
+ negotiatedCapabilities.reConfig = remoteCapabilities.reConfig;
57
40
 
58
- // Alternate Error Detection Method for Zero Checksum is negotiated
59
- // if we desire it and peer announces the same non-none alternate
60
- // error detection method.
41
+ // Alternate Error Detection Method for Zero Checksum is negotiated if we
42
+ // desire it and the remote announces the same non-none alternate error
43
+ // detection method.
61
44
  negotiatedCapabilities.zeroChecksum =
62
45
  sctpOptions.zeroChecksumAlternateErrorDetectionMethod !=
63
46
  ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::NONE &&
64
- remoteZeroChecksumAcceptableParameter &&
65
- remoteZeroChecksumAcceptableParameter->GetAlternateErrorDetectionMethod() ==
47
+ remoteCapabilities.zeroChecksumAlternateErrorDetectionMethod ==
66
48
  sctpOptions.zeroChecksumAlternateErrorDetectionMethod;
67
49
 
68
50
  return negotiatedCapabilities;
@@ -75,10 +57,8 @@ namespace RTC
75
57
  MS_TRACE();
76
58
 
77
59
  MS_DUMP_CLEAN(indentation, "<SCTP::NegotiatedCapabilities>");
78
- MS_DUMP_CLEAN(
79
- indentation, " negotiated max outbound streams: %" PRIu16, this->negotiatedMaxOutboundStreams);
80
- MS_DUMP_CLEAN(
81
- indentation, " negotiated max inbound streams: %" PRIu16, this->negotiatedMaxInboundStreams);
60
+ MS_DUMP_CLEAN(indentation, " max outbound streams: %" PRIu16, this->maxOutboundStreams);
61
+ MS_DUMP_CLEAN(indentation, " max inbound streams: %" PRIu16, this->maxInboundStreams);
82
62
  MS_DUMP_CLEAN(indentation, " partial reliability: %s", this->partialReliability ? "yes" : "no");
83
63
  MS_DUMP_CLEAN(
84
64
  indentation, " message interleaving: %s", this->messageInterleaving ? "yes" : "no");
@@ -24,6 +24,15 @@ namespace RTC
24
24
  return nullptr;
25
25
  }
26
26
 
27
+ // Reject cookies with a zero verification tag. A zero tag is never
28
+ // generated by us, so this limits the effect of a tampered/forged cookie.
29
+ if (Utils::Byte::Get4Bytes(buffer, 8) == 0 || Utils::Byte::Get4Bytes(buffer, 12) == 0)
30
+ {
31
+ MS_WARN_TAG(sctp, "invalid StateCookie, verification tag is zero");
32
+
33
+ return nullptr;
34
+ }
35
+
27
36
  auto* stateCookie = new StateCookie(const_cast<uint8_t*>(buffer), bufferLength);
28
37
 
29
38
  return stateCookie;
@@ -38,7 +47,7 @@ namespace RTC
38
47
  uint32_t remoteInitialTsn,
39
48
  uint32_t remoteAdvertisedReceiverWindowCredit,
40
49
  uint64_t tieTag,
41
- const NegotiatedCapabilities& negotiatedCapabilities,
50
+ const Capabilities& remoteCapabilities,
42
51
  uint64_t creationTimestampMs,
43
52
  const uint8_t* macKey,
44
53
  size_t macKeyLength)
@@ -55,7 +64,7 @@ namespace RTC
55
64
  remoteInitialTsn,
56
65
  remoteAdvertisedReceiverWindowCredit,
57
66
  tieTag,
58
- negotiatedCapabilities,
67
+ remoteCapabilities,
59
68
  creationTimestampMs,
60
69
  macKey,
61
70
  macKeyLength);
@@ -75,7 +84,7 @@ namespace RTC
75
84
  uint32_t remoteInitialTsn,
76
85
  uint32_t remoteAdvertisedReceiverWindowCredit,
77
86
  uint64_t tieTag,
78
- const NegotiatedCapabilities& negotiatedCapabilities,
87
+ const Capabilities& remoteCapabilities,
79
88
  uint64_t creationTimestampMs,
80
89
  const uint8_t* macKey,
81
90
  size_t macKeyLength)
@@ -99,19 +108,19 @@ namespace RTC
99
108
  Utils::Byte::Set4Bytes(buffer, 24, remoteAdvertisedReceiverWindowCredit);
100
109
  Utils::Byte::Set8Bytes(buffer, 28, tieTag);
101
110
 
102
- auto* negotiatedCapabilitiesField = reinterpret_cast<NegotiatedCapabilitiesField*>(
103
- buffer + StateCookie::NegotiatedCapabilitiesOffset);
111
+ auto* remoteCapabilitiesField =
112
+ reinterpret_cast<RemoteCapabilitiesField*>(buffer + StateCookie::RemoteCapabilitiesOffset);
104
113
 
105
- negotiatedCapabilitiesField->reserved = 0;
106
- negotiatedCapabilitiesField->bitA = negotiatedCapabilities.partialReliability;
107
- negotiatedCapabilitiesField->bitB = negotiatedCapabilities.messageInterleaving;
108
- negotiatedCapabilitiesField->bitC = negotiatedCapabilities.reConfig;
109
- negotiatedCapabilitiesField->bitD = negotiatedCapabilities.zeroChecksum;
110
- negotiatedCapabilitiesField->magic2 = htons(StateCookie::Magic2);
111
- negotiatedCapabilitiesField->negotiatedMaxOutboundStreams =
112
- htons(negotiatedCapabilities.negotiatedMaxOutboundStreams);
113
- negotiatedCapabilitiesField->negotiatedMaxInboundStreams =
114
- htons(negotiatedCapabilities.negotiatedMaxInboundStreams);
114
+ remoteCapabilitiesField->reserved = 0;
115
+ remoteCapabilitiesField->bitA = remoteCapabilities.partialReliability;
116
+ remoteCapabilitiesField->bitB = remoteCapabilities.messageInterleaving;
117
+ remoteCapabilitiesField->bitC = remoteCapabilities.reConfig;
118
+ remoteCapabilitiesField->unusedBits = 0;
119
+ remoteCapabilitiesField->magic2 = htons(StateCookie::Magic2);
120
+ remoteCapabilitiesField->zeroChecksumAlternateErrorDetectionMethod =
121
+ htonl(static_cast<uint32_t>(remoteCapabilities.zeroChecksumAlternateErrorDetectionMethod));
122
+ remoteCapabilitiesField->maxOutboundStreams = htons(remoteCapabilities.maxOutboundStreams);
123
+ remoteCapabilitiesField->maxInboundStreams = htons(remoteCapabilities.maxInboundStreams);
115
124
 
116
125
  if (!authenticate)
117
126
  {
@@ -144,10 +153,10 @@ namespace RTC
144
153
  return false;
145
154
  }
146
155
 
147
- auto* negotiatedCapabilitiesField = reinterpret_cast<NegotiatedCapabilitiesField*>(
148
- const_cast<uint8_t*>(buffer) + StateCookie::NegotiatedCapabilitiesOffset);
156
+ const auto* remoteCapabilitiesField = reinterpret_cast<const RemoteCapabilitiesField*>(
157
+ buffer + StateCookie::RemoteCapabilitiesOffset);
149
158
 
150
- if (ntohs(negotiatedCapabilitiesField->magic2) != StateCookie::Magic2)
159
+ if (ntohs(remoteCapabilitiesField->magic2) != StateCookie::Magic2)
151
160
  {
152
161
  return false;
153
162
  }
@@ -228,9 +237,10 @@ namespace RTC
228
237
  {
229
238
  MS_TRACE();
230
239
 
231
- auto negotiatedCapabilities = GetNegotiatedCapabilities();
240
+ const auto remoteCapabilities = GetRemoteCapabilities();
232
241
 
233
242
  MS_DUMP_CLEAN(indentation, "<SCTP::StateCookie>");
243
+
234
244
  MS_DUMP_CLEAN(indentation, " length: %zu (buffer length: %zu)", GetLength(), GetBufferLength());
235
245
  MS_DUMP_CLEAN(indentation, " local verification tag: %" PRIu32, GetLocalVerificationTag());
236
246
  MS_DUMP_CLEAN(indentation, " remote verification tag: %" PRIu32, GetRemoteVerificationTag());
@@ -248,7 +258,9 @@ namespace RTC
248
258
  MS_DUMP_CLEAN(indentation, " creation timestamp (ms): %" PRIu64, GetCreationTimestampMs());
249
259
  }
250
260
 
251
- negotiatedCapabilities.Dump(indentation + 1);
261
+ MS_DUMP_CLEAN(indentation, " remote capabilities:");
262
+ remoteCapabilities.Dump(indentation + 1);
263
+
252
264
  MS_DUMP_CLEAN(indentation, "</SCTP::StateCookie>");
253
265
  }
254
266
 
@@ -263,26 +275,36 @@ namespace RTC
263
275
  return clonedStateCookie;
264
276
  }
265
277
 
266
- NegotiatedCapabilities StateCookie::GetNegotiatedCapabilities() const
278
+ Capabilities StateCookie::GetRemoteCapabilities() const
267
279
  {
268
280
  MS_TRACE();
269
281
 
270
- auto* negotiatedCapabilitiesField = GetNegotiatedCapabilitiesField();
282
+ const auto* remoteCapabilitiesField = GetRemoteCapabilitiesField();
283
+
284
+ Capabilities remoteCapabilities;
285
+
286
+ remoteCapabilities.maxOutboundStreams = ntohs(remoteCapabilitiesField->maxOutboundStreams);
287
+ remoteCapabilities.maxInboundStreams = ntohs(remoteCapabilitiesField->maxInboundStreams);
288
+ remoteCapabilities.partialReliability = remoteCapabilitiesField->bitA;
289
+ remoteCapabilities.messageInterleaving = remoteCapabilitiesField->bitB;
290
+ remoteCapabilities.reConfig = remoteCapabilitiesField->bitC;
271
291
 
272
- NegotiatedCapabilities negotiatedCapabilities;
292
+ // Only keep the zero checksum method if it's a value we know about.
293
+ // Anything else (unknown/future method or a tampered cookie) is treated
294
+ // as none.
295
+ const uint32_t zeroChecksumAlternateErrorDetectionMethod =
296
+ ntohl(remoteCapabilitiesField->zeroChecksumAlternateErrorDetectionMethod);
273
297
 
274
- negotiatedCapabilities.negotiatedMaxOutboundStreams =
275
- ntohs(negotiatedCapabilitiesField->negotiatedMaxOutboundStreams);
276
- negotiatedCapabilities.negotiatedMaxInboundStreams =
277
- ntohs(negotiatedCapabilitiesField->negotiatedMaxInboundStreams);
278
- negotiatedCapabilities.partialReliability = negotiatedCapabilitiesField->bitA;
279
- negotiatedCapabilities.messageInterleaving = negotiatedCapabilitiesField->bitB;
280
- negotiatedCapabilities.reConfig = negotiatedCapabilitiesField->bitC;
281
- negotiatedCapabilities.zeroChecksum = negotiatedCapabilitiesField->bitD;
298
+ remoteCapabilities.zeroChecksumAlternateErrorDetectionMethod =
299
+ zeroChecksumAlternateErrorDetectionMethod ==
300
+ static_cast<uint32_t>(
301
+ ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::SCTP_OVER_DTLS)
302
+ ? ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::SCTP_OVER_DTLS
303
+ : ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::NONE;
282
304
 
283
305
  // NOTE: No need to std::move(). Copy elision (RVO) is used for free in GCC
284
306
  // and clang in C++17 or higher.
285
- return negotiatedCapabilities;
307
+ return remoteCapabilities;
286
308
  }
287
309
  } // namespace SCTP
288
310
  } // namespace RTC
@@ -70,6 +70,22 @@ namespace RTC
70
70
 
71
71
  /* Class methods. */
72
72
 
73
+ const std::string& Chunk::ChunkTypeToString(ChunkType chunkType)
74
+ {
75
+ MS_TRACE();
76
+
77
+ static const std::string Unknown("UNKNOWN");
78
+
79
+ auto it = Chunk::ChunkType2String.find(chunkType);
80
+
81
+ if (it == Chunk::ChunkType2String.end())
82
+ {
83
+ return Unknown;
84
+ }
85
+
86
+ return it->second;
87
+ }
88
+
73
89
  bool Chunk::IsChunk(
74
90
  const uint8_t* buffer,
75
91
  size_t bufferLength,
@@ -89,22 +105,6 @@ namespace RTC
89
105
  return true;
90
106
  }
91
107
 
92
- const std::string& Chunk::ChunkTypeToString(ChunkType chunkType)
93
- {
94
- MS_TRACE();
95
-
96
- static const std::string Unknown("UNKNOWN");
97
-
98
- auto it = Chunk::ChunkType2String.find(chunkType);
99
-
100
- if (it == Chunk::ChunkType2String.end())
101
- {
102
- return Unknown;
103
- }
104
-
105
- return it->second;
106
- }
107
-
108
108
  /* Instance methods. */
109
109
 
110
110
  Chunk::Chunk(uint8_t* buffer, size_t bufferLength) : TLV(buffer, bufferLength)
@@ -312,13 +312,13 @@ namespace RTC
312
312
  chunk->SetLength(GetLength());
313
313
  }
314
314
 
315
- void Chunk::InitializeHeader(ChunkType chunkType, uint8_t flags, uint16_t lengthFieldValue)
315
+ void Chunk::InitializeHeader(ChunkType chunkType, uint8_t flags, uint16_t length)
316
316
  {
317
317
  MS_TRACE();
318
318
 
319
319
  SetType(chunkType);
320
320
  SetFlags(flags);
321
- InitializeTLVHeader(lengthFieldValue);
321
+ InitializeTLVHeader(length);
322
322
  }
323
323
 
324
324
  bool Chunk::ParseParameters()
@@ -32,6 +32,22 @@ namespace RTC
32
32
 
33
33
  /* Class methods. */
34
34
 
35
+ const std::string& ErrorCause::ErrorCauseCodeToString(ErrorCauseCode causeCode)
36
+ {
37
+ MS_TRACE();
38
+
39
+ static const std::string Unknown("UNKNOWN");
40
+
41
+ auto it = ErrorCause::ErrorCauseCode2String.find(causeCode);
42
+
43
+ if (it == ErrorCause::ErrorCauseCode2String.end())
44
+ {
45
+ return Unknown;
46
+ }
47
+
48
+ return it->second;
49
+ }
50
+
35
51
  bool ErrorCause::IsErrorCause(
36
52
  const uint8_t* buffer,
37
53
  size_t bufferLength,
@@ -51,22 +67,6 @@ namespace RTC
51
67
  return true;
52
68
  }
53
69
 
54
- const std::string& ErrorCause::ErrorCauseCodeToString(ErrorCauseCode causeCode)
55
- {
56
- MS_TRACE();
57
-
58
- static const std::string Unknown("UNKNOWN");
59
-
60
- auto it = ErrorCause::ErrorCauseCode2String.find(causeCode);
61
-
62
- if (it == ErrorCause::ErrorCauseCode2String.end())
63
- {
64
- return Unknown;
65
- }
66
-
67
- return it->second;
68
- }
69
-
70
70
  /* Instance methods. */
71
71
 
72
72
  ErrorCause::ErrorCause(uint8_t* buffer, size_t bufferLength) : TLV(buffer, bufferLength)
@@ -107,12 +107,12 @@ namespace RTC
107
107
  SetBuffer(const_cast<uint8_t*>(buffer));
108
108
  }
109
109
 
110
- void ErrorCause::InitializeHeader(ErrorCauseCode causeCode, uint16_t lengthFieldValue)
110
+ void ErrorCause::InitializeHeader(ErrorCauseCode causeCode, uint16_t length)
111
111
  {
112
112
  MS_TRACE();
113
113
 
114
114
  SetCode(causeCode);
115
- InitializeTLVHeader(lengthFieldValue);
115
+ InitializeTLVHeader(length);
116
116
  }
117
117
  } // namespace SCTP
118
118
  } // namespace RTC
@@ -32,6 +32,8 @@ namespace RTC
32
32
 
33
33
  bool Packet::IsSctp(const uint8_t* /*buffer*/, size_t bufferLength)
34
34
  {
35
+ MS_TRACE();
36
+
35
37
  return (
36
38
  bufferLength >= Packet::CommonHeaderLength && Utils::Byte::IsPaddedTo4Bytes(bufferLength));
37
39
  }
@@ -35,6 +35,22 @@ namespace RTC
35
35
 
36
36
  /* Class methods. */
37
37
 
38
+ const std::string& Parameter::ParameterTypeToString(ParameterType parameterType)
39
+ {
40
+ MS_TRACE();
41
+
42
+ static const std::string Unknown("UNKNOWN");
43
+
44
+ auto it = Parameter::ParameterType2String.find(parameterType);
45
+
46
+ if (it == Parameter::ParameterType2String.end())
47
+ {
48
+ return Unknown;
49
+ }
50
+
51
+ return it->second;
52
+ }
53
+
38
54
  bool Parameter::IsParameter(
39
55
  const uint8_t* buffer,
40
56
  size_t bufferLength,
@@ -54,22 +70,6 @@ namespace RTC
54
70
  return true;
55
71
  }
56
72
 
57
- const std::string& Parameter::ParameterTypeToString(ParameterType parameterType)
58
- {
59
- MS_TRACE();
60
-
61
- static const std::string Unknown("UNKNOWN");
62
-
63
- auto it = Parameter::ParameterType2String.find(parameterType);
64
-
65
- if (it == Parameter::ParameterType2String.end())
66
- {
67
- return Unknown;
68
- }
69
-
70
- return it->second;
71
- }
72
-
73
73
  /* Instance methods. */
74
74
 
75
75
  Parameter::Parameter(uint8_t* buffer, size_t bufferLength) : TLV(buffer, bufferLength)
@@ -110,12 +110,12 @@ namespace RTC
110
110
  SetBuffer(const_cast<uint8_t*>(buffer));
111
111
  }
112
112
 
113
- void Parameter::InitializeHeader(ParameterType parameterType, uint16_t lengthFieldValue)
113
+ void Parameter::InitializeHeader(ParameterType parameterType, uint16_t length)
114
114
  {
115
115
  MS_TRACE();
116
116
 
117
117
  SetType(parameterType);
118
- InitializeTLVHeader(lengthFieldValue);
118
+ InitializeTLVHeader(length);
119
119
  }
120
120
  } // namespace SCTP
121
121
  } // namespace RTC
@@ -80,31 +80,22 @@ namespace RTC
80
80
  GetBufferLength());
81
81
  }
82
82
 
83
- void TLV::InitializeTLVHeader(uint16_t lengthFieldValue)
83
+ void TLV::InitializeTLVHeader(uint16_t length)
84
84
  {
85
85
  MS_TRACE();
86
86
 
87
- SetLengthField(lengthFieldValue);
87
+ SetLengthField(length);
88
88
  }
89
89
 
90
- void TLV::SetLengthField(size_t lengthField)
90
+ void TLV::SetVariableLengthValue(const uint8_t* value, size_t valueLength)
91
91
  {
92
92
  MS_TRACE();
93
93
 
94
- if (lengthField > std::numeric_limits<uint16_t>::max())
94
+ if (value == nullptr && valueLength > 0)
95
95
  {
96
- MS_THROW_TYPE_ERROR("lengthField (%zu bytes) cannot be greater than 65535", lengthField);
96
+ MS_THROW_TYPE_ERROR("value cannot be nullptr if valueLength is > 0");
97
97
  }
98
98
 
99
- Utils::Byte::Set2Bytes(const_cast<uint8_t*>(GetBuffer()), 2, lengthField);
100
- }
101
-
102
- void TLV::SetVariableLengthValue(const uint8_t* value, size_t valueLength)
103
- {
104
- MS_TRACE();
105
-
106
- MS_ASSERT(value != nullptr || valueLength == 0, "value cannot be nullptr if valueLength is > 0");
107
-
108
99
  // NOTE: This can throw.
109
100
  SetVariableLengthValueLength(valueLength);
110
101
 
@@ -118,12 +109,12 @@ namespace RTC
118
109
  {
119
110
  MS_TRACE();
120
111
 
121
- auto previousLength = GetLength();
122
- auto previousLengthField = GetLengthField();
123
- auto previousValueLength = GetVariableLengthValueLength();
124
- auto newNotPaddedLength =
112
+ const size_t previousLength = GetLength();
113
+ const uint16_t previousLengthField = GetLengthField();
114
+ const uint16_t previousValueLength = GetVariableLengthValueLength();
115
+ const size_t newNotPaddedLength =
125
116
  size_t{ previousLengthField } - size_t{ previousValueLength } + valueLength;
126
- auto newPaddedLength = Utils::Byte::PadTo4Bytes(newNotPaddedLength);
117
+ const size_t newPaddedLength = Utils::Byte::PadTo4Bytes(newNotPaddedLength);
127
118
 
128
119
  try
129
120
  {
@@ -134,6 +125,10 @@ namespace RTC
134
125
  // Update length field.
135
126
  // NOTE: This will throw if computed value is too big.
136
127
  SetLengthField(newNotPaddedLength);
128
+
129
+ // Fill padding bytes with zero.
130
+ // NOTE: This may throw.
131
+ FillPadding(newPaddedLength - newNotPaddedLength);
137
132
  }
138
133
  catch (const MediaSoupError& error)
139
134
  {
@@ -143,17 +138,13 @@ namespace RTC
143
138
 
144
139
  throw;
145
140
  }
146
-
147
- // Fill padding bytes with zero.
148
- FillPadding(newPaddedLength - newNotPaddedLength);
149
141
  }
150
142
 
151
143
  void TLV::AddItem(const TLV* item)
152
144
  {
153
145
  MS_TRACE();
154
146
 
155
- auto previousLength = GetLength();
156
- auto previousLengthField = GetLengthField();
147
+ const size_t previousLength = GetLength();
157
148
 
158
149
  try
159
150
  {
@@ -169,10 +160,21 @@ namespace RTC
169
160
  {
170
161
  // Rollback.
171
162
  SetLength(previousLength);
172
- SetLengthField(previousLengthField);
173
163
 
174
164
  throw;
175
165
  }
176
166
  }
167
+
168
+ void TLV::SetLengthField(size_t length)
169
+ {
170
+ MS_TRACE();
171
+
172
+ if (length > std::numeric_limits<uint16_t>::max())
173
+ {
174
+ MS_THROW_TYPE_ERROR("length (%zu bytes) cannot be greater than 65535", length);
175
+ }
176
+
177
+ Utils::Byte::Set2Bytes(const_cast<uint8_t*>(GetBuffer()), 2, length);
178
+ }
177
179
  } // namespace SCTP
178
180
  } // namespace RTC
@@ -122,7 +122,7 @@ namespace RTC
122
122
  uint32_t remoteInitialTsn,
123
123
  uint32_t remoteAdvertisedReceiverWindowCredit,
124
124
  uint64_t tieTag,
125
- const NegotiatedCapabilities& negotiatedCapabilities,
125
+ const Capabilities& remoteCapabilities,
126
126
  uint64_t creationTimestampMs,
127
127
  const uint8_t* macKey,
128
128
  size_t macKeyLength)
@@ -147,7 +147,7 @@ namespace RTC
147
147
  remoteInitialTsn,
148
148
  remoteAdvertisedReceiverWindowCredit,
149
149
  tieTag,
150
- negotiatedCapabilities,
150
+ remoteCapabilities,
151
151
  creationTimestampMs,
152
152
  macKey,
153
153
  macKeyLength);
@@ -447,7 +447,10 @@ namespace RTC
447
447
 
448
448
  auto previousLayers = this->encodingContext->GetCurrentLayers();
449
449
 
450
- bool marker{ false };
450
+ // Preserve the original marker bit. ProcessPayload may update it (VP9/AV1
451
+ // overwrite it based on spatial-layer end-of-frame; VP8/H264 do not, so the
452
+ // original packet marker must survive).
453
+ bool marker{ packet->HasMarker() };
451
454
 
452
455
  if (!packet->ProcessPayload(this->encodingContext.get(), marker))
453
456
  {