blob: 22ea354c211632db86e7942348bd5c328664f7f3 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef PC_DATACHANNEL_H_
12#define PC_DATACHANNEL_H_
ossu7bb87ee2017-01-23 04:56:25 -080013
14#include <deque>
15#include <set>
16#include <string>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/datachannelinterface.h"
19#include "api/proxy.h"
20#include "media/base/mediachannel.h"
21#include "pc/channel.h"
Steve Anton044a04d2018-08-31 13:51:19 -070022#include "rtc_base/asyncinvoker.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/scoped_ref_ptr.h"
Artem Titove41c4332018-07-25 15:04:28 +020024#include "rtc_base/third_party/sigslot/sigslot.h"
ossu7bb87ee2017-01-23 04:56:25 -080025
26namespace webrtc {
27
28class DataChannel;
29
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070030// TODO(deadbeef): Once RTP data channels go away, get rid of this and have
31// DataChannel depend on SctpTransportInternal (pure virtual SctpTransport
32// interface) instead.
ossu7bb87ee2017-01-23 04:56:25 -080033class DataChannelProviderInterface {
34 public:
35 // Sends the data to the transport.
36 virtual bool SendData(const cricket::SendDataParams& params,
37 const rtc::CopyOnWriteBuffer& payload,
38 cricket::SendDataResult* result) = 0;
39 // Connects to the transport signals.
40 virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
41 // Disconnects from the transport signals.
42 virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
43 // Adds the data channel SID to the transport for SCTP.
44 virtual void AddSctpDataStream(int sid) = 0;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070045 // Begins the closing procedure by sending an outgoing stream reset. Still
46 // need to wait for callbacks to tell when this completes.
ossu7bb87ee2017-01-23 04:56:25 -080047 virtual void RemoveSctpDataStream(int sid) = 0;
48 // Returns true if the transport channel is ready to send data.
49 virtual bool ReadyToSendData() const = 0;
50
51 protected:
52 virtual ~DataChannelProviderInterface() {}
53};
54
55struct InternalDataChannelInit : public DataChannelInit {
Yves Gerey665174f2018-06-19 15:03:05 +020056 enum OpenHandshakeRole { kOpener, kAcker, kNone };
ossu7bb87ee2017-01-23 04:56:25 -080057 // The default role is kOpener because the default |negotiated| is false.
58 InternalDataChannelInit() : open_handshake_role(kOpener) {}
59 explicit InternalDataChannelInit(const DataChannelInit& base)
60 : DataChannelInit(base), open_handshake_role(kOpener) {
61 // If the channel is externally negotiated, do not send the OPEN message.
62 if (base.negotiated) {
63 open_handshake_role = kNone;
64 }
65 }
66
67 OpenHandshakeRole open_handshake_role;
68};
69
70// Helper class to allocate unique IDs for SCTP DataChannels
71class SctpSidAllocator {
72 public:
73 // Gets the first unused odd/even id based on the DTLS role. If |role| is
74 // SSL_CLIENT, the allocated id starts from 0 and takes even numbers;
75 // otherwise, the id starts from 1 and takes odd numbers.
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070076 // Returns false if no ID can be allocated.
ossu7bb87ee2017-01-23 04:56:25 -080077 bool AllocateSid(rtc::SSLRole role, int* sid);
78
79 // Attempts to reserve a specific sid. Returns false if it's unavailable.
80 bool ReserveSid(int sid);
81
82 // Indicates that |sid| isn't in use any more, and is thus available again.
83 void ReleaseSid(int sid);
84
85 private:
86 // Checks if |sid| is available to be assigned to a new SCTP data channel.
87 bool IsSidAvailable(int sid) const;
88
89 std::set<int> used_sids_;
90};
91
92// DataChannel is a an implementation of the DataChannelInterface based on
93// libjingle's data engine. It provides an implementation of unreliable or
94// reliabledata channels. Currently this class is specifically designed to use
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070095// both RtpDataChannel and SctpTransport.
ossu7bb87ee2017-01-23 04:56:25 -080096
97// DataChannel states:
98// kConnecting: The channel has been created the transport might not yet be
99// ready.
100// kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc
101// and a remote SSRC set by call to UpdateReceiveSsrc and the transport
102// has been writable once.
103// kClosing: DataChannelInterface::Close has been called or UpdateReceiveSsrc
104// has been called with SSRC==0
105// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with
106// SSRC==0.
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700107//
108// How the closing procedure works for SCTP:
109// 1. Alice calls Close(), state changes to kClosing.
110// 2. Alice finishes sending any queued data.
111// 3. Alice calls RemoveSctpDataStream, sends outgoing stream reset.
112// 4. Bob receives incoming stream reset; OnClosingProcedureStartedRemotely
113// called.
114// 5. Bob sends outgoing stream reset. 6. Alice receives incoming reset,
115// Bob receives acknowledgement. Both receive OnClosingProcedureComplete
116// callback and transition to kClosed.
Steve Anton044a04d2018-08-31 13:51:19 -0700117class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
ossu7bb87ee2017-01-23 04:56:25 -0800118 public:
119 static rtc::scoped_refptr<DataChannel> Create(
120 DataChannelProviderInterface* provider,
121 cricket::DataChannelType dct,
122 const std::string& label,
123 const InternalDataChannelInit& config);
124
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800125 static bool IsSctpLike(cricket::DataChannelType type);
126
ossu7bb87ee2017-01-23 04:56:25 -0800127 virtual void RegisterObserver(DataChannelObserver* observer);
128 virtual void UnregisterObserver();
129
130 virtual std::string label() const { return label_; }
131 virtual bool reliable() const;
132 virtual bool ordered() const { return config_.ordered; }
133 virtual uint16_t maxRetransmitTime() const {
134 return config_.maxRetransmitTime;
135 }
136 virtual uint16_t maxRetransmits() const { return config_.maxRetransmits; }
137 virtual std::string protocol() const { return config_.protocol; }
138 virtual bool negotiated() const { return config_.negotiated; }
139 virtual int id() const { return config_.id; }
140 virtual uint64_t buffered_amount() const;
141 virtual void Close();
142 virtual DataState state() const { return state_; }
143 virtual uint32_t messages_sent() const { return messages_sent_; }
144 virtual uint64_t bytes_sent() const { return bytes_sent_; }
145 virtual uint32_t messages_received() const { return messages_received_; }
146 virtual uint64_t bytes_received() const { return bytes_received_; }
147 virtual bool Send(const DataBuffer& buffer);
148
ossu7bb87ee2017-01-23 04:56:25 -0800149 // Called when the channel's ready to use. That can happen when the
150 // underlying DataMediaChannel becomes ready, or when this channel is a new
151 // stream on an existing DataMediaChannel, and we've finished negotiation.
152 void OnChannelReady(bool writable);
153
154 // Slots for provider to connect signals to.
155 void OnDataReceived(const cricket::ReceiveDataParams& params,
156 const rtc::CopyOnWriteBuffer& payload);
ossu7bb87ee2017-01-23 04:56:25 -0800157
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700158 /********************************************
159 * The following methods are for SCTP only. *
160 ********************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800161
162 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
163 // be called once.
164 void SetSctpSid(int sid);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700165 // The remote side started the closing procedure by resetting its outgoing
166 // stream (our incoming stream). Sets state to kClosing.
167 void OnClosingProcedureStartedRemotely(int sid);
168 // The closing procedure is complete; both incoming and outgoing stream
169 // resets are done and the channel can transition to kClosed. Called
170 // asynchronously after RemoveSctpDataStream.
171 void OnClosingProcedureComplete(int sid);
ossu7bb87ee2017-01-23 04:56:25 -0800172 // Called when the transport channel is created.
173 // Only needs to be called for SCTP data channels.
174 void OnTransportChannelCreated();
175 // Called when the transport channel is destroyed.
176 // This method makes sure the DataChannel is disconnected and changes state
177 // to kClosed.
178 void OnTransportChannelDestroyed();
179
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700180 /*******************************************
181 * The following methods are for RTP only. *
182 *******************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800183
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700184 // The remote peer requested that this channel should be closed.
185 void RemotePeerRequestClose();
ossu7bb87ee2017-01-23 04:56:25 -0800186 // Set the SSRC this channel should use to send data on the
187 // underlying data engine. |send_ssrc| == 0 means that the channel is no
188 // longer part of the session negotiation.
189 void SetSendSsrc(uint32_t send_ssrc);
190 // Set the SSRC this channel should use to receive data from the
191 // underlying data engine.
192 void SetReceiveSsrc(uint32_t receive_ssrc);
193
194 cricket::DataChannelType data_channel_type() const {
195 return data_channel_type_;
196 }
197
198 // Emitted when state transitions to kOpen.
199 sigslot::signal1<DataChannel*> SignalOpened;
200 // Emitted when state transitions to kClosed.
201 // In the case of SCTP channels, this signal can be used to tell when the
202 // channel's sid is free.
203 sigslot::signal1<DataChannel*> SignalClosed;
204
205 protected:
206 DataChannel(DataChannelProviderInterface* client,
207 cricket::DataChannelType dct,
208 const std::string& label);
209 virtual ~DataChannel();
210
211 private:
212 // A packet queue which tracks the total queued bytes. Queued packets are
213 // owned by this class.
214 class PacketQueue {
215 public:
216 PacketQueue();
217 ~PacketQueue();
218
Yves Gerey665174f2018-06-19 15:03:05 +0200219 size_t byte_count() const { return byte_count_; }
ossu7bb87ee2017-01-23 04:56:25 -0800220
221 bool Empty() const;
222
223 DataBuffer* Front();
224
225 void Pop();
226
227 void Push(DataBuffer* packet);
228
229 void Clear();
230
231 void Swap(PacketQueue* other);
232
233 private:
234 std::deque<DataBuffer*> packets_;
235 size_t byte_count_;
236 };
237
238 // The OPEN(_ACK) signaling state.
239 enum HandshakeState {
240 kHandshakeInit,
241 kHandshakeShouldSendOpen,
242 kHandshakeShouldSendAck,
243 kHandshakeWaitingForAck,
244 kHandshakeReady
245 };
246
247 bool Init(const InternalDataChannelInit& config);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700248 // Close immediately, ignoring any queued data or closing procedure.
249 // This is called for RTP data channels when SDP indicates a channel should
250 // be removed, or SCTP data channels when the underlying SctpTransport is
251 // being destroyed.
252 void CloseAbruptly();
ossu7bb87ee2017-01-23 04:56:25 -0800253 void UpdateState();
254 void SetState(DataState state);
255 void DisconnectFromProvider();
256
257 void DeliverQueuedReceivedData();
258
259 void SendQueuedDataMessages();
260 bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
261 bool QueueSendDataMessage(const DataBuffer& buffer);
262
263 void SendQueuedControlMessages();
264 void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
265 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
266
267 std::string label_;
268 InternalDataChannelInit config_;
269 DataChannelObserver* observer_;
270 DataState state_;
271 uint32_t messages_sent_;
272 uint64_t bytes_sent_;
273 uint32_t messages_received_;
274 uint64_t bytes_received_;
275 cricket::DataChannelType data_channel_type_;
276 DataChannelProviderInterface* provider_;
277 HandshakeState handshake_state_;
278 bool connected_to_provider_;
279 bool send_ssrc_set_;
280 bool receive_ssrc_set_;
281 bool writable_;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700282 // Did we already start the graceful SCTP closing procedure?
283 bool started_closing_procedure_ = false;
ossu7bb87ee2017-01-23 04:56:25 -0800284 uint32_t send_ssrc_;
285 uint32_t receive_ssrc_;
286 // Control messages that always have to get sent out before any queued
287 // data.
288 PacketQueue queued_control_data_;
289 PacketQueue queued_received_data_;
290 PacketQueue queued_send_data_;
Steve Anton044a04d2018-08-31 13:51:19 -0700291 rtc::AsyncInvoker invoker_;
ossu7bb87ee2017-01-23 04:56:25 -0800292};
293
294// Define proxy for DataChannelInterface.
295BEGIN_SIGNALING_PROXY_MAP(DataChannel)
Yves Gerey665174f2018-06-19 15:03:05 +0200296PROXY_SIGNALING_THREAD_DESTRUCTOR()
297PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
298PROXY_METHOD0(void, UnregisterObserver)
299PROXY_CONSTMETHOD0(std::string, label)
300PROXY_CONSTMETHOD0(bool, reliable)
301PROXY_CONSTMETHOD0(bool, ordered)
302PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
303PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
304PROXY_CONSTMETHOD0(std::string, protocol)
305PROXY_CONSTMETHOD0(bool, negotiated)
306PROXY_CONSTMETHOD0(int, id)
307PROXY_CONSTMETHOD0(DataState, state)
308PROXY_CONSTMETHOD0(uint32_t, messages_sent)
309PROXY_CONSTMETHOD0(uint64_t, bytes_sent)
310PROXY_CONSTMETHOD0(uint32_t, messages_received)
311PROXY_CONSTMETHOD0(uint64_t, bytes_received)
312PROXY_CONSTMETHOD0(uint64_t, buffered_amount)
313PROXY_METHOD0(void, Close)
314PROXY_METHOD1(bool, Send, const DataBuffer&)
ossu7bb87ee2017-01-23 04:56:25 -0800315END_PROXY_MAP()
316
317} // namespace webrtc
318
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200319#endif // PC_DATACHANNEL_H_