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
@@ -130,6 +130,7 @@ table Options {
130
130
  sctp_send_buffer_size: uint32;
131
131
  sctp_per_stream_send_queue_limit: uint32;
132
132
  sctp_max_receiver_window_buffer_size: uint32;
133
+ sctp_default_stream_buffered_amount_low_threshold: uint32;
133
134
  is_data_channel: bool = false;
134
135
  }
135
136
 
@@ -254,4 +254,48 @@ void FuzzerRtcRtcPacket::Fuzz(const uint8_t* data, size_t len)
254
254
  packet->RemoveHeaderExtension();
255
255
  packet->SetPayloadLength(sizeof(payload) - 2);
256
256
  packet->RemovePayload();
257
+
258
+ // Regression test for GHSA-jhm4-v227-4375 (CWE-787 OOB write in
259
+ // UpdateDependencyDescriptor()). Build a fresh packet with a tightly-sized
260
+ // DEPENDENCY_DESCRIPTOR value and attempt to update it with the raw fuzzer
261
+ // input as the new descriptor bytes. When the new length exceeds the original
262
+ // the fixed code must return false without writing out of bounds; when it
263
+ // fits it must succeed. AddressSanitizer will catch any regression here.
264
+ {
265
+ constexpr size_t BufferLenght{ 512 };
266
+ static thread_local uint8_t buffer[BufferLenght];
267
+
268
+ std::unique_ptr<RTC::RTP::Packet> packet{ RTC::RTP::Packet::Factory(buffer, BufferLenght) };
269
+
270
+ if (!packet)
271
+ {
272
+ return;
273
+ }
274
+
275
+ // Use the first byte of the fuzzer input to pick the slot size
276
+ // (1..15 is the valid One-Byte extension range).
277
+ const uint8_t extenLen = (data[0] % 15u) + 1u;
278
+
279
+ static thread_local uint8_t extenValue[15];
280
+
281
+ // clang-format off
282
+ const std::vector<RTC::RTP::Packet::Extension> extensions {
283
+ {
284
+ RTC::RtpHeaderExtensionUri::Type::DEPENDENCY_DESCRIPTOR,
285
+ static_cast<uint8_t>(RTC::RtpHeaderExtensionUri::Type::DEPENDENCY_DESCRIPTOR),
286
+ extenLen,
287
+ extenValue
288
+ }
289
+ };
290
+ // clang-format off
291
+
292
+ packet->SetExtensions(RTC::RTP::Packet::ExtensionsType::OneByte, extensions);
293
+
294
+ // Call UpdateDependencyDescriptor() with the full fuzzer input as
295
+ // the replacement bytes. This covers:
296
+ // len > slotLen → no OOB write (was the bug).
297
+ // len <= slotLen → in-place update.
298
+ // len == 0 → must not crash.
299
+ packet->UpdateDependencyDescriptor(data, len);
300
+ }
257
301
  }
@@ -49,7 +49,8 @@ namespace RTC
49
49
  const std::string& dataProducerId,
50
50
  RTC::DataConsumer::Listener* listener,
51
51
  const FBS::Transport::ConsumeDataRequest* data,
52
- size_t maxMessageSize);
52
+ size_t maxMessageSize,
53
+ bool pipe);
53
54
  ~DataConsumer() override;
54
55
 
55
56
  public:
@@ -67,20 +68,17 @@ namespace RTC
67
68
  }
68
69
  bool IsActive() const
69
70
  {
70
- // It's active it DataConsumer and DataProducer are not paused and the transport
71
- // is connected.
71
+ // It's active it DataConsumer and DataProducer are not paused and the SCTP
72
+ // association (if any) is not closed.
72
73
  // clang-format off
73
74
  return (
74
- this->transportConnected &&
75
- (this->type == DataConsumer::Type::DIRECT || this->sctpAssociationConnected) &&
75
+ (this->type == DataConsumer::Type::DIRECT || !this->sctpAssociationClosed) &&
76
76
  !this->paused &&
77
77
  !this->dataProducerPaused &&
78
78
  !this->dataProducerClosed
79
79
  );
80
80
  // clang-format on
81
81
  }
82
- void TransportConnected();
83
- void TransportDisconnected();
84
82
  bool IsPaused() const
85
83
  {
86
84
  return this->paused;
@@ -91,7 +89,6 @@ namespace RTC
91
89
  }
92
90
  void DataProducerPaused();
93
91
  void DataProducerResumed();
