Source/WebCore: A client MUST close a connection if it detects a masked frame
[WebKit-https.git] / Source / WebCore / Modules / websockets / WebSocketChannel.cpp
1 /*
2  * Copyright (C) 2011, 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if ENABLE(WEB_SOCKETS)
34
35 #include "WebSocketChannel.h"
36
37 #include "Blob.h"
38 #include "CookieJar.h"
39 #include "Document.h"
40 #include "FileError.h"
41 #include "FileReaderLoader.h"
42 #include "Frame.h"
43 #include "FrameLoader.h"
44 #include "FrameLoaderClient.h"
45 #include "InspectorInstrumentation.h"
46 #include "Logging.h"
47 #include "Page.h"
48 #include "ProgressTracker.h"
49 #include "ScriptCallStack.h"
50 #include "ScriptExecutionContext.h"
51 #include "Settings.h"
52 #include "SocketStreamError.h"
53 #include "SocketStreamHandle.h"
54 #include "WebSocketChannelClient.h"
55 #include "WebSocketHandshake.h"
56
57 #include <wtf/ArrayBuffer.h>
58 #include <wtf/CryptographicallyRandomNumber.h>
59 #include <wtf/Deque.h>
60 #include <wtf/FastMalloc.h>
61 #include <wtf/HashMap.h>
62 #include <wtf/OwnPtr.h>
63 #include <wtf/PassOwnPtr.h>
64 #include <wtf/text/CString.h>
65 #include <wtf/text/StringHash.h>
66 #include <wtf/text/WTFString.h>
67
68 using namespace std;
69
70 namespace WebCore {
71
72 const double TCPMaximumSegmentLifetime = 2 * 60.0;
73
74 // Constants for hybi-10 frame format.
75 const unsigned char finalBit = 0x80;
76 const unsigned char compressBit = 0x40;
77 const unsigned char reserved2Bit = 0x20;
78 const unsigned char reserved3Bit = 0x10;
79 const unsigned char opCodeMask = 0xF;
80 const unsigned char maskBit = 0x80;
81 const unsigned char payloadLengthMask = 0x7F;
82 const size_t maxPayloadLengthWithoutExtendedLengthField = 125;
83 const size_t payloadLengthWithTwoByteExtendedLengthField = 126;
84 const size_t payloadLengthWithEightByteExtendedLengthField = 127;
85 const size_t maskingKeyWidthInBytes = 4;
86
87 WebSocketChannel::WebSocketChannel(Document* document, WebSocketChannelClient* client)
88     : m_document(document)
89     , m_client(client)
90     , m_buffer(0)
91     , m_bufferSize(0)
92     , m_resumeTimer(this, &WebSocketChannel::resumeTimerFired)
93     , m_suspended(false)
94     , m_closing(false)
95     , m_receivedClosingHandshake(false)
96     , m_closingTimer(this, &WebSocketChannel::closingTimerFired)
97     , m_closed(false)
98     , m_shouldDiscardReceivedData(false)
99     , m_unhandledBufferedAmount(0)
100     , m_identifier(0)
101     , m_useHixie76Protocol(true)
102     , m_hasContinuousFrame(false)
103     , m_closeEventCode(CloseEventCodeAbnormalClosure)
104     , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen)
105 #if ENABLE(BLOB)
106     , m_blobLoaderStatus(BlobLoaderNotStarted)
107 #endif
108 {
109     if (Settings* settings = m_document->settings())
110         m_useHixie76Protocol = settings->useHixie76WebSocketProtocol();
111
112     if (Page* page = m_document->page())
113         m_identifier = page->progress()->createUniqueIdentifier();
114 }
115
116 WebSocketChannel::~WebSocketChannel()
117 {
118     fastFree(m_buffer);
119 }
120
121 bool WebSocketChannel::useHixie76Protocol()
122 {
123     return m_useHixie76Protocol;
124 }
125
126 void WebSocketChannel::connect(const KURL& url, const String& protocol)
127 {
128     LOG(Network, "WebSocketChannel %p connect", this);
129     ASSERT(!m_handle);
130     ASSERT(!m_suspended);
131     m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document, m_useHixie76Protocol));
132     m_handshake->reset();
133     if (!m_useHixie76Protocol && m_deflateFramer.canDeflate())
134         m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor());
135     if (m_identifier)
136         InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, url, m_document->url());
137     ref();
138     m_handle = SocketStreamHandle::create(m_handshake->url(), this);
139 }
140
141 String WebSocketChannel::subprotocol()
142 {
143     LOG(Network, "WebSocketChannel %p subprotocol", this);
144     if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected)
145         return "";
146     String serverProtocol = m_handshake->serverWebSocketProtocol();
147     if (serverProtocol.isNull())
148         return "";
149     return serverProtocol;
150 }
151
152 String WebSocketChannel::extensions()
153 {
154     LOG(Network, "WebSocketChannel %p extensions", this);
155     if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected)
156         return "";
157     String extensions = m_handshake->acceptedExtensions();
158     if (extensions.isNull())
159         return "";
160     return extensions;
161 }
162
163 ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const String& message)
164 {
165     LOG(Network, "WebSocketChannel %p send %s", this, message.utf8().data());
166     CString utf8 = message.utf8(true);
167     if (utf8.isNull() && message.length())
168         return InvalidMessage;
169     if (m_useHixie76Protocol) {
170         return sendFrameHixie76(utf8.data(), utf8.length()) ? ThreadableWebSocketChannel::SendSuccess : ThreadableWebSocketChannel::SendFail;
171     }
172     enqueueTextFrame(utf8);
173     // According to WebSocket API specification, WebSocket.send() should return void instead
174     // of boolean. However, our implementation still returns boolean due to compatibility
175     // concern (see bug 65850).
176     // m_channel->send() may happen later, thus it's not always possible to know whether
177     // the message has been sent to the socket successfully. In this case, we have no choice
178     // but to return true.
179     return ThreadableWebSocketChannel::SendSuccess;
180 }
181
182 ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const ArrayBuffer& binaryData)
183 {
184     LOG(Network, "WebSocketChannel %p send arraybuffer %p", this, &binaryData);
185     ASSERT(!m_useHixie76Protocol);
186     enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()), binaryData.byteLength());
187     return ThreadableWebSocketChannel::SendSuccess;
188 }
189
190 ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const Blob& binaryData)
191 {
192     LOG(Network, "WebSocketChannel %p send blob %s", this, binaryData.url().string().utf8().data());
193     ASSERT(!m_useHixie76Protocol);
194     enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData);
195     return ThreadableWebSocketChannel::SendSuccess;
196 }
197
198 bool WebSocketChannel::send(const char* data, int length)
199 {
200     LOG(Network, "WebSocketChannel %p send binary %p (%dB)", this, data, length);
201     ASSERT(!m_useHixie76Protocol);
202     enqueueRawFrame(WebSocketFrame::OpCodeBinary, data, length);
203     return true;
204 }
205
206 unsigned long WebSocketChannel::bufferedAmount() const
207 {
208     LOG(Network, "WebSocketChannel %p bufferedAmount", this);
209     ASSERT(m_handle);
210     ASSERT(!m_suspended);
211     return m_handle->bufferedAmount();
212 }
213
214 void WebSocketChannel::close(int code, const String& reason)
215 {
216     LOG(Network, "WebSocketChannel %p close", this);
217     ASSERT(!m_suspended);
218     if (!m_handle)
219         return;
220     startClosingHandshake(code, reason);
221     if (m_closing && !m_closingTimer.isActive())
222         m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime);
223 }
224
225 void WebSocketChannel::fail(const String& reason)
226 {
227     LOG(Network, "WebSocketChannel %p fail: %s", this, reason.utf8().data());
228     ASSERT(!m_suspended);
229     if (m_document)
230         m_document->addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, reason, m_handshake->clientOrigin());
231     if (!m_useHixie76Protocol) {
232         // Hybi-10 specification explicitly states we must not continue to handle incoming data
233         // once the WebSocket connection is failed (section 7.1.7).
234         // FIXME: Should we do this in hixie-76 too?
235         m_shouldDiscardReceivedData = true;
236         if (m_buffer)
237             skipBuffer(m_bufferSize); // Save memory.
238         m_deflateFramer.didFail();
239         m_hasContinuousFrame = false;
240         m_continuousFrameData.clear();
241     }
242     if (m_handle && !m_closed)
243         m_handle->disconnect(); // Will call didClose().
244 }
245
246 void WebSocketChannel::disconnect()
247 {
248     LOG(Network, "WebSocketChannel %p disconnect", this);
249     if (m_identifier && m_document)
250         InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier);
251     if (m_handshake)
252         m_handshake->clearScriptExecutionContext();
253     m_client = 0;
254     m_document = 0;
255     if (m_handle)
256         m_handle->disconnect();
257 }
258
259 void WebSocketChannel::suspend()
260 {
261     m_suspended = true;
262 }
263
264 void WebSocketChannel::resume()
265 {
266     m_suspended = false;
267     if ((m_buffer || m_closed) && m_client && !m_resumeTimer.isActive())
268         m_resumeTimer.startOneShot(0);
269 }
270
271 void WebSocketChannel::willOpenSocketStream(SocketStreamHandle* handle)
272 {
273     LOG(Network, "WebSocketChannel %p willOpensocketStream", this);
274     ASSERT(handle);
275     if (m_document->frame())
276         m_document->frame()->loader()->client()->dispatchWillOpenSocketStream(handle);
277 }
278
279 void WebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle)
280 {
281     LOG(Network, "WebSocketChannel %p didOpenSocketStream", this);
282     ASSERT(handle == m_handle);
283     if (!m_document)
284         return;
285     if (m_identifier)
286         InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, m_handshake->clientHandshakeRequest());
287     CString handshakeMessage = m_handshake->clientHandshakeMessage();
288     if (!handle->send(handshakeMessage.data(), handshakeMessage.length()))
289         fail("Failed to send WebSocket handshake.");
290 }
291
292 void WebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle)
293 {
294     LOG(Network, "WebSocketChannel %p didCloseSocketStream", this);
295     if (m_identifier && m_document)
296         InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier);
297     ASSERT_UNUSED(handle, handle == m_handle || !m_handle);
298     m_closed = true;
299     if (m_closingTimer.isActive())
300         m_closingTimer.stop();
301     if (!m_useHixie76Protocol && m_outgoingFrameQueueStatus != OutgoingFrameQueueClosed)
302         abortOutgoingFrameQueue();
303     if (m_handle) {
304         m_unhandledBufferedAmount = m_handle->bufferedAmount();
305         if (m_suspended)
306             return;
307         WebSocketChannelClient* client = m_client;
308         m_client = 0;
309         m_document = 0;
310         m_handle = 0;
311         if (client)
312             client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason);
313     }
314     deref();
315 }
316
317 void WebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle* handle, const char* data, int len)
318 {
319     LOG(Network, "WebSocketChannel %p didReceiveSocketStreamData %d", this, len);
320     RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
321     ASSERT(handle == m_handle);
322     if (!m_document) {
323         return;
324     }
325     if (len <= 0) {
326         handle->disconnect();
327         return;
328     }
329     if (!m_client) {
330         m_shouldDiscardReceivedData = true;
331         handle->disconnect();
332         return;
333     }
334     if (m_shouldDiscardReceivedData)
335         return;
336     if (!appendToBuffer(data, len)) {
337         m_shouldDiscardReceivedData = true;
338         fail("Ran out of memory while receiving WebSocket data.");
339         return;
340     }
341     while (!m_suspended && m_client && m_buffer)
342         if (!processBuffer())
343             break;
344 }
345
346 void WebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, size_t bufferedAmount)
347 {
348     if (m_client)
349         m_client->didUpdateBufferedAmount(bufferedAmount);
350 }
351
352 void WebSocketChannel::didFailSocketStream(SocketStreamHandle* handle, const SocketStreamError& error)
353 {
354     LOG(Network, "WebSocketChannel %p didFailSocketStream", this);
355     ASSERT(handle == m_handle || !m_handle);
356     if (m_document) {
357         String message;
358         if (error.isNull())
359             message = "WebSocket network error";
360         else if (error.localizedDescription().isNull())
361             message = "WebSocket network error: error code " + String::number(error.errorCode());
362         else
363             message = "WebSocket network error: " + error.localizedDescription();
364         String failingURL = error.failingURL();
365         ASSERT(failingURL.isNull() || m_handshake->url().string() == failingURL);
366         if (failingURL.isNull())
367             failingURL = m_handshake->url().string();
368         m_document->addConsoleMessage(NetworkMessageSource, LogMessageType, ErrorMessageLevel, message, failingURL);
369     }
370     m_shouldDiscardReceivedData = true;
371     handle->disconnect();
372 }
373
374 void WebSocketChannel::didReceiveAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&)
375 {
376 }
377
378 void WebSocketChannel::didCancelAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&)
379 {
380 }
381
382 #if ENABLE(BLOB)
383 void WebSocketChannel::didStartLoading()
384 {
385     LOG(Network, "WebSocketChannel %p didStartLoading", this);
386     ASSERT(m_blobLoader);
387     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
388 }
389
390 void WebSocketChannel::didReceiveData()
391 {
392     LOG(Network, "WebSocketChannel %p didReceiveData", this);
393     ASSERT(m_blobLoader);
394     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
395 }
396
397 void WebSocketChannel::didFinishLoading()
398 {
399     LOG(Network, "WebSocketChannel %p didFinishLoading", this);
400     ASSERT(m_blobLoader);
401     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
402     m_blobLoaderStatus = BlobLoaderFinished;
403     processOutgoingFrameQueue();
404     deref();
405 }
406
407 void WebSocketChannel::didFail(int errorCode)
408 {
409     LOG(Network, "WebSocketChannel %p didFail %d", this, errorCode);
410     ASSERT(m_blobLoader);
411     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
412     m_blobLoader.clear();
413     m_blobLoaderStatus = BlobLoaderFailed;
414     fail("Failed to load Blob: error code = " + String::number(errorCode)); // FIXME: Generate human-friendly reason message.
415     deref();
416 }
417 #endif
418
419 bool WebSocketChannel::appendToBuffer(const char* data, size_t len)
420 {
421     size_t newBufferSize = m_bufferSize + len;
422     if (newBufferSize < m_bufferSize) {
423         LOG(Network, "WebSocket buffer overflow (%lu+%lu)", static_cast<unsigned long>(m_bufferSize), static_cast<unsigned long>(len));
424         return false;
425     }
426     char* newBuffer = 0;
427     if (!tryFastMalloc(newBufferSize).getValue(newBuffer))
428         return false;
429
430     if (m_buffer)
431         memcpy(newBuffer, m_buffer, m_bufferSize);
432     memcpy(newBuffer + m_bufferSize, data, len);
433     fastFree(m_buffer);
434     m_buffer = newBuffer;
435     m_bufferSize = newBufferSize;
436     return true;
437 }
438
439 void WebSocketChannel::skipBuffer(size_t len)
440 {
441     ASSERT(len <= m_bufferSize);
442     m_bufferSize -= len;
443     if (!m_bufferSize) {
444         fastFree(m_buffer);
445         m_buffer = 0;
446         return;
447     }
448     memmove(m_buffer, m_buffer + len, m_bufferSize);
449 }
450
451 bool WebSocketChannel::processBuffer()
452 {
453     ASSERT(!m_suspended);
454     ASSERT(m_client);
455     ASSERT(m_buffer);
456     LOG(Network, "WebSocketChannel %p processBuffer %lu", this, static_cast<unsigned long>(m_bufferSize));
457
458     if (m_shouldDiscardReceivedData)
459         return false;
460
461     if (m_receivedClosingHandshake) {
462         skipBuffer(m_bufferSize);
463         return false;
464     }
465
466     RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
467
468     if (m_handshake->mode() == WebSocketHandshake::Incomplete) {
469         int headerLength = m_handshake->readServerHandshake(m_buffer, m_bufferSize);
470         if (headerLength <= 0)
471             return false;
472         if (m_handshake->mode() == WebSocketHandshake::Connected) {
473             if (m_identifier)
474                 InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document, m_identifier, m_handshake->serverHandshakeResponse());
475             if (!m_handshake->serverSetCookie().isEmpty()) {
476                 if (cookiesEnabled(m_document)) {
477                     ExceptionCode ec; // Exception (for sandboxed documents) ignored.
478                     m_document->setCookie(m_handshake->serverSetCookie(), ec);
479                 }
480             }
481             // FIXME: handle set-cookie2.
482             LOG(Network, "WebSocketChannel %p connected", this);
483             skipBuffer(headerLength);
484             m_client->didConnect();
485             LOG(Network, "remaining in read buf %lu", static_cast<unsigned long>(m_bufferSize));
486             return m_buffer;
487         }
488         ASSERT(m_handshake->mode() == WebSocketHandshake::Failed);
489         LOG(Network, "WebSocketChannel %p connection failed", this);
490         skipBuffer(headerLength);
491         m_shouldDiscardReceivedData = true;
492         fail(m_handshake->failureReason());
493         return false;
494     }
495     if (m_handshake->mode() != WebSocketHandshake::Connected)
496         return false;
497
498     if (m_useHixie76Protocol)
499         return processFrameHixie76();
500
501     return processFrame();
502 }
503
504 void WebSocketChannel::resumeTimerFired(Timer<WebSocketChannel>* timer)
505 {
506     ASSERT_UNUSED(timer, timer == &m_resumeTimer);
507
508     RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
509     while (!m_suspended && m_client && m_buffer)
510         if (!processBuffer())
511             break;
512     if (!m_suspended && m_client && m_closed && m_handle)
513         didCloseSocketStream(m_handle.get());
514 }
515
516 void WebSocketChannel::startClosingHandshake(int code, const String& reason)
517 {
518     LOG(Network, "WebSocketChannel %p closing %d %d", this, m_closing, m_receivedClosingHandshake);
519     if (m_closing)
520         return;
521     ASSERT(m_handle);
522     if (m_useHixie76Protocol) {
523         Vector<char> buf;
524         buf.append('\xff');
525         buf.append('\0');
526         if (!m_handle->send(buf.data(), buf.size())) {
527             m_handle->disconnect();
528             return;
529         }
530     } else {
531         Vector<char> buf;
532         if (!m_receivedClosingHandshake && code != CloseEventCodeNotSpecified) {
533             unsigned char highByte = code >> 8;
534             unsigned char lowByte = code;
535             buf.append(static_cast<char>(highByte));
536             buf.append(static_cast<char>(lowByte));
537             buf.append(reason.utf8().data(), reason.utf8().length());
538         }
539         enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size());
540     }
541     m_closing = true;
542     if (m_client)
543         m_client->didStartClosingHandshake();
544 }
545
546 void WebSocketChannel::closingTimerFired(Timer<WebSocketChannel>* timer)
547 {
548     LOG(Network, "WebSocketChannel %p closing timer", this);
549     ASSERT_UNUSED(timer, &m_closingTimer == timer);
550     if (m_handle)
551         m_handle->disconnect();
552 }
553
554 WebSocketChannel::ParseFrameResult WebSocketChannel::parseFrame(WebSocketFrame& frame, const char*& frameEnd)
555 {
556     const char* p = m_buffer;
557     const char* bufferEnd = m_buffer + m_bufferSize;
558
559     if (m_bufferSize < 2)
560         return FrameIncomplete;
561
562     unsigned char firstByte = *p++;
563     unsigned char secondByte = *p++;
564
565     bool final = firstByte & finalBit;
566     bool compress = firstByte & compressBit;
567     bool reserved2 = firstByte & reserved2Bit;
568     bool reserved3 = firstByte & reserved3Bit;
569     unsigned char opCode = firstByte & opCodeMask;
570
571     bool masked = secondByte & maskBit;
572     if (masked) {
573         fail("A server must not mask any frames that it sends to the client.");
574         return FrameError;
575     }
576     uint64_t payloadLength64 = secondByte & payloadLengthMask;
577     if (payloadLength64 > maxPayloadLengthWithoutExtendedLengthField) {
578         int extendedPayloadLengthSize;
579         if (payloadLength64 == payloadLengthWithTwoByteExtendedLengthField)
580             extendedPayloadLengthSize = 2;
581         else {
582             ASSERT(payloadLength64 == payloadLengthWithEightByteExtendedLengthField);
583             extendedPayloadLengthSize = 8;
584         }
585         if (bufferEnd - p < extendedPayloadLengthSize)
586             return FrameIncomplete;
587         payloadLength64 = 0;
588         for (int i = 0; i < extendedPayloadLengthSize; ++i) {
589             payloadLength64 <<= 8;
590             payloadLength64 |= static_cast<unsigned char>(*p++);
591         }
592         if (extendedPayloadLengthSize == 2 && payloadLength64 <= maxPayloadLengthWithoutExtendedLengthField) {
593             fail("The minimal number of bytes MUST be used to encode the length");
594             return FrameError;
595         }
596         if (extendedPayloadLengthSize == 8 && payloadLength64 <= 0xFFFF) {
597             fail("The minimal number of bytes MUST be used to encode the length");
598             return FrameError;
599         }
600     }
601
602     // FIXME: UINT64_C(0x7FFFFFFFFFFFFFFF) should be used but it did not compile on Qt bots.
603 #if COMPILER(MSVC)
604     static const uint64_t maxPayloadLength = 0x7FFFFFFFFFFFFFFFui64;
605 #else
606     static const uint64_t maxPayloadLength = 0x7FFFFFFFFFFFFFFFull;
607 #endif
608     if (payloadLength64 > maxPayloadLength || payloadLength64 > numeric_limits<size_t>::max()) {
609         fail("WebSocket frame length too large: " + String::number(payloadLength64) + " bytes");
610         return FrameError;
611     }
612     size_t payloadLength = static_cast<size_t>(payloadLength64);
613
614     if (static_cast<size_t>(bufferEnd - p) < payloadLength)
615         return FrameIncomplete;
616
617     frame.opCode = static_cast<WebSocketFrame::OpCode>(opCode);
618     frame.final = final;
619     frame.compress = compress;
620     frame.reserved2 = reserved2;
621     frame.reserved3 = reserved3;
622     frame.masked = masked;
623     frame.payload = p;
624     frame.payloadLength = payloadLength;
625     frameEnd = p + payloadLength;
626     return FrameOK;
627 }
628
629 bool WebSocketChannel::processFrame()
630 {
631     ASSERT(m_buffer);
632
633     WebSocketFrame frame;
634     const char* frameEnd;
635     if (parseFrame(frame, frameEnd) != FrameOK)
636         return false;
637
638     ASSERT(m_buffer < frameEnd);
639     ASSERT(frameEnd <= m_buffer + m_bufferSize);
640
641     OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame);
642     if (!inflateResult->succeeded()) {
643         fail(inflateResult->failureReason());
644         return false;
645     }
646
647     // Validate the frame data.
648     if (WebSocketFrame::isReservedOpCode(frame.opCode)) {
649         fail("Unrecognized frame opcode: " + String::number(frame.opCode));
650         return false;
651     }
652
653     if (frame.reserved2 || frame.reserved3) {
654         fail("One or more reserved bits are on: reserved2 = " + String::number(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3));
655         return false;
656     }
657
658     // All control frames must not be fragmented.
659     if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) {
660         fail("Received fragmented control frame: opcode = " + String::number(frame.opCode));
661         return false;
662     }
663
664     // All control frames must have a payload of 125 bytes or less, which means the frame must not contain
665     // the "extended payload length" field.
666     if (WebSocketFrame::isControlOpCode(frame.opCode) && frame.payloadLength > maxPayloadLengthWithoutExtendedLengthField) {
667         fail("Received control frame having too long payload: " + String::number(frame.payloadLength) + " bytes");
668         return false;
669     }
670
671     // A new data frame is received before the previous continuous frame finishes.
672     // Note that control frames are allowed to come in the middle of continuous frames.
673     if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) {
674         fail("Received new data frame but previous continuous frame is unfinished.");
675         return false;
676     }
677
678     switch (frame.opCode) {
679     case WebSocketFrame::OpCodeContinuation:
680         // An unexpected continuation frame is received without any leading frame.
681         if (!m_hasContinuousFrame) {
682             fail("Received unexpected continuation frame.");
683             return false;
684         }
685         m_continuousFrameData.append(frame.payload, frame.payloadLength);
686         skipBuffer(frameEnd - m_buffer);
687         if (frame.final) {
688             // onmessage handler may eventually call the other methods of this channel,
689             // so we should pretend that we have finished to read this frame and
690             // make sure that the member variables are in a consistent state before
691             // the handler is invoked.
692             // Vector<char>::swap() is used here to clear m_continuousFrameData.
693             OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char>);
694             m_continuousFrameData.swap(*continuousFrameData);
695             m_hasContinuousFrame = false;
696             if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) {
697                 String message;
698                 if (continuousFrameData->size())
699                     message = String::fromUTF8(continuousFrameData->data(), continuousFrameData->size());
700                 else
701                     message = "";
702                 if (message.isNull())
703                     fail("Could not decode a text frame as UTF-8.");
704                 else
705                     m_client->didReceiveMessage(message);
706             } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary)
707                 m_client->didReceiveBinaryData(continuousFrameData.release());
708         }
709         break;
710
711     case WebSocketFrame::OpCodeText:
712         if (frame.final) {
713             String message;
714             if (frame.payloadLength)
715                 message = String::fromUTF8(frame.payload, frame.payloadLength);
716             else
717                 message = "";
718             skipBuffer(frameEnd - m_buffer);
719             if (message.isNull())
720                 fail("Could not decode a text frame as UTF-8.");
721             else
722                 m_client->didReceiveMessage(message);
723         } else {
724             m_hasContinuousFrame = true;
725             m_continuousFrameOpCode = WebSocketFrame::OpCodeText;
726             ASSERT(m_continuousFrameData.isEmpty());
727             m_continuousFrameData.append(frame.payload, frame.payloadLength);
728             skipBuffer(frameEnd - m_buffer);
729         }
730         break;
731
732     case WebSocketFrame::OpCodeBinary:
733         if (frame.final) {
734             OwnPtr<Vector<char> > binaryData = adoptPtr(new Vector<char>(frame.payloadLength));
735             memcpy(binaryData->data(), frame.payload, frame.payloadLength);
736             skipBuffer(frameEnd - m_buffer);
737             m_client->didReceiveBinaryData(binaryData.release());
738         } else {
739             m_hasContinuousFrame = true;
740             m_continuousFrameOpCode = WebSocketFrame::OpCodeBinary;
741             ASSERT(m_continuousFrameData.isEmpty());
742             m_continuousFrameData.append(frame.payload, frame.payloadLength);
743             skipBuffer(frameEnd - m_buffer);
744         }
745         break;
746
747     case WebSocketFrame::OpCodeClose:
748         if (frame.payloadLength >= 2) {
749             unsigned char highByte = static_cast<unsigned char>(frame.payload[0]);
750             unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]);
751             m_closeEventCode = highByte << 8 | lowByte;
752         } else
753             m_closeEventCode = CloseEventCodeNoStatusRcvd;
754         if (frame.payloadLength >= 3)
755             m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2);
756         else
757             m_closeEventReason = "";
758         skipBuffer(frameEnd - m_buffer);
759         m_receivedClosingHandshake = true;
760         startClosingHandshake(m_closeEventCode, m_closeEventReason);
761         if (m_closing) {
762             m_outgoingFrameQueueStatus = OutgoingFrameQueueClosing;
763             processOutgoingFrameQueue();
764         }
765         break;
766
767     case WebSocketFrame::OpCodePing:
768         enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength);
769         skipBuffer(frameEnd - m_buffer);
770         break;
771
772     case WebSocketFrame::OpCodePong:
773         // A server may send a pong in response to our ping, or an unsolicited pong which is not associated with
774         // any specific ping. Either way, there's nothing to do on receipt of pong.
775         skipBuffer(frameEnd - m_buffer);
776         break;
777
778     default:
779         ASSERT_NOT_REACHED();
780         skipBuffer(frameEnd - m_buffer);
781         break;
782     }
783
784     return m_buffer;
785 }
786
787 bool WebSocketChannel::processFrameHixie76()
788 {
789     const char* nextFrame = m_buffer;
790     const char* p = m_buffer;
791     const char* end = p + m_bufferSize;
792
793     unsigned char frameByte = static_cast<unsigned char>(*p++);
794     if ((frameByte & 0x80) == 0x80) {
795         size_t length = 0;
796         bool errorFrame = false;
797         bool lengthFinished = false;
798         while (p < end) {
799             if (length > numeric_limits<size_t>::max() / 128) {
800                 LOG(Network, "frame length overflow %lu", static_cast<unsigned long>(length));
801                 errorFrame = true;
802                 break;
803             }
804             size_t newLength = length * 128;
805             unsigned char msgByte = static_cast<unsigned char>(*p);
806             unsigned int lengthMsgByte = msgByte & 0x7f;
807             if (newLength > numeric_limits<size_t>::max() - lengthMsgByte) {
808                 LOG(Network, "frame length overflow %lu+%u", static_cast<unsigned long>(newLength), lengthMsgByte);
809                 errorFrame = true;
810                 break;
811             }
812             newLength += lengthMsgByte;
813             if (newLength < length) { // sanity check
814                 LOG(Network, "frame length integer wrap %lu->%lu", static_cast<unsigned long>(length), static_cast<unsigned long>(newLength));
815                 errorFrame = true;
816                 break;
817             }
818             length = newLength;
819             ++p;
820             if (!(msgByte & 0x80)) {
821                 lengthFinished = true;
822                 break;
823             }
824         }
825         if (!errorFrame && !lengthFinished)
826             return false;
827         if (p + length < p) {
828             LOG(Network, "frame buffer pointer wrap %p+%lu->%p", p, static_cast<unsigned long>(length), p + length);
829             errorFrame = true;
830         }
831         if (errorFrame) {
832             skipBuffer(m_bufferSize); // Save memory.
833             m_shouldDiscardReceivedData = true;
834             m_client->didReceiveMessageError();
835             fail("WebSocket frame length too large");
836             return false;
837         }
838         ASSERT(p + length >= p);
839         if (p + length <= end) {
840             p += length;
841             nextFrame = p;
842             ASSERT(nextFrame > m_buffer);
843             skipBuffer(nextFrame - m_buffer);
844             if (frameByte == 0xff && !length) {
845                 m_receivedClosingHandshake = true;
846                 startClosingHandshake(CloseEventCodeNotSpecified, "");
847                 if (m_closing)
848                     m_handle->close(); // close after sending FF 00.
849             } else
850                 m_client->didReceiveMessageError();
851             return m_buffer;
852         }
853         return false;
854     }
855
856     const char* msgStart = p;
857     while (p < end && *p != '\xff')
858         ++p;
859     if (p < end && *p == '\xff') {
860         int msgLength = p - msgStart;
861         ++p;
862         nextFrame = p;
863         if (frameByte == 0x00) {
864             String msg = String::fromUTF8(msgStart, msgLength);
865             skipBuffer(nextFrame - m_buffer);
866             m_client->didReceiveMessage(msg);
867         } else {
868             skipBuffer(nextFrame - m_buffer);
869             m_client->didReceiveMessageError();
870         }
871         return m_buffer;
872     }
873     return false;
874 }
875
876 void WebSocketChannel::enqueueTextFrame(const CString& string)
877 {
878     ASSERT(!m_useHixie76Protocol);
879     ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
880     OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame);
881     frame->opCode = WebSocketFrame::OpCodeText;
882     frame->frameType = QueuedFrameTypeString;
883     frame->stringData = string;
884     m_outgoingFrameQueue.append(frame.release());
885     processOutgoingFrameQueue();
886 }
887
888 void WebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
889 {
890     ASSERT(!m_useHixie76Protocol);
891     ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
892     OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame);
893     frame->opCode = opCode;
894     frame->frameType = QueuedFrameTypeVector;
895     frame->vectorData.resize(dataLength);
896     if (dataLength)
897         memcpy(frame->vectorData.data(), data, dataLength);
898     m_outgoingFrameQueue.append(frame.release());
899     processOutgoingFrameQueue();
900 }
901
902 void WebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, const Blob& blob)
903 {
904     ASSERT(!m_useHixie76Protocol);
905     ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
906     OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame);
907     frame->opCode = opCode;
908     frame->frameType = QueuedFrameTypeBlob;
909     frame->blobData = Blob::create(blob.url(), blob.type(), blob.size());
910     m_outgoingFrameQueue.append(frame.release());
911     processOutgoingFrameQueue();
912 }
913
914 void WebSocketChannel::processOutgoingFrameQueue()
915 {
916     ASSERT(!m_useHixie76Protocol);
917     if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed)
918         return;
919
920     while (!m_outgoingFrameQueue.isEmpty()) {
921         OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst();
922         switch (frame->frameType) {
923         case QueuedFrameTypeString: {
924             if (!sendFrame(frame->opCode, frame->stringData.data(), frame->stringData.length()))
925                 fail("Failed to send WebSocket frame.");
926             break;
927         }
928
929         case QueuedFrameTypeVector:
930             if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vectorData.size()))
931                 fail("Failed to send WebSocket frame.");
932             break;
933
934         case QueuedFrameTypeBlob: {
935 #if ENABLE(BLOB)
936             switch (m_blobLoaderStatus) {
937             case BlobLoaderNotStarted:
938                 ref(); // Will be derefed after didFinishLoading() or didFail().
939                 ASSERT(!m_blobLoader);
940                 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadAsArrayBuffer, this));
941                 m_blobLoaderStatus = BlobLoaderStarted;
942                 m_blobLoader->start(m_document, frame->blobData.get());
943                 m_outgoingFrameQueue.prepend(frame.release());
944                 return;
945
946             case BlobLoaderStarted:
947             case BlobLoaderFailed:
948                 m_outgoingFrameQueue.prepend(frame.release());
949                 return;
950
951             case BlobLoaderFinished: {
952                 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult();
953                 m_blobLoader.clear();
954                 m_blobLoaderStatus = BlobLoaderNotStarted;
955                 if (!sendFrame(frame->opCode, static_cast<const char*>(result->data()), result->byteLength()))
956                     fail("Failed to send WebSocket frame.");
957                 break;
958             }
959             }
960 #else
961             fail("FileReader is not available. Could not send a Blob as WebSocket binary message.");
962 #endif
963             break;
964         }
965
966         default:
967             ASSERT_NOT_REACHED();
968             break;
969         }
970     }
971
972     ASSERT(m_outgoingFrameQueue.isEmpty());
973     if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosing) {
974         m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed;
975         m_handle->close();
976     }
977 }
978
979 void WebSocketChannel::abortOutgoingFrameQueue()
980 {
981     ASSERT(!m_useHixie76Protocol);
982     m_outgoingFrameQueue.clear();
983     m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed;
984 #if ENABLE(BLOB)
985     if (m_blobLoaderStatus == BlobLoaderStarted) {
986         m_blobLoader->cancel();
987         didFail(FileError::ABORT_ERR);
988     }
989 #endif
990 }
991
992 static void appendMaskedFramePayload(const WebSocketFrame& frame, Vector<char>& frameData)
993 {
994     size_t maskingKeyStart = frameData.size();
995     frameData.grow(frameData.size() + maskingKeyWidthInBytes); // Add placeholder for masking key. Will be overwritten.
996     size_t payloadStart = frameData.size();
997     frameData.append(frame.payload, frame.payloadLength);
998
999     cryptographicallyRandomValues(frameData.data() + maskingKeyStart, maskingKeyWidthInBytes);
1000     for (size_t i = 0; i < frame.payloadLength; ++i)
1001         frameData[payloadStart + i] ^= frameData[maskingKeyStart + i % maskingKeyWidthInBytes];
1002 }
1003
1004 static void makeFrameData(const WebSocketFrame& frame, Vector<char>& frameData)
1005 {
1006     unsigned char firstByte = (frame.final ? finalBit : 0) | frame.opCode;
1007     if (frame.compress)
1008         firstByte |= compressBit;
1009     frameData.append(firstByte);
1010     if (frame.payloadLength <= maxPayloadLengthWithoutExtendedLengthField)
1011         frameData.append(maskBit | frame.payloadLength);
1012     else if (frame.payloadLength <= 0xFFFF) {
1013         frameData.append(maskBit | payloadLengthWithTwoByteExtendedLengthField);
1014         frameData.append((frame.payloadLength & 0xFF00) >> 8);
1015         frameData.append(frame.payloadLength & 0xFF);
1016     } else {
1017         frameData.append(maskBit | payloadLengthWithEightByteExtendedLengthField);
1018         char extendedPayloadLength[8];
1019         size_t remaining = frame.payloadLength;
1020         // Fill the length into extendedPayloadLength in the network byte order.
1021         for (int i = 0; i < 8; ++i) {
1022             extendedPayloadLength[7 - i] = remaining & 0xFF;
1023             remaining >>= 8;
1024         }
1025         ASSERT(!remaining);
1026         frameData.append(extendedPayloadLength, 8);
1027     }
1028
1029     appendMaskedFramePayload(frame, frameData);
1030 }
1031
1032 bool WebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
1033 {
1034     ASSERT(m_handle);
1035     ASSERT(!m_suspended);
1036
1037     ASSERT(!(opCode & ~opCodeMask)); // Checks whether "opCode" fits in the range of opCodes.
1038     WebSocketFrame frame(opCode, true, false, true, data, dataLength);
1039
1040     OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame);
1041     if (!deflateResult->succeeded()) {
1042         fail(deflateResult->failureReason());
1043         return false;
1044     }
1045
1046     Vector<char> frameData;
1047     makeFrameData(frame, frameData);
1048
1049     return m_handle->send(frameData.data(), frameData.size());
1050 }
1051
1052 bool WebSocketChannel::sendFrameHixie76(const char* data, size_t dataLength)
1053 {
1054     ASSERT(m_handle);
1055     ASSERT(!m_suspended);
1056
1057     Vector<char> frame;
1058     frame.append('\0'); // Frame type.
1059     frame.append(data, dataLength);
1060     frame.append('\xff'); // Frame end.
1061     return m_handle->send(frame.data(), frame.size());
1062 }
1063
1064 }  // namespace WebCore
1065
1066 #endif  // ENABLE(WEB_SOCKETS)