1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "net/dcsctp/socket/dcsctp_socket.h"
11
12 #include <algorithm>
13 #include <cstdint>
14 #include <limits>
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "absl/functional/bind_front.h"
21 #include "absl/memory/memory.h"
22 #include "absl/strings/string_view.h"
23 #include "absl/types/optional.h"
24 #include "api/array_view.h"
25 #include "api/task_queue/task_queue_base.h"
26 #include "net/dcsctp/packet/chunk/abort_chunk.h"
27 #include "net/dcsctp/packet/chunk/chunk.h"
28 #include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
29 #include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
30 #include "net/dcsctp/packet/chunk/data_chunk.h"
31 #include "net/dcsctp/packet/chunk/data_common.h"
32 #include "net/dcsctp/packet/chunk/error_chunk.h"
33 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
34 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
35 #include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
36 #include "net/dcsctp/packet/chunk/heartbeat_request_chunk.h"
37 #include "net/dcsctp/packet/chunk/idata_chunk.h"
38 #include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
39 #include "net/dcsctp/packet/chunk/init_ack_chunk.h"
40 #include "net/dcsctp/packet/chunk/init_chunk.h"
41 #include "net/dcsctp/packet/chunk/reconfig_chunk.h"
42 #include "net/dcsctp/packet/chunk/sack_chunk.h"
43 #include "net/dcsctp/packet/chunk/shutdown_ack_chunk.h"
44 #include "net/dcsctp/packet/chunk/shutdown_chunk.h"
45 #include "net/dcsctp/packet/chunk/shutdown_complete_chunk.h"
46 #include "net/dcsctp/packet/chunk_validators.h"
47 #include "net/dcsctp/packet/data.h"
48 #include "net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h"
49 #include "net/dcsctp/packet/error_cause/error_cause.h"
50 #include "net/dcsctp/packet/error_cause/no_user_data_cause.h"
51 #include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
52 #include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
53 #include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
54 #include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
55 #include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
56 #include "net/dcsctp/packet/parameter/parameter.h"
57 #include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
58 #include "net/dcsctp/packet/parameter/supported_extensions_parameter.h"
59 #include "net/dcsctp/packet/sctp_packet.h"
60 #include "net/dcsctp/packet/tlv_trait.h"
61 #include "net/dcsctp/public/dcsctp_message.h"
62 #include "net/dcsctp/public/dcsctp_options.h"
63 #include "net/dcsctp/public/dcsctp_socket.h"
64 #include "net/dcsctp/public/packet_observer.h"
65 #include "net/dcsctp/public/types.h"
66 #include "net/dcsctp/rx/data_tracker.h"
67 #include "net/dcsctp/rx/reassembly_queue.h"
68 #include "net/dcsctp/socket/callback_deferrer.h"
69 #include "net/dcsctp/socket/capabilities.h"
70 #include "net/dcsctp/socket/heartbeat_handler.h"
71 #include "net/dcsctp/socket/state_cookie.h"
72 #include "net/dcsctp/socket/stream_reset_handler.h"
73 #include "net/dcsctp/socket/transmission_control_block.h"
74 #include "net/dcsctp/timer/timer.h"
75 #include "net/dcsctp/tx/retransmission_queue.h"
76 #include "net/dcsctp/tx/send_queue.h"
77 #include "rtc_base/checks.h"
78 #include "rtc_base/logging.h"
79 #include "rtc_base/strings/string_builder.h"
80 #include "rtc_base/strings/string_format.h"
81
82 namespace dcsctp {
83 namespace {
84
85 // https://tools.ietf.org/html/rfc4960#section-5.1
86 constexpr uint32_t kMinVerificationTag = 1;
87 constexpr uint32_t kMaxVerificationTag = std::numeric_limits<uint32_t>::max();
88
89 // https://tools.ietf.org/html/rfc4960#section-3.3.2
90 constexpr uint32_t kMinInitialTsn = 0;
91 constexpr uint32_t kMaxInitialTsn = std::numeric_limits<uint32_t>::max();
92
ComputeCapabilities(const DcSctpOptions & options,uint16_t peer_nbr_outbound_streams,uint16_t peer_nbr_inbound_streams,const Parameters & parameters)93 Capabilities ComputeCapabilities(const DcSctpOptions& options,
94 uint16_t peer_nbr_outbound_streams,
95 uint16_t peer_nbr_inbound_streams,
96 const Parameters& parameters) {
97 Capabilities capabilities;
98 absl::optional<SupportedExtensionsParameter> supported_extensions =
99 parameters.get<SupportedExtensionsParameter>();
100
101 if (options.enable_partial_reliability) {
102 capabilities.partial_reliability =
103 parameters.get<ForwardTsnSupportedParameter>().has_value();
104 if (supported_extensions.has_value()) {
105 capabilities.partial_reliability |=
106 supported_extensions->supports(ForwardTsnChunk::kType);
107 }
108 }
109
110 if (options.enable_message_interleaving && supported_extensions.has_value()) {
111 capabilities.message_interleaving =
112 supported_extensions->supports(IDataChunk::kType) &&
113 supported_extensions->supports(IForwardTsnChunk::kType);
114 }
115 if (supported_extensions.has_value() &&
116 supported_extensions->supports(ReConfigChunk::kType)) {
117 capabilities.reconfig = true;
118 }
119
120 capabilities.negotiated_maximum_incoming_streams = std::min(
121 options.announced_maximum_incoming_streams, peer_nbr_outbound_streams);
122 capabilities.negotiated_maximum_outgoing_streams = std::min(
123 options.announced_maximum_outgoing_streams, peer_nbr_inbound_streams);
124
125 return capabilities;
126 }
127
AddCapabilityParameters(const DcSctpOptions & options,Parameters::Builder & builder)128 void AddCapabilityParameters(const DcSctpOptions& options,
129 Parameters::Builder& builder) {
130 std::vector<uint8_t> chunk_types = {ReConfigChunk::kType};
131
132 if (options.enable_partial_reliability) {
133 builder.Add(ForwardTsnSupportedParameter());
134 chunk_types.push_back(ForwardTsnChunk::kType);
135 }
136 if (options.enable_message_interleaving) {
137 chunk_types.push_back(IDataChunk::kType);
138 chunk_types.push_back(IForwardTsnChunk::kType);
139 }
140 builder.Add(SupportedExtensionsParameter(std::move(chunk_types)));
141 }
142
MakeTieTag(DcSctpSocketCallbacks & cb)143 TieTag MakeTieTag(DcSctpSocketCallbacks& cb) {
144 uint32_t tie_tag_upper =
145 cb.GetRandomInt(0, std::numeric_limits<uint32_t>::max());
146 uint32_t tie_tag_lower =
147 cb.GetRandomInt(1, std::numeric_limits<uint32_t>::max());
148 return TieTag(static_cast<uint64_t>(tie_tag_upper) << 32 |
149 static_cast<uint64_t>(tie_tag_lower));
150 }
151
DeterminePeerImplementation(rtc::ArrayView<const uint8_t> cookie)152 SctpImplementation DeterminePeerImplementation(
153 rtc::ArrayView<const uint8_t> cookie) {
154 if (cookie.size() > 8) {
155 absl::string_view magic(reinterpret_cast<const char*>(cookie.data()), 8);
156 if (magic == "dcSCTP00") {
157 return SctpImplementation::kDcsctp;
158 }
159 if (magic == "KAME-BSD") {
160 return SctpImplementation::kUsrSctp;
161 }
162 }
163 return SctpImplementation::kOther;
164 }
165 } // namespace
166
DcSctpSocket(absl::string_view log_prefix,DcSctpSocketCallbacks & callbacks,std::unique_ptr<PacketObserver> packet_observer,const DcSctpOptions & options)167 DcSctpSocket::DcSctpSocket(absl::string_view log_prefix,
168 DcSctpSocketCallbacks& callbacks,
169 std::unique_ptr<PacketObserver> packet_observer,
170 const DcSctpOptions& options)
171 : log_prefix_(std::string(log_prefix) + ": "),
172 packet_observer_(std::move(packet_observer)),
173 options_(options),
174 callbacks_(callbacks),
175 timer_manager_([this](webrtc::TaskQueueBase::DelayPrecision precision) {
176 return callbacks_.CreateTimeout(precision);
177 }),
178 t1_init_(timer_manager_.CreateTimer(
179 "t1-init",
180 absl::bind_front(&DcSctpSocket::OnInitTimerExpiry, this),
181 TimerOptions(options.t1_init_timeout,
182 TimerBackoffAlgorithm::kExponential,
183 options.max_init_retransmits))),
184 t1_cookie_(timer_manager_.CreateTimer(
185 "t1-cookie",
186 absl::bind_front(&DcSctpSocket::OnCookieTimerExpiry, this),
187 TimerOptions(options.t1_cookie_timeout,
188 TimerBackoffAlgorithm::kExponential,
189 options.max_init_retransmits))),
190 t2_shutdown_(timer_manager_.CreateTimer(
191 "t2-shutdown",
192 absl::bind_front(&DcSctpSocket::OnShutdownTimerExpiry, this),
193 TimerOptions(options.t2_shutdown_timeout,
194 TimerBackoffAlgorithm::kExponential,
195 options.max_retransmissions))),
196 packet_sender_(callbacks_,
197 absl::bind_front(&DcSctpSocket::OnSentPacket, this)),
198 send_queue_(log_prefix_,
199 &callbacks_,
200 options_.max_send_buffer_size,
201 options_.mtu,
202 options_.default_stream_priority,
203 options_.total_buffered_amount_low_threshold) {}
204
log_prefix() const205 std::string DcSctpSocket::log_prefix() const {
206 return log_prefix_ + "[" + std::string(ToString(state_)) + "] ";
207 }
208
IsConsistent() const209 bool DcSctpSocket::IsConsistent() const {
210 if (tcb_ != nullptr && tcb_->reassembly_queue().HasMessages()) {
211 return false;
212 }
213 switch (state_) {
214 case State::kClosed:
215 return (tcb_ == nullptr && !t1_init_->is_running() &&
216 !t1_cookie_->is_running() && !t2_shutdown_->is_running());
217 case State::kCookieWait:
218 return (tcb_ == nullptr && t1_init_->is_running() &&
219 !t1_cookie_->is_running() && !t2_shutdown_->is_running());
220 case State::kCookieEchoed:
221 return (tcb_ != nullptr && !t1_init_->is_running() &&
222 t1_cookie_->is_running() && !t2_shutdown_->is_running() &&
223 tcb_->has_cookie_echo_chunk());
224 case State::kEstablished:
225 return (tcb_ != nullptr && !t1_init_->is_running() &&
226 !t1_cookie_->is_running() && !t2_shutdown_->is_running());
227 case State::kShutdownPending:
228 return (tcb_ != nullptr && !t1_init_->is_running() &&
229 !t1_cookie_->is_running() && !t2_shutdown_->is_running());
230 case State::kShutdownSent:
231 return (tcb_ != nullptr && !t1_init_->is_running() &&
232 !t1_cookie_->is_running() && t2_shutdown_->is_running());
233 case State::kShutdownReceived:
234 return (tcb_ != nullptr && !t1_init_->is_running() &&
235 !t1_cookie_->is_running() && !t2_shutdown_->is_running());
236 case State::kShutdownAckSent:
237 return (tcb_ != nullptr && !t1_init_->is_running() &&
238 !t1_cookie_->is_running() && t2_shutdown_->is_running());
239 }
240 }
241
ToString(DcSctpSocket::State state)242 constexpr absl::string_view DcSctpSocket::ToString(DcSctpSocket::State state) {
243 switch (state) {
244 case DcSctpSocket::State::kClosed:
245 return "CLOSED";
246 case DcSctpSocket::State::kCookieWait:
247 return "COOKIE_WAIT";
248 case DcSctpSocket::State::kCookieEchoed:
249 return "COOKIE_ECHOED";
250 case DcSctpSocket::State::kEstablished:
251 return "ESTABLISHED";
252 case DcSctpSocket::State::kShutdownPending:
253 return "SHUTDOWN_PENDING";
254 case DcSctpSocket::State::kShutdownSent:
255 return "SHUTDOWN_SENT";
256 case DcSctpSocket::State::kShutdownReceived:
257 return "SHUTDOWN_RECEIVED";
258 case DcSctpSocket::State::kShutdownAckSent:
259 return "SHUTDOWN_ACK_SENT";
260 }
261 }
262
SetState(State state,absl::string_view reason)263 void DcSctpSocket::SetState(State state, absl::string_view reason) {
264 if (state_ != state) {
265 RTC_DLOG(LS_VERBOSE) << log_prefix_ << "Socket state changed from "
266 << ToString(state_) << " to " << ToString(state)
267 << " due to " << reason;
268 state_ = state;
269 }
270 }
271
SendInit()272 void DcSctpSocket::SendInit() {
273 Parameters::Builder params_builder;
274 AddCapabilityParameters(options_, params_builder);
275 InitChunk init(/*initiate_tag=*/connect_params_.verification_tag,
276 /*a_rwnd=*/options_.max_receiver_window_buffer_size,
277 options_.announced_maximum_outgoing_streams,
278 options_.announced_maximum_incoming_streams,
279 connect_params_.initial_tsn, params_builder.Build());
280 SctpPacket::Builder b(VerificationTag(0), options_);
281 b.Add(init);
282 packet_sender_.Send(b);
283 }
284
MakeConnectionParameters()285 void DcSctpSocket::MakeConnectionParameters() {
286 VerificationTag new_verification_tag(
287 callbacks_.GetRandomInt(kMinVerificationTag, kMaxVerificationTag));
288 TSN initial_tsn(callbacks_.GetRandomInt(kMinInitialTsn, kMaxInitialTsn));
289 connect_params_.initial_tsn = initial_tsn;
290 connect_params_.verification_tag = new_verification_tag;
291 }
292
Connect()293 void DcSctpSocket::Connect() {
294 RTC_DCHECK_RUN_ON(&thread_checker_);
295 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
296
297 if (state_ == State::kClosed) {
298 MakeConnectionParameters();
299 RTC_DLOG(LS_INFO)
300 << log_prefix()
301 << rtc::StringFormat(
302 "Connecting. my_verification_tag=%08x, my_initial_tsn=%u",
303 *connect_params_.verification_tag, *connect_params_.initial_tsn);
304 SendInit();
305 t1_init_->Start();
306 SetState(State::kCookieWait, "Connect called");
307 } else {
308 RTC_DLOG(LS_WARNING) << log_prefix()
309 << "Called Connect on a socket that is not closed";
310 }
311 RTC_DCHECK(IsConsistent());
312 }
313
CreateTransmissionControlBlock(const Capabilities & capabilities,VerificationTag my_verification_tag,TSN my_initial_tsn,VerificationTag peer_verification_tag,TSN peer_initial_tsn,size_t a_rwnd,TieTag tie_tag)314 void DcSctpSocket::CreateTransmissionControlBlock(
315 const Capabilities& capabilities,
316 VerificationTag my_verification_tag,
317 TSN my_initial_tsn,
318 VerificationTag peer_verification_tag,
319 TSN peer_initial_tsn,
320 size_t a_rwnd,
321 TieTag tie_tag) {
322 metrics_.uses_message_interleaving = capabilities.message_interleaving;
323 metrics_.negotiated_maximum_incoming_streams =
324 capabilities.negotiated_maximum_incoming_streams;
325 metrics_.negotiated_maximum_outgoing_streams =
326 capabilities.negotiated_maximum_outgoing_streams;
327 tcb_ = std::make_unique<TransmissionControlBlock>(
328 timer_manager_, log_prefix_, options_, capabilities, callbacks_,
329 send_queue_, my_verification_tag, my_initial_tsn, peer_verification_tag,
330 peer_initial_tsn, a_rwnd, tie_tag, packet_sender_,
331 [this]() { return state_ == State::kEstablished; });
332 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Created TCB: " << tcb_->ToString();
333 }
334
RestoreFromState(const DcSctpSocketHandoverState & state)335 void DcSctpSocket::RestoreFromState(const DcSctpSocketHandoverState& state) {
336 RTC_DCHECK_RUN_ON(&thread_checker_);
337 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
338
339 if (state_ != State::kClosed) {
340 callbacks_.OnError(ErrorKind::kUnsupportedOperation,
341 "Only closed socket can be restored from state");
342 } else {
343 if (state.socket_state ==
344 DcSctpSocketHandoverState::SocketState::kConnected) {
345 VerificationTag my_verification_tag =
346 VerificationTag(state.my_verification_tag);
347 connect_params_.verification_tag = my_verification_tag;
348
349 Capabilities capabilities;
350 capabilities.partial_reliability = state.capabilities.partial_reliability;
351 capabilities.message_interleaving =
352 state.capabilities.message_interleaving;
353 capabilities.reconfig = state.capabilities.reconfig;
354 capabilities.negotiated_maximum_incoming_streams =
355 state.capabilities.negotiated_maximum_incoming_streams;
356 capabilities.negotiated_maximum_outgoing_streams =
357 state.capabilities.negotiated_maximum_outgoing_streams;
358
359 send_queue_.RestoreFromState(state);
360
361 CreateTransmissionControlBlock(
362 capabilities, my_verification_tag, TSN(state.my_initial_tsn),
363 VerificationTag(state.peer_verification_tag),
364 TSN(state.peer_initial_tsn), static_cast<size_t>(0),
365 TieTag(state.tie_tag));
366
367 tcb_->RestoreFromState(state);
368
369 SetState(State::kEstablished, "restored from handover state");
370 callbacks_.OnConnected();
371 }
372 }
373
374 RTC_DCHECK(IsConsistent());
375 }
376
Shutdown()377 void DcSctpSocket::Shutdown() {
378 RTC_DCHECK_RUN_ON(&thread_checker_);
379 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
380
381 if (tcb_ != nullptr) {
382 // https://tools.ietf.org/html/rfc4960#section-9.2
383 // "Upon receipt of the SHUTDOWN primitive from its upper layer, the
384 // endpoint enters the SHUTDOWN-PENDING state and remains there until all
385 // outstanding data has been acknowledged by its peer."
386
387 // TODO(webrtc:12739): Remove this check, as it just hides the problem that
388 // the socket can transition from ShutdownSent to ShutdownPending, or
389 // ShutdownAckSent to ShutdownPending which is illegal.
390 if (state_ != State::kShutdownSent && state_ != State::kShutdownAckSent) {
391 SetState(State::kShutdownPending, "Shutdown called");
392 t1_init_->Stop();
393 t1_cookie_->Stop();
394 MaybeSendShutdownOrAck();
395 }
396 } else {
397 // Connection closed before even starting to connect, or during the initial
398 // connection phase. There is no outstanding data, so the socket can just
399 // be closed (stopping any connection timers, if any), as this is the
400 // client's intention, by calling Shutdown.
401 InternalClose(ErrorKind::kNoError, "");
402 }
403 RTC_DCHECK(IsConsistent());
404 }
405
Close()406 void DcSctpSocket::Close() {
407 RTC_DCHECK_RUN_ON(&thread_checker_);
408 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
409
410 if (state_ != State::kClosed) {
411 if (tcb_ != nullptr) {
412 SctpPacket::Builder b = tcb_->PacketBuilder();
413 b.Add(AbortChunk(/*filled_in_verification_tag=*/true,
414 Parameters::Builder()
415 .Add(UserInitiatedAbortCause("Close called"))
416 .Build()));
417 packet_sender_.Send(b);
418 }
419 InternalClose(ErrorKind::kNoError, "");
420 } else {
421 RTC_DLOG(LS_INFO) << log_prefix() << "Called Close on a closed socket";
422 }
423 RTC_DCHECK(IsConsistent());
424 }
425
CloseConnectionBecauseOfTooManyTransmissionErrors()426 void DcSctpSocket::CloseConnectionBecauseOfTooManyTransmissionErrors() {
427 packet_sender_.Send(tcb_->PacketBuilder().Add(AbortChunk(
428 true, Parameters::Builder()
429 .Add(UserInitiatedAbortCause("Too many retransmissions"))
430 .Build())));
431 InternalClose(ErrorKind::kTooManyRetries, "Too many retransmissions");
432 }
433
InternalClose(ErrorKind error,absl::string_view message)434 void DcSctpSocket::InternalClose(ErrorKind error, absl::string_view message) {
435 if (state_ != State::kClosed) {
436 t1_init_->Stop();
437 t1_cookie_->Stop();
438 t2_shutdown_->Stop();
439 tcb_ = nullptr;
440
441 if (error == ErrorKind::kNoError) {
442 callbacks_.OnClosed();
443 } else {
444 callbacks_.OnAborted(error, message);
445 }
446 SetState(State::kClosed, message);
447 }
448 // This method's purpose is to abort/close and make it consistent by ensuring
449 // that e.g. all timers really are stopped.
450 RTC_DCHECK(IsConsistent());
451 }
452
SetStreamPriority(StreamID stream_id,StreamPriority priority)453 void DcSctpSocket::SetStreamPriority(StreamID stream_id,
454 StreamPriority priority) {
455 RTC_DCHECK_RUN_ON(&thread_checker_);
456 send_queue_.SetStreamPriority(stream_id, priority);
457 }
GetStreamPriority(StreamID stream_id) const458 StreamPriority DcSctpSocket::GetStreamPriority(StreamID stream_id) const {
459 RTC_DCHECK_RUN_ON(&thread_checker_);
460 return send_queue_.GetStreamPriority(stream_id);
461 }
462
Send(DcSctpMessage message,const SendOptions & send_options)463 SendStatus DcSctpSocket::Send(DcSctpMessage message,
464 const SendOptions& send_options) {
465 RTC_DCHECK_RUN_ON(&thread_checker_);
466 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
467 LifecycleId lifecycle_id = send_options.lifecycle_id;
468
469 if (message.payload().empty()) {
470 if (lifecycle_id.IsSet()) {
471 callbacks_.OnLifecycleEnd(lifecycle_id);
472 }
473 callbacks_.OnError(ErrorKind::kProtocolViolation,
474 "Unable to send empty message");
475 return SendStatus::kErrorMessageEmpty;
476 }
477 if (message.payload().size() > options_.max_message_size) {
478 if (lifecycle_id.IsSet()) {
479 callbacks_.OnLifecycleEnd(lifecycle_id);
480 }
481 callbacks_.OnError(ErrorKind::kProtocolViolation,
482 "Unable to send too large message");
483 return SendStatus::kErrorMessageTooLarge;
484 }
485 if (state_ == State::kShutdownPending || state_ == State::kShutdownSent ||
486 state_ == State::kShutdownReceived || state_ == State::kShutdownAckSent) {
487 // https://tools.ietf.org/html/rfc4960#section-9.2
488 // "An endpoint should reject any new data request from its upper layer
489 // if it is in the SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED, or
490 // SHUTDOWN-ACK-SENT state."
491 if (lifecycle_id.IsSet()) {
492 callbacks_.OnLifecycleEnd(lifecycle_id);
493 }
494 callbacks_.OnError(ErrorKind::kWrongSequence,
495 "Unable to send message as the socket is shutting down");
496 return SendStatus::kErrorShuttingDown;
497 }
498 if (send_queue_.IsFull()) {
499 if (lifecycle_id.IsSet()) {
500 callbacks_.OnLifecycleEnd(lifecycle_id);
501 }
502 callbacks_.OnError(ErrorKind::kResourceExhaustion,
503 "Unable to send message as the send queue is full");
504 return SendStatus::kErrorResourceExhaustion;
505 }
506
507 TimeMs now = callbacks_.TimeMillis();
508 ++metrics_.tx_messages_count;
509 send_queue_.Add(now, std::move(message), send_options);
510 if (tcb_ != nullptr) {
511 tcb_->SendBufferedPackets(now);
512 }
513
514 RTC_DCHECK(IsConsistent());
515 return SendStatus::kSuccess;
516 }
517
ResetStreams(rtc::ArrayView<const StreamID> outgoing_streams)518 ResetStreamsStatus DcSctpSocket::ResetStreams(
519 rtc::ArrayView<const StreamID> outgoing_streams) {
520 RTC_DCHECK_RUN_ON(&thread_checker_);
521 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
522
523 if (tcb_ == nullptr) {
524 callbacks_.OnError(ErrorKind::kWrongSequence,
525 "Can't reset streams as the socket is not connected");
526 return ResetStreamsStatus::kNotConnected;
527 }
528 if (!tcb_->capabilities().reconfig) {
529 callbacks_.OnError(ErrorKind::kUnsupportedOperation,
530 "Can't reset streams as the peer doesn't support it");
531 return ResetStreamsStatus::kNotSupported;
532 }
533
534 tcb_->stream_reset_handler().ResetStreams(outgoing_streams);
535 MaybeSendResetStreamsRequest();
536
537 RTC_DCHECK(IsConsistent());
538 return ResetStreamsStatus::kPerformed;
539 }
540
state() const541 SocketState DcSctpSocket::state() const {
542 RTC_DCHECK_RUN_ON(&thread_checker_);
543 switch (state_) {
544 case State::kClosed:
545 return SocketState::kClosed;
546 case State::kCookieWait:
547 case State::kCookieEchoed:
548 return SocketState::kConnecting;
549 case State::kEstablished:
550 return SocketState::kConnected;
551 case State::kShutdownPending:
552 case State::kShutdownSent:
553 case State::kShutdownReceived:
554 case State::kShutdownAckSent:
555 return SocketState::kShuttingDown;
556 }
557 }
558
SetMaxMessageSize(size_t max_message_size)559 void DcSctpSocket::SetMaxMessageSize(size_t max_message_size) {
560 RTC_DCHECK_RUN_ON(&thread_checker_);
561 options_.max_message_size = max_message_size;
562 }
563
buffered_amount(StreamID stream_id) const564 size_t DcSctpSocket::buffered_amount(StreamID stream_id) const {
565 RTC_DCHECK_RUN_ON(&thread_checker_);
566 return send_queue_.buffered_amount(stream_id);
567 }
568
buffered_amount_low_threshold(StreamID stream_id) const569 size_t DcSctpSocket::buffered_amount_low_threshold(StreamID stream_id) const {
570 RTC_DCHECK_RUN_ON(&thread_checker_);
571 return send_queue_.buffered_amount_low_threshold(stream_id);
572 }
573
SetBufferedAmountLowThreshold(StreamID stream_id,size_t bytes)574 void DcSctpSocket::SetBufferedAmountLowThreshold(StreamID stream_id,
575 size_t bytes) {
576 RTC_DCHECK_RUN_ON(&thread_checker_);
577 send_queue_.SetBufferedAmountLowThreshold(stream_id, bytes);
578 }
579
GetMetrics() const580 absl::optional<Metrics> DcSctpSocket::GetMetrics() const {
581 RTC_DCHECK_RUN_ON(&thread_checker_);
582
583 if (tcb_ == nullptr) {
584 return absl::nullopt;
585 }
586
587 Metrics metrics = metrics_;
588 metrics.cwnd_bytes = tcb_->cwnd();
589 metrics.srtt_ms = tcb_->current_srtt().value();
590 size_t packet_payload_size =
591 options_.mtu - SctpPacket::kHeaderSize - DataChunk::kHeaderSize;
592 metrics.unack_data_count =
593 tcb_->retransmission_queue().outstanding_items() +
594 (send_queue_.total_buffered_amount() + packet_payload_size - 1) /
595 packet_payload_size;
596 metrics.peer_rwnd_bytes = tcb_->retransmission_queue().rwnd();
597 metrics.negotiated_maximum_incoming_streams =
598 tcb_->capabilities().negotiated_maximum_incoming_streams;
599 metrics.negotiated_maximum_incoming_streams =
600 tcb_->capabilities().negotiated_maximum_incoming_streams;
601
602 return metrics;
603 }
604
MaybeSendShutdownOnPacketReceived(const SctpPacket & packet)605 void DcSctpSocket::MaybeSendShutdownOnPacketReceived(const SctpPacket& packet) {
606 if (state_ == State::kShutdownSent) {
607 bool has_data_chunk =
608 std::find_if(packet.descriptors().begin(), packet.descriptors().end(),
609 [](const SctpPacket::ChunkDescriptor& descriptor) {
610 return descriptor.type == DataChunk::kType;
611 }) != packet.descriptors().end();
612 if (has_data_chunk) {
613 // https://tools.ietf.org/html/rfc4960#section-9.2
614 // "While in the SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately
615 // respond to each received packet containing one or more DATA chunks with
616 // a SHUTDOWN chunk and restart the T2-shutdown timer.""
617 SendShutdown();
618 t2_shutdown_->set_duration(tcb_->current_rto());
619 t2_shutdown_->Start();
620 }
621 }
622 }
623
MaybeSendResetStreamsRequest()624 void DcSctpSocket::MaybeSendResetStreamsRequest() {
625 absl::optional<ReConfigChunk> reconfig =
626 tcb_->stream_reset_handler().MakeStreamResetRequest();
627 if (reconfig.has_value()) {
628 SctpPacket::Builder builder = tcb_->PacketBuilder();
629 builder.Add(*reconfig);
630 packet_sender_.Send(builder);
631 }
632 }
633
ValidatePacket(const SctpPacket & packet)634 bool DcSctpSocket::ValidatePacket(const SctpPacket& packet) {
635 const CommonHeader& header = packet.common_header();
636 VerificationTag my_verification_tag =
637 tcb_ != nullptr ? tcb_->my_verification_tag() : VerificationTag(0);
638
639 if (header.verification_tag == VerificationTag(0)) {
640 if (packet.descriptors().size() == 1 &&
641 packet.descriptors()[0].type == InitChunk::kType) {
642 // https://tools.ietf.org/html/rfc4960#section-8.5.1
643 // "When an endpoint receives an SCTP packet with the Verification Tag
644 // set to 0, it should verify that the packet contains only an INIT chunk.
645 // Otherwise, the receiver MUST silently discard the packet.""
646 return true;
647 }
648 callbacks_.OnError(
649 ErrorKind::kParseFailed,
650 "Only a single INIT chunk can be present in packets sent on "
651 "verification_tag = 0");
652 return false;
653 }
654
655 if (packet.descriptors().size() == 1 &&
656 packet.descriptors()[0].type == AbortChunk::kType) {
657 // https://tools.ietf.org/html/rfc4960#section-8.5.1
658 // "The receiver of an ABORT MUST accept the packet if the Verification
659 // Tag field of the packet matches its own tag and the T bit is not set OR
660 // if it is set to its peer's tag and the T bit is set in the Chunk Flags.
661 // Otherwise, the receiver MUST silently discard the packet and take no
662 // further action."
663 bool t_bit = (packet.descriptors()[0].flags & 0x01) != 0;
664 if (t_bit && tcb_ == nullptr) {
665 // Can't verify the tag - assume it's okey.
666 return true;
667 }
668 if ((!t_bit && header.verification_tag == my_verification_tag) ||
669 (t_bit && header.verification_tag == tcb_->peer_verification_tag())) {
670 return true;
671 }
672 callbacks_.OnError(ErrorKind::kParseFailed,
673 "ABORT chunk verification tag was wrong");
674 return false;
675 }
676
677 if (packet.descriptors()[0].type == InitAckChunk::kType) {
678 if (header.verification_tag == connect_params_.verification_tag) {
679 return true;
680 }
681 callbacks_.OnError(
682 ErrorKind::kParseFailed,
683 rtc::StringFormat(
684 "Packet has invalid verification tag: %08x, expected %08x",
685 *header.verification_tag, *connect_params_.verification_tag));
686 return false;
687 }
688
689 if (packet.descriptors()[0].type == CookieEchoChunk::kType) {
690 // Handled in chunk handler (due to RFC 4960, section 5.2.4).
691 return true;
692 }
693
694 if (packet.descriptors().size() == 1 &&
695 packet.descriptors()[0].type == ShutdownCompleteChunk::kType) {
696 // https://tools.ietf.org/html/rfc4960#section-8.5.1
697 // "The receiver of a SHUTDOWN COMPLETE shall accept the packet if the
698 // Verification Tag field of the packet matches its own tag and the T bit is
699 // not set OR if it is set to its peer's tag and the T bit is set in the
700 // Chunk Flags. Otherwise, the receiver MUST silently discard the packet
701 // and take no further action."
702 bool t_bit = (packet.descriptors()[0].flags & 0x01) != 0;
703 if (t_bit && tcb_ == nullptr) {
704 // Can't verify the tag - assume it's okey.
705 return true;
706 }
707 if ((!t_bit && header.verification_tag == my_verification_tag) ||
708 (t_bit && header.verification_tag == tcb_->peer_verification_tag())) {
709 return true;
710 }
711 callbacks_.OnError(ErrorKind::kParseFailed,
712 "SHUTDOWN_COMPLETE chunk verification tag was wrong");
713 return false;
714 }
715
716 // https://tools.ietf.org/html/rfc4960#section-8.5
717 // "When receiving an SCTP packet, the endpoint MUST ensure that the value
718 // in the Verification Tag field of the received SCTP packet matches its own
719 // tag. If the received Verification Tag value does not match the receiver's
720 // own tag value, the receiver shall silently discard the packet and shall not
721 // process it any further..."
722 if (header.verification_tag == my_verification_tag) {
723 return true;
724 }
725
726 callbacks_.OnError(
727 ErrorKind::kParseFailed,
728 rtc::StringFormat(
729 "Packet has invalid verification tag: %08x, expected %08x",
730 *header.verification_tag, *my_verification_tag));
731 return false;
732 }
733
HandleTimeout(TimeoutID timeout_id)734 void DcSctpSocket::HandleTimeout(TimeoutID timeout_id) {
735 RTC_DCHECK_RUN_ON(&thread_checker_);
736 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
737
738 timer_manager_.HandleTimeout(timeout_id);
739
740 if (tcb_ != nullptr && tcb_->HasTooManyTxErrors()) {
741 // Tearing down the TCB has to be done outside the handlers.
742 CloseConnectionBecauseOfTooManyTransmissionErrors();
743 }
744
745 RTC_DCHECK(IsConsistent());
746 }
747
ReceivePacket(rtc::ArrayView<const uint8_t> data)748 void DcSctpSocket::ReceivePacket(rtc::ArrayView<const uint8_t> data) {
749 RTC_DCHECK_RUN_ON(&thread_checker_);
750 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
751
752 ++metrics_.rx_packets_count;
753
754 if (packet_observer_ != nullptr) {
755 packet_observer_->OnReceivedPacket(callbacks_.TimeMillis(), data);
756 }
757
758 absl::optional<SctpPacket> packet =
759 SctpPacket::Parse(data, options_.disable_checksum_verification);
760 if (!packet.has_value()) {
761 // https://tools.ietf.org/html/rfc4960#section-6.8
762 // "The default procedure for handling invalid SCTP packets is to
763 // silently discard them."
764 callbacks_.OnError(ErrorKind::kParseFailed,
765 "Failed to parse received SCTP packet");
766 RTC_DCHECK(IsConsistent());
767 return;
768 }
769
770 if (RTC_DLOG_IS_ON) {
771 for (const auto& descriptor : packet->descriptors()) {
772 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received "
773 << DebugConvertChunkToString(descriptor.data);
774 }
775 }
776
777 if (!ValidatePacket(*packet)) {
778 RTC_DLOG(LS_VERBOSE) << log_prefix()
779 << "Packet failed verification tag check - dropping";
780 RTC_DCHECK(IsConsistent());
781 return;
782 }
783
784 MaybeSendShutdownOnPacketReceived(*packet);
785
786 for (const auto& descriptor : packet->descriptors()) {
787 if (!Dispatch(packet->common_header(), descriptor)) {
788 break;
789 }
790 }
791
792 if (tcb_ != nullptr) {
793 tcb_->data_tracker().ObservePacketEnd();
794 tcb_->MaybeSendSack();
795 }
796
797 RTC_DCHECK(IsConsistent());
798 }
799
DebugPrintOutgoing(rtc::ArrayView<const uint8_t> payload)800 void DcSctpSocket::DebugPrintOutgoing(rtc::ArrayView<const uint8_t> payload) {
801 auto packet = SctpPacket::Parse(payload);
802 RTC_DCHECK(packet.has_value());
803
804 for (const auto& desc : packet->descriptors()) {
805 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Sent "
806 << DebugConvertChunkToString(desc.data);
807 }
808 }
809
Dispatch(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)810 bool DcSctpSocket::Dispatch(const CommonHeader& header,
811 const SctpPacket::ChunkDescriptor& descriptor) {
812 switch (descriptor.type) {
813 case DataChunk::kType:
814 HandleData(header, descriptor);
815 break;
816 case InitChunk::kType:
817 HandleInit(header, descriptor);
818 break;
819 case InitAckChunk::kType:
820 HandleInitAck(header, descriptor);
821 break;
822 case SackChunk::kType:
823 HandleSack(header, descriptor);
824 break;
825 case HeartbeatRequestChunk::kType:
826 HandleHeartbeatRequest(header, descriptor);
827 break;
828 case HeartbeatAckChunk::kType:
829 HandleHeartbeatAck(header, descriptor);
830 break;
831 case AbortChunk::kType:
832 HandleAbort(header, descriptor);
833 break;
834 case ErrorChunk::kType:
835 HandleError(header, descriptor);
836 break;
837 case CookieEchoChunk::kType:
838 HandleCookieEcho(header, descriptor);
839 break;
840 case CookieAckChunk::kType:
841 HandleCookieAck(header, descriptor);
842 break;
843 case ShutdownChunk::kType:
844 HandleShutdown(header, descriptor);
845 break;
846 case ShutdownAckChunk::kType:
847 HandleShutdownAck(header, descriptor);
848 break;
849 case ShutdownCompleteChunk::kType:
850 HandleShutdownComplete(header, descriptor);
851 break;
852 case ReConfigChunk::kType:
853 HandleReconfig(header, descriptor);
854 break;
855 case ForwardTsnChunk::kType:
856 HandleForwardTsn(header, descriptor);
857 break;
858 case IDataChunk::kType:
859 HandleIData(header, descriptor);
860 break;
861 case IForwardTsnChunk::kType:
862 HandleIForwardTsn(header, descriptor);
863 break;
864 default:
865 return HandleUnrecognizedChunk(descriptor);
866 }
867 return true;
868 }
869
HandleUnrecognizedChunk(const SctpPacket::ChunkDescriptor & descriptor)870 bool DcSctpSocket::HandleUnrecognizedChunk(
871 const SctpPacket::ChunkDescriptor& descriptor) {
872 bool report_as_error = (descriptor.type & 0x40) != 0;
873 bool continue_processing = (descriptor.type & 0x80) != 0;
874 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received unknown chunk: "
875 << static_cast<int>(descriptor.type);
876 if (report_as_error) {
877 rtc::StringBuilder sb;
878 sb << "Received unknown chunk of type: "
879 << static_cast<int>(descriptor.type) << " with report-error bit set";
880 callbacks_.OnError(ErrorKind::kParseFailed, sb.str());
881 RTC_DLOG(LS_VERBOSE)
882 << log_prefix()
883 << "Unknown chunk, with type indicating it should be reported.";
884
885 // https://tools.ietf.org/html/rfc4960#section-3.2
886 // "... report in an ERROR chunk using the 'Unrecognized Chunk Type'
887 // cause."
888 if (tcb_ != nullptr) {
889 // Need TCB - this chunk must be sent with a correct verification tag.
890 packet_sender_.Send(tcb_->PacketBuilder().Add(
891 ErrorChunk(Parameters::Builder()
892 .Add(UnrecognizedChunkTypeCause(std::vector<uint8_t>(
893 descriptor.data.begin(), descriptor.data.end())))
894 .Build())));
895 }
896 }
897 if (!continue_processing) {
898 // https://tools.ietf.org/html/rfc4960#section-3.2
899 // "Stop processing this SCTP packet and discard it, do not process any
900 // further chunks within it."
901 RTC_DLOG(LS_VERBOSE) << log_prefix()
902 << "Unknown chunk, with type indicating not to "
903 "process any further chunks";
904 }
905
906 return continue_processing;
907 }
908
OnInitTimerExpiry()909 absl::optional<DurationMs> DcSctpSocket::OnInitTimerExpiry() {
910 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t1_init_->name()
911 << " has expired: " << t1_init_->expiration_count()
912 << "/" << t1_init_->options().max_restarts.value_or(-1);
913 RTC_DCHECK(state_ == State::kCookieWait);
914
915 if (t1_init_->is_running()) {
916 SendInit();
917 } else {
918 InternalClose(ErrorKind::kTooManyRetries, "No INIT_ACK received");
919 }
920 RTC_DCHECK(IsConsistent());
921 return absl::nullopt;
922 }
923
OnCookieTimerExpiry()924 absl::optional<DurationMs> DcSctpSocket::OnCookieTimerExpiry() {
925 // https://tools.ietf.org/html/rfc4960#section-4
926 // "If the T1-cookie timer expires, the endpoint MUST retransmit COOKIE
927 // ECHO and restart the T1-cookie timer without changing state. This MUST
928 // be repeated up to 'Max.Init.Retransmits' times. After that, the endpoint
929 // MUST abort the initialization process and report the error to the SCTP
930 // user."
931 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t1_cookie_->name()
932 << " has expired: " << t1_cookie_->expiration_count()
933 << "/"
934 << t1_cookie_->options().max_restarts.value_or(-1);
935
936 RTC_DCHECK(state_ == State::kCookieEchoed);
937
938 if (t1_cookie_->is_running()) {
939 tcb_->SendBufferedPackets(callbacks_.TimeMillis());
940 } else {
941 InternalClose(ErrorKind::kTooManyRetries, "No COOKIE_ACK received");
942 }
943
944 RTC_DCHECK(IsConsistent());
945 return absl::nullopt;
946 }
947
OnShutdownTimerExpiry()948 absl::optional<DurationMs> DcSctpSocket::OnShutdownTimerExpiry() {
949 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t2_shutdown_->name()
950 << " has expired: " << t2_shutdown_->expiration_count()
951 << "/"
952 << t2_shutdown_->options().max_restarts.value_or(-1);
953
954 if (!t2_shutdown_->is_running()) {
955 // https://tools.ietf.org/html/rfc4960#section-9.2
956 // "An endpoint should limit the number of retransmissions of the SHUTDOWN
957 // chunk to the protocol parameter 'Association.Max.Retrans'. If this
958 // threshold is exceeded, the endpoint should destroy the TCB..."
959
960 packet_sender_.Send(tcb_->PacketBuilder().Add(
961 AbortChunk(true, Parameters::Builder()
962 .Add(UserInitiatedAbortCause(
963 "Too many retransmissions of SHUTDOWN"))
964 .Build())));
965
966 InternalClose(ErrorKind::kTooManyRetries, "No SHUTDOWN_ACK received");
967 RTC_DCHECK(IsConsistent());
968 return absl::nullopt;
969 }
970
971 // https://tools.ietf.org/html/rfc4960#section-9.2
972 // "If the timer expires, the endpoint must resend the SHUTDOWN with the
973 // updated last sequential TSN received from its peer."
974 SendShutdown();
975 RTC_DCHECK(IsConsistent());
976 return tcb_->current_rto();
977 }
978
OnSentPacket(rtc::ArrayView<const uint8_t> packet,SendPacketStatus status)979 void DcSctpSocket::OnSentPacket(rtc::ArrayView<const uint8_t> packet,
980 SendPacketStatus status) {
981 // The packet observer is invoked even if the packet was failed to be sent, to
982 // indicate an attempt was made.
983 if (packet_observer_ != nullptr) {
984 packet_observer_->OnSentPacket(callbacks_.TimeMillis(), packet);
985 }
986
987 if (status == SendPacketStatus::kSuccess) {
988 if (RTC_DLOG_IS_ON) {
989 DebugPrintOutgoing(packet);
990 }
991
992 // The heartbeat interval timer is restarted for every sent packet, to
993 // fire when the outgoing channel is inactive.
994 if (tcb_ != nullptr) {
995 tcb_->heartbeat_handler().RestartTimer();
996 }
997
998 ++metrics_.tx_packets_count;
999 }
1000 }
1001
ValidateHasTCB()1002 bool DcSctpSocket::ValidateHasTCB() {
1003 if (tcb_ != nullptr) {
1004 return true;
1005 }
1006
1007 callbacks_.OnError(
1008 ErrorKind::kNotConnected,
1009 "Received unexpected commands on socket that is not connected");
1010 return false;
1011 }
1012
ReportFailedToParseChunk(int chunk_type)1013 void DcSctpSocket::ReportFailedToParseChunk(int chunk_type) {
1014 rtc::StringBuilder sb;
1015 sb << "Failed to parse chunk of type: " << chunk_type;
1016 callbacks_.OnError(ErrorKind::kParseFailed, sb.str());
1017 }
1018
HandleData(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1019 void DcSctpSocket::HandleData(const CommonHeader& header,
1020 const SctpPacket::ChunkDescriptor& descriptor) {
1021 absl::optional<DataChunk> chunk = DataChunk::Parse(descriptor.data);
1022 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1023 HandleDataCommon(*chunk);
1024 }
1025 }
1026
HandleIData(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1027 void DcSctpSocket::HandleIData(const CommonHeader& header,
1028 const SctpPacket::ChunkDescriptor& descriptor) {
1029 absl::optional<IDataChunk> chunk = IDataChunk::Parse(descriptor.data);
1030 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1031 HandleDataCommon(*chunk);
1032 }
1033 }
1034
HandleDataCommon(AnyDataChunk & chunk)1035 void DcSctpSocket::HandleDataCommon(AnyDataChunk& chunk) {
1036 TSN tsn = chunk.tsn();
1037 AnyDataChunk::ImmediateAckFlag immediate_ack = chunk.options().immediate_ack;
1038 Data data = std::move(chunk).extract();
1039
1040 if (data.payload.empty()) {
1041 // Empty DATA chunks are illegal.
1042 packet_sender_.Send(tcb_->PacketBuilder().Add(
1043 ErrorChunk(Parameters::Builder().Add(NoUserDataCause(tsn)).Build())));
1044 callbacks_.OnError(ErrorKind::kProtocolViolation,
1045 "Received DATA chunk with no user data");
1046 return;
1047 }
1048
1049 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Handle DATA, queue_size="
1050 << tcb_->reassembly_queue().queued_bytes()
1051 << ", water_mark="
1052 << tcb_->reassembly_queue().watermark_bytes()
1053 << ", full=" << tcb_->reassembly_queue().is_full()
1054 << ", above="
1055 << tcb_->reassembly_queue().is_above_watermark();
1056
1057 if (tcb_->reassembly_queue().is_full()) {
1058 // If the reassembly queue is full, there is nothing that can be done. The
1059 // specification only allows dropping gap-ack-blocks, and that's not
1060 // likely to help as the socket has been trying to fill gaps since the
1061 // watermark was reached.
1062 packet_sender_.Send(tcb_->PacketBuilder().Add(AbortChunk(
1063 true, Parameters::Builder().Add(OutOfResourceErrorCause()).Build())));
1064 InternalClose(ErrorKind::kResourceExhaustion,
1065 "Reassembly Queue is exhausted");
1066 return;
1067 }
1068
1069 if (tcb_->reassembly_queue().is_above_watermark()) {
1070 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Is above high watermark";
1071 // If the reassembly queue is above its high watermark, only accept data
1072 // chunks that increase its cumulative ack tsn in an attempt to fill gaps
1073 // to deliver messages.
1074 if (!tcb_->data_tracker().will_increase_cum_ack_tsn(tsn)) {
1075 RTC_DLOG(LS_VERBOSE) << log_prefix()
1076 << "Rejected data because of exceeding watermark";
1077 tcb_->data_tracker().ForceImmediateSack();
1078 return;
1079 }
1080 }
1081
1082 if (!tcb_->data_tracker().IsTSNValid(tsn)) {
1083 RTC_DLOG(LS_VERBOSE) << log_prefix()
1084 << "Rejected data because of failing TSN validity";
1085 return;
1086 }
1087
1088 if (tcb_->data_tracker().Observe(tsn, immediate_ack)) {
1089 tcb_->reassembly_queue().Add(tsn, std::move(data));
1090 tcb_->reassembly_queue().MaybeResetStreamsDeferred(
1091 tcb_->data_tracker().last_cumulative_acked_tsn());
1092 DeliverReassembledMessages();
1093 }
1094 }
1095
HandleInit(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1096 void DcSctpSocket::HandleInit(const CommonHeader& header,
1097 const SctpPacket::ChunkDescriptor& descriptor) {
1098 absl::optional<InitChunk> chunk = InitChunk::Parse(descriptor.data);
1099 if (!ValidateParseSuccess(chunk)) {
1100 return;
1101 }
1102
1103 if (chunk->initiate_tag() == VerificationTag(0) ||
1104 chunk->nbr_outbound_streams() == 0 || chunk->nbr_inbound_streams() == 0) {
1105 // https://tools.ietf.org/html/rfc4960#section-3.3.2
1106 // "If the value of the Initiate Tag in a received INIT chunk is found
1107 // to be 0, the receiver MUST treat it as an error and close the
1108 // association by transmitting an ABORT."
1109
1110 // "A receiver of an INIT with the OS value set to 0 SHOULD abort the
1111 // association."
1112
1113 // "A receiver of an INIT with the MIS value of 0 SHOULD abort the
1114 // association."
1115
1116 packet_sender_.Send(
1117 SctpPacket::Builder(VerificationTag(0), options_)
1118 .Add(AbortChunk(
1119 /*filled_in_verification_tag=*/false,
1120 Parameters::Builder()
1121 .Add(ProtocolViolationCause("INIT malformed"))
1122 .Build())));
1123 InternalClose(ErrorKind::kProtocolViolation, "Received invalid INIT");
1124 return;
1125 }
1126
1127 if (state_ == State::kShutdownAckSent) {
1128 // https://tools.ietf.org/html/rfc4960#section-9.2
1129 // "If an endpoint is in the SHUTDOWN-ACK-SENT state and receives an
1130 // INIT chunk (e.g., if the SHUTDOWN COMPLETE was lost) with source and
1131 // destination transport addresses (either in the IP addresses or in the
1132 // INIT chunk) that belong to this association, it should discard the INIT
1133 // chunk and retransmit the SHUTDOWN ACK chunk."
1134 RTC_DLOG(LS_VERBOSE) << log_prefix()
1135 << "Received Init indicating lost ShutdownComplete";
1136 SendShutdownAck();
1137 return;
1138 }
1139
1140 TieTag tie_tag(0);
1141 if (state_ == State::kClosed) {
1142 RTC_DLOG(LS_VERBOSE) << log_prefix()
1143 << "Received Init in closed state (normal)";
1144
1145 MakeConnectionParameters();
1146 } else if (state_ == State::kCookieWait || state_ == State::kCookieEchoed) {
1147 // https://tools.ietf.org/html/rfc4960#section-5.2.1
1148 // "This usually indicates an initialization collision, i.e., each
1149 // endpoint is attempting, at about the same time, to establish an
1150 // association with the other endpoint. Upon receipt of an INIT in the
1151 // COOKIE-WAIT state, an endpoint MUST respond with an INIT ACK using the
1152 // same parameters it sent in its original INIT chunk (including its
1153 // Initiate Tag, unchanged). When responding, the endpoint MUST send the
1154 // INIT ACK back to the same address that the original INIT (sent by this
1155 // endpoint) was sent."
1156 RTC_DLOG(LS_VERBOSE) << log_prefix()
1157 << "Received Init indicating simultaneous connections";
1158 } else {
1159 RTC_DCHECK(tcb_ != nullptr);
1160 // https://tools.ietf.org/html/rfc4960#section-5.2.2
1161 // "The outbound SCTP packet containing this INIT ACK MUST carry a
1162 // Verification Tag value equal to the Initiate Tag found in the
1163 // unexpected INIT. And the INIT ACK MUST contain a new Initiate Tag
1164 // (randomly generated; see Section 5.3.1). Other parameters for the
1165 // endpoint SHOULD be copied from the existing parameters of the
1166 // association (e.g., number of outbound streams) into the INIT ACK and
1167 // cookie."
1168 RTC_DLOG(LS_VERBOSE) << log_prefix()
1169 << "Received Init indicating restarted connection";
1170 // Create a new verification tag - different from the previous one.
1171 for (int tries = 0; tries < 10; ++tries) {
1172 connect_params_.verification_tag = VerificationTag(
1173 callbacks_.GetRandomInt(kMinVerificationTag, kMaxVerificationTag));
1174 if (connect_params_.verification_tag != tcb_->my_verification_tag()) {
1175 break;
1176 }
1177 }
1178
1179 // Make the initial TSN make a large jump, so that there is no overlap
1180 // with the old and new association.
1181 connect_params_.initial_tsn =
1182 TSN(*tcb_->retransmission_queue().next_tsn() + 1000000);
1183 tie_tag = tcb_->tie_tag();
1184 }
1185
1186 RTC_DLOG(LS_VERBOSE)
1187 << log_prefix()
1188 << rtc::StringFormat(
1189 "Proceeding with connection. my_verification_tag=%08x, "
1190 "my_initial_tsn=%u, peer_verification_tag=%08x, "
1191 "peer_initial_tsn=%u",
1192 *connect_params_.verification_tag, *connect_params_.initial_tsn,
1193 *chunk->initiate_tag(), *chunk->initial_tsn());
1194
1195 Capabilities capabilities =
1196 ComputeCapabilities(options_, chunk->nbr_outbound_streams(),
1197 chunk->nbr_inbound_streams(), chunk->parameters());
1198
1199 SctpPacket::Builder b(chunk->initiate_tag(), options_);
1200 Parameters::Builder params_builder =
1201 Parameters::Builder().Add(StateCookieParameter(
1202 StateCookie(chunk->initiate_tag(), chunk->initial_tsn(),
1203 chunk->a_rwnd(), tie_tag, capabilities)
1204 .Serialize()));
1205 AddCapabilityParameters(options_, params_builder);
1206
1207 InitAckChunk init_ack(/*initiate_tag=*/connect_params_.verification_tag,
1208 options_.max_receiver_window_buffer_size,
1209 options_.announced_maximum_outgoing_streams,
1210 options_.announced_maximum_incoming_streams,
1211 connect_params_.initial_tsn, params_builder.Build());
1212 b.Add(init_ack);
1213 packet_sender_.Send(b);
1214 }
1215
HandleInitAck(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1216 void DcSctpSocket::HandleInitAck(
1217 const CommonHeader& header,
1218 const SctpPacket::ChunkDescriptor& descriptor) {
1219 absl::optional<InitAckChunk> chunk = InitAckChunk::Parse(descriptor.data);
1220 if (!ValidateParseSuccess(chunk)) {
1221 return;
1222 }
1223
1224 if (state_ != State::kCookieWait) {
1225 // https://tools.ietf.org/html/rfc4960#section-5.2.3
1226 // "If an INIT ACK is received by an endpoint in any state other than
1227 // the COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk."
1228 RTC_DLOG(LS_VERBOSE) << log_prefix()
1229 << "Received INIT_ACK in unexpected state";
1230 return;
1231 }
1232
1233 auto cookie = chunk->parameters().get<StateCookieParameter>();
1234 if (!cookie.has_value()) {
1235 packet_sender_.Send(
1236 SctpPacket::Builder(connect_params_.verification_tag, options_)
1237 .Add(AbortChunk(
1238 /*filled_in_verification_tag=*/false,
1239 Parameters::Builder()
1240 .Add(ProtocolViolationCause("INIT-ACK malformed"))
1241 .Build())));
1242 InternalClose(ErrorKind::kProtocolViolation,
1243 "InitAck chunk doesn't contain a cookie");
1244 return;
1245 }
1246 Capabilities capabilities =
1247 ComputeCapabilities(options_, chunk->nbr_outbound_streams(),
1248 chunk->nbr_inbound_streams(), chunk->parameters());
1249 t1_init_->Stop();
1250
1251 metrics_.peer_implementation = DeterminePeerImplementation(cookie->data());
1252
1253 // If the connection is re-established (peer restarted, but re-used old
1254 // connection), make sure that all message identifiers are reset and any
1255 // partly sent message is re-sent in full. The same is true when the socket
1256 // is closed and later re-opened, which never happens in WebRTC, but is a
1257 // valid operation on the SCTP level. Note that in case of handover, the
1258 // send queue is already re-configured, and shouldn't be reset.
1259 send_queue_.Reset();
1260
1261 CreateTransmissionControlBlock(capabilities, connect_params_.verification_tag,
1262 connect_params_.initial_tsn,
1263 chunk->initiate_tag(), chunk->initial_tsn(),
1264 chunk->a_rwnd(), MakeTieTag(callbacks_));
1265
1266 SetState(State::kCookieEchoed, "INIT_ACK received");
1267
1268 // The connection isn't fully established just yet.
1269 tcb_->SetCookieEchoChunk(CookieEchoChunk(cookie->data()));
1270 tcb_->SendBufferedPackets(callbacks_.TimeMillis());
1271 t1_cookie_->Start();
1272 }
1273
HandleCookieEcho(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1274 void DcSctpSocket::HandleCookieEcho(
1275 const CommonHeader& header,
1276 const SctpPacket::ChunkDescriptor& descriptor) {
1277 absl::optional<CookieEchoChunk> chunk =
1278 CookieEchoChunk::Parse(descriptor.data);
1279 if (!ValidateParseSuccess(chunk)) {
1280 return;
1281 }
1282
1283 absl::optional<StateCookie> cookie =
1284 StateCookie::Deserialize(chunk->cookie());
1285 if (!cookie.has_value()) {
1286 callbacks_.OnError(ErrorKind::kParseFailed, "Failed to parse state cookie");
1287 return;
1288 }
1289
1290 if (tcb_ != nullptr) {
1291 if (!HandleCookieEchoWithTCB(header, *cookie)) {
1292 return;
1293 }
1294 } else {
1295 if (header.verification_tag != connect_params_.verification_tag) {
1296 callbacks_.OnError(
1297 ErrorKind::kParseFailed,
1298 rtc::StringFormat(
1299 "Received CookieEcho with invalid verification tag: %08x, "
1300 "expected %08x",
1301 *header.verification_tag, *connect_params_.verification_tag));
1302 return;
1303 }
1304 }
1305
1306 // The init timer can be running on simultaneous connections.
1307 t1_init_->Stop();
1308 t1_cookie_->Stop();
1309 if (state_ != State::kEstablished) {
1310 if (tcb_ != nullptr) {
1311 tcb_->ClearCookieEchoChunk();
1312 }
1313 SetState(State::kEstablished, "COOKIE_ECHO received");
1314 callbacks_.OnConnected();
1315 }
1316
1317 if (tcb_ == nullptr) {
1318 // If the connection is re-established (peer restarted, but re-used old
1319 // connection), make sure that all message identifiers are reset and any
1320 // partly sent message is re-sent in full. The same is true when the socket
1321 // is closed and later re-opened, which never happens in WebRTC, but is a
1322 // valid operation on the SCTP level. Note that in case of handover, the
1323 // send queue is already re-configured, and shouldn't be reset.
1324 send_queue_.Reset();
1325
1326 CreateTransmissionControlBlock(
1327 cookie->capabilities(), connect_params_.verification_tag,
1328 connect_params_.initial_tsn, cookie->initiate_tag(),
1329 cookie->initial_tsn(), cookie->a_rwnd(), MakeTieTag(callbacks_));
1330 }
1331
1332 SctpPacket::Builder b = tcb_->PacketBuilder();
1333 b.Add(CookieAckChunk());
1334
1335 // https://tools.ietf.org/html/rfc4960#section-5.1
1336 // "A COOKIE ACK chunk may be bundled with any pending DATA chunks (and/or
1337 // SACK chunks), but the COOKIE ACK chunk MUST be the first chunk in the
1338 // packet."
1339 tcb_->SendBufferedPackets(b, callbacks_.TimeMillis());
1340 }
1341
HandleCookieEchoWithTCB(const CommonHeader & header,const StateCookie & cookie)1342 bool DcSctpSocket::HandleCookieEchoWithTCB(const CommonHeader& header,
1343 const StateCookie& cookie) {
1344 RTC_DLOG(LS_VERBOSE) << log_prefix()
1345 << "Handling CookieEchoChunk with TCB. local_tag="
1346 << *tcb_->my_verification_tag()
1347 << ", peer_tag=" << *header.verification_tag
1348 << ", tcb_tag=" << *tcb_->peer_verification_tag()
1349 << ", cookie_tag=" << *cookie.initiate_tag()
1350 << ", local_tie_tag=" << *tcb_->tie_tag()
1351 << ", peer_tie_tag=" << *cookie.tie_tag();
1352 // https://tools.ietf.org/html/rfc4960#section-5.2.4
1353 // "Handle a COOKIE ECHO when a TCB Exists"
1354 if (header.verification_tag != tcb_->my_verification_tag() &&
1355 tcb_->peer_verification_tag() != cookie.initiate_tag() &&
1356 cookie.tie_tag() == tcb_->tie_tag()) {
1357 // "A) In this case, the peer may have restarted."
1358 if (state_ == State::kShutdownAckSent) {
1359 // "If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
1360 // that the peer has restarted ... it MUST NOT set up a new association
1361 // but instead resend the SHUTDOWN ACK and send an ERROR chunk with a
1362 // "Cookie Received While Shutting Down" error cause to its peer."
1363 SctpPacket::Builder b(cookie.initiate_tag(), options_);
1364 b.Add(ShutdownAckChunk());
1365 b.Add(ErrorChunk(Parameters::Builder()
1366 .Add(CookieReceivedWhileShuttingDownCause())
1367 .Build()));
1368 packet_sender_.Send(b);
1369 callbacks_.OnError(ErrorKind::kWrongSequence,
1370 "Received COOKIE-ECHO while shutting down");
1371 return false;
1372 }
1373
1374 RTC_DLOG(LS_VERBOSE) << log_prefix()
1375 << "Received COOKIE-ECHO indicating a restarted peer";
1376
1377 tcb_ = nullptr;
1378 callbacks_.OnConnectionRestarted();
1379 } else if (header.verification_tag == tcb_->my_verification_tag() &&
1380 tcb_->peer_verification_tag() != cookie.initiate_tag()) {
1381 // TODO(boivie): Handle the peer_tag == 0?
1382 // "B) In this case, both sides may be attempting to start an
1383 // association at about the same time, but the peer endpoint started its
1384 // INIT after responding to the local endpoint's INIT."
1385 RTC_DLOG(LS_VERBOSE)
1386 << log_prefix()
1387 << "Received COOKIE-ECHO indicating simultaneous connections";
1388 tcb_ = nullptr;
1389 } else if (header.verification_tag != tcb_->my_verification_tag() &&
1390 tcb_->peer_verification_tag() == cookie.initiate_tag() &&
1391 cookie.tie_tag() == TieTag(0)) {
1392 // "C) In this case, the local endpoint's cookie has arrived late.
1393 // Before it arrived, the local endpoint sent an INIT and received an
1394 // INIT ACK and finally sent a COOKIE ECHO with the peer's same tag but
1395 // a new tag of its own. The cookie should be silently discarded. The
1396 // endpoint SHOULD NOT change states and should leave any timers
1397 // running."
1398 RTC_DLOG(LS_VERBOSE)
1399 << log_prefix()
1400 << "Received COOKIE-ECHO indicating a late COOKIE-ECHO. Discarding";
1401 return false;
1402 } else if (header.verification_tag == tcb_->my_verification_tag() &&
1403 tcb_->peer_verification_tag() == cookie.initiate_tag()) {
1404 // "D) When both local and remote tags match, the endpoint should enter
1405 // the ESTABLISHED state, if it is in the COOKIE-ECHOED state. It
1406 // should stop any cookie timer that may be running and send a COOKIE
1407 // ACK."
1408 RTC_DLOG(LS_VERBOSE)
1409 << log_prefix()
1410 << "Received duplicate COOKIE-ECHO, probably because of peer not "
1411 "receiving COOKIE-ACK and retransmitting COOKIE-ECHO. Continuing.";
1412 }
1413 return true;
1414 }
1415
HandleCookieAck(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1416 void DcSctpSocket::HandleCookieAck(
1417 const CommonHeader& header,
1418 const SctpPacket::ChunkDescriptor& descriptor) {
1419 absl::optional<CookieAckChunk> chunk = CookieAckChunk::Parse(descriptor.data);
1420 if (!ValidateParseSuccess(chunk)) {
1421 return;
1422 }
1423
1424 if (state_ != State::kCookieEchoed) {
1425 // https://tools.ietf.org/html/rfc4960#section-5.2.5
1426 // "At any state other than COOKIE-ECHOED, an endpoint should silently
1427 // discard a received COOKIE ACK chunk."
1428 RTC_DLOG(LS_VERBOSE) << log_prefix()
1429 << "Received COOKIE_ACK not in COOKIE_ECHOED state";
1430 return;
1431 }
1432
1433 // RFC 4960, Errata ID: 4400
1434 t1_cookie_->Stop();
1435 tcb_->ClearCookieEchoChunk();
1436 SetState(State::kEstablished, "COOKIE_ACK received");
1437 tcb_->SendBufferedPackets(callbacks_.TimeMillis());
1438 callbacks_.OnConnected();
1439 }
1440
DeliverReassembledMessages()1441 void DcSctpSocket::DeliverReassembledMessages() {
1442 if (tcb_->reassembly_queue().HasMessages()) {
1443 for (auto& message : tcb_->reassembly_queue().FlushMessages()) {
1444 ++metrics_.rx_messages_count;
1445 callbacks_.OnMessageReceived(std::move(message));
1446 }
1447 }
1448 }
1449
HandleSack(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1450 void DcSctpSocket::HandleSack(const CommonHeader& header,
1451 const SctpPacket::ChunkDescriptor& descriptor) {
1452 absl::optional<SackChunk> chunk = SackChunk::Parse(descriptor.data);
1453
1454 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1455 TimeMs now = callbacks_.TimeMillis();
1456 SackChunk sack = ChunkValidators::Clean(*std::move(chunk));
1457
1458 if (tcb_->retransmission_queue().HandleSack(now, sack)) {
1459 MaybeSendShutdownOrAck();
1460 // Receiving an ACK may make the socket go into fast recovery mode.
1461 // https://datatracker.ietf.org/doc/html/rfc4960#section-7.2.4
1462 // "Determine how many of the earliest (i.e., lowest TSN) DATA chunks
1463 // marked for retransmission will fit into a single packet, subject to
1464 // constraint of the path MTU of the destination transport address to
1465 // which the packet is being sent. Call this value K. Retransmit those K
1466 // DATA chunks in a single packet. When a Fast Retransmit is being
1467 // performed, the sender SHOULD ignore the value of cwnd and SHOULD NOT
1468 // delay retransmission for this single packet."
1469 tcb_->MaybeSendFastRetransmit();
1470
1471 // Receiving an ACK will decrease outstanding bytes (maybe now below
1472 // cwnd?) or indicate packet loss that may result in sending FORWARD-TSN.
1473 tcb_->SendBufferedPackets(now);
1474 } else {
1475 RTC_DLOG(LS_VERBOSE) << log_prefix()
1476 << "Dropping out-of-order SACK with TSN "
1477 << *sack.cumulative_tsn_ack();
1478 }
1479 }
1480 }
1481
HandleHeartbeatRequest(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1482 void DcSctpSocket::HandleHeartbeatRequest(
1483 const CommonHeader& header,
1484 const SctpPacket::ChunkDescriptor& descriptor) {
1485 absl::optional<HeartbeatRequestChunk> chunk =
1486 HeartbeatRequestChunk::Parse(descriptor.data);
1487
1488 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1489 tcb_->heartbeat_handler().HandleHeartbeatRequest(*std::move(chunk));
1490 }
1491 }
1492
HandleHeartbeatAck(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1493 void DcSctpSocket::HandleHeartbeatAck(
1494 const CommonHeader& header,
1495 const SctpPacket::ChunkDescriptor& descriptor) {
1496 absl::optional<HeartbeatAckChunk> chunk =
1497 HeartbeatAckChunk::Parse(descriptor.data);
1498
1499 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1500 tcb_->heartbeat_handler().HandleHeartbeatAck(*std::move(chunk));
1501 }
1502 }
1503
HandleAbort(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1504 void DcSctpSocket::HandleAbort(const CommonHeader& header,
1505 const SctpPacket::ChunkDescriptor& descriptor) {
1506 absl::optional<AbortChunk> chunk = AbortChunk::Parse(descriptor.data);
1507 if (ValidateParseSuccess(chunk)) {
1508 std::string error_string = ErrorCausesToString(chunk->error_causes());
1509 if (tcb_ == nullptr) {
1510 // https://tools.ietf.org/html/rfc4960#section-3.3.7
1511 // "If an endpoint receives an ABORT with a format error or no TCB is
1512 // found, it MUST silently discard it."
1513 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received ABORT (" << error_string
1514 << ") on a connection with no TCB. Ignoring";
1515 return;
1516 }
1517
1518 RTC_DLOG(LS_WARNING) << log_prefix() << "Received ABORT (" << error_string
1519 << ") - closing connection.";
1520 InternalClose(ErrorKind::kPeerReported, error_string);
1521 }
1522 }
1523
HandleError(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1524 void DcSctpSocket::HandleError(const CommonHeader& header,
1525 const SctpPacket::ChunkDescriptor& descriptor) {
1526 absl::optional<ErrorChunk> chunk = ErrorChunk::Parse(descriptor.data);
1527 if (ValidateParseSuccess(chunk)) {
1528 std::string error_string = ErrorCausesToString(chunk->error_causes());
1529 if (tcb_ == nullptr) {
1530 RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received ERROR (" << error_string
1531 << ") on a connection with no TCB. Ignoring";
1532 return;
1533 }
1534
1535 RTC_DLOG(LS_WARNING) << log_prefix() << "Received ERROR: " << error_string;
1536 callbacks_.OnError(ErrorKind::kPeerReported,
1537 "Peer reported error: " + error_string);
1538 }
1539 }
1540
HandleReconfig(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1541 void DcSctpSocket::HandleReconfig(
1542 const CommonHeader& header,
1543 const SctpPacket::ChunkDescriptor& descriptor) {
1544 TimeMs now = callbacks_.TimeMillis();
1545 absl::optional<ReConfigChunk> chunk = ReConfigChunk::Parse(descriptor.data);
1546 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1547 tcb_->stream_reset_handler().HandleReConfig(*std::move(chunk));
1548 // Handling this response may result in outgoing stream resets finishing
1549 // (either successfully or with failure). If there still are pending streams
1550 // that were waiting for this request to finish, continue resetting them.
1551 MaybeSendResetStreamsRequest();
1552
1553 // If a response was processed, pending to-be-reset streams may now have
1554 // become unpaused. Try to send more DATA chunks.
1555 tcb_->SendBufferedPackets(now);
1556 }
1557 }
1558
HandleShutdown(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1559 void DcSctpSocket::HandleShutdown(
1560 const CommonHeader& header,
1561 const SctpPacket::ChunkDescriptor& descriptor) {
1562 if (!ValidateParseSuccess(ShutdownChunk::Parse(descriptor.data))) {
1563 return;
1564 }
1565
1566 if (state_ == State::kClosed) {
1567 return;
1568 } else if (state_ == State::kCookieWait || state_ == State::kCookieEchoed) {
1569 // https://tools.ietf.org/html/rfc4960#section-9.2
1570 // "If a SHUTDOWN is received in the COOKIE-WAIT or COOKIE ECHOED state,
1571 // the SHUTDOWN chunk SHOULD be silently discarded."
1572 } else if (state_ == State::kShutdownSent) {
1573 // https://tools.ietf.org/html/rfc4960#section-9.2
1574 // "If an endpoint is in the SHUTDOWN-SENT state and receives a
1575 // SHUTDOWN chunk from its peer, the endpoint shall respond immediately
1576 // with a SHUTDOWN ACK to its peer, and move into the SHUTDOWN-ACK-SENT
1577 // state restarting its T2-shutdown timer."
1578 SendShutdownAck();
1579 SetState(State::kShutdownAckSent, "SHUTDOWN received");
1580 } else if (state_ == State::kShutdownAckSent) {
1581 // TODO(webrtc:12739): This condition should be removed and handled by the
1582 // next (state_ != State::kShutdownReceived).
1583 return;
1584 } else if (state_ != State::kShutdownReceived) {
1585 RTC_DLOG(LS_VERBOSE) << log_prefix()
1586 << "Received SHUTDOWN - shutting down the socket";
1587 // https://tools.ietf.org/html/rfc4960#section-9.2
1588 // "Upon reception of the SHUTDOWN, the peer endpoint shall enter the
1589 // SHUTDOWN-RECEIVED state, stop accepting new data from its SCTP user,
1590 // and verify, by checking the Cumulative TSN Ack field of the chunk, that
1591 // all its outstanding DATA chunks have been received by the SHUTDOWN
1592 // sender."
1593 SetState(State::kShutdownReceived, "SHUTDOWN received");
1594 MaybeSendShutdownOrAck();
1595 }
1596 }
1597
HandleShutdownAck(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1598 void DcSctpSocket::HandleShutdownAck(
1599 const CommonHeader& header,
1600 const SctpPacket::ChunkDescriptor& descriptor) {
1601 if (!ValidateParseSuccess(ShutdownAckChunk::Parse(descriptor.data))) {
1602 return;
1603 }
1604
1605 if (state_ == State::kShutdownSent || state_ == State::kShutdownAckSent) {
1606 // https://tools.ietf.org/html/rfc4960#section-9.2
1607 // "Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall stop
1608 // the T2-shutdown timer, send a SHUTDOWN COMPLETE chunk to its peer, and
1609 // remove all record of the association."
1610
1611 // "If an endpoint is in the SHUTDOWN-ACK-SENT state and receives a
1612 // SHUTDOWN ACK, it shall stop the T2-shutdown timer, send a SHUTDOWN
1613 // COMPLETE chunk to its peer, and remove all record of the association."
1614
1615 SctpPacket::Builder b = tcb_->PacketBuilder();
1616 b.Add(ShutdownCompleteChunk(/*tag_reflected=*/false));
1617 packet_sender_.Send(b);
1618 InternalClose(ErrorKind::kNoError, "");
1619 } else {
1620 // https://tools.ietf.org/html/rfc4960#section-8.5.1
1621 // "If the receiver is in COOKIE-ECHOED or COOKIE-WAIT state
1622 // the procedures in Section 8.4 SHOULD be followed; in other words, it
1623 // should be treated as an Out Of The Blue packet."
1624
1625 // https://tools.ietf.org/html/rfc4960#section-8.4
1626 // "If the packet contains a SHUTDOWN ACK chunk, the receiver
1627 // should respond to the sender of the OOTB packet with a SHUTDOWN
1628 // COMPLETE. When sending the SHUTDOWN COMPLETE, the receiver of the OOTB
1629 // packet must fill in the Verification Tag field of the outbound packet
1630 // with the Verification Tag received in the SHUTDOWN ACK and set the T
1631 // bit in the Chunk Flags to indicate that the Verification Tag is
1632 // reflected."
1633
1634 SctpPacket::Builder b(header.verification_tag, options_);
1635 b.Add(ShutdownCompleteChunk(/*tag_reflected=*/true));
1636 packet_sender_.Send(b);
1637 }
1638 }
1639
HandleShutdownComplete(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1640 void DcSctpSocket::HandleShutdownComplete(
1641 const CommonHeader& header,
1642 const SctpPacket::ChunkDescriptor& descriptor) {
1643 if (!ValidateParseSuccess(ShutdownCompleteChunk::Parse(descriptor.data))) {
1644 return;
1645 }
1646
1647 if (state_ == State::kShutdownAckSent) {
1648 // https://tools.ietf.org/html/rfc4960#section-9.2
1649 // "Upon reception of the SHUTDOWN COMPLETE chunk, the endpoint will
1650 // verify that it is in the SHUTDOWN-ACK-SENT state; if it is not, the
1651 // chunk should be discarded. If the endpoint is in the SHUTDOWN-ACK-SENT
1652 // state, the endpoint should stop the T2-shutdown timer and remove all
1653 // knowledge of the association (and thus the association enters the
1654 // CLOSED state)."
1655 InternalClose(ErrorKind::kNoError, "");
1656 }
1657 }
1658
HandleForwardTsn(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1659 void DcSctpSocket::HandleForwardTsn(
1660 const CommonHeader& header,
1661 const SctpPacket::ChunkDescriptor& descriptor) {
1662 absl::optional<ForwardTsnChunk> chunk =
1663 ForwardTsnChunk::Parse(descriptor.data);
1664 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1665 HandleForwardTsnCommon(*chunk);
1666 }
1667 }
1668
HandleIForwardTsn(const CommonHeader & header,const SctpPacket::ChunkDescriptor & descriptor)1669 void DcSctpSocket::HandleIForwardTsn(
1670 const CommonHeader& header,
1671 const SctpPacket::ChunkDescriptor& descriptor) {
1672 absl::optional<IForwardTsnChunk> chunk =
1673 IForwardTsnChunk::Parse(descriptor.data);
1674 if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
1675 HandleForwardTsnCommon(*chunk);
1676 }
1677 }
1678
HandleForwardTsnCommon(const AnyForwardTsnChunk & chunk)1679 void DcSctpSocket::HandleForwardTsnCommon(const AnyForwardTsnChunk& chunk) {
1680 if (!tcb_->capabilities().partial_reliability) {
1681 SctpPacket::Builder b = tcb_->PacketBuilder();
1682 b.Add(AbortChunk(/*filled_in_verification_tag=*/true,
1683 Parameters::Builder()
1684 .Add(ProtocolViolationCause(
1685 "I-FORWARD-TSN received, but not indicated "
1686 "during connection establishment"))
1687 .Build()));
1688 packet_sender_.Send(b);
1689
1690 callbacks_.OnError(ErrorKind::kProtocolViolation,
1691 "Received a FORWARD_TSN without announced peer support");
1692 return;
1693 }
1694 tcb_->data_tracker().HandleForwardTsn(chunk.new_cumulative_tsn());
1695 tcb_->reassembly_queue().Handle(chunk);
1696 // A forward TSN - for ordered streams - may allow messages to be
1697 // delivered.
1698 DeliverReassembledMessages();
1699
1700 // Processing a FORWARD_TSN might result in sending a SACK.
1701 tcb_->MaybeSendSack();
1702 }
1703
MaybeSendShutdownOrAck()1704 void DcSctpSocket::MaybeSendShutdownOrAck() {
1705 if (tcb_->retransmission_queue().outstanding_bytes() != 0) {
1706 return;
1707 }
1708
1709 if (state_ == State::kShutdownPending) {
1710 // https://tools.ietf.org/html/rfc4960#section-9.2
1711 // "Once all its outstanding data has been acknowledged, the endpoint
1712 // shall send a SHUTDOWN chunk to its peer including in the Cumulative TSN
1713 // Ack field the last sequential TSN it has received from the peer. It
1714 // shall then start the T2-shutdown timer and enter the SHUTDOWN-SENT
1715 // state.""
1716
1717 SendShutdown();
1718 t2_shutdown_->set_duration(tcb_->current_rto());
1719 t2_shutdown_->Start();
1720 SetState(State::kShutdownSent, "No more outstanding data");
1721 } else if (state_ == State::kShutdownReceived) {
1722 // https://tools.ietf.org/html/rfc4960#section-9.2
1723 // "If the receiver of the SHUTDOWN has no more outstanding DATA
1724 // chunks, the SHUTDOWN receiver MUST send a SHUTDOWN ACK and start a
1725 // T2-shutdown timer of its own, entering the SHUTDOWN-ACK-SENT state. If
1726 // the timer expires, the endpoint must resend the SHUTDOWN ACK."
1727
1728 SendShutdownAck();
1729 SetState(State::kShutdownAckSent, "No more outstanding data");
1730 }
1731 }
1732
SendShutdown()1733 void DcSctpSocket::SendShutdown() {
1734 SctpPacket::Builder b = tcb_->PacketBuilder();
1735 b.Add(ShutdownChunk(tcb_->data_tracker().last_cumulative_acked_tsn()));
1736 packet_sender_.Send(b);
1737 }
1738
SendShutdownAck()1739 void DcSctpSocket::SendShutdownAck() {
1740 packet_sender_.Send(tcb_->PacketBuilder().Add(ShutdownAckChunk()));
1741 t2_shutdown_->set_duration(tcb_->current_rto());
1742 t2_shutdown_->Start();
1743 }
1744
GetHandoverReadiness() const1745 HandoverReadinessStatus DcSctpSocket::GetHandoverReadiness() const {
1746 RTC_DCHECK_RUN_ON(&thread_checker_);
1747 HandoverReadinessStatus status;
1748 if (state_ != State::kClosed && state_ != State::kEstablished) {
1749 status.Add(HandoverUnreadinessReason::kWrongConnectionState);
1750 }
1751 status.Add(send_queue_.GetHandoverReadiness());
1752 if (tcb_) {
1753 status.Add(tcb_->GetHandoverReadiness());
1754 }
1755 return status;
1756 }
1757
1758 absl::optional<DcSctpSocketHandoverState>
GetHandoverStateAndClose()1759 DcSctpSocket::GetHandoverStateAndClose() {
1760 RTC_DCHECK_RUN_ON(&thread_checker_);
1761 CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
1762
1763 if (!GetHandoverReadiness().IsReady()) {
1764 return absl::nullopt;
1765 }
1766
1767 DcSctpSocketHandoverState state;
1768
1769 if (state_ == State::kClosed) {
1770 state.socket_state = DcSctpSocketHandoverState::SocketState::kClosed;
1771 } else if (state_ == State::kEstablished) {
1772 state.socket_state = DcSctpSocketHandoverState::SocketState::kConnected;
1773 tcb_->AddHandoverState(state);
1774 send_queue_.AddHandoverState(state);
1775 InternalClose(ErrorKind::kNoError, "handover");
1776 }
1777
1778 return std::move(state);
1779 }
1780
1781 } // namespace dcsctp
1782