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
@@ -1401,6 +1401,10 @@ namespace RTC
1401
1401
 
1402
1402
  if (this->sctpAssociation)
1403
1403
  {
1404
+ // NOTE: This must be called after removing data consumers from the maps,
1405
+ // otherwise if `OnAssociationStreamBufferedAmountLow()` was triggered it
1406
+ // would end up emitting an event associated to an already closed data
1407
+ // consumer.
1404
1408
  this->sctpAssociation->ResetStreams(
1405
1409
  std::array<uint16_t, 1>{ dataConsumer->GetSctpStreamParameters().streamId });
1406
1410
  }
@@ -1760,30 +1764,30 @@ namespace RTC
1760
1764
  }
1761
1765
 
1762
1766
  RTC::Producer* Transport::AssertAndGetProducerById(
1763
- const std::string& producerId, const std::string& message) const
1767
+ const std::string& producerId, const std::string& method) const
1764
1768
  {
1765
1769
  MS_TRACE();
1766
1770
 
1767
- auto it = this->mapProducers.find(producerId);
1771
+ const auto it = this->mapProducers.find(producerId);
1768
1772
 
1769
1773
  if (it == this->mapProducers.end())
1770
1774
  {
1771
- MS_THROW_NOT_FOUND_ERROR("Producer not found [method:%s]", message.c_str());
1775
+ MS_THROW_NOT_FOUND_ERROR("Producer not found [method:%s]", method.c_str());
1772
1776
  }
1773
1777
 
1774
1778
  return it->second;
1775
1779
  }
1776
1780
 