94
- void SctpAssociationConnected();
95
92
  void SctpAssociationClosed();
96
93
  void SctpBufferedAmountLow(uint32_t bufferedAmount) const;
97
94
  void SctpSendBufferFull() const;
@@ -116,14 +113,14 @@ namespace RTC
116
113
  SharedInterface* shared{ nullptr };
117
114
  RTC::DataConsumer::Listener* listener{ nullptr };
118
115
  size_t maxMessageSize{ 0u };
116
+ bool pipe{ false };
119
117
  // Others.
120
118
  Type type;
121
119
  RTC::SctpStreamParameters sctpStreamParameters;
122
120
  std::string label;
123
121
  std::string protocol;
124
122
  ankerl::unordered_dense::set<uint16_t> subchannels;
125
- bool transportConnected{ false };
126
- bool sctpAssociationConnected{ false };
123
+ bool sctpAssociationClosed{ false };
127
124
  bool paused{ false };
128
125
  bool dataProducerPaused{ false };
129
126
  bool dataProducerClosed{ false };
@@ -41,6 +41,10 @@ namespace RTC
41
41
 
42
42
  private:
43
43
  bool IsConnected() const override;
44
+ bool IsPipe() const override
45
+ {
46
+ return true;
47
+ }
44
48
  bool HasSrtp() const;
45
49
  void SendRtpPacket(
46
50
  RTC::Consumer* consumer,
@@ -68,6 +68,22 @@ namespace RTC
68
68
  return this->payload.size();
69
69
  }
70
70
 
71
+ /**
72
+ * Replace the whole payload of the message.
73
+ */
74
+ void SetPayload(std::vector<uint8_t> payload)
75
+ {
76
+ this->payload = std::move(payload);
77
+ }
78
+
79
+ /**
80
+ * Remove the first `len` bytes from the beginning of the payload.
81
+ */
82
+ void RemovePayloadFront(size_t len)
83
+ {
84
+ this->payload.erase(this->payload.begin(), this->payload.begin() + len);
85
+ }
86
+
71
87
  /**
72
88
  * Useful to extract the payload and its ownership when destructing the
73
89
  * message.
@@ -83,6 +83,13 @@ namespace RTC
83
83
  */
84
84
  size_t maxReceiverWindowBufferSize{ 5 * 1024 * 1024 };
85
85
 
