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