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.
Files changed (91) hide show
  1. package/README.md +4 -4
  2. package/node/lib/Worker.d.ts +1 -1
  3. package/node/lib/Worker.d.ts.map +1 -1
  4. package/node/lib/Worker.js +8 -2
  5. package/node/lib/WorkerTypes.d.ts +8 -4
  6. package/node/lib/WorkerTypes.d.ts.map +1 -1
  7. package/node/lib/index.d.ts +1 -1
  8. package/node/lib/index.d.ts.map +1 -1
  9. package/node/lib/index.js +2 -1
  10. package/node/lib/sctpParametersTypes.d.ts +3 -13
  11. package/node/lib/sctpParametersTypes.d.ts.map +1 -1
  12. package/node/lib/test/test-PlainTransport.js +8 -3
  13. package/node/lib/test/test-WebRtcTransport.js +9 -4
  14. package/package.json +10 -10
  15. package/worker/Makefile +0 -4
  16. package/worker/fuzzer/src/fuzzer.cpp +6 -5
  17. package/worker/include/RTC/DataConsumer.hpp +4 -14
  18. package/worker/include/RTC/SCTP/TODO_SCTP.md +18 -10
  19. package/worker/include/RTC/SCTP/association/Association.hpp +39 -31
  20. package/worker/include/RTC/SCTP/association/{AssociationDeferredListener.hpp → AssociationListenerDeferrer.hpp} +10 -8
  21. package/worker/include/RTC/SCTP/association/HeartbeatHandler.hpp +77 -0
  22. package/worker/include/RTC/SCTP/association/NegotiatedCapabilities.hpp +2 -2
  23. package/worker/include/RTC/SCTP/association/PacketSender.hpp +2 -2
  24. package/worker/include/RTC/SCTP/association/StateCookie.hpp +2 -2
  25. package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +272 -0
  26. package/worker/include/RTC/SCTP/association/TCBContext.hpp +67 -0
  27. package/worker/include/RTC/SCTP/association/TransmissionControlBlock.hpp +81 -11
  28. package/worker/include/RTC/SCTP/common/UnwrappedSequenceNumber.hpp +274 -0
  29. package/worker/include/RTC/SCTP/packet/Chunk.hpp +0 -1
  30. package/worker/include/RTC/SCTP/packet/UserData.hpp +1 -0
  31. package/worker/include/RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.hpp +14 -10
  32. package/worker/include/RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.hpp +14 -10
  33. package/worker/include/RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp +13 -2
  34. package/worker/include/RTC/SCTP/public/AssociationInterface.hpp +7 -1
  35. package/worker/include/RTC/SCTP/public/AssociationListener.hpp +11 -0
  36. package/worker/include/RTC/SCTP/public/Message.hpp +1 -0
  37. package/worker/include/RTC/SCTP/public/SctpOptions.hpp +4 -4
  38. package/worker/include/RTC/SctpAssociation.hpp +2 -2
  39. package/worker/include/RTC/Transport.hpp +9 -13
  40. package/worker/include/Settings.hpp +2 -1
  41. package/worker/include/Utils.hpp +130 -6
  42. package/worker/meson.build +10 -39
  43. package/worker/meson_options.txt +0 -1
  44. package/worker/scripts/package-lock.json +6 -6
  45. package/worker/src/DepLibUring.cpp +1 -1
  46. package/worker/src/RTC/DataConsumer.cpp +5 -29
  47. package/worker/src/RTC/PipeTransport.cpp +15 -12
  48. package/worker/src/RTC/PlainTransport.cpp +15 -12
  49. package/worker/src/RTC/RTP/RetransmissionBuffer.cpp +5 -5
  50. package/worker/src/RTC/RTP/RtpStream.cpp +2 -2
  51. package/worker/src/RTC/RTP/RtxStream.cpp +1 -1
  52. package/worker/src/RTC/RateCalculator.cpp +5 -5
  53. package/worker/src/RTC/SCTP/association/Association.cpp +218 -148
  54. package/worker/src/RTC/SCTP/association/{AssociationDeferredListener.cpp → AssociationListenerDeferrer.cpp} +38 -30
  55. package/worker/src/RTC/SCTP/association/HeartbeatHandler.cpp +244 -0
  56. package/worker/src/RTC/SCTP/association/NegotiatedCapabilities.cpp +8 -6
  57. package/worker/src/RTC/SCTP/association/PacketSender.cpp +7 -2
  58. package/worker/src/RTC/SCTP/association/StateCookie.cpp +8 -8
  59. package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +512 -0
  60. package/worker/src/RTC/SCTP/association/TransmissionControlBlock.cpp +45 -39
  61. package/worker/src/RTC/SCTP/packet/chunks/SackChunk.cpp +1 -1
  62. package/worker/src/RTC/SCTP/packet/errorCauses/UserInitiatedAbortErrorCause.cpp +1 -1
  63. package/worker/src/RTC/SCTP/packet/parameters/IncomingSsnResetRequestParameter.cpp +22 -5
  64. package/worker/src/RTC/SCTP/packet/parameters/OutgoingSsnResetRequestParameter.cpp +22 -5
  65. package/worker/src/RTC/SCTP/tx/RetransmissionErrorCounter.cpp +1 -1
  66. package/worker/src/RTC/SctpAssociation.cpp +1 -2
  67. package/worker/src/RTC/SeqManager.cpp +4 -4
  68. package/worker/src/RTC/Transport.cpp +247 -134
  69. package/worker/src/RTC/WebRtcTransport.cpp +9 -5
  70. package/worker/src/Settings.cpp +21 -1
  71. package/worker/src/Worker.cpp +13 -10
  72. package/worker/src/lib.cpp +11 -8
  73. package/worker/tasks.py +2 -35
  74. package/worker/test/src/RTC/SCTP/association/TestNegotiatedCapabilities.cpp +13 -12
  75. package/worker/test/src/RTC/SCTP/association/TestStateCookie.cpp +20 -20
  76. package/worker/test/src/RTC/SCTP/common/TestUnwrappedSequenceNumber.cpp +210 -0
  77. package/worker/test/src/RTC/SCTP/packet/chunks/TestAbortAssociationChunk.cpp +2 -2
  78. package/worker/test/src/RTC/SCTP/packet/chunks/TestHeartbeatAckChunk.cpp +9 -4
  79. package/worker/test/src/RTC/SCTP/packet/chunks/TestHeartbeatRequestChunk.cpp +5 -0
  80. package/worker/test/src/RTC/SCTP/packet/chunks/TestInitAckChunk.cpp +1 -1
  81. package/worker/test/src/RTC/SCTP/packet/chunks/TestInitChunk.cpp +5 -5
  82. package/worker/test/src/RTC/SCTP/packet/chunks/TestReConfigChunk.cpp +19 -20
  83. package/worker/test/src/RTC/SCTP/packet/chunks/TestUnknownChunk.cpp +3 -0
  84. package/worker/test/src/RTC/SCTP/packet/errorCauses/TestUnknownErrorCause.cpp +3 -0
  85. package/worker/test/src/RTC/SCTP/packet/parameters/TestIncomingSsnResetRequestParameter.cpp +24 -27
  86. package/worker/test/src/RTC/SCTP/packet/parameters/TestOutgoingSsnResetRequestParameter.cpp +25 -30
  87. package/worker/test/src/RTC/SCTP/packet/parameters/TestStateCookieParameter.cpp +8 -6
  88. package/worker/test/src/RTC/SCTP/packet/parameters/TestSupportedExtensionsParameter.cpp +12 -0
  89. package/worker/test/src/RTC/SCTP/packet/parameters/TestZeroChecksumAcceptableParameter.cpp +5 -8
  90. package/worker/test/src/Utils/TestNumber.cpp +119 -49
  91. package/worker/test/src/tests.cpp +11 -8
