mediasoup 3.21.2 → 3.23.0

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 (46) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/node/lib/PipeTransportTypes.d.ts +8 -0
  3. package/node/lib/PipeTransportTypes.d.ts.map +1 -1
  4. package/node/lib/PlainTransportTypes.d.ts +8 -0
  5. package/node/lib/PlainTransportTypes.d.ts.map +1 -1
  6. package/node/lib/Router.d.ts +6 -6
  7. package/node/lib/Router.d.ts.map +1 -1
  8. package/node/lib/Router.js +28 -25
  9. package/node/lib/RouterTypes.d.ts +8 -4
  10. package/node/lib/RouterTypes.d.ts.map +1 -1
  11. package/node/lib/WebRtcTransportTypes.d.ts +8 -0
  12. package/node/lib/WebRtcTransportTypes.d.ts.map +1 -1
  13. package/node/lib/fbs/transport/options.d.ts +5 -2
  14. package/node/lib/fbs/transport/options.d.ts.map +1 -1
  15. package/node/lib/fbs/transport/options.js +18 -7
  16. package/node/lib/test/test-DataConsumer.js +3 -0
  17. package/node/lib/test/test-PipeTransport.js +33 -1
  18. package/package.json +11 -11
  19. package/worker/fbs/transport.fbs +1 -0
  20. package/worker/fuzzer/src/RTC/RTP/FuzzerPacket.cpp +44 -0
  21. package/worker/include/RTC/DataConsumer.hpp +7 -10
  22. package/worker/include/RTC/PipeTransport.hpp +4 -0
  23. package/worker/include/RTC/SCTP/public/Message.hpp +16 -0
  24. package/worker/include/RTC/SCTP/public/SctpOptions.hpp +7 -0
  25. package/worker/include/RTC/SCTP/tx/RoundRobinSendQueue.hpp +2 -0
  26. package/worker/include/RTC/SubchannelsCodec.hpp +76 -0
  27. package/worker/include/RTC/Transport.hpp +4 -5
  28. package/worker/meson.build +2 -0
  29. package/worker/scripts/package-lock.json +8 -7
  30. package/worker/src/RTC/DataConsumer.cpp +45 -62
  31. package/worker/src/RTC/ICE/StunPacket.cpp +6 -2
  32. package/worker/src/RTC/RTP/Packet.cpp +11 -0
  33. package/worker/src/RTC/SCTP/association/Association.cpp +1 -0
  34. package/worker/src/RTC/SCTP/association/StateCookie.cpp +5 -2
  35. package/worker/src/RTC/SCTP/packet/errorCauses/MissingMandatoryParameterErrorCause.cpp +4 -1
  36. package/worker/src/RTC/SCTP/tx/RoundRobinSendQueue.cpp +10 -2
  37. package/worker/src/RTC/SrtpSession.cpp +82 -25
  38. package/worker/src/RTC/SubchannelsCodec.cpp +153 -0
  39. package/worker/src/RTC/Transport.cpp +26 -58
  40. package/worker/subprojects/libsrtp3.wrap +4 -4
  41. package/worker/tasks.py +1 -1
  42. package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +34 -0
  43. package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +1 -0
  44. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestMissingMandatoryParameterErrorCause.cpp +24 -0
  45. package/worker/test/src/RTC/SCTP/tx/TestRoundRobinSendQueue.cpp +180 -39
  46. package/worker/test/src/RTC/TestSubchannelsCodec.cpp +224 -0
@@ -5,7 +5,6 @@
5
5
  #include "DepLibSRTP.hpp"
6
6
  #include "Logger.hpp"
7
7
  #include "MediaSoupErrors.hpp"
8
- #include <cstring> // std::memset()
9
8
 
10
9
  namespace RTC