86
+ /**
87
+ * The default threshold that, when the amount of data in a stream send
88
+ * buffer goes below this value, will trigger
89
+ * `Association::OnAssociationStreamBufferedAmountLow()`.
90
+ */
91
+ size_t defaultStreamBufferedAmountLowThreshold{ 0 };
92
+
86
93
  /**
87
94
  * A threshold that, when the amount of data in the send buffer goes below
88
95
  * this value, will trigger `Association::OnAssociationTotalBufferedAmountLow()`.
@@ -275,6 +275,7 @@ namespace RTC
275
275
  AssociationListenerInterface& associationListener,
276
276
  size_t mtu,
277
277
  uint16_t defaultPriority,
278
+ size_t defaultStreamBufferedAmountLowThreshold,
278
279
  size_t totalBufferedAmountLowThreshold);
279
280
 
280
281
  ~RoundRobinSendQueue() override;
@@ -343,6 +344,7 @@ namespace RTC
343
344
  private:
344
345
  AssociationListenerInterface& associationListener;
345
346
  const uint16_t defaultPriority;
347
+ const size_t defaultStreamBufferedAmountLowThreshold;
346
348
  StreamScheduler scheduler;
347
349
  // The total amount of buffer data, for all streams.
348
350
  ThresholdWatcher totalBufferedAmountThresholdWatcher;
@@ -0,0 +1,76 @@
1
+ #ifndef MS_RTC_SUBCHANNELS_CODEC_HPP
2
+ #define MS_RTC_SUBCHANNELS_CODEC_HPP
3
+
4
+ #include "common.hpp"
5
+ #include "RTC/SCTP/public/Message.hpp"
6
+ #include <vector>
7
+
8
+ namespace RTC
9
+ {
10
+ /**
11
+ * Helper to (optionally) encode/decode subchannels and required subchannel at
12
+ * the beginning of an SCTP message payload so that this information travels
13
+ * within the SCTP message itself.
14
+ */
15
+ class SubchannelsCodec
16
+ {
17
+ /**
18
+ * Wire layout of the encoded header prepended to the message payload (all
19
+ * fields in network byte order). `R` is the `requiredSubchannelFlag`, i.e.
20
+ * the least significant bit of the Magic Token. The `requiredSubchannel`
21
+ * field is only present when `R` is 1.
22
+ *
23
+ * 0 1 2 3
24
+ * 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
25
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
+ * | Magic Token (1/2) |
27
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
+ * | Magic Token (2/2) |R|
29
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30
+ * | subchannelsCount | Subchannel 0 |
31
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32
+ * | ... |
33
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34
+ * | Subchannel N-1 | requiredSubchannel (if R=1) |
35
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36
+ */
37
+
38
+ public:
39
+ /**
40
+ * 8-byte Magic Token that prefixes an encoded payload. It is intentionally
41
+ * made of non-printable high bytes and starts with a byte that is not a valid
42
+ * UTF-8 leading byte (0x80-0xBF), so a real string message (valid UTF-8) can
43
+ * never begin with it and the chance of colliding with a binary message is
44
+ * negligible. Its least significant bit is reserved as the
45
+ * `requiredSubchannelFlag`, so it is always 0 in the token constant itself.
46
+ */
47
+ static constexpr uint64_t MagicToken{ 0xA5F09CB3D6E1F28C };
48
+ static constexpr uint64_t RequiredSubchannelFlagMask{ 0x1 };
49
+
50
+ public:
51
+ /**
52
+ * If `subchannels` is not empty or `requiredSubchannel` has value, encodes
53
+ * them at the beginning of the given message payload.
54
+ *
55
+ * @returns true if the message was encoded, false otherwise.
56
+ */
57
+ static bool EncodeSubchannels(
58
+ RTC::SCTP::Message& message,
59
+ const std::vector<uint16_t>& subchannels,
60
+ std::optional<uint16_t> requiredSubchannel);
61
+
62
+ /**
63
+ * If the given message payload starts with the Magic Token, extracts the
64
+ * encoded subchannels and (optionally) the required subchannel, fills the
65
+ * given arguments and removes the encoded header from the message payload.
66
+ *
67
+ * @returns true if the message was successfully decoded, false otherwise.
68
+ */
69
+ static bool DecodeSubchannels(
70
+ RTC::SCTP::Message& message,
71
+ std::vector<uint16_t>& subchannels,
72
+ std::optional<uint16_t>& requiredSubchannel);
73
+ };
74
+ } // namespace RTC
75
+
76
+ #endif
@@ -219,6 +219,10 @@ namespace RTC
219
219
  const std::string& dataConsumerId, const std::string& method) const final;
220
220
  virtual void CheckNoSctpDataConsumer(uint16_t streamId, const std::string& method) const final;
221
221
  virtual bool IsConnected() const = 0;
222
+ virtual bool IsPipe() const
223
+ {
224
+ return false;
225
+ }
222
226
  virtual void SendRtpPacket(
223
227
  RTC::Consumer* consumer, RTC::RTP::Packet* packet, const onSendCallback* cb = nullptr) = 0;
224
228
  virtual void HandleRtcpPacket(RTC::RTCP::Packet* packet) final;
@@ -390,11 +394,6 @@ namespace RTC
390
394
  // For SCTP capable transports and for direct transport.
391
395
  size_t maxSendMessageSize{ 0u };
392
396
  size_t maxReceiveMessageSize{ 0u };
393
- // For SCTP capable transports.
394
- size_t sctpSendBufferSize{ 0u };
395
- size_t sctpPerStreamSendQueueLimit{ 0u };
396
- size_t sctpMaxReceiverWindowBufferSize{ 0u };
397
-
398
397
  struct TraceEventTypes traceEventTypes;
399
398
  };
400
399
  } // namespace RTC
@@ -136,6 +136,7 @@ common_sources = [
136
136
  'src/RTC/SimpleProducerStreamManager.cpp',
137
137
  'src/RTC/SimulcastProducerStreamManager.cpp',
138
138
  'src/RTC/SrtpSession.cpp',
139
+ 'src/RTC/SubchannelsCodec.cpp',
139
140
  'src/RTC/SvcProducerStreamManager.cpp',
140
141
  'src/RTC/TcpConnection.cpp',
141
142
  'src/RTC/TcpServer.cpp',
@@ -430,6 +431,7 @@ test_sources = [
430
431
  'test/src/RTC/TestRateCalculator.cpp',
431
432
  'test/src/RTC/TestRtpEncodingParameters.cpp',
432
433
  'test/src/RTC/TestSeqManager.cpp',
434
+ 'test/src/RTC/TestSubchannelsCodec.cpp',
433
435
  'test/src/RTC/TestTransportCongestionControlServer.cpp',
434
436
  'test/src/RTC/TestTransportTuple.cpp',
435
437
  'test/src/RTC/TestTrendCalculator.cpp',
@@ -21,14 +21,15 @@
21
21
  }
22
22
  },