@@ -1,30 +1,31 @@
1
- #define MS_CLASS "RTC::SCTP::AssociationDeferredListener"
1
+ #define MS_CLASS "RTC::SCTP::AssociationListenerDeferrer"
2
2
  // #define MS_LOG_DEV_LEVEL 3
3
3
 
4
- #include "RTC/SCTP/association/AssociationDeferredListener.hpp"
4
+ #include "RTC/SCTP/association/AssociationListenerDeferrer.hpp"
5
5
  #include "Logger.hpp"
6
6
 
7
7
  namespace RTC
8
8
  {
9
9
  namespace SCTP
10
10
  {
11
- AssociationDeferredListener::ScopedDeferred::ScopedDeferred(
12
- AssociationDeferredListener& deferredListener)
13
- : deferredListener(deferredListener)
11
+ AssociationListenerDeferrer::ScopedDeferrer::ScopedDeferrer(
12
+ AssociationListenerDeferrer& listenerDeferrer)
13
+ : listenerDeferrer(listenerDeferrer)
14
14
  {
15
15
  MS_TRACE();
16
16
 
17
- this->deferredListener.SetReady();
17
+ this->listenerDeferrer.SetReady();
18
18
  }
19
19
 
20
- AssociationDeferredListener::ScopedDeferred::~ScopedDeferred()
20
+ // NOLINTNEXTLINE(bugprone-exception-escape)
21
+ AssociationListenerDeferrer::ScopedDeferrer::~ScopedDeferrer()
21
22
  {
22
23
  MS_TRACE();
23
24
 
24
- this->deferredListener.TriggerDeferredCallbacks();
25
+ this->listenerDeferrer.TriggerDeferredCallbacks();
25
26
  }
26
27
 
27
- AssociationDeferredListener::AssociationDeferredListener(AssociationListener* innerListener)
28
+ AssociationListenerDeferrer::AssociationListenerDeferrer(AssociationListener* innerListener)
28
29
  : innerListener(innerListener)
29
30
  {
30
31
  MS_TRACE();
@@ -32,21 +33,20 @@ namespace RTC
32
33
  this->deferredCallbacks.reserve(8);
33
34
  }
34
35
 
35
- void AssociationDeferredListener::SetReady()
36
+ void AssociationListenerDeferrer::SetReady()
36
37
  {
37
38
  MS_TRACE();
38
39
 
40
+ MS_ASSERT(!this->ready, "already ready");
41
+
39
42
  this->ready = true;
40
43
  }
41
44
 
42
- void AssociationDeferredListener::TriggerDeferredCallbacks()
45
+ void AssociationListenerDeferrer::TriggerDeferredCallbacks()
43
46
  {
44
47
  MS_TRACE();
45
48
 
46
- if (!this->ready)
47
- {
48
- return;
49
- }
49
+ MS_ASSERT(this->ready, "not ready");
50
50
 
51
51
  this->ready = false;
52
52
 
@@ -72,17 +72,15 @@ namespace RTC
72
72
  }
73
73
  }
74
74
 
75
- bool AssociationDeferredListener::OnAssociationSendData(const uint8_t* data, size_t len)
75
+ bool AssociationListenerDeferrer::OnAssociationSendData(const uint8_t* data, size_t len)
76
76
  {
77
77
  MS_TRACE();
78
78
 
79
- MS_ASSERT(this->ready, "not ready");
80
-
81
79
  // Will not be deferred but called directly.
82
80
  return this->innerListener->OnAssociationSendData(data, len);
83
81
  }
84
82
 
85
- void AssociationDeferredListener::OnAssociationConnecting()
83
+ void AssociationListenerDeferrer::OnAssociationConnecting()
86
84
  {
87
85
  MS_TRACE();
88
86
 
@@ -96,7 +94,7 @@ namespace RTC
96
94
  std::monostate{});
97
95
  }