1777
1781
  RTC::Consumer* Transport::AssertAndGetConsumerById(
1778
- const std::string& consumerId, const std::string& message) const
1782
+ const std::string& consumerId, const std::string& method) const
1779
1783
  {
1780
1784
  MS_TRACE();
1781
1785
 
1782
- auto it = this->mapConsumers.find(consumerId);
1786
+ const auto it = this->mapConsumers.find(consumerId);
1783
1787
 
1784
1788
  if (it == this->mapConsumers.end())
1785
1789
  {
1786
- MS_THROW_NOT_FOUND_ERROR("Consumer not found [method:%s]", message.c_str());
1790
+ MS_THROW_NOT_FOUND_ERROR("Consumer not found [method:%s]", method.c_str());
1787
1791
  }
1788
1792
 
1789
1793
  return it->second;
@@ -1793,7 +1797,7 @@ namespace RTC
1793
1797
  {
1794
1798
  MS_TRACE();
1795
1799
 
1796
- auto mapSsrcConsumerIt = this->mapSsrcConsumer.find(ssrc);
1800
+ const auto mapSsrcConsumerIt = this->mapSsrcConsumer.find(ssrc);
1797
1801
 
1798
1802
  if (mapSsrcConsumerIt == this->mapSsrcConsumer.end())
1799
1803
  {
@@ -1809,7 +1813,7 @@ namespace RTC
1809
1813
  {
1810
1814
  MS_TRACE();
1811
1815
 
1812
- auto mapRtxSsrcConsumerIt = this->mapRtxSsrcConsumer.find(ssrc);
1816
+ const auto mapRtxSsrcConsumerIt = this->mapRtxSsrcConsumer.find(ssrc);
1813
1817
 
1814
1818
  if (mapRtxSsrcConsumerIt == this->mapRtxSsrcConsumer.end())
1815
1819
  {
@@ -1822,92 +1826,92 @@ namespace RTC
1822
1826
  }
1823
1827
 
1824
1828
  RTC::DataProducer* Transport::AssertAndGetDataProducerById(
1825
- const std::string& dataProducerId, const std::string& message) const
1829
+ const std::string& dataProducerId, const std::string& method) const
1826
1830
  {
1827
1831
  MS_TRACE();
1828
1832
 
1829
- auto it = this->mapDataProducers.find(dataProducerId);
1833
+ const auto it = this->mapDataProducers.find(dataProducerId);
1830
1834
 
1831
1835
  if (it == this->mapDataProducers.end())
1832
1836
  {
1833
- MS_THROW_NOT_FOUND_ERROR("DataProducer not found [method:%s]", message.c_str());
1837
+ MS_THROW_NOT_FOUND_ERROR("DataProducer not found [method:%s]", method.c_str());
1834
1838
  }
1835
1839
 
1836
1840
  return it->second;
1837
1841
  }
1838
1842
 
1839
1843
  RTC::DataConsumer* Transport::AssertAndGetDataConsumerById(
1840
- const std::string& dataConsumerId, const std::string& message) const
1844
+ const std::string& dataConsumerId, const std::string& method) const
1841
1845
  {
1842
1846
  MS_TRACE();
1843
1847
 
1844
- auto it = this->mapDataConsumers.find(dataConsumerId);
1848
+ const auto it = this->mapDataConsumers.find(dataConsumerId);
1845
1849
 
1846
1850
  if (it == this->mapDataConsumers.end())
1847
1851
  {
1848
- MS_THROW_NOT_FOUND_ERROR("DataConsumer not found [method:%s]", message.c_str());
1852
+ MS_THROW_NOT_FOUND_ERROR("DataConsumer not found [method:%s]", method.c_str());
1849
1853
  }
1850
1854
 
1851
1855
  return it->second;
1852
1856
  }
1853
1857
 
1854
- RTC::DataConsumer* Transport::AssertAndGetSctpDataConsumerByStreamId(uint16_t streamId) const
1858
+ RTC::DataConsumer* Transport::GetSctpDataConsumerByStreamId(uint16_t streamId) const
1855
1859
  {
1856
1860
  MS_TRACE();
1857
1861
 
1858
- auto it = this->mapSctpStreamIdDataConsumers.find(streamId);
1862
+ const auto it = this->mapSctpStreamIdDataConsumers.find(streamId);
1859
1863
 
1860
1864
  if (it == this->mapSctpStreamIdDataConsumers.end())
1861
1865
  {
1862
- MS_THROW_NOT_FOUND_ERROR("SCTP DataConsumer with streamId %" PRIu16 " not found", streamId);
1866
+ return nullptr;
1863
1867
  }
1864
1868
 
1865
1869
  return it->second;
1866
1870
  }
1867
1871
 
1868
- void Transport::CheckNoProducer(const std::string& producerId, const std::string& message) const
1872
+ void Transport::CheckNoProducer(const std::string& producerId, const std::string& method) const
1869
1873
  {
1870
1874
  MS_TRACE();
1871
1875
 
1872
1876
  if (this->mapProducers.contains(producerId))
1873
1877
  {
1874
- MS_THROW_ERROR("a Producer with same producerId already exists [method:%s]", message.c_str());
1878
+ MS_THROW_ERROR("a Producer with same producerId already exists [method:%s]", method.c_str());
1875
1879
  }
1876
1880
  }
1877
1881
 
1878
- void Transport::CheckNoConsumer(const std::string& dataConsumerId, const std::string& message) const
1882
+ void Transport::CheckNoConsumer(const std::string& dataConsumerId, const std::string& method) const
1879
1883
  {
1880
1884
  MS_TRACE();
1881
1885
 
1882
1886
  if (this->mapConsumers.contains(dataConsumerId))
1883
1887
  {
1884
- MS_THROW_ERROR("a Consumer with same consumerId already exists [method:%s]", message.c_str());
1888
+ MS_THROW_ERROR("a Consumer with same consumerId already exists [method:%s]", method.c_str());
1885
1889
  }
1886
1890
  }
1887
1891
 
1888
- void Transport::CheckNoDataProducer(const std::string& dataProducerId, const std::string& message) const
1892
+ void Transport::CheckNoDataProducer(const std::string& dataProducerId, const std::string& method) const
1889
1893
  {
1890
1894
  MS_TRACE();
1891
1895
 
1892
1896
  if (this->mapDataProducers.contains(dataProducerId))
1893
1897
  {
1894
1898
  MS_THROW_ERROR(
1895
- "a DataProducer with same dataProducerId already exists [method:%s]", message.c_str());
1899
+ "a DataProducer with same dataProducerId already exists [method:%s]", method.c_str());
1896
1900
  }
1897
1901
  }
1898
1902
 
1899
- void Transport::CheckNoDataConsumer(const std::string& dataConsumerId, const std::string& message) const
1903
+ void Transport::CheckNoDataConsumer(const std::string& dataConsumerId, const std::string& method) const
1900
1904
  {
1901
1905
  MS_TRACE();
1902
1906
 
1903
1907
  if (this->mapDataConsumers.contains(dataConsumerId))
1904
1908
  {
1905
1909
  MS_THROW_ERROR(
1906
- "a DataConsumer with same dataConsumerId already exists [method:%s]", message.c_str());
1910
+ "a DataConsumer with same dataConsumerId already exists [method:%s]", method.c_str());
1907
1911
  }
1908
1912
  }
