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
@@ -43,7 +43,7 @@ namespace RTC
43
43
 
44
44
  class Chunk : public TLV
45
45
  {
46
- // We need that packet calls protected and private methods in this class.
46
+ // We need that Packet calls protected and private methods in this class.
47
47
  friend class Packet;
48
48
 
49
49
  public:
@@ -148,6 +148,9 @@ namespace RTC
148
148
  static constexpr size_t ChunkHeaderLength{ 4 };
149
149
 
150
150
  public:
151
+ static const std::string& ChunkTypeToString(ChunkType chunkType);
152
+
153
+ protected:
151
154
  /**
152
155
  * Whether given buffer could be a a valid chunk.
153
156
  *
@@ -168,8 +171,6 @@ namespace RTC
168
171
  uint16_t& chunkLength,
169
172
  uint8_t& padding);
170
173
 
171
- static const std::string& ChunkTypeToString(ChunkType chunkType);
172
-
173
174
  private:
174
175
  static const ankerl::unordered_dense::map<ChunkType, std::string> ChunkType2String;
175
176
 
@@ -183,12 +184,15 @@ namespace RTC
183
184
  public:
184
185
  ~Chunk() override;
185
186
 
187
+ /**
188
+ * Must be overridden by each subclass.
189
+ */
186
190
  void Dump(int indentation = 0) const override = 0;
187
191
 
188
192
  void Serialize(uint8_t* buffer, size_t bufferLength) final;
189
193
 
190
194
  /**
191
- * Can be overridden by each subclass.
195
+ * Must be overridden by each subclass.
192
196
  */
193
197
  Chunk* Clone(uint8_t* buffer, size_t bufferLength) const override = 0;
194
198
 
@@ -323,7 +327,7 @@ namespace RTC
323
327
  auto* ptr = const_cast<uint8_t*>(GetBuffer()) + GetLength();
324
328
  // The remaining length in the buffer is the potential buffer length
325
329
  // of the parameter.
326
- size_t parameterMaxBufferLength = GetBufferLength() - (ptr - GetBuffer());
330
+ const size_t parameterMaxBufferLength = GetBufferLength() - (ptr - GetBuffer());
327
331
 
328
332
  auto* parameter = T::Factory(ptr, parameterMaxBufferLength);
329
333
 
@@ -444,7 +448,7 @@ namespace RTC
444
448
  auto* ptr = const_cast<uint8_t*>(GetBuffer()) + GetLength();
445
449
  // The remaining length in the buffer is the potential buffer length
446
450
  // of the error cause.
447
- size_t errorCauseMaxBufferLength = GetBufferLength() - (ptr - GetBuffer());
451
+ const size_t errorCauseMaxBufferLength = GetBufferLength() - (ptr - GetBuffer());
448
452
 
449
453
  auto* errorCause = T::Factory(ptr, errorCauseMaxBufferLength);
450
454
 
@@ -491,7 +495,7 @@ namespace RTC
491
495
 
492
496
  virtual void SoftCloneInto(Chunk* chunk) const final;
493
497
 
494
- virtual void InitializeHeader(ChunkType chunkType, uint8_t flags, uint16_t lengthFieldValue) final;
498
+ virtual void InitializeHeader(ChunkType chunkType, uint8_t flags, uint16_t length) final;
495
499
 
496
500
  virtual bool GetBit0() const final
497
501
  {
@@ -39,7 +39,7 @@ namespace RTC
39
39
 
40
40
  class ErrorCause : public TLV
41
41
  {
42
- // We need that chunk calls protected and private methods in this class.
42
+ // We need that Chunk calls protected and private methods in this class.
43
43
  friend class Chunk;
44
44
 
45
45
  public:
@@ -88,6 +88,9 @@ namespace RTC
88
88
  static constexpr size_t ErrorCauseHeaderLength{ 4 };
89
89
 
90
90
  public:
91
+ static const std::string& ErrorCauseCodeToString(ErrorCauseCode causeCode);
92
+
93
+ protected:
91
94
  /**
92
95
  * Whether given buffer could be a a valid error cause.
93
96
  *
@@ -108,8 +111,6 @@ namespace RTC
108
111
  uint16_t& causeLength,
109
112
  uint8_t& padding);
110
113
 
111
- static const std::string& ErrorCauseCodeToString(ErrorCauseCode causeCode);
112
-
113
114
  private:
114
115
  static const ankerl::unordered_dense::map<ErrorCauseCode, std::string> ErrorCauseCode2String;
115
116
 
@@ -123,8 +124,14 @@ namespace RTC
123
124
  public:
124
125
  ~ErrorCause() override;
125
126
 
127
+ /**
128
+ * Must be overridden by each subclass.
129
+ */
126
130
  void Dump(int indentation = 0) const override = 0;
127
131
 
132
+ /**
133
+ * Must be overridden by each subclass.
134
+ */
128
135
  ErrorCause* Clone(uint8_t* buffer, size_t bufferLength) const override = 0;
129
136
 
130
137
  virtual ErrorCauseCode GetCode() const final
@@ -170,7 +177,7 @@ namespace RTC
170
177
 
171
178
  virtual void SoftCloneInto(ErrorCause* errorCause) const final;
172
179
 
173
- virtual void InitializeHeader(ErrorCauseCode errorCauseCode, uint16_t lengthFieldValue) final;
180
+ virtual void InitializeHeader(ErrorCauseCode errorCauseCode, uint16_t length) final;
174
181
 
175
182
  /**
176
183
  * Error Cause subclasses with header bigger than default one (4 bytes)
@@ -239,7 +239,7 @@ namespace RTC
239
239
  auto* ptr = const_cast<uint8_t*>(GetBuffer()) + GetLength();
240
240
  // The remaining length in the buffer is the potential buffer length
241
241
  // of the chunk.
242
- size_t chunkMaxBufferLength = GetBufferLength() - (ptr - GetBuffer());
242
+ const size_t chunkMaxBufferLength = GetBufferLength() - (ptr - GetBuffer());
243
243
 
244
244
  auto* chunk = T::Factory(ptr, chunkMaxBufferLength);
245
245
 
@@ -40,7 +40,7 @@ namespace RTC
40
40
 
41
41
  class Parameter : public TLV
42
42
  {
43
- // We need that chunk calls protected and private methods in this class.
43
+ // We need that Chunk calls protected and private methods in this class.
44
44
  friend class Chunk;
45
45
 
46
46
  public:
@@ -102,6 +102,9 @@ namespace RTC
102
102
  static constexpr size_t ParameterHeaderLength{ 4 };
103
103
 
104
104
  public:
105
+ static const std::string& ParameterTypeToString(ParameterType parameterType);
106
+
107
+ protected:
105
108
  /**
106
109
  * Whether given buffer could be a a valid parameter.
107
110
  *
@@ -123,8 +126,6 @@ namespace RTC
123
126
  uint16_t& parameterLength,
124
127
  uint8_t& padding);
125
128
 
126
- static const std::string& ParameterTypeToString(ParameterType parameterType);
127
-
128
129
  private:
129
130
  static const ankerl::unordered_dense::map<ParameterType, std::string> ParameterType2String;
130
131
 
@@ -138,8 +139,14 @@ namespace RTC
138
139
  public:
139
140
  ~Parameter() override;
140
141
 
142
+ /**
143
+ * Must be overridden by each subclass.
144
+ */
141
145
  void Dump(int indentation = 0) const override = 0;
142
146
 
147
+ /**
148
+ * Must be overridden by each subclass.
149
+ */
143
150
  Parameter* Clone(uint8_t* buffer, size_t bufferLength) const override = 0;
144
151
 
145
152
  virtual ParameterType GetType() const final
@@ -173,7 +180,7 @@ namespace RTC
173
180
 
174
181
  virtual void SoftCloneInto(Parameter* parameter) const final;
175
182
 
176
- virtual void InitializeHeader(ParameterType parameterType, uint16_t lengthFieldValue) final;
183
+ virtual void InitializeHeader(ParameterType parameterType, uint16_t length) final;
177
184
 
178
185
  /**
179
186
  * Parameter subclasses with header bigger than default one (4 bytes)
@@ -54,7 +54,7 @@ namespace RTC
54
54
  */
55
55
  virtual void DumpCommon(int indentation) const;
56
56
 
57
- virtual void InitializeTLVHeader(uint16_t lengthFieldValue) final;
57
+ virtual void InitializeTLVHeader(uint16_t length) final;
58
58
 
59
59
  /**
60
60
  * Subclasses with header bigger than default one (4 bytes) must override
@@ -163,7 +163,7 @@ namespace RTC
163
163
  * @throw MediaSoupTypeError - If given `length` is higher than maximum
164
164
  * allowed one (65535).
165
165
  */
166
- virtual void SetLengthField(size_t lengthField) final;
166
+ virtual void SetLengthField(size_t length) final;
167
167
  };
168
168
  } // namespace SCTP
169
169
  } // namespace RTC