98
96
 
99
- void AssociationDeferredListener::OnAssociationConnected()
97
+ void AssociationListenerDeferrer::OnAssociationConnected()
100
98
  {
101
99
  MS_TRACE();
102
100
 
@@ -110,7 +108,7 @@ namespace RTC
110
108
  std::monostate{});
111
109
  }
112
110
 
113
- void AssociationDeferredListener::OnAssociationFailed(
111
+ void AssociationListenerDeferrer::OnAssociationFailed(
114
112
  Types::ErrorKind errorKind, std::string_view errorMessage)
115
113
  {
116
114
  MS_TRACE();
@@ -126,7 +124,7 @@ namespace RTC
126
124
  Error{ .errorKind = errorKind, .message = std::string(errorMessage) });
127
125
  }
128
126
 
129
- void AssociationDeferredListener::OnAssociationClosed(
127
+ void AssociationListenerDeferrer::OnAssociationClosed(
130
128
  Types::ErrorKind errorKind, std::string_view errorMessage)
131
129
  {
132
130
  MS_TRACE();
@@ -142,7 +140,7 @@ namespace RTC
142
140
  Error{ .errorKind = errorKind, .message = std::string(errorMessage) });
143
141
  }
144
142
 
145
- void AssociationDeferredListener::OnAssociationRestarted()
143
+ void AssociationListenerDeferrer::OnAssociationRestarted()
146
144
  {
147
145
  MS_TRACE();
148
146
 
@@ -156,7 +154,7 @@ namespace RTC
156
154
  std::monostate{});
