blob: eef127928fbfaf48e3b52c2e32ded6716301ee8c [file] [log] [blame]
ossu7bb87ee2017-01-23 04:56:25 -08001/*
2 * Copyright 2012 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
Steve Anton10542f22019-01-11 09:11:00 -080011#ifndef PC_DATA_CHANNEL_H_
12#define PC_DATA_CHANNEL_H_
ossu7bb87ee2017-01-23 04:56:25 -080013
14#include <deque>
Steve Anton944c7552018-12-13 14:19:10 -080015#include <memory>
ossu7bb87ee2017-01-23 04:56:25 -080016#include <set>
17#include <string>
18
Steve Anton10542f22019-01-11 09:11:00 -080019#include "api/data_channel_interface.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "api/proxy.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010021#include "api/scoped_refptr.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "media/base/media_channel.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "pc/channel.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "rtc_base/async_invoker.h"
Artem Titove41c4332018-07-25 15:04:28 +020025#include "rtc_base/third_party/sigslot/sigslot.h"
ossu7bb87ee2017-01-23 04:56:25 -080026
27namespace webrtc {
28
29class DataChannel;
30
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070031// TODO(deadbeef): Once RTP data channels go away, get rid of this and have
32// DataChannel depend on SctpTransportInternal (pure virtual SctpTransport
33// interface) instead.
ossu7bb87ee2017-01-23 04:56:25 -080034class DataChannelProviderInterface {
35 public:
36 // Sends the data to the transport.
37 virtual bool SendData(const cricket::SendDataParams& params,
38 const rtc::CopyOnWriteBuffer& payload,
39 cricket::SendDataResult* result) = 0;
40 // Connects to the transport signals.
41 virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
42 // Disconnects from the transport signals.
43 virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
44 // Adds the data channel SID to the transport for SCTP.
45 virtual void AddSctpDataStream(int sid) = 0;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070046 // Begins the closing procedure by sending an outgoing stream reset. Still
47 // need to wait for callbacks to tell when this completes.
ossu7bb87ee2017-01-23 04:56:25 -080048 virtual void RemoveSctpDataStream(int sid) = 0;
49 // Returns true if the transport channel is ready to send data.
50 virtual bool ReadyToSendData() const = 0;
51
52 protected:
53 virtual ~DataChannelProviderInterface() {}
54};
55
56struct InternalDataChannelInit : public DataChannelInit {
Yves Gerey665174f2018-06-19 15:03:05 +020057 enum OpenHandshakeRole { kOpener, kAcker, kNone };
ossu7bb87ee2017-01-23 04:56:25 -080058 // The default role is kOpener because the default |negotiated| is false.
59 InternalDataChannelInit() : open_handshake_role(kOpener) {}
60 explicit InternalDataChannelInit(const DataChannelInit& base)
61 : DataChannelInit(base), open_handshake_role(kOpener) {
62 // If the channel is externally negotiated, do not send the OPEN message.
63 if (base.negotiated) {
64 open_handshake_role = kNone;
65 }
66 }
67
68 OpenHandshakeRole open_handshake_role;
69};
70
71// Helper class to allocate unique IDs for SCTP DataChannels
72class SctpSidAllocator {
73 public:
74 // Gets the first unused odd/even id based on the DTLS role. If |role| is
75 // SSL_CLIENT, the allocated id starts from 0 and takes even numbers;
76 // otherwise, the id starts from 1 and takes odd numbers.
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070077 // Returns false if no ID can be allocated.
ossu7bb87ee2017-01-23 04:56:25 -080078 bool AllocateSid(rtc::SSLRole role, int* sid);
79
80 // Attempts to reserve a specific sid. Returns false if it's unavailable.
81 bool ReserveSid(int sid);
82
83 // Indicates that |sid| isn't in use any more, and is thus available again.
84 void ReleaseSid(int sid);
85
86 private:
87 // Checks if |sid| is available to be assigned to a new SCTP data channel.
88 bool IsSidAvailable(int sid) const;
89
90 std::set<int> used_sids_;
91};
92
93// DataChannel is a an implementation of the DataChannelInterface based on
94// libjingle's data engine. It provides an implementation of unreliable or
95// reliabledata channels. Currently this class is specifically designed to use
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070096// both RtpDataChannel and SctpTransport.
ossu7bb87ee2017-01-23 04:56:25 -080097
98// DataChannel states:
99// kConnecting: The channel has been created the transport might not yet be
100// ready.
101// kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc
102// and a remote SSRC set by call to UpdateReceiveSsrc and the transport
103// has been writable once.
104// kClosing: DataChannelInterface::Close has been called or UpdateReceiveSsrc
105// has been called with SSRC==0
106// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with
107// SSRC==0.
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700108//
109// How the closing procedure works for SCTP:
110// 1. Alice calls Close(), state changes to kClosing.
111// 2. Alice finishes sending any queued data.
112// 3. Alice calls RemoveSctpDataStream, sends outgoing stream reset.
113// 4. Bob receives incoming stream reset; OnClosingProcedureStartedRemotely
114// called.
115// 5. Bob sends outgoing stream reset. 6. Alice receives incoming reset,
116// Bob receives acknowledgement. Both receive OnClosingProcedureComplete
117// callback and transition to kClosed.
Steve Anton044a04d2018-08-31 13:51:19 -0700118class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
ossu7bb87ee2017-01-23 04:56:25 -0800119 public:
120 static rtc::scoped_refptr<DataChannel> Create(
121 DataChannelProviderInterface* provider,
122 cricket::DataChannelType dct,
123 const std::string& label,
124 const InternalDataChannelInit& config);
125
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800126 static bool IsSctpLike(cricket::DataChannelType type);
127
ossu7bb87ee2017-01-23 04:56:25 -0800128 virtual void RegisterObserver(DataChannelObserver* observer);
129 virtual void UnregisterObserver();
130
131 virtual std::string label() const { return label_; }
132 virtual bool reliable() const;
133 virtual bool ordered() const { return config_.ordered; }
134 virtual uint16_t maxRetransmitTime() const {
135 return config_.maxRetransmitTime;
136 }
137 virtual uint16_t maxRetransmits() const { return config_.maxRetransmits; }
138 virtual std::string protocol() const { return config_.protocol; }
139 virtual bool negotiated() const { return config_.negotiated; }
140 virtual int id() const { return config_.id; }
141 virtual uint64_t buffered_amount() const;
142 virtual void Close();
143 virtual DataState state() const { return state_; }
144 virtual uint32_t messages_sent() const { return messages_sent_; }
145 virtual uint64_t bytes_sent() const { return bytes_sent_; }
146 virtual uint32_t messages_received() const { return messages_received_; }
147 virtual uint64_t bytes_received() const { return bytes_received_; }
148 virtual bool Send(const DataBuffer& buffer);
149
Harald Alvestrand1f928d32019-03-28 11:29:38 +0100150 // Close immediately, ignoring any queued data or closing procedure.
151 // This is called for RTP data channels when SDP indicates a channel should
152 // be removed, or SCTP data channels when the underlying SctpTransport is
153 // being destroyed.
154 // It is also called by the PeerConnection if SCTP ID assignment fails.
155 void CloseAbruptly();
156
ossu7bb87ee2017-01-23 04:56:25 -0800157 // Called when the channel's ready to use. That can happen when the
158 // underlying DataMediaChannel becomes ready, or when this channel is a new
159 // stream on an existing DataMediaChannel, and we've finished negotiation.
160 void OnChannelReady(bool writable);
161
162 // Slots for provider to connect signals to.
163 void OnDataReceived(const cricket::ReceiveDataParams& params,
164 const rtc::CopyOnWriteBuffer& payload);
ossu7bb87ee2017-01-23 04:56:25 -0800165
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700166 /********************************************
167 * The following methods are for SCTP only. *
168 ********************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800169
170 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
171 // be called once.
172 void SetSctpSid(int sid);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700173 // The remote side started the closing procedure by resetting its outgoing
174 // stream (our incoming stream). Sets state to kClosing.
175 void OnClosingProcedureStartedRemotely(int sid);
176 // The closing procedure is complete; both incoming and outgoing stream
177 // resets are done and the channel can transition to kClosed. Called
178 // asynchronously after RemoveSctpDataStream.
179 void OnClosingProcedureComplete(int sid);
ossu7bb87ee2017-01-23 04:56:25 -0800180 // Called when the transport channel is created.
181 // Only needs to be called for SCTP data channels.
182 void OnTransportChannelCreated();
183 // Called when the transport channel is destroyed.
184 // This method makes sure the DataChannel is disconnected and changes state
185 // to kClosed.
186 void OnTransportChannelDestroyed();
187
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700188 /*******************************************
189 * The following methods are for RTP only. *
190 *******************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800191
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700192 // The remote peer requested that this channel should be closed.
193 void RemotePeerRequestClose();
ossu7bb87ee2017-01-23 04:56:25 -0800194 // Set the SSRC this channel should use to send data on the
195 // underlying data engine. |send_ssrc| == 0 means that the channel is no
196 // longer part of the session negotiation.
197 void SetSendSsrc(uint32_t send_ssrc);
198 // Set the SSRC this channel should use to receive data from the
199 // underlying data engine.
200 void SetReceiveSsrc(uint32_t receive_ssrc);
201
202 cricket::DataChannelType data_channel_type() const {
203 return data_channel_type_;
204 }
205
206 // Emitted when state transitions to kOpen.
207 sigslot::signal1<DataChannel*> SignalOpened;
208 // Emitted when state transitions to kClosed.
209 // In the case of SCTP channels, this signal can be used to tell when the
210 // channel's sid is free.
211 sigslot::signal1<DataChannel*> SignalClosed;
212
213 protected:
214 DataChannel(DataChannelProviderInterface* client,
215 cricket::DataChannelType dct,
216 const std::string& label);
217 virtual ~DataChannel();
218
219 private:
220 // A packet queue which tracks the total queued bytes. Queued packets are
221 // owned by this class.
Steve Anton944c7552018-12-13 14:19:10 -0800222 class PacketQueue final {
ossu7bb87ee2017-01-23 04:56:25 -0800223 public:
Yves Gerey665174f2018-06-19 15:03:05 +0200224 size_t byte_count() const { return byte_count_; }
ossu7bb87ee2017-01-23 04:56:25 -0800225
226 bool Empty() const;
227
Steve Anton944c7552018-12-13 14:19:10 -0800228 std::unique_ptr<DataBuffer> PopFront();
ossu7bb87ee2017-01-23 04:56:25 -0800229
Steve Anton944c7552018-12-13 14:19:10 -0800230 void PushFront(std::unique_ptr<DataBuffer> packet);
231 void PushBack(std::unique_ptr<DataBuffer> packet);
ossu7bb87ee2017-01-23 04:56:25 -0800232
233 void Clear();
234
235 void Swap(PacketQueue* other);
236
237 private:
Steve Anton944c7552018-12-13 14:19:10 -0800238 std::deque<std::unique_ptr<DataBuffer>> packets_;
239 size_t byte_count_ = 0;
ossu7bb87ee2017-01-23 04:56:25 -0800240 };
241
242 // The OPEN(_ACK) signaling state.
243 enum HandshakeState {
244 kHandshakeInit,
245 kHandshakeShouldSendOpen,
246 kHandshakeShouldSendAck,
247 kHandshakeWaitingForAck,
248 kHandshakeReady
249 };
250
251 bool Init(const InternalDataChannelInit& config);
ossu7bb87ee2017-01-23 04:56:25 -0800252 void UpdateState();
253 void SetState(DataState state);
254 void DisconnectFromProvider();
255
256 void DeliverQueuedReceivedData();
257
258 void SendQueuedDataMessages();
259 bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
260 bool QueueSendDataMessage(const DataBuffer& buffer);
261
262 void SendQueuedControlMessages();
263 void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
264 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
265
266 std::string label_;
267 InternalDataChannelInit config_;
268 DataChannelObserver* observer_;
269 DataState state_;
270 uint32_t messages_sent_;
271 uint64_t bytes_sent_;
272 uint32_t messages_received_;
273 uint64_t bytes_received_;
Marina Cioceae448a3f2019-03-04 15:52:21 +0100274 // Number of bytes of data that have been queued using Send(). Increased
275 // before each transport send and decreased after each successful send.
276 uint64_t buffered_amount_;
ossu7bb87ee2017-01-23 04:56:25 -0800277 cricket::DataChannelType data_channel_type_;
278 DataChannelProviderInterface* provider_;
279 HandshakeState handshake_state_;
280 bool connected_to_provider_;
281 bool send_ssrc_set_;
282 bool receive_ssrc_set_;
283 bool writable_;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700284 // Did we already start the graceful SCTP closing procedure?
285 bool started_closing_procedure_ = false;
ossu7bb87ee2017-01-23 04:56:25 -0800286 uint32_t send_ssrc_;
287 uint32_t receive_ssrc_;
288 // Control messages that always have to get sent out before any queued
289 // data.
290 PacketQueue queued_control_data_;
291 PacketQueue queued_received_data_;
292 PacketQueue queued_send_data_;
Steve Anton044a04d2018-08-31 13:51:19 -0700293 rtc::AsyncInvoker invoker_;
ossu7bb87ee2017-01-23 04:56:25 -0800294};
295
296// Define proxy for DataChannelInterface.
297BEGIN_SIGNALING_PROXY_MAP(DataChannel)
Yves Gerey665174f2018-06-19 15:03:05 +0200298PROXY_SIGNALING_THREAD_DESTRUCTOR()
299PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
300PROXY_METHOD0(void, UnregisterObserver)
301PROXY_CONSTMETHOD0(std::string, label)
302PROXY_CONSTMETHOD0(bool, reliable)
303PROXY_CONSTMETHOD0(bool, ordered)
304PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
305PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
306PROXY_CONSTMETHOD0(std::string, protocol)
307PROXY_CONSTMETHOD0(bool, negotiated)
308PROXY_CONSTMETHOD0(int, id)
309PROXY_CONSTMETHOD0(DataState, state)
310PROXY_CONSTMETHOD0(uint32_t, messages_sent)
311PROXY_CONSTMETHOD0(uint64_t, bytes_sent)
312PROXY_CONSTMETHOD0(uint32_t, messages_received)
313PROXY_CONSTMETHOD0(uint64_t, bytes_received)
314PROXY_CONSTMETHOD0(uint64_t, buffered_amount)
315PROXY_METHOD0(void, Close)
316PROXY_METHOD1(bool, Send, const DataBuffer&)
ossu7bb87ee2017-01-23 04:56:25 -0800317END_PROXY_MAP()
318
319} // namespace webrtc
320
Steve Anton10542f22019-01-11 09:11:00 -0800321#endif // PC_DATA_CHANNEL_H_