1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "config.h"
26
27#if ENABLE(MEDIA_STREAM)
28
29#include "RTCDataChannel.h"
30
31#include "Blob.h"
32#include "Event.h"
33#include "ExceptionCode.h"
34#include "MessageEvent.h"
35#include "RTCPeerConnectionHandler.h"
36#include "ScriptExecutionContext.h"
37#include <wtf/ArrayBuffer.h>
38#include <wtf/ArrayBufferView.h>
39
40namespace WebCore {
41
42PassRefPtr<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext* context, RTCPeerConnectionHandler* handler, const String& label, bool reliable, ExceptionCode& ec)
43{
44 ASSERT(handler);
45 RefPtr<RTCDataChannel> dataChannel = create(context, handler, RTCDataChannelDescriptor::create(label, reliable));
46 if (!handler->openDataChannel(dataChannel->descriptor())) {
47 ec = NOT_SUPPORTED_ERR;
48 return 0;
49 }
50 return dataChannel.release();
51}
52
53PassRefPtr<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext* context, RTCPeerConnectionHandler* handler, PassRefPtr<RTCDataChannelDescriptor> descriptor)
54{
55 ASSERT(handler);
56 ASSERT(descriptor);
57 return adoptRef(new RTCDataChannel(context, handler, descriptor));
58}
59
60RTCDataChannel::RTCDataChannel(ScriptExecutionContext* context, RTCPeerConnectionHandler* handler, PassRefPtr<RTCDataChannelDescriptor> descriptor)
61 : m_scriptExecutionContext(context)
62 , m_stopped(false)
63 , m_descriptor(descriptor)
64 , m_binaryType(BinaryTypeArrayBuffer)
65 , m_handler(handler)
66{
67 m_descriptor->setClient(this);
68}
69
70RTCDataChannel::~RTCDataChannel()
71{
72 m_descriptor->setClient(0);
73}
74
75String RTCDataChannel::label() const
76{
77 return m_descriptor->label();
78}
79
80bool RTCDataChannel::reliable() const
81{
82 return m_descriptor->reliable();
83}
84
85String RTCDataChannel::readyState() const
86{
87 switch (m_descriptor->readyState()) {
88 case RTCDataChannelDescriptor::ReadyStateConnecting:
89 return ASCIILiteral("connecting");
90 case RTCDataChannelDescriptor::ReadyStateOpen:
91 return ASCIILiteral("open");
92 case RTCDataChannelDescriptor::ReadyStateClosing:
93 return ASCIILiteral("closing");
94 case RTCDataChannelDescriptor::ReadyStateClosed:
95 return ASCIILiteral("closed");
96 }
97
98 ASSERT_NOT_REACHED();
99 return String();
100}
101
102unsigned long RTCDataChannel::bufferedAmount() const
103{
104 return m_descriptor->bufferedAmount();
105}
106
107String RTCDataChannel::binaryType() const
108{
109 switch (m_binaryType) {
110 case BinaryTypeBlob:
111 return ASCIILiteral("blob");
112 case BinaryTypeArrayBuffer:
113 return ASCIILiteral("arraybuffer");
114 }
115 ASSERT_NOT_REACHED();
116 return String();
117}
118
119void RTCDataChannel::setBinaryType(const String& binaryType, ExceptionCode& ec)
120{
121 if (binaryType == "blob")
122 ec = NOT_SUPPORTED_ERR;
123 else if (binaryType == "arraybuffer")
124 m_binaryType = BinaryTypeArrayBuffer;
125 else
126 ec = TYPE_MISMATCH_ERR;
127}
128
129void RTCDataChannel::send(const String& data, ExceptionCode& ec)
130{
131 if (m_descriptor->readyState() != RTCDataChannelDescriptor::ReadyStateOpen) {
132 ec = INVALID_STATE_ERR;
133 return;
134 }
135 if (!m_handler->sendStringData(descriptor(), data)) {
136 // FIXME: Decide what the right exception here is.
137 ec = SYNTAX_ERR;
138 }
139}
140
141void RTCDataChannel::send(PassRefPtr<ArrayBuffer> prpData, ExceptionCode& ec)
142{
143 if (m_descriptor->readyState() != RTCDataChannelDescriptor::ReadyStateOpen) {
144 ec = INVALID_STATE_ERR;
145 return;
146 }
147
148 RefPtr<ArrayBuffer> data = prpData;
149
150 size_t dataLength = data->byteLength();
151 if (!dataLength)
152 return;
153
154 const char* dataPointer = static_cast<const char*>(data->data());
155
156 if (!m_handler->sendRawData(descriptor(), dataPointer, dataLength)) {
157 // FIXME: Decide what the right exception here is.
158 ec = SYNTAX_ERR;
159 }
160}
161
162void RTCDataChannel::send(PassRefPtr<ArrayBufferView> data, ExceptionCode& ec)
163{
164 RefPtr<ArrayBuffer> arrayBuffer(data->buffer());
165 send(arrayBuffer.release(), ec);
166}
167
168void RTCDataChannel::send(PassRefPtr<Blob> data, ExceptionCode& ec)
169{
170 // FIXME: implement
171 ec = NOT_SUPPORTED_ERR;
172}
173
174void RTCDataChannel::close()
175{
176 if (m_stopped)
177 return;
178
179 m_handler->closeDataChannel(descriptor());
180}
181
182void RTCDataChannel::readyStateChanged()
183{
184 if (m_stopped)
185 return;
186
187 switch (m_descriptor->readyState()) {
188 case RTCDataChannelDescriptor::ReadyStateOpen:
189 dispatchEvent(Event::create(eventNames().openEvent, false, false));
190 break;
191 case RTCDataChannelDescriptor::ReadyStateClosed:
192 dispatchEvent(Event::create(eventNames().closeEvent, false, false));
193 break;
194 default:
195 break;
196 }
197}
198
199void RTCDataChannel::dataArrived(const String& text)
200{
201 if (m_stopped)
202 return;
203
204 dispatchEvent(MessageEvent::create(text));
205}
206
207void RTCDataChannel::dataArrived(const char* data, size_t dataLength)
208{
209 if (m_stopped)
210 return;
211
212 if (m_binaryType == BinaryTypeBlob) {
213 // FIXME: Implement.
214 return;
215 }
216 if (m_binaryType == BinaryTypeArrayBuffer) {
217 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(data, dataLength);
218 dispatchEvent(MessageEvent::create(buffer.release()));
219 return;
220 }
221 ASSERT_NOT_REACHED();
222}
223
224void RTCDataChannel::error()
225{
226 if (m_stopped)
227 return;
228
229 dispatchEvent(Event::create(eventNames().errorEvent, false, false));
230}
231
232RTCDataChannelDescriptor* RTCDataChannel::descriptor()
233{
234 return m_descriptor.get();
235}
236
237const AtomicString& RTCDataChannel::interfaceName() const
238{
239 return eventNames().interfaceForRTCDataChannel;
240}
241
242ScriptExecutionContext* RTCDataChannel::scriptExecutionContext() const
243{
244 return m_scriptExecutionContext;
245}
246
247void RTCDataChannel::stop()
248{
249 m_stopped = true;
250 m_handler = 0;
251 m_descriptor->setClient(0);
252 m_scriptExecutionContext = 0;
253}
254
255EventTargetData* RTCDataChannel::eventTargetData()
256{
257 return &m_eventTargetData;
258}
259
260EventTargetData* RTCDataChannel::ensureEventTargetData()
261{
262 return &m_eventTargetData;
263}
264
265} // namespace WebCore
266
267#endif // ENABLE(MEDIA_STREAM)