157
155
  }
158
156
 
159
- void AssociationDeferredListener::OnAssociationError(
157
+ void AssociationListenerDeferrer::OnAssociationError(
160
158
  Types::ErrorKind errorKind, std::string_view errorMessage)
161
159
  {
162
160
  MS_TRACE();
@@ -172,7 +170,7 @@ namespace RTC
172
170
  Error{ .errorKind = errorKind, .message = std::string(errorMessage) });
173
171
  }
174
172
 
175
- void AssociationDeferredListener::OnAssociationMessageReceived(Message message)
173
+ void AssociationListenerDeferrer::OnAssociationMessageReceived(Message message)
176
174
  {
177
175
  MS_TRACE();
178
176
 
@@ -186,7 +184,7 @@ namespace RTC
186
184
  std::move(message));
187
185
  }
188
186
 
189
- void AssociationDeferredListener::OnAssociationStreamsResetPerformed(
187
+ void AssociationListenerDeferrer::OnAssociationStreamsResetPerformed(
190
188
  std::span<const uint16_t> outboundStreamIds)
191
189
  {
192
190
  MS_TRACE();
@@ -202,7 +200,7 @@ namespace RTC
202
200
  StreamReset{ .streamIds = { outboundStreamIds.begin(), outboundStreamIds.end() } });
203
201
  }
204
202
 
205
- void AssociationDeferredListener::OnAssociationStreamsResetFailed(
203
+ void AssociationListenerDeferrer::OnAssociationStreamsResetFailed(
206
204
  std::span<const uint16_t> outboundStreamIds, std::string_view errorMessage)
207
205
  {
208
206
  MS_TRACE();
@@ -219,7 +217,7 @@ namespace RTC
219
217
  .errorMessage = std::string(errorMessage) });
220
218
  }
221
219
 
222
- void AssociationDeferredListener::OnAssociationInboundStreamsReset(
220
+ void AssociationListenerDeferrer::OnAssociationInboundStreamsReset(
223
221
  std::span<const uint16_t> inboundStreamIds)
224
222
  {
225
223
  MS_TRACE();
@@ -235,9 +233,10 @@ namespace RTC
235
233
  StreamReset{ .streamIds = { inboundStreamIds.begin(), inboundStreamIds.end() } });
236
234
  }
237
235
 
238
- void AssociationDeferredListener::OnAssociationStreamBufferedAmountLow(uint16_t streamId)
236
+ void AssociationListenerDeferrer::OnAssociationStreamBufferedAmountLow(uint16_t streamId)
239
237
  {
240
238
  MS_TRACE();
239
+ ;
241
240
 
242
241
  MS_ASSERT(this->ready, "not ready");
243
242
 
@@ -249,7 +248,7 @@ namespace RTC
249
248
  streamId);
250
249
  }
251
250
 
252
- void AssociationDeferredListener::OnAssociationTotalBufferedAmountLow()
251
+ void AssociationListenerDeferrer::OnAssociationTotalBufferedAmountLow()
253
252
  {
254
253
  MS_TRACE();
255
254
 
@@ -262,5 +261,14 @@ namespace RTC
262
261
  },
263
262
  std::monostate{});
264
263
  }
264
+
265
+ bool AssociationListenerDeferrer::OnAssociationIsTransportReadyForSctp()
266
+ {
267
+ MS_TRACE();
268
+ ;
269
+
270
+ // Will not be deferred but called directly.
271
+ return this->innerListener->OnAssociationIsTransportReadyForSctp();
272
+ }
265
273
  } // namespace SCTP
