blob: af8dd938d0b21241defe4fcbbdd2a1e51f26fdf7 [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"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "media/base/media_channel.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "pc/channel.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "rtc_base/async_invoker.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/scoped_ref_ptr.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
ossu7bb87ee2017-01-23 04:56:25 -0800150 // Called when the channel's ready to use. That can happen when the
151 // underlying DataMediaChannel becomes ready, or when this channel is a new
152 // stream on an existing DataMediaChannel, and we've finished negotiation.
153 void OnChannelReady(bool writable);
154
155 // Slots for provider to connect signals to.
156 void OnDataReceived(const cricket::ReceiveDataParams& params,
157 const rtc::CopyOnWriteBuffer& payload);
ossu7bb87ee2017-01-23 04:56:25 -0800158
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700159 /********************************************
160 * The following methods are for SCTP only. *
161 ********************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800162
163 // Sets the SCTP sid and adds to transport layer if not set yet. Should only
164 // be called once.
165 void SetSctpSid(int sid);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700166 // The remote side started the closing procedure by resetting its outgoing
167 // stream (our incoming stream). Sets state to kClosing.
168 void OnClosingProcedureStartedRemotely(int sid);
169 // The closing procedure is complete; both incoming and outgoing stream
170 // resets are done and the channel can transition to kClosed. Called
171 // asynchronously after RemoveSctpDataStream.
172 void OnClosingProcedureComplete(int sid);
ossu7bb87ee2017-01-23 04:56:25 -0800173 // Called when the transport channel is created.
174 // Only needs to be called for SCTP data channels.
175 void OnTransportChannelCreated();
176 // Called when the transport channel is destroyed.
177 // This method makes sure the DataChannel is disconnected and changes state
178 // to kClosed.
179 void OnTransportChannelDestroyed();
180
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700181 /*******************************************
182 * The following methods are for RTP only. *
183 *******************************************/
ossu7bb87ee2017-01-23 04:56:25 -0800184
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700185 // The remote peer requested that this channel should be closed.
186 void RemotePeerRequestClose();
ossu7bb87ee2017-01-23 04:56:25 -0800187 // Set the SSRC this channel should use to send data on the
188 // underlying data engine. |send_ssrc| == 0 means that the channel is no
189 // longer part of the session negotiation.
190 void SetSendSsrc(uint32_t send_ssrc);
191 // Set the SSRC this channel should use to receive data from the
192 // underlying data engine.
193 void SetReceiveSsrc(uint32_t receive_ssrc);
194
195 cricket::DataChannelType data_channel_type() const {
196 return data_channel_type_;
197 }
198
199 // Emitted when state transitions to kOpen.
200 sigslot::signal1<DataChannel*> SignalOpened;
201 // Emitted when state transitions to kClosed.
202 // In the case of SCTP channels, this signal can be used to tell when the
203 // channel's sid is free.
204 sigslot::signal1<DataChannel*> SignalClosed;
205
206 protected:
207 DataChannel(DataChannelProviderInterface* client,
208 cricket::DataChannelType dct,
209 const std::string& label);
210 virtual ~DataChannel();
211
212 private:
213 // A packet queue which tracks the total queued bytes. Queued packets are
214 // owned by this class.
Steve Anton944c7552018-12-13 14:19:10 -0800215 class PacketQueue final {
ossu7bb87ee2017-01-23 04:56:25 -0800216 public:
Yves Gerey665174f2018-06-19 15:03:05 +0200217 size_t byte_count() const { return byte_count_; }
ossu7bb87ee2017-01-23 04:56:25 -0800218
219 bool Empty() const;
220
Steve Anton944c7552018-12-13 14:19:10 -0800221 std::unique_ptr<DataBuffer> PopFront();
ossu7bb87ee2017-01-23 04:56:25 -0800222
Steve Anton944c7552018-12-13 14:19:10 -0800223 void PushFront(std::unique_ptr<DataBuffer> packet);
224 void PushBack(std::unique_ptr<DataBuffer> packet);
ossu7bb87ee2017-01-23 04:56:25 -0800225
226 void Clear();
227
228 void Swap(PacketQueue* other);
229
230 private:
Steve Anton944c7552018-12-13 14:19:10 -0800231 std::deque<std::unique_ptr<DataBuffer>> packets_;
232 size_t byte_count_ = 0;
ossu7bb87ee2017-01-23 04:56:25 -0800233 };
234
235 // The OPEN(_ACK) signaling state.
236 enum HandshakeState {
237 kHandshakeInit,
238 kHandshakeShouldSendOpen,
239 kHandshakeShouldSendAck,
240 kHandshakeWaitingForAck,
241 kHandshakeReady
242 };
243
244 bool Init(const InternalDataChannelInit& config);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700245 // Close immediately, ignoring any queued data or closing procedure.
246 // This is called for RTP data channels when SDP indicates a channel should
247 // be removed, or SCTP data channels when the underlying SctpTransport is
248 // being destroyed.
249 void CloseAbruptly();
ossu7bb87ee2017-01-23 04:56:25 -0800250 void UpdateState();
251 void SetState(DataState state);
252 void DisconnectFromProvider();
253
254 void DeliverQueuedReceivedData();
255
256 void SendQueuedDataMessages();
257 bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
258 bool QueueSendDataMessage(const DataBuffer& buffer);
259
260 void SendQueuedControlMessages();
261 void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
262 bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
263
264 std::string label_;
265 InternalDataChannelInit config_;
266 DataChannelObserver* observer_;
267 DataState state_;
268 uint32_t messages_sent_;
269 uint64_t bytes_sent_;
270 uint32_t messages_received_;
271 uint64_t bytes_received_;
272 cricket::DataChannelType data_channel_type_;
273 DataChannelProviderInterface* provider_;
274 HandshakeState handshake_state_;
275 bool connected_to_provider_;
276 bool send_ssrc_set_;
277 bool receive_ssrc_set_;
278 bool writable_;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700279 // Did we already start the graceful SCTP closing procedure?
280 bool started_closing_procedure_ = false;
ossu7bb87ee2017-01-23 04:56:25 -0800281 uint32_t send_ssrc_;
282 uint32_t receive_ssrc_;
283 // Control messages that always have to get sent out before any queued
284 // data.
285 PacketQueue queued_control_data_;
286 PacketQueue queued_received_data_;
287 PacketQueue queued_send_data_;
Steve Anton044a04d2018-08-31 13:51:19 -0700288 rtc::AsyncInvoker invoker_;
ossu7bb87ee2017-01-23 04:56:25 -0800289};
290
291// Define proxy for DataChannelInterface.
292BEGIN_SIGNALING_PROXY_MAP(DataChannel)
Yves Gerey665174f2018-06-19 15:03:05 +0200293PROXY_SIGNALING_THREAD_DESTRUCTOR()
294PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
295PROXY_METHOD0(void, UnregisterObserver)
296PROXY_CONSTMETHOD0(std::string, label)
297PROXY_CONSTMETHOD0(bool, reliable)
298PROXY_CONSTMETHOD0(bool, ordered)
299PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
300PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
301PROXY_CONSTMETHOD0(std::string, protocol)
302PROXY_CONSTMETHOD0(bool, negotiated)
303PROXY_CONSTMETHOD0(int, id)
304PROXY_CONSTMETHOD0(DataState, state)
305PROXY_CONSTMETHOD0(uint32_t, messages_sent)
306PROXY_CONSTMETHOD0(uint64_t, bytes_sent)
307PROXY_CONSTMETHOD0(uint32_t, messages_received)
308PROXY_CONSTMETHOD0(uint64_t, bytes_received)
309PROXY_CONSTMETHOD0(uint64_t, buffered_amount)
310PROXY_METHOD0(void, Close)
311PROXY_METHOD1(bool, Send, const DataBuffer&)
ossu7bb87ee2017-01-23 04:56:25 -0800312END_PROXY_MAP()
313
314} // namespace webrtc
315
Steve Anton10542f22019-01-11 09:11:00 -0800316#endif // PC_DATA_CHANNEL_H_