1/*
2 * libjingle
3 * Copyright 2012, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef TALK_APP_WEBRTC_DATACHANNEL_H_
29#define TALK_APP_WEBRTC_DATACHANNEL_H_
30
31#include <string>
32#include <queue>
33
34#include "talk/app/webrtc/datachannelinterface.h"
35#include "talk/app/webrtc/proxy.h"
36#include "talk/base/messagehandler.h"
37#include "talk/base/scoped_ref_ptr.h"
38#include "talk/base/sigslot.h"
39#include "talk/media/base/mediachannel.h"
40#include "talk/session/media/channel.h"
41
42namespace webrtc {
43
44class DataChannel;
45
46class DataChannelProviderInterface {
47 public:
48  // Sends the data to the transport.
49  virtual bool SendData(const cricket::SendDataParams& params,
50                        const talk_base::Buffer& payload,
51                        cricket::SendDataResult* result) = 0;
52  // Connects to the transport signals.
53  virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
54  // Disconnects from the transport signals.
55  virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
56  // Adds the data channel SID to the transport for SCTP.
57  virtual void AddSctpDataStream(uint32 sid) = 0;
58  // Removes the data channel SID from the transport for SCTP.
59  virtual void RemoveSctpDataStream(uint32 sid) = 0;
60  // Returns true if the transport channel is ready to send data.
61  virtual bool ReadyToSendData() const = 0;
62
63 protected:
64  virtual ~DataChannelProviderInterface() {}
65};
66
67// DataChannel is a an implementation of the DataChannelInterface based on
68// libjingle's data engine. It provides an implementation of unreliable or
69// reliabledata channels. Currently this class is specifically designed to use
70// both RtpDataEngine and SctpDataEngine.
71
72// DataChannel states:
73// kConnecting: The channel has been created the transport might not yet be
74//              ready.
75// kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc
76//        and a remote SSRC set by call to UpdateReceiveSsrc and the transport
77//        has been writable once.
78// kClosing: DataChannelInterface::Close has been called or UpdateReceiveSsrc
79//           has been called with SSRC==0
80// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with
81//          SSRC==0.
82class DataChannel : public DataChannelInterface,
83                    public sigslot::has_slots<>,
84                    public talk_base::MessageHandler {
85 public:
86  static talk_base::scoped_refptr<DataChannel> Create(
87      DataChannelProviderInterface* provider,
88      cricket::DataChannelType dct,
89      const std::string& label,
90      const DataChannelInit* config);
91
92  virtual void RegisterObserver(DataChannelObserver* observer);
93  virtual void UnregisterObserver();
94
95  virtual std::string label() const { return label_; }
96  virtual bool reliable() const;
97  virtual bool ordered() const { return config_.ordered; }
98  virtual uint16 maxRetransmitTime() const {
99    return config_.maxRetransmitTime;
100  }
101  virtual uint16 maxRetransmits() const {
102    return config_.maxRetransmits;
103  }
104  virtual std::string protocol() const { return config_.protocol; }
105  virtual bool negotiated() const { return config_.negotiated; }
106  virtual int id() const { return config_.id; }
107  virtual uint64 buffered_amount() const;
108  virtual void Close();
109  virtual DataState state() const { return state_; }
110  virtual bool Send(const DataBuffer& buffer);
111
112  // talk_base::MessageHandler override.
113  virtual void OnMessage(talk_base::Message* msg);
114
115  // Called if the underlying data engine is closing.
116  void OnDataEngineClose();
117
118  // Called when the channel's ready to use.  That can happen when the
119  // underlying DataMediaChannel becomes ready, or when this channel is a new
120  // stream on an existing DataMediaChannel, and we've finished negotiation.
121  void OnChannelReady(bool writable);
122
123  // Sigslots from cricket::DataChannel
124  void OnDataReceived(cricket::DataChannel* channel,
125                      const cricket::ReceiveDataParams& params,
126                      const talk_base::Buffer& payload);
127
128  // The remote peer request that this channel should be closed.
129  void RemotePeerRequestClose();
130
131  // The following methods are for SCTP only.
132
133  // Sets the SCTP sid and adds to transport layer if not set yet.
134  void SetSctpSid(int sid);
135  // Called when the transport channel is created.
136  void OnTransportChannelCreated();
137
138  // The following methods are for RTP only.
139
140  // Set the SSRC this channel should use to send data on the
141  // underlying data engine. |send_ssrc| == 0 means that the channel is no
142  // longer part of the session negotiation.
143  void SetSendSsrc(uint32 send_ssrc);
144  // Set the SSRC this channel should use to receive data from the
145  // underlying data engine.
146  void SetReceiveSsrc(uint32 receive_ssrc);
147
148  cricket::DataChannelType data_channel_type() const {
149    return data_channel_type_;
150  }
151
152 protected:
153  DataChannel(DataChannelProviderInterface* client,
154              cricket::DataChannelType dct,
155              const std::string& label);
156  virtual ~DataChannel();
157
158 private:
159  bool Init(const DataChannelInit* config);
160  void DoClose();
161  void UpdateState();
162  void SetState(DataState state);
163  void DisconnectFromTransport();
164  void DeliverQueuedControlData();
165  void QueueControl(const talk_base::Buffer* buffer);
166  void ClearQueuedControlData();
167  void DeliverQueuedReceivedData();
168  void ClearQueuedReceivedData();
169  void DeliverQueuedSendData();
170  void ClearQueuedSendData();
171  bool InternalSendWithoutQueueing(const DataBuffer& buffer,
172                                   cricket::SendDataResult* send_result);
173  bool QueueSendData(const DataBuffer& buffer);
174  bool SendOpenMessage(const talk_base::Buffer* buffer);
175
176
177  std::string label_;
178  DataChannelInit config_;
179  DataChannelObserver* observer_;
180  DataState state_;
181  bool was_ever_writable_;
182  bool connected_to_provider_;
183  cricket::DataChannelType data_channel_type_;
184  DataChannelProviderInterface* provider_;
185  bool send_ssrc_set_;
186  uint32 send_ssrc_;
187  bool receive_ssrc_set_;
188  uint32 receive_ssrc_;
189  // Control messages that always have to get sent out before any queued
190  // data.
191  std::queue<const talk_base::Buffer*> queued_control_data_;
192  std::queue<DataBuffer*> queued_received_data_;
193  std::deque<DataBuffer*> queued_send_data_;
194};
195
196class DataChannelFactory {
197 public:
198  virtual talk_base::scoped_refptr<DataChannel> CreateDataChannel(
199      const std::string& label,
200      const DataChannelInit* config) = 0;
201
202 protected:
203  virtual ~DataChannelFactory() {}
204};
205
206// Define proxy for DataChannelInterface.
207BEGIN_PROXY_MAP(DataChannel)
208  PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
209  PROXY_METHOD0(void, UnregisterObserver)
210  PROXY_CONSTMETHOD0(std::string, label)
211  PROXY_CONSTMETHOD0(bool, reliable)
212  PROXY_CONSTMETHOD0(bool, ordered)
213  PROXY_CONSTMETHOD0(uint16, maxRetransmitTime)
214  PROXY_CONSTMETHOD0(uint16, maxRetransmits)
215  PROXY_CONSTMETHOD0(std::string, protocol)
216  PROXY_CONSTMETHOD0(bool, negotiated)
217  PROXY_CONSTMETHOD0(int, id)
218  PROXY_CONSTMETHOD0(DataState, state)
219  PROXY_CONSTMETHOD0(uint64, buffered_amount)
220  PROXY_METHOD0(void, Close)
221  PROXY_METHOD1(bool, Send, const DataBuffer&)
222END_PROXY()
223
224}  // namespace webrtc
225
226#endif  // TALK_APP_WEBRTC_DATACHANNEL_H_
227