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