23
23
  "node_modules/brace-expansion": {
24
- "version": "5.0.6",
25
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
26
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
24
+ "version": "5.0.8",
25
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
26
+ "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
27
+ "license": "MIT",
27
28
  "dependencies": {
28
29
  "balanced-match": "^4.0.2"
29
30
  },
30
31
  "engines": {
31
- "node": "18 || 20 || >=22"
32
+ "node": "20 || >=22"
32
33
  }
33
34
  },
34
35
  "node_modules/glob": {
@@ -104,9 +105,9 @@
104
105
  "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="
105
106
  },
106
107
  "brace-expansion": {
107
- "version": "5.0.6",
108
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
109
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
108
+ "version": "5.0.8",
109
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
110
+ "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
110
111
  "requires": {
111
112
  "balanced-match": "^4.0.2"
112
113
  }
@@ -4,6 +4,7 @@
4
4
  #include "RTC/DataConsumer.hpp"
5
5
  #include "Logger.hpp"
6
6
  #include "MediaSoupErrors.hpp"
7
+ #include "RTC/SubchannelsCodec.hpp"
7
8
 
8
9
  namespace RTC
9
10
  {
@@ -15,12 +16,14 @@ namespace RTC
15
16
  const std::string& dataProducerId,
16
17
  RTC::DataConsumer::Listener* listener,
17
18
  const FBS::Transport::ConsumeDataRequest* data,
18
- size_t maxMessageSize)
19
+ size_t maxMessageSize,
20
+ bool pipe)
19
21
  : id(id),
20
22
  dataProducerId(dataProducerId),
21
23
  shared(shared),
22
24
  listener(listener),
23
- maxMessageSize(maxMessageSize)
25
+ maxMessageSize(maxMessageSize),
26
+ pipe(pipe)
24
27
  {
25
28
  MS_TRACE();
26
29
 
@@ -398,24 +401,6 @@ namespace RTC
398
401
  }
399
402
  }
400
403
 
401
- void DataConsumer::TransportConnected()
402
- {
403
- MS_TRACE();
404
-
405
- this->transportConnected = true;
406
-
407
- MS_DEBUG_DEV("Transport connected [dataConsumerId:%s]", this->id.c_str());
408
- }
409
-
410
- void DataConsumer::TransportDisconnected()
411
- {
412
- MS_TRACE();
413
-
414
- this->transportConnected = false;
415
-
416
- MS_DEBUG_DEV("Transport disconnected [dataConsumerId:%s]", this->id.c_str());
417
- }
418
-
419
404
  void DataConsumer::DataProducerPaused()
420
405
  {
421
406
  MS_TRACE();
@@ -450,22 +435,11 @@ namespace RTC
450
435
  this->id, FBS::Notification::Event::DATACONSUMER_DATAPRODUCER_RESUME);
451
436
  }
452
437
 
453
- void DataConsumer::SctpAssociationConnected()
454
- {
455
- MS_TRACE();
456
-
457
- this->sctpAssociationConnected = true;
458
-
459
- MS_DEBUG_DEV("SctpAssociation connected [dataConsumerId:%s]", this->id.c_str());
460
- }
461
-
462
438
  void DataConsumer::SctpAssociationClosed()
463
439
  {
464
440
  MS_TRACE();
465
441
 
466
- this->sctpAssociationConnected = false;
467
-
468
- MS_DEBUG_DEV("SctpAssociation closed [dataConsumerId:%s]", this->id.c_str());
442
+ this->sctpAssociationClosed = true;
469
443
  }
470
444
 
471
445
  void DataConsumer::SctpBufferedAmountLow(uint32_t bufferedAmount) const
@@ -526,48 +500,57 @@ namespace RTC
526
500
  return false;
527
501
  }
528
502
 
