Remove the Timer parameters from timer callbacks
[WebKit-https.git] / Source / WebCore / Modules / mediastream / RTCDataChannel.cpp
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 "Dictionary.h"
33 #include "Event.h"
34 #include "ExceptionCode.h"
35 #include "MessageEvent.h"
36 #include "RTCDataChannelHandler.h"
37 #include "RTCPeerConnectionHandler.h"
38 #include "ScriptExecutionContext.h"
39 #include <runtime/ArrayBuffer.h>
40 #include <runtime/ArrayBufferView.h>
41 #include <wtf/NeverDestroyed.h>
42
43 namespace WebCore {
44
45 static const AtomicString& blobKeyword()
46 {
47     static NeverDestroyed<AtomicString> blob("blob", AtomicString::ConstructFromLiteral);
48     return blob;
49 }
50
51 static const AtomicString& arraybufferKeyword()
52 {
53     static NeverDestroyed<AtomicString> arraybuffer("arraybuffer", AtomicString::ConstructFromLiteral);
54     return arraybuffer;
55 }
56
57 PassRefPtr<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext* context, RTCPeerConnectionHandler* peerConnectionHandler, const String& label, const Dictionary& options, ExceptionCode& ec)
58 {
59     RTCDataChannelInit initData;
60     String maxRetransmitsStr;
61     String maxRetransmitTimeStr;
62     options.get("ordered", initData.ordered);
63     options.get("negotiated", initData.negotiated);
64     options.get("id", initData.id);
65     options.get("maxRetransmits", maxRetransmitsStr);
66     options.get("maxRetransmitTime", maxRetransmitTimeStr);
67     options.get("protocol", initData.protocol);
68
69     bool maxRetransmitsConversion;
70     bool maxRetransmitTimeConversion;
71     initData.maxRetransmits = maxRetransmitsStr.toUIntStrict(&maxRetransmitsConversion);
72     initData.maxRetransmitTime = maxRetransmitTimeStr.toUIntStrict(&maxRetransmitTimeConversion);
73     if (maxRetransmitsConversion && maxRetransmitTimeConversion) {
74         ec = SYNTAX_ERR;
75         return nullptr;
76     }
77
78     std::unique_ptr<RTCDataChannelHandler> handler = peerConnectionHandler->createDataChannel(label, initData);
79     if (!handler) {
80         ec = NOT_SUPPORTED_ERR;
81         return nullptr;
82     }
83     return adoptRef(new RTCDataChannel(context, WTF::move(handler)));
84 }
85
86 PassRefPtr<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext* context, std::unique_ptr<RTCDataChannelHandler> handler)
87 {
88     ASSERT(handler);
89     return adoptRef(new RTCDataChannel(context, WTF::move(handler)));
90 }
91
92 RTCDataChannel::RTCDataChannel(ScriptExecutionContext* context, std::unique_ptr<RTCDataChannelHandler> handler)
93     : m_scriptExecutionContext(context)
94     , m_handler(WTF::move(handler))
95     , m_stopped(false)
96     , m_readyState(ReadyStateConnecting)
97     , m_binaryType(BinaryTypeArrayBuffer)
98     , m_scheduledEventtimer(*this, &RTCDataChannel::scheduledEventTimerFired)
99 {
100     m_handler->setClient(this);
101 }
102
103 RTCDataChannel::~RTCDataChannel()
104 {
105 }
106
107 String RTCDataChannel::label() const
108 {
109     return m_handler->label();
110 }
111
112 bool RTCDataChannel::ordered() const
113 {
114     return m_handler->ordered();
115 }
116
117 unsigned short RTCDataChannel::maxRetransmitTime() const
118 {
119     return m_handler->maxRetransmitTime();
120 }
121
122 unsigned short RTCDataChannel::maxRetransmits() const
123 {
124 return m_handler->maxRetransmits();
125 }
126
127 String RTCDataChannel::protocol() const
128 {
129     return m_handler->protocol();
130 }
131
132 bool RTCDataChannel::negotiated() const
133 {
134     return m_handler->negotiated();
135 }
136
137 unsigned short RTCDataChannel::id() const
138 {
139     return m_handler->id();
140 }
141
142 AtomicString RTCDataChannel::readyState() const
143 {
144     static NeverDestroyed<AtomicString> connectingState("connecting", AtomicString::ConstructFromLiteral);
145     static NeverDestroyed<AtomicString> openState("open", AtomicString::ConstructFromLiteral);
146     static NeverDestroyed<AtomicString> closingState("closing", AtomicString::ConstructFromLiteral);
147     static NeverDestroyed<AtomicString> closedState("closed", AtomicString::ConstructFromLiteral);
148     
149     switch (m_readyState) {
150     case ReadyStateConnecting:
151         return connectingState;
152     case ReadyStateOpen:
153         return openState;
154     case ReadyStateClosing:
155         return closingState;
156     case ReadyStateClosed:
157         return closedState;
158     }
159
160     ASSERT_NOT_REACHED();
161     return emptyAtom;
162 }
163
164 unsigned long RTCDataChannel::bufferedAmount() const
165 {
166     return m_handler->bufferedAmount();
167 }
168
169 AtomicString RTCDataChannel::binaryType() const
170 {
171     switch (m_binaryType) {
172     case BinaryTypeBlob:
173         return blobKeyword();
174     case BinaryTypeArrayBuffer:
175         return arraybufferKeyword();
176     }
177
178     ASSERT_NOT_REACHED();
179     return emptyAtom;
180 }
181
182 void RTCDataChannel::setBinaryType(const AtomicString& binaryType, ExceptionCode& ec)
183 {
184     if (binaryType == blobKeyword())
185         ec = NOT_SUPPORTED_ERR;
186     else if (binaryType == arraybufferKeyword())
187         m_binaryType = BinaryTypeArrayBuffer;
188     else
189         ec = TYPE_MISMATCH_ERR;
190 }
191
192 void RTCDataChannel::send(const String& data, ExceptionCode& ec)
193 {
194     if (m_readyState != ReadyStateOpen) {
195         ec = INVALID_STATE_ERR;
196         return;
197     }
198
199     if (!m_handler->sendStringData(data)) {
200         // FIXME: Decide what the right exception here is.
201         ec = SYNTAX_ERR;
202     }
203 }
204
205 void RTCDataChannel::send(PassRefPtr<ArrayBuffer> prpData, ExceptionCode& ec)
206 {
207     if (m_readyState != ReadyStateOpen) {
208         ec = INVALID_STATE_ERR;
209         return;
210     }
211
212     RefPtr<ArrayBuffer> data = prpData;
213
214     size_t dataLength = data->byteLength();
215     if (!dataLength)
216         return;
217
218     const char* dataPointer = static_cast<const char*>(data->data());
219
220     if (!m_handler->sendRawData(dataPointer, dataLength)) {
221         // FIXME: Decide what the right exception here is.
222         ec = SYNTAX_ERR;
223     }
224 }
225
226 void RTCDataChannel::send(PassRefPtr<ArrayBufferView> data, ExceptionCode& ec)
227 {
228     RefPtr<ArrayBuffer> arrayBuffer(data->buffer());
229     send(arrayBuffer.release(), ec);
230 }
231
232 void RTCDataChannel::send(PassRefPtr<Blob>, ExceptionCode& ec)
233 {
234     // FIXME: implement
235     ec = NOT_SUPPORTED_ERR;
236 }
237
238 void RTCDataChannel::close()
239 {
240     if (m_stopped)
241         return;
242
243     m_handler->close();
244 }
245
246 void RTCDataChannel::didChangeReadyState(ReadyState newState)
247 {
248     if (m_stopped || m_readyState == ReadyStateClosed || m_readyState == newState)
249         return;
250
251     m_readyState = newState;
252
253     switch (m_readyState) {
254     case ReadyStateOpen:
255         scheduleDispatchEvent(Event::create(eventNames().openEvent, false, false));
256         break;
257     case ReadyStateClosed:
258         scheduleDispatchEvent(Event::create(eventNames().closeEvent, false, false));
259         break;
260     default:
261         break;
262     }
263 }
264
265 void RTCDataChannel::didReceiveStringData(const String& text)
266 {
267     if (m_stopped)
268         return;
269
270     scheduleDispatchEvent(MessageEvent::create(text));
271 }
272
273 void RTCDataChannel::didReceiveRawData(const char* data, size_t dataLength)
274 {
275     if (m_stopped)
276         return;
277
278     if (m_binaryType == BinaryTypeBlob) {
279         // FIXME: Implement.
280         return;
281     }
282
283     if (m_binaryType == BinaryTypeArrayBuffer) {
284         RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(data, dataLength);
285         scheduleDispatchEvent(MessageEvent::create(buffer.release()));
286         return;
287     }
288     ASSERT_NOT_REACHED();
289 }
290
291 void RTCDataChannel::didDetectError()
292 {
293     if (m_stopped)
294         return;
295
296     scheduleDispatchEvent(Event::create(eventNames().errorEvent, false, false));
297 }
298
299 void RTCDataChannel::stop()
300 {
301     m_stopped = true;
302     m_readyState = ReadyStateClosed;
303     m_handler->setClient(0);
304     m_scriptExecutionContext = 0;
305 }
306
307 void RTCDataChannel::scheduleDispatchEvent(PassRefPtr<Event> event)
308 {
309     m_scheduledEvents.append(event);
310
311     if (!m_scheduledEventTimer.isActive())
312         m_scheduledEventTimer.startOneShot(0);
313 }
314
315 void RTCDataChannel::scheduledEventTimerFired()
316 {
317     if (m_stopped)
318         return;
319
320     Vector<RefPtr<Event>> events;
321     events.swap(m_scheduledEvents);
322
323     Vector<RefPtr<Event>>::iterator it = events.begin();
324     for (; it != events.end(); ++it)
325         dispatchEvent((*it).release());
326
327     events.clear();
328 }
329
330 } // namespace WebCore
331
332 #endif // ENABLE(MEDIA_STREAM)