blob: cbb0c8b2cf0aba568ca7dbff4b3d1b93a5cb95b1 [file] [log] [blame]
ossu7bb87ee2017-01-23 12:56:251/*
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 04:47:3111#ifndef PC_DATACHANNEL_H_
12#define PC_DATACHANNEL_H_
ossu7bb87ee2017-01-23 12:56:2513
14#include <deque>
15#include <set>
16#include <string>
17
Mirko Bonadei92ea95e2017-09-15 04:47:3118#include "api/datachannelinterface.h"
19#include "api/proxy.h"
20#include "media/base/mediachannel.h"
21#include "pc/channel.h"
Steve Anton044a04d2018-08-31 20:51:1922#include "rtc_base/asyncinvoker.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "rtc_base/scoped_ref_ptr.h"
Artem Titove41c4332018-07-25 13:04:2824#include "rtc_base/third_party/sigslot/sigslot.h"
ossu7bb87ee2017-01-23 12:56:2525
26namespace webrtc {
27
28class DataChannel;
29
Taylor Brandstettercdd05f02018-05-31 20:23:3230// 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 12:56:2533class 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 20:23:3245 // 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 12:56:2547 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 13:03:0556 enum OpenHandshakeRole { kOpener, kAcker, kNone };
ossu7bb87ee2017-01-23 12:56:2557 // 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 20:23:3276 // Returns false if no ID can be allocated.
ossu7bb87ee2017-01-23 12:56:2577 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 20:23:3295// both RtpDataChannel and SctpTransport.
ossu7bb87ee2017-01-23 12:56:2596
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 20:23:32107//
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 20:51:19117class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
ossu7bb87ee2017-01-23 12:56:25118 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
125 virtual void RegisterObserver(DataChannelObserver* observer);
126 virtual void UnregisterObserver();
127
128 virtual std::string label() const { return label_; }
129 virtual bool reliable() const;
130 virtual bool ordered() const { return config_.ordered; }
131 virtual uint16_t maxRetransmitTime() const {
132 return config_.maxRetransmitTime;
133 }
134 virtual uint16_t maxRetransmits() const { return config_.maxRetransmits; }
135 virtual std::string protocol() const { return config_.protocol; }
136 virtual bool negotiated() const { return config_.negotiated; }
137 virtual int id() const { return config_.id; }
138 virtual uint64_t buffered_amount() const;
139 virtual void Close();
140 virtual DataState state() const { return state_; }
141 virtual uint32_t messages_sent() const { return messages_sent_; }
142 virtual uint64_t bytes_sent() const { return bytes_sent_; }
143 virtual uint32_t messages_received() const { return messages_received_; }
144 virtual uint64_t bytes_received() const { return bytes_received_; }
145 virtual bool Send(const DataBuffer& buffer);
146
ossu7bb87ee2017-01-23 12:56:25147 // Called when the channel's ready to use. That can happen when the
148 // underlying DataMediaChannel becomes ready, or when this channel is a new
149 // stream on an existing DataMediaChannel, and we've finished negotiation.
150 void OnChannelReady(bool writable);
151
152 // Slots for provider to connect signals to.
153 void OnDataReceived(const cricket::ReceiveDataParams& params,
154 const rtc::CopyOnWriteBuffer& payload);
ossu7bb87ee2017-01-23 12:56:25155
Taylor Brandstettercdd05f02018-05-31 20:23:32156 /********************************************
157 * The following methods are for SCTP only. *
158 ********************************************/
ossu7bb87ee2017-01-23 12:56:25159
160 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
161 // be called once.
162 void SetSctpSid(int sid);
Taylor Brandstettercdd05f02018-05-31 20:23:32163 // The remote side started the closing procedure by resetting its outgoing
164 // stream (our incoming stream). Sets state to kClosing.
165 void OnClosingProcedureStartedRemotely(int sid);
166 // The closing procedure is complete; both incoming and outgoing stream
167 // resets are done and the channel can transition to kClosed. Called
168 // asynchronously after RemoveSctpDataStream.
169 void OnClosingProcedureComplete(int sid);
ossu7bb87ee2017-01-23 12:56:25170 // Called when the transport channel is created.
171 // Only needs to be called for SCTP data channels.
172 void OnTransportChannelCreated();
173 // Called when the transport channel is destroyed.
174 // This method makes sure the DataChannel is disconnected and changes state
175 // to kClosed.
176 void OnTransportChannelDestroyed();
177
Taylor Brandstettercdd05f02018-05-31 20:23:32178 /*******************************************
179 * The following methods are for RTP only. *
180 *******************************************/
ossu7bb87ee2017-01-23 12:56:25181
Taylor Brandstettercdd05f02018-05-31 20:23:32182 // The remote peer requested that this channel should be closed.
183 void RemotePeerRequestClose();
ossu7bb87ee2017-01-23 12:56:25184 // Set the SSRC this channel should use to send data on the
185 // underlying data engine. |send_ssrc| == 0 means that the channel is no
186 // longer part of the session negotiation.
187 void SetSendSsrc(uint32_t send_ssrc);
188 // Set the SSRC this channel should use to receive data from the
189 // underlying data engine.
190 void SetReceiveSsrc(uint32_t receive_ssrc);
191
192 cricket::DataChannelType data_channel_type() const {
193 return data_channel_type_;
194 }
195
196 // Emitted when state transitions to kOpen.
197 sigslot::signal1<DataChannel*> SignalOpened;
198 // Emitted when state transitions to kClosed.
199 // In the case of SCTP channels, this signal can be used to tell when the
200 // channel's sid is free.
201 sigslot::signal1<DataChannel*> SignalClosed;
202
203 protected:
204 DataChannel(DataChannelProviderInterface* client,
205 cricket::DataChannelType dct,
206 const std::string& label);
207 virtual ~DataChannel();
208
209 private:
210 // A packet queue which tracks the total queued bytes. Queued packets are
211 // owned by this class.
212 class PacketQueue {
213 public:
214 PacketQueue();
215 ~PacketQueue();
216
Yves Gerey665174f2018-06-19 13:03:05217 size_t byte_count() const { return byte_count_; }
ossu7bb87ee2017-01-23 12:56:25218
219 bool Empty() const;
220
221 DataBuffer* Front();
222
223 void Pop();
224
225 void Push(DataBuffer* packet);
226
227 void Clear();
228
229 void Swap(PacketQueue* other);
230
231 private:
232 std::deque<DataBuffer*> packets_;
233 size_t byte_count_;
234 };
235
236 // The OPEN(_ACK) signaling state.
237 enum HandshakeState {
238 kHandshakeInit,
239 kHandshakeShouldSendOpen,
240 kHandshakeShouldSendAck,
241 kHandshakeWaitingForAck,
242 kHandshakeReady
243 };
244
245 bool Init(const InternalDataChannelInit& config);
Taylor Brandstettercdd05f02018-05-31 20:23:32246 // Close immediately, ignoring any queued data or closing procedure.
247 // This is called for RTP data channels when SDP indicates a channel should
248 // be removed, or SCTP data channels when the underlying SctpTransport is
249 // being destroyed.
250 void CloseAbruptly();
ossu7bb87ee2017-01-23 12:56:25251 void UpdateState();
252 void SetState(DataState state);
253 void DisconnectFromProvider();
254
255 void DeliverQueuedReceivedData();
256
257 void SendQueuedDataMessages();
258 bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
259 bool QueueSendDataMessage(const DataBuffer& buffer);
260
261 void SendQueuedControlMessages();
262 void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
263 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
264
265 std::string label_;
266 InternalDataChannelInit config_;
267 DataChannelObserver* observer_;
268 DataState state_;
269 uint32_t messages_sent_;
270 uint64_t bytes_sent_;
271 uint32_t messages_received_;
272 uint64_t bytes_received_;
273 cricket::DataChannelType data_channel_type_;
274 DataChannelProviderInterface* provider_;
275 HandshakeState handshake_state_;
276 bool connected_to_provider_;
277 bool send_ssrc_set_;
278 bool receive_ssrc_set_;
279 bool writable_;
Taylor Brandstettercdd05f02018-05-31 20:23:32280 // Did we already start the graceful SCTP closing procedure?
281 bool started_closing_procedure_ = false;
ossu7bb87ee2017-01-23 12:56:25282 uint32_t send_ssrc_;
283 uint32_t receive_ssrc_;
284 // Control messages that always have to get sent out before any queued
285 // data.
286 PacketQueue queued_control_data_;
287 PacketQueue queued_received_data_;
288 PacketQueue queued_send_data_;
Steve Anton044a04d2018-08-31 20:51:19289 rtc::AsyncInvoker invoker_;
ossu7bb87ee2017-01-23 12:56:25290};
291
292// Define proxy for DataChannelInterface.
293BEGIN_SIGNALING_PROXY_MAP(DataChannel)
Yves Gerey665174f2018-06-19 13:03:05294PROXY_SIGNALING_THREAD_DESTRUCTOR()
295PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
296PROXY_METHOD0(void, UnregisterObserver)
297PROXY_CONSTMETHOD0(std::string, label)
298PROXY_CONSTMETHOD0(bool, reliable)
299PROXY_CONSTMETHOD0(bool, ordered)
300PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
301PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
302PROXY_CONSTMETHOD0(std::string, protocol)
303PROXY_CONSTMETHOD0(bool, negotiated)
304PROXY_CONSTMETHOD0(int, id)
305PROXY_CONSTMETHOD0(DataState, state)
306PROXY_CONSTMETHOD0(uint32_t, messages_sent)
307PROXY_CONSTMETHOD0(uint64_t, bytes_sent)
308PROXY_CONSTMETHOD0(uint32_t, messages_received)
309PROXY_CONSTMETHOD0(uint64_t, bytes_received)
310PROXY_CONSTMETHOD0(uint64_t, buffered_amount)
311PROXY_METHOD0(void, Close)
312PROXY_METHOD1(bool, Send, const DataBuffer&)
ossu7bb87ee2017-01-23 12:56:25313END_PROXY_MAP()
314
315} // namespace webrtc
316
Mirko Bonadei92ea95e2017-09-15 04:47:31317#endif // PC_DATACHANNEL_H_