@@ -2,7 +2,7 @@
2
2
  #define MS_RTC_SCTP_STATE_COOKIE_PARAMETER_HPP
3
3
 
4
4
  #include "common.hpp"
5
- #include "RTC/SCTP/association/NegotiatedCapabilities.hpp"
5
+ #include "RTC/SCTP/association/Capabilities.hpp"
6
6
  #include "RTC/SCTP/packet/Parameter.hpp"
7
7
 
8
8
  namespace RTC
@@ -104,7 +104,7 @@ namespace RTC
104
104
  uint32_t remoteInitialTsn,
105
105
  uint32_t remoteAdvertisedReceiverWindowCredit,
106
106
  uint64_t tieTag,
107
- const NegotiatedCapabilities& negotiatedCapabilities,
107
+ const Capabilities& remoteCapabilities,
108
108
  uint64_t creationTimestampMs = 0,
109
109
  const uint8_t* macKey = nullptr,
110
110
  size_t macKeyLength = 0);
@@ -201,23 +201,23 @@ namespace RTC
201
201
 
202
202
  private:
203
203
  virtual RTC::Producer* AssertAndGetProducerById(
204
- const std::string& producerId, const std::string& message) const final;
204
+ const std::string& producerId, const std::string& method) const final;
205
205
  virtual RTC::Consumer* AssertAndGetConsumerById(
206
- const std::string& consumerId, const std::string& message) const final;
206
+ const std::string& consumerId, const std::string& method) const final;
207
207
  virtual RTC::Consumer* GetConsumerByMediaSsrc(uint32_t ssrc) const final;
