xref: /aosp_15_r20/external/webrtc/net/dcsctp/socket/dcsctp_socket.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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"
20 #include "api/sequence_checker.h"
21 #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"
50 #include "net/dcsctp/socket/packet_sender.h"
51 #include "net/dcsctp/socket/state_cookie.h"
52 #include "net/dcsctp/socket/transmission_control_block.h"
53 #include "net/dcsctp/timer/timer.h"
54 #include "net/dcsctp/tx/retransmission_error_counter.h"
55 #include "net/dcsctp/tx/retransmission_queue.h"
56 #include "net/dcsctp/tx/retransmission_timeout.h"
57 #include "net/dcsctp/tx/rr_send_queue.h"
58 
59 namespace 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.
70 class 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;
89   void RestoreFromState(const DcSctpSocketHandoverState& state) override;
90   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;
options()97   const DcSctpOptions& options() const override { return options_; }
98   void SetMaxMessageSize(size_t max_message_size) override;
99   void SetStreamPriority(StreamID stream_id, StreamPriority priority) override;
100   StreamPriority GetStreamPriority(StreamID stream_id) const override;
101   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;
104   absl::optional<Metrics> GetMetrics() const override;
105   HandoverReadinessStatus GetHandoverReadiness() const override;
106   absl::optional<DcSctpSocketHandoverState> GetHandoverStateAndClose() override;
peer_implementation()107   SctpImplementation peer_implementation() const override {
108     return metrics_.peer_implementation;
109   }
110   // Returns this socket's verification tag, or zero if not yet connected.
verification_tag()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 
141   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 
149   // 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();
161   void OnSentPacket(rtc::ArrayView<const uint8_t> packet,
162                     SendPacketStatus status);
163   // 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);
168   // If there are streams pending to be reset, send a request to reset them.
169   void MaybeSendResetStreamsRequest();
170   // Sends a INIT chunk.
171   void SendInit();
172   // 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>
ValidateParseSuccess(const absl::optional<T> & c)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_;
269   RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker thread_checker_;
270   Metrics metrics_;
271   DcSctpOptions options_;
272 
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 
281   // Packets that failed to be sent, but should be retried.
282   PacketSender packet_sender_;
283 
284   // 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.
286   RRSendQueue send_queue_;
287 
288   // 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_;
295 };
296 }  // namespace dcsctp
297 
298 #endif  // NET_DCSCTP_SOCKET_DCSCTP_SOCKET_H_
299