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