15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011, 2012 Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/MainThreadWebSocketChannel.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 34df95704c49daea886ddad70775bda23618d6274dBen Murdoch#include "bindings/v8/ExceptionStatePlaceholder.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h" 361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/dom/ExecutionContext.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/Blob.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/FileReaderLoader.h" 39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h" 41f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "core/inspector/InspectorTraceEvents.h" 4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoader.h" 4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoaderClient.h" 44f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "core/loader/MixedContentChecker.h" 4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/UniqueIdentifier.h" 4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Page.h" 4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/WebSocketChannelClient.h" 481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h" 491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/network/SocketStreamError.h" 501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/network/SocketStreamHandle.h" 5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/ArrayBuffer.h" 5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/FastMalloc.h" 5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/HashMap.h" 5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/OwnPtr.h" 5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/StringHash.h" 5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/WTFString.h" 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std; 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double TCPMaximumSegmentLifetime = 2 * 60.0; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_document(document) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_client(client) 6753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_suspended(false) 6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) , m_didFailOfClientAlreadyRun(false) 7051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) , m_hasCalledDisconnectOnHandle(false) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_receivedClosingHandshake(false) 7253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) 735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) , m_state(ChannelIdle) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_shouldDiscardReceivedData(false) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_identifier(0) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasContinuousFrame(false) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_closeEventCode(CloseEventCodeAbnormalClosure) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) 7976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) , m_numConsumedBytesInCurrentFrame(0) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_blobLoaderStatus(BlobLoaderNotStarted) 81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) , m_sourceURLAtConstruction(sourceURL) 82a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) , m_lineNumberAtConstruction(lineNumber) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (m_document->page()) 8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_identifier = createUniqueIdentifier(); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)MainThreadWebSocketChannel::~MainThreadWebSocketChannel() 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 92f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liubool MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 94a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p connect()", this); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_handle); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 97f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 98f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_document->frame() && !m_document->frame()->loader().mixedContentChecker()->canConnectInsecureWebSocket(m_document->securityOrigin(), url)) 99f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return false; 100f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (MixedContentChecker::isMixedContent(m_document->securityOrigin(), url)) { 101f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu String message = "Connecting to a non-secure WebSocket server from a secure origin is deprecated."; 102f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu m_document->addConsoleMessage(JSMessageSource, WarningMessageLevel, message); 103f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 104f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_handshake->reset(); 107bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionProcessor()); 10881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor()); 109f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier) { 110f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketCreate", "data", InspectorWebSocketCreateEvent::data(m_document, m_identifier, url, protocol)); 111323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 112f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 11393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, url, protocol); 114f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ref(); 116f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 117f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_handle = SocketStreamHandle::create(this); 118f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) ASSERT(m_handle); 119f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (m_document->frame()) { 120f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_document->frame()->loader().client()->dispatchWillOpenSocketStream(m_handle.get()); 121f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 122f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_handle->connect(m_handshake->url()); 123f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 124f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return true; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)WebSocketChannel::SendResult MainThreadWebSocketChannel::send(const String& message) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 129a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending String '%s'", this, message.utf8().data()); 13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CString utf8 = message.utf8(StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD); 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueTextFrame(utf8); 13253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // m_channel->send() may happen later, thus it's not always possible to know whether 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the message has been sent to the socket successfully. In this case, we have no choice 135521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // but to return SendSuccess. 13653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return WebSocketChannel::SendSuccess; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)WebSocketChannel::SendResult MainThreadWebSocketChannel::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 141a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending ArrayBuffer %p byteOffset=%u byteLength=%u", this, &binaryData, byteOffset, byteLength); 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()) + byteOffset, byteLength); 14353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 14453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return WebSocketChannel::SendSuccess; 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)WebSocketChannel::SendResult MainThreadWebSocketChannel::send(PassRefPtr<BlobDataHandle> binaryData) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 149a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending Blob '%s'", this, binaryData->uuid().utf8().data()); 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData); 15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return WebSocketChannel::SendSuccess; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 155d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)WebSocketChannel::SendResult MainThreadWebSocketChannel::send(PassOwnPtr<Vector<char> > data) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 157d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending Vector %p", this, data.get()); 158d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) enqueueVector(WebSocketFrame::OpCodeBinary, data); 15953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 160d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return WebSocketChannel::SendSuccess; 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::close(int code, const String& reason) 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 165a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", this, code, reason.utf8().data()); 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_handle) 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startClosingHandshake(code, reason); 170521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (!m_closingTimer.isActive()) 171d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime, FROM_HERE); 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MainThreadWebSocketChannel::clearDocument() 17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (m_handshake) 17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_handshake->clearDocument(); 17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_document = 0; 17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 18151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void MainThreadWebSocketChannel::disconnectHandle() 18251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){ 18351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (!m_handle) 18451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return; 18551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) m_hasCalledDisconnectOnHandle = true; 18651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) m_handle->disconnect(); 18751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)} 18851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void MainThreadWebSocketChannel::callDidReceiveMessageError() 190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 191d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!m_client || m_didFailOfClientAlreadyRun) 192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return; 193d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_didFailOfClientAlreadyRun = true; 194d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_client->didReceiveMessageError(); 195d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 196d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 19781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 199a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reason.utf8().data()); 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_document) { 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_identifier, reason); 20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const String message = "WebSocket connection to '" + m_handshake->url().elidedString() + "' failed: " + reason; 203a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_document->addConsoleMessage(JSMessageSource, level, message, sourceURL, lineNumber); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Hybi-10 specification explicitly states we must not continue to handle incoming data 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // once the WebSocket connection is failed (section 7.1.7). 207323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_buffer.isEmpty()) 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(m_buffer.size()); // Save memory. 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_deflateFramer.didFail(); 21253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_perMessageDeflate.didFail(); 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = false; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.clear(); 215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 216d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) callDidReceiveMessageError(); 217d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 21851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (m_state != ChannelClosed) 21951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); // Will call didCloseSocketStream(). 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::disconnect() 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 224a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p disconnect()", this); 225f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier && m_document) { 226f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 227323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 228f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 230f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 23109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) clearDocument(); 23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client = 0; 23551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::suspend() 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_suspended = true; 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::resume() 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_suspended = false; 2465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if ((!m_buffer.isEmpty() || (m_state == ChannelClosed)) && m_client && !m_resumeTimer.isActive()) 247d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_resumeTimer.startOneShot(0, FROM_HERE); 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 252a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(handle == m_handle); 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_document) 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 256f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier) { 257f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketSendHandshakeRequest", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 258323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 259f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 260d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, m_handshake->clientHandshakeRequest().get()); 261f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CString handshakeMessage = m_handshake->clientHandshakeMessage(); 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) 26481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket handshake."); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle) 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 269a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); 270f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier && m_document) { 271f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 272323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 273f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 275f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 27751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 27851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) // Show error message on JS console if this is unexpected connection close 27951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) // during opening handshake. 28051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (!m_hasCalledDisconnectOnHandle && m_handshake->mode() == WebSocketHandshake::Incomplete && m_document) { 28151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) const String message = "WebSocket connection to '" + m_handshake->url().elidedString() + "' failed: Connection closed before receiving a handshake response"; 282a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message, m_sourceURLAtConstruction, m_lineNumberAtConstruction); 28351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 28451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 2855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_state = ChannelClosed; 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_closingTimer.isActive()) 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closingTimer.stop(); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_outgoingFrameQueueStatus != OutgoingFrameQueueClosed) 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) abortOutgoingFrameQueue(); 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handle) { 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WebSocketChannelClient* client = m_client; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client = 0; 29309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) clearDocument(); 294d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_handle = nullptr; 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (client) 29676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) client->didClose(m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason); 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deref(); 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle* handle, const char* data, int len) 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 303a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didReceiveSocketStreamData() Received %d bytes", this, len); 304323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(handle == m_handle); 30653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m_document) 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (len <= 0) { 30951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_client) { 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 31451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_shouldDiscardReceivedData) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!appendToBuffer(data, len)) { 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 32181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Ran out of memory while receiving WebSocket data."); 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 324f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) processBuffer(); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)void MainThreadWebSocketChannel::didConsumeBufferedAmount(SocketStreamHandle*, size_t consumed) 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 32976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (m_framingOverheadQueue.isEmpty()) { 33076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // Ignore the handshake consumption. 33176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) return; 33276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 33376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (!m_client || m_state == ChannelClosed) 33476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) return; 33576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) size_t remain = consumed; 33676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) while (remain > 0) { 33776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) ASSERT(!m_framingOverheadQueue.isEmpty()); 33876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) const FramingOverhead& frame = m_framingOverheadQueue.first(); 33976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) 34076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) ASSERT(m_numConsumedBytesInCurrentFrame <= frame.frameDataSize()); 34176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) size_t consumedInThisFrame = std::min(remain, frame.frameDataSize() - m_numConsumedBytesInCurrentFrame); 34276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) remain -= consumedInThisFrame; 34376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_numConsumedBytesInCurrentFrame += consumedInThisFrame; 34476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) 34576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (m_numConsumedBytesInCurrentFrame == frame.frameDataSize()) { 34676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (m_client && WebSocketFrame::isNonControlOpCode(frame.opcode())) { 34776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // FIXME: As |consumed| is the number of possibly compressed 34876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // bytes, we can't determine the number of consumed original 34976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // bytes in the middle of a frame. 35076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_client->didConsumeBufferedAmount(frame.originalPayloadLength()); 35176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 35276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_framingOverheadQueue.takeFirst(); 35376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_numConsumedBytesInCurrentFrame = 0; 35476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 35576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didFailSocketStream(SocketStreamHandle* handle, const SocketStreamError& error) 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 360a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didFailSocketStream()", this); 36153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 36353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) String message; 36453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (error.isNull()) 36553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) message = "WebSocket network error"; 36653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else if (error.localizedDescription().isNull()) 36753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) message = "WebSocket network error: error code " + String::number(error.errorCode()); 36853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else 36953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) message = "WebSocket network error: error code " + String::number(error.errorCode()) + ", " + error.localizedDescription(); 37053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) String failingURL = error.failingURL(); 37153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT(failingURL.isNull() || m_handshake->url().string() == failingURL); 37253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (failingURL.isNull()) 37353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) failingURL = m_handshake->url().string(); 374a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "Error Message: '%s', FailURL: '%s'", message.utf8().data(), failingURL.utf8().data()); 375d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 376323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) RefPtrWillBeRawPtr<WebSocketChannel> protect(this); 377d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 378d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (m_state != ChannelClosing && m_state != ChannelClosed) 379d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) callDidReceiveMessageError(); 380d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 38151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (m_state != ChannelClosed) 38251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didStartLoading() 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 387a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didStartLoading()", this); 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didReceiveData() 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 394a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didReceiveData()", this); 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didFinishLoading() 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 401a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didFinishLoading()", this); 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderFinished; 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) processOutgoingFrameQueue(); 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deref(); 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 409591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid MainThreadWebSocketChannel::didFail(FileError::ErrorCode errorCode) 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 411a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, errorCode); 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader.clear(); 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderFailed; 41681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to load Blob: error code = " + String::number(errorCode)); // FIXME: Generate human-friendly reason message. 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deref(); 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t newBufferSize = m_buffer.size() + len; 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (newBufferSize < m_buffer.size()) { 424a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p appendToBuffer() Buffer overflow (%lu bytes already in receive buffer and appending %lu bytes)", this, static_cast<unsigned long>(m_buffer.size()), static_cast<unsigned long>(len)); 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.append(data, len); 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 43153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::skipBuffer(size_t len) 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ASSERT_WITH_SECURITY_IMPLICATION(len <= m_buffer.size()); 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memmove(m_buffer.data(), m_buffer.data() + len, m_buffer.size() - len); 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.resize(m_buffer.size() - len); 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 438f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void MainThreadWebSocketChannel::processBuffer() 439f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){ 440f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) while (!m_suspended && m_client && !m_buffer.isEmpty()) { 441f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (!processOneItemFromBuffer()) 442f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) break; 443f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 444f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} 445f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 446f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)bool MainThreadWebSocketChannel::processOneItemFromBuffer() 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_client); 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_buffer.isEmpty()); 451a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p processBuffer() Receive buffer has %lu bytes", this, static_cast<unsigned long>(m_buffer.size())); 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_shouldDiscardReceivedData) 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_receivedClosingHandshake) { 4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(m_buffer.size()); 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 461323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. 4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handshake->mode() == WebSocketHandshake::Incomplete) { 4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int headerLength = m_handshake->readServerHandshake(m_buffer.data(), m_buffer.size()); 4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (headerLength <= 0) 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handshake->mode() == WebSocketHandshake::Connected) { 468f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier) { 469323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketReceiveHandshakeResponse", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 470f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 471d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document, m_identifier, 0, &m_handshake->serverHandshakeResponse()); 472f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 47351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 47451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (m_deflateFramer.enabled() && m_document) { 47551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) const String message = "WebSocket extension \"x-webkit-deflate-frame\" is deprecated"; 476a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_document->addConsoleMessage(JSMessageSource, WarningMessageLevel, message, m_sourceURLAtConstruction, m_lineNumberAtConstruction); 47751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 47851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 479a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p Connected", this); 4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(headerLength); 4815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) String subprotocol = m_handshake->serverWebSocketProtocol(); 4825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) String extensions = m_handshake->acceptedExtensions(); 4835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) m_client->didConnect(subprotocol.isNull() ? "" : subprotocol, extensions.isNull() ? "" : extensions); 484a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m_buffer", this, static_cast<unsigned long>(m_buffer.size())); 4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !m_buffer.isEmpty(); 4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); 488a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(headerLength); 4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 49181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(m_handshake->failureReason()); 4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handshake->mode() != WebSocketHandshake::Connected) 4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return processFrame(); 4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 50053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChannel>* timer) 5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(timer, timer == &m_resumeTimer); 5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 504323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. 505f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) processBuffer(); 5065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!m_suspended && m_client && (m_state == ChannelClosed) && m_handle) 5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didCloseSocketStream(m_handle.get()); 5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 51053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::startClosingHandshake(int code, const String& reason) 5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 512a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p startClosingHandshake() code=%d m_state=%d m_receivedClosingHandshake=%d", this, code, m_state, m_receivedClosingHandshake); 5135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (m_state == ChannelClosing || m_state == ChannelClosed) 5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_handle); 5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<char> buf; 5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_receivedClosingHandshake && code != CloseEventCodeNotSpecified) { 5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char highByte = code >> 8; 5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char lowByte = code; 5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf.append(static_cast<char>(highByte)); 5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf.append(static_cast<char>(lowByte)); 5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf.append(reason.utf8().data(), reason.utf8().length()); 5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size()); 52653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_state = ChannelClosing; 5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_client) 5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didStartClosingHandshake(); 5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::closingTimerFired(Timer<MainThreadWebSocketChannel>* timer) 5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 535a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p closingTimerFired()", this); 5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(timer, &m_closingTimer == timer); 53751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 54153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool MainThreadWebSocketChannel::processFrame() 5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_buffer.isEmpty()); 5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WebSocketFrame frame; 5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const char* frameEnd; 5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String errorString; 5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffer.data(), m_buffer.size(), frame, frameEnd, errorString); 5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == WebSocketFrame::FrameIncomplete) 5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == WebSocketFrame::FrameError) { 55281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(errorString); 5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_buffer.data() < frameEnd); 5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); 5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); 5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!inflateResult->succeeded()) { 56181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(inflateResult->failureReason()); 5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 56453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m_perMessageDeflate.inflate(frame)) { 56581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(m_perMessageDeflate.failureReason()); 56653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return false; 56753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Validate the frame data. 5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (WebSocketFrame::isReservedOpCode(frame.opCode)) { 57181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Unrecognized frame opcode: " + String::number(frame.opCode)); 5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (frame.compress || frame.reserved2 || frame.reserved3) { 57681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("One or more reserved bits are on: reserved1 = " + String::number(frame.compress) + ", reserved2 = " + String::number(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3)); 5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.masked) { 58181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("A server must not mask any frames that it sends to the client."); 5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // All control frames must not be fragmented. 5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { 58781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received fragmented control frame: opcode = " + String::number(frame.opCode)); 5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // All control frames must have a payload of 125 bytes or less, which means the frame must not contain 5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the "extended payload length" field. 5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsExtendedLengthField(frame.payloadLength)) { 59481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received control frame having too long payload: " + String::number(frame.payloadLength) + " bytes"); 5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // A new data frame is received before the previous continuous frame finishes. 5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note that control frames are allowed to come in the middle of continuous frames. 6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) { 60109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) failAsError("Received start of new message but previous message is unfinished."); 6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 60509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); 6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (frame.opCode) { 6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeContinuation: 6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // An unexpected continuation frame is received without any leading frame. 6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_hasContinuousFrame) { 61181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received unexpected continuation frame."); 6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.append(frame.payload, frame.payloadLength); 6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.final) { 6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // onmessage handler may eventually call the other methods of this channel, 6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // so we should pretend that we have finished to read this frame and 6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // make sure that the member variables are in a consistent state before 6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the handler is invoked. 6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Vector<char>::swap() is used here to clear m_continuousFrameData. 6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char>); 6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.swap(*continuousFrameData); 6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = false; 6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { 6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String message; 6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (continuousFrameData->size()) 6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = String::fromUTF8(continuousFrameData->data(), continuousFrameData->size()); 6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = ""; 6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (message.isNull()) 63281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Could not decode a text frame as UTF-8."); 6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveMessage(message); 635d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) { 6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveBinaryData(continuousFrameData.release()); 637d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeText: 6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.final) { 6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String message; 6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.payloadLength) 6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = String::fromUTF8(frame.payload, frame.payloadLength); 6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = ""; 6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (message.isNull()) 65081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Could not decode a text frame as UTF-8."); 6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveMessage(message); 6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = true; 6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameOpCode = WebSocketFrame::OpCodeText; 6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_continuousFrameData.isEmpty()); 6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.append(frame.payload, frame.payloadLength); 6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeBinary: 6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.final) { 6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<Vector<char> > binaryData = adoptPtr(new Vector<char>(frame.payloadLength)); 6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(binaryData->data(), frame.payload, frame.payloadLength); 6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveBinaryData(binaryData.release()); 6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = true; 6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameOpCode = WebSocketFrame::OpCodeBinary; 6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_continuousFrameData.isEmpty()); 6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.append(frame.payload, frame.payloadLength); 6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeClose: 678d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!frame.payloadLength) { 6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = CloseEventCodeNoStatusRcvd; 680d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else if (frame.payloadLength == 1) { 6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = CloseEventCodeAbnormalClosure; 68281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received a broken close frame containing an invalid size body."); 6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char highByte = static_cast<unsigned char>(frame.payload[0]); 6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]); 6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = highByte << 8 | lowByte; 6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCode == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHandshake) { 6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = CloseEventCodeAbnormalClosure; 69081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received a broken close frame containing a reserved status code."); 6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.payloadLength >= 3) 6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2); 6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventReason = ""; 6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_receivedClosingHandshake = true; 7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startClosingHandshake(m_closeEventCode, m_closeEventReason); 701521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) m_outgoingFrameQueueStatus = OutgoingFrameQueueClosing; 702521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) processOutgoingFrameQueue(); 7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodePing: 7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength); 7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 70853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodePong: 7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // A server may send a pong in response to our ping, or an unsolicited pong which is not associated with 7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // any specific ping. Either way, there's nothing to do on receipt of pong. 7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: 7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 72353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_perMessageDeflate.resetInflateBuffer(); 7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !m_buffer.isEmpty(); 7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 72753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueTextFrame(const CString& string) 7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 730d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->opCode = WebSocketFrame::OpCodeText; 7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->frameType = QueuedFrameTypeString; 7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->stringData = string; 7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 73853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 741d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->opCode = opCode; 7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->frameType = QueuedFrameTypeVector; 7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->vectorData.resize(dataLength); 7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dataLength) 7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(frame->vectorData.data(), data, dataLength); 7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 751d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueVector(WebSocketFrame::OpCode opCode, PassOwnPtr<Vector<char> > data) 752d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 753d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 754d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 755d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 756d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) frame->opCode = opCode; 757d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) frame->frameType = QueuedFrameTypeVector; 758d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) frame->vectorData.swap(*data); 759d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 760d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 761d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7621e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, PassRefPtr<BlobDataHandle> blobData) 7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 765d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->opCode = opCode; 7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->frameType = QueuedFrameTypeBlob; 7691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) frame->blobData = blobData; 7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 77353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::processOutgoingFrameQueue() 7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) 7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!m_outgoingFrameQueue.isEmpty()) { 7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); 7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (frame->frameType) { 7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case QueuedFrameTypeString: { 7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sendFrame(frame->opCode, frame->stringData.data(), frame->stringData.length())) 78381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket frame."); 7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case QueuedFrameTypeVector: 7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vectorData.size())) 78981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket frame."); 7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case QueuedFrameTypeBlob: { 7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (m_blobLoaderStatus) { 7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderNotStarted: 7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ref(); // Will be derefed after didFinishLoading() or didFail(). 7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_blobLoader); 7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadAsArrayBuffer, this)); 7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderStarted; 7991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) m_blobLoader->start(m_document, frame->blobData); 8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.prepend(frame.release()); 8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderStarted: 8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderFailed: 8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.prepend(frame.release()); 8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderFinished: { 8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); 8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader.clear(); 8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderNotStarted; 8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sendFrame(frame->opCode, static_cast<const char*>(result->data()), result->byteLength())) 81381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket frame."); 8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: 8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueue.isEmpty()); 8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosing) { 8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed; 8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_handle->close(); 8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 83353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::abortOutgoingFrameQueue() 8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.clear(); 8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed; 8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_blobLoaderStatus == BlobLoaderStarted) { 8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader->cancel(); 8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didFail(FileError::ABORT_ERR); 8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 84353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_handle); 8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 84853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSocketFrame::Masked); 84909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); 8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); 8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!deflateResult->succeeded()) { 85381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(deflateResult->failureReason()); 8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 85753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m_perMessageDeflate.deflate(frame)) { 85881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(m_perMessageDeflate.failureReason()); 85953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return false; 86053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 86153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<char> frameData; 8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame.makeFrameData(frameData); 86476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_framingOverheadQueue.append(FramingOverhead(opCode, frameData.size(), dataLength)); 8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 86653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_perMessageDeflate.resetDeflateBuffer(); 8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_handle->send(frameData.data(), frameData.size()); 8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 87053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} // namespace WebCore 871