11
10
  {
@@ -127,42 +126,34 @@ namespace RTC
127
126
  {
128
127
  MS_TRACE();
129
128
 
130
- srtp_policy_t policy; // NOLINT(cppcoreguidelines-pro-type-member-init)
131
-
132
- // Set all policy fields to 0.
133
- std::memset(&policy, 0, sizeof(srtp_policy_t));
129
+ srtp_profile_t profile;
134
130
 
135
131
  switch (cryptoSuite)
136
132
  {
137
133
  case CryptoSuite::AEAD_AES_256_GCM:
138
134
  {
139
- srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
140
- srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp);
135
+ profile = srtp_profile_aead_aes_256_gcm;
141
136
 
142
137
  break;
143
138
  }
144
139
 
145
140
  case CryptoSuite::AEAD_AES_128_GCM:
146
141
  {
147
- srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
148
- srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp);
142
+ profile = srtp_profile_aead_aes_128_gcm;
149
143
 
150
144
  break;
151
145
  }
152
146
 
153
147
  case CryptoSuite::AES_CM_128_HMAC_SHA1_80:
154
148
  {
155
- srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
156
- srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
149
+ profile = srtp_profile_aes128_cm_sha1_80;
157
150
 
158
151
  break;
159
152
  }
160
153
 
161
154
  case CryptoSuite::AES_CM_128_HMAC_SHA1_32:
162
155
  {
163
- srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
164
- // NOTE: Must be 80 for RTCP.
165
- srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
156
+ profile = srtp_profile_aes128_cm_sha1_32;
166
157
 
167
158
  break;
168
159
  }
@@ -173,35 +164,101 @@ namespace RTC
173
164
  }
174
165
  }
175
166
 
176
- MS_ASSERT(
177
- keyLen == policy.rtp.cipher_key_len, "given keyLen does not match policy.rtp.cipher_keyLen");
167
+ // Create the policy object.
168
+ srtp_policy_t policy{ nullptr };
169
+ srtp_err_status_t err = srtp_policy_create(std::addressof(policy));
170
+
171
+ if (DepLibSRTP::IsError(err))
172
+ {
173
+ MS_THROW_ERROR("srtp_policy_create() failed: %s", DepLibSRTP::GetErrorString(err).c_str());
174
+ }
175
+
176
+ // Set SSRC.
177
+ srtp_ssrc_t ssrc{};
178
178
 
179
179
  switch (type)
180
180
  {
181
181
  case Type::INBOUND:
182
182
  {
183
- policy.ssrc.type = ssrc_any_inbound;
183
+ ssrc.type = ssrc_any_inbound;
184
184
 
185
185
  break;
186
186
  }
187
187
 
188
188
  case Type::OUTBOUND:
189
189
  {
190
- policy.ssrc.type = ssrc_any_outbound;
190
+ ssrc.type = ssrc_any_outbound;
191
191
 
192
192
  break;
193
193
  }
194
194
  }
195
195
 
196
- policy.ssrc.value = 0;
197
- policy.key = key;
196
+ ssrc.value = 0;
197
+
198
+ err = srtp_policy_set_ssrc(policy, ssrc);
199
+
200
+ if (DepLibSRTP::IsError(err))
201
+ {
202
+ srtp_policy_destroy(policy);
203
+ MS_THROW_ERROR("srtp_policy_set_ssrc() failed: %s", DepLibSRTP::GetErrorString(err).c_str());
204
+ }
205
+
206
+ // Set the crypto profile.
207
+ err = srtp_policy_set_profile(policy, profile);
208
+
209
+ if (DepLibSRTP::IsError(err))
210
+ {
211
+ srtp_policy_destroy(policy);
212
+ MS_THROW_ERROR("srtp_policy_set_profile() failed: %s", DepLibSRTP::GetErrorString(err).c_str());
213
+ }
214
+
215
+ // Split the concatenated key+salt buffer using the profile's lengths.
216
+ const size_t masterKeyLen = srtp_profile_get_master_key_length(profile);
217
+ const size_t masterSaltLen = srtp_profile_get_master_salt_length(profile);
218
+
219
+ MS_ASSERT(
220
+ keyLen == masterKeyLen + masterSaltLen,
221
+ "given keyLen does not match profile master key + salt length");
222
+
223
+ err = srtp_policy_add_key(
224
+ policy,
225
+ /*key*/ key,
226
+ /*key_len*/ masterKeyLen,
227
+ /*salt*/ key + masterKeyLen,
228
+ /*salt_len*/ masterSaltLen,
229
+ /*mki*/ nullptr,
230
+ /*mki_len*/ 0);
231
+
232
+ if (DepLibSRTP::IsError(err))
233
+ {
234
+ srtp_policy_destroy(policy);
235
+ MS_THROW_ERROR("srtp_policy_add_key() failed: %s", DepLibSRTP::GetErrorString(err).c_str());
236
+ }
237
+
198
238
  // Required for sending RTP retransmission without RTX.