529
- // If a required subchannel is given, verify that this data consumer is
530
- // subscribed to it.
531
- if (
532
- requiredSubchannel.has_value() &&
533
- this->subchannels.find(requiredSubchannel.value()) == this->subchannels.end())
503
+ if (!this->pipe)
534
504
  {
535
- if (cb)
505
+ // If a required subchannel is given, verify that this data consumer is
506
+ // subscribed to it.
507
+ if (requiredSubchannel.has_value() && !this->subchannels.contains(requiredSubchannel.value()))
536
508
  {
537
- (*cb)(false, false);
538
- delete cb;
539
- }
540
-
541
- return false;
542
- }
509
+ if (cb)
510
+ {
511
+ (*cb)(false, false);
512
+ delete cb;
513
+ }
543
514
 
544
- // If subchannels are given, verify that this data consumer is subscribed
545
- // to at least one of them.
546
- if (!subchannels.empty())
547
- {
548
- bool subchannelMatched{ false };
515
+ return false;
516
+ }
549
517
 
550
- for (const auto subchannel : subchannels)
518
+ // If subchannels are given, verify that this data consumer is subscribed
519
+ // to at least one of them.
520
+ if (!subchannels.empty())
551
521
  {
552
- if (this->subchannels.find(subchannel) != this->subchannels.end())
522
+ bool subchannelMatched{ false };
523
+
524
+ for (const auto subchannel : subchannels)
553
525
  {
554
- subchannelMatched = true;
526
+ if (this->subchannels.contains(subchannel))
527
+ {
528
+ subchannelMatched = true;
555
529
 
556
- break;
530
+ break;
531
+ }
557
532
  }
558
- }
559
533
 
560
- if (!subchannelMatched)
561
- {
562
- if (cb)
534
+ if (!subchannelMatched)
563
535
  {
564
- (*cb)(false, false);
565
- delete cb;
566
- }
536
+ if (cb)
537
+ {
538
+ (*cb)(false, false);
539
+ delete cb;
540
+ }
567
541
 
568
- return false;
542
+ return false;
543
+ }
569
544
  }
570
545
  }
546
+ // This is a piped DataConsumer, so instead of verifying subchannels locally,
547
+ // encode the subchannels and required subchannel at the beginning of the
548
+ // message payload so the receiving PipeTransport can decode them and apply
549
+ // them to its own DataConsumers.
550
+ else
551
+ {
552
+ RTC::SubchannelsCodec::EncodeSubchannels(message, subchannels, requiredSubchannel);
553
+ }
571
554
 
572
555
  const size_t messageLen = message.GetPayloadLength();
573
556
 
@@ -575,7 +558,7 @@ namespace RTC
575
558
  {
576
559
  MS_WARN_TAG(
577
560
  message,
578
- "given message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]",
561
+ "message exceeds maxMessageSize value [maxMessageSize:%zu, len:%zu]",
579
562
  messageLen,
580
563
  this->maxMessageSize);
581
564
 
@@ -4,8 +4,9 @@
4
4
  #include "RTC/ICE/StunPacket.hpp"
5
5
  #include "Logger.hpp"
6
6
  #include "MediaSoupErrors.hpp"
7
+ #include <openssl/crypto.h>
7
8
  #include <cstdio> // std::snprintf()
8
- #include <cstring> // std::memcmp(), std::memcpy(), std::memset()
9
+ #include <cstring> // std::memcpy(), std::memset()
9
10
  #include <string>
10
11
 
11
12
  namespace RTC
@@ -744,7 +745,10 @@ namespace RTC
744
745
 
745
746
  // Compare the computed HMAC-SHA1 with the MESSAGE-INTEGRITY in the STUN
746
747
  // packet.
747
- if (std::memcmp(messageIntegrity, computedMessageIntegrity, StunPacket::FixedHeaderLength) == 0)
748
+ //
749
+ // NOTE: Use `CRYPTO_memcmp()` to have constant time memory comparison.
750
+ // See https://github.com/versatica/mediasoup/security/advisories/GHSA-xvjj-6cm4-ppgq
751
+ if (CRYPTO_memcmp(messageIntegrity, computedMessageIntegrity, StunPacket::FixedHeaderLength) == 0)
748
752
  {
749
753
  result = StunPacket::AuthenticationResult::OK;
750
754
  }
@@ -1083,6 +1083,17 @@ namespace RTC
1083
1083
  return false;
1084
1084
  }
1085
1085
 
1086
+ if (len > extenLen)
1087
+ {
1088
+ MS_WARN_TAG(
1089
+ rtp,
1090
+ "no enough space for updated dependency descriptor [needed:%zu, available:%" PRIu8 "]",
1091
+ len,
1092
+ extenLen);
1093
+
1094
+ return false;
1095
+ }
1096
+
1086
1097
  std::memcpy(extenValue, data, len);
