mediasoup 3.19.19 → 3.19.21
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/README.md +4 -4
- package/node/lib/Worker.d.ts +1 -1
- package/node/lib/Worker.d.ts.map +1 -1
- package/node/lib/Worker.js +8 -2
- package/node/lib/WorkerTypes.d.ts +8 -4
- package/node/lib/WorkerTypes.d.ts.map +1 -1
- package/node/lib/index.d.ts +1 -1
- package/node/lib/index.d.ts.map +1 -1
- package/node/lib/index.js +2 -1
- package/node/lib/sctpParametersTypes.d.ts +3 -13
- package/node/lib/sctpParametersTypes.d.ts.map +1 -1
- package/node/lib/test/test-PlainTransport.js +8 -3
- package/node/lib/test/test-WebRtcTransport.js +9 -4
- package/package.json +10 -10
- package/worker/Makefile +0 -4
- package/worker/fuzzer/src/fuzzer.cpp +6 -5
- package/worker/include/RTC/DataConsumer.hpp +4 -14
- package/worker/include/RTC/SCTP/TODO_SCTP.md +18 -10
- package/worker/include/RTC/SCTP/association/Association.hpp +39 -31
- package/worker/include/RTC/SCTP/association/{AssociationDeferredListener.hpp → AssociationListenerDeferrer.hpp} +10 -8
- package/worker/include/RTC/SCTP/association/HeartbeatHandler.hpp +77 -0
- package/worker/include/RTC/SCTP/association/NegotiatedCapabilities.hpp +2 -2
- package/worker/include/RTC/SCTP/association/PacketSender.hpp +2 -2
- package/worker/include/RTC/SCTP/association/StateCookie.hpp +2 -2
- package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +272 -0
- package/worker/include/RTC/SCTP/association/TCBContext.hpp +67 -0
- package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +81 -11
- package/worker/include/RTC/SCTP/common/UnwrappedSequenceNumber.hpp +274 -0
- package/worker/include/RTC/SCTP/packet/Chunk.hpp +0 -1
- package/worker/include/RTC/SCTP/packet/UserData.hpp +1 -0
- package/worker/include/RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.hpp +14 -10
- package/worker/include/RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.hpp +14 -10
- package/worker/include/RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp +13 -2
- package/worker/include/RTC/SCTP/public/AssociationInterface.hpp +7 -1
- package/worker/include/RTC/SCTP/public/AssociationListener.hpp +11 -0
- package/worker/include/RTC/SCTP/public/Message.hpp +1 -0
- package/worker/include/RTC/SCTP/public/SctpOptions.hpp +4 -4
- package/worker/include/RTC/SctpAssociation.hpp +2 -2
- package/worker/include/RTC/Transport.hpp +9 -13
- package/worker/include/Settings.hpp +2 -1
- package/worker/include/Utils.hpp +130 -6
- package/worker/meson.build +10 -39
- package/worker/meson_options.txt +0 -1
- package/worker/scripts/package-lock.json +6 -6
- package/worker/src/DepLibUring.cpp +1 -1
- package/worker/src/RTC/DataConsumer.cpp +5 -29
- package/worker/src/RTC/PipeTransport.cpp +15 -12
- package/worker/src/RTC/PlainTransport.cpp +15 -12
- package/worker/src/RTC/RTP/RetransmissionBuffer.cpp +5 -5
- package/worker/src/RTC/RTP/RtpStream.cpp +2 -2
- package/worker/src/RTC/RTP/RtxStream.cpp +1 -1
- package/worker/src/RTC/RateCalculator.cpp +5 -5
- package/worker/src/RTC/SCTP/association/Association.cpp +218 -148
- package/worker/src/RTC/SCTP/association/{AssociationDeferredListener.cpp → AssociationListenerDeferrer.cpp} +38 -30
- package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +244 -0
- package/worker/src/RTC/SCTP/association/NegotiatedCapabilities.cpp +8 -6
- package/worker/src/RTC/SCTP/association/PacketSender.cpp +7 -2
- package/worker/src/RTC/SCTP/association/StateCookie.cpp +8 -8
- package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +512 -0
- package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +45 -39
- package/worker/src/RTC/SCTP/packet/chunks/SackChunk.cpp +1 -1
- package/worker/src/RTC/SCTP/packet/errorCauses/UserInitiatedAbortErrorCause.cpp +1 -1
- package/worker/src/RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.cpp +22 -5
- package/worker/src/RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.cpp +22 -5
- package/worker/src/RTC/SCTP/tx/RetransmissionErrorCounter.cpp +1 -1
- package/worker/src/RTC/SctpAssociation.cpp +1 -2
- package/worker/src/RTC/SeqManager.cpp +4 -4
- package/worker/src/RTC/Transport.cpp +247 -134
- package/worker/src/RTC/WebRtcTransport.cpp +9 -5
- package/worker/src/Settings.cpp +21 -1
- package/worker/src/Worker.cpp +13 -10
- package/worker/src/lib.cpp +11 -8
- package/worker/tasks.py +2 -35
- package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +13 -12
- package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +20 -20
- package/worker/test/src/RTC/SCTP/common/TestUnwrappedSequenceNumber.cpp +210 -0
- package/worker/test/src/RTC/SCTP/packet/chunks/TestAbortAssociationChunk.cpp +2 -2
- package/worker/test/src/RTC/SCTP/packet/chunks/TestHeartbeatAckChunk.cpp +9 -4
- package/worker/test/src/RTC/SCTP/packet/chunks/TestHeartbeatRequestChunk.cpp +5 -0
- package/worker/test/src/RTC/SCTP/packet/chunks/TestInitAckChunk.cpp +1 -1
- package/worker/test/src/RTC/SCTP/packet/chunks/TestInitChunk.cpp +5 -5
- package/worker/test/src/RTC/SCTP/packet/chunks/TestReConfigChunk.cpp +19 -20
- package/worker/test/src/RTC/SCTP/packet/chunks/TestUnknownChunk.cpp +3 -0
- package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUnknownErrorCause.cpp +3 -0
- package/worker/test/src/RTC/SCTP/packet/parameters/TestIncomingSsnResetRequestParameter.cpp +24 -27
- package/worker/test/src/RTC/SCTP/packet/parameters/TestOutgoingSsnResetRequestParameter.cpp +25 -30
- package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +8 -6
- package/worker/test/src/RTC/SCTP/packet/parameters/TestSupportedExtensionsParameter.cpp +12 -0
- package/worker/test/src/RTC/SCTP/packet/parameters/TestZeroChecksumAcceptableParameter.cpp +5 -8
- package/worker/test/src/Utils/TestNumber.cpp +119 -49
- package/worker/test/src/tests.cpp +11 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#ifndef
|
|
2
|
-
#define
|
|
1
|
+
#ifndef MS_RTC_SCTP_ASSOCIATION_LISTENER_DEFERRED_HPP
|
|
2
|
+
#define MS_RTC_SCTP_ASSOCIATION_LISTENER_DEFERRED_HPP
|
|
3
3
|
|
|
4
4
|
#include "common.hpp"
|
|
5
5
|
#include "RTC/SCTP/public/AssociationListener.hpp"
|
|
@@ -15,18 +15,18 @@ namespace RTC
|
|
|
15
15
|
{
|
|
16
16
|
namespace SCTP
|
|
17
17
|
{
|
|
18
|
-
class
|
|
18
|
+
class AssociationListenerDeferrer : public AssociationListener
|
|
19
19
|
{
|
|
20
20
|
public:
|
|
21
|
-
class
|
|
21
|
+
class ScopedDeferrer
|
|
22
22
|
{
|
|
23
23
|
public:
|
|
24
|
-
explicit
|
|
24
|
+
explicit ScopedDeferrer(AssociationListenerDeferrer& listenerDeferrer);
|
|
25
25
|
|
|
26
|
-
~
|
|
26
|
+
~ScopedDeferrer();
|
|
27
27
|
|
|
28
28
|
private:
|
|
29
|
-
|
|
29
|
+
AssociationListenerDeferrer& listenerDeferrer;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
private:
|
|
@@ -49,7 +49,7 @@ namespace RTC
|
|
|
49
49
|
using Callback = std::function<void(CallbackData, AssociationListener*)>;
|
|
50
50
|
|
|
51
51
|
public:
|
|
52
|
-
explicit
|
|
52
|
+
explicit AssociationListenerDeferrer(AssociationListener* innerListener);
|
|
53
53
|
|
|
54
54
|
private:
|
|
55
55
|
void SetReady();
|
|
@@ -85,6 +85,8 @@ namespace RTC
|
|
|
85
85
|
|
|
86
86
|
void OnAssociationTotalBufferedAmountLow() override;
|
|
87
87
|
|
|
88
|
+
bool OnAssociationIsTransportReadyForSctp() override;
|
|
89
|
+
|
|
88
90
|
private:
|
|
89
91
|
AssociationListener* innerListener;
|
|
90
92
|
bool ready{ false };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#ifndef MS_RTC_SCTP_HEARTBEAT_HANDLER_HPP
|
|
2
|
+
#define MS_RTC_SCTP_HEARTBEAT_HANDLER_HPP
|
|
3
|
+
|
|
4
|
+
#include "common.hpp"
|
|
5
|
+
#include "RTC/SCTP/association/TCBContext.hpp"
|
|
6
|
+
#include "RTC/SCTP/packet/chunks/HeartbeatAckChunk.hpp"
|
|
7
|
+
#include "RTC/SCTP/packet/chunks/HeartbeatRequestChunk.hpp"
|
|
8
|
+
#include "RTC/SCTP/public/AssociationListener.hpp"
|
|
9
|
+
#include "RTC/SCTP/public/SctpOptions.hpp"
|
|
10
|
+
#include "handles/BackoffTimerHandle.hpp"
|
|
11
|
+
|
|
12
|
+
namespace RTC
|
|
13
|
+
{
|
|
14
|
+
namespace SCTP
|
|
15
|
+
{
|
|
16
|
+
/**
|
|
17
|
+
* HeartbeatHandler handles all logic around sending heartbeats and receiving
|
|
18
|
+
* the responses, as well as receiving incoming heartbeat requests.
|
|
19
|
+
*
|
|
20
|
+
* Heartbeats are sent on idle connections to ensure that the connection is
|
|
21
|
+
* still healthy and to measure the RTT. If a number of heartbeats time out,
|
|
22
|
+
* the connection will eventually be closed.
|
|
23
|
+
*/
|
|
24
|
+
class HeartbeatHandler : public BackoffTimerHandle::Listener
|
|
25
|
+
{
|
|
26
|
+
public:
|
|
27
|
+
HeartbeatHandler(
|
|
28
|
+
AssociationListener& associationListener,
|
|
29
|
+
const SctpOptions& sctpOptions,
|
|
30
|
+
TCBContext* tcbContext);
|
|
31
|
+
|
|
32
|
+
~HeartbeatHandler() override;
|
|
33
|
+
|
|
34
|
+
public:
|
|
35
|
+
/**
|
|
36
|
+
* Called when the heartbeat interval timer should be restarted. This is
|
|
37
|
+
* generally done every time data is sent, which makes the timer expire
|
|
38
|
+
* when the connection is idle.
|
|
39
|
+
*/
|
|
40
|
+
void RestartTimer();
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Called on received HEARTBEAT_REQUEST Chunk.
|
|
44
|
+
*/
|
|
45
|
+
void HandleReceivedHeartbeatRequestChunk(
|
|
46
|
+
const HeartbeatRequestChunk* receivedHeartbeatRequestChunk);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Called on received HEARTBEAT_ACK Chunk.
|
|
50
|
+
*/
|
|
51
|
+
void HandleReceivedHeartbeatAckChunk(const HeartbeatAckChunk* receivedHeartbeatAckChunk);
|
|
52
|
+
|
|
53
|
+
private:
|
|
54
|
+
void OnIntervalTimer(uint64_t& baseTimeoutMs, bool& stop);
|
|
55
|
+
|
|
56
|
+
void OnTimeoutTimer(uint64_t& baseTimeoutMs, bool& stop);
|
|
57
|
+
|
|
58
|
+
/* Pure virtual methods inherited from BackoffTimerHandle::Listener. */
|
|
59
|
+
public:
|
|
60
|
+
void OnTimer(BackoffTimerHandle* backoffTimer, uint64_t& baseTimeoutMs, bool& stop) override;
|
|
61
|
+
|
|
62
|
+
private:
|
|
63
|
+
AssociationListener& associationListener;
|
|
64
|
+
const SctpOptions sctpOptions;
|
|
65
|
+
TCBContext* tcbContext{ nullptr };
|
|
66
|
+
// The time for a connection to be idle before a heartbeat is sent.
|
|
67
|
+
const uint64_t intervalDurationMs{ 0 };
|
|
68
|
+
// Adding RTT to the duration will add some jitter, which is good in
|
|
69
|
+
// production, but less good in unit tests, which is why it can be disabled.
|
|
70
|
+
const bool intervalDurationShouldIncludeRtt{ false };
|
|
71
|
+
const std::unique_ptr<BackoffTimerHandle> intervalTimer;
|
|
72
|
+
const std::unique_ptr<BackoffTimerHandle> timeoutTimer;
|
|
73
|
+
};
|
|
74
|
+
} // namespace SCTP
|
|
75
|
+
} // namespace RTC
|
|
76
|
+
|
|
77
|
+
#endif
|
|
@@ -29,12 +29,12 @@ namespace RTC
|
|
|
29
29
|
/**
|
|
30
30
|
* Negotiated maximum number of outbound streams (OS).
|
|
31
31
|
*/
|
|
32
|
-
uint16_t
|
|
32
|
+
uint16_t negotiatedMaxOutboundStreams{ 0 };
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Negotiated maximum number of inbound streams (MIS).
|
|
36
36
|
*/
|
|
37
|
-
uint16_t
|
|
37
|
+
uint16_t negotiatedMaxInboundStreams{ 0 };
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Partial Reliability Extension.
|
|
@@ -23,7 +23,7 @@ namespace RTC
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
public:
|
|
26
|
-
PacketSender(Listener
|
|
26
|
+
PacketSender(Listener* listener, AssociationListener& associationListener);
|
|
27
27
|
|
|
28
28
|
~PacketSender();
|
|
29
29
|
|
|
@@ -42,7 +42,7 @@ namespace RTC
|
|
|
42
42
|
bool SendPacket(Packet* packet, bool writeChecksum = true);
|
|
43
43
|
|
|
44
44
|
private:
|
|
45
|
-
Listener
|
|
45
|
+
Listener* listener;
|
|
46
46
|
AssociationListener& associationListener;
|
|
47
47
|
};
|
|
48
48
|
} // namespace SCTP
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
#ifndef MS_RTC_SCTP_STREAM_RESET_HANDLER_HPP
|
|
2
|
+
#define MS_RTC_SCTP_STREAM_RESET_HANDLER_HPP
|
|
3
|
+
|
|
4
|
+
#include "common.hpp"
|
|
5
|
+
#include "RTC/SCTP/association/TCBContext.hpp"
|
|
6
|
+
#include "RTC/SCTP/common/UnwrappedSequenceNumber.hpp"
|
|
7
|
+
#include "RTC/SCTP/packet/Packet.hpp"
|
|
8
|
+
#include "RTC/SCTP/packet/chunks/ReConfigChunk.hpp"
|
|
9
|
+
#include "RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.hpp"
|
|
10
|
+
#include "RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.hpp"
|
|
11
|
+
#include "RTC/SCTP/packet/parameters/ReconfigurationResponseParameter.hpp"
|
|
12
|
+
#include "RTC/SCTP/public/AssociationListener.hpp"
|
|
13
|
+
#include "handles/BackoffTimerHandle.hpp"
|
|
14
|
+
#include <span>
|
|
15
|
+
#include <vector>
|
|
16
|
+
|
|
17
|
+
namespace RTC
|
|
18
|
+
{
|
|
19
|
+
namespace SCTP
|
|
20
|
+
{
|
|
21
|
+
/**
|
|
22
|
+
* StreamResetHandler handles sending outgoing stream reset requests (to
|
|
23
|
+
* close an SCTP stream, which translates to closing a data channel in
|
|
24
|
+
* WebRTC).
|
|
25
|
+
*
|
|
26
|
+
* It also handles incoming "outgoing stream reset requests", when the peer
|
|
27
|
+
* wants to close its streams.
|
|
28
|
+
*
|
|
29
|
+
* Resetting streams is an asynchronous operation where the client will
|
|
30
|
+
* request a request a stream to be reset, but then it might not be
|
|
31
|
+
* performed exactly at this point. First, the sender might need to discard
|
|
32
|
+
* all messages that have been enqueued for this stream, or it may select to
|
|
33
|
+
* wait until all have been sent. At least, it must wait for the currently
|
|
34
|
+
* sending fragmented message to be fully sent, because a stream can't be
|
|
35
|
+
* reset while having received half a message. In the stream reset request,
|
|
36
|
+
* the "sender's last assigned TSN" is provided, which is simply the TSN for
|
|
37
|
+
* which the receiver should've received all messages before this value,
|
|
38
|
+
* before the stream can be reset. Since fragments can get lost or sent
|
|
39
|
+
* out-of-order, the receiver of a request may not have received all the
|
|
40
|
+
* data just yet, and then it will respond to the sender: "In progress". In
|
|
41
|
+
* other words, try again. The sender will then need to start a timer and
|
|
42
|
+
* try the very same request again (but with a new sequence number) until
|
|
43
|
+
* the receiver successfully performs the operation.
|
|
44
|
+
*
|
|
45
|
+
* All this can take some time, and may be driven by timers, so the client
|
|
46
|
+
* will ultimately be notified using callbacks.
|
|
47
|
+
*
|
|
48
|
+
* In this implementation, when a stream is reset, the queued but
|
|
49
|
+
* not-yet-sent messages will be discarded, but that may change in the future.
|
|
50
|
+
* RFC8831 allows both behaviors.
|
|
51
|
+
*/
|
|
52
|
+
class StreamResetHandler : public TCBContext, public BackoffTimerHandle::Listener
|
|
53
|
+
{
|
|
54
|
+
private:
|
|
55
|
+
enum class ReqSeqNbrValidationResult : uint8_t
|
|
56
|
+
{
|
|
57
|
+
VALID,
|
|
58
|
+
RETRANSMISSION,
|
|
59
|
+
BAD_SEQUENCE_NUMBER,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Represents a stream request operation. There can only be one ongoing at
|
|
64
|
+
* any time, and a sent request may either succeed, fail or result in the
|
|
65
|
+
* receiver signaling that it can't process it right now, and then it will
|
|
66
|
+
* be retried.
|
|
67
|
+
*/
|
|
68
|
+
class CurrentRequest
|
|
69
|
+
{
|
|
70
|
+
public:
|
|
71
|
+
CurrentRequest(uint32_t senderLastAssignedTsn, std::vector<uint16_t> streamIds)
|
|
72
|
+
: reqSeqNbr(std::nullopt),
|
|
73
|
+
senderLastAssignedTsn(senderLastAssignedTsn),
|
|
74
|
+
streamIds(std::move(streamIds))
|
|
75
|
+
{
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns the current request sequence number, if this request has been
|
|
80
|
+
* sent (check `HasBeenFirst()` first). Will return 0 if the request is
|
|
81
|
+
* just prepared (or scheduled for retransmission) but not yet sent.
|
|
82
|
+
*/
|
|
83
|
+
uint32_t GetReqSeqNbr() const
|
|
84
|
+
{
|
|
85
|
+
return this->reqSeqNbr.value_or(0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The sender's last assigned TSN, from the retransmission queue. The
|
|
90
|
+
* receiver uses this to know when all data up to this TSN has been
|
|
91
|
+
* received, to know when to safely reset the stream.
|
|
92
|
+
*/
|
|
93
|
+
uint32_t GetSenderLastAssignedTsn() const
|
|
94
|
+
{
|
|
95
|
+
return senderLastAssignedTsn;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The streams that are to be reset.
|
|
100
|
+
*/
|
|
101
|
+
const std::vector<uint16_t>& GetStreamIds() const
|
|
102
|
+
{
|
|
103
|
+
return this->streamIds;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* If this request has been sent yet. If not, then it's either because
|
|
108
|
+
* it has only been prepared and not yet sent, or because the received
|
|
109
|
+
* couldn't apply the request, and then the exact same request will be
|
|
110
|
+
* retried, but with a new sequence number.
|
|
111
|
+
*/
|
|
112
|
+
bool HasBeenSent() const
|
|
113
|
+
{
|
|
114
|
+
return this->reqSeqNbr.has_value();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* If the receiver can't apply the request yet (and answered "In
|
|
119
|
+
* Progress"), this will be called to prepare the request to be
|
|
120
|
+
* retransmitted at a later time.
|
|
121
|
+
*/
|
|
122
|
+
void PrepareRetransmission()
|
|
123
|
+
{
|
|
124
|
+
this->reqSeqNbr = std::nullopt;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* If the request hasn't been sent yet, this assigns it a request
|
|
129
|
+
* number.
|
|
130
|
+
*/
|
|
131
|
+
void PrepareToSend(uint32_t newReqSeqNbr)
|
|
132
|
+
{
|
|
133
|
+
this->reqSeqNbr = newReqSeqNbr;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void SetDeferred(bool isDeferred)
|
|
137
|
+
{
|
|
138
|
+
this->isDeferred = isDeferred;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
bool IsDeferred() const
|
|
142
|
+
{
|
|
143
|
+
return this->isDeferred;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private:
|
|
147
|
+
// If this is set, this request has been sent. If it's not set, the
|
|
148
|
+
// request has been prepared, but has not yet been sent. This is
|
|
149
|
+
// typically used when the peer responded "in progress" and the same
|
|
150
|
+
// request (but a different request number) must be sent again.
|
|
151
|
+
std::optional<uint32_t> reqSeqNbr{ 0 };
|
|
152
|
+
// The sender's (that's us) last assigned TSN, from the retransmission
|
|
153
|
+
// queue.
|
|
154
|
+
uint32_t senderLastAssignedTsn{ 0 };
|
|
155
|
+
// The streams that are to be reset in this request.
|
|
156
|
+
std::vector<uint16_t> streamIds;
|
|
157
|
+
// If the request is deferred (received "In Progress"), the next timeout
|
|
158
|
+
// should not be treated as a timeout.
|
|
159
|
+
bool isDeferred{ false };
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
private:
|
|
163
|
+
using UnwrappedReConfigRequestSn = UnwrappedSequenceNumber<uint32_t>;
|
|
164
|
+
|
|
165
|
+
public:
|
|
166
|
+
StreamResetHandler(
|
|
167
|
+
AssociationListener& associationListener, TCBContext* tcbContext
|
|
168
|
+
// TODO: SCTP: Implement
|
|
169
|
+
// DataTracker* dataTracker,
|
|
170
|
+
// ReassemblyQueue* reassemblyQueue,
|
|
171
|
+
// RetransmissionQueue* retransmissionQueue
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
~StreamResetHandler() override;
|
|
175
|
+
|
|
176
|
+
public:
|
|
177
|
+
/**
|
|
178
|
+
* Initiates reset of the provided streams. While there can only be one
|
|
179
|
+
* ongoing stream reset request at any time, this method can be called at
|
|
180
|
+
* any time and also multiple times. It will enqueue requests that can't
|
|
181
|
+
* be directly fulfilled, and will asynchronously process them when any
|
|
182
|
+
* ongoing request has completed.
|
|
183
|
+
*/
|
|
184
|
+
void ResetStreams(std::span<const uint16_t> outgoingStreamIds);
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Called when handling and incoming RE-CONFIG chunk. Processes a stream
|
|
188
|
+
* reconfiguration chunk and may send a RE-CONFIG back to the peer with
|
|
189
|
+
* either 1 or 2 responses.
|
|
190
|
+
*/
|
|
191
|
+
void HandleReceivedReConfigChunk(const ReConfigChunk* receivedReConfigChunk);
|
|
192
|
+
|
|
193
|
+
private:
|
|
194
|
+
/**
|
|
195
|
+
* Called to validate a received RE-CONFIG chunk.
|
|
196
|
+
*/
|
|
197
|
+
bool ValidateReceivedReConfigChunk(const ReConfigChunk* receivedReConfigChunk);
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Creates a Reset Streams request that must be sent if returned. Will
|
|
201
|
+
* start the reconfig timer. Will return `nullptr` if there is no need
|
|
202
|
+
* to create a request (no streams to reset) or if there already is an
|
|
203
|
+
* ongoing stream reset request that hasn't completed yet.
|
|
204
|
+
*/
|
|
205
|
+
ReConfigChunk* CreateStreamResetRequest();
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Creates the actual RE-CONFIG chunk. A request (which set
|
|
209
|
+
* `currentRequest`) must have been created prior.
|
|
210
|
+
*/
|
|
211
|
+
ReConfigChunk* CreateReconfigChunk();
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Called to validate the `reqSeqNbr`, that it's the next in sequence.
|
|
215
|
+
*/
|
|
216
|
+
ReqSeqNbrValidationResult ValidateReqSeqNbr(UnwrappedReConfigRequestSn reqSeqNbr);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Called when this Association receives an outgoing stream reset request.
|
|
220
|
+
* It might either be performed straight away, or have to be deferred, and
|
|
221
|
+
* the result of that will be put in `responses`.
|
|
222
|
+
*/
|
|
223
|
+
void HandleReceivedOutgoingSsnResetRequestParameter(
|
|
224
|
+
const OutgoingSsnResetRequestParameter* receivedOutgoingSsnResetRequestParameter,
|
|
225
|
+
ReConfigChunk* reConfigChunk);
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Called when this Association receives an incoming stream reset request.
|
|
229
|
+
* This isn't really supported, but a successful response is put in
|
|
230
|
+
* `responses`.
|
|
231
|
+
*/
|
|
232
|
+
void HandleReceivedIncomingSsnResetRequestParameter(
|
|
233
|
+
const IncomingSsnResetRequestParameter* receivedIncomingSsnResetRequestParameter,
|
|
234
|
+
ReConfigChunk* reConfigChunk);
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Called when receiving a response to an outgoing stream reset request.
|
|
238
|
+
* It will either commit the stream resetting, if the operation was
|
|
239
|
+
* successful, or will schedule a retry if it was deferred. And if it
|
|
240
|
+
* failed, the operation will be rolled back.
|
|
241
|
+
*/
|
|
242
|
+
void HandleReceivedReconfigurationResponseParameter(
|
|
243
|
+
const ReconfigurationResponseParameter* receivedReconfigurationResponseParameter);
|
|
244
|
+
|
|
245
|
+
void OnReConfigTimer(uint64_t& baseTimeoutMs, bool& stop);
|
|
246
|
+
|
|
247
|
+
/* Pure virtual methods inherited from BackoffTimerHandle::Listener. */
|
|
248
|
+
public:
|
|
249
|
+
void OnTimer(BackoffTimerHandle* backoffTimer, uint64_t& baseTimeoutMs, bool& stop) override;
|
|
250
|
+
|
|
251
|
+
private:
|
|
252
|
+
AssociationListener& associationListener;
|
|
253
|
+
TCBContext* tcbContext{ nullptr };
|
|
254
|
+
// TODO: SCTP: Implement
|
|
255
|
+
// DataTracker* dataTracker{ nullptr };,
|
|
256
|
+
// ReassemblyQueue* reassemblyQueue{ nullptr };,
|
|
257
|
+
// RetransmissionQueue* retransmissionQueue{ nullptr };
|
|
258
|
+
UnwrappedReConfigRequestSn::Unwrapper incomingReConfigRequestSnUnwrapper;
|
|
259
|
+
const std::unique_ptr<BackoffTimerHandle> reConfigTimer;
|
|
260
|
+
// The next sequence number for outgoing stream requests.
|
|
261
|
+
uint32_t nextOutgoingReqSeqNbr{ 0 };
|
|
262
|
+
// The current stream request operation.
|
|
263
|
+
std::optional<CurrentRequest> currentRequest;
|
|
264
|
+
// For incoming requests. Last processed request sequence number.
|
|
265
|
+
UnwrappedReConfigRequestSn lastProcessedReqSeqNbr;
|
|
266
|
+
// The result from last processed incoming request.
|
|
267
|
+
ReconfigurationResponseParameter::Result lastProcessedReqResult;
|
|
268
|
+
};
|
|
269
|
+
} // namespace SCTP
|
|
270
|
+
} // namespace RTC
|
|
271
|
+
|
|
272
|
+
#endif
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#ifndef MS_RTC_SCTP_TCB_CONTEXT_HPP
|
|
2
|
+
#define MS_RTC_SCTP_TCB_CONTEXT_HPP
|
|
3
|
+
|
|
4
|
+
#include "common.hpp"
|
|
5
|
+
#include "RTC/SCTP/packet/Packet.hpp"
|
|
6
|
+
#include <string_view>
|
|
7
|
+
|
|
8
|
+
namespace RTC
|
|
9
|
+
{
|
|
10
|
+
namespace SCTP
|
|
11
|
+
{
|
|
12
|
+
class TCBContext
|
|
13
|
+
{
|
|
14
|
+
public:
|
|
15
|
+
virtual ~TCBContext() = default;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Indicates if the SCTP Association has been established.
|
|
19
|
+
*/
|
|
20
|
+
virtual bool IsAssociationEstablished() const = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The value of the Initiate Tag field the peer put in its INIT or
|
|
24
|
+
* INIT_ACK Chunk.
|
|
25
|
+
*/
|
|
26
|
+
virtual uint32_t GetLocalInitialTsn() const = 0;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The value of the Initial TSN field the peer put in its INIT or
|
|
30
|
+
* INIT_ACK Chunk.
|
|
31
|
+
*/
|
|
32
|
+
virtual uint32_t GetRemoteInitialTsn() const = 0;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* To be called when a RTT has been measured, to update the RTO value.
|
|
36
|
+
*/
|
|
37
|
+
virtual void ObserveRtt(uint64_t rtt) = 0;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns the Retransmission Timeout (RTO) value.
|
|
41
|
+
*/
|
|
42
|
+
virtual uint64_t GetCurrentRtoMs() const = 0;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Increments the transmission error counter, given a human readable
|
|
46
|
+
* reason.
|
|
47
|
+
*/
|
|
48
|
+
virtual bool IncrementTxErrorCounter(std::string_view reason) = 0;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Clears the transmission error counter.
|
|
52
|
+
*/
|
|
53
|
+
virtual void ClearTxErrorCounter() = 0;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns true if there have been too many retransmission errors.
|
|
57
|
+
*/
|
|
58
|
+
virtual bool HasTooManyTxErrors() const = 0;
|
|
59
|
+
|
|
60
|
+
virtual std::unique_ptr<Packet> CreatePacket() const = 0;
|
|
61
|
+
|
|
62
|
+
virtual void Send(Packet* packet) = 0;
|
|
63
|
+
};
|
|
64
|
+
} // namespace SCTP
|
|
65
|
+
} // namespace RTC
|
|
66
|
+
|
|
67
|
+
#endif
|
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
#define MS_RTC_SCTP_TRANSMISSION_CONTROL_BLOCK_HPP
|
|
3
3
|
|
|
4
4
|
#include "common.hpp"
|
|
5
|
+
#include "RTC/SCTP/association/HeartbeatHandler.hpp"
|
|
5
6
|
#include "RTC/SCTP/association/NegotiatedCapabilities.hpp"
|
|
6
7
|
#include "RTC/SCTP/association/PacketSender.hpp"
|
|
8
|
+
#include "RTC/SCTP/association/TCBContext.hpp"
|
|
7
9
|
#include "RTC/SCTP/packet/Packet.hpp"
|
|
8
10
|
#include "RTC/SCTP/public/AssociationListener.hpp"
|
|
9
11
|
#include "RTC/SCTP/public/SctpOptions.hpp"
|
|
10
12
|
#include "RTC/SCTP/tx/RetransmissionErrorCounter.hpp"
|
|
11
13
|
#include "RTC/SCTP/tx/RetransmissionTimeout.hpp"
|
|
12
14
|
#include "handles/BackoffTimerHandle.hpp"
|
|
15
|
+
#include <string_view>
|
|
13
16
|
#include <vector>
|
|
14
17
|
|
|
15
18
|
namespace RTC
|
|
@@ -22,7 +25,7 @@ namespace RTC
|
|
|
22
25
|
*
|
|
23
26
|
* @see https://datatracker.ietf.org/doc/html/rfc9260#section-14
|
|
24
27
|
*/
|
|
25
|
-
class TransmissionControlBlock : public BackoffTimerHandle::Listener
|
|
28
|
+
class TransmissionControlBlock : public TCBContext, public BackoffTimerHandle::Listener
|
|
26
29
|
{
|
|
27
30
|
public:
|
|
28
31
|
TransmissionControlBlock(
|
|
@@ -35,13 +38,23 @@ namespace RTC
|
|
|
35
38
|
uint32_t remoteInitialTsn,
|
|
36
39
|
uint32_t remoteAdvertisedReceiverWindowCredit,
|
|
37
40
|
uint64_t tieTag,
|
|
38
|
-
const NegotiatedCapabilities& negotiatedCapabilities
|
|
41
|
+
const NegotiatedCapabilities& negotiatedCapabilities,
|
|
42
|
+
std::function<bool()> isAssociationEstablished);
|
|
39
43
|
|
|
40
44
|
~TransmissionControlBlock() override;
|
|
41
45
|
|
|
42
46
|
public:
|
|
43
47
|
void Dump(int indentation = 0) const;
|
|
44
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @remarks
|
|
51
|
+
* - Implements TCBContext interface.
|
|
52
|
+
*/
|
|
53
|
+
bool IsAssociationEstablished() const override
|
|
54
|
+
{
|
|
55
|
+
return this->isAssociationEstablished();
|
|
56
|
+
}
|
|
57
|
+
|
|
45
58
|
/**
|
|
46
59
|
* The value of the Initiate Tag field we put in our INIT or INIT_ACK
|
|
47
60
|
* Chunk. Packets sent by the remote peer must include this value in
|
|
@@ -65,8 +78,11 @@ namespace RTC
|
|
|
65
78
|
/**
|
|
66
79
|
* The value of the Initial TSN field we put in our INIT or INIT_ACK
|
|
67
80
|
* Chunk.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* - Implements TCBContext interface.
|
|
68
84
|
*/
|
|
69
|
-
uint32_t GetLocalInitialTsn() const
|
|
85
|
+
uint32_t GetLocalInitialTsn() const override
|
|
70
86
|
{
|
|
71
87
|
return this->localInitialTsn;
|
|
72
88
|
}
|
|
@@ -74,8 +90,11 @@ namespace RTC
|
|
|
74
90
|
/**
|
|
75
91
|
* The value of the Initial TSN field the peer put in its INIT or
|
|
76
92
|
* INIT_ACK Chunk.
|
|
93
|
+
*
|
|
94
|
+
* @remarks
|
|
95
|
+
* - Implements TCBContext interface.
|
|
77
96
|
*/
|
|
78
|
-
uint32_t GetRemoteInitialTsn() const
|
|
97
|
+
uint32_t GetRemoteInitialTsn() const override
|
|
79
98
|
{
|
|
80
99
|
return this->remoteInitialTsn;
|
|
81
100
|
}
|
|
@@ -105,9 +124,17 @@ namespace RTC
|
|
|
105
124
|
return this->negotiatedCapabilities;
|
|
106
125
|
}
|
|
107
126
|
|
|
108
|
-
|
|
127
|
+
/**
|
|
128
|
+
* @remarks
|
|
129
|
+
* - Implements TCBContext interface.
|
|
130
|
+
*/
|
|
131
|
+
void ObserveRtt(uint64_t rtt) override;
|
|
109
132
|
|
|
110
|
-
|
|
133
|
+
/**
|
|
134
|
+
* @remarks
|
|
135
|
+
* - Implements TCBContext interface.
|
|
136
|
+
*/
|
|
137
|
+
uint64_t GetCurrentRtoMs() const override
|
|
111
138
|
{
|
|
112
139
|
return this->rto.GetRtoMs();
|
|
113
140
|
}
|
|
@@ -117,10 +144,25 @@ namespace RTC
|
|
|
117
144
|
return this->rto.GetSrttMs();
|
|
118
145
|
}
|
|
119
146
|
|
|
120
|
-
|
|
147
|
+
/**
|
|
148
|
+
* @remarks
|
|
149
|
+
* - Implements TCBContext interface.
|
|
150
|
+
*/
|
|
151
|
+
std::unique_ptr<Packet> CreatePacket() const override;
|
|
121
152
|
|
|
122
153
|
std::unique_ptr<Packet> CreatePacketWithVerificationTag(uint32_t verificationTag) const;
|
|
123
154
|
|
|
155
|
+
/**
|
|
156
|
+
* @remarks
|
|
157
|
+
* - Implements TCBContext interface.
|
|
158
|
+
*/
|
|
159
|
+
void Send(Packet* packet) override;
|
|
160
|
+
|
|
161
|
+
HeartbeatHandler& GetHeartbeatHandler()
|
|
162
|
+
{
|
|
163
|
+
return this->heartbeatHandler;
|
|
164
|
+
}
|
|
165
|
+
|
|
124
166
|
void SetRemoteStateCookie(std::vector<uint8_t> remoteStateCookie);
|
|
125
167
|
|
|
126
168
|
void ClearRemoteStateCookie();
|
|
@@ -132,9 +174,34 @@ namespace RTC
|
|
|
132
174
|
|
|
133
175
|
void MaySendSackChunk();
|
|
134
176
|
|
|
135
|
-
|
|
136
|
-
|
|
177
|
+
/**
|
|
178
|
+
* @remarks
|
|
179
|
+
* - Implements TCBContext interface.
|
|
180
|
+
*/
|
|
181
|
+
bool IncrementTxErrorCounter(std::string_view reason) override
|
|
182
|
+
{
|
|
183
|
+
return this->txErrorCounter.Increment(reason);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @remarks
|
|
188
|
+
* - Implements TCBContext interface.
|
|
189
|
+
*/
|
|
190
|
+
void ClearTxErrorCounter() override
|
|
191
|
+
{
|
|
192
|
+
return this->txErrorCounter.Clear();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @remarks
|
|
197
|
+
* - Implements TCBContext interface.
|
|
198
|
+
*/
|
|
199
|
+
bool HasTooManyTxErrors() const override
|
|
200
|
+
{
|
|
201
|
+
return this->txErrorCounter.IsExhausted();
|
|
202
|
+
}
|
|
137
203
|
|
|
204
|
+
private:
|
|
138
205
|
void OnT3RtxTimer(uint64_t& baseTimeoutMs, bool& stop);
|
|
139
206
|
|
|
140
207
|
void OnDelayedAckTimer(uint64_t& baseTimeoutMs, bool& stop);
|
|
@@ -155,16 +222,19 @@ namespace RTC
|
|
|
155
222
|
// Nonce, used to detect reconnections.
|
|
156
223
|
uint64_t tieTag{ 0 };
|
|
157
224
|
NegotiatedCapabilities negotiatedCapabilities;
|
|
158
|
-
|
|
225
|
+
std::function<bool()> isAssociationEstablished;
|
|
226
|
+
// The data retransmission timer.
|
|
159
227
|
const std::unique_ptr<BackoffTimerHandle> t3RtxTimer;
|
|
160
228
|
// Delayed ack timer, which triggers when acks should be sent (when
|
|
161
229
|
// delayed).
|
|
162
230
|
const std::unique_ptr<BackoffTimerHandle> delayedAckTimer;
|
|
163
231
|
RetransmissionTimeout rto;
|
|
164
232
|
RetransmissionErrorCounter txErrorCounter;
|
|
233
|
+
HeartbeatHandler heartbeatHandler;
|
|
165
234
|
// Rate limiting of FORWARD_TSN. Next can be sent at or after this
|
|
166
235
|
// timestamp.
|
|
167
|
-
|
|
236
|
+
// TODO: SCTP: Uncomment.
|
|
237
|
+
// uint64_t limitForwardTsnUntilMs{ 0 };
|
|
168
238
|
// Only valid when state is State::COOKIE_ECHOED. In this state, the
|
|
169
239
|
// Association must wait for COOKIE_ACK to continue sending any packets (not
|
|
170
240
|
// including a COOKIE_ECHO). So if this state cookie is present, the
|