1909
1913
 
1910
- void Transport::CheckNoSctpDataConsumer(uint16_t streamId, const std::string& message) const
1914
+ void Transport::CheckNoSctpDataConsumer(uint16_t streamId, const std::string& method) const
1911
1915
  {
1912
1916
  MS_TRACE();
1913
1917
 
@@ -1916,7 +1920,7 @@ namespace RTC
1916
1920
  MS_THROW_ERROR(
1917
1921
  "an SCTP DataConsumer with same streamId %" PRIu16 " already exists [method:%s]",
1918
1922
  streamId,
1919
- message.c_str());
1923
+ method.c_str());
1920
1924
  }
1921
1925
  }
1922
1926
 
@@ -2938,6 +2942,10 @@ namespace RTC
2938
2942
  this->mapSctpStreamIdDataConsumers.erase(dataConsumer->GetSctpStreamParameters().streamId);
2939
2943
  }
2940
2944
 
2945
+ // NOTE: This must be called after removing the data consumer from the maps,
2946
+ // otherwise if `OnAssociationStreamBufferedAmountLow()` was triggered it
2947
+ // would end up emitting an event associated to an already closed data
2948
+ // consumer.
2941
2949
  if (this->sctpAssociation)
2942
2950
  {
2943
2951
  this->sctpAssociation->ResetStreams(
@@ -3247,8 +3255,6 @@ namespace RTC
3247
3255
 
3248
3256
  if (!dataConsumersToClose.empty())
3249
3257
  {
3250
- this->sctpAssociation->ResetStreams(streamsToReset);
3251
-
3252
3258
  for (auto* dataConsumer : dataConsumersToClose)
3253
3259
  {
3254
3260
  // Remove it from the maps.
@@ -3271,6 +3277,12 @@ namespace RTC
3271
3277
  // Delete it.
3272
3278
  delete dataConsumer;
3273
3279
  }
3280
+
3281
+ // NOTE: This must be called after removing data consumers from the maps,
3282
+ // otherwise if `OnAssociationStreamBufferedAmountLow()` was triggered it
3283
+ // would end up emitting an event associated to an already closed data
3284
+ // consumer.
3285
+ this->sctpAssociation->ResetStreams(streamsToReset);
3274
3286
  }
3275
3287
  }
3276
3288
  }
@@ -3279,7 +3291,7 @@ namespace RTC
3279
3291
  {
3280
3292
  MS_TRACE();
3281
3293
 
3282
- const auto* dataConsumer = AssertAndGetSctpDataConsumerByStreamId(streamId);
3294
+ const auto* dataConsumer = GetSctpDataConsumerByStreamId(streamId);
3283
3295
 
3284
3296
  if (!dataConsumer)
3285
3297
  {
@@ -184,52 +184,52 @@ flatbuffers::Offset<FBS::Worker::ResourceUsageResponse> Worker::FillBufferResour
184
184
  }
185
185
 
186
186
  RTC::WebRtcServer* Worker::AssertAndGetWebRtcServerById(
187
- const std::string& webRtcServerId, const std::string& message) const
187
+ const std::string& webRtcServerId, const std::string& method) const
188
188
  {
189
189
  MS_TRACE();
190
190
 
191
- auto it = this->mapWebRtcServers.find(webRtcServerId);
191
+ const auto it = this->mapWebRtcServers.find(webRtcServerId);
192
192
 
193
193
  if (it == this->mapWebRtcServers.end())
194
194
  {
195
- MS_THROW_NOT_FOUND_ERROR("WebRtcServer not found [method:%s]", message.c_str());
195
+ MS_THROW_NOT_FOUND_ERROR("WebRtcServer not found [method:%s]", method.c_str());
196
196
  }
197
197
 
198
198
  return it->second;
199
199
  }
