blob: 9208ada5ca64f360ea981e976f4fb963f1b2ce4f [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Henrik Kjellander15583c12016-02-10 10:53:12 +010011#ifndef WEBRTC_API_DATACHANNEL_H_
12#define WEBRTC_API_DATACHANNEL_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000013
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +000014#include <deque>
deadbeefab9b2d12015-10-14 11:33:11 -070015#include <set>
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000016#include <string>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000017
Henrik Kjellander15583c12016-02-10 10:53:12 +010018#include "webrtc/api/datachannelinterface.h"
19#include "webrtc/api/proxy.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000020#include "webrtc/base/messagehandler.h"
21#include "webrtc/base/scoped_ref_ptr.h"
22#include "webrtc/base/sigslot.h"
kjellandera96e2d72016-02-04 23:52:28 -080023#include "webrtc/media/base/mediachannel.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010024#include "webrtc/pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000025
26namespace webrtc {
27
wu@webrtc.org78187522013-10-07 23:32:02 +000028class DataChannel;
29
30class DataChannelProviderInterface {
31 public:
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000032 // Sends the data to the transport.
wu@webrtc.org78187522013-10-07 23:32:02 +000033 virtual bool SendData(const cricket::SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -070034 const rtc::CopyOnWriteBuffer& payload,
wu@webrtc.org78187522013-10-07 23:32:02 +000035 cricket::SendDataResult* result) = 0;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000036 // Connects to the transport signals.
wu@webrtc.org78187522013-10-07 23:32:02 +000037 virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000038 // Disconnects from the transport signals.
wu@webrtc.org78187522013-10-07 23:32:02 +000039 virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000040 // Adds the data channel SID to the transport for SCTP.
bemasc@webrtc.org9b5467e2014-12-04 23:16:52 +000041 virtual void AddSctpDataStream(int sid) = 0;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000042 // Removes the data channel SID from the transport for SCTP.
bemasc@webrtc.org9b5467e2014-12-04 23:16:52 +000043 virtual void RemoveSctpDataStream(int sid) = 0;
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +000044 // Returns true if the transport channel is ready to send data.
45 virtual bool ReadyToSendData() const = 0;
wu@webrtc.org78187522013-10-07 23:32:02 +000046
47 protected:
48 virtual ~DataChannelProviderInterface() {}
49};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +000051struct InternalDataChannelInit : public DataChannelInit {
52 enum OpenHandshakeRole {
53 kOpener,
54 kAcker,
55 kNone
56 };
57 // 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
deadbeefab9b2d12015-10-14 11:33:11 -070070// 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.
76 // Returns false if no id can be allocated.
77 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
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092// DataChannel is a an implementation of the DataChannelInterface based on
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000093// libjingle's data engine. It provides an implementation of unreliable or
94// reliabledata channels. Currently this class is specifically designed to use
95// both RtpDataEngine and SctpDataEngine.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096
97// DataChannel states:
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000098// kConnecting: The channel has been created the transport might not yet be
99// ready.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100// 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.
107class DataChannel : public DataChannelInterface,
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +0000108 public sigslot::has_slots<>,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000109 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110 public:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000111 static rtc::scoped_refptr<DataChannel> Create(
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000112 DataChannelProviderInterface* provider,
wu@webrtc.org78187522013-10-07 23:32:02 +0000113 cricket::DataChannelType dct,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000114 const std::string& label,
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000115 const InternalDataChannelInit& config);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116
117 virtual void RegisterObserver(DataChannelObserver* observer);
118 virtual void UnregisterObserver();
119
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000120 virtual std::string label() const { return label_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000121 virtual bool reliable() const;
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000122 virtual bool ordered() const { return config_.ordered; }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200123 virtual uint16_t maxRetransmitTime() const {
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000124 return config_.maxRetransmitTime;
125 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200126 virtual uint16_t maxRetransmits() const { return config_.maxRetransmits; }
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000127 virtual std::string protocol() const { return config_.protocol; }
128 virtual bool negotiated() const { return config_.negotiated; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 virtual int id() const { return config_.id; }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200130 virtual uint64_t buffered_amount() const;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131 virtual void Close();
132 virtual DataState state() const { return state_; }
hbos84ffdee2016-10-12 14:14:39 -0700133 virtual uint32_t messages_sent() const { return messages_sent_; }
134 virtual uint64_t bytes_sent() const { return bytes_sent_; }
135 virtual uint32_t messages_received() const { return messages_received_; }
136 virtual uint64_t bytes_received() const { return bytes_received_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137 virtual bool Send(const DataBuffer& buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000138
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000139 // rtc::MessageHandler override.
140 virtual void OnMessage(rtc::Message* msg);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +0000141
wu@webrtc.org91053e72013-08-10 07:18:04 +0000142 // Called when the channel's ready to use. That can happen when the
143 // underlying DataMediaChannel becomes ready, or when this channel is a new
144 // stream on an existing DataMediaChannel, and we've finished negotiation.
145 void OnChannelReady(bool writable);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000146
147 // Sigslots from cricket::DataChannel
148 void OnDataReceived(cricket::DataChannel* channel,
149 const cricket::ReceiveDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -0700150 const rtc::CopyOnWriteBuffer& payload);
deadbeefab9b2d12015-10-14 11:33:11 -0700151 void OnStreamClosedRemotely(uint32_t sid);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000153 // The remote peer request that this channel should be closed.
154 void RemotePeerRequestClose();
155
156 // The following methods are for SCTP only.
157
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +0000158 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
159 // be called once.
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000160 void SetSctpSid(int sid);
161 // Called when the transport channel is created.
deadbeefab9b2d12015-10-14 11:33:11 -0700162 // Only needs to be called for SCTP data channels.
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000163 void OnTransportChannelCreated();
deadbeefab9b2d12015-10-14 11:33:11 -0700164 // Called when the transport channel is destroyed.
Taylor Brandstetter4cb5b642016-08-12 10:10:31 -0700165 // This method makes sure the DataChannel is disconnected and changes state
166 // to kClosed.
deadbeefab9b2d12015-10-14 11:33:11 -0700167 void OnTransportChannelDestroyed();
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000168
169 // The following methods are for RTP only.
170
171 // Set the SSRC this channel should use to send data on the
172 // underlying data engine. |send_ssrc| == 0 means that the channel is no
173 // longer part of the session negotiation.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200174 void SetSendSsrc(uint32_t send_ssrc);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000175 // Set the SSRC this channel should use to receive data from the
176 // underlying data engine.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200177 void SetReceiveSsrc(uint32_t receive_ssrc);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +0000178
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000179 cricket::DataChannelType data_channel_type() const {
180 return data_channel_type_;
181 }
182
hbos82ebe022016-11-14 01:41:09 -0800183 // Emitted when state transitions to kOpen.
184 sigslot::signal1<DataChannel*> SignalOpened;
deadbeefab9b2d12015-10-14 11:33:11 -0700185 // Emitted when state transitions to kClosed.
186 // In the case of SCTP channels, this signal can be used to tell when the
187 // channel's sid is free.
188 sigslot::signal1<DataChannel*> SignalClosed;
189
wu@webrtc.org78187522013-10-07 23:32:02 +0000190 protected:
191 DataChannel(DataChannelProviderInterface* client,
192 cricket::DataChannelType dct,
193 const std::string& label);
194 virtual ~DataChannel();
195
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000196 private:
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +0000197 // A packet queue which tracks the total queued bytes. Queued packets are
198 // owned by this class.
199 class PacketQueue {
200 public:
201 PacketQueue();
202 ~PacketQueue();
203
204 size_t byte_count() const {
205 return byte_count_;
206 }
207
208 bool Empty() const;
209
210 DataBuffer* Front();
211
212 void Pop();
213
214 void Push(DataBuffer* packet);
215
216 void Clear();
217
218 void Swap(PacketQueue* other);
219
220 private:
221 std::deque<DataBuffer*> packets_;
222 size_t byte_count_;
223 };
224
Lally Singh5c6c6e02015-05-29 11:52:39 -0400225 // The OPEN(_ACK) signaling state.
226 enum HandshakeState {
227 kHandshakeInit,
228 kHandshakeShouldSendOpen,
229 kHandshakeShouldSendAck,
230 kHandshakeWaitingForAck,
231 kHandshakeReady
232 };
233
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000234 bool Init(const InternalDataChannelInit& config);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000235 void DoClose();
236 void UpdateState();
237 void SetState(DataState state);
Lally Singh5c6c6e02015-05-29 11:52:39 -0400238 void DisconnectFromProvider();
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +0000239
wu@webrtc.orgd64719d2013-08-01 00:00:07 +0000240 void DeliverQueuedReceivedData();
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +0000241
242 void SendQueuedDataMessages();
jiayl@webrtc.org6ca61902014-11-12 17:28:40 +0000243 bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +0000244 bool QueueSendDataMessage(const DataBuffer& buffer);
245
246 void SendQueuedControlMessages();
jbaucheec21bd2016-03-20 06:15:43 -0700247 void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
248 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000249
250 std::string label_;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000251 InternalDataChannelInit config_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000252 DataChannelObserver* observer_;
253 DataState state_;
hbos84ffdee2016-10-12 14:14:39 -0700254 uint32_t messages_sent_;
255 uint64_t bytes_sent_;
256 uint32_t messages_received_;
257 uint64_t bytes_received_;
henrika@webrtc.org44461fa2014-01-13 09:35:02 +0000258 cricket::DataChannelType data_channel_type_;
259 DataChannelProviderInterface* provider_;
Lally Singh5c6c6e02015-05-29 11:52:39 -0400260 HandshakeState handshake_state_;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000261 bool connected_to_provider_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 bool send_ssrc_set_;
henrika@webrtc.org44461fa2014-01-13 09:35:02 +0000263 bool receive_ssrc_set_;
Lally Singh5c6c6e02015-05-29 11:52:39 -0400264 bool writable_;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200265 uint32_t send_ssrc_;
266 uint32_t receive_ssrc_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000267 // Control messages that always have to get sent out before any queued
268 // data.
jiayl@webrtc.orgb43c99d2014-06-20 17:11:14 +0000269 PacketQueue queued_control_data_;
270 PacketQueue queued_received_data_;
271 PacketQueue queued_send_data_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000272};
273
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274// Define proxy for DataChannelInterface.
nisse72c8d2b2016-04-15 03:49:07 -0700275BEGIN_SIGNALING_PROXY_MAP(DataChannel)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
277 PROXY_METHOD0(void, UnregisterObserver)
278 PROXY_CONSTMETHOD0(std::string, label)
279 PROXY_CONSTMETHOD0(bool, reliable)
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000280 PROXY_CONSTMETHOD0(bool, ordered)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200281 PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
282 PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000283 PROXY_CONSTMETHOD0(std::string, protocol)
284 PROXY_CONSTMETHOD0(bool, negotiated)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 PROXY_CONSTMETHOD0(int, id)
286 PROXY_CONSTMETHOD0(DataState, state)
hbos84ffdee2016-10-12 14:14:39 -0700287 PROXY_CONSTMETHOD0(uint32_t, messages_sent)
288 PROXY_CONSTMETHOD0(uint64_t, bytes_sent)
289 PROXY_CONSTMETHOD0(uint32_t, messages_received)
290 PROXY_CONSTMETHOD0(uint64_t, bytes_received)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200291 PROXY_CONSTMETHOD0(uint64_t, buffered_amount)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 PROXY_METHOD0(void, Close)
293 PROXY_METHOD1(bool, Send, const DataBuffer&)
nisse72c8d2b2016-04-15 03:49:07 -0700294END_SIGNALING_PROXY()
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295
296} // namespace webrtc
297
Henrik Kjellander15583c12016-02-10 10:53:12 +0100298#endif // WEBRTC_API_DATACHANNEL_H_