blob: 157c515d65f9effbba0b46800f798e0b90f9faa6 [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#ifndef NET_DCSCTP_SOCKET_DCSCTP_SOCKET_H_
11#define NET_DCSCTP_SOCKET_DCSCTP_SOCKET_H_
12
13#include <cstdint>
14#include <memory>
15#include <string>
16#include <utility>
17
18#include "absl/strings/string_view.h"
19#include "api/array_view.h"
Victor Boivie5755f3e2021-09-29 22:23:15 +020020#include "api/sequence_checker.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020021#include "net/dcsctp/packet/chunk/abort_chunk.h"
22#include "net/dcsctp/packet/chunk/chunk.h"
23#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
24#include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
25#include "net/dcsctp/packet/chunk/data_chunk.h"
26#include "net/dcsctp/packet/chunk/data_common.h"
27#include "net/dcsctp/packet/chunk/error_chunk.h"
28#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
29#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
30#include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
31#include "net/dcsctp/packet/chunk/heartbeat_request_chunk.h"
32#include "net/dcsctp/packet/chunk/idata_chunk.h"
33#include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
34#include "net/dcsctp/packet/chunk/init_ack_chunk.h"
35#include "net/dcsctp/packet/chunk/init_chunk.h"
36#include "net/dcsctp/packet/chunk/reconfig_chunk.h"
37#include "net/dcsctp/packet/chunk/sack_chunk.h"
38#include "net/dcsctp/packet/chunk/shutdown_ack_chunk.h"
39#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
40#include "net/dcsctp/packet/chunk/shutdown_complete_chunk.h"
41#include "net/dcsctp/packet/data.h"
42#include "net/dcsctp/packet/sctp_packet.h"
43#include "net/dcsctp/public/dcsctp_message.h"
44#include "net/dcsctp/public/dcsctp_options.h"
45#include "net/dcsctp/public/dcsctp_socket.h"
46#include "net/dcsctp/public/packet_observer.h"
47#include "net/dcsctp/rx/data_tracker.h"
48#include "net/dcsctp/rx/reassembly_queue.h"
49#include "net/dcsctp/socket/callback_deferrer.h"
Victor Boivieabf61882021-08-12 15:57:49 +020050#include "net/dcsctp/socket/packet_sender.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020051#include "net/dcsctp/socket/state_cookie.h"
52#include "net/dcsctp/socket/transmission_control_block.h"
53#include "net/dcsctp/timer/timer.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020054#include "net/dcsctp/tx/retransmission_error_counter.h"
55#include "net/dcsctp/tx/retransmission_queue.h"
56#include "net/dcsctp/tx/retransmission_timeout.h"
Victor Boivie2440d342021-05-20 13:47:32 +020057#include "net/dcsctp/tx/rr_send_queue.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020058
59namespace dcsctp {
60
61// DcSctpSocket represents a single SCTP socket, to be used over DTLS.
62//
63// Every dcSCTP is completely isolated from any other socket.
64//
65// This class manages all packet and chunk dispatching and mainly handles the
66// connection sequences (connect, close, shutdown, etc) as well as managing
67// the Transmission Control Block (tcb).
68//
69// This class is thread-compatible.
70class DcSctpSocket : public DcSctpSocketInterface {
71 public:
72 // Instantiates a DcSctpSocket, which interacts with the world through the
73 // `callbacks` interface and is configured using `options`.
74 //
75 // For debugging, `log_prefix` will prefix all debug logs, and a
76 // `packet_observer` can be attached to e.g. dump sent and received packets.
77 DcSctpSocket(absl::string_view log_prefix,
78 DcSctpSocketCallbacks& callbacks,
79 std::unique_ptr<PacketObserver> packet_observer,
80 const DcSctpOptions& options);
81
82 DcSctpSocket(const DcSctpSocket&) = delete;
83 DcSctpSocket& operator=(const DcSctpSocket&) = delete;
84
85 // Implementation of `DcSctpSocketInterface`.
86 void ReceivePacket(rtc::ArrayView<const uint8_t> data) override;
87 void HandleTimeout(TimeoutID timeout_id) override;
88 void Connect() override;
Sergey Sukhanov43972812021-09-17 15:32:48 +020089 void RestoreFromState(const DcSctpSocketHandoverState& state) override;
Victor Boivieb6580cc2021-04-08 09:56:59 +020090 void Shutdown() override;
91 void Close() override;
92 SendStatus Send(DcSctpMessage message,
93 const SendOptions& send_options) override;
94 ResetStreamsStatus ResetStreams(
95 rtc::ArrayView<const StreamID> outgoing_streams) override;
96 SocketState state() const override;
97 const DcSctpOptions& options() const override { return options_; }
Florent Castelli0810b052021-05-04 20:12:52 +020098 void SetMaxMessageSize(size_t max_message_size) override;
Victor Boivie7e897ae2022-05-02 13:04:37 +020099 void SetStreamPriority(StreamID stream_id, StreamPriority priority) override;
100 StreamPriority GetStreamPriority(StreamID stream_id) const override;
Victor Boivie236ac502021-05-20 19:34:18 +0200101 size_t buffered_amount(StreamID stream_id) const override;
102 size_t buffered_amount_low_threshold(StreamID stream_id) const override;
103 void SetBufferedAmountLowThreshold(StreamID stream_id, size_t bytes) override;
Victor Boivief7fc71d2022-05-13 14:27:55 +0200104 absl::optional<Metrics> GetMetrics() const override;
Sergey Sukhanov43972812021-09-17 15:32:48 +0200105 HandoverReadinessStatus GetHandoverReadiness() const override;
106 absl::optional<DcSctpSocketHandoverState> GetHandoverStateAndClose() override;
Victor Boivief4fa1662021-09-24 23:01:21 +0200107 SctpImplementation peer_implementation() const override {
Victor Boivief7fc71d2022-05-13 14:27:55 +0200108 return metrics_.peer_implementation;
Victor Boivief4fa1662021-09-24 23:01:21 +0200109 }
Victor Boivieb6580cc2021-04-08 09:56:59 +0200110 // Returns this socket's verification tag, or zero if not yet connected.
111 VerificationTag verification_tag() const {
112 return tcb_ != nullptr ? tcb_->my_verification_tag() : VerificationTag(0);
113 }
114
115 private:
116 // Parameter proposals valid during the connect phase.
117 struct ConnectParameters {
118 TSN initial_tsn = TSN(0);
119 VerificationTag verification_tag = VerificationTag(0);
120 };
121
122 // Detailed state (separate from SocketState, which is the public state).
123 enum class State {
124 kClosed,
125 kCookieWait,
126 // TCB valid in these:
127 kCookieEchoed,
128 kEstablished,
129 kShutdownPending,
130 kShutdownSent,
131 kShutdownReceived,
132 kShutdownAckSent,
133 };
134
135 // Returns the log prefix used for debug logging.
136 std::string log_prefix() const;
137
138 bool IsConsistent() const;
139 static constexpr absl::string_view ToString(DcSctpSocket::State state);
140
Victor Boivie2cffde72022-06-27 20:35:37 +0000141 void CreateTransmissionControlBlock(const Capabilities& capabilities,
142 VerificationTag my_verification_tag,
143 TSN my_initial_tsn,
144 VerificationTag peer_verification_tag,
145 TSN peer_initial_tsn,
146 size_t a_rwnd,
147 TieTag tie_tag);
148
Victor Boivieb6580cc2021-04-08 09:56:59 +0200149 // Changes the socket state, given a `reason` (for debugging/logging).
150 void SetState(State state, absl::string_view reason);
151 // Fills in `connect_params` with random verification tag and initial TSN.
152 void MakeConnectionParameters();
153 // Closes the association. Note that the TCB will not be valid past this call.
154 void InternalClose(ErrorKind error, absl::string_view message);
155 // Closes the association, because of too many retransmission errors.
156 void CloseConnectionBecauseOfTooManyTransmissionErrors();
157 // Timer expiration handlers
158 absl::optional<DurationMs> OnInitTimerExpiry();
159 absl::optional<DurationMs> OnCookieTimerExpiry();
160 absl::optional<DurationMs> OnShutdownTimerExpiry();
Victor Boivieabf61882021-08-12 15:57:49 +0200161 void OnSentPacket(rtc::ArrayView<const uint8_t> packet,
162 SendPacketStatus status);
Victor Boivieb6580cc2021-04-08 09:56:59 +0200163 // Sends SHUTDOWN or SHUTDOWN-ACK if the socket is shutting down and if all
164 // outstanding data has been acknowledged.
165 void MaybeSendShutdownOrAck();
166 // If the socket is shutting down, responds SHUTDOWN to any incoming DATA.
167 void MaybeSendShutdownOnPacketReceived(const SctpPacket& packet);
Victor Boivief9e116f2022-03-31 17:15:03 +0200168 // If there are streams pending to be reset, send a request to reset them.
169 void MaybeSendResetStreamsRequest();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200170 // Sends a INIT chunk.
171 void SendInit();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200172 // Sends a SHUTDOWN chunk.
173 void SendShutdown();
174 // Sends a SHUTDOWN-ACK chunk.
175 void SendShutdownAck();
176 // Validates the SCTP packet, as a whole - not the validity of individual
177 // chunks within it, as that's done in the different chunk handlers.
178 bool ValidatePacket(const SctpPacket& packet);
179 // Parses `payload`, which is a serialized packet that is just going to be
180 // sent and prints all chunks.
181 void DebugPrintOutgoing(rtc::ArrayView<const uint8_t> payload);
182 // Called whenever there may be reassembled messages, and delivers those.
183 void DeliverReassembledMessages();
184 // Returns true if there is a TCB, and false otherwise (and reports an error).
185 bool ValidateHasTCB();
186
187 // Returns true if the parsing of a chunk of type `T` succeeded. If it didn't,
188 // it reports an error and returns false.
189 template <class T>
190 bool ValidateParseSuccess(const absl::optional<T>& c) {
191 if (c.has_value()) {
192 return true;
193 }
194
195 ReportFailedToParseChunk(T::kType);
196 return false;
197 }
198
199 // Reports failing to have parsed a chunk with the provided `chunk_type`.
200 void ReportFailedToParseChunk(int chunk_type);
201 // Called when unknown chunks are received. May report an error.
202 bool HandleUnrecognizedChunk(const SctpPacket::ChunkDescriptor& descriptor);
203
204 // Will dispatch more specific chunk handlers.
205 bool Dispatch(const CommonHeader& header,
206 const SctpPacket::ChunkDescriptor& descriptor);
207 // Handles incoming DATA chunks.
208 void HandleData(const CommonHeader& header,
209 const SctpPacket::ChunkDescriptor& descriptor);
210 // Handles incoming I-DATA chunks.
211 void HandleIData(const CommonHeader& header,
212 const SctpPacket::ChunkDescriptor& descriptor);
213 // Common handler for DATA and I-DATA chunks.
214 void HandleDataCommon(AnyDataChunk& chunk);
215 // Handles incoming INIT chunks.
216 void HandleInit(const CommonHeader& header,
217 const SctpPacket::ChunkDescriptor& descriptor);
218 // Handles incoming INIT-ACK chunks.
219 void HandleInitAck(const CommonHeader& header,
220 const SctpPacket::ChunkDescriptor& descriptor);
221 // Handles incoming SACK chunks.
222 void HandleSack(const CommonHeader& header,
223 const SctpPacket::ChunkDescriptor& descriptor);
224 // Handles incoming HEARTBEAT chunks.
225 void HandleHeartbeatRequest(const CommonHeader& header,
226 const SctpPacket::ChunkDescriptor& descriptor);
227 // Handles incoming HEARTBEAT-ACK chunks.
228 void HandleHeartbeatAck(const CommonHeader& header,
229 const SctpPacket::ChunkDescriptor& descriptor);
230 // Handles incoming ABORT chunks.
231 void HandleAbort(const CommonHeader& header,
232 const SctpPacket::ChunkDescriptor& descriptor);
233 // Handles incoming ERROR chunks.
234 void HandleError(const CommonHeader& header,
235 const SctpPacket::ChunkDescriptor& descriptor);
236 // Handles incoming COOKIE-ECHO chunks.
237 void HandleCookieEcho(const CommonHeader& header,
238 const SctpPacket::ChunkDescriptor& descriptor);
239 // Handles receiving COOKIE-ECHO when there already is a TCB. The return value
240 // indicates if the processing should continue.
241 bool HandleCookieEchoWithTCB(const CommonHeader& header,
242 const StateCookie& cookie);
243 // Handles incoming COOKIE-ACK chunks.
244 void HandleCookieAck(const CommonHeader& header,
245 const SctpPacket::ChunkDescriptor& descriptor);
246 // Handles incoming SHUTDOWN chunks.
247 void HandleShutdown(const CommonHeader& header,
248 const SctpPacket::ChunkDescriptor& descriptor);
249 // Handles incoming SHUTDOWN-ACK chunks.
250 void HandleShutdownAck(const CommonHeader& header,
251 const SctpPacket::ChunkDescriptor& descriptor);
252 // Handles incoming FORWARD-TSN chunks.
253 void HandleForwardTsn(const CommonHeader& header,
254 const SctpPacket::ChunkDescriptor& descriptor);
255 // Handles incoming I-FORWARD-TSN chunks.
256 void HandleIForwardTsn(const CommonHeader& header,
257 const SctpPacket::ChunkDescriptor& descriptor);
258 // Handles incoming RE-CONFIG chunks.
259 void HandleReconfig(const CommonHeader& header,
260 const SctpPacket::ChunkDescriptor& descriptor);
261 // Common handled for FORWARD-TSN/I-FORWARD-TSN.
262 void HandleForwardTsnCommon(const AnyForwardTsnChunk& chunk);
263 // Handles incoming SHUTDOWN-COMPLETE chunks
264 void HandleShutdownComplete(const CommonHeader& header,
265 const SctpPacket::ChunkDescriptor& descriptor);
266
267 const std::string log_prefix_;
268 const std::unique_ptr<PacketObserver> packet_observer_;
Victor Boivie5755f3e2021-09-29 22:23:15 +0200269 RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker thread_checker_;
Victor Boivied4716ea2021-08-09 12:26:32 +0200270 Metrics metrics_;
Florent Castelli0810b052021-05-04 20:12:52 +0200271 DcSctpOptions options_;
Victor Boivieb6580cc2021-04-08 09:56:59 +0200272
273 // Enqueues callbacks and dispatches them just before returning to the caller.
274 CallbackDeferrer callbacks_;
275
276 TimerManager timer_manager_;
277 const std::unique_ptr<Timer> t1_init_;
278 const std::unique_ptr<Timer> t1_cookie_;
279 const std::unique_ptr<Timer> t2_shutdown_;
280
Victor Boivieabf61882021-08-12 15:57:49 +0200281 // Packets that failed to be sent, but should be retried.
282 PacketSender packet_sender_;
283
Victor Boivieb6580cc2021-04-08 09:56:59 +0200284 // The actual SendQueue implementation. As data can be sent on a socket before
285 // the connection is established, this component is not in the TCB.
Victor Boivie2440d342021-05-20 13:47:32 +0200286 RRSendQueue send_queue_;
Victor Boivieb6580cc2021-04-08 09:56:59 +0200287
Victor Boivieb6580cc2021-04-08 09:56:59 +0200288 // Contains verification tag and initial TSN between having sent the INIT
289 // until the connection is established (there is no TCB at this point).
290 ConnectParameters connect_params_;
291 // The socket state.
292 State state_ = State::kClosed;
293 // If the connection is established, contains a transmission control block.
294 std::unique_ptr<TransmissionControlBlock> tcb_;
Victor Boivieb6580cc2021-04-08 09:56:59 +0200295};
296} // namespace dcsctp
297
298#endif // NET_DCSCTP_SOCKET_DCSCTP_SOCKET_H_