mediasoup 3.21.0 → 3.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +1882 -0
  2. package/node/lib/test/test-Consumer.js +111 -0
  3. package/node/lib/test/test-Producer.js +54 -0
  4. package/npm-scripts.mjs +0 -5
  5. package/package.json +9 -8
  6. package/worker/fuzzer/src/RTC/SCTP/association/FuzzerStateCookie.cpp +4 -6
  7. package/worker/include/RTC/NEW_RTCP/packet/ByePacket.hpp +165 -0
  8. package/worker/include/RTC/NEW_RTCP/packet/CompoundPacket.hpp +183 -0
  9. package/worker/include/RTC/NEW_RTCP/packet/Packet.hpp +354 -0
  10. package/worker/include/RTC/NEW_RTCP/packet/TODO_NEW_RTCP.md +17 -0
  11. package/worker/include/RTC/RTP/Codecs/Tools.hpp +2 -0
  12. package/worker/include/RTC/Router.hpp +4 -4
  13. package/worker/include/RTC/SCTP/association/Capabilities.hpp +73 -0
  14. package/worker/include/RTC/SCTP/association/NegotiatedCapabilities.hpp +7 -9
  15. package/worker/include/RTC/SCTP/association/StateCookie.hpp +38 -28
  16. package/worker/include/RTC/SCTP/packet/Chunk.hpp +11 -7
  17. package/worker/include/RTC/SCTP/packet/ErrorCause.hpp +11 -4
  18. package/worker/include/RTC/SCTP/packet/Packet.hpp +1 -1
  19. package/worker/include/RTC/SCTP/packet/Parameter.hpp +11 -4
  20. package/worker/include/RTC/SCTP/packet/TLV.hpp +2 -2
  21. package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +2 -2
  22. package/worker/include/RTC/Transport.hpp +10 -10
  23. package/worker/include/Worker.hpp +4 -4
  24. package/worker/meson.build +7 -0
  25. package/worker/scripts/clang-scripts.mjs +54 -0
  26. package/worker/src/RTC/Consumer.cpp +22 -4
  27. package/worker/src/RTC/NEW_RTCP/packet/ByePacket.cpp +266 -0
  28. package/worker/src/RTC/NEW_RTCP/packet/CompoundPacket.cpp +219 -0
  29. package/worker/src/RTC/NEW_RTCP/packet/Packet.cpp +222 -0
  30. package/worker/src/RTC/RTP/Codecs/H264.cpp +3 -0
  31. package/worker/src/RTC/RTP/Codecs/VP8.cpp +3 -0
  32. package/worker/src/RTC/Router.cpp +14 -14
  33. package/worker/src/RTC/SCTP/association/Association.cpp +23 -11
  34. package/worker/src/RTC/SCTP/association/Capabilities.cpp +87 -0
  35. package/worker/src/RTC/SCTP/association/NegotiatedCapabilities.cpp +20 -40
  36. package/worker/src/RTC/SCTP/association/StateCookie.cpp +54 -32
  37. package/worker/src/RTC/SCTP/packet/Chunk.cpp +18 -18
  38. package/worker/src/RTC/SCTP/packet/ErrorCause.cpp +18 -18
  39. package/worker/src/RTC/SCTP/packet/Packet.cpp +2 -0
  40. package/worker/src/RTC/SCTP/packet/Parameter.cpp +18 -18
  41. package/worker/src/RTC/SCTP/packet/TLV.cpp +27 -25
  42. package/worker/src/RTC/SCTP/packet/parameters/StateCookieParameter.cpp +2 -2
  43. package/worker/src/RTC/SvcProducerStreamManager.cpp +4 -1
  44. package/worker/src/RTC/Transport.cpp +42 -30
  45. package/worker/src/Worker.cpp +10 -10
  46. package/worker/test/include/RTC/ICE/iceCommon.hpp +1 -1
  47. package/worker/test/include/RTC/RTCP/rtcpCommon.hpp +58 -0
  48. package/worker/test/include/RTC/RTP/rtpCommon.hpp +1 -1
  49. package/worker/test/src/RTC/NEW_RTCP/packet/TestByePacket.cpp +302 -0
  50. package/worker/test/src/RTC/NEW_RTCP/rtcpCommon.cpp +29 -0
  51. package/worker/test/src/RTC/RTP/TestPacket.cpp +17 -15
  52. package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +3 -3
  53. package/worker/test/src/RTC/SCTP/association/TestCapabilities.cpp +99 -0
  54. package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +14 -16
  55. package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +198 -102
  56. package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +11 -10
@@ -0,0 +1,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& message) const
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]", message.c_str());
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& message) const
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]", message.c_str());
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& message) const
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]", message.c_str());
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& message) const
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]", message.c_str());
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().negotiatedMaxOutboundStreams;
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().negotiatedMaxInboundStreams;
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
- negotiatedCapabilities.negotiatedMaxOutboundStreams;
785
- this->privateMetrics.negotiatedMaxInboundStreams =
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, receivedInitChunk);
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
- negotiatedCapabilities,
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, receivedInitAckChunk);
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
- cookie->GetNegotiatedCapabilities());
1796
+ negotiatedCapabilities);
1785
1797
  }
1786
1798
 
1787
1799
  // https://datatracker.ietf.org/doc/html/rfc9260#section-5.1