blob: 449165729d92aa2498520e8d61be07115da891d5 [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"
22#include "rtc_base/messagehandler.h"
23#include "rtc_base/scoped_ref_ptr.h"
24#include "rtc_base/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.
ossu7bb87ee2017-01-23 04:56:25 -0800117class DataChannel : public DataChannelInterface,
118 public sigslot::has_slots<>,
119 public rtc::MessageHandler {
120 public:
121 static rtc::scoped_refptr<DataChannel> Create(
122 DataChannelProviderInterface* provider,
123 cricket::DataChannelType dct,
124 const std::string& label,
125 const InternalDataChannelInit& config);
126
127 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
149 // rtc::MessageHandler override.
150 virtual void OnMessage(rtc::Message* msg);
151
152 // Called when the channel's ready to use. That can happen when the
153 // underlying DataMediaChannel becomes ready, or when this channel is a new
154 // stream on an existing DataMediaChannel, and we've finished negotiation.
155 void OnChannelReady(bool writable);
156
157 // Slots for provider to connect signals to.
158 void OnDataReceived(const cricket::ReceiveDataParams& params,
159 const rtc::CopyOnWriteBuffer& payload);
ossu7bb87ee2017-01-23 04:56:25 -0800160
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700161 /********************************************
162 * The following methods are for SCTP only. *
163 ********************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800164
165 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
166 // be called once.
167 void SetSctpSid(int sid);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700168 // The remote side started the closing procedure by resetting its outgoing
169 // stream (our incoming stream). Sets state to kClosing.
170 void OnClosingProcedureStartedRemotely(int sid);
171 // The closing procedure is complete; both incoming and outgoing stream
172 // resets are done and the channel can transition to kClosed. Called
173 // asynchronously after RemoveSctpDataStream.
174 void OnClosingProcedureComplete(int sid);
ossu7bb87ee2017-01-23 04:56:25 -0800175 // Called when the transport channel is created.
176 // Only needs to be called for SCTP data channels.
177 void OnTransportChannelCreated();
178 // Called when the transport channel is destroyed.
179 // This method makes sure the DataChannel is disconnected and changes state
180 // to kClosed.
181 void OnTransportChannelDestroyed();
182
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700183 /*******************************************
184 * The following methods are for RTP only. *
185 *******************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800186
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700187 // The remote peer requested that this channel should be closed.
188 void RemotePeerRequestClose();
ossu7bb87ee2017-01-23 04:56:25 -0800189 // Set the SSRC this channel should use to send data on the
190 // underlying data engine. |send_ssrc| == 0 means that the channel is no
191 // longer part of the session negotiation.
192 void SetSendSsrc(uint32_t send_ssrc);
193 // Set the SSRC this channel should use to receive data from the
194 // underlying data engine.
195 void SetReceiveSsrc(uint32_t receive_ssrc);
196
197 cricket::DataChannelType data_channel_type() const {
198 return data_channel_type_;
199 }
200
201 // Emitted when state transitions to kOpen.
202 sigslot::signal1<DataChannel*> SignalOpened;
203 // Emitted when state transitions to kClosed.
204 // In the case of SCTP channels, this signal can be used to tell when the
205 // channel's sid is free.
206 sigslot::signal1<DataChannel*> SignalClosed;
207
208 protected:
209 DataChannel(DataChannelProviderInterface* client,
210 cricket::DataChannelType dct,
211 const std::string& label);
212 virtual ~DataChannel();
213
214 private:
215 // A packet queue which tracks the total queued bytes. Queued packets are
216 // owned by this class.
217 class PacketQueue {
218 public:
219 PacketQueue();
220 ~PacketQueue();
221
Yves Gerey665174f2018-06-19 15:03:05 +0200222 size_t byte_count() const { return byte_count_; }
ossu7bb87ee2017-01-23 04:56:25 -0800223
224 bool Empty() const;
225
226 DataBuffer* Front();
227
228 void Pop();
229
230 void Push(DataBuffer* packet);
231
232 void Clear();
233
234 void Swap(PacketQueue* other);
235
236 private:
237 std::deque<DataBuffer*> packets_;
238 size_t byte_count_;
239 };
240
241 // The OPEN(_ACK) signaling state.
242 enum HandshakeState {
243 kHandshakeInit,
244 kHandshakeShouldSendOpen,
245 kHandshakeShouldSendAck,
246 kHandshakeWaitingForAck,
247 kHandshakeReady
248 };
249
250 bool Init(const InternalDataChannelInit& config);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700251 // Close immediately, ignoring any queued data or closing procedure.
252 // This is called for RTP data channels when SDP indicates a channel should
253 // be removed, or SCTP data channels when the underlying SctpTransport is
254 // being destroyed.
255 void CloseAbruptly();
ossu7bb87ee2017-01-23 04:56:25 -0800256 void UpdateState();
257 void SetState(DataState state);
258 void DisconnectFromProvider();
259
260 void DeliverQueuedReceivedData();
261
262 void SendQueuedDataMessages();
263 bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
264 bool QueueSendDataMessage(const DataBuffer& buffer);
265
266 void SendQueuedControlMessages();
267 void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
268 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
269
270 std::string label_;
271 InternalDataChannelInit config_;
272 DataChannelObserver* observer_;
273 DataState state_;
274 uint32_t messages_sent_;
275 uint64_t bytes_sent_;
276 uint32_t messages_received_;
277 uint64_t bytes_received_;
278 cricket::DataChannelType data_channel_type_;
279 DataChannelProviderInterface* provider_;
280 HandshakeState handshake_state_;
281 bool connected_to_provider_;
282 bool send_ssrc_set_;
283 bool receive_ssrc_set_;
284 bool writable_;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700285 // Did we already start the graceful SCTP closing procedure?
286 bool started_closing_procedure_ = false;
ossu7bb87ee2017-01-23 04:56:25 -0800287 uint32_t send_ssrc_;
288 uint32_t receive_ssrc_;
289 // Control messages that always have to get sent out before any queued
290 // data.
291 PacketQueue queued_control_data_;
292 PacketQueue queued_received_data_;
293 PacketQueue queued_send_data_;
294};
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200321#endif // PC_DATACHANNEL_H_