mediasoup 3.20.3 → 3.20.5
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 +2 -2
- package/worker/include/RTC/SCTP/association/Association.hpp +16 -2
- package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +16 -1
- 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/include/RTC/SeqManager.hpp +2 -2
- 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 +56 -14
- package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +33 -13
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +19 -11
- package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +34 -11
- package/worker/src/RTC/SCTP/rx/DataTracker.cpp +4 -1
- package/worker/src/RTC/SCTP/rx/ReassemblyQueue.cpp +17 -8
- package/worker/src/RTC/SeqManager.cpp +42 -29
- 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/TestPacketSender.cpp +121 -0
- package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +369 -0
- package/worker/test/src/RTC/SCTP/association/TestTransmissionControlBlock.cpp +11 -0
- package/worker/test/src/RTC/SCTP/rx/TestReassemblyQueue.cpp +24 -0
|
@@ -21,6 +21,7 @@ namespace RTC
|
|
|
21
21
|
/* Instance methods. */
|
|
22
22
|
|
|
23
23
|
TransmissionControlBlock::TransmissionControlBlock(
|
|
24
|
+
TransmissionControlBlockContextInterface::Listener* listener,
|
|
24
25
|
AssociationListenerDeferrer& associationListenerDeferrer,
|
|
25
26
|
const SctpOptions& sctpOptions,
|
|
26
27
|
SharedInterface* shared,
|
|
@@ -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),
|
|
@@ -407,10 +409,19 @@ 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
|
+
|
|
414
425
|
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
415
426
|
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
416
427
|
// Association does in its own timer handlers.
|
|
@@ -432,6 +443,15 @@ namespace RTC
|
|
|
432
443
|
|
|
433
444
|
SendBufferedPackets(nowMs);
|
|
434
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
|
+
}
|
|
435
455
|
}
|
|
436
456
|
}
|
|
437
457
|
|
|
@@ -439,6 +459,18 @@ namespace RTC
|
|
|
439
459
|
{
|
|
440
460
|
MS_TRACE();
|
|
441
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
|
+
|
|
442
474
|
// This is a top-level timer entry point (invoked by libuv outside any other
|
|
443
475
|
// SCTP API call), so it must establish the deferrer scope itself, just like
|
|
444
476
|
// Association does in its own timer handlers.
|
|
@@ -454,15 +486,6 @@ namespace RTC
|
|
|
454
486
|
{
|
|
455
487
|
MS_TRACE();
|
|
456
488
|
|
|
457
|
-
const auto maxRestarts = backoffTimer->GetMaxRestarts();
|
|
458
|
-
|
|
459
|
-
MS_DEBUG_TAG(
|
|
460
|
-
sctp,
|
|
461
|
-
"%s timer has expired [expìrations:%zu/%s]",
|
|
462
|
-
backoffTimer->GetLabel().c_str(),
|
|
463
|
-
backoffTimer->GetExpirationCount(),
|
|
464
|
-
maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
|
|
465
|
-
|
|
466
489
|
if (backoffTimer == this->t3RtxTimer.get())
|
|
467
490
|
{
|
|
468
491
|
OnT3RtxTimer(baseTimeoutMs, stop);
|
|
@@ -268,7 +268,9 @@ namespace RTC
|
|
|
268
268
|
{
|
|
269
269
|
MS_TRACE();
|
|
270
270
|
|
|
271
|
-
UpdateAckState(
|
|
271
|
+
// NOTE: Assign directly instead of going through UpdateAckState() to avoid
|
|
272
|
+
// its side effect of stopping the delayed-ack timer.
|
|
273
|
+
this->ackState = AckState::IMMEDIATE;
|
|
272
274
|
}
|
|
273
275
|
|
|
274
276
|
bool DataTracker::WillIncreaseCumAckTsn(uint32_t tsn) const
|
|
@@ -359,6 +361,7 @@ namespace RTC
|
|
|
359
361
|
{
|
|
360
362
|
this->delayedAckTimer->Start();
|
|
361
363
|
}
|
|
364
|
+
|
|
362
365
|
this->ackState = newAckState;
|
|
363
366
|
}
|
|
364
367
|
}
|
|
@@ -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();
|
|
@@ -63,9 +63,15 @@ namespace RTC
|
|
|
63
63
|
{
|
|
64
64
|
this->maxInput = input;
|
|
65
65
|
this->maxDropped = input;
|
|
66
|
-
// Insert input in
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
// Insert input in sorted order, if not present.
|
|
67
|
+
const SeqLowerThan seqLowerThan;
|
|
68
|
+
const auto it =
|
|
69
|
+
std::lower_bound(this->dropped.begin(), this->dropped.end(), input, seqLowerThan);
|
|
70
|
+
|
|
71
|
+
if (it == this->dropped.end() || *it != input)
|
|
72
|
+
{
|
|
73
|
+
this->dropped.insert(it, input);
|
|
74
|
+
}
|
|
69
75
|
|
|
70
76
|
ClearDropped();
|
|
71
77
|
}
|
|
@@ -74,7 +80,15 @@ namespace RTC
|
|
|
74
80
|
// Allows for properly accounting for out of order drops until an input is forwarded.
|
|
75
81
|
else if (this->maxInput == this->maxDropped && SeqManager<T, N>::IsSeqHigherThan(input, this->maxForwarded))
|
|
76
82
|
{
|
|
77
|
-
|
|
83
|
+
// Insert input in sorted order, if not present.
|
|
84
|
+
const SeqLowerThan seqLowerThan;
|
|
85
|
+
const auto it =
|
|
86
|
+
std::lower_bound(this->dropped.begin(), this->dropped.end(), input, seqLowerThan);
|
|
87
|
+
|
|
88
|
+
if (it == this->dropped.end() || *it != input)
|
|
89
|
+
{
|
|
90
|
+
this->dropped.insert(it, input);
|
|
91
|
+
}
|
|
78
92
|
|
|
79
93
|
ClearDropped();
|
|
80
94
|
}
|
|
@@ -112,22 +126,24 @@ namespace RTC
|
|
|
112
126
|
{
|
|
113
127
|
goto done;
|
|
114
128
|
}
|
|
115
|
-
// This input was dropped.
|
|
116
|
-
else if (this->dropped.find(input) != this->dropped.end())
|
|
117
|
-
{
|
|
118
|
-
MS_DEBUG_DEV("trying to send a dropped input");
|
|
119
|
-
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
// There are dropped inputs, calculate 'base' for this input.
|
|
123
129
|
else
|
|
124
130
|
{
|
|
125
|
-
|
|
131
|
+
const SeqLowerThan seqLowerThan;
|
|
132
|
+
const auto it =
|
|
133
|
+
std::lower_bound(this->dropped.begin(), this->dropped.end(), input, seqLowerThan);
|
|
126
134
|
|
|
127
|
-
|
|
128
|
-
|
|
135
|
+
if (it != this->dropped.end() && *it == input)
|
|
136
|
+
{
|
|
137
|
+
MS_DEBUG_DEV("trying to send a dropped input");
|
|
138
|
+
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// There are dropped inputs, calculate 'base' for this input.
|
|
143
|
+
auto droppedCount = std::distance(
|
|
144
|
+
this->dropped.begin(),
|
|
145
|
+
std::lower_bound(this->dropped.begin(), this->dropped.end(), input, SeqLowerThan()));
|
|
129
146
|
|
|
130
|
-
droppedCount -= std::distance(it, this->dropped.end());
|
|
131
147
|
base = (this->base - droppedCount) & SeqManager::MaxValue;
|
|
132
148
|
}
|
|
133
149
|
|
|
@@ -191,19 +207,16 @@ namespace RTC
|
|
|
191
207
|
|
|
192
208
|
const size_t previousDroppedSize = this->dropped.size();
|
|
193
209
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
210
|
+
// Cleanup dropped values.
|
|
211
|
+
this->dropped.erase(
|
|
212
|
+
this->dropped.begin(),
|
|
213
|
+
std::find_if(
|
|
214
|
+
this->dropped.begin(),
|
|
215
|
+
this->dropped.end(),
|
|
216
|
+
[this](T value)
|
|
217
|
+
{
|
|
218
|
+
return !SeqManager<T, N>::IsSeqHigherThan(value, this->maxInput);
|
|
219
|
+
}));
|
|
207
220
|
|
|
208
221
|
// Adapt base.
|
|
209
222
|
this->base = (this->base - (previousDroppedSize - this->dropped.size())) & SeqManager::MaxValue;
|
|
@@ -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.
|