mediasoup 3.20.5 → 3.20.7
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/node/lib/Worker.d.ts +1 -1
- package/node/lib/Worker.d.ts.map +1 -1
- package/node/lib/Worker.js +1 -11
- package/node/lib/WorkerTypes.d.ts +0 -9
- package/node/lib/WorkerTypes.d.ts.map +1 -1
- package/node/lib/fbs/plain-transport/connect-response.d.ts.map +1 -1
- package/node/lib/fbs/plain-transport/connect-response.js +0 -1
- package/node/lib/fbs/worker/dump-response.d.ts +1 -5
- package/node/lib/fbs/worker/dump-response.d.ts.map +1 -1
- package/node/lib/fbs/worker/dump-response.js +3 -16
- package/node/lib/index.d.ts +1 -1
- package/node/lib/index.d.ts.map +1 -1
- package/node/lib/index.js +1 -2
- package/node/lib/test/test-PlainTransport.js +30 -0
- package/node/lib/test/test-Worker.js +0 -1
- package/npm-scripts.mjs +13 -8
- package/package.json +8 -8
- package/worker/fbs/meson.build +0 -1
- package/worker/fbs/plainTransport.fbs +1 -1
- package/worker/fbs/worker.fbs +0 -2
- package/worker/include/RTC/Consumer.hpp +80 -45
- package/worker/include/RTC/ICE/StunPacket.hpp +8 -9
- package/worker/include/RTC/PipeProducerStreamManager.hpp +78 -0
- package/worker/include/RTC/ProducerStreamManager.hpp +181 -0
- package/worker/include/RTC/RTP/Packet.hpp +1 -1
- package/worker/include/RTC/RTP/ProbationGenerator.hpp +1 -1
- 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/Chunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/ErrorCause.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/Packet.hpp +1 -2
- package/worker/include/RTC/SCTP/packet/Parameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/TLV.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/DataChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/ForwardTsnChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/IDataChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/IForwardTsnChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/InitAckChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/InitChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/SackChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/ShutdownChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/errorCauses/InvalidStreamIdentifierErrorCause.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/errorCauses/MissingMandatoryParameterErrorCause.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/errorCauses/NoUserDataErrorCause.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/errorCauses/StaleCookieErrorCause.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/AddIncomingStreamsRequestParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/AddOutgoingStreamsRequestParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/CookiePreservativeParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/IPv4AddressParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/IPv6AddressParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/ReconfigurationResponseParameter.hpp +2 -2
- package/worker/include/RTC/SCTP/packet/parameters/SsnTsnResetRequestParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/parameters/StateCookieParameter.hpp +4 -1
- package/worker/include/RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp +1 -1
- package/worker/include/RTC/SCTP/public/SctpOptions.hpp +13 -0
- 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/include/Settings.hpp +0 -1
- package/worker/include/handles/TcpConnectionHandle.hpp +0 -4
- package/worker/include/handles/UdpSocketHandle.hpp +0 -4
- package/worker/meson.build +9 -39
- package/worker/meson_options.txt +0 -1
- 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 +9 -6
- package/worker/src/RTC/PlainTransport.cpp +9 -6
- package/worker/src/RTC/RTP/Packet.cpp +0 -2
- package/worker/src/RTC/RTP/RtpStreamSend.cpp +0 -20
- package/worker/src/RTC/Router.cpp +0 -37
- package/worker/src/RTC/SCTP/association/Association.cpp +150 -8
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +96 -31
- 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/SimpleProducerStreamManager.cpp +343 -0
- package/worker/src/RTC/SimulcastProducerStreamManager.cpp +1068 -0
- package/worker/src/RTC/SrtpSession.cpp +0 -24
- package/worker/src/RTC/SvcProducerStreamManager.cpp +664 -0
- package/worker/src/RTC/Transport.cpp +10 -66
- package/worker/src/RTC/WebRtcTransport.cpp +13 -7
- package/worker/src/Settings.cpp +0 -14
- package/worker/src/Utils/Crypto.cpp +3 -3
- package/worker/src/Utils/String.cpp +1 -1
- package/worker/src/Worker.cpp +5 -38
- package/worker/src/handles/TcpConnectionHandle.cpp +1 -42
- package/worker/src/handles/UdpSocketHandle.cpp +1 -42
- package/worker/src/lib.cpp +1 -10
- 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/fbs/liburing.fbs +0 -7
- package/worker/include/DepLibUring.hpp +0 -143
- 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/DepLibUring.cpp +0 -638
- 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
- package/worker/subprojects/liburing.wrap +0 -14
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "RTC/SCTP/packet/errorCauses/NoUserDataErrorCause.hpp"
|
|
8
8
|
#include "RTC/SCTP/packet/errorCauses/OutOfResourceErrorCause.hpp"
|
|
9
9
|
#include "RTC/SCTP/packet/errorCauses/ProtocolViolationErrorCause.hpp"
|
|
10
|
+
#include "RTC/SCTP/packet/errorCauses/StaleCookieErrorCause.hpp"
|
|
10
11
|
#include "RTC/SCTP/packet/errorCauses/UnrecognizedChunkTypeErrorCause.hpp"
|
|
11
12
|
#include "RTC/SCTP/packet/errorCauses/UserInitiatedAbortErrorCause.hpp"
|
|
12
13
|
#include "RTC/SCTP/packet/parameters/ForwardTsnSupportedParameter.hpp"
|
|
@@ -83,6 +84,15 @@ namespace RTC
|
|
|
83
84
|
mayConnectOnReceivedSctpData(mayConnectOnReceivedSctpData)
|
|
84
85
|
{
|
|
85
86
|
MS_TRACE();
|
|
87
|
+
|
|
88
|
+
// Generate the per-association secret used to authenticate the State
|
|
89
|
+
// Cookies we generate.
|
|
90
|
+
//
|
|
91
|
+
// @see RFC 9260 section 5.1.3.
|
|
92
|
+
if (this->sctpOptions.requireAuthenticatedCookie)
|
|
93
|
+
{
|
|
94
|
+
Utils::Crypto::WriteRandomBytes(this->stateCookieSecret, Association::StateCookieSecretLength);
|
|
95
|
+
}
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
Association::~Association()
|
|
@@ -650,6 +660,8 @@ namespace RTC
|
|
|
650
660
|
|
|
651
661
|
const auto prevState = this->state;
|
|
652
662
|
|
|
663
|
+
// Notice that, contrary to what happens in dcsctp, here the association
|
|
664
|
+
// never transitions back to NEW state.
|
|
653
665
|
SetState(State::CLOSED, message);
|
|
654
666
|
|
|
655
667
|
if (prevState == State::COOKIE_WAIT || prevState == State::COOKIE_ECHOED)
|
|
@@ -1057,6 +1069,32 @@ namespace RTC
|
|
|
1057
1069
|
{
|
|
1058
1070
|
MS_TRACE();
|
|
1059
1071
|
|
|
1072
|
+
// https://datatracker.ietf.org/doc/html/rfc9653#section-5.3
|
|
1073
|
+
//
|
|
1074
|
+
// "If an endpoint has sent the Zero Checksum Acceptable Chunk Parameter
|
|
1075
|
+
// indicating the support of an alternate error detection method in an INIT
|
|
1076
|
+
// or INIT ACK chunk, in addition to SCTP packets containing the correct
|
|
1077
|
+
// CRC32c checksum value it MUST accept SCTP packets that have an incorrect
|
|
1078
|
+
// checksum value of zero [...]"
|
|
1079
|
+
const bool acceptZeroChecksum =
|
|
1080
|
+
this->sctpOptions.zeroChecksumAlternateErrorDetectionMethod !=
|
|
1081
|
+
ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::NONE;
|
|
1082
|
+
|
|
1083
|
+
// Validate the CRC32c checksum unless this is a zero checksum packet that we
|
|
1084
|
+
// announced we are willing to accept.
|
|
1085
|
+
if (!acceptZeroChecksum || receivedPacket->GetChecksum() != 0)
|
|
1086
|
+
{
|
|
1087
|
+
if (!receivedPacket->ValidateCRC32cChecksum())
|
|
1088
|
+
{
|
|
1089
|
+
MS_WARN_TAG(sctp, "invalid CRC32c checksum, packet discarded");
|
|
1090
|
+
|
|
1091
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
1092
|
+
Types::ErrorKind::PARSE_FAILED, "invalid CRC32c checksum");
|
|
1093
|
+
|
|
1094
|
+
return false;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1060
1098
|
const uint32_t localVerificationTag = this->tcb ? this->tcb->GetLocalVerificationTag() : 0;
|
|
1061
1099
|
|
|
1062
1100
|
// https://datatracker.ietf.org/doc/html/rfc9260#section-8.5.1
|
|
@@ -1113,7 +1151,7 @@ namespace RTC
|
|
|
1113
1151
|
{
|
|
1114
1152
|
MS_WARN_TAG(
|
|
1115
1153
|
sctp,
|
|
1116
|
-
"
|
|
1154
|
+
"received ABORT chunk has invalid verification tag %" PRIu32 ", packet discarded",
|
|
1117
1155
|
receivedPacket->GetVerificationTag());
|
|
1118
1156
|
|
|
1119
1157
|
this->associationListenerDeferrer.OnAssociationError(
|
|
@@ -1537,6 +1575,12 @@ namespace RTC
|
|
|
1537
1575
|
const auto negotiatedCapabilities =
|
|
1538
1576
|
NegotiatedCapabilities::Factory(this->sctpOptions, receivedInitChunk);
|
|
1539
1577
|
|
|
1578
|
+
// When authentication is enabled, generate an authenticated cookie with a
|
|
1579
|
+
// creation timestamp and a MAC keyed with our per-association secret.
|
|
1580
|
+
//
|
|
1581
|
+
// @see RFC 9260 section 5.1.3.
|
|
1582
|
+
const bool authenticateCookie = this->sctpOptions.requireAuthenticatedCookie;
|
|
1583
|
+
|
|
1540
1584
|
// Write the StateCookie in place in the parameter.
|
|
1541
1585
|
stateCookieParameter->WriteStateCookieInPlace(
|
|
1542
1586
|
localVerificationTag,
|
|
@@ -1545,7 +1589,10 @@ namespace RTC
|
|
|
1545
1589
|
receivedInitChunk->GetInitialTsn(),
|
|
1546
1590
|
receivedInitChunk->GetAdvertisedReceiverWindowCredit(),
|
|
1547
1591
|
tieTag,
|
|
1548
|
-
negotiatedCapabilities
|
|
1592
|
+
negotiatedCapabilities,
|
|
1593
|
+
/*creationTimestampMs*/ authenticateCookie ? this->shared->GetTimeMs() : 0,
|
|
1594
|
+
/*macKey*/ authenticateCookie ? this->stateCookieSecret : nullptr,
|
|
1595
|
+
/*macKeyLength*/ authenticateCookie ? Association::StateCookieSecretLength : 0);
|
|
1549
1596
|
|
|
1550
1597
|
stateCookieParameter->Consolidate();
|
|
1551
1598
|
|
|
@@ -1678,6 +1725,18 @@ namespace RTC
|
|
|
1678
1725
|
return;
|
|
1679
1726
|
}
|
|
1680
1727
|
|
|
1728
|
+
// When authentication is enabled, verify that the cookie was generated by
|
|
1729
|
+
// us (valid MAC) and is not stale before trusting any of its contents.
|
|
1730
|
+
//
|
|
1731
|
+
// @see RFC 9260 section 5.1.4.
|
|
1732
|
+
if (this->sctpOptions.requireAuthenticatedCookie)
|
|
1733
|
+
{
|
|
1734
|
+
if (!VerifyReceivedStateCookie(cookie.get()))
|
|
1735
|
+
{
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1681
1740
|
if (this->tcb)
|
|
1682
1741
|
{
|
|
1683
1742
|
if (!HandleReceivedCookieEchoChunkWithTcb(receivedPacket, cookie.get()))
|
|
@@ -2073,6 +2132,10 @@ namespace RTC
|
|
|
2073
2132
|
errorCausesStr.append(errorCause->ToString());
|
|
2074
2133
|
}
|
|
2075
2134
|
|
|
2135
|
+
// https://datatracker.ietf.org/doc/html/rfc9260#section-3.3.7
|
|
2136
|
+
//
|
|
2137
|
+
// "If an endpoint receives an ABORT with a format error or no TCB is
|
|
2138
|
+
// found, it MUST silently discard it."
|
|
2076
2139
|
if (!this->tcb)
|
|
2077
2140
|
{
|
|
2078
2141
|
MS_DEBUG_TAG(
|
|
@@ -2083,7 +2146,7 @@ namespace RTC
|
|
|
2083
2146
|
return;
|
|
2084
2147
|
}
|
|
2085
2148
|
|
|
2086
|
-
|
|
2149
|
+
MS_DEBUG_TAG(sctp, "received ABORT chunk, closing association: %s", errorCausesStr.c_str());
|
|
2087
2150
|
|
|
2088
2151
|
InternalClose(Types::ErrorKind::PEER_REPORTED, errorCausesStr);
|
|
2089
2152
|
}
|
|
@@ -2306,11 +2369,11 @@ namespace RTC
|
|
|
2306
2369
|
// to deliver messages.
|
|
2307
2370
|
if (this->tcb->GetReassemblyQueue().IsAboveWatermark())
|
|
2308
2371
|
{
|
|
2309
|
-
|
|
2372
|
+
MS_WARN_DEV("reassembly queue is above watermark");
|
|
2310
2373
|
|
|
2311
2374
|
if (!this->tcb->GetDataTracker().WillIncreaseCumAckTsn(tsn))
|
|
2312
2375
|
{
|
|
2313
|
-
MS_WARN_TAG(sctp, "reassembly queue is above watermark");
|
|
2376
|
+
MS_WARN_TAG(sctp, "rejecting received data because reassembly queue is above watermark");
|
|
2314
2377
|
|
|
2315
2378
|
this->tcb->GetDataTracker().ForceImmediateSack();
|
|
2316
2379
|
|
|
@@ -2320,7 +2383,7 @@ namespace RTC
|
|
|
2320
2383
|
|
|
2321
2384
|
if (!this->tcb->GetDataTracker().IsTsnValid(tsn))
|
|
2322
2385
|
{
|
|
2323
|
-
MS_WARN_TAG(sctp, "data
|
|
2386
|
+
MS_WARN_TAG(sctp, "rejecting received data because of failing TSN validity");
|
|
2324
2387
|
|
|
2325
2388
|
return;
|
|
2326
2389
|
}
|
|
@@ -2371,8 +2434,7 @@ namespace RTC
|
|
|
2371
2434
|
}
|
|
2372
2435
|
else
|
|
2373
2436
|
{
|
|
2374
|
-
|
|
2375
|
-
sctp,
|
|
2437
|
+
MS_WARN_DEV(
|
|
2376
2438
|
"dropping received out-of-order SACK [TSN:%" PRIu32 "]",
|
|
2377
2439
|
receivedSackChunk->GetCumulativeTsnAck());
|
|
2378
2440
|
}
|
|
@@ -2432,6 +2494,86 @@ namespace RTC
|
|
|
2432
2494
|
return !skipProcessing;
|
|
2433
2495
|
}
|
|
2434
2496
|
|
|
2497
|
+
bool Association::VerifyReceivedStateCookie(const StateCookie* cookie)
|
|
2498
|
+
{
|
|
2499
|
+
MS_TRACE();
|
|
2500
|
+
|
|
2501
|
+
// https://datatracker.ietf.org/doc/html/rfc9260#section-5.1.4
|
|
2502
|
+
//
|
|
2503
|
+
// "Authenticate the State Cookie as one that it previously generated by
|
|
2504
|
+
// comparing the computed MAC against the one carried in the State Cookie.
|
|
2505
|
+
// If this comparison fails, the SCTP packet, including the COOKIE ECHO and
|
|
2506
|
+
// any DATA chunks, should be silently discarded."
|
|
2507
|
+
//
|
|
2508
|
+
// NOTE: The Verification Tag check (RFC 9260 section 5.1.4) is not done
|
|
2509
|
+
// here but in the COOKIE-ECHO handling logic (with and without TCB), which
|
|
2510
|
+
// is performed regardless of whether authentication is enabled.
|
|
2511
|
+
if (!StateCookie::VerifyMac(
|
|
2512
|
+
cookie->GetBuffer(),
|
|
2513
|
+
cookie->GetLength(),
|
|
2514
|
+
this->stateCookieSecret,
|
|
2515
|
+
Association::StateCookieSecretLength))
|
|
2516
|
+
{
|
|
2517
|
+
MS_WARN_TAG(
|
|
2518
|
+
sctp,
|
|
2519
|
+
"received COOKIE-ECHO chunk with State Cookie that failed MAC authentication, discarding");
|
|
2520
|
+
|
|
2521
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
2522
|
+
Types::ErrorKind::PARSE_FAILED,
|
|
2523
|
+
"received COOKIE-ECHO chunk with unauthenticated State Cookie");
|
|
2524
|
+
|
|
2525
|
+
return false;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
// https://datatracker.ietf.org/doc/html/rfc9260#section-5.1.4
|
|
2529
|
+
//
|
|
2530
|
+
// "Compare the creation timestamp in the State Cookie to the current local
|
|
2531
|
+
// time. If the elapsed time is longer than the lifespan carried in the
|
|
2532
|
+
// State Cookie, then the packet, including the COOKIE ECHO and any attached
|
|
2533
|
+
// DATA chunks, SHOULD be discarded, and the endpoint MUST transmit an ERROR
|
|
2534
|
+
// chunk with a 'Stale Cookie' error cause to the peer endpoint."
|
|
2535
|
+
const uint64_t nowMs = this->shared->GetTimeMs();
|
|
2536
|
+
const uint64_t creationMs = cookie->GetCreationTimestampMs();
|
|
2537
|
+
|
|
2538
|
+
if (nowMs > creationMs && nowMs - creationMs > StateCookie::ValidCookieLifeMs)
|
|
2539
|
+
{
|
|
2540
|
+
const uint64_t stalenessMs = nowMs - creationMs - StateCookie::ValidCookieLifeMs;
|
|
2541
|
+
|
|
2542
|
+
MS_WARN_TAG(
|
|
2543
|
+
sctp,
|
|
2544
|
+
"received COOKIE-ECHO chunk with stale State Cookie, sending Stale Cookie error [staleness:%" PRIu64
|
|
2545
|
+
"ms]",
|
|
2546
|
+
stalenessMs);
|
|
2547
|
+
|
|
2548
|
+
// Respond with an ERROR chunk carrying a Stale Cookie error cause. The
|
|
2549
|
+
// packet must use the verification tag the peer expects (the remote
|
|
2550
|
+
// verification tag stored in the cookie we generated).
|
|
2551
|
+
auto packet = CreatePacketWithVerificationTag(cookie->GetRemoteVerificationTag());
|
|
2552
|
+
auto* operationErrorChunk = packet->BuildChunkInPlace<OperationErrorChunk>();
|
|
2553
|
+
auto* staleCookieErrorCause =
|
|
2554
|
+
operationErrorChunk->BuildErrorCauseInPlace<StaleCookieErrorCause>();
|
|
2555
|
+
|
|
2556
|
+
// The Measure of Staleness is expressed in microseconds.
|
|
2557
|
+
const uint64_t stalenessUs = stalenessMs * 1000;
|
|
2558
|
+
|
|
2559
|
+
staleCookieErrorCause->SetMeasureOfStaleness(
|
|
2560
|
+
stalenessUs > std::numeric_limits<uint32_t>::max() ? std::numeric_limits<uint32_t>::max()
|
|
2561
|
+
: static_cast<uint32_t>(stalenessUs));
|
|
2562
|
+
|
|
2563
|
+
staleCookieErrorCause->Consolidate();
|
|
2564
|
+
operationErrorChunk->Consolidate();
|
|
2565
|
+
|
|
2566
|
+
this->packetSender.SendPacket(packet.get());
|
|
2567
|
+
|
|
2568
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
2569
|
+
Types::ErrorKind::WRONG_SEQUENCE, "received COOKIE-ECHO chunk with stale State Cookie");
|
|
2570
|
+
|
|
2571
|
+
return false;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
return true;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2435
2577
|
void Association::OnT1InitTimer(uint64_t& /*baseTimeoutMs*/, bool& /*stop*/)
|
|
2436
2578
|
{
|
|
2437
2579
|
MS_TRACE();
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
#include "RTC/SCTP/association/StateCookie.hpp"
|
|
5
5
|
#include "Logger.hpp"
|
|
6
6
|
#include "MediaSoupErrors.hpp"
|
|
7
|
+
#include <cstring> // std::memcpy(), std::memcmp()
|
|
8
|
+
#include <string_view>
|
|
7
9
|
|
|
8
10
|
namespace RTC
|
|
9
11
|
{
|
|
@@ -11,31 +13,6 @@ namespace RTC
|
|
|
11
13
|
{
|
|
12
14
|
/* Class methods. */
|
|
13
15
|
|
|
14
|
-
bool StateCookie::IsMediasoupStateCookie(const uint8_t* buffer, size_t bufferLength)
|
|
15
|
-
{
|
|
16
|
-
MS_TRACE();
|
|
17
|
-
|
|
18
|
-
if (bufferLength != StateCookie::StateCookieLength)
|
|
19
|
-
{
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (Utils::Byte::Get8Bytes(buffer, 0) != StateCookie::Magic1)
|
|
24
|
-
{
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
auto* negotiatedCapabilitiesField = reinterpret_cast<NegotiatedCapabilitiesField*>(
|
|
29
|
-
const_cast<uint8_t*>(buffer) + StateCookie::NegotiatedCapabilitiesOffset);
|
|
30
|
-
|
|
31
|
-
if (ntohs(negotiatedCapabilitiesField->magic2) != StateCookie::Magic2)
|
|
32
|
-
{
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
16
|
StateCookie* StateCookie::Parse(const uint8_t* buffer, size_t bufferLength)
|
|
40
17
|
{
|
|
41
18
|
MS_TRACE();
|
|
@@ -61,7 +38,10 @@ namespace RTC
|
|
|
61
38
|
uint32_t remoteInitialTsn,
|
|
62
39
|
uint32_t remoteAdvertisedReceiverWindowCredit,
|
|
63
40
|
uint64_t tieTag,
|
|
64
|
-
const NegotiatedCapabilities& negotiatedCapabilities
|
|
41
|
+
const NegotiatedCapabilities& negotiatedCapabilities,
|
|
42
|
+
uint64_t creationTimestampMs,
|
|
43
|
+
const uint8_t* macKey,
|
|
44
|
+
size_t macKeyLength)
|
|
65
45
|
{
|
|
66
46
|
MS_TRACE();
|
|
67
47
|
|
|
@@ -75,9 +55,15 @@ namespace RTC
|
|
|
75
55
|
remoteInitialTsn,
|
|
76
56
|
remoteAdvertisedReceiverWindowCredit,
|
|
77
57
|
tieTag,
|
|
78
|
-
negotiatedCapabilities
|
|
58
|
+
negotiatedCapabilities,
|
|
59
|
+
creationTimestampMs,
|
|
60
|
+
macKey,
|
|
61
|
+
macKeyLength);
|
|
62
|
+
|
|
63
|
+
const size_t cookieLength = macKey != nullptr ? StateCookie::AuthenticatedStateCookieLength
|
|
64
|
+
: StateCookie::StateCookieLength;
|
|
79
65
|
|
|
80
|
-
return new StateCookie(buffer,
|
|
66
|
+
return new StateCookie(buffer, cookieLength);
|
|
81
67
|
}
|
|
82
68
|
|
|
83
69
|
void StateCookie::Write(
|
|
@@ -89,11 +75,18 @@ namespace RTC
|
|
|
89
75
|
uint32_t remoteInitialTsn,
|
|
90
76
|
uint32_t remoteAdvertisedReceiverWindowCredit,
|
|
91
77
|
uint64_t tieTag,
|
|
92
|
-
const NegotiatedCapabilities& negotiatedCapabilities
|
|
78
|
+
const NegotiatedCapabilities& negotiatedCapabilities,
|
|
79
|
+
uint64_t creationTimestampMs,
|
|
80
|
+
const uint8_t* macKey,
|
|
81
|
+
size_t macKeyLength)
|
|
93
82
|
{
|
|
94
83
|
MS_TRACE();
|
|
95
84
|
|
|
96
|
-
|
|
85
|
+
const bool authenticate = macKey != nullptr;
|
|
86
|
+
const size_t cookieLength =
|
|
87
|
+
authenticate ? StateCookie::AuthenticatedStateCookieLength : StateCookie::StateCookieLength;
|
|
88
|
+
|
|
89
|
+
if (bufferLength < cookieLength)
|
|
97
90
|
{
|
|
98
91
|
MS_THROW_TYPE_ERROR("buffer too small");
|
|
99
92
|
}
|
|
@@ -119,6 +112,65 @@ namespace RTC
|
|
|
119
112
|
htons(negotiatedCapabilities.negotiatedMaxOutboundStreams);
|
|
120
113
|
negotiatedCapabilitiesField->negotiatedMaxInboundStreams =
|
|
121
114
|
htons(negotiatedCapabilities.negotiatedMaxInboundStreams);
|
|
115
|
+
|
|
116
|
+
if (!authenticate)
|
|
117
|
+
{
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Append the creation timestamp and the MAC computed over all preceding
|
|
122
|
+
// bytes (including the timestamp).
|
|
123
|
+
//
|
|
124
|
+
// @see RFC 9260 section 5.1.3.
|
|
125
|
+
Utils::Byte::Set8Bytes(buffer, StateCookie::TimestampOffset, creationTimestampMs);
|
|
126
|
+
|
|
127
|
+
const uint8_t* mac = Utils::Crypto::GetHmacSha1(
|
|
128
|
+
reinterpret_cast<const char*>(macKey), macKeyLength, buffer, StateCookie::MacOffset);
|
|
129
|
+
|
|
130
|
+
std::memcpy(buffer + StateCookie::MacOffset, mac, StateCookie::MacLength);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bool StateCookie::IsMediasoupStateCookie(const uint8_t* buffer, size_t bufferLength)
|
|
134
|
+
{
|
|
135
|
+
MS_TRACE();
|
|
136
|
+
|
|
137
|
+
if (bufferLength != StateCookie::StateCookieLength && bufferLength != StateCookie::AuthenticatedStateCookieLength)
|
|
138
|
+
{
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (Utils::Byte::Get8Bytes(buffer, 0) != StateCookie::Magic1)
|
|
143
|
+
{
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
auto* negotiatedCapabilitiesField = reinterpret_cast<NegotiatedCapabilitiesField*>(
|
|
148
|
+
const_cast<uint8_t*>(buffer) + StateCookie::NegotiatedCapabilitiesOffset);
|
|
149
|
+
|
|
150
|
+
if (ntohs(negotiatedCapabilitiesField->magic2) != StateCookie::Magic2)
|
|
151
|
+
{
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
bool StateCookie::VerifyMac(
|
|
159
|
+
const uint8_t* buffer, size_t bufferLength, const uint8_t* macKey, size_t macKeyLength)
|
|
160
|
+
{
|
|
161
|
+
MS_TRACE();
|
|
162
|
+
|
|
163
|
+
// An authenticated cookie has a fixed length.
|
|
164
|
+
if (bufferLength != StateCookie::AuthenticatedStateCookieLength)
|
|
165
|
+
{
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Recompute the MAC over all bytes preceding the MAC field.
|
|
170
|
+
const uint8_t* expectedMac = Utils::Crypto::GetHmacSha1(
|
|
171
|
+
reinterpret_cast<const char*>(macKey), macKeyLength, buffer, StateCookie::MacOffset);
|
|
172
|
+
|
|
173
|
+
return std::memcmp(buffer + StateCookie::MacOffset, expectedMac, StateCookie::MacLength) == 0;
|
|
122
174
|
}
|
|
123
175
|
|
|
124
176
|
Types::SctpImplementation StateCookie::DetermineSctpImplementation(
|
|
@@ -158,7 +210,13 @@ namespace RTC
|
|
|
158
210
|
{
|
|
159
211
|
MS_TRACE();
|
|
160
212
|
|
|
161
|
-
|
|
213
|
+
// The cookie length is determined by whether it carries a MAC. When the
|
|
214
|
+
// cookie is cloned into a larger buffer, `CloneInto()` will set the
|
|
215
|
+
// proper length afterwards.
|
|
216
|
+
SetLength(
|
|
217
|
+
bufferLength == StateCookie::AuthenticatedStateCookieLength
|
|
218
|
+
? StateCookie::AuthenticatedStateCookieLength
|
|
219
|
+
: StateCookie::StateCookieLength);
|
|
162
220
|
}
|
|
163
221
|
|
|
164
222
|
StateCookie::~StateCookie()
|
|
@@ -183,6 +241,13 @@ namespace RTC
|
|
|
183
241
|
" remote advertised receiver window credit: %" PRIu32,
|
|
184
242
|
GetRemoteAdvertisedReceiverWindowCredit());
|
|
185
243
|
MS_DUMP_CLEAN(indentation, " tie-tag: %" PRIu64, GetTieTag());
|
|
244
|
+
MS_DUMP_CLEAN(indentation, " authenticated: %s", IsAuthenticated() ? "yes" : "no");
|
|
245
|
+
|
|
246
|
+
if (IsAuthenticated())
|
|
247
|
+
{
|
|
248
|
+
MS_DUMP_CLEAN(indentation, " creation timestamp (ms): %" PRIu64, GetCreationTimestampMs());
|
|
249
|
+
}
|
|
250
|
+
|
|
186
251
|
negotiatedCapabilities.Dump(indentation + 1);
|
|
187
252
|
MS_DUMP_CLEAN(indentation, "</SCTP::StateCookie>");
|
|
188
253
|
}
|
|
@@ -419,7 +419,7 @@ namespace RTC
|
|
|
419
419
|
|
|
420
420
|
auto crc32c = GetChecksum();
|
|
421
421
|
|
|
422
|
-
// NOTE: Cannot use SetChecksum() because
|
|
422
|
+
// NOTE: Cannot use `SetChecksum()` because this is a `const` method.
|
|
423
423
|
GetHeaderPointer()->checksum = 0;
|
|
424
424
|
|
|
425
425
|
auto computedCrc32c = Utils::Crypto::GetCRC32c(GetBuffer(), GetLength());
|
|
@@ -122,7 +122,10 @@ namespace RTC
|
|
|
122
122
|
uint32_t remoteInitialTsn,
|
|
123
123
|
uint32_t remoteAdvertisedReceiverWindowCredit,
|
|
124
124
|
uint64_t tieTag,
|
|
125
|
-
const NegotiatedCapabilities& negotiatedCapabilities
|
|
125
|
+
const NegotiatedCapabilities& negotiatedCapabilities,
|
|
126
|
+
uint64_t creationTimestampMs,
|
|
127
|
+
const uint8_t* macKey,
|
|
128
|
+
size_t macKeyLength)
|
|
126
129
|
{
|
|
127
130
|
MS_TRACE();
|
|
128
131
|
|
|
@@ -144,9 +147,15 @@ namespace RTC
|
|
|
144
147
|
remoteInitialTsn,
|
|
145
148
|
remoteAdvertisedReceiverWindowCredit,
|
|
146
149
|
tieTag,
|
|
147
|
-
negotiatedCapabilities
|
|
150
|
+
negotiatedCapabilities,
|
|
151
|
+
creationTimestampMs,
|
|
152
|
+
macKey,
|
|
153
|
+
macKeyLength);
|
|
148
154
|
|
|
149
|
-
|
|
155
|
+
const size_t cookieLength = macKey != nullptr ? StateCookie::AuthenticatedStateCookieLength
|
|
156
|
+
: StateCookie::StateCookieLength;
|
|
157
|
+
|
|
158
|
+
SetVariableLengthValueLength(cookieLength);
|
|
150
159
|
}
|
|
151
160
|
|
|
152
161
|
StateCookieParameter* StateCookieParameter::SoftClone(const uint8_t* buffer) const
|
|
@@ -84,6 +84,10 @@ namespace RTC
|
|
|
84
84
|
ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethodToString(
|
|
85
85
|
this->zeroChecksumAlternateErrorDetectionMethod)
|
|
86
86
|
.c_str());
|
|
87
|
+
MS_DUMP_CLEAN(
|
|
88
|
+
indentation,
|
|
89
|
+
" require authenticated cookie: %s",
|
|
90
|
+
this->requireAuthenticatedCookie ? "yes" : "no");
|
|
87
91
|
MS_DUMP_CLEAN(indentation, "</SCTP::SctpOptions>");
|
|
88
92
|
}
|
|
89
93
|
} // namespace SCTP
|