blob: 13bebd4612e51a773e6dff37e527fb3a4c600422 [file] [log] [blame]
ossu7bb87ee2017-01-23 12:56:251/*
Taylor Brandstetter3a034e12020-07-09 22:32:342 * Copyright 2020 The WebRTC project authors. All Rights Reserved.
ossu7bb87ee2017-01-23 12:56:253 *
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
Taylor Brandstetter3a034e12020-07-09 22:32:3411#ifndef PC_SCTP_DATA_CHANNEL_H_
12#define PC_SCTP_DATA_CHANNEL_H_
ossu7bb87ee2017-01-23 12:56:2513
Harald Alvestrand5761e7b2021-01-29 14:45:0814#include <stdint.h>
15
Steve Anton944c7552018-12-13 22:19:1016#include <memory>
ossu7bb87ee2017-01-23 12:56:2517#include <set>
18#include <string>
19
Harald Alvestrand5761e7b2021-01-29 14:45:0820#include "absl/types/optional.h"
Steve Anton10542f22019-01-11 17:11:0021#include "api/data_channel_interface.h"
Harald Alvestrandfd5ae7f2020-05-16 06:37:4922#include "api/priority.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0823#include "api/rtc_error.h"
Mirko Bonadeid9708072019-01-25 19:26:4824#include "api/scoped_refptr.h"
Tommi8efaec62023-03-21 17:45:2425#include "api/sequence_checker.h"
Tommia50a81a2023-04-11 15:32:3426#include "api/task_queue/pending_task_safety_flag.h"
Niels Möller2a707032020-06-16 14:39:1327#include "api/transport/data_channel_transport_interface.h"
Taylor Brandstetter3a034e12020-07-09 22:32:3428#include "pc/data_channel_utils.h"
Tommi492296c2023-03-12 15:59:2529#include "pc/sctp_utils.h"
30#include "rtc_base/containers/flat_set.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0831#include "rtc_base/copy_on_write_buffer.h"
Taylor Brandstetter3a034e12020-07-09 22:32:3432#include "rtc_base/ssl_stream_adapter.h" // For SSLRole
Tommi8efaec62023-03-21 17:45:2433#include "rtc_base/system/no_unique_address.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0834#include "rtc_base/thread.h"
35#include "rtc_base/thread_annotations.h"
Tommi1c0d91f2023-03-02 14:42:0636#include "rtc_base/weak_ptr.h"
ossu7bb87ee2017-01-23 12:56:2537
38namespace webrtc {
39
Taylor Brandstetter3a034e12020-07-09 22:32:3440class SctpDataChannel;
ossu7bb87ee2017-01-23 12:56:2541
Tommi55f72802023-03-27 10:39:3342// Interface that acts as a bridge from the data channel to the transport.
Tommif9e13f82023-04-06 19:21:4543// All methods in this interface need to be invoked on the network thread.
Harald Alvestrand9e5aeb92022-05-11 09:35:3644class SctpDataChannelControllerInterface {
ossu7bb87ee2017-01-23 12:56:2545 public:
46 // Sends the data to the transport.
Tommi1fabbac2023-03-21 13:48:5147 virtual RTCError SendData(StreamId sid,
48 const SendDataParams& params,
49 const rtc::CopyOnWriteBuffer& payload) = 0;
ossu7bb87ee2017-01-23 12:56:2550 // Adds the data channel SID to the transport for SCTP.
Tommi4c842222023-03-21 10:35:2451 virtual void AddSctpDataStream(StreamId sid) = 0;
Taylor Brandstettercdd05f02018-05-31 20:23:3252 // Begins the closing procedure by sending an outgoing stream reset. Still
53 // need to wait for callbacks to tell when this completes.
Tommi4c842222023-03-21 10:35:2454 virtual void RemoveSctpDataStream(StreamId sid) = 0;
Tommid2afbaf2023-03-02 09:51:1655 // Notifies the controller of state changes.
56 virtual void OnChannelStateChanged(SctpDataChannel* data_channel,
57 DataChannelInterface::DataState state) = 0;
ossu7bb87ee2017-01-23 12:56:2558
59 protected:
Harald Alvestrand9e5aeb92022-05-11 09:35:3660 virtual ~SctpDataChannelControllerInterface() {}
ossu7bb87ee2017-01-23 12:56:2561};
62
63struct InternalDataChannelInit : public DataChannelInit {
Yves Gerey665174f2018-06-19 13:03:0564 enum OpenHandshakeRole { kOpener, kAcker, kNone };
Artem Titov880fa812021-07-30 20:30:2365 // The default role is kOpener because the default `negotiated` is false.
ossu7bb87ee2017-01-23 12:56:2566 InternalDataChannelInit() : open_handshake_role(kOpener) {}
Harald Alvestrandf3736ed2019-04-08 11:09:3067 explicit InternalDataChannelInit(const DataChannelInit& base);
Tommic2429a02023-03-03 10:28:2368
69 // Does basic validation to determine if a data channel instance can be
70 // constructed using the configuration.
71 bool IsValid() const;
72
ossu7bb87ee2017-01-23 12:56:2573 OpenHandshakeRole open_handshake_role;
Tommi335d0842023-03-25 09:56:1874 // Optional fallback or backup flag from PC that's used for non-prenegotiated
75 // stream ids in situations where we cannot determine the SSL role from the
76 // transport for purposes of generating a stream ID.
77 // See: https://www.rfc-editor.org/rfc/rfc8832.html#name-protocol-overview
78 absl::optional<rtc::SSLRole> fallback_ssl_role;
ossu7bb87ee2017-01-23 12:56:2579};
80
Taylor Brandstetter3a034e12020-07-09 22:32:3481// Helper class to allocate unique IDs for SCTP DataChannels.
ossu7bb87ee2017-01-23 12:56:2582class SctpSidAllocator {
83 public:
Tommie08f9a92023-03-28 08:09:4084 SctpSidAllocator() = default;
Artem Titov880fa812021-07-30 20:30:2385 // Gets the first unused odd/even id based on the DTLS role. If `role` is
ossu7bb87ee2017-01-23 12:56:2586 // SSL_CLIENT, the allocated id starts from 0 and takes even numbers;
87 // otherwise, the id starts from 1 and takes odd numbers.
Tommi8efaec62023-03-21 17:45:2488 // If a `StreamId` cannot be allocated, `StreamId::HasValue()` will be false.
89 StreamId AllocateSid(rtc::SSLRole role);
ossu7bb87ee2017-01-23 12:56:2590
91 // Attempts to reserve a specific sid. Returns false if it's unavailable.
Tommi8efaec62023-03-21 17:45:2492 bool ReserveSid(StreamId sid);
ossu7bb87ee2017-01-23 12:56:2593
Artem Titov880fa812021-07-30 20:30:2394 // Indicates that `sid` isn't in use any more, and is thus available again.
Tommi8efaec62023-03-21 17:45:2495 void ReleaseSid(StreamId sid);
ossu7bb87ee2017-01-23 12:56:2596
97 private:
Tommi8efaec62023-03-21 17:45:2498 flat_set<StreamId> used_sids_ RTC_GUARDED_BY(&sequence_checker_);
Tommie08f9a92023-03-28 08:09:4099 RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_{
100 SequenceChecker::kDetached};
ossu7bb87ee2017-01-23 12:56:25101};
102
Taylor Brandstetter3a034e12020-07-09 22:32:34103// SctpDataChannel is an implementation of the DataChannelInterface based on
104// SctpTransport. It provides an implementation of unreliable or
Tommi00264ca2023-03-14 12:21:06105// reliable data channels.
ossu7bb87ee2017-01-23 12:56:25106
107// DataChannel states:
108// kConnecting: The channel has been created the transport might not yet be
109// ready.
Taylor Brandstetter3a034e12020-07-09 22:32:34110// kOpen: The open handshake has been performed (if relevant) and the data
111// channel is able to send messages.
112// kClosing: DataChannelInterface::Close has been called, or the remote side
113// initiated the closing procedure, but the closing procedure has not
114// yet finished.
115// kClosed: The closing handshake is finished (possibly initiated from this,
116// side, possibly from the peer).
Taylor Brandstettercdd05f02018-05-31 20:23:32117//
118// How the closing procedure works for SCTP:
119// 1. Alice calls Close(), state changes to kClosing.
120// 2. Alice finishes sending any queued data.
121// 3. Alice calls RemoveSctpDataStream, sends outgoing stream reset.
122// 4. Bob receives incoming stream reset; OnClosingProcedureStartedRemotely
123// called.
Taylor Brandstetter3a034e12020-07-09 22:32:34124// 5. Bob sends outgoing stream reset.
125// 6. Alice receives incoming reset, Bob receives acknowledgement. Both receive
126// OnClosingProcedureComplete callback and transition to kClosed.
Tommi00264ca2023-03-14 12:21:06127class SctpDataChannel : public DataChannelInterface {
ossu7bb87ee2017-01-23 12:56:25128 public:
Taylor Brandstetter3a034e12020-07-09 22:32:34129 static rtc::scoped_refptr<SctpDataChannel> Create(
Tommi1c0d91f2023-03-02 14:42:06130 rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
ossu7bb87ee2017-01-23 12:56:25131 const std::string& label,
Tommie9aa8672023-03-20 13:43:09132 bool connected_to_transport,
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42133 const InternalDataChannelInit& config,
134 rtc::Thread* signaling_thread,
135 rtc::Thread* network_thread);
ossu7bb87ee2017-01-23 12:56:25136
Taylor Brandstetter3a034e12020-07-09 22:32:34137 // Instantiates an API proxy for a SctpDataChannel instance that will be
138 // handed out to external callers.
Tommif9e13f82023-04-06 19:21:45139 // The `signaling_safety` flag is used for the ObserverAdapter callback proxy
140 // which delivers callbacks on the signaling thread but must not deliver such
141 // callbacks after the peerconnection has been closed. The data controller
142 // will update the flag when closed, which will cancel any pending event
143 // notifications.
Tomas Gunnarsson6476d0b2020-06-16 16:39:50144 static rtc::scoped_refptr<DataChannelInterface> CreateProxy(
Tommif9e13f82023-04-06 19:21:45145 rtc::scoped_refptr<SctpDataChannel> channel,
146 rtc::scoped_refptr<PendingTaskSafetyFlag> signaling_safety);
Bjorn Mellem175aa2e2018-11-08 19:23:22147
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42148 void RegisterObserver(DataChannelObserver* observer) override;
149 void UnregisterObserver() override;
ossu7bb87ee2017-01-23 12:56:25150
Tommi492296c2023-03-12 15:59:25151 std::string label() const override;
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42152 bool reliable() const override;
Tommi492296c2023-03-12 15:59:25153 bool ordered() const override;
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42154
Tommi492296c2023-03-12 15:59:25155 // Backwards compatible accessors
156 uint16_t maxRetransmitTime() const override;
157 uint16_t maxRetransmits() const override;
158
159 absl::optional<int> maxPacketLifeTime() const override;
160 absl::optional<int> maxRetransmitsOpt() const override;
161 std::string protocol() const override;
162 bool negotiated() const override;
163 int id() const override;
164 Priority priority() const override;
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42165
166 uint64_t buffered_amount() const override;
167 void Close() override;
168 DataState state() const override;
169 RTCError error() const override;
170 uint32_t messages_sent() const override;
171 uint64_t bytes_sent() const override;
172 uint32_t messages_received() const override;
173 uint64_t bytes_received() const override;
174 bool Send(const DataBuffer& buffer) override;
Tommia50a81a2023-04-11 15:32:34175 void SendAsync(DataBuffer buffer,
176 absl::AnyInvocable<void(RTCError) &&> on_complete) override;
ossu7bb87ee2017-01-23 12:56:25177
Harald Alvestrand1f928d32019-03-28 10:29:38178 // Close immediately, ignoring any queued data or closing procedure.
Taylor Brandstetter3a034e12020-07-09 22:32:34179 // This is called when the underlying SctpTransport is being destroyed.
Harald Alvestrand1f928d32019-03-28 10:29:38180 // It is also called by the PeerConnection if SCTP ID assignment fails.
Harald Alvestranddfbfb462019-12-08 04:55:43181 void CloseAbruptlyWithError(RTCError error);
182 // Specializations of CloseAbruptlyWithError
183 void CloseAbruptlyWithDataChannelFailure(const std::string& message);
Harald Alvestrand1f928d32019-03-28 10:29:38184
Taylor Brandstetter3a034e12020-07-09 22:32:34185 // Called when the SctpTransport's ready to use. That can happen when we've
186 // finished negotiation, or if the channel was created after negotiation has
187 // already finished.
Tommie9aa8672023-03-20 13:43:09188 void OnTransportReady();
Taylor Brandstetter3a034e12020-07-09 22:32:34189
Tommi4e1c9572023-03-15 11:36:20190 void OnDataReceived(DataMessageType type,
ossu7bb87ee2017-01-23 12:56:25191 const rtc::CopyOnWriteBuffer& payload);
ossu7bb87ee2017-01-23 12:56:25192
ossu7bb87ee2017-01-23 12:56:25193 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
194 // be called once.
Tommi1158bde2023-03-30 10:01:56195 void SetSctpSid_n(StreamId sid);
Tommi00264ca2023-03-14 12:21:06196
Taylor Brandstettercdd05f02018-05-31 20:23:32197 // The remote side started the closing procedure by resetting its outgoing
198 // stream (our incoming stream). Sets state to kClosing.
Tommi00264ca2023-03-14 12:21:06199 void OnClosingProcedureStartedRemotely();
Taylor Brandstettercdd05f02018-05-31 20:23:32200 // The closing procedure is complete; both incoming and outgoing stream
201 // resets are done and the channel can transition to kClosed. Called
202 // asynchronously after RemoveSctpDataStream.
Tommi51edb562023-03-14 08:23:51203 void OnClosingProcedureComplete();
ossu7bb87ee2017-01-23 12:56:25204 // Called when the transport channel is created.
ossu7bb87ee2017-01-23 12:56:25205 void OnTransportChannelCreated();
Harald Alvestrand408cb4b2019-11-16 11:09:08206 // Called when the transport channel is unusable.
ossu7bb87ee2017-01-23 12:56:25207 // This method makes sure the DataChannel is disconnected and changes state
208 // to kClosed.
Florent Castellidcb9ffc2021-06-29 12:58:23209 void OnTransportChannelClosed(RTCError error);
ossu7bb87ee2017-01-23 12:56:25210
Taylor Brandstetter3a034e12020-07-09 22:32:34211 DataChannelStats GetStats() const;
ossu7bb87ee2017-01-23 12:56:25212
Tommi56548982023-03-27 16:07:34213 // Returns a unique identifier that's guaranteed to always be available,
214 // doesn't change throughout SctpDataChannel's lifetime and is used for
215 // stats purposes (see also `GetStats()`).
216 int internal_id() const { return internal_id_; }
217
Tommi1158bde2023-03-30 10:01:56218 StreamId sid_n() const {
219 RTC_DCHECK_RUN_ON(network_thread_);
220 return id_n_;
221 }
Tommi492296c2023-03-12 15:59:25222
Harald Alvestrand928e7a32019-07-31 11:16:45223 // Reset the allocator for internal ID values for testing, so that
224 // the internal IDs generated are predictable. Test only.
225 static void ResetInternalIdAllocatorForTesting(int new_value);
226
ossu7bb87ee2017-01-23 12:56:25227 protected:
Taylor Brandstetter3a034e12020-07-09 22:32:34228 SctpDataChannel(const InternalDataChannelInit& config,
Tommi1c0d91f2023-03-02 14:42:06229 rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
Taylor Brandstetter3a034e12020-07-09 22:32:34230 const std::string& label,
Tommie9aa8672023-03-20 13:43:09231 bool connected_to_transport,
Taylor Brandstetter3a034e12020-07-09 22:32:34232 rtc::Thread* signaling_thread,
233 rtc::Thread* network_thread);
234 ~SctpDataChannel() override;
ossu7bb87ee2017-01-23 12:56:25235
236 private:
Tommif9e13f82023-04-06 19:21:45237 class ObserverAdapter;
238
ossu7bb87ee2017-01-23 12:56:25239 // The OPEN(_ACK) signaling state.
240 enum HandshakeState {
241 kHandshakeInit,
242 kHandshakeShouldSendOpen,
243 kHandshakeShouldSendAck,
244 kHandshakeWaitingForAck,
245 kHandshakeReady
246 };
247
Tommia50a81a2023-04-11 15:32:34248 RTCError SendImpl(DataBuffer buffer) RTC_RUN_ON(network_thread_);
Tommif9e13f82023-04-06 19:21:45249 void UpdateState() RTC_RUN_ON(network_thread_);
250 void SetState(DataState state) RTC_RUN_ON(network_thread_);
ossu7bb87ee2017-01-23 12:56:25251
Tommif9e13f82023-04-06 19:21:45252 void DeliverQueuedReceivedData() RTC_RUN_ON(network_thread_);
ossu7bb87ee2017-01-23 12:56:25253
Tommif9e13f82023-04-06 19:21:45254 void SendQueuedDataMessages() RTC_RUN_ON(network_thread_);
Tommia50a81a2023-04-11 15:32:34255 RTCError SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked)
Tommif9e13f82023-04-06 19:21:45256 RTC_RUN_ON(network_thread_);
257 bool QueueSendDataMessage(const DataBuffer& buffer)
258 RTC_RUN_ON(network_thread_);
ossu7bb87ee2017-01-23 12:56:25259
Tommif9e13f82023-04-06 19:21:45260 void SendQueuedControlMessages() RTC_RUN_ON(network_thread_);
261 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer)
262 RTC_RUN_ON(network_thread_);
ossu7bb87ee2017-01-23 12:56:25263
Tommia50a81a2023-04-11 15:32:34264 bool connected_to_transport() const RTC_RUN_ON(network_thread_) {
265 return network_safety_->alive();
266 }
267
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42268 rtc::Thread* const signaling_thread_;
269 rtc::Thread* const network_thread_;
Tommi1158bde2023-03-30 10:01:56270 StreamId id_n_ RTC_GUARDED_BY(network_thread_);
Harald Alvestrand928e7a32019-07-31 11:16:45271 const int internal_id_;
Tomas Gunnarsson0ca13d92020-06-10 10:17:50272 const std::string label_;
Tommi492296c2023-03-12 15:59:25273 const std::string protocol_;
274 const absl::optional<int> max_retransmit_time_;
275 const absl::optional<int> max_retransmits_;
276 const absl::optional<Priority> priority_;
277 const bool negotiated_;
278 const bool ordered_;
279
Tommif9e13f82023-04-06 19:21:45280 DataChannelObserver* observer_ RTC_GUARDED_BY(network_thread_) = nullptr;
281 std::unique_ptr<ObserverAdapter> observer_adapter_;
282 DataState state_ RTC_GUARDED_BY(network_thread_) = kConnecting;
283 RTCError error_ RTC_GUARDED_BY(network_thread_);
284 uint32_t messages_sent_ RTC_GUARDED_BY(network_thread_) = 0;
285 uint64_t bytes_sent_ RTC_GUARDED_BY(network_thread_) = 0;
286 uint32_t messages_received_ RTC_GUARDED_BY(network_thread_) = 0;
287 uint64_t bytes_received_ RTC_GUARDED_BY(network_thread_) = 0;
Tommi1c0d91f2023-03-02 14:42:06288 rtc::WeakPtr<SctpDataChannelControllerInterface> controller_
Tommif9e13f82023-04-06 19:21:45289 RTC_GUARDED_BY(network_thread_);
290 HandshakeState handshake_state_ RTC_GUARDED_BY(network_thread_) =
Taylor Brandstetter3a034e12020-07-09 22:32:34291 kHandshakeInit;
Taylor Brandstettercdd05f02018-05-31 20:23:32292 // Did we already start the graceful SCTP closing procedure?
Tommif9e13f82023-04-06 19:21:45293 bool started_closing_procedure_ RTC_GUARDED_BY(network_thread_) = false;
ossu7bb87ee2017-01-23 12:56:25294 // Control messages that always have to get sent out before any queued
295 // data.
Tommif9e13f82023-04-06 19:21:45296 PacketQueue queued_control_data_ RTC_GUARDED_BY(network_thread_);
297 PacketQueue queued_received_data_ RTC_GUARDED_BY(network_thread_);
298 PacketQueue queued_send_data_ RTC_GUARDED_BY(network_thread_);
Tommia50a81a2023-04-11 15:32:34299 rtc::scoped_refptr<PendingTaskSafetyFlag> network_safety_ =
300 PendingTaskSafetyFlag::CreateDetachedInactive();
ossu7bb87ee2017-01-23 12:56:25301};
302
ossu7bb87ee2017-01-23 12:56:25303} // namespace webrtc
304
Taylor Brandstetter3a034e12020-07-09 22:32:34305#endif // PC_SCTP_DATA_CHANNEL_H_