266
274
  } // namespace RTC
@@ -0,0 +1,244 @@
1
+ #define MS_CLASS "RTC::SCTP::HeartbeatHandler"
2
+ // TODO: SCTP: COMMENT
3
+ #define MS_LOG_DEV_LEVEL 3
4
+
5
+ #include "RTC/SCTP/association/HeartbeatHandler.hpp"
6
+ #include "DepLibUV.hpp"
7
+ #include "Logger.hpp"
8
+ #include "Utils.hpp"
9
+ #include "RTC/SCTP/packet/parameters/HeartbeatInfoParameter.hpp"
10
+ #include "RTC/SCTP/public/SctpTypes.hpp"
11
+ #include <string>
12
+
13
+ namespace RTC
14
+ {
15
+ namespace SCTP
16
+ {
17
+ /* Static. */
18
+
19
+ static constexpr int HeartbeatInfoLength{ 8 };
20
+
21
+ /* Instance methods. */
22
+
23
+ HeartbeatHandler::HeartbeatHandler(
24
+ AssociationListener& associationListener, const SctpOptions& sctpOptions, TCBContext* tcbContext)
25
+ : associationListener(associationListener),
26
+ sctpOptions(sctpOptions),
27
+ tcbContext(tcbContext),
28
+ intervalDurationMs(sctpOptions.heartbeatIntervalMs),
29
+ intervalDurationShouldIncludeRtt(sctpOptions.heartbeatIntervalIncludeRtt),
30
+ intervalTimer(
31
+ std::make_unique<BackoffTimerHandle>(
32
+ /*listener*/ this,
33
+ /*baseTimeoutMs*/ sctpOptions.initialRtoMs,
34
+ /*backoffAlgorithm*/ BackoffTimerHandle::BackoffAlgorithm::EXPONENTIAL,
35
+ /*maxBackoffTimeoutMs*/ sctpOptions.timerMaxBackoffTimeoutMs,
36
+ /*maxRestarts*/ std::nullopt)),
37
+ timeoutTimer(
38
+ std::make_unique<BackoffTimerHandle>(
39
+ /*listener*/ this,
40
+ /*baseTimeoutMs*/ sctpOptions.initialRtoMs,
41
+ /*backoffAlgorithm*/ BackoffTimerHandle::BackoffAlgorithm::FIXED,
42
+ /*maxBackoffTimeoutMs*/ std::nullopt,
43
+ /*maxRestarts*/ 0))
44
+ {
45
+ MS_TRACE();
46
+ }
47
+
48
+ HeartbeatHandler::~HeartbeatHandler()
49
+ {
50
+ MS_TRACE();
51
+ }
52
+
53
+ void HeartbeatHandler::RestartTimer()
54
+ {
55
+ MS_TRACE();
56
+
57
+ // Heartbeating has been disabled.
58
+ if (this->intervalDurationMs == 0)
59
+ {
60
+ return;
61
+ }
62
+
63
+ if (intervalDurationShouldIncludeRtt)
64
+ {
65
+ this->intervalTimer->SetBaseTimeoutMs(
66
+ this->intervalDurationMs + this->tcbContext->GetCurrentRtoMs());
67
+ }
68
+ else
69
+ {
70
+ this->intervalTimer->SetBaseTimeoutMs(this->intervalDurationMs);
71
+ }
72
+
73
+ this->intervalTimer->Start();
74
+ }
75
+
76
+ void HeartbeatHandler::HandleReceivedHeartbeatRequestChunk(
77
+ const HeartbeatRequestChunk* receivedHeartbeatRequestChunk)
78
+ {
79
+ MS_TRACE();
80
+
81
+ // https://datatracker.ietf.org/doc/html/rfc9260#section-8.3
82
+ //
83
+ // "The receiver of the HEARTBEAT chunk SHOULD immediately respond with a
84
+ // HEARTBEAT ACK chunk that contains the Heartbeat Information TLV,
85
+ // together with any other received TLVs, copied unchanged from the
86
+ // received HEARTBEAT chunk."
87
+ auto packet = this->tcbContext->CreatePacket();
88
+ auto* heartbeatAckChunk = packet->BuildChunkInPlace<HeartbeatAckChunk>();
89
+
90
+ // Here we have to extract all Parameters from receivedHeartbeatRequestChunk
91
+ // and add them into heartbeatAckChunk.
92
+ for (auto it = receivedHeartbeatRequestChunk->ParametersBegin();
93
+ it != receivedHeartbeatRequestChunk->ParametersEnd();
94
+ ++it)
95
+ {
96
+ const auto* parameter = *it;
97
+
98
+ heartbeatAckChunk->AddParameter(parameter);
99
+ }
100
+
101
+ heartbeatAckChunk->Consolidate();
102
+
103
+ this->tcbContext->Send(packet.get());
104
+ }
105
+
106
+ void HeartbeatHandler::HandleReceivedHeartbeatAckChunk(
107
+ const HeartbeatAckChunk* receivedHeartbeatAckChunk)
108
+ {
109
+ MS_TRACE();
110
+
111
+ this->timeoutTimer->Stop();
112
+
113
+ const auto* heartbeatInfoParameter =
114
+ receivedHeartbeatAckChunk->GetFirstParameterOfType<HeartbeatInfoParameter>();
115
+
116
+ if (!heartbeatInfoParameter)
117
+ {
118
+ this->associationListener.OnAssociationError(
119
+ Types::ErrorKind::PARSE_FAILED,
120
+ "ignoring HEARTBEAT_ACK chunk without Heartbeat Info parameter");
121
+
122
+ return;
123
+ }
124
+
125
+ const auto* info = heartbeatInfoParameter->GetInfo();
126
+ const uint16_t infoLen = heartbeatInfoParameter->GetInfoLength();
127
+
128
+ if (!info)
129
+ {
130
+ this->associationListener.OnAssociationError(
131
+ Types::ErrorKind::PARSE_FAILED, "ignoring Heartbeat Info parameter without info field");
132
+
133
+ return;
134
+ }
135
+ else if (infoLen != HeartbeatInfoLength)
136
+ {
137
+ this->associationListener.OnAssociationError(
138
+ Types::ErrorKind::PARSE_FAILED, "ignoring Heartbeat Info parameter with wrong length");
139
+
140
+ return;
141
+ }
142
+
143
+ const uint64_t createdAtMs = Utils::Byte::Get8Bytes(info, 0);
144
+ const uint64_t nowMs = DepLibUV::GetTimeMs();
145
+
146
+ if (createdAtMs > 0 && createdAtMs <= nowMs)
147
+ {
148
+ const uint64_t rtt = nowMs - createdAtMs;
149
+
150
+ MS_DEBUG_DEV("valid HEARTBEAT_ACK Chunk received, calling ObserveRtt(%" PRIu64 ")", rtt);
151
+
152
+ this->tcbContext->ObserveRtt(rtt);
153
+ }
154
+ else
155
+ {
156
+ MS_WARN_DEV(
157
+ "ignoring received HEARTBEAT_ACK Chunk with invalid info content [createdAtMs:%" PRIu64
158
+ ", nowMs:%" PRIu64 "]",
159
+ createdAtMs,
160
+ nowMs);
161
+ }
162
+
163
+ // https://datatracker.ietf.org/doc/html/rfc9260#section-8.1
164
+ //
165
+ // "When a HEARTBEAT ACK chunk is received from the peer endpoint, the
166
+ // counter SHOULD also be reset."
167
+ this->tcbContext->ClearTxErrorCounter();
168
+ }
169
+
170
+ void HeartbeatHandler::OnIntervalTimer(uint64_t& /*baseTimeoutMs*/, bool& /*stop*/)
171
+ {
172
+ MS_TRACE();
173
+
174
+ if (!this->tcbContext->IsAssociationEstablished())
175
+ {
176
+ MS_DEBUG_DEV("won't send HEARTBEAT_REQUEST when SCTP Association is not established");
177
+
178
+ return;
179
+ }
180
+
181
+ const auto maxRestarts = this->intervalTimer->GetMaxRestarts();
182
+
183
+ MS_DEBUG_TAG(
184
+ sctp,
185
+ "interval timer has expired %zu/%s]",
186
+ this->intervalTimer->GetExpirationCount(),
187
+ maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
188
+
189
+ this->timeoutTimer->SetBaseTimeoutMs(this->tcbContext->GetCurrentRtoMs());
190
+ this->timeoutTimer->Start();
191
+
192
+ alignas(8) uint8_t info[HeartbeatInfoLength];
193
+ const uint64_t nowMs = DepLibUV::GetTimeMs();
194
+
195
+ Utils::Byte::Set8Bytes(info, 0, nowMs);
196
+
197
+ auto packet = this->tcbContext->CreatePacket();
198
+ auto* heartbeatRequestChunk = packet->BuildChunkInPlace<HeartbeatRequestChunk>();
199
+ auto* heartbeatInfoParameter =
200
+ heartbeatRequestChunk->BuildParameterInPlace<HeartbeatInfoParameter>();
201
+
202
+ heartbeatInfoParameter->SetInfo(info, HeartbeatInfoLength);
203
+ heartbeatInfoParameter->Consolidate();
204
+ heartbeatRequestChunk->Consolidate();
205
+
206
+ MS_DEBUG_DEV("sending HEARTBEAT_REQUEST Chunk with info content [nowMs:%" PRIu64 "]", nowMs);
207
+
208
+ this->tcbContext->Send(packet.get());
209
+ }
210
+
211
+ void HeartbeatHandler::OnTimeoutTimer(uint64_t& /*baseTimeoutMs*/, bool& /*stop*/)
212
+ {
213
+ MS_TRACE();
214
+
215
+ const auto maxRestarts = this->timeoutTimer->GetMaxRestarts();
216
+
217
+ MS_DEBUG_TAG(
218
+ sctp,
219
+ "timeout timer has expired %zu/%s]",
220
+ this->timeoutTimer->GetExpirationCount(),
221
+ maxRestarts ? std::to_string(maxRestarts.value()).c_str() : "Infinite");
222
+
223
+ // Note that the timeout timer is not restarted. It will be started again when
224
+ // the interval timer expires.
225
+ MS_ASSERT(!this->timeoutTimer->IsRunning(), "timeout timer shouldn't be running");
226
+
227
+ this->tcbContext->IncrementTxErrorCounter("hearbeat timeout");
228
+ }
229
+
230
+ void HeartbeatHandler::OnTimer(BackoffTimerHandle* backoffTimer, uint64_t& baseTimeoutMs, bool& stop)
231
+ {
232
+ MS_TRACE();
233
+
234
+ if (backoffTimer == this->intervalTimer.get())
235
+ {
236
+ OnIntervalTimer(baseTimeoutMs, stop);
237
+ }
238
+ else if (backoffTimer == this->timeoutTimer.get())
239
+ {
240
+ OnTimeoutTimer(baseTimeoutMs, stop);
241
+ }
242
+ }
243
+ } // namespace SCTP
244
+ } // namespace RTC
@@ -27,11 +27,11 @@ namespace RTC
27
27
  const auto* remoteZeroChecksumAcceptableParameter =
28
28
  remoteChunk->template GetFirstParameterOfType<ZeroChecksumAcceptableParameter>();
29
29
 
30
- negotiatedCapabilities.maxOutboundStreams =
31
- std::min(sctpOptions.maxOutboundStreams, remoteChunk->GetNumberOfInboundStreams());
30
+ negotiatedCapabilities.negotiatedMaxOutboundStreams =
31
+ std::min(sctpOptions.announcedMaxOutboundStreams, remoteChunk->GetNumberOfInboundStreams());
32
32
 
33
- negotiatedCapabilities.maxInboundStreams =
34
- std::min(sctpOptions.maxInboundStreams, remoteChunk->GetNumberOfOutboundStreams());
33
+ negotiatedCapabilities.negotiatedMaxInboundStreams =
34
+ std::min(sctpOptions.announcedMaxInboundStreams, remoteChunk->GetNumberOfOutboundStreams());
35
35
 
36
36
  // Partial Reliability Extension is negotiated if we desire it and
37
37
  // peer announces support via Forward-TSN-Supported Parameter or via
@@ -75,8 +75,10 @@ namespace RTC
75
75
  MS_TRACE();
76
76
 
77
77
  MS_DUMP_CLEAN(indentation, "<SCTP::NegotiatedCapabilities>");
78
- MS_DUMP_CLEAN(indentation, " max outbound streams: %" PRIu16, this->maxOutboundStreams);
79
- MS_DUMP_CLEAN(indentation, " max inbound streams: %" PRIu16, this->maxInboundStreams);
78
+ MS_DUMP_CLEAN(
79
+ indentation, " negotiated max outbound streams: %" PRIu16, this->negotiatedMaxOutboundStreams);
80
+ MS_DUMP_CLEAN(
81
+ indentation, " negotiated max inbound streams: %" PRIu16, this->negotiatedMaxInboundStreams);
80
82
  MS_DUMP_CLEAN(indentation, " partial reliability: %s", this->partialReliability ? "yes" : "no");
81
83
  MS_DUMP_CLEAN(
82
84
  indentation, " message interleaving: %s", this->messageInterleaving ? "yes" : "no");
@@ -8,7 +8,7 @@ namespace RTC
8
8
  {
9
9
  namespace SCTP
10
10
  {
11
- PacketSender::PacketSender(Listener& listener, AssociationListener& associationListener)
11
+ PacketSender::PacketSender(Listener* listener, AssociationListener& associationListener)
12
12
  : listener(listener), associationListener(associationListener)
13
13
  {
14
14
  MS_TRACE();
@@ -38,7 +38,12 @@ namespace RTC
38
38
  const bool sent =
39
39
  this->associationListener.OnAssociationSendData(packet->GetBuffer(), packet->GetLength());
40
40
 
41
- this->listener.OnPacketSenderPacketSent(this, packet, sent);
41
+ this->listener->OnPacketSenderPacketSent(this, packet, sent);
42
+
43
+ if (!sent)
44
+ {
45
+ MS_WARN_TAG(sctp, "coudln't send SCTP Packet");
46
+ }
42
47
 
43
48
  return sent;
44
49
  }
@@ -115,10 +115,10 @@ namespace RTC
115
115
  negotiatedCapabilitiesField->bitC = negotiatedCapabilities.reConfig;
116
116
  negotiatedCapabilitiesField->bitD = negotiatedCapabilities.zeroChecksum;
117
117
  negotiatedCapabilitiesField->magic2 = htons(StateCookie::Magic2);
118
- negotiatedCapabilitiesField->maxOutboundStreams =
119
- htons(negotiatedCapabilities.maxOutboundStreams);
120
- negotiatedCapabilitiesField->maxInboundStreams =
121
- htons(negotiatedCapabilities.maxInboundStreams);
118
+ negotiatedCapabilitiesField->negotiatedMaxOutboundStreams =
119
+ htons(negotiatedCapabilities.negotiatedMaxOutboundStreams);
120
+ negotiatedCapabilitiesField->negotiatedMaxInboundStreams =
121
+ htons(negotiatedCapabilities.negotiatedMaxInboundStreams);
122
122
  }
123
123
 
124
124
  Types::SctpImplementation StateCookie::DetermineSctpImplementation(
@@ -206,10 +206,10 @@ namespace RTC
206
206
 
207
207
  NegotiatedCapabilities negotiatedCapabilities;
208
208
 
209
- negotiatedCapabilities.maxOutboundStreams =
210
- ntohs(negotiatedCapabilitiesField->maxOutboundStreams);
211
- negotiatedCapabilities.maxInboundStreams =
212
- ntohs(negotiatedCapabilitiesField->maxInboundStreams);
209
+ negotiatedCapabilities.negotiatedMaxOutboundStreams =
210
+ ntohs(negotiatedCapabilitiesField->negotiatedMaxOutboundStreams);
211
+ negotiatedCapabilities.negotiatedMaxInboundStreams =
212
+ ntohs(negotiatedCapabilitiesField->negotiatedMaxInboundStreams);
213
213
  negotiatedCapabilities.partialReliability = negotiatedCapabilitiesField->bitA;
214
214
  negotiatedCapabilities.messageInterleaving = negotiatedCapabilitiesField->bitB;
215
215
  negotiatedCapabilities.reConfig = negotiatedCapabilitiesField->bitC;