mediasoup 3.19.21 → 3.19.22
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 -0
- package/node/lib/Worker.d.ts.map +1 -1
- package/node/lib/Worker.js +14 -0
- package/package.json +4 -2
- package/worker/fuzzer/src/RTC/FuzzerDtlsTransport.cpp +9 -3
- package/worker/fuzzer/src/RTC/RTP/FuzzerRtpStreamSend.cpp +9 -1
- package/worker/include/Channel/ChannelMessageRegistrator.hpp +39 -0
- package/worker/include/Channel/ChannelMessageRegistratorInterface.hpp +32 -0
- package/worker/include/Channel/ChannelSocket.hpp +1 -1
- package/worker/include/DepUsrSCTP.hpp +8 -7
- package/worker/include/RTC/ActiveSpeakerObserver.hpp +7 -7
- package/worker/include/RTC/AudioLevelObserver.hpp +7 -7
- package/worker/include/RTC/Consumer.hpp +3 -3
- package/worker/include/RTC/DataConsumer.hpp +3 -3
- package/worker/include/RTC/DataProducer.hpp +3 -3
- package/worker/include/RTC/DirectTransport.hpp +2 -2
- package/worker/include/RTC/DtlsTransport.hpp +8 -6
- package/worker/include/RTC/ICE/IceServer.hpp +8 -5
- package/worker/include/RTC/KeyFrameRequestManager.hpp +15 -12
- package/worker/include/RTC/NackGenerator.hpp +7 -6
- package/worker/include/RTC/PipeConsumer.hpp +1 -2
- package/worker/include/RTC/PipeTransport.hpp +2 -2
- package/worker/include/RTC/PlainTransport.hpp +2 -2
- package/worker/include/RTC/Producer.hpp +3 -3
- package/worker/include/RTC/RTP/RtpStream.hpp +7 -1
- package/worker/include/RTC/RTP/RtpStreamRecv.hpp +6 -5
- package/worker/include/RTC/RTP/RtpStreamSend.hpp +4 -1
- package/worker/include/RTC/Router.hpp +3 -3
- package/worker/include/RTC/RtpObserver.hpp +3 -3
- package/worker/include/RTC/SCTP/TODO_SCTP.md +18 -6
- package/worker/include/RTC/SCTP/association/Association.hpp +11 -8
- package/worker/include/RTC/SCTP/association/HeartbeatHandler.hpp +9 -6
- package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +37 -23
- package/worker/include/RTC/SCTP/association/TCBContext.hpp +3 -2
- package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +81 -8
- package/worker/include/RTC/SCTP/packet/UserData.hpp +36 -0
- package/worker/include/RTC/SCTP/packet/chunks/ForwardTsnChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/packet/chunks/IForwardTsnChunk.hpp +1 -1
- package/worker/include/RTC/SCTP/public/SctpOptions.hpp +2 -1
- package/worker/include/RTC/SCTP/tx/OutstandingData.hpp +604 -0
- package/worker/include/RTC/SCTP/tx/RetransmissionQueue.hpp +336 -0
- package/worker/include/RTC/SCTP/tx/RetransmissionTimeout.hpp +5 -4
- package/worker/include/RTC/Serializable.hpp +8 -0
- package/worker/include/RTC/SimpleConsumer.hpp +1 -2
- package/worker/include/RTC/SimulcastConsumer.hpp +1 -2
- package/worker/include/RTC/SvcConsumer.hpp +1 -2
- package/worker/include/RTC/Transport.hpp +8 -8
- package/worker/include/RTC/TransportCongestionControlClient.hpp +8 -5
- package/worker/include/RTC/TransportCongestionControlServer.hpp +8 -5
- package/worker/include/RTC/WebRtcServer.hpp +3 -3
- package/worker/include/RTC/WebRtcTransport.hpp +3 -3
- package/worker/include/Shared.hpp +40 -0
- package/worker/include/SharedInterface.hpp +44 -0
- package/worker/include/Utils.hpp +6 -0
- package/worker/include/Worker.hpp +3 -3
- package/worker/include/common.hpp +1 -1
- package/worker/include/handles/BackoffTimerHandle.hpp +27 -65
- package/worker/include/handles/BackoffTimerHandleInterface.hpp +116 -0
- package/worker/include/handles/TimerHandle.hpp +36 -20
- package/worker/include/handles/TimerHandleInterface.hpp +43 -0
- package/worker/meson.build +21 -4
- package/worker/meson_options.txt +2 -1
- package/worker/mocks/include/Channel/MockChannelMessageRegistrator.hpp +45 -0
- package/worker/mocks/include/MockShared.hpp +43 -0
- package/worker/mocks/src/Channel/MockChannelMessageRegistrator.cpp +128 -0
- package/worker/mocks/src/MockShared.cpp +26 -0
- package/worker/scripts/clang-scripts.mjs +4 -1
- package/worker/src/Channel/ChannelMessageRegistrator.cpp +125 -0
- package/worker/src/Channel/ChannelSocket.cpp +1 -1
- package/worker/src/DepUsrSCTP.cpp +10 -4
- package/worker/src/RTC/ActiveSpeakerObserver.cpp +7 -7
- package/worker/src/RTC/AudioLevelObserver.cpp +12 -10
- package/worker/src/RTC/Consumer.cpp +23 -20
- package/worker/src/RTC/DataConsumer.cpp +11 -11
- package/worker/src/RTC/DataProducer.cpp +3 -3
- package/worker/src/RTC/DirectTransport.cpp +16 -16
- package/worker/src/RTC/DtlsTransport.cpp +4 -4
- package/worker/src/RTC/ICE/IceServer.cpp +4 -3
- package/worker/src/RTC/KeyFrameRequestManager.cpp +15 -15
- package/worker/src/RTC/NackGenerator.cpp +3 -3
- package/worker/src/RTC/PipeConsumer.cpp +5 -4
- package/worker/src/RTC/PipeTransport.cpp +3 -3
- package/worker/src/RTC/PlainTransport.cpp +10 -9
- package/worker/src/RTC/Producer.cpp +30 -28
- package/worker/src/RTC/RTCP/FeedbackPsRpsi.cpp +1 -2
- package/worker/src/RTC/RTP/RtpStream.cpp +9 -2
- package/worker/src/RTC/RTP/RtpStreamRecv.cpp +5 -4
- package/worker/src/RTC/RTP/RtpStreamSend.cpp +5 -2
- package/worker/src/RTC/Router.cpp +3 -3
- package/worker/src/RTC/RtpObserver.cpp +2 -1
- package/worker/src/RTC/SCTP/association/Association.cpp +94 -114
- package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +27 -21
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +52 -55
- package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +144 -25
- package/worker/src/RTC/SCTP/packet/chunks/ForwardTsnChunk.cpp +2 -2
- package/worker/src/RTC/SCTP/packet/chunks/IForwardTsnChunk.cpp +2 -2
- package/worker/src/RTC/SCTP/tx/OutstandingData.cpp +905 -0
- package/worker/src/RTC/SCTP/tx/RetransmissionQueue.cpp +799 -0
- package/worker/src/RTC/SCTP/tx/RetransmissionTimeout.cpp +1 -1
- package/worker/src/RTC/SctpAssociation.cpp +1 -1
- package/worker/src/RTC/SimpleConsumer.cpp +8 -7
- package/worker/src/RTC/SimulcastConsumer.cpp +11 -10
- package/worker/src/RTC/SvcConsumer.cpp +11 -10
- package/worker/src/RTC/Transport.cpp +36 -26
- package/worker/src/RTC/TransportCongestionControlClient.cpp +4 -2
- package/worker/src/RTC/TransportCongestionControlServer.cpp +4 -3
- package/worker/src/RTC/WebRtcServer.cpp +5 -4
- package/worker/src/RTC/WebRtcTransport.cpp +39 -26
- package/worker/src/Shared.cpp +35 -0
- package/worker/src/Worker.cpp +10 -23
- package/worker/src/handles/BackoffTimerHandle.cpp +11 -16
- package/worker/src/handles/TimerHandle.cpp +5 -4
- package/worker/src/lib.cpp +14 -1
- package/worker/tasks.py +1 -1
- package/worker/test/include/RTC/ICE/iceCommon.hpp +1 -0
- package/worker/test/include/RTC/RTP/rtpCommon.hpp +1 -0
- package/worker/test/include/RTC/SCTP/sctpCommon.hpp +6 -0
- package/worker/test/src/RTC/RTP/TestRtpStreamRecv.cpp +12 -5
- package/worker/test/src/RTC/RTP/TestRtpStreamSend.cpp +34 -23
- package/worker/test/src/RTC/SCTP/tx/TestOutstandingData.cpp +1196 -0
- package/worker/test/src/RTC/SCTP/tx/TestRetransmissionTimeout.cpp +33 -33
- package/worker/test/src/RTC/TestKeyFrameRequestManager.cpp +14 -6
- package/worker/test/src/RTC/TestNackGenerator.cpp +6 -2
- package/worker/test/src/RTC/TestSimpleConsumer.cpp +6 -10
- package/worker/test/src/RTC/TestTransportCongestionControlServer.cpp +9 -2
- package/worker/test/src/Utils/TestByte.cpp +98 -0
- package/worker/include/ChannelMessageRegistrator.hpp +0 -30
- package/worker/include/RTC/Shared.hpp +0 -23
- package/worker/src/ChannelMessageRegistrator.cpp +0 -119
- package/worker/src/RTC/Shared.cpp +0 -23
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
#ifndef MS_RTC_SCTP_OUTSTANDING_DATA_HPP
|
|
2
|
+
#define MS_RTC_SCTP_OUTSTANDING_DATA_HPP
|
|
3
|
+
|
|
4
|
+
#include "common.hpp"
|
|
5
|
+
#include "RTC/SCTP/common/UnwrappedSequenceNumber.hpp"
|
|
6
|
+
#include "RTC/SCTP/packet/Packet.hpp"
|
|
7
|
+
#include "RTC/SCTP/packet/UserData.hpp"
|
|
8
|
+
#include "RTC/SCTP/packet/chunks/SackChunk.hpp"
|
|
9
|
+
#include "RTC/SCTP/public/SctpTypes.hpp"
|
|
10
|
+
#include <deque>
|
|
11
|
+
#include <limits>
|
|
12
|
+
#include <optional>
|
|
13
|
+
#include <ostream>
|
|
14
|
+
#include <set>
|
|
15
|
+
#include <span>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
18
|
+
namespace RTC
|
|
19
|
+
{
|
|
20
|
+
namespace SCTP
|
|
21
|
+
{
|
|
22
|
+
/**
|
|
23
|
+
* This class keeps track of outstanding data Chunks (sent, not yet acked)
|
|
24
|
+
* and handles acking, nacking, rescheduling and abandoning.
|
|
25
|
+
*
|
|
26
|
+
* Items are added to this queue as they are sent and will be removed when
|
|
27
|
+
* the peer acks them using the cumulative TSN ack.
|
|
28
|
+
*/
|
|
29
|
+
class OutstandingData
|
|
30
|
+
{
|
|
31
|
+
public:
|
|
32
|
+
static constexpr uint16_t MaxRetransmitsNoLimit{ std::numeric_limits<uint16_t>::max() };
|
|
33
|
+
static constexpr uint16_t ExpiresAtMsInfinite{ 0 };
|
|
34
|
+
|
|
35
|
+
#ifdef MS_TEST
|
|
36
|
+
public:
|
|
37
|
+
/**
|
|
38
|
+
* State for DATA Chunks (message fragments) in the queue.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* - Used in tests.
|
|
42
|
+
*/
|
|
43
|
+
enum class State : uint8_t
|
|
44
|
+
{
|
|
45
|
+
/**
|
|
46
|
+
* The Chunk has been sent but not received yet (from the sender's point
|
|
47
|
+
* of view, as no SACK has been received yet that reference this Chunk).
|
|
48
|
+
*/
|
|
49
|
+
IN_FLIGHT,
|
|
50
|
+
/**
|
|
51
|
+
* A SACK has been received which explicitly marked this Chunk as missing.
|
|
52
|
+
* It's now NACKED and may be retransmitted if NACKED enough times.
|
|
53
|
+
*/
|
|
54
|
+
NACKED,
|
|
55
|
+
/**
|
|
56
|
+
* A Chunk that will be retransmitted when possible.
|
|
57
|
+
*/
|
|
58
|
+
TO_BE_RETRANSMITTED,
|
|
59
|
+
/**
|
|
60
|
+
* A SACK has been received which explicitly marked this Chunk as
|
|
61
|
+
* received.
|
|
62
|
+
*/
|
|
63
|
+
ACKED,
|
|
64
|
+
/**
|
|
65
|
+
* A Chunk whose message has expired or has been retransmitted too many
|
|
66
|
+
* times (RFC3758). It will not be retransmitted anymore.
|
|
67
|
+
*/
|
|
68
|
+
ABANDONED,
|
|
69
|
+
};
|
|
70
|
+
#endif
|
|
71
|
+
|
|
72
|
+
public:
|
|
73
|
+
using UnwrappedTsn = UnwrappedSequenceNumber<uint32_t>;
|
|
74
|
+
|
|
75
|
+
public:
|
|
76
|
+
/**
|
|
77
|
+
* Contains variables scoped to a processing of an incoming SACK.
|
|
78
|
+
*/
|
|
79
|
+
struct AckInfo
|
|
80
|
+
{
|
|
81
|
+
explicit AckInfo(UnwrappedTsn cumulativeTsnAck) : highestTsnAcked(cumulativeTsnAck)
|
|
82
|
+
{
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Bytes acked by increasing `cumulativeTsnAck` and `gapAckBlocks`.
|
|
87
|
+
*/
|
|
88
|
+
size_t bytesAcked{ 0 };
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Indicates if this SACK indicates that packet loss has occurred. Just
|
|
92
|
+
* because a packet is missing in the SACK doesn't necessarily mean that
|
|
93
|
+
* there is packet loss as that packet might be in-flight and received
|
|
94
|
+
* out-of-order. But when it has been reported missing consecutive
|
|
95
|
+
* times, it will eventually be considered "lost" and this will be set.
|
|
96
|
+
*/
|
|
97
|
+
bool hasPacketLoss{ false };
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Highest TSN Newly Acknowledged, an SCTP variable.
|
|
101
|
+
*/
|
|
102
|
+
UnwrappedTsn highestTsnAcked;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The set of lifecycle IDs that were acked using `cumulativeTsnAck`.
|
|
106
|
+
*/
|
|
107
|
+
std::vector<uint64_t> ackedLifecycleIds;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The set of lifecycle IDs that were acked, but had been abandoned.
|
|
111
|
+
*/
|
|
112
|
+
std::vector<uint64_t> abandonedLifecycleIds;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
private:
|
|
116
|
+
/**
|
|
117
|
+
* A fragmented message's DATA Chunk while in the retransmission queue,
|
|
118
|
+
* and its associated metadata.
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* - This data structure has been optimized for size, by ordering fields
|
|
122
|
+
* to avoid unnecessary padding.
|
|
123
|
+
*/
|
|
124
|
+
class Item
|
|
125
|
+
{
|
|
126
|
+
public:
|
|
127
|
+
enum class NackAction : uint8_t
|
|
128
|
+
{
|
|
129
|
+
NOTHING,
|
|
130
|
+
RETRANSMIT,
|
|
131
|
+
ABANDON,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
private:
|
|
135
|
+
private:
|
|
136
|
+
enum class Lifecycle : uint8_t
|
|
137
|
+
{
|
|
138
|
+
/**
|
|
139
|
+
* The Chunk is alive (sent, received, etc).
|
|
140
|
+
*/
|
|
141
|
+
ACTIVE,
|
|
142
|
+
/**
|
|
143
|
+
* The Chunk is scheduled to be retransmitted, and will then
|
|
144
|
+
* transition to become active.
|
|
145
|
+
*/
|
|
146
|
+
TO_BE_RETRANSMITTED,
|
|
147
|
+
/**
|
|
148
|
+
* The Chunk has been abandoned. This is a terminal state.
|
|
149
|
+
*/
|
|
150
|
+
ABANDONED
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
enum class AckState : uint8_t
|
|
154
|
+
{
|
|
155
|
+
/**
|
|
156
|
+
* The Chunk is in-flight.
|
|
157
|
+
*/
|
|
158
|
+
UNACKED,
|
|
159
|
+
/**
|
|
160
|
+
* The Chunk has been received and acknowledged.
|
|
161
|
+
*/
|
|
162
|
+
ACKED,
|
|
163
|
+
/**
|
|
164
|
+
* The Chunk has been nacked and is possibly lost.
|
|
165
|
+
*/
|
|
166
|
+
NACKED
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
public:
|
|
170
|
+
Item(
|
|
171
|
+
uint32_t messageId,
|
|
172
|
+
UserData data,
|
|
173
|
+
uint64_t timeSentMs,
|
|
174
|
+
uint16_t maxRetransmissions,
|
|
175
|
+
uint64_t expiresAtMs,
|
|
176
|
+
uint64_t lifecycleId);
|
|
177
|
+
|
|
178
|
+
Item(const Item&) = delete;
|
|
179
|
+
|
|
180
|
+
Item& operator=(const Item&) = delete;
|
|
181
|
+
|
|
182
|
+
public:
|
|
183
|
+
uint32_t GetMessageId() const
|
|
184
|
+
{
|
|
185
|
+
return this->messageId;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
uint64_t GetTimeSentMs() const
|
|
189
|
+
{
|
|
190
|
+
return this->timeSentMs;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const UserData& GetData() const
|
|
194
|
+
{
|
|
195
|
+
return this->data;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Acks an item.
|
|
200
|
+
*/
|
|
201
|
+
void Ack();
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Nacks an item. If it has been nacked enough times, or if
|
|
205
|
+
* `retransmitNow` is set, it might be marked for retransmission. If
|
|
206
|
+
* the item has reached its max retransmission value, it will instead
|
|
207
|
+
* be abandoned. The action performed is indicated as return value.
|
|
208
|
+
*/
|
|
209
|
+
NackAction Nack(bool retransmitNow);
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Prepares the item to be retransmitted. Sets it as outstanding and
|
|
213
|
+
* clears all nack counters.
|
|
214
|
+
*/
|
|
215
|
+
void MarkAsRetransmitted();
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Marks this item as abandoned.
|
|
219
|
+
*/
|
|
220
|
+
void Abandon();
|
|
221
|
+
|
|
222
|
+
bool IsOutstanding() const
|
|
223
|
+
{
|
|
224
|
+
return this->ackState != AckState::ACKED && this->lifecycle == Lifecycle::ACTIVE;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
bool IsAcked() const
|
|
228
|
+
{
|
|
229
|
+
return this->ackState == AckState::ACKED;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
bool IsNacked() const
|
|
233
|
+
{
|
|
234
|
+
return this->ackState == AckState::NACKED;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
bool IsAbandoned() const
|
|
238
|
+
{
|
|
239
|
+
return this->lifecycle == Lifecycle::ABANDONED;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Indicates if this Chunk should be retransmitted.
|
|
244
|
+
*/
|
|
245
|
+
bool ShouldBeRetransmitted() const
|
|
246
|
+
{
|
|
247
|
+
return this->lifecycle == Lifecycle::TO_BE_RETRANSMITTED;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Indicates if this Chunk has ever been retransmitted.
|
|
252
|
+
*/
|
|
253
|
+
bool HasBeenRetransmitted() const
|
|
254
|
+
{
|
|
255
|
+
return this->numRetransmissions > 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Given the current time, and the current state of this DATA Chunk, it
|
|
260
|
+
* will indicate if it has expired (SCTP Partial Reliability Extension).
|
|
261
|
+
*/
|
|
262
|
+
bool HasExpired(uint64_t nowMs) const
|
|
263
|
+
{
|
|
264
|
+
return (
|
|
265
|
+
this->expiresAtMs != OutstandingData::ExpiresAtMsInfinite && this->expiresAtMs <= nowMs);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
uint64_t GetLifecycleId() const
|
|
269
|
+
{
|
|
270
|
+
return this->lifecycleId;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const uint32_t messageId;
|
|
274
|
+
// When the packet was sent, and placed in this queue.
|
|
275
|
+
const uint64_t timeSentMs;
|
|
276
|
+
// If the message was sent with a maximum number of retransmissions,
|
|
277
|
+
// this is set to that number. The value zero (0) means that it will
|
|
278
|
+
// never be retransmitted.
|
|
279
|
+
const uint16_t maxRetransmissions;
|
|
280
|
+
// Indicates the life cycle status of this Chunk.
|
|
281
|
+
Lifecycle lifecycle{ Lifecycle::ACTIVE };
|
|
282
|
+
// Indicates the presence of this Chunk, if it's in flight (UNACKED),
|
|
283
|
+
// has been received (ACKED) or is possibly lost (NACKED).
|
|
284
|
+
AckState ackState{ AckState::UNACKED };
|
|
285
|
+
// The number of times the DATA Chunk has been nacked (by having
|
|
286
|
+
// received a SACK which doesn't include it). Will be cleared on
|
|
287
|
+
// retransmissions.
|
|
288
|
+
uint8_t nackCount{ 0 };
|
|
289
|
+
// The number of times the DATA Chunk has been retransmitted.
|
|
290
|
+
uint16_t numRetransmissions{ 0 };
|
|
291
|
+
// At this exact millisecond, the item is considered expired. If the
|
|
292
|
+
// message is not to be expired, this is set to the infinite future.
|
|
293
|
+
// NOTE: If 0 it means infinite time.
|
|
294
|
+
const uint64_t expiresAtMs;
|
|
295
|
+
// An optional lifecycle id, which may only be set for the last
|
|
296
|
+
// fragment.
|
|
297
|
+
const uint64_t lifecycleId;
|
|
298
|
+
// The actual data to send/retransmit.
|
|
299
|
+
const UserData data;
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
public:
|
|
303
|
+
OutstandingData(
|
|
304
|
+
size_t dataChunkHeaderLength,
|
|
305
|
+
UnwrappedTsn lastCumulativeTsnAck,
|
|
306
|
+
std::function<bool(uint16_t /*streamId*/, uint32_t /*outgoingMessageId*/)> discardFromSendQueue);
|
|
307
|
+
|
|
308
|
+
public:
|
|
309
|
+
AckInfo HandleSack(
|
|
310
|
+
UnwrappedTsn cumulativeTsnAck,
|
|
311
|
+
std::span<const SackChunk::GapAckBlock> gapAckBlocks,
|
|
312
|
+
bool isInFastRecovery);
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Returns as many of the Chunks that are eligible for fast retransmissions
|
|
316
|
+
* and that would fit in a single packet of `maxLength`. The eligible
|
|
317
|
+
* Chunks that didn't fit will be marked for (normal) retransmission and
|
|
318
|
+
* will not be returned if this method is called again.
|
|
319
|
+
*/
|
|
320
|
+
std::vector<std::pair<uint32_t /*tsn*/, UserData>> GetChunksToBeFastRetransmitted(size_t maxLength);
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Given `maxLength` of space left in a packet, which Chunks can be added
|
|
324
|
+
* to it?
|
|
325
|
+
*/
|
|
326
|
+
std::vector<std::pair<uint32_t /*tsn*/, UserData>> GetChunksToBeRetransmitted(size_t maxLength);
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* How many inflight bytes there are, as sent on the wire as packets.
|
|
330
|
+
*/
|
|
331
|
+
size_t GetUnackedPacketBytes() const
|
|
332
|
+
{
|
|
333
|
+
return this->unackedPacketBytes;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* How many inflight bytes there are, counting only the payload.
|
|
338
|
+
*/
|
|
339
|
+
size_t GetUnackedPayloadBytes() const
|
|
340
|
+
{
|
|
341
|
+
return this->unackedPayloadBytes;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Returns the number of DATA Chunks that are in-flight (not acked or
|
|
346
|
+
* nacked).
|
|
347
|
+
*/
|
|
348
|
+
size_t GetUnackedItems() const
|
|
349
|
+
{
|
|
350
|
+
return this->unackedItems;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Given the current time `nowMs`, expire and abandon outstanding (sent
|
|
355
|
+
* at least once) Chunks that have a limited lifetime.
|
|
356
|
+
*/
|
|
357
|
+
void ExpireOutstandingChunks(uint64_t nowMs);
|
|
358
|
+
|
|
359
|
+
bool IsEmpty() const
|
|
360
|
+
{
|
|
361
|
+
return this->outstandingData.empty();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
bool HasDataToBeFastRetransmitted() const
|
|
365
|
+
{
|
|
366
|
+
return !this->toBeFastRetransmitted.empty();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
bool HasDataToBeRetransmitted() const
|
|
370
|
+
{
|
|
371
|
+
return !this->toBeRetransmitted.empty() || !this->toBeFastRetransmitted.empty();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
UnwrappedTsn GetLastCumulativeTsnAck() const
|
|
375
|
+
{
|
|
376
|
+
return this->lastCumulativeTsnAck;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
UnwrappedTsn GetNextTsn() const
|
|
380
|
+
{
|
|
381
|
+
return this->GetHighestOutstandingTsn().GetNextValue();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
UnwrappedTsn GetHighestOutstandingTsn() const;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Schedules `data` to be sent, with the provided partial reliability
|
|
388
|
+
* parameters. Returns the TSN if the item was actually added and
|
|
389
|
+
* scheduled to be sent, and std::nullopt if it shouldn't be sent.
|
|
390
|
+
*/
|
|
391
|
+
std::optional<UnwrappedTsn> Insert(
|
|
392
|
+
uint32_t messageId,
|
|
393
|
+
const UserData& data,
|
|
394
|
+
uint64_t timeSentMs,
|
|
395
|
+
uint16_t maxRetransmissions = OutstandingData::MaxRetransmitsNoLimit,
|
|
396
|
+
uint64_t expiresAtMs = OutstandingData::ExpiresAtMsInfinite,
|
|
397
|
+
uint64_t lifecycleId = 0);
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Nacks all outstanding data.
|
|
401
|
+
*/
|
|
402
|
+
void NackAll();
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Creates a FORWARD-TSN Chunk and adds it to the given Packet.
|
|
406
|
+
*/
|
|
407
|
+
void CreateForwardTsn(Packet* packet) const;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Creates an I-FORWARD-TSN Chunk and adds it to the given Packet.
|
|
411
|
+
*/
|
|
412
|
+
void CreateIForwardTsn(Packet* packet) const;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Given the current time and a TSN, it returns the measured RTT between
|
|
416
|
+
* when the Chunk was sent and now. It takes into acccount Karn's
|
|
417
|
+
* algorithm, so if the Chunk has ever been retransmitted, it will return
|
|
418
|
+
* `std::nullopt`.
|
|
419
|
+
*/
|
|
420
|
+
std::optional<uint64_t> MeasureRtt(uint64_t nowMs, UnwrappedTsn tsn) const;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Returns true if the next Chunk that is not acked by the peer has been
|
|
424
|
+
* abandoned, which means that a FORWARD-TSN should be sent.
|
|
425
|
+
*/
|
|
426
|
+
bool ShouldSendForwardTsn() const;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Called when an outgoing stream reset is sent, marking the last assigned
|
|
430
|
+
* TSN as a breakpoint that a FORWARD-TSN shouldn't cross.
|
|
431
|
+
*/
|
|
432
|
+
void BeginResetStreams();
|
|
433
|
+
|
|
434
|
+
#ifdef MS_TEST
|
|
435
|
+
/**
|
|
436
|
+
* Returns the internal state of all queued Chunks.
|
|
437
|
+
*
|
|
438
|
+
* @remarks
|
|
439
|
+
* - Used in tests.
|
|
440
|
+
*/
|
|
441
|
+
std::vector<std::pair<uint32_t /*tsn*/, State>> GetChunkStatesForTesting() const;
|
|
442
|
+
#endif
|
|
443
|
+
|
|
444
|
+
private:
|
|
445
|
+
/**
|
|
446
|
+
* Returns how large a Chunk will be, serialized, carrying the data.
|
|
447
|
+
*/
|
|
448
|
+
size_t GetSerializedChunkLength(const UserData& data) const;
|
|
449
|
+
|
|
450
|
+
Item& GetItem(UnwrappedTsn tsn);
|
|
451
|
+
|
|
452
|
+
const Item& GetItem(UnwrappedTsn tsn) const;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Given a `cumulativeTsnAck` from an incoming SACK, will remove those
|
|
456
|
+
* items in the retransmission queue up until this value and will update
|
|
457
|
+
* `ackInfo` by setting `this->lastCumulativeTsnAck`.
|
|
458
|
+
*/
|
|
459
|
+
void RemoveAcked(UnwrappedTsn cumulativeTsnAck, AckInfo& ackInfo);
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Will mark the Chunks covered by the `gapAckBlocks` from an incoming
|
|
463
|
+
* SACK as "acked" and update `ackInfo` by adding new TSNs to
|
|
464
|
+
* `this->cumulativeTsnAck`.
|
|
465
|
+
*/
|
|
466
|
+
void AckGapBlocks(
|
|
467
|
+
UnwrappedTsn cumulativeTsnAck,
|
|
468
|
+
std::span<const SackChunk::GapAckBlock> gapAckBlocks,
|
|
469
|
+
AckInfo& ackInfo);
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Mark Chunks reported as "missing", as "nacked" or "to be retransmitted"
|
|
473
|
+
* depending how many times this has happened. Only packets up until
|
|
474
|
+
* `ackInfo.highestTsnAcked` (highest TSN newly acknowledged) are
|
|
475
|
+
* nacked/retransmitted. The method will set `ackInfo.hasPacketLoss`.
|
|
476
|
+
*/
|
|
477
|
+
void NackBetweenAckBlocks(
|
|
478
|
+
UnwrappedTsn cumulativeTsnAck,
|
|
479
|
+
std::span<const SackChunk::GapAckBlock> gapAckBlocks,
|
|
480
|
+
bool isInFastRecovery,
|
|
481
|
+
bool cumulativeTsnAckedAdvanced,
|
|
482
|
+
AckInfo& ackInfo);
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Process the acknowledgement of the Chunk referenced by `item` and
|
|
486
|
+
* updates state in `ackInfo` and the object's state.
|
|
487
|
+
*/
|
|
488
|
+
void AckChunk(AckInfo& ackInfo, UnwrappedTsn tsn, Item& item);
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Helper method to process an incoming nack of an item and perform the
|
|
492
|
+
* correct operations given the action indicated when nacking an item
|
|
493
|
+
* (e.g. retransmitting or abandoning). The return value indicate if an
|
|
494
|
+
* action was performed, meaning that packet loss was detected and acted
|
|
495
|
+
* upon. If `doFastRetransmit` is set and if the item has been nacked
|
|
496
|
+
* sufficiently many times so that it should be retransmitted, this will
|
|
497
|
+
* schedule it to be "fast retransmitted". This is only done just before
|
|
498
|
+
* going into fast recovery.
|
|
499
|
+
*
|
|
500
|
+
* @remarks
|
|
501
|
+
* - Note that since nacking an item may result in it becoming abandoned,
|
|
502
|
+
* which in turn could alter `this->outstandingData`, any iterators are
|
|
503
|
+
* invalidated after having called this method.
|
|
504
|
+
*/
|
|
505
|
+
bool NackItem(UnwrappedTsn tsn, bool retransmitNow, bool doFastRetransmit);
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Given that a message fragment, `item` has been abandoned, abandon all
|
|
509
|
+
* other fragments that share the same message - both never-before-sent
|
|
510
|
+
* fragments that are still in the SendQueue and outstanding Chunks.
|
|
511
|
+
*/
|
|
512
|
+
void AbandonAllFor(const OutstandingData::Item& item);
|
|
513
|
+
|
|
514
|
+
std::vector<std::pair<uint32_t /*tsn*/, UserData>> ExtractChunksThatCanFit(
|
|
515
|
+
std::set<UnwrappedTsn>& chunks, size_t maxLength);
|
|
516
|
+
|
|
517
|
+
void AssertIsConsistent() const;
|
|
518
|
+
|
|
519
|
+
private:
|
|
520
|
+
// The size of the data Chunk (DATA/I-DATA) header that is used.
|
|
521
|
+
const size_t dataChunkHeaderLength;
|
|
522
|
+
// The last cumulative TSN ack number.
|
|
523
|
+
UnwrappedTsn lastCumulativeTsnAck;
|
|
524
|
+
// Callback when to discard items from the send queue.
|
|
525
|
+
std::function<bool(uint16_t /*streamId*/, uint32_t /*outgoingMessageId*/)> discardFromSendQueue;
|
|
526
|
+
// Outstanding items. If non-empty, the first element has
|
|
527
|
+
// `TSN=this->lastCumulativeTsnAck_ + 1` and the following items are in
|
|
528
|
+
// strict increasing TSN order. The last item has
|
|
529
|
+
// `TSN=GetHighestOutstandingTsn()`.
|
|
530
|
+
std::deque<Item> outstandingData;
|
|
531
|
+
// The number of bytes that are in-flight, counting only the payload.
|
|
532
|
+
size_t unackedPayloadBytes{ 0 };
|
|
533
|
+
// The number of bytes that are in-flight, as sent on the wire (as
|
|
534
|
+
// packets).
|
|
535
|
+
size_t unackedPacketBytes{ 0 };
|
|
536
|
+
// The number of DATA Chunks that are in-flight (sent but not yet acked
|
|
537
|
+
// or nacked).
|
|
538
|
+
size_t unackedItems{ 0 };
|
|
539
|
+
// Data Chunks that are eligible for fast retransmission.
|
|
540
|
+
std::set<UnwrappedTsn> toBeFastRetransmitted;
|
|
541
|
+
// Data Chunks that are to be retransmitted.
|
|
542
|
+
std::set<UnwrappedTsn> toBeRetransmitted;
|
|
543
|
+
// Wben a stream reset has begun, the "next TSN to assign" is added to
|
|
544
|
+
// this set, and removed when the cum-ack TSN reaches it. This is used
|
|
545
|
+
// to limit a FORWARD-TSN to reset streams past a "stream reset last
|
|
546
|
+
// assigned TSN".
|
|
547
|
+
// NOTE: dcsctp uses `webrtc::flat_set<UnwrappedTsn>` type which is more
|
|
548
|
+
// efficient in read operations.
|
|
549
|
+
std::set<UnwrappedTsn> streamResetBreakpointTsns;
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
#ifdef MS_TEST
|
|
553
|
+
/**
|
|
554
|
+
* For logging purposes in Catch2 tests.
|
|
555
|
+
*/
|
|
556
|
+
inline std::ostream& operator<<(std::ostream& os, OutstandingData::State state)
|
|
557
|
+
{
|
|
558
|
+
switch (state)
|
|
559
|
+
{
|
|
560
|
+
case OutstandingData::State::IN_FLIGHT:
|
|
561
|
+
{
|
|
562
|
+
return os << "IN_FLIGHT";
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
case OutstandingData::State::NACKED:
|
|
566
|
+
{
|
|
567
|
+
return os << "NACKED";
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
case OutstandingData::State::TO_BE_RETRANSMITTED:
|
|
571
|
+
{
|
|
572
|
+
return os << "TO_BE_RETRANSMITTED";
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
case OutstandingData::State::ACKED:
|
|
576
|
+
{
|
|
577
|
+
return os << "ACKED";
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
case OutstandingData::State::ABANDONED:
|
|
581
|
+
{
|
|
582
|
+
return os << "ABANDONED";
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
default:
|
|
586
|
+
{
|
|
587
|
+
return os << "UNKNOWN(" << static_cast<int>(state) << ")";
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* For Catch2 to print it nicely.
|
|
594
|
+
*/
|
|
595
|
+
inline std::ostream& operator<<(
|
|
596
|
+
std::ostream& os, const std::pair<uint32_t, OutstandingData::State>& s)
|
|
597
|
+
{
|
|
598
|
+
return os << "{tsn:" << s.first << ", state:" << s.second << "}";
|
|
599
|
+
}
|
|
600
|
+
#endif
|
|
601
|
+
} // namespace SCTP
|
|
602
|
+
} // namespace RTC
|
|
603
|
+
|
|
604
|
+
#endif
|