mediasoup 3.20.4 → 3.20.6
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/package.json +4 -4
- package/worker/include/RTC/Consumer.hpp +80 -45
- package/worker/include/RTC/PipeProducerStreamManager.hpp +78 -0
- package/worker/include/RTC/ProducerStreamManager.hpp +181 -0
- package/worker/include/RTC/SCTP/association/Association.hpp +24 -0
- package/worker/include/RTC/SCTP/association/StateCookie.hpp +104 -11
- package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +4 -1
- package/worker/include/RTC/SCTP/public/SctpOptions.hpp +13 -0
- package/worker/include/RTC/SeqManager.hpp +2 -2
- package/worker/include/RTC/SimpleProducerStreamManager.hpp +72 -0
- package/worker/include/RTC/SimulcastProducerStreamManager.hpp +93 -0
- package/worker/include/RTC/SvcProducerStreamManager.hpp +72 -0
- package/worker/include/RTC/Transport.hpp +7 -1
- package/worker/meson.build +9 -5
- package/worker/src/RTC/Consumer.cpp +1404 -30
- package/worker/src/RTC/DirectTransport.cpp +4 -1
- package/worker/src/RTC/PipeProducerStreamManager.cpp +266 -0
- package/worker/src/RTC/PipeTransport.cpp +4 -1
- package/worker/src/RTC/PlainTransport.cpp +4 -1
- package/worker/src/RTC/SCTP/association/Association.cpp +142 -3
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +96 -31
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +4 -0
- package/worker/src/RTC/SCTP/packet/Packet.cpp +1 -1
- package/worker/src/RTC/SCTP/packet/parameters/StateCookieParameter.cpp +12 -3
- package/worker/src/RTC/SCTP/public/SctpOptions.cpp +4 -0
- package/worker/src/RTC/SCTP/rx/DataTracker.cpp +4 -1
- package/worker/src/RTC/SeqManager.cpp +42 -29
- package/worker/src/RTC/SimpleProducerStreamManager.cpp +343 -0
- package/worker/src/RTC/SimulcastProducerStreamManager.cpp +1068 -0
- package/worker/src/RTC/SvcProducerStreamManager.cpp +664 -0
- package/worker/src/RTC/Transport.cpp +7 -44
- package/worker/src/RTC/WebRtcTransport.cpp +8 -2
- package/worker/test/include/RTC/SCTP/sctpCommon.hpp +1 -1
- package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +115 -0
- package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +123 -0
- package/worker/test/src/RTC/SCTP/packet/TestPacket.cpp +4 -4
- package/worker/test/src/RTC/{TestSimpleConsumer.cpp → TestConsumer.cpp} +6 -7
- package/worker/test/src/RTC/TestPipeProducerStreamManager.cpp +471 -0
- package/worker/test/src/RTC/TestSimpleProducerStreamManager.cpp +531 -0
- package/worker/test/src/RTC/TestSimulcastProducerStreamManager.cpp +1040 -0
- package/worker/test/src/RTC/TestSvcProducerStreamManager.cpp +1278 -0
- package/worker/include/RTC/PipeConsumer.hpp +0 -95
- package/worker/include/RTC/SimpleConsumer.hpp +0 -102
- package/worker/include/RTC/SimulcastConsumer.hpp +0 -141
- package/worker/include/RTC/SvcConsumer.hpp +0 -118
- package/worker/src/RTC/PipeConsumer.cpp +0 -874
- package/worker/src/RTC/SimpleConsumer.cpp +0 -882
- package/worker/src/RTC/SimulcastConsumer.cpp +0 -1887
- package/worker/src/RTC/SvcConsumer.cpp +0 -1384
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
#include "FBS/transport.h"
|
|
13
13
|
#include "RTC/BweType.hpp"
|
|
14
14
|
#include "RTC/Consts.hpp"
|
|
15
|
-
#include "RTC/
|
|
15
|
+
#include "RTC/Consumer.hpp"
|
|
16
16
|
#include "RTC/RTCP/FeedbackPs.hpp"
|
|
17
17
|
#include "RTC/RTCP/FeedbackPsAfb.hpp"
|
|
18
18
|
#include "RTC/RTCP/FeedbackPsRemb.hpp"
|
|
@@ -22,9 +22,6 @@
|
|
|
22
22
|
#include "RTC/RtpDictionaries.hpp"
|
|
23
23
|
#include "RTC/SCTP/association/Association.hpp"
|
|
24
24
|
#include "RTC/SCTP/public/SctpOptions.hpp"
|
|
25
|
-
#include "RTC/SimpleConsumer.hpp"
|
|
26
|
-
#include "RTC/SimulcastConsumer.hpp"
|
|
27
|
-
#include "RTC/SvcConsumer.hpp"
|
|
28
25
|
#ifdef MS_RTC_LOGGER_RTP
|
|
29
26
|
#include "RTC/RtcLogger.hpp"
|
|
30
27
|
#endif
|
|
@@ -41,7 +38,8 @@ namespace RTC
|
|
|
41
38
|
SharedInterface* shared,
|
|
42
39
|
const std::string& id,
|
|
43
40
|
RTC::Transport::Listener* listener,
|
|
44
|
-
const FBS::Transport::Options* options
|
|
41
|
+
const FBS::Transport::Options* options,
|
|
42
|
+
bool requireSctpStateCookieAuthentication)
|
|
45
43
|
: id(id),
|
|
46
44
|
shared(shared),
|
|
47
45
|
listener(listener),
|
|
@@ -87,7 +85,8 @@ namespace RTC
|
|
|
87
85
|
.maxSendBufferSize = this->sctpSendBufferSize,
|
|
88
86
|
.perStreamSendQueueLimit = this->sctpPerStreamSendQueueLimit,
|
|
89
87
|
.maxReceiveMessageSize = this->maxReceiveMessageSize,
|
|
90
|
-
.maxReceiverWindowBufferSize = this->sctpMaxReceiverWindowBufferSize
|
|
88
|
+
.maxReceiverWindowBufferSize = this->sctpMaxReceiverWindowBufferSize,
|
|
89
|
+
.requireAuthenticatedCookie = requireSctpStateCookieAuthentication
|
|
91
90
|
};
|
|
92
91
|
|
|
93
92
|
this->sctpAssociation = std::make_unique<RTC::SCTP::Association>(
|
|
@@ -780,44 +779,8 @@ namespace RTC
|
|
|
780
779
|
MS_THROW_ERROR("a Consumer with same consumerId already exists");
|
|
781
780
|
}
|
|
782
781
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
RTC::Consumer* consumer{ nullptr };
|
|
786
|
-
|
|
787
|
-
switch (type)
|
|
788
|
-
{
|
|
789
|
-
case RTC::RtpParameters::Type::SIMPLE:
|
|
790
|
-
{
|
|
791
|
-
// This may throw.
|
|
792
|
-
consumer = new RTC::SimpleConsumer(this->shared, consumerId, producerId, this, body);
|
|
793
|
-
|
|
794
|
-
break;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
case RTC::RtpParameters::Type::SIMULCAST:
|
|
798
|
-
{
|
|
799
|
-
// This may throw.
|
|
800
|
-
consumer = new RTC::SimulcastConsumer(this->shared, consumerId, producerId, this, body);
|
|
801
|
-
|
|
802
|
-
break;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
case RTC::RtpParameters::Type::SVC:
|
|
806
|
-
{
|
|
807
|
-
// This may throw.
|
|
808
|
-
consumer = new RTC::SvcConsumer(this->shared, consumerId, producerId, this, body);
|
|
809
|
-
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
case RTC::RtpParameters::Type::PIPE:
|
|
814
|
-
{
|
|
815
|
-
// This may throw.
|
|
816
|
-
consumer = new RTC::PipeConsumer(this->shared, consumerId, producerId, this, body);
|
|
817
|
-
|
|
818
|
-
break;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
782
|
+
// This may throw.
|
|
783
|
+
auto* consumer = new RTC::Consumer(this->shared, consumerId, producerId, this, body);
|
|
821
784
|
|
|
822
785
|
// Notify the listener.
|
|
823
786
|
// This may throw if no Producer is found.
|
|
@@ -38,7 +38,10 @@ namespace RTC
|
|
|
38
38
|
const std::string& id,
|
|
39
39
|
RTC::Transport::Listener* listener,
|
|
40
40
|
const FBS::WebRtcTransport::WebRtcTransportOptions* options)
|
|
41
|
-
|
|
41
|
+
// SCTP over WebRtcTransport runs within a DTLS session, so State Cookie
|
|
42
|
+
// authentication is not needed.
|
|
43
|
+
: RTC::Transport::Transport(
|
|
44
|
+
shared, id, listener, options->base(), /*requireSctpStateCookieAuthentication*/ false)
|
|
42
45
|
{
|
|
43
46
|
MS_TRACE();
|
|
44
47
|
|
|
@@ -284,7 +287,10 @@ namespace RTC
|
|
|
284
287
|
WebRtcTransportListener* webRtcTransportListener,
|
|
285
288
|
const std::vector<RTC::ICE::IceCandidate>& iceCandidates,
|
|
286
289
|
const FBS::WebRtcTransport::WebRtcTransportOptions* options)
|
|
287
|
-
|
|
290
|
+
// SCTP over WebRtcTransport runs within a DTLS session, so State Cookie
|
|
291
|
+
// authentication is not needed.
|
|
292
|
+
: RTC::Transport::Transport(
|
|
293
|
+
shared, id, listener, options->base(), /*requireSctpStateCookieAuthentication*/ false),
|
|
288
294
|
webRtcTransportListener(webRtcTransportListener),
|
|
289
295
|
iceCandidates(iceCandidates)
|
|
290
296
|
{
|
|
@@ -54,8 +54,8 @@ namespace sctpCommon
|
|
|
54
54
|
REQUIRE(packet->GetSourcePort() == sourcePort); \
|
|
55
55
|
REQUIRE(packet->GetDestinationPort() == destinationPort); \
|
|
56
56
|
REQUIRE(packet->GetVerificationTag() == verificationTag); \
|
|
57
|
-
REQUIRE(packet->GetChecksum() == checksum); \
|
|
58
57
|
REQUIRE(packet->ValidateCRC32cChecksum() == hasValidCrc32cChecksum); \
|
|
58
|
+
REQUIRE(packet->GetChecksum() == checksum); \
|
|
59
59
|
REQUIRE(packet->GetChunksCount() == chunksCount); \
|
|
60
60
|
REQUIRE(packet->HasChunks() == (chunksCount > 0)); \
|
|
61
61
|
REQUIRE(packet->GetChunkAt(chunksCount) == nullptr); \
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#include "common.hpp"
|
|
2
2
|
#include "RTC/SCTP/association/Association.hpp"
|
|
3
|
+
#include "RTC/SCTP/association/NegotiatedCapabilities.hpp"
|
|
4
|
+
#include "RTC/SCTP/association/StateCookie.hpp"
|
|
3
5
|
#include "RTC/SCTP/packet/ErrorCause.hpp"
|
|
4
6
|
#include "RTC/SCTP/packet/Packet.hpp"
|
|
5
7
|
#include "RTC/SCTP/packet/chunks/AbortAssociationChunk.hpp"
|
|
@@ -1752,4 +1754,117 @@ SCENARIO("SCTP Association", "[sctp][association]")
|
|
|
1752
1754
|
|
|
1753
1755
|
REQUIRE(getReceivedMessagePpids(z).empty() == true);
|
|
1754
1756
|
}
|
|
1757
|
+
|
|
1758
|
+
SECTION("establishes connection with State Cookie authentication enabled")
|
|
1759
|
+
{
|
|
1760
|
+
auto sctpOptions = makeSctpOptions();
|
|
1761
|
+
|
|
1762
|
+
sctpOptions.requireAuthenticatedCookie = true;
|
|
1763
|
+
|
|
1764
|
+
AssociationUnderTest a(sctpOptions);
|
|
1765
|
+
AssociationUnderTest z(sctpOptions);
|
|
1766
|
+
|
|
1767
|
+
// The full handshake must succeed: Z generates an authenticated cookie that
|
|
1768
|
+
// A echoes back and Z verifies against its own secret.
|
|
1769
|
+
connectAssociations(a, z);
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
SECTION("forged COOKIE-ECHO is accepted without authentication but rejected with it")
|
|
1773
|
+
{
|
|
1774
|
+
// Forge a plain (unauthenticated) State Cookie with attacker-chosen values,
|
|
1775
|
+
// as in the published PoC. It passes the magic checks but carries no MAC.
|
|
1776
|
+
const uint32_t forgedTag = 0xDEADBEEF;
|
|
1777
|
+
const RTC::SCTP::NegotiatedCapabilities negotiatedCapabilities;
|
|
1778
|
+
|
|
1779
|
+
std::vector<uint8_t> cookieBuffer(RTC::SCTP::StateCookie::StateCookieLength);
|
|
1780
|
+
|
|
1781
|
+
RTC::SCTP::StateCookie::Write(
|
|
1782
|
+
cookieBuffer.data(),
|
|
1783
|
+
cookieBuffer.size(),
|
|
1784
|
+
/*localVerificationTag*/ forgedTag,
|
|
1785
|
+
/*remoteVerificationTag*/ 0xCAFEBABE,
|
|
1786
|
+
/*localInitialTsn*/ 1000,
|
|
1787
|
+
/*remoteInitialTsn*/ 2000,
|
|
1788
|
+
/*remoteAdvertisedReceiverWindowCredit*/ 65535,
|
|
1789
|
+
/*tieTag*/ 0,
|
|
1790
|
+
negotiatedCapabilities);
|
|
1791
|
+
|
|
1792
|
+
// Builds a COOKIE-ECHO packet carrying the forged cookie. `buffers` must
|
|
1793
|
+
// outlive the returned packet.
|
|
1794
|
+
const auto buildForgedCookieEcho =
|
|
1795
|
+
[&](std::vector<uint8_t>& packetBuffer) -> std::unique_ptr<RTC::SCTP::Packet>
|
|
1796
|
+
{
|
|
1797
|
+
auto packet = buildPacket(packetBuffer, forgedTag);
|
|
1798
|
+
auto* cookieEchoChunk = packet->BuildChunkInPlace<RTC::SCTP::CookieEchoChunk>();
|
|
1799
|
+
|
|
1800
|
+
cookieEchoChunk->SetCookie(cookieBuffer.data(), cookieBuffer.size());
|
|
1801
|
+
cookieEchoChunk->Consolidate();
|
|
1802
|
+
|
|
1803
|
+
return packet;
|
|
1804
|
+
};
|
|
1805
|
+
|
|
1806
|
+
// Without authentication, the forged COOKIE-ECHO is accepted and an
|
|
1807
|
+
// association is wrongly established (this is the vulnerability).
|
|
1808
|
+
{
|
|
1809
|
+
AssociationUnderTest z;
|
|
1810
|
+
|
|
1811
|
+
std::vector<uint8_t> packetBuffer(1500);
|
|
1812
|
+
|
|
1813
|
+
const auto packet = buildForgedCookieEcho(packetBuffer);
|
|
1814
|
+
|
|
1815
|
+
injectPacket(z, packet.get());
|
|
1816
|
+
|
|
1817
|
+
REQUIRE(z.association.GetAssociationState() == RTC::SCTP::Types::AssociationState::CONNECTED);
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
// With authentication required, the forged COOKIE-ECHO fails MAC
|
|
1821
|
+
// verification and is silently discarded.
|
|
1822
|
+
{
|
|
1823
|
+
auto sctpOptions = makeSctpOptions();
|
|
1824
|
+
|
|
1825
|
+
sctpOptions.requireAuthenticatedCookie = true;
|
|
1826
|
+
|
|
1827
|
+
AssociationUnderTest z(sctpOptions);
|
|
1828
|
+
|
|
1829
|
+
std::vector<uint8_t> packetBuffer(1500);
|
|
1830
|
+
|
|
1831
|
+
const auto packet = buildForgedCookieEcho(packetBuffer);
|
|
1832
|
+
|
|
1833
|
+
injectPacket(z, packet.get());
|
|
1834
|
+
|
|
1835
|
+
REQUIRE(z.association.GetAssociationState() != RTC::SCTP::Types::AssociationState::CONNECTED);
|
|
1836
|
+
// No COOKIE-ACK (nor any other packet) is sent in response.
|
|
1837
|
+
REQUIRE(z.listener.ConsumeFirstSentPacket().empty() == true);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
SECTION("rejects a stale COOKIE-ECHO when authentication is required")
|
|
1842
|
+
{
|
|
1843
|
+
auto sctpOptions = makeSctpOptions();
|
|
1844
|
+
|
|
1845
|
+
sctpOptions.requireAuthenticatedCookie = true;
|
|
1846
|
+
|
|
1847
|
+
AssociationUnderTest a(sctpOptions);
|
|
1848
|
+
AssociationUnderTest z(sctpOptions);
|
|
1849
|
+
|
|
1850
|
+
a.association.Connect();
|
|
1851
|
+
// Z reads INIT, produces INIT-ACK with an authenticated cookie timestamped
|
|
1852
|
+
// with Z's current time.
|
|
1853
|
+
deliverFirstSentPacket(a, z);
|
|
1854
|
+
// A reads INIT-ACK, produces COOKIE-ECHO (echoing Z's cookie).
|
|
1855
|
+
deliverFirstSentPacket(z, a);
|
|
1856
|
+
|
|
1857
|
+
// Make the cookie stale on Z's side by advancing its clock beyond the cookie
|
|
1858
|
+
// lifespan before the COOKIE-ECHO is delivered.
|
|
1859
|
+
z.AdvanceTimeMs(RTC::SCTP::StateCookie::ValidCookieLifeMs + 1000);
|
|
1860
|
+
|
|
1861
|
+
// Z reads the now stale COOKIE-ECHO.
|
|
1862
|
+
deliverFirstSentPacket(a, z);
|
|
1863
|
+
|
|
1864
|
+
REQUIRE(z.association.GetAssociationState() != RTC::SCTP::Types::AssociationState::CONNECTED);
|
|
1865
|
+
// Z responds with an ERROR chunk (carrying a Stale Cookie error cause).
|
|
1866
|
+
REQUIRE(
|
|
1867
|
+
packetHasSingleChunkOfType<RTC::SCTP::OperationErrorChunk>(
|
|
1868
|
+
z.listener.ConsumeFirstSentPacket()) == true);
|
|
1869
|
+
}
|
|
1755
1870
|
}
|
|
@@ -507,4 +507,127 @@ SCENARIO("SCTP State Cookie", "[sctp][statecookie]")
|
|
|
507
507
|
RTC::SCTP::StateCookie::DetermineSctpImplementation(buffer4, sizeof(buffer4)) ==
|
|
508
508
|
RTC::SCTP::Types::SctpImplementation::UNKNOWN);
|
|
509
509
|
}
|
|
510
|
+
|
|
511
|
+
SECTION("authenticated StateCookie::Write() and StateCookie::VerifyMac() succeed")
|
|
512
|
+
{
|
|
513
|
+
const RTC::SCTP::NegotiatedCapabilities negotiatedCapabilities = {
|
|
514
|
+
.negotiatedMaxOutboundStreams = 62000,
|
|
515
|
+
.negotiatedMaxInboundStreams = 55555,
|
|
516
|
+
.partialReliability = true,
|
|
517
|
+
.messageInterleaving = true,
|
|
518
|
+
.reConfig = true,
|
|
519
|
+
.zeroChecksum = false
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const uint8_t macKey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
523
|
+
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
|
|
524
|
+
const uint64_t creationTimestampMs = 1234567890;
|
|
525
|
+
|
|
526
|
+
auto* buffer = sctpCommon::FactoryBuffer;
|
|
527
|
+
|
|
528
|
+
RTC::SCTP::StateCookie::Write(
|
|
529
|
+
/*buffer*/ buffer,
|
|
530
|
+
/*bufferLength*/ RTC::SCTP::StateCookie::AuthenticatedStateCookieLength,
|
|
531
|
+
/*localVerificationTag*/ 6660666,
|
|
532
|
+
/*remoteVerificationTag*/ 9990999,
|
|
533
|
+
/*localInitialTsn*/ 1110111,
|
|
534
|
+
/*remoteInitialTsn*/ 2220222,
|
|
535
|
+
/*remoteAdvertisedReceiverWindowCredit*/ 999909999,
|
|
536
|
+
/*tieTag*/ 1111222233334444,
|
|
537
|
+
negotiatedCapabilities,
|
|
538
|
+
/*creationTimestampMs*/ creationTimestampMs,
|
|
539
|
+
/*macKey*/ macKey,
|
|
540
|
+
/*macKeyLength*/ sizeof(macKey));
|
|
541
|
+
|
|
542
|
+
/* It must be recognized as a (longer) mediasoup State Cookie. */
|
|
543
|
+
|
|
544
|
+
REQUIRE(
|
|
545
|
+
RTC::SCTP::StateCookie::IsMediasoupStateCookie(
|
|
546
|
+
buffer, RTC::SCTP::StateCookie::AuthenticatedStateCookieLength) == true);
|
|
547
|
+
|
|
548
|
+
/* Parse it. */
|
|
549
|
+
|
|
550
|
+
auto* stateCookie =
|
|
551
|
+
RTC::SCTP::StateCookie::Parse(buffer, RTC::SCTP::StateCookie::AuthenticatedStateCookieLength);
|
|
552
|
+
|
|
553
|
+
REQUIRE(stateCookie);
|
|
554
|
+
REQUIRE(stateCookie->GetLength() == RTC::SCTP::StateCookie::AuthenticatedStateCookieLength);
|
|
555
|
+
REQUIRE(stateCookie->IsAuthenticated() == true);
|
|
556
|
+
REQUIRE(stateCookie->GetCreationTimestampMs() == creationTimestampMs);
|
|
557
|
+
REQUIRE(stateCookie->GetLocalVerificationTag() == 6660666);
|
|
558
|
+
REQUIRE(stateCookie->GetRemoteVerificationTag() == 9990999);
|
|
559
|
+
|
|
560
|
+
/* The MAC must verify with the right key. */
|
|
561
|
+
|
|
562
|
+
REQUIRE(
|
|
563
|
+
RTC::SCTP::StateCookie::VerifyMac(
|
|
564
|
+
buffer, RTC::SCTP::StateCookie::AuthenticatedStateCookieLength, macKey, sizeof(macKey)) ==
|
|
565
|
+
true);
|
|
566
|
+
|
|
567
|
+
/* The MAC must NOT verify with a wrong key. */
|
|
568
|
+
|
|
569
|
+
const uint8_t wrongMacKey[] = { 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
|
|
570
|
+
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };
|
|
571
|
+
|
|
572
|
+
REQUIRE(
|
|
573
|
+
RTC::SCTP::StateCookie::VerifyMac(
|
|
574
|
+
buffer,
|
|
575
|
+
RTC::SCTP::StateCookie::AuthenticatedStateCookieLength,
|
|
576
|
+
wrongMacKey,
|
|
577
|
+
sizeof(wrongMacKey)) == false);
|
|
578
|
+
|
|
579
|
+
/* Tampering with any byte must invalidate the MAC. */
|
|
580
|
+
|
|
581
|
+
buffer[8] ^= 0x01;
|
|
582
|
+
|
|
583
|
+
REQUIRE(
|
|
584
|
+
RTC::SCTP::StateCookie::VerifyMac(
|
|
585
|
+
buffer, RTC::SCTP::StateCookie::AuthenticatedStateCookieLength, macKey, sizeof(macKey)) ==
|
|
586
|
+
false);
|
|
587
|
+
|
|
588
|
+
buffer[8] ^= 0x01;
|
|
589
|
+
|
|
590
|
+
/* It verifies again once restored. */
|
|
591
|
+
|
|
592
|
+
REQUIRE(
|
|
593
|
+
RTC::SCTP::StateCookie::VerifyMac(
|
|
594
|
+
buffer, RTC::SCTP::StateCookie::AuthenticatedStateCookieLength, macKey, sizeof(macKey)) ==
|
|
595
|
+
true);
|
|
596
|
+
|
|
597
|
+
delete stateCookie;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
SECTION("StateCookie::VerifyMac() fails on a non-authenticated (plain) cookie")
|
|
601
|
+
{
|
|
602
|
+
const RTC::SCTP::NegotiatedCapabilities negotiatedCapabilities = {
|
|
603
|
+
.negotiatedMaxOutboundStreams = 62000,
|
|
604
|
+
.negotiatedMaxInboundStreams = 55555,
|
|
605
|
+
.partialReliability = true,
|
|
606
|
+
.messageInterleaving = true,
|
|
607
|
+
.reConfig = true,
|
|
608
|
+
.zeroChecksum = false
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
const uint8_t macKey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
|
612
|
+
|
|
613
|
+
auto* buffer = sctpCommon::FactoryBuffer;
|
|
614
|
+
|
|
615
|
+
// Write a plain (44 bytes) cookie.
|
|
616
|
+
RTC::SCTP::StateCookie::Write(
|
|
617
|
+
/*buffer*/ buffer,
|
|
618
|
+
/*bufferLength*/ RTC::SCTP::StateCookie::StateCookieLength,
|
|
619
|
+
/*localVerificationTag*/ 6660666,
|
|
620
|
+
/*remoteVerificationTag*/ 9990999,
|
|
621
|
+
/*localInitialTsn*/ 1110111,
|
|
622
|
+
/*remoteInitialTsn*/ 2220222,
|
|
623
|
+
/*remoteAdvertisedReceiverWindowCredit*/ 999909999,
|
|
624
|
+
/*tieTag*/ 1111222233334444,
|
|
625
|
+
negotiatedCapabilities);
|
|
626
|
+
|
|
627
|
+
// A plain cookie has no MAC, so `VerifyMac()` must fail regardless of the
|
|
628
|
+
// key.
|
|
629
|
+
REQUIRE(
|
|
630
|
+
RTC::SCTP::StateCookie::VerifyMac(
|
|
631
|
+
buffer, RTC::SCTP::StateCookie::StateCookieLength, macKey, sizeof(macKey)) == false);
|
|
632
|
+
}
|
|
510
633
|
}
|
|
@@ -25,7 +25,7 @@ SCENARIO("SCTP Packet", "[serializable][sctp][packet]")
|
|
|
25
25
|
REQUIRE(alignof(RTC::SCTP::Packet::CommonHeader) == 4);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
SECTION("Parse() without
|
|
28
|
+
SECTION("Parse() without chunks succeeds")
|
|
29
29
|
{
|
|
30
30
|
// clang-format off
|
|
31
31
|
alignas(4) uint8_t buffer[] =
|
|
@@ -112,7 +112,7 @@ SCENARIO("SCTP Packet", "[serializable][sctp][packet]")
|
|
|
112
112
|
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == nullptr);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
SECTION("Parse() with
|
|
115
|
+
SECTION("Parse() with chunks succeeds")
|
|
116
116
|
{
|
|
117
117
|
// clang-format off
|
|
118
118
|
alignas(4) uint8_t buffer[] =
|
|
@@ -502,7 +502,7 @@ SCENARIO("SCTP Packet", "[serializable][sctp][packet]")
|
|
|
502
502
|
REQUIRE(parameter3_1->GetInfo()[3] == 0x00);
|
|
503
503
|
}
|
|
504
504
|
|
|
505
|
-
SECTION("Factory() with
|
|
505
|
+
SECTION("Factory() with chunks succeeds")
|
|
506
506
|
{
|
|
507
507
|
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
|
|
508
508
|
sctpCommon::FactoryBuffer, sizeof(sctpCommon::FactoryBuffer)) };
|
|
@@ -813,7 +813,7 @@ SCENARIO("SCTP Packet", "[serializable][sctp][packet]")
|
|
|
813
813
|
REQUIRE(obtainedChunk1->GetT() == true);
|
|
814
814
|
}
|
|
815
815
|
|
|
816
|
-
SECTION("BuildChunkInPlace() throws if given
|
|
816
|
+
SECTION("BuildChunkInPlace() throws if given chunk exceeds Packet buffer length")
|
|
817
817
|
{
|
|
818
818
|
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
|
|
819
819
|
sctpCommon::FactoryBuffer, 28) };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#include "FBS/rtpParameters.h"
|
|
2
2
|
#include "FBS/transport.h"
|
|
3
|
+
#include "RTC/Consumer.hpp"
|
|
3
4
|
#include "RTC/RTP/Packet.hpp"
|
|
4
5
|
#include "RTC/RTP/RtpStream.hpp"
|
|
5
6
|
#include "RTC/RTP/RtpStreamRecv.hpp"
|
|
6
7
|
#include "RTC/RTP/SharedPacket.hpp"
|
|
7
8
|
#include "RTC/RtpDictionaries.hpp"
|
|
8
|
-
#include "RTC/SimpleConsumer.hpp"
|
|
9
9
|
#include "flatbuffers/buffer.h"
|
|
10
10
|
#include "mocks/include/MockShared.hpp"
|
|
11
11
|
#include <catch2/catch_test_macros.hpp>
|
|
@@ -112,7 +112,7 @@ namespace
|
|
|
112
112
|
return rtpParameters.FillBuffer(builder);
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
std::unique_ptr<RTC::
|
|
115
|
+
std::unique_ptr<RTC::Consumer> createConsumer(ConsumerListener* listener)
|
|
116
116
|
{
|
|
117
117
|
flatbuffers::FlatBufferBuilder bufferBuilder;
|
|
118
118
|
|
|
@@ -140,8 +140,8 @@ namespace
|
|
|
140
140
|
|
|
141
141
|
const auto* consumeRequest = flatbuffers::GetRoot<FBS::Transport::ConsumeRequest>(buf);
|
|
142
142
|
|
|
143
|
-
return std::make_unique<RTC::
|
|
144
|
-
|
|
143
|
+
return std::make_unique<RTC::Consumer>(
|
|
144
|
+
&shared,
|
|
145
145
|
consumeRequest->consumerId()->str(),
|
|
146
146
|
consumeRequest->producerId()->str(),
|
|
147
147
|
listener,
|
|
@@ -181,12 +181,12 @@ namespace
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
std::unique_ptr<ConsumerListener> listener;
|
|
184
|
-
std::unique_ptr<RTC::
|
|
184
|
+
std::unique_ptr<RTC::Consumer> consumer;
|
|
185
185
|
std::unique_ptr<RTC::RTP::RtpStreamRecv> rtpStream;
|
|
186
186
|
};
|
|
187
187
|
} // namespace
|
|
188
188
|
|
|
189
|
-
SCENARIO("
|
|
189
|
+
SCENARIO("Consumer with SimpleProducerStreamManager", "[rtp][consumer]")
|
|
190
190
|
{
|
|
191
191
|
// TODO: We should NOT parse RTP packets for tests anymore. We should use
|
|
192
192
|
// RTC::RTP::Packet::Factory() instead.
|
|
@@ -230,7 +230,6 @@ SCENARIO("SimpleConsumer", "[rtp][consumer]")
|
|
|
230
230
|
0xFF, 0xFF, 0xFF, 0xFF,
|
|
231
231
|
0xFF, 0xFF, 0xFF, 0xFF,
|
|
232
232
|
0xFF, 0xFF, 0xFF, 0xFF,
|
|
233
|
-
0xFF, 0xFF, 0xFF, 0xFF,
|
|
234
233
|
};
|
|
235
234
|
// clang-format on
|
|
236
235
|
|