208
208
  virtual RTC::Consumer* GetConsumerByRtxSsrc(uint32_t ssrc) const final;
209
209
  virtual RTC::DataProducer* AssertAndGetDataProducerById(
210
- const std::string& dataProducerId, const std::string& message) const final;
210
+ const std::string& dataProducerId, const std::string& method) const final;
211
211
  virtual RTC::DataConsumer* AssertAndGetDataConsumerById(
212
- const std::string& dataConsumerId, const std::string& message) const final;
213
- virtual RTC::DataConsumer* AssertAndGetSctpDataConsumerByStreamId(uint16_t streamId) const final;
214
- virtual void CheckNoProducer(const std::string& producerId, const std::string& message) const final;
215
- virtual void CheckNoConsumer(const std::string& consumerId, const std::string& message) const final;
212
+ const std::string& dataConsumerId, const std::string& method) const final;
213
+ virtual RTC::DataConsumer* GetSctpDataConsumerByStreamId(uint16_t streamId) const final;
214
+ virtual void CheckNoProducer(const std::string& producerId, const std::string& method) const final;
215
+ virtual void CheckNoConsumer(const std::string& consumerId, const std::string& method) const final;
216
216
  virtual void CheckNoDataProducer(
217
- const std::string& dataProducerId, const std::string& message) const final;
217
+ const std::string& dataProducerId, const std::string& method) const final;
218
218
  virtual void CheckNoDataConsumer(
219
- const std::string& dataConsumerId, const std::string& message) const final;
220
- virtual void CheckNoSctpDataConsumer(uint16_t streamId, const std::string& message) const final;
219
+ const std::string& dataConsumerId, const std::string& method) const final;
220
+ virtual void CheckNoSctpDataConsumer(uint16_t streamId, const std::string& method) const final;
221
221
  virtual bool IsConnected() const = 0;
222
222
  virtual void SendRtpPacket(
223
223
  RTC::Consumer* consumer, RTC::RTP::Packet* packet, const onSendCallback* cb = nullptr) = 0;
@@ -27,10 +27,10 @@ private:
27
27
  flatbuffers::FlatBufferBuilder& builder) const;
28
28
  void SetNewRouterId(std::string& routerId) const;
