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.
- package/CHANGELOG.md +13 -0
- package/node/lib/PipeTransportTypes.d.ts +8 -0
- package/node/lib/PipeTransportTypes.d.ts.map +1 -1
- package/node/lib/PlainTransportTypes.d.ts +8 -0
- package/node/lib/PlainTransportTypes.d.ts.map +1 -1
- package/node/lib/Router.d.ts +6 -6
- package/node/lib/Router.d.ts.map +1 -1
- package/node/lib/Router.js +28 -25
- package/node/lib/RouterTypes.d.ts +8 -4
- package/node/lib/RouterTypes.d.ts.map +1 -1
- package/node/lib/WebRtcTransportTypes.d.ts +8 -0
- package/node/lib/WebRtcTransportTypes.d.ts.map +1 -1
- package/node/lib/fbs/transport/options.d.ts +5 -2
- package/node/lib/fbs/transport/options.d.ts.map +1 -1
- package/node/lib/fbs/transport/options.js +18 -7
- package/node/lib/test/test-DataConsumer.js +3 -0
- package/node/lib/test/test-PipeTransport.js +33 -1
- package/package.json +11 -11
- package/worker/fbs/transport.fbs +1 -0
- package/worker/fuzzer/src/RTC/RTP/FuzzerPacket.cpp +44 -0
- package/worker/include/RTC/DataConsumer.hpp +7 -10
- package/worker/include/RTC/PipeTransport.hpp +4 -0
- package/worker/include/RTC/SCTP/public/Message.hpp +16 -0
- package/worker/include/RTC/SCTP/public/SctpOptions.hpp +7 -0
- package/worker/include/RTC/SCTP/tx/RoundRobinSendQueue.hpp +2 -0
- package/worker/include/RTC/SubchannelsCodec.hpp +76 -0
- package/worker/include/RTC/Transport.hpp +4 -5
- package/worker/meson.build +2 -0
- package/worker/scripts/package-lock.json +8 -7
- package/worker/src/RTC/DataConsumer.cpp +45 -62
- package/worker/src/RTC/ICE/StunPacket.cpp +6 -2
- package/worker/src/RTC/RTP/Packet.cpp +11 -0
- package/worker/src/RTC/SCTP/association/Association.cpp +1 -0
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +5 -2
- package/worker/src/RTC/SCTP/packet/errorCauses/MissingMandatoryParameterErrorCause.cpp +4 -1
- package/worker/src/RTC/SCTP/tx/RoundRobinSendQueue.cpp +10 -2
- package/worker/src/RTC/SrtpSession.cpp +82 -25
- package/worker/src/RTC/SubchannelsCodec.cpp +153 -0
- package/worker/src/RTC/Transport.cpp +26 -58
- package/worker/subprojects/libsrtp3.wrap +4 -4
- package/worker/tasks.py +1 -1
- package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +34 -0
- package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +1 -0
- package/worker/test/src/RTC/SCTP/packet/errorCauses/TestMissingMandatoryParameterErrorCause.cpp +24 -0
- package/worker/test/src/RTC/SCTP/tx/TestRoundRobinSendQueue.cpp +180 -39
- package/worker/test/src/RTC/TestSubchannelsCodec.cpp +224 -0
package/worker/fbs/transport.fbs
CHANGED
|
@@ -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
|
|
71
|
-
// is
|
|
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->
|
|
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
|
|
126
|
-
bool sctpAssociationConnected{ false };
|
|
123
|
+
bool sctpAssociationClosed{ false };
|
|
127
124
|
bool paused{ false };
|
|
128
125
|
bool dataProducerPaused{ false };
|
|
129
126
|
bool dataProducerClosed{ false };
|
|
@@ -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
|
package/worker/meson.build
CHANGED
|
@@ -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.
|
|
25
|
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.
|
|
26
|
-
"integrity": "sha512-
|
|
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": "
|
|
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.
|
|
108
|
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.
|
|
109
|
-
"integrity": "sha512-
|
|
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->
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
509
|
+
if (cb)
|
|
510
|
+
{
|
|
511
|
+
(*cb)(false, false);
|
|
512
|
+
delete cb;
|
|
513
|
+
}
|
|
543
514
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
if (!subchannels.empty())
|
|
547
|
-
{
|
|
548
|
-
bool subchannelMatched{ false };
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
549
517
|
|
|
550
|
-
|
|
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
|
-
|
|
522
|
+
bool subchannelMatched{ false };
|
|
523
|
+
|
|
524
|
+
for (const auto subchannel : subchannels)
|
|
553
525
|
{
|
|
554
|
-
|
|
526
|
+
if (this->subchannels.contains(subchannel))
|
|
527
|
+
{
|
|
528
|
+
subchannelMatched = true;
|
|
555
529
|
|
|
556
|
-
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
557
532
|
}
|
|
558
|
-
}
|
|
559
533
|
|
|
560
|
-
|
|
561
|
-
{
|
|
562
|
-
if (cb)
|
|
534
|
+
if (!subchannelMatched)
|
|
563
535
|
{
|
|
564
|
-
(
|
|
565
|
-
|
|
566
|
-
|
|
536
|
+
if (cb)
|
|
537
|
+
{
|
|
538
|
+
(*cb)(false, false);
|
|
539
|
+
delete cb;
|
|
540
|
+
}
|
|
567
541
|
|
|
568
|
-
|
|
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
|
-
"
|
|
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::
|
|
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
|
-
|
|
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 <
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|