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.
- package/CHANGELOG.md +1882 -0
- package/node/lib/test/test-Consumer.js +111 -0
- package/node/lib/test/test-Producer.js +54 -0
- package/npm-scripts.mjs +0 -5
- package/package.json +9 -8
- package/worker/fuzzer/src/RTC/SCTP/association/FuzzerStateCookie.cpp +4 -6
- package/worker/include/RTC/NEW_RTCP/packet/ByePacket.hpp +165 -0
- package/worker/include/RTC/NEW_RTCP/packet/CompoundPacket.hpp +183 -0
- package/worker/include/RTC/NEW_RTCP/packet/Packet.hpp +354 -0
- package/worker/include/RTC/NEW_RTCP/packet/TODO_NEW_RTCP.md +17 -0
- package/worker/include/RTC/RTP/Codecs/Tools.hpp +2 -0
- package/worker/include/RTC/Router.hpp +4 -4
- package/worker/include/RTC/SCTP/association/Capabilities.hpp +73 -0
- package/worker/include/RTC/SCTP/association/NegotiatedCapabilities.hpp +7 -9
- package/worker/include/RTC/SCTP/association/StateCookie.hpp +38 -28
- package/worker/include/RTC/SCTP/packet/Chunk.hpp +11 -7
- package/worker/include/RTC/SCTP/packet/ErrorCause.hpp +11 -4
- package/worker/include/RTC/SCTP/packet/Packet.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/Parameter.hpp +11 -4
- package/worker/include/RTC/SCTP/packet/TLV.hpp +2 -2
- package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +2 -2
- package/worker/include/RTC/Transport.hpp +10 -10
- package/worker/include/Worker.hpp +4 -4
- package/worker/meson.build +7 -0
- package/worker/scripts/clang-scripts.mjs +54 -0
- package/worker/src/RTC/Consumer.cpp +22 -4
- package/worker/src/RTC/NEW_RTCP/packet/ByePacket.cpp +266 -0
- package/worker/src/RTC/NEW_RTCP/packet/CompoundPacket.cpp +219 -0
- package/worker/src/RTC/NEW_RTCP/packet/Packet.cpp +222 -0
- package/worker/src/RTC/RTP/Codecs/H264.cpp +3 -0
- package/worker/src/RTC/RTP/Codecs/VP8.cpp +3 -0
- package/worker/src/RTC/Router.cpp +14 -14
- package/worker/src/RTC/SCTP/association/Association.cpp +23 -11
- package/worker/src/RTC/SCTP/association/Capabilities.cpp +87 -0
- package/worker/src/RTC/SCTP/association/NegotiatedCapabilities.cpp +20 -40
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +54 -32
- package/worker/src/RTC/SCTP/packet/Chunk.cpp +18 -18
- package/worker/src/RTC/SCTP/packet/ErrorCause.cpp +18 -18
- package/worker/src/RTC/SCTP/packet/Packet.cpp +2 -0
- package/worker/src/RTC/SCTP/packet/Parameter.cpp +18 -18
- package/worker/src/RTC/SCTP/packet/TLV.cpp +27 -25
- package/worker/src/RTC/SCTP/packet/parameters/StateCookieParameter.cpp +2 -2
- package/worker/src/RTC/SvcProducerStreamManager.cpp +4 -1
- package/worker/src/RTC/Transport.cpp +42 -30
- package/worker/src/Worker.cpp +10 -10
- package/worker/test/include/RTC/ICE/iceCommon.hpp +1 -1
- package/worker/test/include/RTC/RTCP/rtcpCommon.hpp +58 -0
- package/worker/test/include/RTC/RTP/rtpCommon.hpp +1 -1
- package/worker/test/src/RTC/NEW_RTCP/packet/TestByePacket.cpp +302 -0
- package/worker/test/src/RTC/NEW_RTCP/rtcpCommon.cpp +29 -0
- package/worker/test/src/RTC/RTP/TestPacket.cpp +17 -15
- package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +3 -3
- package/worker/test/src/RTC/SCTP/association/TestCapabilities.cpp +99 -0
- package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +14 -16
- package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +198 -102
- package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +11 -10
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#define MS_CLASS "RTC::RTCP::CompoundPacket"
|
|
2
|
+
// #define MS_LOG_DEV_LEVEL 3
|
|
3
|
+
|
|
4
|
+
#include "RTC/NEW_RTCP/packet/CompoundPacket.hpp"
|
|
5
|
+
#include "Logger.hpp"
|
|
6
|
+
#include "MediaSoupErrors.hpp"
|
|
7
|
+
#include "Utils.hpp"
|
|
8
|
+
#include <cstring> // std::memmove()
|
|
9
|
+
|
|
10
|
+
namespace RTC
|
|
11
|
+
{
|
|
12
|
+
namespace NEW_RTCP
|
|
13
|
+
{
|
|
14
|
+
/* Class methods. */
|
|
15
|
+
|
|
16
|
+
CompoundPacket* CompoundPacket::Parse(const uint8_t* buffer, size_t bufferLength)
|
|
17
|
+
{
|
|
18
|
+
MS_TRACE();
|
|
19
|
+
|
|
20
|
+
if (!Packet::IsRtcp(buffer, bufferLength))
|
|
21
|
+
{
|
|
22
|
+
MS_WARN_TAG(rtcp, "not an RTCP compound packet");
|
|
23
|
+
|
|
24
|
+
return nullptr;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
auto* compoundPacket = new CompoundPacket(const_cast<uint8_t*>(buffer), bufferLength);
|
|
28
|
+
|
|
29
|
+
// Pointer that initially points to the given data buffer and is later
|
|
30
|
+
// incremented to point to each packet within the compound packet.
|
|
31
|
+
const auto* ptr = buffer;
|
|
32
|
+
|
|
33
|
+
while (ptr < buffer + bufferLength)
|
|
34
|
+
{
|
|
35
|
+
// The remaining length in the buffer is the potential buffer length
|
|
36
|
+
// of the current packet.
|
|
37
|
+
const size_t packetMaxBufferLength = bufferLength - (ptr - buffer);
|
|
38
|
+
|
|
39
|
+
// Here we must anticipate the type of each packet to use its appropriate
|
|
40
|
+
// parser.
|
|
41
|
+
Packet::PacketType packetType;
|
|
42
|
+
size_t packetLength;
|
|
43
|
+
|
|
44
|
+
if (!Packet::IsPacket(ptr, packetMaxBufferLength, packetType, packetLength))
|
|
45
|
+
{
|
|
46
|
+
MS_WARN_TAG(rtcp, "not an RTCP packet");
|
|
47
|
+
|
|
48
|
+
delete compoundPacket;
|
|
49
|
+
return nullptr;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Packet* packet{ nullptr }; // NOLINT(misc-const-correctness)
|
|
53
|
+
|
|
54
|
+
MS_DEBUG_DEV("parsing RTCP packet [ptr:%zu, type:%" PRIu8 "]", ptr - buffer, packetType);
|
|
55
|
+
|
|
56
|
+
switch (packetType)
|
|
57
|
+
{
|
|
58
|
+
case Packet::PacketType::IJ:
|
|
59
|
+
{
|
|
60
|
+
// TODO
|
|
61
|
+
// packet = ExtendedJitterReportPacket::ParseStrict(ptr, packetLength);
|
|
62
|
+
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
default:
|
|
67
|
+
{
|
|
68
|
+
// TODO
|
|
69
|
+
// packet = UnknownPacket::ParseStrict(ptr, packetLength);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!packet)
|
|
74
|
+
{
|
|
75
|
+
delete compoundPacket;
|
|
76
|
+
return nullptr;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
compoundPacket->packets.push_back(packet);
|
|
80
|
+
|
|
81
|
+
ptr += packet->GetLength();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const size_t computedLength = ptr - buffer;
|
|
85
|
+
|
|
86
|
+
// Ensure computed length matches the total given buffer length.
|
|
87
|
+
if (computedLength != bufferLength)
|
|
88
|
+
{
|
|
89
|
+
MS_WARN_TAG(
|
|
90
|
+
rtcp,
|
|
91
|
+
"computed length (%zu bytes) != buffer length (%zu bytes)",
|
|
92
|
+
computedLength,
|
|
93
|
+
bufferLength);
|
|
94
|
+
|
|
95
|
+
delete compoundPacket;
|
|
96
|
+
return nullptr;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// It's mandatory to call SetLength() once we are done and we know the
|
|
100
|
+
// exact length of the packet.
|
|
101
|
+
compoundPacket->SetLength(computedLength);
|
|
102
|
+
|
|
103
|
+
return compoundPacket;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Instance methods. */
|
|
107
|
+
|
|
108
|
+
CompoundPacket::CompoundPacket(uint8_t* buffer, size_t bufferLength)
|
|
109
|
+
: Serializable(buffer, bufferLength)
|
|
110
|
+
{
|
|
111
|
+
MS_TRACE();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
CompoundPacket::~CompoundPacket()
|
|
115
|
+
{
|
|
116
|
+
MS_TRACE();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void CompoundPacket::Dump(int indentation) const
|
|
120
|
+
{
|
|
121
|
+
MS_TRACE();
|
|
122
|
+
|
|
123
|
+
MS_DUMP_CLEAN(indentation, "<RTCP::CompoundPacket>");
|
|
124
|
+
MS_DUMP_CLEAN(indentation, " length: %zu (buffer length: %zu)", GetLength(), GetBufferLength());
|
|
125
|
+
MS_DUMP_CLEAN(indentation, " packets count: %zu", GetPacketsCount());
|
|
126
|
+
MS_DUMP_CLEAN(
|
|
127
|
+
indentation, " needs consolidation of packets: %s", NeedsConsolidation() ? "yes" : "no");
|
|
128
|
+
for (const auto* packet : this->packets)
|
|
129
|
+
{
|
|
130
|
+
packet->Dump(indentation + 1);
|
|
131
|
+
}
|
|
132
|
+
MS_DUMP_CLEAN(indentation, "</RTCP::CompoundPacket>");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
void CompoundPacket::Serialize(uint8_t* buffer, size_t bufferLength)
|
|
136
|
+
{
|
|
137
|
+
MS_TRACE();
|
|
138
|
+
|
|
139
|
+
const auto* previousBuffer = GetBuffer();
|
|
140
|
+
|
|
141
|
+
// Invoke the parent method to copy the whole buffer.
|
|
142
|
+
Serializable::Serialize(buffer, bufferLength);
|
|
143
|
+
|
|
144
|
+
for (auto* packet : this->packets)
|
|
145
|
+
{
|
|
146
|
+
const size_t offset = packet->GetBuffer() - previousBuffer;
|
|
147
|
+
|
|
148
|
+
packet->SoftSerialize(buffer + offset);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
CompoundPacket* CompoundPacket::Clone(uint8_t* buffer, size_t bufferLength) const
|
|
153
|
+
{
|
|
154
|
+
MS_TRACE();
|
|
155
|
+
|
|
156
|
+
auto* clonedCompoundPacket = new CompoundPacket(buffer, bufferLength);
|
|
157
|
+
|
|
158
|
+
Serializable::CloneInto(clonedCompoundPacket);
|
|
159
|
+
|
|
160
|
+
// Soft clone packets into the given cloned compound packet.
|
|
161
|
+
for (auto* packet : this->packets)
|
|
162
|
+
{
|
|
163
|
+
const size_t offset = packet->GetBuffer() - GetBuffer();
|
|
164
|
+
|
|
165
|
+
auto* softClonedPacket = packet->SoftClone(buffer + offset);
|
|
166
|
+
|
|
167
|
+
clonedCompoundPacket->packets.push_back(softClonedPacket);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return clonedCompoundPacket;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void CompoundPacket::HandleInPlacePacket(Packet* packet)
|
|
174
|
+
{
|
|
175
|
+
MS_TRACE();
|
|
176
|
+
|
|
177
|
+
this->needsConsolidation = true;
|
|
178
|
+
|
|
179
|
+
// When the application completes the packet it must call
|
|
180
|
+
// `packet->Consolidate()` and that will trigger this event.
|
|
181
|
+
packet->SetConsolidatedListener(
|
|
182
|
+
[this, packet]()
|
|
183
|
+
{
|
|
184
|
+
try
|
|
185
|
+
{
|
|
186
|
+
// NOTE: Packet class doesn't have `NeedsConsolidation()` method.
|
|
187
|
+
|
|
188
|
+
// Fix buffer length assigned to the packet.
|
|
189
|
+
packet->SetBufferLength(packet->GetLength());
|
|
190
|
+
|
|
191
|
+
// Update compound packet length.
|
|
192
|
+
// NOTE: This will throw if there is no enough space in the compound
|
|
193
|
+
// packet buffer.
|
|
194
|
+
SetLength(GetLength() + packet->GetLength());
|
|
195
|
+
|
|
196
|
+
// Add the packet to the list.
|
|
197
|
+
this->packets.push_back(packet);
|
|
198
|
+
this->needsConsolidation = false;
|
|
199
|
+
}
|
|
200
|
+
catch (const MediaSoupError& error)
|
|
201
|
+
{
|
|
202
|
+
this->needsConsolidation = false;
|
|
203
|
+
|
|
204
|
+
throw;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
void CompoundPacket::AssertDoesNotNeedConsolidation() const
|
|
210
|
+
{
|
|
211
|
+
MS_TRACE();
|
|
212
|
+
|
|
213
|
+
if (this->needsConsolidation)
|
|
214
|
+
{
|
|
215
|
+
MS_THROW_ERROR("compound packet needs consolidation of some ongoing packet");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} // namespace NEW_RTCP
|
|
219
|
+
} // namespace RTC
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#define MS_CLASS "RTC::RTCP::Packet"
|
|
2
|
+
// #define MS_LOG_DEV_LEVEL 3
|
|
3
|
+
|
|
4
|
+
#include "RTC/NEW_RTCP/packet/Packet.hpp"
|
|
5
|
+
#include "Logger.hpp"
|
|
6
|
+
#include "MediaSoupErrors.hpp"
|
|
7
|
+
#include <cstring> // std::memmove()
|
|
8
|
+
#include <limits> // std::numeric_limits
|
|
9
|
+
|
|
10
|
+
namespace RTC
|
|
11
|
+
{
|
|
12
|
+
namespace NEW_RTCP
|
|
13
|
+
{
|
|
14
|
+
/* Class variables. */
|
|
15
|
+
|
|
16
|
+
// clang-format off
|
|
17
|
+
const ankerl::unordered_dense::map<Packet::PacketType, std::string> Packet::PacketType2String =
|
|
18
|
+
{
|
|
19
|
+
{ Packet::PacketType::IJ, "IF" },
|
|
20
|
+
{ Packet::PacketType::SR, "SR" },
|
|
21
|
+
{ Packet::PacketType::RR, "RR" },
|
|
22
|
+
{ Packet::PacketType::SDES, "SDES" },
|
|
23
|
+
{ Packet::PacketType::BYE, "BYE" },
|
|
24
|
+
{ Packet::PacketType::APP, "APP" },
|
|
25
|
+
{ Packet::PacketType::RTPFB, "RTPFB" },
|
|
26
|
+
{ Packet::PacketType::PSFB, "PSFB" },
|
|
27
|
+
{ Packet::PacketType::XR, "XR" },
|
|
28
|
+
};
|
|
29
|
+
// clang-format on
|
|
30
|
+
|
|
31
|
+
/* Class methods. */
|
|
32
|
+
|
|
33
|
+
bool Packet::IsRtcp(const uint8_t* buffer, size_t bufferLength)
|
|
34
|
+
{
|
|
35
|
+
MS_TRACE();
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
bufferLength >= Packet::CommonHeaderLength &&
|
|
39
|
+
// @see RFC 7983.
|
|
40
|
+
(buffer[0] > 127 && buffer[0] < 192) &&
|
|
41
|
+
// RTP Version must be 2.
|
|
42
|
+
(buffer[0] >> 6) == 2 &&
|
|
43
|
+
// RTCP packet types defined by IANA:
|
|
44
|
+
// http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4
|
|
45
|
+
// RFC 5761 (RTCP-mux) states this range for secure RTCP/RTP detection.
|
|
46
|
+
(buffer[1] >= 192 && buffer[1] <= 223) &&
|
|
47
|
+
// RTCP packets must have a length that is a multiple of 4 bytes.
|
|
48
|
+
Utils::Byte::IsPaddedTo4Bytes(bufferLength));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const std::string& Packet::PacketTypeToString(PacketType packetType)
|
|
52
|
+
{
|
|
53
|
+
MS_TRACE();
|
|
54
|
+
|
|
55
|
+
static const std::string Unknown("UNKNOWN");
|
|
56
|
+
|
|
57
|
+
auto it = Packet::PacketType2String.find(packetType);
|
|
58
|
+
|
|
59
|
+
if (it == Packet::PacketType2String.end())
|
|
60
|
+
{
|
|
61
|
+
return Unknown;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return it->second;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
bool Packet::IsPacket(
|
|
68
|
+
const uint8_t* buffer, size_t bufferLength, PacketType& packetType, size_t& packetLength)
|
|
69
|
+
{
|
|
70
|
+
MS_TRACE();
|
|
71
|
+
|
|
72
|
+
if (!Packet::IsRtcp(buffer, bufferLength))
|
|
73
|
+
{
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// The padding mechanism is not implemented since it's only used when
|
|
78
|
+
// encrypting the compound packet by following the section 9.1 of RFC
|
|
79
|
+
// 3550 which absolutely nobody does (SRTCP is used instead). So packets
|
|
80
|
+
// with Padding bit set to 1 are considered invalid and rejected.
|
|
81
|
+
if ((buffer[0] >> 5) & 0x01)
|
|
82
|
+
{
|
|
83
|
+
MS_WARN_TAG(rtcp, "RTCP packet with Padding bit set to 1 not supported");
|
|
84
|
+
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
packetType = static_cast<Packet::PacketType>(buffer[1]);
|
|
89
|
+
packetLength = (static_cast<size_t>(Utils::Byte::Get2Bytes(buffer, 2)) + 1) * 4;
|
|
90
|
+
|
|
91
|
+
if (bufferLength < packetLength)
|
|
92
|
+
{
|
|
93
|
+
MS_WARN_TAG(
|
|
94
|
+
rtcp,
|
|
95
|
+
"no space for announced packet length [packetType:%s, packetLength:%zu, bufferLength:%zu]",
|
|
96
|
+
Packet::PacketTypeToString(packetType).c_str(),
|
|
97
|
+
packetLength,
|
|
98
|
+
bufferLength);
|
|
99
|
+
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Instance methods. */
|
|
107
|
+
|
|
108
|
+
Packet::Packet(uint8_t* buffer, size_t bufferLength) : Serializable(buffer, bufferLength)
|
|
109
|
+
{
|
|
110
|
+
MS_TRACE();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Packet::~Packet()
|
|
114
|
+
{
|
|
115
|
+
MS_TRACE();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void Packet::DumpCommon(int indentation) const
|
|
119
|
+
{
|
|
120
|
+
MS_TRACE();
|
|
121
|
+
|
|
122
|
+
MS_DUMP_CLEAN(
|
|
123
|
+
indentation,
|
|
124
|
+
" type: %" PRIu8 " (%s) (unknown: %s)",
|
|
125
|
+
static_cast<uint8_t>(GetType()),
|
|
126
|
+
Packet::PacketTypeToString(GetType()).c_str(),
|
|
127
|
+
HasUnknownType() ? "yes" : "no");
|
|
128
|
+
MS_DUMP_CLEAN(indentation, " length: %zu (buffer length: %zu)", GetLength(), GetBufferLength());
|
|
129
|
+
MS_DUMP_CLEAN(indentation, " count field: %" PRIu8, GetCount());
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
void Packet::SoftSerialize(const uint8_t* buffer)
|
|
133
|
+
{
|
|
134
|
+
MS_TRACE();
|
|
135
|
+
|
|
136
|
+
SetBuffer(const_cast<uint8_t*>(buffer));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
void Packet::SoftCloneInto(Packet* packet) const
|
|
140
|
+
{
|
|
141
|
+
MS_TRACE();
|
|
142
|
+
|
|
143
|
+
// Need to manually set Serializable length.
|
|
144
|
+
packet->SetLength(GetLength());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
void Packet::InitializeHeader(PacketType packetType, uint16_t length)
|
|
148
|
+
{
|
|
149
|
+
MS_TRACE();
|
|
150
|
+
|
|
151
|
+
auto* commonHeader = GetCommonHeaderPointer();
|
|
152
|
+
|
|
153
|
+
commonHeader->version = 2;
|
|
154
|
+
commonHeader->padding = 0;
|
|
155
|
+
commonHeader->count = 0;
|
|
156
|
+
commonHeader->packetType = packetType;
|
|
157
|
+
|
|
158
|
+
SetLengthField(length);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
void Packet::SetLengthField(size_t length)
|
|
162
|
+
{
|
|
163
|
+
MS_TRACE();
|
|
164
|
+
|
|
165
|
+
// The Length field is the length of the RTCP packet in 32-bit words minus
|
|
166
|
+
// one, so the maximum representable packet length is (65535 + 1) * 4 bytes.
|
|
167
|
+
if (length > (std::numeric_limits<uint16_t>::max() + 1) * 4)
|
|
168
|
+
{
|
|
169
|
+
MS_THROW_TYPE_ERROR("length (%zu bytes) cannot be greater than 262144", length);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
Utils::Byte::Set2Bytes(const_cast<uint8_t*>(GetBuffer()), 2, (length / 4) - 1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
void Packet::SetVariableLengthValue(const uint8_t* value, size_t valueLength)
|
|
176
|
+
{
|
|
177
|
+
MS_TRACE();
|
|
178
|
+
|
|
179
|
+
if (value == nullptr && valueLength > 0)
|
|
180
|
+
{
|
|
181
|
+
MS_THROW_TYPE_ERROR("value cannot be nullptr if valueLength is > 0");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// NOTE: This can throw.
|
|
185
|
+
SetVariableLengthValueLength(valueLength);
|
|
186
|
+
|
|
187
|
+
if (value)
|
|
188
|
+
{
|
|
189
|
+
std::memmove(GetVariableLengthValuePointer(), value, valueLength);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
void Packet::SetVariableLengthValueLength(size_t valueLength)
|
|
194
|
+
{
|
|
195
|
+
MS_TRACE();
|
|
196
|
+
|
|
197
|
+
const size_t previousLength = GetLength();
|
|
198
|
+
const size_t previousLengthField = GetLengthFieldComputed();
|
|
199
|
+
const size_t previousValueLength = GetVariableLengthValueLength();
|
|
200
|
+
const size_t newLength = previousLengthField - previousValueLength + valueLength;
|
|
201
|
+
|
|
202
|
+
try
|
|
203
|
+
{
|
|
204
|
+
// Let's call SetLength() on parent with the new computed length.
|
|
205
|
+
// NOTE: If there is no space in the buffer for it, it will throw.
|
|
206
|
+
SetLength(newLength);
|
|
207
|
+
|
|
208
|
+
// Update length field.
|
|
209
|
+
// NOTE: This will throw if computed value is too big.
|
|
210
|
+
SetLengthField(newLength);
|
|
211
|
+
}
|
|
212
|
+
catch (const MediaSoupError& error)
|
|
213
|
+
{
|
|
214
|
+
// Rollback.
|
|
215
|
+
SetLength(previousLength);
|
|
216
|
+
SetLengthField(previousLengthField);
|
|
217
|
+
|
|
218
|
+
throw;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} // namespace NEW_RTCP
|
|
222
|
+
} // namespace RTC
|
|
@@ -178,6 +178,9 @@ namespace RTC
|
|
|
178
178
|
return false;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
// H264 always has a single spatial layer (0).
|
|
182
|
+
context->SetCurrentSpatialLayer(0);
|
|
183
|
+
|
|
181
184
|
// Update/fix current temporal layer.
|
|
182
185
|
if (this->payloadDescriptor->temporalLayer > context->GetCurrentTemporalLayer())
|
|
183
186
|
{
|
|
@@ -348,6 +348,9 @@ namespace RTC
|
|
|
348
348
|
return false;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
// VP8 always has a single spatial layer (0).
|
|
352
|
+
context->SetCurrentSpatialLayer(0);
|
|
353
|
+
|
|
351
354
|
// Update/fix current temporal layer.
|
|
352
355
|
if (this->payloadDescriptor->hasTlIndex && this->payloadDescriptor->tlIndex == context->GetTargetTemporalLayer())
|
|
353
356
|
{
|
|
@@ -442,52 +442,52 @@ namespace RTC
|
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
RTC::Transport* Router::AssertAndGetTransportById(
|
|
445
|
-
const std::string& transportId, const std::string&
|
|
445
|
+
const std::string& transportId, const std::string& method) const
|
|
446
446
|
{
|
|
447
447
|
MS_TRACE();
|
|
448
448
|
|
|
449
|
-
auto it = this->mapTransports.find(transportId);
|
|
449
|
+
const auto it = this->mapTransports.find(transportId);
|
|
450
450
|
|
|
451
451
|
if (this->mapTransports.find(transportId) == this->mapTransports.end())
|
|
452
452
|
{
|
|
453
|
-
MS_THROW_NOT_FOUND_ERROR("Transport not found [method:%s]",
|
|
453
|
+
MS_THROW_NOT_FOUND_ERROR("Transport not found [method:%s]", method.c_str());
|
|
454
454
|
}
|
|
455
455
|
|
|
456
456
|
return it->second;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
459
|
RTC::RtpObserver* Router::AssertAndGetRtpObserverById(
|
|
460
|
-
const std::string& rtpObserverId, const std::string&
|
|
460
|
+
const std::string& rtpObserverId, const std::string& method) const
|
|
461
461
|
{
|
|
462
462
|
MS_TRACE();
|
|
463
463
|
|
|
464
|
-
auto it = this->mapRtpObservers.find(rtpObserverId);
|
|
464
|
+
const auto it = this->mapRtpObservers.find(rtpObserverId);
|
|
465
465
|
|
|
466
466
|
if (this->mapRtpObservers.find(rtpObserverId) == this->mapRtpObservers.end())
|
|
467
467
|
{
|
|
468
|
-
MS_THROW_NOT_FOUND_ERROR("RtpObserver not found [method:%s]",
|
|
468
|
+
MS_THROW_NOT_FOUND_ERROR("RtpObserver not found [method:%s]", method.c_str());
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
return it->second;
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
-
void Router::CheckNoTransport(const std::string& transportId, const std::string&
|
|
474
|
+
void Router::CheckNoTransport(const std::string& transportId, const std::string& method) const
|
|
475
475
|
{
|
|
476
476
|
MS_TRACE();
|
|
477
477
|
|
|
478
478
|
if (this->mapTransports.contains(transportId))
|
|
479
479
|
{
|
|
480
|
-
MS_THROW_ERROR("a Transport with same id already exists [method:%s]",
|
|
480
|
+
MS_THROW_ERROR("a Transport with same id already exists [method:%s]", method.c_str());
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
void Router::CheckNoRtpObserver(const std::string& rtpObserverId, const std::string&
|
|
484
|
+
void Router::CheckNoRtpObserver(const std::string& rtpObserverId, const std::string& method) const
|
|
485
485
|
{
|
|
486
486
|
MS_TRACE();
|
|
487
487
|
|
|
488
488
|
if (this->mapRtpObservers.contains(rtpObserverId))
|
|
489
489
|
{
|
|
490
|
-
MS_THROW_ERROR("an RtpObserver with same id already exists [method:%s]",
|
|
490
|
+
MS_THROW_ERROR("an RtpObserver with same id already exists [method:%s]", method.c_str());
|
|
491
491
|
}
|
|
492
492
|
}
|
|
493
493
|
|
|
@@ -566,7 +566,7 @@ namespace RTC
|
|
|
566
566
|
consumer->ProducerPaused();
|
|
567
567
|
}
|
|
568
568
|
|
|
569
|
-
auto it = this->mapProducerRtpObservers.find(producer);
|
|
569
|
+
const auto it = this->mapProducerRtpObservers.find(producer);
|
|
570
570
|
|
|
571
571
|
if (it != this->mapProducerRtpObservers.end())
|
|
572
572
|
{
|
|
@@ -590,7 +590,7 @@ namespace RTC
|
|
|
590
590
|
consumer->ProducerResumed();
|
|
591
591
|
}
|
|
592
592
|
|
|
593
|
-
auto it = this->mapProducerRtpObservers.find(producer);
|
|
593
|
+
const auto it = this->mapProducerRtpObservers.find(producer);
|
|
594
594
|
|
|
595
595
|
if (it != this->mapProducerRtpObservers.end())
|
|
596
596
|
{
|
|
@@ -688,7 +688,7 @@ namespace RTC
|
|
|
688
688
|
}
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
-
auto it = this->mapProducerRtpObservers.find(producer);
|
|
691
|
+
const auto it = this->mapProducerRtpObservers.find(producer);
|
|
692
692
|
|
|
693
693
|
if (it != this->mapProducerRtpObservers.end())
|
|
694
694
|
{
|
|
@@ -1076,7 +1076,7 @@ namespace RTC
|
|
|
1076
1076
|
RTC::Producer* Router::RtpObserverGetProducer(
|
|
1077
1077
|
RTC::RtpObserver* /* rtpObserver */, const std::string& id)
|
|
1078
1078
|
{
|
|
1079
|
-
auto it = this->mapProducers.find(id);
|
|
1079
|
+
const auto it = this->mapProducers.find(id);
|
|
1080
1080
|
|
|
1081
1081
|
if (it == this->mapProducers.end())
|
|
1082
1082
|
{
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include "RTC/SCTP/association/Association.hpp"
|
|
5
5
|
#include "Logger.hpp"
|
|
6
|
+
#include "RTC/SCTP/association/Capabilities.hpp"
|
|
6
7
|
#include "RTC/SCTP/packet/errorCauses/CookieReceivedWhileShuttingDownErrorCause.hpp"
|
|
7
8
|
#include "RTC/SCTP/packet/errorCauses/NoUserDataErrorCause.hpp"
|
|
8
9
|
#include "RTC/SCTP/packet/errorCauses/OutOfResourceErrorCause.hpp"
|
|
@@ -615,7 +616,7 @@ namespace RTC
|
|
|
615
616
|
|
|
616
617
|
if (this->tcb)
|
|
617
618
|
{
|
|
618
|
-
return this->tcb->GetNegotiatedCapabilities().
|
|
619
|
+
return this->tcb->GetNegotiatedCapabilities().maxOutboundStreams;
|
|
619
620
|
}
|
|
620
621
|
else
|
|
621
622
|
{
|
|
@@ -629,7 +630,7 @@ namespace RTC
|
|
|
629
630
|
|
|
630
631
|
if (this->tcb)
|
|
631
632
|
{
|
|
632
|
-
return this->tcb->GetNegotiatedCapabilities().
|
|
633
|
+
return this->tcb->GetNegotiatedCapabilities().maxInboundStreams;
|
|
633
634
|
}
|
|
634
635
|
else
|
|
635
636
|
{
|
|
@@ -780,11 +781,9 @@ namespace RTC
|
|
|
780
781
|
return this->state == State::ESTABLISHED;
|
|
781
782
|
});
|
|
782
783
|
|
|
783
|
-
this->privateMetrics.negotiatedMaxOutboundStreams =
|
|
784
|
-
|
|
785
|
-
this->privateMetrics.
|
|
786
|
-
negotiatedCapabilities.negotiatedMaxInboundStreams;
|
|
787
|
-
this->privateMetrics.usesPartialReliability = negotiatedCapabilities.partialReliability;
|
|
784
|
+
this->privateMetrics.negotiatedMaxOutboundStreams = negotiatedCapabilities.maxOutboundStreams;
|
|
785
|
+
this->privateMetrics.negotiatedMaxInboundStreams = negotiatedCapabilities.maxInboundStreams;
|
|
786
|
+
this->privateMetrics.usesPartialReliability = negotiatedCapabilities.partialReliability;
|
|
788
787
|
this->privateMetrics.usesMessageInterleaving = negotiatedCapabilities.messageInterleaving;
|
|
789
788
|
this->privateMetrics.usesReConfig = negotiatedCapabilities.reConfig;
|
|
790
789
|
this->privateMetrics.usesZeroChecksum = negotiatedCapabilities.zeroChecksum;
|
|
@@ -1564,8 +1563,13 @@ namespace RTC
|
|
|
1564
1563
|
// Insert a StateCookieParameter in the INIT-ACK chunk.
|
|
1565
1564
|
auto* stateCookieParameter = initAckChunk->BuildParameterInPlace<StateCookieParameter>();
|
|
1566
1565
|
|
|
1566
|
+
// The raw capabilities announced by the remote endpoint are stored in the
|
|
1567
|
+
// cookie (not the negotiated ones). This way, when the COOKIE-ECHO is
|
|
1568
|
+
// received they are re-negotiated against our local options, limiting the
|
|
1569
|
+
// effect of a tampered/forged cookie.
|
|
1570
|
+
const auto remoteCapabilities = Capabilities::Factory(receivedInitChunk);
|
|
1567
1571
|
const auto negotiatedCapabilities =
|
|
1568
|
-
NegotiatedCapabilities::Factory(this->sctpOptions,
|
|
1572
|
+
NegotiatedCapabilities::Factory(this->sctpOptions, remoteCapabilities);
|
|
1569
1573
|
|
|
1570
1574
|
// When authentication is enabled, generate an authenticated cookie with a
|
|
1571
1575
|
// creation timestamp and a MAC keyed with our per-association secret.
|
|
@@ -1581,7 +1585,7 @@ namespace RTC
|
|
|
1581
1585
|
receivedInitChunk->GetInitialTsn(),
|
|
1582
1586
|
receivedInitChunk->GetAdvertisedReceiverWindowCredit(),
|
|
1583
1587
|
tieTag,
|
|
1584
|
-
|
|
1588
|
+
remoteCapabilities,
|
|
1585
1589
|
/*creationTimestampMs*/ authenticateCookie ? this->shared->GetTimeMs() : 0,
|
|
1586
1590
|
/*macKey*/ authenticateCookie ? this->stateCookieSecret : nullptr,
|
|
1587
1591
|
/*macKeyLength*/ authenticateCookie ? Association::StateCookieSecretLength : 0);
|
|
@@ -1652,8 +1656,9 @@ namespace RTC
|
|
|
1652
1656
|
|
|
1653
1657
|
this->t1InitTimer->Stop();
|
|
1654
1658
|
|
|
1659
|
+
const auto remoteCapabilities = Capabilities::Factory(receivedInitAckChunk);
|
|
1655
1660
|
const auto negotiatedCapabilities =
|
|
1656
|
-
NegotiatedCapabilities::Factory(this->sctpOptions,
|
|
1661
|
+
NegotiatedCapabilities::Factory(this->sctpOptions, remoteCapabilities);
|
|
1657
1662
|
|
|
1658
1663
|
// If the association is re-established (peer restarted, but re-used old
|
|
1659
1664
|
// association), make sure that all message identifiers are reset and any
|
|
@@ -1774,6 +1779,13 @@ namespace RTC
|
|
|
1774
1779
|
// WebRTC, but is a valid operation on the SCTP level.
|
|
1775
1780
|
this->sendQueue.Reset();
|
|
1776
1781
|
|
|
1782
|
+
// Re-negotiate the raw capabilities stored in the cookie against our
|
|
1783
|
+
// local options. This limits the effect of a tampered/forged cookie
|
|
1784
|
+
// since it can never enable an extension we didn't signal nor raise
|
|
1785
|
+
// the stream limits above what we announced.
|
|
1786
|
+
const auto negotiatedCapabilities =
|
|
1787
|
+
NegotiatedCapabilities::Factory(this->sctpOptions, cookie->GetRemoteCapabilities());
|
|
1788
|
+
|
|
1777
1789
|
CreateTransmissionControlBlock(
|
|
1778
1790
|
cookie->GetLocalVerificationTag(),
|
|
1779
1791
|
cookie->GetRemoteVerificationTag(),
|
|
@@ -1781,7 +1793,7 @@ namespace RTC
|
|
|
1781
1793
|
cookie->GetRemoteInitialTsn(),
|
|
1782
1794
|
cookie->GetRemoteAdvertisedReceiverWindowCredit(),
|
|
1783
1795
|
/*tieTag*/ Utils::Crypto::GetRandomUInt<uint64_t>(0, MaxTieTag),
|
|
1784
|
-
|
|
1796
|
+
negotiatedCapabilities);
|
|
1785
1797
|
}
|
|
1786
1798
|
|
|
1787
1799
|
// https://datatracker.ietf.org/doc/html/rfc9260#section-5.1
|