29
29
  RTC::WebRtcServer* AssertAndGetWebRtcServerById(
30
- const std::string& webRtcServerId, const std::string& message) const;
31
- RTC::Router* AssertAndGetRouterById(const std::string& routerId, const std::string& message) const;
32
- void CheckNoWebRtcServer(const std::string& webRtcServerId, const std::string& message) const;
33
- void CheckNoRouter(const std::string& routerId, const std::string& message) const;
30
+ const std::string& webRtcServerId, const std::string& method) const;
31
+ RTC::Router* AssertAndGetRouterById(const std::string& routerId, const std::string& method) const;
32
+ void CheckNoWebRtcServer(const std::string& webRtcServerId, const std::string& method) const;
33
+ void CheckNoRouter(const std::string& routerId, const std::string& method) const;
34
34
 
35
35
  /* Methods inherited from Channel::ChannelSocket::RequestHandler. */
36
36
  public:
@@ -202,8 +202,12 @@ common_sources = [
202
202
  'src/RTC/RTCP/XR.cpp',
203
203
  'src/RTC/RTCP/XrDelaySinceLastRr.cpp',
204
204
  'src/RTC/RTCP/XrReceiverReferenceTime.cpp',
205
+ 'src/RTC/NEW_RTCP/packet/CompoundPacket.cpp',
206
+ 'src/RTC/NEW_RTCP/packet/Packet.cpp',
207
+ 'src/RTC/NEW_RTCP/packet/ByePacket.cpp',
205
208
  'src/RTC/SCTP/association/Association.cpp',
206
209
  'src/RTC/SCTP/association/AssociationListenerDeferrer.cpp',
210
+ 'src/RTC/SCTP/association/Capabilities.cpp',
207
211
  'src/RTC/SCTP/association/HeartbeatHandler.cpp',
208
212
  'src/RTC/SCTP/association/NegotiatedCapabilities.cpp',
209
213
  'src/RTC/SCTP/association/PacketSender.cpp',
@@ -463,8 +467,11 @@ test_sources = [
463
467
  'test/src/RTC/RTCP/TestSenderReport.cpp',
464
468
  'test/src/RTC/RTCP/TestPacket.cpp',
465
469
  'test/src/RTC/RTCP/TestXr.cpp',
470
+ 'test/src/RTC/NEW_RTCP/rtcpCommon.cpp',
471
+ 'test/src/RTC/NEW_RTCP/packet/TestByePacket.cpp',
466
472
  'test/src/RTC/SCTP/sctpCommon.cpp',
467
473
  'test/src/RTC/SCTP/association/TestAssociation.cpp',
474
+ 'test/src/RTC/SCTP/association/TestCapabilities.cpp',
468
475
  'test/src/RTC/SCTP/association/TestHeartbeatHandler.cpp',
469
476
  'test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp',
470
477
  'test/src/RTC/SCTP/association/TestPacketSender.cpp',
@@ -170,6 +170,27 @@ function normalizeCompileCommands() {
170
170
  // Convert to relative path from repo root.
171
171
  entry.file = path.relative(ROOT_DIR, absolutePath);
172
172
  }
173
+
174
+ // Make include search paths absolute. Meson emits them relative to the
175
+ // build directory, which makes clang-tidy report note locations (such as
176
+ // those coming from Catch2 macro expansions) with relative paths that
177
+ // ZedThree/clang-tidy-review fails to open (it resolves them against its
178
+ // own working directory). Absolutizing them avoids that.
179
+ if (entry.directory) {
180
+ if (typeof entry.command === 'string') {
181
+ entry.command = normalizeIncludePaths(
182
+ entry.command.split(/\s+/),
183
+ entry.directory
184
+ ).join(' ');
185
+ }
186
+
187
+ if (Array.isArray(entry.arguments)) {
188
+ entry.arguments = normalizeIncludePaths(
189
+ entry.arguments,
190
+ entry.directory
191
+ );
192
+ }
193
+ }
173
194
  }
174
195
 
175
196
  fs.writeFileSync(compileCommandsFile, JSON.stringify(commands, null, 2));
@@ -182,6 +203,39 @@ function normalizeCompileCommands() {
182
203
  }
183
204
  }
184
205
 