200
200
 
201
- RTC::Router* Worker::AssertAndGetRouterById(const std::string& routerId, const std::string& message) const
201
+ RTC::Router* Worker::AssertAndGetRouterById(const std::string& routerId, const std::string& method) const
202
202
  {
203
203
  MS_TRACE();
204
204
 
205
- auto it = this->mapRouters.find(routerId);
205
+ const auto it = this->mapRouters.find(routerId);
206
206
 
207
207
  if (it == this->mapRouters.end())
208
208
  {
209
- MS_THROW_NOT_FOUND_ERROR("Router not found [method:%s]", message.c_str());
209
+ MS_THROW_NOT_FOUND_ERROR("Router not found [method:%s]", method.c_str());
210
210
  }
211
211
 
212
212
  return it->second;
213
213
  }
214
214
 
215
- void Worker::CheckNoWebRtcServer(const std::string& webRtcServerId, const std::string& message) const
215
+ void Worker::CheckNoWebRtcServer(const std::string& webRtcServerId, const std::string& method) const
216
216
  {
217
217
  MS_TRACE();
218
218
 
219
219
  if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end())
220
220
  {
221
221
  MS_THROW_ERROR(
222
- "a WebRtcServer with same webRtcServerId already exists [method:%s]", message.c_str());
222
+ "a WebRtcServer with same webRtcServerId already exists [method:%s]", method.c_str());
223
223
  }
224
224
  }
225
225
 
226
- void Worker::CheckNoRouter(const std::string& routerId, const std::string& message) const
226
+ void Worker::CheckNoRouter(const std::string& routerId, const std::string& method) const
227
227
  {
228
228
  MS_TRACE();
229
229
 
230
230
  if (this->mapRouters.find(routerId) != this->mapRouters.end())
231
231
  {
232
- MS_THROW_ERROR("a Router with same routerId already exists [method:%s]", message.c_str());
232
+ MS_THROW_ERROR("a Router with same routerId already exists [method:%s]", method.c_str());
233
233
  }
234
234
  }
235
235
 