1087
1098
 
1088
1099
  SetExtensionLength(this->headerExtensionIds.dependencyDescriptor, len);
@@ -54,6 +54,7 @@ namespace RTC
54
54
  this->associationListenerDeferrer,
55
55
  sctpOptions.mtu,
56
56
  sctpOptions.defaultStreamPriority,
57
+ sctpOptions.defaultStreamBufferedAmountLowThreshold,
57
58
  sctpOptions.totalBufferedAmountLowThreshold),
58
59
  t1InitTimer(this->shared->CreateBackoffTimer(
59
60
  BackoffTimerHandleInterface::BackoffTimerHandleOptions{
@@ -4,7 +4,8 @@
4
4
  #include "RTC/SCTP/association/StateCookie.hpp"
5
5
  #include "Logger.hpp"
6
6
  #include "MediaSoupErrors.hpp"
7
- #include <cstring> // std::memcpy(), std::memcmp()
7
+ #include <openssl/crypto.h>
8
+ #include <cstring> // std::memcpy()
8
9
  #include <string_view>
9
10
 
10
11
  namespace RTC
@@ -179,7 +180,9 @@ namespace RTC
179
180
  const uint8_t* expectedMac = Utils::Crypto::GetHmacSha1(
180
181
  reinterpret_cast<const char*>(macKey), macKeyLength, buffer, StateCookie::MacOffset);
181
182
 
182
- return std::memcmp(buffer + StateCookie::MacOffset, expectedMac, StateCookie::MacLength) == 0;
183
+ // NOTE: Use `CRYPTO_memcmp()` to have constant time memory comparison.
184
+ // See https://github.com/versatica/mediasoup/security/advisories/GHSA-xvjj-6cm4-ppgq
185
+ return CRYPTO_memcmp(buffer + StateCookie::MacOffset, expectedMac, StateCookie::MacLength) == 0;
183
186
  }
184
187
 
185
188
  Types::SctpImplementation StateCookie::DetermineSctpImplementation(
@@ -81,8 +81,11 @@ namespace RTC
81
81
  new MissingMandatoryParameterErrorCause(const_cast<uint8_t*>(buffer), bufferLength);
82
82
 
83
83
  // In this chunk we must validate that some fields have correct values.
84
+ //
85
+ // NOTE: Must cast result to uint64_t to avoid integer overflow.
86
+ // See https://github.com/versatica/mediasoup/security/advisories/GHSA-p9cq-fqxc-987w
84
87
  if (
85
- (errorCause->GetNumberOfMissingParameters() * 2) !=
88
+ (static_cast<uint64_t>(errorCause->GetNumberOfMissingParameters()) * 2) !=
86
89
  causeLength -
87
90
  MissingMandatoryParameterErrorCause::MissingMandatoryParameterErrorCauseHeaderLength)
88
91
  {
@@ -20,9 +20,11 @@ namespace RTC
20
20
  AssociationListenerInterface& associationListener,
21
21
  size_t mtu,
22
22
  uint16_t defaultPriority,
23
+ size_t defaultStreamBufferedAmountLowThreshold,
23
24
  size_t totalBufferedAmountLowThreshold)
24
25
  : associationListener(associationListener),
25
26
  defaultPriority(defaultPriority),
27
+ defaultStreamBufferedAmountLowThreshold(defaultStreamBufferedAmountLowThreshold),
26
28
  scheduler(mtu),
27
29
  totalBufferedAmountThresholdWatcher(
28
30
  [this]()
@@ -256,7 +258,9 @@ namespace RTC
256
258
 
257
259
  if (it == this->streams.end())
258
260
  {
259
- return 0;
261
+ // The stream is created lazily (on first send or when its threshold is
262
+ // explicitly set), so report the default that it will be created with.
263
+ return this->defaultStreamBufferedAmountLowThreshold;
260
264
  }
261
265
 
262
266
  const auto& stream = it->second;
@@ -297,7 +301,11 @@ namespace RTC
297
301
  this->associationListener.OnAssociationStreamBufferedAmountLow(streamId);
298
302
  }));
299
303
 
300
- return it2->second;
304
+ auto& stream = it2->second;
305
+
306
+ stream.GetBufferedAmount().SetLowThreshold(this->defaultStreamBufferedAmountLowThreshold);
307
+
308
+ return stream;
301
309
  }
302
310
 
303
311
  void RoundRobinSendQueue::AssertIsConsistent() const