206
+ function normalizeIncludePaths(tokens, directory) {
207
+ const includeFlags = ['-I', '-isystem', '-iquote', '-idirafter'];
208
+ const result = [];
209
+
210
+ for (let i = 0; i < tokens.length; ++i) {
211
+ const token = tokens[i];
212
+
213
+ // Attached form, e.g. `-I../../../subprojects/foo`.
214
+ const attachedFlag = includeFlags.find(
215
+ flag => token.startsWith(flag) && token.length > flag.length
216
+ );
217
+
218
+ if (attachedFlag) {
219
+ const includePath = token.slice(attachedFlag.length);
220
+
221
+ result.push(`${attachedFlag}${path.resolve(directory, includePath)}`);
222
+
223
+ continue;
224
+ }
225
+
226
+ // Separated form, e.g. `-isystem ../../../subprojects/foo`.
227
+ if (includeFlags.includes(token) && i + 1 < tokens.length) {
228
+ result.push(token, path.resolve(directory, tokens[++i]));
229
+
230
+ continue;
231
+ }
232
+
233
+ result.push(token);
234
+ }
235
+
236
+ return result;
237
+ }
238
+
185
239
  function getClangToolBinary({ clangToolName, version, checkRequireVersion }) {
186
240
  logInfo(
187
241
  `getClangToolBinary() [clangToolName:${clangToolName}, version:${version}]`
@@ -33,12 +33,11 @@ namespace RTC
33
33
  producerId(producerId),
34
34
  shared(shared),
35
35
  listener(listener),
36
- kind(RTC::Media::Kind(data->kind())),
37
- type(RTC::RtpParameters::Type(data->type()))
36
+ kind(RTC::Media::Kind(data->kind()))
38
37
  {
39
38
  MS_TRACE();
40
39
 
41
- this->pipe = this->type == RTC::RtpParameters::Type::PIPE;
40
+ this->pipe = data->type() == FBS::RtpParameters::Type::PIPE;
42
41
 
43
42
  // This may throw.
44
43
  this->rtpParameters = RTC::RtpParameters(data->rtpParameters());
@@ -85,7 +84,7 @@ namespace RTC
85
84
  }
86
85
 
87
86
  // Ensure there are as many encodings as consumable encodings for pipe.
88
- if (pipe && this->rtpParameters.encodings.size() != this->consumableRtpEncodings.size())
87
+ if (this->pipe && this->rtpParameters.encodings.size() != this->consumableRtpEncodings.size())
89
88
  {
90
89
  MS_THROW_TYPE_ERROR("number of rtpParameters.encodings and consumableRtpEncodings do not match");
91
90
  }
@@ -203,6 +202,25 @@ namespace RTC
203
202
  // Build preferred layers from FBS data.
204
203
  RTC::ConsumerTypes::VideoLayers preferredLayers;
205
204
 
205
+ // Derive the stream type from consumableRtpEncodings.
206
+ if (this->pipe)
207
+ {
208
+ this->type = RTC::RtpParameters::Type::PIPE;
209
+ }
210
+ else if (this->consumableRtpEncodings.size() > 1u)
211
+ {
212
+ this->type = RTC::RtpParameters::Type::SIMULCAST;
213
+ }
214
+ else if (this->consumableRtpEncodings[0].spatialLayers > 1u || this->consumableRtpEncodings[0].temporalLayers > 1u)
215
+ {
216
+ // Single encoding with multiple layers is always SVC.
217
+ this->type = RTC::RtpParameters::Type::SVC;
218
+ }
219
+ else
220
+ {
221
+ this->type = RTC::RtpParameters::Type::SIMPLE;
222
+ }
223
+
206
224
  // Create the appropriate ProducerStreamManager subclass based on type.
207
225
  switch (this->type)
208
226
  {
@@ -0,0 +1,266 @@
1
+ #define MS_CLASS "RTC::NEW_RTCP::ByePacket"
2
+ // #define MS_LOG_DEV_LEVEL 3
3
+
4
+ #include "RTC/NEW_RTCP/packet/ByePacket.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 methods. */
15
+
16
+ ByePacket* ByePacket::Parse(const uint8_t* buffer, size_t bufferLength)
17
+ {
18
+ MS_TRACE();
19
+
20
+ Packet::PacketType packetType;
21
+ size_t packetLength;
22
+
23
+ if (!Packet::IsPacket(buffer, bufferLength, packetType, packetLength))
24
+ {
25
+ return nullptr;
26
+ }
27
+
28
+ if (packetType != Packet::PacketType::BYE)
29
+ {
30
+ MS_WARN_DEV("invalid packet type");
31
+
32
+ return nullptr;
33
+ }
34
+
35
+ return ByePacket::ParseStrict(buffer, bufferLength, packetLength);
36
+ }
37
+
38
+ ByePacket* ByePacket::Factory(uint8_t* buffer, size_t bufferLength)
39
+ {
40
+ MS_TRACE();
41
+
42
+ if (bufferLength < Packet::CommonHeaderLength)
43
+ {
44
+ MS_THROW_TYPE_ERROR("buffer too small");
45
+ }
46
+
47
+ auto* packet = new ByePacket(buffer, bufferLength);
48
+
49
+ packet->InitializeHeader(Packet::PacketType::BYE, Packet::CommonHeaderLength);
50
+
51
+ // No need to invoke SetLength() since constructor invoked it with
52
+ // minimum Packet length.
53
+
54
+ return packet;
55
+ }
56
+
57
+ ByePacket* ByePacket::ParseStrict(const uint8_t* buffer, size_t bufferLength, size_t packetLength)
58
+ {
59
+ MS_TRACE();
60
+
61
+ auto* packet = new ByePacket(const_cast<uint8_t*>(buffer), bufferLength);
62
+
63
+ // Must always invoke SetLength() after constructing a Serializable with
64
+ // not fixed length. It's also required so the getters below operate
65
+ // against the real packet bounds.
66
+ packet->SetLength(packetLength);
67
+
68
+ // Validate that the announced SSRC/CSRC count fits into the packet.
69
+ const size_t ssrcsEndOffset = Packet::CommonHeaderLength + (packet->GetCount() * 4);
70
+
71
+ if (ssrcsEndOffset > packetLength)
72
+ {
73
+ MS_WARN_TAG(rtcp, "SSRC/CSRC count exceeds the packet length");
74
+
75
+ delete packet;
76
+ return nullptr;
77
+ }
78
+
79
+ // Validate that the value of the Reason length field fits into the packet.
80
+ if (packet->HasReason())
81
+ {
82
+ const uint8_t reasonLength = packet->GetReasonLength();
83
+ // The Reason string starts right after the 1 byte Reason length field.
84
+ const size_t reasonEndOffset = ssrcsEndOffset + 1 + reasonLength;
85
+
86
+ if (reasonEndOffset > packetLength)
87
+ {
88
+ MS_WARN_TAG(
89
+ rtcp, "Reason length (%" PRIu8 " bytes) exceeds the packet length", reasonLength);
90
+
91
+ delete packet;
92
+ return nullptr;
93
+ }
94
+ }
95
+
96
+ return packet;
97
+ }
98
+
99
+ /* Instance methods. */
100
+
101
+ ByePacket::ByePacket(uint8_t* buffer, size_t bufferLength) : Packet(buffer, bufferLength)
102
+ {
103
+ MS_TRACE();
104
+
105
+ SetLength(Packet::CommonHeaderLength);
106
+ }
107
+
108
+ ByePacket::~ByePacket()
109
+ {
110
+ MS_TRACE();
111
+ }
112
+
113
+ void ByePacket::Dump(int indentation) const
114
+ {
115
+ MS_TRACE();
116
+
117
+ MS_DUMP_CLEAN(indentation, "<RTCP::ByePacket>");
118
+ DumpCommon(indentation);
119
+ MS_DUMP_CLEAN(indentation, " ssrcs:");
120
+ for (const uint32_t ssrc : GetSsrcs())
121
+ {
122
+ MS_DUMP_CLEAN(indentation, " - ssrc: %" PRIu32, ssrc);
123
+ }
124
+ if (HasReason())
125
+ {
126
+ const auto reason = GetReason();
127
+
128
+ MS_DUMP_CLEAN(indentation, " has reason: yes");
129
+ MS_DUMP_CLEAN(
130
+ indentation, " reason: \"%.*s\"", static_cast<int>(reason.size()), reason.data());
131
+ }
132
+ else
133
+ {
134
+ MS_DUMP_CLEAN(indentation, " has reason: no");
135
+ }
136
+ MS_DUMP_CLEAN(indentation, "</RTCP::ByePacket>");
137
+ }
138
+
139
+ ByePacket* ByePacket::Clone(uint8_t* buffer, size_t bufferLength) const
140
+ {
141
+ MS_TRACE();
142
+
143
+ auto* clonedPacket = new ByePacket(buffer, bufferLength);
144
+
145
+ CloneInto(clonedPacket);
146
+ SoftCloneInto(clonedPacket);
147
+
148
+ return clonedPacket;
149
+ }
150
+
151
+ std::vector<uint32_t> ByePacket::GetSsrcs() const
152
+ {
153
+ MS_TRACE();
154
+
155
+ const uint8_t numberOfSsrcs = GetCount();
156
+ std::vector<uint32_t> ssrcs;
157
+
158
+ ssrcs.reserve(numberOfSsrcs);
159
+
160
+ for (uint8_t idx{ 0 }; idx < numberOfSsrcs; ++idx)
161
+ {
162
+ ssrcs.emplace_back(GetSsrcAt(idx));
163
+ }
164
+
165
+ return ssrcs;
166
+ }
167
+
168
+ void ByePacket::AddSsrc(uint32_t ssrc)
169
+ {
170
+ MS_TRACE();
171
+
172
+ if (GetCount() == 31)
173
+ {
174
+ MS_THROW_ERROR("cannot add more than 31 ssrcs");
175
+ }
176
+
177
+ // NOTE: Must be checked before growing the length below, otherwise
178
+ // `HasReason()` would be unreliable since the length grows before the
179
+ // Count field is incremented.
180
+ const bool hadReason = HasReason();
181
+
182
+ // NOTE: This may throw.
183
+ SetVariableLengthValueLength(GetVariableLengthValueLength() + 4);
184
+
185
+ // Must move Reason fields down to make room for the new SSRC.
186
+ if (hadReason)
187
+ {
188
+ std::memmove(
189
+ GetReasonLengthPointer() + 4,
190
+ GetReasonLengthPointer(),
191
+ Utils::Byte::PadTo4Bytes(1u + GetReasonLength()));
192
+ }
193
+
194
+ // Add the new ssrc.
195
+ Utils::Byte::Set4Bytes(GetSsrcsPointer(), GetCount() * 4, ssrc);
196
+
197
+ // Update the counter field.
198
+ SetCount(GetCount() + 1);
199
+ }
200
+
201
+ void ByePacket::SetReason(const std::string_view& reason)
202
+ {
203
+ MS_TRACE();
204
+
205
+ if (reason.size() > std::numeric_limits<uint8_t>::max())
206
+ {
207
+ MS_THROW_TYPE_ERROR("reason length (%zu bytes) cannot be greater than 255", reason.size());
208
+ }
209
+
210
+ const size_t previousLength = GetLength();
211
+ const size_t previousLengthField = GetLengthFieldComputed();
212
+ // The previous total length of Reason length and Reason fields padded
213
+ // to 4 bytes.
214
+ const uint16_t previousReasonFieldsPaddedLength =
215
+ HasReason() ? Utils::Byte::PadTo4Bytes(1u + GetReasonLength()) : 0;
216
+ // The new total length of Reason length and Reason fields padded to
217
+ // 4 bytes.
218
+ const uint16_t newReasonFieldsPaddedLength =
219
+ !reason.empty() ? Utils::Byte::PadTo4Bytes(1 + reason.size()) : 0;
220
+ const size_t newLength = size_t{ previousLength } - size_t{ previousReasonFieldsPaddedLength } +
221
+ size_t{ newReasonFieldsPaddedLength };
222
+
223
+ try
224
+ {
225
+ // Let's call SetLength() on parent with the new computed length.
226
+ // NOTE: If there is no space in the buffer for it, it will throw.
227
+ SetLength(newLength);
228
+
229
+ // Update length field.
230
+ // NOTE: This will throw if computed value is too big.
231
+ SetLengthField(newLength);
232
+
233
+ if (!reason.empty())
234
+ {
235
+ // Write Reason length field.
236
+ Utils::Byte::Set1Byte(GetReasonLengthPointer(), 0, reason.size());
237
+
238
+ // Write Reason field.
239
+ std::memmove(GetReasonPointer(), reason.data(), reason.size());
240
+
241
+ // Fill padding bytes with zero.
242
+ FillPadding(newReasonFieldsPaddedLength - 1 - reason.size());
243
+ }
244
+ }
245
+ catch (const MediaSoupError& error)
246
+ {
247
+ // Rollback.
248
+ SetLength(previousLength);
249
+ SetLengthField(previousLengthField);
250
+
251
+ throw;
252
+ }
253
+ }
254
+
255
+ ByePacket* ByePacket::SoftClone(const uint8_t* buffer) const
256
+ {
257
+ MS_TRACE();
258
+
259
+ auto* softClonedPacket = new ByePacket(const_cast<uint8_t*>(buffer), GetLength());
260
+
261
+ SoftCloneInto(softClonedPacket);
262
+
263
+ return softClonedPacket;
264
+ }
265
+ } // namespace NEW_RTCP
266
+ } // namespace RTC