mediasoup 3.20.2 → 3.20.4
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/npm-scripts.mjs +26 -0
- package/package.json +4 -3
- package/worker/include/RTC/SCTP/association/Association.hpp +16 -2
- package/worker/include/RTC/SCTP/association/HeartbeatHandler.hpp +3 -3
- package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +3 -3
- package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +19 -4
- package/worker/include/RTC/SCTP/association/TransmissionControlBlockContextInterface.hpp +19 -2
- package/worker/include/RTC/SCTP/public/SctpTypes.hpp +2 -0
- package/worker/include/RTC/SCTP/rx/ReassemblyQueue.hpp +7 -0
- package/worker/include/RTC/SCTP/tx/RetransmissionErrorCounter.hpp +3 -4
- package/worker/meson.build +3 -0
- package/worker/mocks/include/RTC/SCTP/association/MockAssociationListener.hpp +68 -7
- package/worker/mocks/include/handles/MockBackoffTimerHandle.hpp +10 -4
- package/worker/mocks/src/handles/MockBackoffTimerHandle.cpp +7 -0
- package/worker/src/RTC/SCTP/association/Association.cpp +52 -12
- package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +48 -18
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +26 -17
- package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +48 -15
- package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +17 -8
- package/worker/src/RTC/Transport.cpp +1 -1
- package/worker/test/src/RTC/SCTP/association/TestAssociation.cpp +1755 -0
- package/worker/test/src/RTC/SCTP/association/TestHeartbeatHandler.cpp +4 -1
- package/worker/test/src/RTC/SCTP/association/TestPacketSender.cpp +121 -0
- package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +369 -0
- package/worker/test/src/RTC/SCTP/association/TestTransmissionControlBlock.cpp +16 -2
- package/worker/test/src/RTC/SCTP/rx/TestReassemblyQueue.cpp +24 -0
|
@@ -19,11 +19,11 @@ namespace RTC
|
|
|
19
19
|
/* Instance methods. */
|
|
20
20
|
|
|
21
21
|
HeartbeatHandler::HeartbeatHandler(
|
|
22
|
-
|
|
22
|
+
AssociationListenerDeferrer& associationListenerDeferrer,
|
|
23
23
|
const SctpOptions& sctpOptions,
|
|
24
24
|
SharedInterface* shared,
|
|
25
25
|
TransmissionControlBlockContextInterface* tcbContext)
|
|
26
|
-
:
|
|
26
|
+
: associationListenerDeferrer(associationListenerDeferrer),
|
|
27
27
|
sctpOptions(sctpOptions),
|
|
28
28
|
shared(shared),
|
|
29
29
|
tcbContext(tcbContext),
|
|
@@ -34,7 +34,7 @@ namespace RTC
|
|
|
34
34
|
.listener = this,
|
|
35
35
|
.label = "sctp-heartbeat-interval",
|
|
36
36
|
.baseTimeoutMs = sctpOptions.initialRtoMs,
|
|
37
|
-
.backoffAlgorithm = BackoffTimerHandleInterface::BackoffAlgorithm::
|
|
37
|
+
.backoffAlgorithm = BackoffTimerHandleInterface::BackoffAlgorithm::FIXED,
|
|
38
38
|
.maxBackoffTimeoutMs = sctpOptions.timerMaxBackoffTimeoutMs,
|
|
39
39
|
.maxRestarts = std::nullopt })),
|
|
40
40
|
timeoutTimer(this->shared->CreateBackoffTimer(
|
|
@@ -42,7 +42,7 @@ namespace RTC
|
|
|
42
42
|
.listener = this,
|
|
43
43
|
.label = "sctp-heartbeat-timeout",
|
|
44
44
|
.baseTimeoutMs = sctpOptions.initialRtoMs,
|
|
45
|
-
.backoffAlgorithm = BackoffTimerHandleInterface::BackoffAlgorithm::
|
|
45
|
+
.backoffAlgorithm = BackoffTimerHandleInterface::BackoffAlgorithm::EXPONENTIAL,
|
|
46
46
|
.maxBackoffTimeoutMs = std::nullopt,
|
|
47
47
|
.maxRestarts = 0 }))
|
|
48
48
|
{
|
|
@@ -124,7 +124,7 @@ namespace RTC
|
|
|
124
124
|
|
|
125
125
|
if (!heartbeatInfoParameter)
|
|
126
126
|
{
|
|
127
|
-
this->
|
|
127
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
128
128
|
Types::ErrorKind::PARSE_FAILED,
|
|
129
129
|
"ignoring HEARTBEAT-ACK chunk without Heartbeat Info parameter");
|
|
130
130
|
|
|
@@ -136,14 +136,14 @@ namespace RTC
|
|
|
136
136
|
|
|
137
137
|
if (!info)
|
|
138
138
|
{
|
|
139
|
-
this->
|
|
139
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
140
140
|
Types::ErrorKind::PARSE_FAILED, "ignoring Heartbeat Info parameter without info field");
|
|
141
141
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
else if (infoLen != HeartbeatInfoLength)
|
|
145
145
|
{
|
|
146
|
-
this->
|
|
146
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
147
147
|
Types::ErrorKind::PARSE_FAILED, "ignoring Heartbeat Info parameter with wrong length");
|
|
148
148
|
|
|
149
149
|
return;
|
|
@@ -180,6 +180,23 @@ namespace RTC
|
|
|
180
180
|
{
|
|
181
181
|
MS_TRACE();
|
|
182
182
|
|
|
183
|
+
#if MS_LOG_DEV_LEVEL == 3
|
|
184
|
+
const auto maxRestarts = this->intervalTimer->GetMaxRestarts();
|
|
185
|
+
#endif
|
|
186
|
+
|
|
187
|
+
// NOTE: This timer expires periodically on idle connections (forever), so
|
|
188
|
+
// it's logged at dev level to avoid being noisy.
|
|
189
|
+
MS_DEBUG_DEV(
|
|
190
|
+
"%s timer has expired [expirations:%zu, maxRestarts:%s]",
|
|
191
|
+
this->intervalTimer->GetLabel().c_str(),
|
|
192
|
+
this->intervalTimer->GetExpirationCount(),
|
|
193
|
+
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
194
|
+
|
|
195
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
196
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
197
|
+
// Association does in its own timer handlers.
|
|
198
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
199
|
+
|
|
183
200
|
if (!this->tcbContext->IsAssociationEstablished())
|
|
184
201
|
{
|
|
185
202
|
MS_DEBUG_DEV("won't send HEARTBEAT-REQUEST when SCTP association is not established");
|
|
@@ -210,15 +227,37 @@ namespace RTC
|
|
|
210
227
|
this->tcbContext->SendPacket(packet.get());
|
|
211
228
|
}
|
|
212
229
|
|
|
213
|
-
void HeartbeatHandler::OnTimeoutTimer(uint64_t& /*baseTimeoutMs*/, bool&
|
|
230
|
+
void HeartbeatHandler::OnTimeoutTimer(uint64_t& /*baseTimeoutMs*/, bool& stop)
|
|
214
231
|
{
|
|
215
232
|
MS_TRACE();
|
|
216
233
|
|
|
234
|
+
const auto maxRestarts = this->timeoutTimer->GetMaxRestarts();
|
|
235
|
+
|
|
236
|
+
MS_DEBUG_TAG(
|
|
237
|
+
sctp,
|
|
238
|
+
"%s timer has expired [expirations:%zu, maxRestarts:%s]",
|
|
239
|
+
this->timeoutTimer->GetLabel().c_str(),
|
|
240
|
+
this->timeoutTimer->GetExpirationCount(),
|
|
241
|
+
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
242
|
+
|
|
243
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
244
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
245
|
+
// Association does in its own timer handlers.
|
|
246
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
247
|
+
|
|
217
248
|
// Note that the timeout timer is not restarted. It will be started again when
|
|
218
249
|
// the interval timer expires.
|
|
219
250
|
MS_ASSERT(!this->timeoutTimer->IsRunning(), "timeout timer shouldn't be running");
|
|
220
251
|
|
|
221
|
-
this->tcbContext->IncrementTxErrorCounter("hearbeat timeout")
|
|
252
|
+
if (!this->tcbContext->IncrementTxErrorCounter("hearbeat timeout"))
|
|
253
|
+
{
|
|
254
|
+
// `IncrementTxErrorCounter()` has closed (and destroyed) the TCB (and
|
|
255
|
+
// hence this HeartbeatHandler and its timers). Signal the firing timer to
|
|
256
|
+
// stop and don't touch any member afterwards.
|
|
257
|
+
stop = true;
|
|
258
|
+
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
222
261
|
}
|
|
223
262
|
|
|
224
263
|
void HeartbeatHandler::OnBackoffTimer(
|
|
@@ -226,15 +265,6 @@ namespace RTC
|
|
|
226
265
|
{
|
|
227
266
|
MS_TRACE();
|
|
228
267
|
|
|
229
|
-
const auto maxRestarts = backoffTimer->GetMaxRestarts();
|
|
230
|
-
|
|
231
|
-
MS_DEBUG_TAG(
|
|
232
|
-
sctp,
|
|
233
|
-
"%s timer has expired [expìrations:%zu/%s]",
|
|
234
|
-
backoffTimer->GetLabel().c_str(),
|
|
235
|
-
backoffTimer->GetExpirationCount(),
|
|
236
|
-
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
237
|
-
|
|
238
268
|
if (backoffTimer == this->intervalTimer.get())
|
|
239
269
|
{
|
|
240
270
|
OnIntervalTimer(baseTimeoutMs, stop);
|
|
@@ -13,13 +13,13 @@ namespace RTC
|
|
|
13
13
|
/* Instance methods. */
|
|
14
14
|
|
|
15
15
|
StreamResetHandler::StreamResetHandler(
|
|
16
|
-
|
|
16
|
+
AssociationListenerDeferrer& associationListenerDeferrer,
|
|
17
17
|
SharedInterface* shared,
|
|
18
18
|
TransmissionControlBlockContextInterface* tcbContext,
|
|
19
19
|
DataTracker* dataTracker,
|
|
20
20
|
ReassemblyQueue* reassemblyQueue,
|
|
21
21
|
RetransmissionQueue* retransmissionQueue)
|
|
22
|
-
:
|
|
22
|
+
: associationListenerDeferrer(associationListenerDeferrer),
|
|
23
23
|
shared(shared),
|
|
24
24
|
tcbContext(tcbContext),
|
|
25
25
|
dataTracker(dataTracker),
|
|
@@ -89,7 +89,7 @@ namespace RTC
|
|
|
89
89
|
|
|
90
90
|
if (!ValidateReceivedReConfigChunk(receivedReConfigChunk))
|
|
91
91
|
{
|
|
92
|
-
this->
|
|
92
|
+
this->associationListenerDeferrer.OnAssociationError(
|
|
93
93
|
Types::ErrorKind::PARSE_FAILED, "invalid RE-CONFIG command received");
|
|
94
94
|
|
|
95
95
|
return;
|
|
@@ -334,7 +334,7 @@ namespace RTC
|
|
|
334
334
|
this->reassemblyQueue->ResetStreamsAndLeaveDeferredReset(
|
|
335
335
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
336
336
|
|
|
337
|
-
this->
|
|
337
|
+
this->associationListenerDeferrer.OnAssociationInboundStreamsReset(
|
|
338
338
|
receivedOutgoingSsnResetRequestParameter->GetStreamIds());
|
|
339
339
|
|
|
340
340
|
this->lastProcessedReqResult = ReconfigurationResponseParameter::Result::SUCCESS_PERFORMED;
|
|
@@ -412,7 +412,7 @@ namespace RTC
|
|
|
412
412
|
MS_DEBUG_DEV(
|
|
413
413
|
"reset stream success [reqSeqNbr:%" PRIu32 "]", this->currentRequest->GetReqSeqNbr());
|
|
414
414
|
|
|
415
|
-
this->
|
|
415
|
+
this->associationListenerDeferrer.OnAssociationStreamsResetPerformed(
|
|
416
416
|
this->currentRequest->GetStreamIds());
|
|
417
417
|
|
|
418
418
|
this->currentRequest = std::nullopt;
|
|
@@ -450,7 +450,7 @@ namespace RTC
|
|
|
450
450
|
receivedReconfigurationResponseParameter->GetResult())
|
|
451
451
|
.c_str());
|
|
452
452
|
|
|
453
|
-
this->
|
|
453
|
+
this->associationListenerDeferrer.OnAssociationStreamsResetFailed(
|
|
454
454
|
this->currentRequest->GetStreamIds(),
|
|
455
455
|
ReconfigurationResponseParameter::ResultToString(
|
|
456
456
|
receivedReconfigurationResponseParameter->GetResult()));
|
|
@@ -465,10 +465,24 @@ namespace RTC
|
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
void StreamResetHandler::OnReConfigTimer(uint64_t& baseTimeoutMs, bool&
|
|
468
|
+
void StreamResetHandler::OnReConfigTimer(uint64_t& baseTimeoutMs, bool& stop)
|
|
469
469
|
{
|
|
470
470
|
MS_TRACE();
|
|
471
471
|
|
|
472
|
+
const auto maxRestarts = this->reConfigTimer->GetMaxRestarts();
|
|
473
|
+
|
|
474
|
+
MS_DEBUG_TAG(
|
|
475
|
+
sctp,
|
|
476
|
+
"%s timer has expired [expirations:%zu, maxRestarts:%s]",
|
|
477
|
+
this->reConfigTimer->GetLabel().c_str(),
|
|
478
|
+
this->reConfigTimer->GetExpirationCount(),
|
|
479
|
+
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
480
|
+
|
|
481
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
482
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
483
|
+
// Association does in its own timer handlers.
|
|
484
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
485
|
+
|
|
472
486
|
if (this->currentRequest && this->currentRequest->HasBeenSent())
|
|
473
487
|
{
|
|
474
488
|
// The request was deferred (received "In Progress"). This is not a
|
|
@@ -481,7 +495,11 @@ namespace RTC
|
|
|
481
495
|
// response.
|
|
482
496
|
else if (!this->tcbContext->IncrementTxErrorCounter("RECONFIG timeout"))
|
|
483
497
|
{
|
|
484
|
-
//
|
|
498
|
+
// `IncrementTxErrorCounter()` has closed (and destroyed) the TCB (and
|
|
499
|
+
// hence this StreamResetHandler and its timer). Signal the firing timer
|
|
500
|
+
// to stop and don't touch any member afterwards.
|
|
501
|
+
stop = true;
|
|
502
|
+
|
|
485
503
|
return;
|
|
486
504
|
}
|
|
487
505
|
}
|
|
@@ -506,15 +524,6 @@ namespace RTC
|
|
|
506
524
|
{
|
|
507
525
|
MS_TRACE();
|
|
508
526
|
|
|
509
|
-
const auto maxRestarts = backoffTimer->GetMaxRestarts();
|
|
510
|
-
|
|
511
|
-
MS_DEBUG_TAG(
|
|
512
|
-
sctp,
|
|
513
|
-
"%s timer has expired [expìrations:%zu/%s]",
|
|
514
|
-
backoffTimer->GetLabel().c_str(),
|
|
515
|
-
backoffTimer->GetExpirationCount(),
|
|
516
|
-
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
517
|
-
|
|
518
527
|
if (backoffTimer == this->reConfigTimer.get())
|
|
519
528
|
{
|
|
520
529
|
OnReConfigTimer(baseTimeoutMs, stop);
|
|
@@ -21,7 +21,8 @@ namespace RTC
|
|
|
21
21
|
/* Instance methods. */
|
|
22
22
|
|
|
23
23
|
TransmissionControlBlock::TransmissionControlBlock(
|
|
24
|
-
|
|
24
|
+
TransmissionControlBlockContextInterface::Listener* listener,
|
|
25
|
+
AssociationListenerDeferrer& associationListenerDeferrer,
|
|
25
26
|
const SctpOptions& sctpOptions,
|
|
26
27
|
SharedInterface* shared,
|
|
27
28
|
SendQueueInterface& sendQueue,
|
|
@@ -35,7 +36,8 @@ namespace RTC
|
|
|
35
36
|
const NegotiatedCapabilities& negotiatedCapabilities,
|
|
36
37
|
size_t maxPacketLength,
|
|
37
38
|
std::function<bool()> isAssociationEstablished)
|
|
38
|
-
:
|
|
39
|
+
: listener(listener),
|
|
40
|
+
associationListenerDeferrer(associationListenerDeferrer),
|
|
39
41
|
sctpOptions(sctpOptions),
|
|
40
42
|
shared(shared),
|
|
41
43
|
packetSender(packetSender),
|
|
@@ -71,7 +73,7 @@ namespace RTC
|
|
|
71
73
|
sctpOptions.maxReceiverWindowBufferSize, negotiatedCapabilities.messageInterleaving),
|
|
72
74
|
retransmissionQueue(
|
|
73
75
|
this,
|
|
74
|
-
this->
|
|
76
|
+
this->associationListenerDeferrer,
|
|
75
77
|
localInitialTsn,
|
|
76
78
|
remoteAdvertisedReceiverWindowCredit,
|
|
77
79
|
sendQueue,
|
|
@@ -80,13 +82,13 @@ namespace RTC
|
|
|
80
82
|
negotiatedCapabilities.partialReliability,
|
|
81
83
|
negotiatedCapabilities.messageInterleaving),
|
|
82
84
|
streamResetHandler(
|
|
83
|
-
this->
|
|
85
|
+
this->associationListenerDeferrer,
|
|
84
86
|
this->shared,
|
|
85
87
|
this,
|
|
86
88
|
std::addressof(this->dataTracker),
|
|
87
89
|
std::addressof(this->reassemblyQueue),
|
|
88
90
|
std::addressof(this->retransmissionQueue)),
|
|
89
|
-
heartbeatHandler(this->
|
|
91
|
+
heartbeatHandler(this->associationListenerDeferrer, sctpOptions, this->shared, this)
|
|
90
92
|
{
|
|
91
93
|
MS_TRACE();
|
|
92
94
|
|
|
@@ -407,10 +409,24 @@ namespace RTC
|
|
|
407
409
|
}
|
|
408
410
|
}
|
|
409
411
|
|
|
410
|
-
void TransmissionControlBlock::OnT3RtxTimer(uint64_t& /*baseTimeoutMs*/, bool&
|
|
412
|
+
void TransmissionControlBlock::OnT3RtxTimer(uint64_t& /*baseTimeoutMs*/, bool& stop)
|
|
411
413
|
{
|
|
412
414
|
MS_TRACE();
|
|
413
415
|
|
|
416
|
+
const auto maxRestarts = this->t3RtxTimer->GetMaxRestarts();
|
|
417
|
+
|
|
418
|
+
MS_DEBUG_TAG(
|
|
419
|
+
sctp,
|
|
420
|
+
"%s timer has expired [expirations:%zu, maxRestarts:%s]",
|
|
421
|
+
this->t3RtxTimer->GetLabel().c_str(),
|
|
422
|
+
this->t3RtxTimer->GetExpirationCount(),
|
|
423
|
+
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
424
|
+
|
|
425
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
426
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
427
|
+
// Association does in its own timer handlers.
|
|
428
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
429
|
+
|
|
414
430
|
// In the COOKIE-ECHO state, let the T1-COOKIE timer trigger
|
|
415
431
|
// retransmissions, to avoid having two timers doing that.
|
|
416
432
|
if (this->remoteStateCookie.has_value())
|
|
@@ -427,6 +443,15 @@ namespace RTC
|
|
|
427
443
|
|
|
428
444
|
SendBufferedPackets(nowMs);
|
|
429
445
|
}
|
|
446
|
+
else
|
|
447
|
+
{
|
|
448
|
+
// `IncrementTxErrorCounter()` has closed (and destroyed) this TCB and
|
|
449
|
+
// its timers. Signal the firing timer to stop and don't touch any
|
|
450
|
+
// member afterwards.
|
|
451
|
+
stop = true;
|
|
452
|
+
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
430
455
|
}
|
|
431
456
|
}
|
|
432
457
|
|
|
@@ -434,6 +459,23 @@ namespace RTC
|
|
|
434
459
|
{
|
|
435
460
|
MS_TRACE();
|
|
436
461
|
|
|
462
|
+
#if MS_LOG_DEV_LEVEL == 3
|
|
463
|
+
const auto maxRestarts = this->delayedAckTimer->GetMaxRestarts();
|
|
464
|
+
#endif
|
|
465
|
+
|
|
466
|
+
// NOTE: This timer expires very frequently (whenever received data is
|
|
467
|
+
// pending to be acked), so it's logged at dev level to avoid being noisy.
|
|
468
|
+
MS_DEBUG_DEV(
|
|
469
|
+
"%s timer has expired [expirations:%zu, maxRestarts:%s]",
|
|
470
|
+
this->delayedAckTimer->GetLabel().c_str(),
|
|
471
|
+
this->delayedAckTimer->GetExpirationCount(),
|
|
472
|
+
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
473
|
+
|
|
474
|
+
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
475
|
+
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
476
|
+
// Association does in its own timer handlers.
|
|
477
|
+
const AssociationListenerDeferrer::ScopedDeferrer deferrer(this->associationListenerDeferrer);
|
|
478
|
+
|
|
437
479
|
this->dataTracker.HandleDelayedAckTimerExpiry();
|
|
438
480
|
|
|
439
481
|
MaySendSackChunk();
|
|
@@ -444,15 +486,6 @@ namespace RTC
|
|
|
444
486
|
{
|
|
445
487
|
MS_TRACE();
|
|
446
488
|
|
|
447
|
-
const auto maxRestarts = backoffTimer->GetMaxRestarts();
|
|
448
|
-
|
|
449
|
-
MS_DEBUG_TAG(
|
|
450
|
-
sctp,
|
|
451
|
-
"%s timer has expired [expìrations:%zu/%s]",
|
|
452
|
-
backoffTimer->GetLabel().c_str(),
|
|
453
|
-
backoffTimer->GetExpirationCount(),
|
|
454
|
-
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
455
|
-
|
|
456
489
|
if (backoffTimer == this->t3RtxTimer.get())
|
|
457
490
|
{
|
|
458
491
|
OnT3RtxTimer(baseTimeoutMs, stop);
|
|
@@ -140,12 +140,16 @@ namespace RTC
|
|
|
140
140
|
{
|
|
141
141
|
MS_DEBUG_DEV("forward TSN to %" PRIu32 ", deferring", tsn.Wrap());
|
|
142
142
|
|
|
143
|
+
this->queuedBytes += ForwardTsnCost(skippedStreams.size());
|
|
144
|
+
|
|
143
145
|
this->deferredResetStreams->deferredActions.emplace_back(
|
|
144
146
|
[this,
|
|
145
147
|
newCumulativeTsn,
|
|
146
148
|
skippedStreams2 = std::vector<AnyForwardTsnChunk::SkippedStream>(
|
|
147
149
|
skippedStreams.begin(), skippedStreams.end())]
|
|
148
150
|
{
|
|
151
|
+
this->queuedBytes -= ForwardTsnCost(skippedStreams2.size());
|
|
152
|
+
|
|
149
153
|
HandleForwardTsn(newCumulativeTsn, skippedStreams2);
|
|
150
154
|
});
|
|
151
155
|
|
|
@@ -216,15 +220,13 @@ namespace RTC
|
|
|
216
220
|
|
|
217
221
|
if (!this->deferredResetStreams.has_value())
|
|
218
222
|
{
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
MS_DEBUG_DEV(
|
|
223
|
-
"entering deferred reset [senderLastAssignedTsn:%" PRIu32 "]", senderLastAssignedTsn);
|
|
223
|
+
MS_DEBUG_DEV(
|
|
224
|
+
"entering deferred reset [senderLastAssignedTsn:%" PRIu32 "]", senderLastAssignedTsn);
|
|
224
225
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
this->deferredResetStreams = std::make_optional<DeferredResetStreams>(
|
|
227
|
+
this->tsnUnwrapper.Unwrap(senderLastAssignedTsn),
|
|
228
|
+
std::set<uint16_t>(streamIds.begin(), streamIds.end()));
|
|
229
|
+
}
|
|
228
230
|
|
|
229
231
|
AssertIsConsistent();
|
|
230
232
|
}
|
|
@@ -244,6 +246,13 @@ namespace RTC
|
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
size_t ReassemblyQueue::ForwardTsnCost(size_t numStreams)
|
|
250
|
+
{
|
|
251
|
+
MS_TRACE();
|
|
252
|
+
|
|
253
|
+
return (1 + numStreams) * 4;
|
|
254
|
+
}
|
|
255
|
+
|
|
247
256
|
void ReassemblyQueue::AddReassembledMessage(std::span<const Types::UnwrappedTsn> tsns, Message message)
|
|
248
257
|
{
|
|
249
258
|
MS_TRACE();
|
|
@@ -91,7 +91,7 @@ namespace RTC
|
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
this->sctpAssociation = std::make_unique<RTC::SCTP::Association>(
|
|
94
|
-
sctpOptions, this, this->shared, options->isDataChannel());
|
|
94
|
+
sctpOptions, this, this->shared, options->isDataChannel(), /*mayConnectOnReceivedSctpData*/ true);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// Create the RTCP timer.
|