199
- policy.allow_repeat_tx = true;
200
- policy.window_size = 1024;
201
- policy.next = nullptr;
239
+ err = srtp_policy_set_allow_repeat_tx(policy, true);
240
+
241
+ if (DepLibSRTP::IsError(err))
242
+ {
243
+ srtp_policy_destroy(policy);
244
+ MS_THROW_ERROR(
245
+ "srtp_policy_set_allow_repeat_tx() failed: %s", DepLibSRTP::GetErrorString(err).c_str());
246
+ }
247
+
248
+ err = srtp_policy_set_window_size(policy, 1024);
249
+
250
+ if (DepLibSRTP::IsError(err))
251
+ {
252
+ srtp_policy_destroy(policy);
253
+ MS_THROW_ERROR(
254
+ "srtp_policy_set_window_size() failed: %s", DepLibSRTP::GetErrorString(err).c_str());
255
+ }
256
+
257
+ // Create the SRTP session.
258
+ err = srtp_create(std::addressof(this->session), policy);
202
259
 
203
- // Set the SRTP session.
204
- const srtp_err_status_t err = srtp_create(&this->session, &policy);
260
+ // Policy is no longer needed once the session is created.
261
+ srtp_policy_destroy(policy);
205
262
 
206
263
  if (DepLibSRTP::IsError(err))
