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/scoped_ref_ptr.h" 37 #include "talk/base/sigslot.h" 38 #include "talk/session/media/channel.h" 39 40 namespace webrtc { 41 42 class WebRtcSession; 43 44 // DataChannel is a an implementation of the DataChannelInterface based on 45 // libjingle's data engine. It provides an implementation of unreliable data 46 // channels. Currently this class is specifically designed to use RtpDataEngine, 47 // and will changed to use SCTP in the future. 48 49 // DataChannel states: 50 // kConnecting: The channel has been created but SSRC for sending and receiving 51 // has not yet been set and the transport might not yet be ready. 52 // kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc 53 // and a remote SSRC set by call to UpdateReceiveSsrc and the transport 54 // has been writable once. 55 // kClosing: DataChannelInterface::Close has been called or UpdateReceiveSsrc 56 // has been called with SSRC==0 57 // kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with 58 // SSRC==0. 59 class DataChannel : public DataChannelInterface, 60 public sigslot::has_slots<> { 61 public: 62 static talk_base::scoped_refptr<DataChannel> Create( 63 WebRtcSession* session, 64 const std::string& label, 65 const DataChannelInit* config); 66 67 virtual void RegisterObserver(DataChannelObserver* observer); 68 virtual void UnregisterObserver(); 69 70 virtual std::string label() const { return label_; } 71 virtual bool reliable() const; 72 virtual int id() const { return config_.id; } 73 virtual uint64 buffered_amount() const; 74 virtual void Close(); 75 virtual DataState state() const { return state_; } 76 virtual bool Send(const DataBuffer& buffer); 77 // Send a control message right now, or queue for later. 78 virtual bool SendControl(const talk_base::Buffer* buffer); 79 void ConnectToDataSession(); 80 81 // Set the SSRC this channel should use to receive data from the 82 // underlying data engine. 83 void SetReceiveSsrc(uint32 receive_ssrc); 84 // The remote peer request that this channel should be closed. 85 void RemotePeerRequestClose(); 86 87 // Set the SSRC this channel should use to send data on the 88 // underlying data engine. |send_ssrc| == 0 means that the channel is no 89 // longer part of the session negotiation. 90 void SetSendSsrc(uint32 send_ssrc); 91 92 // Called if the underlying data engine is closing. 93 void OnDataEngineClose(); 94 95 // Called when the channel's ready to use. That can happen when the 96 // underlying DataMediaChannel becomes ready, or when this channel is a new 97 // stream on an existing DataMediaChannel, and we've finished negotiation. 98 void OnChannelReady(bool writable); 99 protected: 100 DataChannel(WebRtcSession* session, const std::string& label); 101 virtual ~DataChannel(); 102 103 bool Init(const DataChannelInit* config); 104 bool HasNegotiationCompleted(); 105 106 // Sigslots from cricket::DataChannel 107 void OnDataReceived(cricket::DataChannel* channel, 108 const cricket::ReceiveDataParams& params, 109 const talk_base::Buffer& payload); 110 111 private: 112 void DoClose(); 113 void UpdateState(); 114 void SetState(DataState state); 115 void DisconnectFromDataSession(); 116 bool IsConnectedToDataSession() { return data_session_ != NULL; } 117 void DeliverQueuedControlData(); 118 void QueueControl(const talk_base::Buffer* buffer); 119 void DeliverQueuedReceivedData(); 120 void ClearQueuedReceivedData(); 121 void SendQueuedSendData(); 122 void ClearQueuedSendData(); 123 bool InternalSendWithoutQueueing(const DataBuffer& buffer, 124 cricket::SendDataResult* send_result); 125 bool QueueSendData(const DataBuffer& buffer); 126 127 std::string label_; 128 DataChannelInit config_; 129 DataChannelObserver* observer_; 130 DataState state_; 131 bool was_ever_writable_; 132 WebRtcSession* session_; 133 cricket::DataChannel* data_session_; 134 bool send_ssrc_set_; 135 uint32 send_ssrc_; 136 bool receive_ssrc_set_; 137 uint32 receive_ssrc_; 138 // Control messages that always have to get sent out before any queued 139 // data. 140 std::queue<const talk_base::Buffer*> queued_control_data_; 141 std::queue<DataBuffer*> queued_received_data_; 142 std::deque<DataBuffer*> queued_send_data_; 143 }; 144 145 class DataChannelFactory { 146 public: 147 virtual talk_base::scoped_refptr<DataChannel> CreateDataChannel( 148 const std::string& label, 149 const DataChannelInit* config) = 0; 150 151 protected: 152 virtual ~DataChannelFactory() {} 153 }; 154 155 // Define proxy for DataChannelInterface. 156 BEGIN_PROXY_MAP(DataChannel) 157 PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*) 158 PROXY_METHOD0(void, UnregisterObserver) 159 PROXY_CONSTMETHOD0(std::string, label) 160 PROXY_CONSTMETHOD0(bool, reliable) 161 PROXY_CONSTMETHOD0(int, id) 162 PROXY_CONSTMETHOD0(DataState, state) 163 PROXY_CONSTMETHOD0(uint64, buffered_amount) 164 PROXY_METHOD0(void, Close) 165 PROXY_METHOD1(bool, Send, const DataBuffer&) 166 END_PROXY() 167 168 } // namespace webrtc 169 170 #endif // TALK_APP_WEBRTC_DATACHANNEL_H_ 171