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