207
264
  {
@@ -0,0 +1,153 @@
1
+ #define MS_CLASS "RTC::SubchannelsCodec"
2
+ // #define MS_LOG_DEV_LEVEL 3
3
+
4
+ #include "RTC/SubchannelsCodec.hpp"
5
+ #include "Logger.hpp"
6
+ #include "Utils.hpp"
7
+
8
+ namespace RTC
9
+ {
10
+ /* Class methods. */
11
+
12
+ bool SubchannelsCodec::EncodeSubchannels(
13
+ RTC::SCTP::Message& message,
14
+ const std::vector<uint16_t>& subchannels,
15
+ std::optional<uint16_t> requiredSubchannel)
16
+ {
17
+ MS_TRACE();
18
+
19
+ // Nothing to encode.
20
+ if (subchannels.empty() && !requiredSubchannel.has_value())
21
+ {
22
+ return false;
23
+ }
24
+
25
+ if (subchannels.size() > 0xFFFF)
26
+ {
27
+ MS_ERROR("too many subchannels to encode [count:%zu]", subchannels.size());
28
+
29
+ return false;
30
+ }
31
+
32
+ const auto subchannelsCount = static_cast<uint16_t>(subchannels.size());
33
+ const bool requiredSubchannelFlag = requiredSubchannel.has_value();
34
+
35
+ // Length of the header to prepend.
36
+ size_t headerLen =
37
+ 8 /* Magic Token */ + 2 /* subchannelsCount */ + (static_cast<size_t>(subchannelsCount) * 2);
38
+
39
+ if (requiredSubchannelFlag)
40
+ {
41
+ headerLen += 2;
42
+ }
43
+
44
+ const auto payload = message.GetPayload();
45
+
46
+ // Build the whole new payload at once (header followed by the original
47
+ // payload) so it can be moved into the message with a single allocation.
48
+ std::vector<uint8_t> newPayload(headerLen + payload.size());
49
+
50
+ uint64_t magicToken = SubchannelsCodec::MagicToken;
51
+
52
+ if (requiredSubchannelFlag)
53
+ {
54
+ magicToken |= SubchannelsCodec::RequiredSubchannelFlagMask;
55
+ }
56
+
57
+ size_t offset = 0;
58
+
59
+ Utils::Byte::Set8Bytes(newPayload.data(), offset, magicToken);
60
+ offset += 8;
61
+
62
+ Utils::Byte::Set2Bytes(newPayload.data(), offset, subchannelsCount);
63
+ offset += 2;
64
+
65
+ for (const auto subchannel : subchannels)
66
+ {
67
+ Utils::Byte::Set2Bytes(newPayload.data(), offset, subchannel);
68
+ offset += 2;
69
+ }
70
+
71
+ if (requiredSubchannelFlag)
72
+ {
73
+ Utils::Byte::Set2Bytes(newPayload.data(), offset, requiredSubchannel.value());
74
+ offset += 2;
75
+ }
76
+
77
+ // Append the original payload right after the encoded header.
78
+ std::ranges::copy(payload, newPayload.begin() + offset);
79
+
80
+ message.SetPayload(std::move(newPayload));
81
+
82
+ return true;
83
+ }
84
+
85
+ bool SubchannelsCodec::DecodeSubchannels(
86
+ RTC::SCTP::Message& message,
87
+ std::vector<uint16_t>& subchannels,
88
+ std::optional<uint16_t>& requiredSubchannel)
89
+ {
90
+ MS_TRACE();
91
+
92
+ const auto payload = message.GetPayload();
93
+ const size_t len = payload.size();
94
+
95
+ // Not even enough bytes to hold the Magic Token and `subchannelsCount` field,
96
+ // so nothing to decode.
97
+ if (len < 10)
98
+ {
99
+ return false;
100
+ }
101
+
102
+ const uint64_t magicToken = Utils::Byte::Get8Bytes(payload.data(), 0);
103
+
104
+ // The message does not start with the Magic Token, so nothing to decode.
105
+ if ((magicToken & ~SubchannelsCodec::RequiredSubchannelFlagMask) != SubchannelsCodec::MagicToken)
106
+ {
107
+ return false;
108
+ }
109
+
110
+ const bool requiredSubchannelFlag =
111
+ (magicToken & SubchannelsCodec::RequiredSubchannelFlagMask) != 0;
112
+
113
+ const uint16_t subchannelsCount = Utils::Byte::Get2Bytes(payload.data(), 8);
114
+
115
+ // Offset right after the Magic Token and subchannelsCount fields.
116
+ size_t offset = 10;
117
+
118
+ // Bytes needed to hold all announced subchannels and, if present, the
119
+ // requiredSubchannel.
120
+ size_t neededLen = offset + (static_cast<size_t>(subchannelsCount) * 2);
121
+
122
+ if (requiredSubchannelFlag)
123
+ {
124
+ neededLen += 2;
125
+ }
126
+
127
+ if (len < neededLen)
128
+ {
129
+ MS_WARN_DEV("message too short to hold announced subchannels, ignoring");
130
+
131
+ return false;
132
+ }
133
+
134
+ subchannels.reserve(subchannelsCount);
135
+
136
+ for (uint16_t i = 0; i < subchannelsCount; ++i)
137
+ {
138
+ subchannels.push_back(Utils::Byte::Get2Bytes(payload.data(), offset));
139
+ offset += 2;
140
+ }
141
+
142
+ if (requiredSubchannelFlag)
143
+ {
144
+ requiredSubchannel = Utils::Byte::Get2Bytes(payload.data(), offset);
145
+ offset += 2;
146
+ }
147
+
148
+ // Remove the decoded header from the beginning of the message payload.
149
+ message.RemovePayloadFront(offset);
150
+
151
+ return true;
152
+ }
153
+ } // namespace RTC
@@ -18,6 +18,7 @@
18
18
  #include "RTC/RtpDictionaries.hpp"
19
19
  #include "RTC/SCTP/association/Association.hpp"
20
20
  #include "RTC/SCTP/public/SctpOptions.hpp"
21
+ #include "RTC/SubchannelsCodec.hpp"
21
22
  #include "Utils.hpp"
22
23
  #ifdef MS_RTC_LOGGER_RTP
23
24
  #include "RTC/RtcLogger.hpp"
@@ -48,20 +49,10 @@ namespace RTC
48
49
  {
49
50
  MS_TRACE();
50
51
 
52
+ this->direct = options->direct();
51
53
  this->maxSendMessageSize = options->maxSendMessageSize();
52
54
  this->maxReceiveMessageSize = options->maxReceiveMessageSize();
53
55
 
54
- if (options->direct())
55
- {
56
- this->direct = true;
57
- }
58
- else
59
- {
60
- this->sctpSendBufferSize = options->sctpSendBufferSize();
61
- this->sctpPerStreamSendQueueLimit = options->sctpPerStreamSendQueueLimit();
62
- this->sctpMaxReceiverWindowBufferSize = options->sctpMaxReceiverWindowBufferSize();
63
- }
64
-
65
56
  if (
66
57
  auto initialAvailableOutgoingBitrate = options->initialAvailableOutgoingBitrate();
67
58
  initialAvailableOutgoingBitrate.has_value())
@@ -79,11 +70,13 @@ namespace RTC
79
70
  const RTC::SCTP::SctpOptions sctpOptions = {
80
71
  .mtu = RTC::Consts::MaxSafeMtuSizeForSctp,
81
72
  .maxSendMessageSize = this->maxSendMessageSize,
82
- .maxSendBufferSize = this->sctpSendBufferSize,
83
- .perStreamSendQueueLimit = this->sctpPerStreamSendQueueLimit,
73
+ .maxSendBufferSize = options->sctpSendBufferSize(),
74
+ .perStreamSendQueueLimit = options->sctpPerStreamSendQueueLimit(),
84
75
  .maxReceiveMessageSize = this->maxReceiveMessageSize,
85
- .maxReceiverWindowBufferSize = this->sctpMaxReceiverWindowBufferSize,
86
- .requireAuthenticatedCookie = requireSctpStateCookieAuthentication
76
+ .maxReceiverWindowBufferSize = options->sctpMaxReceiverWindowBufferSize(),
77
+ .defaultStreamBufferedAmountLowThreshold =
78
+ options->sctpDefaultStreamBufferedAmountLowThreshold(),
79
+ .requireAuthenticatedCookie = requireSctpStateCookieAuthentication
87
80
  };
88
81
 
89
82
  this->sctpAssociation = std::make_unique<RTC::SCTP::Association>(
@@ -1111,7 +1104,13 @@ namespace RTC
1111
1104
 
1112
1105
  // This may throw.
1113
1106
  auto* dataConsumer = new RTC::DataConsumer(
1114
- this->shared, dataConsumerId, dataProducerId, this, body, this->maxSendMessageSize);
1107
+ this->shared,
1108
+ dataConsumerId,
1109
+ dataProducerId,
1110
+ this,
1111
+ body,
1112
+ this->maxSendMessageSize,
1113
+ this->IsPipe());
1115
1114
 
1116
1115
  // Verify the type of the DataConsumer.
1117
1116
  switch (dataConsumer->GetType())
@@ -1189,19 +1188,8 @@ namespace RTC
1189
1188
 
1190
1189
  request->Accept(FBS::Response::Body::DataConsumer_DumpResponse, dumpOffset);
1191
1190
 
1192
- if (IsConnected())
1193
- {
1194
- dataConsumer->TransportConnected();
1195
- }
1196
-
1197
1191
  if (dataConsumer->GetType() == RTC::DataConsumer::Type::SCTP)
1198
1192
  {
1199
- if (this->sctpAssociation->GetAssociationState() == RTC::SCTP::Types::AssociationState::CONNECTED)
1200
- {
1201
- // Tell to the DataConsumer.
1202
- dataConsumer->SctpAssociationConnected();
1203
- }
1204
-
1205
1193
  // Tell to the SCTP association.
1206
1194
  this->sctpAssociation->MayConnect();
1207
1195
  }
@@ -1480,14 +1468,6 @@ namespace RTC
1480
1468
  consumer->TransportConnected();
1481
1469
  }
1482
1470
 
1483
- // Tell all DataConsumers.
1484
- for (auto& kv : this->mapDataConsumers)
1485
- {
1486
- auto* dataConsumer = kv.second;
1487
-
1488
- dataConsumer->TransportConnected();
1489
- }
1490
-
1491
1471
  // Tell the SctpAssociation.
1492
1472
  if (this->sctpAssociation)
1493
1473
  {
@@ -1530,14 +1510,6 @@ namespace RTC
1530
1510
  consumer->TransportDisconnected();
1531
1511
  }
1532
1512
 
1533
- // Tell all DataConsumers.
1534
- for (auto& kv : this->mapDataConsumers)
1535
- {
1536
- auto* dataConsumer = kv.second;
1537
-
1538
- dataConsumer->TransportDisconnected();
1539
- }
1540
-
1541
1513
  // Stop the RTCP timer.
1542
1514
  this->rtcpTimer->Stop();
1543
1515
 
@@ -2999,17 +2971,6 @@ namespace RTC
2999
2971
  {
3000
2972
  MS_TRACE();
3001
2973
 
3002
- // Tell all DataConsumers.
3003
- for (auto& kv : this->mapDataConsumers)
3004
- {
3005
- auto* dataConsumer = kv.second;
3006
-
3007
- if (dataConsumer->GetType() == RTC::DataConsumer::Type::SCTP)
3008
- {
3009
- dataConsumer->SctpAssociationConnected();
3010
- }
3011
- }
3012
-
3013
2974
  // Notify the upper layer.
3014
2975
 
3015
2976
  // First tell it about the SCTP negotiated capabilities.
@@ -3041,7 +3002,7 @@ namespace RTC
3041
3002
 
3042
3003
  // For debugging purposes.
3043
3004
  #if MS_LOG_DEV_LEVEL == 3
3044
- MS_DUMP("--- SCTP association connected:");
3005
+ MS_DUMP("SCTP association connected:");
3045
3006
  this->sctpAssociation->Dump();
3046
3007
  #endif
3047
3008
  }
@@ -3187,10 +3148,17 @@ namespace RTC
3187
3148
  // Pass the SCTP message to the corresponding DataProducer.
3188
3149
  try
3189
3150
  {
3190
- static thread_local std::vector<uint16_t> emptySubchannels;
3151
+ std::vector<uint16_t> subchannels;
3152
+ std::optional<uint16_t> requiredSubchannel;
3153
+
3154
+ // When this is a pipe transport, the subchannels and required subchannel
3155
+ // may be encoded at the beginning of the message payload.
3156
+ if (this->IsPipe())
3157
+ {
3158
+ RTC::SubchannelsCodec::DecodeSubchannels(message, subchannels, requiredSubchannel);
3159
+ }
3191
3160
 
3192
- dataProducer->ReceiveMessage(
3193
- std::move(message), emptySubchannels, /*requiredSubchannel*/ std::nullopt);
3161
+ dataProducer->ReceiveMessage(std::move(message), subchannels, requiredSubchannel);
3194
3162
  }
3195
3163
  catch (std::exception& error)
3196
3164
  {
@@ -1,8 +1,8 @@
1
1
  [wrap-file]
2
- directory = libsrtp-3.0.0-beta
3
- source_url = https://github.com/versatica/libsrtp/archive/v3.0.0-beta.zip
4
- source_filename = libsrtp-3.0.0-beta.zip
5
- source_hash = b0cb21aaf27120b1a242f3d9b07c145b4a6c7a02a25da0824539fd95611f690c
2
+ directory = libsrtp-3.0.0-beta-2fc078db
3
+ source_url = https://github.com/versatica/libsrtp/archive/v3.0.0-beta-2fc078db.zip
4
+ source_filename = libsrtp-3.0.0-beta-2fc078db.zip
5
+ source_hash = d2c0fc2fdb84c615ed835471014611fb0b55f92c183c690ebeceb6ad4821a8b9
6
6
 
7
7
  [provide]
8
8
  libsrtp3 = libsrtp3_dep
package/worker/tasks.py CHANGED
@@ -43,7 +43,7 @@ NUM_CORES = (
43
43
  )
44
44
  PYTHON = os.getenv("PYTHON") or sys.executable
45
45
  MESON = os.getenv("MESON") or f"{PIP_MESON_NINJA_DIR}/bin/meson"
46
- MESON_VERSION = os.getenv("MESON_VERSION") or "1.9.1"
46
+ MESON_VERSION = os.getenv("MESON_VERSION") or "1.11.2"
47
47
  # MESON_ARGS can be used to provide extra configuration parameters to meson,
48
48
  # such as adding defines or changing optimization options. For instance, use
49
49
  # `MESON_ARGS="-Dms_log_trace=true -Dms_log_file_line=true" npm i` to compile
@@ -1057,6 +1057,40 @@ SCENARIO("SCTP Association", "[sctp][association]")
1057
1057
  REQUIRE(a.listener.HasOnStreamBufferedAmountLowBeenCalledWithStreamId(1) == true);
1058
1058
  }
1059
1059
 
1060
+ SECTION("applies the configured default buffered amount low threshold to new streams")
1061
+ {
1062
+ auto sctpOptions = makeSctpOptions();
1063
+
1064
+ sctpOptions.defaultStreamBufferedAmountLowThreshold = 1024;
1065
+
1066
+ AssociationUnderTest a(sctpOptions);
1067
+
1068
+ // Sending a message creates the outgoing stream, which must inherit the
1069
+ // configured default buffered amount low threshold.
1070
+ sendMessage(a, 1, 53, std::vector<uint8_t>(10));
1071
+
1072
+ REQUIRE(a.association.GetStreamBufferedAmountLowThreshold(1) == 1024);
1073
+ }
1074
+
1075
+ SECTION("does not trigger buffered amount low until crossing a non-zero default threshold")
1076
+ {
1077
+ auto sctpOptions = makeSctpOptions();
1078
+
1079
+ sctpOptions.defaultStreamBufferedAmountLowThreshold = 1024;
1080
+
1081
+ AssociationUnderTest a(sctpOptions);
1082
+ AssociationUnderTest z;
1083
+
1084
+ connectAssociations(a, z);
1085
+
1086
+ // A small message never takes the buffered amount above the threshold, so
1087
+ // draining it must not trigger the event.
1088
+ sendMessage(a, 1, 53, std::vector<uint8_t>(10));
1089
+ exchangeMessages(a, z);
1090
+
1091
+ REQUIRE(a.listener.HasOnStreamBufferedAmountLowBeenCalledWithStreamId(1) == false);
1092
+ }
1093
+
1060
1094
  SECTION("detects the peer implementation")
1061
1095
  {
1062
1096
  AssociationUnderTest a;
@@ -57,6 +57,7 @@ namespace
57
57
  this->associationListener,
58
58
  this->sctpOptions.mtu,
59
59
  this->sctpOptions.defaultStreamPriority,
60
+ this->sctpOptions.defaultStreamBufferedAmountLowThreshold,
60
61
  this->sctpOptions.totalBufferedAmountLowThreshold),
61
62
  dataTracker(this->delayedAckTimer.get(), RemoteInitialTsn),
62
63
  reassemblyQueue(this->sctpOptions.maxReceiverWindowBufferSize),
@@ -164,6 +164,30 @@ SCENARIO("Invalid Stream Identifier Error Cause (2)", "[serializable][sctp][erro
164
164
  // clang-format on
165
165
 
166
166
  REQUIRE(!RTC::SCTP::MissingMandatoryParameterErrorCause::Parse(buffer3, sizeof(buffer3)));
167
+
168
+ // Security advisory.
169
+ // See https://github.com/versatica/mediasoup/security/advisories/GHSA-p9cq-fqxc-987w
170
+ //
171
+ // Number of missing parameters chosen so that, multiplied by 2 in 32-bit
172
+ // arithmetic, it wraps around to a value that would falsely match the
173
+ // length field. 0x80000001 (2147483649) * 2 wraps to 2, which equals
174
+ // Length 10 minus the 8-byte header. The check must be done in 64-bit
175
+ // arithmetic so this malformed cause is rejected instead of accepted
176
+ // (which would later drive an out-of-bounds read while iterating the
177
+ // bogus 2.1 billion parameter count).
178
+ // clang-format off
179
+ alignas(4) uint8_t buffer4[] =
180
+ {
181
+ // Code:2 (MISSING-MANDATORY-PARAMETER), Length: 10
182
+ 0x00, 0x02, 0x00, 0x0A,
183
+ // Number of missing params: 0x80000001 (2147483649)
184
+ 0x80, 0x00, 0x00, 0x01,
185
+ // A single param type (2 bytes) plus 2 bytes of padding
186
+ 0x00, 0x05, 0x00, 0x00,
187
+ };
188
+ // clang-format on
189
+
190
+ REQUIRE(!RTC::SCTP::MissingMandatoryParameterErrorCause::Parse(buffer4, sizeof(buffer4)));
167
191
  }
168
192
 
169
193
  SECTION("MissingMandatoryParameterErrorCause::Factory() succeeds")