xref: /aosp_15_r20/external/webrtc/net/dcsctp/socket/dcsctp_socket.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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