@@ -57,7 +57,7 @@ namespace iceCommon
57
57
  { \
58
58
  uint8_t* originalBuffer = static_cast<uint8_t*>(std::malloc(bufferLength)); \
59
59
  std::memcpy(originalBuffer, buffer, bufferLength); \
60
- REQUIRE(RTC::ICE::StunPacket::IsStun(buffer, bufferLength) == true); \
60
+ REQUIRE(RTC::ICE::StunPacket::IsStun(buffer, length) == true); \
61
61
  REQUIRE(packet); \
62
62
  REQUIRE(packet->GetBuffer() != nullptr); \
63
63
  REQUIRE(packet->GetBuffer() == buffer); \
@@ -0,0 +1,58 @@
1
+ #ifndef MS_TEST_RTC_RTCP_COMMON_HPP
2
+ #define MS_TEST_RTC_RTCP_COMMON_HPP
3
+
4
+ #include "common.hpp"
5
+ #include "MediaSoupErrors.hpp"
6
+ #include "RTC/NEW_RTCP/packet/Packet.hpp"
7
+ #include "Utils.hpp"
8
+ #include "test/include/testHelpers.hpp"
9
+ #include <catch2/catch_test_macros.hpp>
10
+ #include <cstdlib> // std::malloc(), std::free()
11
+ #include <cstring> // std::memcpy()
12
+
13
+ namespace rtcpCommon
14
+ {
15
+ // NOTE: We need to declare them here with `extern` and then define them in
16
+ // rtcpCommon.cpp.
17
+ // NOTE: Random size buffers because anyway we use sizeof(XxxxBuffer).
18
+ extern thread_local uint8_t FactoryBuffer[66661];
19
+ extern thread_local uint8_t SerializeBuffer[66662];
20
+ extern thread_local uint8_t CloneBuffer[66663];
21
+ extern thread_local uint8_t DataBuffer[66664];
22
+ extern thread_local uint8_t ThrowBuffer[66665];
23
+
24
+ void ResetBuffers();
25
+ } // namespace rtcpCommon
26
+
27
+ // NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
28
+ #define CHECK_RTCP_PACKET( \
29
+ /*const RTC::RTCP::Packet**/ packet, \
30
+ /*const uint8_t**/ buffer, \
31
+ /*size_t*/ bufferLength, \
32
+ /*size_t*/ length, \
33
+ /*RTC::RTCP::Packet::PacketType*/ packetType, \
34
+ /*bool*/ unknownType) \
35
+ do \
36
+ { \
37
+ uint8_t* originalBuffer = static_cast<uint8_t*>(std::malloc(bufferLength)); \
38
+ std::memcpy(originalBuffer, buffer, bufferLength); \
39
+ REQUIRE(RTC::NEW_RTCP::Packet::IsRtcp(buffer, length) == true); \
40
+ REQUIRE(packet); \
41
+ REQUIRE(packet->GetBuffer() != nullptr); \
42
+ REQUIRE(packet->GetBuffer() == buffer); \
43
+ REQUIRE(packet->GetBufferLength() != 0); \
44
+ REQUIRE(packet->GetBufferLength() == bufferLength); \
45
+ REQUIRE(packet->GetLength() != 0); \
46
+ REQUIRE(packet->GetLength() == length); \
47
+ REQUIRE(packet->GetAvailableLength() == packet->GetBufferLength() - packet->GetLength()); \
48
+ REQUIRE(Utils::Byte::IsPaddedTo4Bytes(packet->GetLength()) == true); \
49
+ REQUIRE(static_cast<unsigned>(packet->GetVersion()) == 2); \
50
+ REQUIRE(packet->GetType() == packetType); \
51
+ REQUIRE(packet->HasUnknownType() == unknownType); \
52
+ REQUIRE(packet->HasPadding() == false); \
53
+ REQUIRE_THROWS_AS(packet->Serialize(rtcpCommon::ThrowBuffer, length - 1), MediaSoupError); \
54
+ REQUIRE_THROWS_AS(packet->Clone(rtcpCommon::ThrowBuffer, length - 1), MediaSoupError); \
55
+ std::free(originalBuffer); \
56
+ } while (false)
57
+
58
+ #endif
@@ -47,7 +47,7 @@ namespace rtpCommon
47
47
  { \
48
48
  uint8_t* originalBuffer = static_cast<uint8_t*>(std::malloc(bufferLength)); \
49
49
  std::memcpy(originalBuffer, buffer, bufferLength); \
50
- REQUIRE(RTC::RTP::Packet::IsRtp(buffer, bufferLength) == true); \
50
+ REQUIRE(RTC::RTP::Packet::IsRtp(buffer, length) == true); \
51
51
  REQUIRE(packet); \
52
52
  REQUIRE(packet->GetBuffer() != nullptr); \
53
53
  REQUIRE(packet->GetBuffer() == buffer); \
@@ -0,0 +1,302 @@
1
+ #include "common.hpp"
2
+ #include "MediaSoupErrors.hpp"
3
+ #include "RTC/NEW_RTCP/packet/ByePacket.hpp"
4
+ #include "test/include/RTC/RTCP/rtcpCommon.hpp"
5
+ #include <catch2/catch_test_macros.hpp>
6
+ #include <cstring> // std::memset()
7
+ #include <vector>
8
+
9
+ SCENARIO("RTCP Bye Packet (203)", "[serializable][rtcp]")
10
+ {
11
+ rtcpCommon::ResetBuffers();
12
+
13
+ SECTION("ByePacket::Parse() succeeds")
14
+ {
15
+ // clang-format off
16
+ alignas(4) uint8_t buffer[] =
17
+ {
18
+ // V=2, P=0, SC=3, PT:203, Length: 5
19
+ 0b10000011, 0xCB, 0x00, 0x05,
20
+ // SSRC 1: 1111111
21
+ 0x00, 0x10, 0xF4, 0x47,
22
+ // SSRC 2: 2222222
23
+ 0x00, 0x21, 0xE8, 0x8E,
24
+ // SSRC 3: 12345678
25
+ 0x00, 0xBC, 0x61, 0x4E,
26
+ // Reason length: 6, Reason: "foo"
27
+ 0x06, 0x66, 0x6F, 0x6F,
28
+ // Reason: "bar", 1 byte of padding
29
+ 0x62, 0x61, 0x72, 0x00
30
+ };
31
+ // clang-format on
32
+
33
+ std::unique_ptr<RTC::NEW_RTCP::ByePacket> packet{ RTC::NEW_RTCP::ByePacket::Parse(
34
+ buffer, sizeof(buffer)) };
35
+
36
+ CHECK_RTCP_PACKET(
37
+ /*packet*/ packet.get(),
38
+ /*buffer*/ buffer,
39
+ /*bufferLength*/ sizeof(buffer),
40
+ /*length*/ 24,
41
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
42
+ /*unknownType*/ false);
43
+
44
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111111, 2222222, 12345678 });
45
+ REQUIRE(packet->HasReason() == true);
46
+ REQUIRE(packet->GetReason() == "foobar");
47
+ // Check padding bytes.
48
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
49
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 'r');
50
+
51
+ // No space to add more ssrcs.
52
+ REQUIRE_THROWS_AS(packet->AddSsrc(3333), MediaSoupTypeError);
53
+ // No space for a reason larger than the current one.
54
+ REQUIRE_THROWS_AS(packet->SetReason("lolololo"), MediaSoupTypeError);
55
+
56
+ /* Serialize it. */
57
+
58
+ packet->Serialize(rtcpCommon::SerializeBuffer, sizeof(rtcpCommon::SerializeBuffer));
59
+
60
+ std::memset(buffer, 0xFF, sizeof(buffer));
61
+
62
+ CHECK_RTCP_PACKET(
63
+ /*packet*/ packet.get(),
64
+ /*buffer*/ rtcpCommon::SerializeBuffer,
65
+ /*bufferLength*/ sizeof(rtcpCommon::SerializeBuffer),
66
+ /*length*/ 24,
67
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
68
+ /*unknownType*/ false);
69
+
70
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111111, 2222222, 12345678 });
71
+ REQUIRE(packet->HasReason() == true);
72
+ REQUIRE(packet->GetReason() == "foobar");
73
+ // Check padding bytes.
74
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
75
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 'r');
76
+
77
+ /* Clone it. */
78
+
79
+ packet.reset(packet->Clone(rtcpCommon::CloneBuffer, sizeof(rtcpCommon::CloneBuffer)));
80
+
81
+ std::memset(rtcpCommon::SerializeBuffer, 0xFF, sizeof(rtcpCommon::SerializeBuffer));
82
+
83
+ CHECK_RTCP_PACKET(
84
+ /*packet*/ packet.get(),
85
+ /*buffer*/ rtcpCommon::CloneBuffer,
86
+ /*bufferLength*/ sizeof(rtcpCommon::CloneBuffer),
87
+ /*length*/ 24,
88
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
89
+ /*unknownType*/ false);
90
+
91
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111111, 2222222, 12345678 });
92
+ REQUIRE(packet->HasReason() == true);
93
+ REQUIRE(packet->GetReason() == "foobar");
94
+ // Check padding bytes.
95
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
96
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 'r');
97
+
98
+ /* Modify it. */
99
+
100
+ packet->AddSsrc(3333);
101
+
102
+ CHECK_RTCP_PACKET(
103
+ /*packet*/ packet.get(),
104
+ /*buffer*/ rtcpCommon::CloneBuffer,
105
+ /*bufferLength*/ sizeof(rtcpCommon::CloneBuffer),
106
+ /*length*/ 28,
107
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
108
+ /*unknownType*/ false);
109
+
110
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111111, 2222222, 12345678, 3333 });
111
+ REQUIRE(packet->HasReason() == true);
112
+ REQUIRE(packet->GetReason() == "foobar");
113
+ // Check padding bytes.
114
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
115
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 'r');
116
+
117
+ packet->SetReason("");
118
+
119
+ CHECK_RTCP_PACKET(
120
+ /*packet*/ packet.get(),
121
+ /*buffer*/ rtcpCommon::CloneBuffer,
122
+ /*bufferLength*/ sizeof(rtcpCommon::CloneBuffer),
123
+ /*length*/ 20,
124
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
125
+ /*unknownType*/ false);
126
+
127
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111111, 2222222, 12345678, 3333 });
128
+ REQUIRE(packet->HasReason() == false);
129
+ REQUIRE(packet->GetReason().empty());
130
+
131
+ packet->SetReason("abcde");
132
+
133
+ CHECK_RTCP_PACKET(
134
+ /*packet*/ packet.get(),
135
+ /*buffer*/ rtcpCommon::CloneBuffer,
136
+ /*bufferLength*/ sizeof(rtcpCommon::CloneBuffer),
137
+ /*length*/ 28,
138
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
139
+ /*unknownType*/ false);
140
+
141
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111111, 2222222, 12345678, 3333 });
142
+ REQUIRE(packet->HasReason() == true);
143
+ REQUIRE(packet->GetReason() == "abcde");
144
+ // Check padding bytes.
145
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
146
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 0);
147
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 3] == 'e');
148
+ }
149
+
150
+ SECTION("ByePacket::Parse() fails")
151
+ {
152
+ // Length field should be 5 (24 bytes).
153
+ // clang-format off
154
+ alignas(4) uint8_t buffer1[] =
155
+ {
156
+ // V=2, P=0, SC=3, PT:203, Length: 6
157
+ 0b10000011, 0xCB, 0x00, 0x06,
158
+ // SSRC 1: 1111111
159
+ 0x00, 0x10, 0xF4, 0x47,
160
+ // SSRC 2: 2222222
161
+ 0x00, 0x21, 0xE8, 0x8E,
162
+ // SSRC 3: 12345678
163
+ 0x00, 0xBC, 0x61, 0x4E,
164
+ // Reason length: 6, Reason: "foo"
165
+ 0x06, 0x66, 0x6F, 0x6F,
166
+ // Reason: "bar", 1 byte of padding
167
+ 0x62, 0x61, 0x72, 0x00
168
+ };
169
+ // clang-format on
170
+
171
+ REQUIRE(!RTC::NEW_RTCP::ByePacket::Parse(buffer1, sizeof(buffer1)));
172
+
173
+ // SC should be 3 instead of 4 (first byte should be 0b10000011). So the parser ends
174
+ // reading a wrong value of the Reason length field and fails.
175
+ // clang-format off
176
+ alignas(4) uint8_t buffer2[] =
177
+ {
178
+ // V=2, P=0, SC=3, PT:203, Length: 5
179
+ 0b10000100, 0xCB, 0x00, 0x05,
180
+ // SSRC 1: 1111111
181
+ 0x00, 0x10, 0xF4, 0x47,
182
+ // SSRC 2: 2222222
183
+ 0x00, 0x21, 0xE8, 0x8E,
184
+ // SSRC 3: 12345678
185
+ 0x00, 0xBC, 0x61, 0x4E,
186
+ // Reason length: 6, Reason: "foo"
187
+ 0x06, 0x66, 0x6F, 0x6F,
188
+ // Reason: "bar", 1 byte of padding
189
+ 0x62, 0x61, 0x72, 0x00
190
+ };
191
+ // clang-format on
192
+
193
+ REQUIRE(!RTC::NEW_RTCP::ByePacket::Parse(buffer2, sizeof(buffer2)));
194
+
195
+ // Parse() called with less buffer length than needed.
196
+ // clang-format off
197
+ alignas(4) uint8_t buffer3[] =
198
+ {
199
+ // V=2, P=0, SC=3, PT:203, Length: 5
200
+ 0b10000011, 0xCB, 0x00, 0x05,
201
+ // SSRC 1: 1111111
202
+ 0x00, 0x10, 0xF4, 0x47,
203
+ // SSRC 2: 2222222
204
+ 0x00, 0x21, 0xE8, 0x8E,
205
+ // SSRC 3: 12345678
206
+ 0x00, 0xBC, 0x61, 0x4E,
207
+ // Reason length: 6, Reason: "foo"
208
+ 0x06, 0x66, 0x6F, 0x6F,
209
+ // Reason: "bar", 1 byte of padding
210
+ 0x62, 0x61, 0x72, 0x00
211
+ };
212
+ // clang-format on
213
+
214
+ REQUIRE(!RTC::NEW_RTCP::ByePacket::Parse(buffer3, sizeof(buffer3) - 1));
215
+ }
216
+
217
+ SECTION("ByePacket::Factory() succeeds")
218
+ {
219
+ std::unique_ptr<RTC::NEW_RTCP::ByePacket> packet{ RTC::NEW_RTCP::ByePacket::Factory(
220
+ rtcpCommon::FactoryBuffer, sizeof(rtcpCommon::FactoryBuffer)) };
221
+
222
+ CHECK_RTCP_PACKET(
223
+ /*packet*/ packet.get(),
224
+ /*buffer*/ rtcpCommon::FactoryBuffer,
225
+ /*bufferLength*/ sizeof(rtcpCommon::FactoryBuffer),
226
+ /*length*/ 4,
227
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
228
+ /*unknownType*/ false);
229
+
230
+ REQUIRE(packet->GetSsrcs().empty());
231
+ REQUIRE(packet->HasReason() == false);
232
+ REQUIRE(packet->GetReason().empty());
233
+
234
+ /* Modify it. */
235
+
236
+ packet->AddSsrc(1111);
237
+ packet->AddSsrc(2222);
238
+ // Reason string is 25 bytes, so padded(1 + 25) is needed = 28 bytes.
239
+ packet->SetReason("amazing reason, isn't it?");
240
+ packet->AddSsrc(3333);
241
+
242
+ CHECK_RTCP_PACKET(
243
+ /*packet*/ packet.get(),
244
+ /*buffer*/ rtcpCommon::FactoryBuffer,
245
+ /*bufferLength*/ sizeof(rtcpCommon::FactoryBuffer),
246
+ /*length*/ 4 + 4 + 4 + 4 + 28,
247
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
248
+ /*unknownType*/ false);
249
+
250
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111, 2222, 3333 });
251
+ REQUIRE(packet->HasReason() == true);
252
+ REQUIRE(packet->GetReason() == "amazing reason, isn't it?");
253
+ // Check padding bytes.
254
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
255
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 0);
256
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 3] == '?');
257
+
258
+ /* Serialize it. */
259
+
260
+ packet->Serialize(rtcpCommon::SerializeBuffer, sizeof(rtcpCommon::SerializeBuffer));
261
+
262
+ std::memset(rtcpCommon::FactoryBuffer, 0xFF, sizeof(rtcpCommon::FactoryBuffer));
263
+
264
+ CHECK_RTCP_PACKET(
265
+ /*packet*/ packet.get(),
266
+ /*buffer*/ rtcpCommon::SerializeBuffer,
267
+ /*bufferLength*/ sizeof(rtcpCommon::SerializeBuffer),
268
+ /*length*/ 4 + 4 + 4 + 4 + 28,
269
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
270
+ /*unknownType*/ false);
271
+
272
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111, 2222, 3333 });
273
+ REQUIRE(packet->HasReason() == true);
274
+ REQUIRE(packet->GetReason() == "amazing reason, isn't it?");
275
+ // Check padding bytes.
276
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
277
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 0);
278
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 3] == '?');
279
+
280
+ /* Clone it. */
281
+
282
+ packet.reset(packet->Clone(rtcpCommon::CloneBuffer, sizeof(rtcpCommon::CloneBuffer)));
283
+
284
+ std::memset(rtcpCommon::SerializeBuffer, 0xFF, sizeof(rtcpCommon::SerializeBuffer));
285
+
286
+ CHECK_RTCP_PACKET(
287
+ /*packet*/ packet.get(),
288
+ /*buffer*/ rtcpCommon::CloneBuffer,
289
+ /*bufferLength*/ sizeof(rtcpCommon::CloneBuffer),
290
+ /*length*/ 4 + 4 + 4 + 4 + 28,
291
+ /*packetType*/ RTC::NEW_RTCP::Packet::PacketType::BYE,
292
+ /*unknownType*/ false);
293
+
294
+ REQUIRE(packet->GetSsrcs() == std::vector<uint32_t>{ 1111, 2222, 3333 });
295
+ REQUIRE(packet->HasReason() == true);
296
+ REQUIRE(packet->GetReason() == "amazing reason, isn't it?");
297
+ // Check padding bytes.
298
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 1] == 0);
299
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 2] == 0);
300
+ REQUIRE(packet->GetBuffer()[packet->GetLength() - 3] == '?');
301
+ }
302
+ }