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 "ExceptionCodePlaceholder.h" 41#include "FileError.h" 42#include "FileReaderLoader.h" 43#include "Frame.h" 44#include "InspectorInstrumentation.h" 45#include "Logging.h" 46#include "Page.h" 47#include "ProgressTracker.h" 48#include "ResourceRequest.h" 49#include "ScriptExecutionContext.h" 50#include "Settings.h" 51#include "SocketStreamError.h" 52#include "SocketStreamHandle.h" 53#include "WebSocketChannelClient.h" 54#include "WebSocketHandshake.h" 55#include <runtime/ArrayBuffer.h> 56#include <wtf/Deque.h> 57#include <wtf/FastMalloc.h> 58#include <wtf/HashMap.h> 59#include <wtf/OwnPtr.h> 60#include <wtf/PassOwnPtr.h> 61#include <wtf/text/CString.h> 62#include <wtf/text/StringHash.h> 63#include <wtf/text/WTFString.h> 64 65namespace WebCore { 66 67const double TCPMaximumSegmentLifetime = 2 * 60.0; 68 69WebSocketChannel::WebSocketChannel(Document* document, WebSocketChannelClient* client) 70 : m_document(document) 71 , m_client(client) 72 , m_resumeTimer(this, &WebSocketChannel::resumeTimerFired) 73 , m_suspended(false) 74 , m_closing(false) 75 , m_receivedClosingHandshake(false) 76 , m_closingTimer(this, &WebSocketChannel::closingTimerFired) 77 , m_closed(false) 78 , m_shouldDiscardReceivedData(false) 79 , m_unhandledBufferedAmount(0) 80 , m_identifier(0) 81 , m_hasContinuousFrame(false) 82 , m_closeEventCode(CloseEventCodeAbnormalClosure) 83 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) 84 , m_blobLoaderStatus(BlobLoaderNotStarted) 85{ 86 if (Page* page = m_document->page()) 87 m_identifier = page->progress().createUniqueIdentifier(); 88} 89 90WebSocketChannel::~WebSocketChannel() 91{ 92} 93 94void WebSocketChannel::connect(const URL& url, const String& protocol) 95{ 96 LOG(Network, "WebSocketChannel %p connect()", this); 97 ASSERT(!m_handle); 98 ASSERT(!m_suspended); 99 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); 100 m_handshake->reset(); 101 if (m_deflateFramer.canDeflate()) 102 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor()); 103 if (m_identifier) 104 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, url, m_document->url(), protocol); 105 ref(); 106 m_handle = SocketStreamHandle::create(m_handshake->url(), this); 107} 108 109String WebSocketChannel::subprotocol() 110{ 111 LOG(Network, "WebSocketChannel %p subprotocol()", this); 112 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) 113 return ""; 114 String serverProtocol = m_handshake->serverWebSocketProtocol(); 115 if (serverProtocol.isNull()) 116 return ""; 117 return serverProtocol; 118} 119 120String WebSocketChannel::extensions() 121{ 122 LOG(Network, "WebSocketChannel %p extensions()", this); 123 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) 124 return ""; 125 String extensions = m_handshake->acceptedExtensions(); 126 if (extensions.isNull()) 127 return ""; 128 return extensions; 129} 130 131ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const String& message) 132{ 133 LOG(Network, "WebSocketChannel %p send() Sending String '%s'", this, message.utf8().data()); 134 CString utf8 = message.utf8(StrictConversionReplacingUnpairedSurrogatesWithFFFD); 135 enqueueTextFrame(utf8); 136 processOutgoingFrameQueue(); 137 // According to WebSocket API specification, WebSocket.send() should return void instead 138 // of boolean. However, our implementation still returns boolean due to compatibility 139 // concern (see bug 65850). 140 // m_channel->send() may happen later, thus it's not always possible to know whether 141 // the message has been sent to the socket successfully. In this case, we have no choice 142 // but to return true. 143 return ThreadableWebSocketChannel::SendSuccess; 144} 145 146ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) 147{ 148 LOG(Network, "WebSocketChannel %p send() Sending ArrayBuffer %p byteOffset=%u byteLength=%u", this, &binaryData, byteOffset, byteLength); 149 enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()) + byteOffset, byteLength); 150 processOutgoingFrameQueue(); 151 return ThreadableWebSocketChannel::SendSuccess; 152} 153 154ThreadableWebSocketChannel::SendResult WebSocketChannel::send(Blob& binaryData) 155{ 156 LOG(Network, "WebSocketChannel %p send() Sending Blob '%s'", this, binaryData.url().string().utf8().data()); 157 enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData); 158 processOutgoingFrameQueue(); 159 return ThreadableWebSocketChannel::SendSuccess; 160} 161 162bool WebSocketChannel::send(const char* data, int length) 163{ 164 LOG(Network, "WebSocketChannel %p send() Sending char* data=%p length=%d", this, data, length); 165 enqueueRawFrame(WebSocketFrame::OpCodeBinary, data, length); 166 processOutgoingFrameQueue(); 167 return true; 168} 169 170unsigned long WebSocketChannel::bufferedAmount() const 171{ 172 LOG(Network, "WebSocketChannel %p bufferedAmount()", this); 173 ASSERT(m_handle); 174 ASSERT(!m_suspended); 175 return m_handle->bufferedAmount(); 176} 177 178void WebSocketChannel::close(int code, const String& reason) 179{ 180 LOG(Network, "WebSocketChannel %p close() code=%d reason='%s'", this, code, reason.utf8().data()); 181 ASSERT(!m_suspended); 182 if (!m_handle) 183 return; 184 startClosingHandshake(code, reason); 185 if (m_closing && !m_closingTimer.isActive()) 186 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); 187} 188 189void WebSocketChannel::fail(const String& reason) 190{ 191 LOG(Network, "WebSocketChannel %p fail() reason='%s'", this, reason.utf8().data()); 192 ASSERT(!m_suspended); 193 if (m_document) { 194 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_identifier, reason); 195 m_document->addConsoleMessage(MessageSource::Network, MessageLevel::Error, "WebSocket connection to '" + m_handshake->url().stringCenterEllipsizedToLength() + "' failed: " + reason); 196 } 197 198 // Hybi-10 specification explicitly states we must not continue to handle incoming data 199 // once the WebSocket connection is failed (section 7.1.7). 200 Ref<WebSocketChannel> protect(*this); // The client can close the channel, potentially removing the last reference. 201 m_shouldDiscardReceivedData = true; 202 if (!m_buffer.isEmpty()) 203 skipBuffer(m_buffer.size()); // Save memory. 204 m_deflateFramer.didFail(); 205 m_hasContinuousFrame = false; 206 m_continuousFrameData.clear(); 207 m_client->didReceiveMessageError(); 208 209 if (m_handle && !m_closed) 210 m_handle->disconnect(); // Will call didClose(). 211} 212 213void WebSocketChannel::disconnect() 214{ 215 LOG(Network, "WebSocketChannel %p disconnect()", this); 216 if (m_identifier && m_document) 217 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 218 if (m_handshake) 219 m_handshake->clearScriptExecutionContext(); 220 m_client = 0; 221 m_document = 0; 222 if (m_handle) 223 m_handle->disconnect(); 224} 225 226void WebSocketChannel::suspend() 227{ 228 m_suspended = true; 229} 230 231void WebSocketChannel::resume() 232{ 233 m_suspended = false; 234 if ((!m_buffer.isEmpty() || m_closed) && m_client && !m_resumeTimer.isActive()) 235 m_resumeTimer.startOneShot(0); 236} 237 238void WebSocketChannel::willOpenSocketStream(SocketStreamHandle*) 239{ 240 LOG(Network, "WebSocketChannel %p willOpenSocketStream()", this); 241} 242 243void WebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) 244{ 245 LOG(Network, "WebSocketChannel %p didOpenSocketStream()", this); 246 ASSERT(handle == m_handle); 247 if (!m_document) 248 return; 249 if (m_identifier) 250 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, m_handshake->clientHandshakeRequest()); 251 CString handshakeMessage = m_handshake->clientHandshakeMessage(); 252 if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) 253 fail("Failed to send WebSocket handshake."); 254} 255 256void WebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle) 257{ 258 LOG(Network, "WebSocketChannel %p didCloseSocketStream()", this); 259 if (m_identifier && m_document) 260 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 261 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 262 m_closed = true; 263 if (m_closingTimer.isActive()) 264 m_closingTimer.stop(); 265 if (m_outgoingFrameQueueStatus != OutgoingFrameQueueClosed) 266 abortOutgoingFrameQueue(); 267 if (m_handle) { 268 m_unhandledBufferedAmount = m_handle->bufferedAmount(); 269 if (m_suspended) 270 return; 271 WebSocketChannelClient* client = m_client; 272 m_client = 0; 273 m_document = 0; 274 m_handle = 0; 275 if (client) 276 client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason); 277 } 278 deref(); 279} 280 281void WebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle* handle, const char* data, int len) 282{ 283 LOG(Network, "WebSocketChannel %p didReceiveSocketStreamData() Received %d bytes", this, len); 284 Ref<WebSocketChannel> protect(*this); // The client can close the channel, potentially removing the last reference. 285 ASSERT(handle == m_handle); 286 if (!m_document) { 287 return; 288 } 289 if (len <= 0) { 290 handle->disconnect(); 291 return; 292 } 293 if (!m_client) { 294 m_shouldDiscardReceivedData = true; 295 handle->disconnect(); 296 return; 297 } 298 if (m_shouldDiscardReceivedData) 299 return; 300 if (!appendToBuffer(data, len)) { 301 m_shouldDiscardReceivedData = true; 302 fail("Ran out of memory while receiving WebSocket data."); 303 return; 304 } 305 while (!m_suspended && m_client && !m_buffer.isEmpty()) 306 if (!processBuffer()) 307 break; 308} 309 310void WebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, size_t bufferedAmount) 311{ 312 if (m_client) 313 m_client->didUpdateBufferedAmount(bufferedAmount); 314} 315 316void WebSocketChannel::didFailSocketStream(SocketStreamHandle* handle, const SocketStreamError& error) 317{ 318 LOG(Network, "WebSocketChannel %p didFailSocketStream()", this); 319 ASSERT(handle == m_handle || !m_handle); 320 if (m_document) { 321 String message; 322 if (error.isNull()) 323 message = "WebSocket network error"; 324 else if (error.localizedDescription().isNull()) 325 message = "WebSocket network error: error code " + String::number(error.errorCode()); 326 else 327 message = "WebSocket network error: " + error.localizedDescription(); 328 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_identifier, message); 329 m_document->addConsoleMessage(MessageSource::Network, MessageLevel::Error, message); 330 } 331 m_shouldDiscardReceivedData = true; 332 handle->disconnect(); 333} 334 335void WebSocketChannel::didReceiveAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&) 336{ 337} 338 339void WebSocketChannel::didCancelAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&) 340{ 341} 342 343void WebSocketChannel::didStartLoading() 344{ 345 LOG(Network, "WebSocketChannel %p didStartLoading()", this); 346 ASSERT(m_blobLoader); 347 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 348} 349 350void WebSocketChannel::didReceiveData() 351{ 352 LOG(Network, "WebSocketChannel %p didReceiveData()", this); 353 ASSERT(m_blobLoader); 354 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 355} 356 357void WebSocketChannel::didFinishLoading() 358{ 359 LOG(Network, "WebSocketChannel %p didFinishLoading()", this); 360 ASSERT(m_blobLoader); 361 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 362 m_blobLoaderStatus = BlobLoaderFinished; 363 processOutgoingFrameQueue(); 364 deref(); 365} 366 367void WebSocketChannel::didFail(int errorCode) 368{ 369 LOG(Network, "WebSocketChannel %p didFail() errorCode=%d", this, errorCode); 370 ASSERT(m_blobLoader); 371 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 372 m_blobLoader.clear(); 373 m_blobLoaderStatus = BlobLoaderFailed; 374 fail("Failed to load Blob: error code = " + String::number(errorCode)); // FIXME: Generate human-friendly reason message. 375 deref(); 376} 377 378bool WebSocketChannel::appendToBuffer(const char* data, size_t len) 379{ 380 size_t newBufferSize = m_buffer.size() + len; 381 if (newBufferSize < m_buffer.size()) { 382 LOG(Network, "WebSocketChannel %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)); 383 return false; 384 } 385 m_buffer.append(data, len); 386 return true; 387} 388 389void WebSocketChannel::skipBuffer(size_t len) 390{ 391 ASSERT_WITH_SECURITY_IMPLICATION(len <= m_buffer.size()); 392 memmove(m_buffer.data(), m_buffer.data() + len, m_buffer.size() - len); 393 m_buffer.resize(m_buffer.size() - len); 394} 395 396bool WebSocketChannel::processBuffer() 397{ 398 ASSERT(!m_suspended); 399 ASSERT(m_client); 400 ASSERT(!m_buffer.isEmpty()); 401 LOG(Network, "WebSocketChannel %p processBuffer() Receive buffer has %lu bytes", this, static_cast<unsigned long>(m_buffer.size())); 402 403 if (m_shouldDiscardReceivedData) 404 return false; 405 406 if (m_receivedClosingHandshake) { 407 skipBuffer(m_buffer.size()); 408 return false; 409 } 410 411 Ref<WebSocketChannel> protect(*this); // The client can close the channel, potentially removing the last reference. 412 413 if (m_handshake->mode() == WebSocketHandshake::Incomplete) { 414 int headerLength = m_handshake->readServerHandshake(m_buffer.data(), m_buffer.size()); 415 if (headerLength <= 0) 416 return false; 417 if (m_handshake->mode() == WebSocketHandshake::Connected) { 418 if (m_identifier) 419 InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document, m_identifier, m_handshake->serverHandshakeResponse()); 420 if (!m_handshake->serverSetCookie().isEmpty()) { 421 if (cookiesEnabled(m_document)) { 422 // Exception (for sandboxed documents) ignored. 423 m_document->setCookie(m_handshake->serverSetCookie(), IGNORE_EXCEPTION); 424 } 425 } 426 // FIXME: handle set-cookie2. 427 LOG(Network, "WebSocketChannel %p Connected", this); 428 skipBuffer(headerLength); 429 m_client->didConnect(); 430 LOG(Network, "WebSocketChannel %p %lu bytes remaining in m_buffer", this, static_cast<unsigned long>(m_buffer.size())); 431 return !m_buffer.isEmpty(); 432 } 433 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); 434 LOG(Network, "WebSocketChannel %p Connection failed", this); 435 skipBuffer(headerLength); 436 m_shouldDiscardReceivedData = true; 437 fail(m_handshake->failureReason()); 438 return false; 439 } 440 if (m_handshake->mode() != WebSocketHandshake::Connected) 441 return false; 442 443 return processFrame(); 444} 445 446void WebSocketChannel::resumeTimerFired(Timer<WebSocketChannel>* timer) 447{ 448 ASSERT_UNUSED(timer, timer == &m_resumeTimer); 449 450 Ref<WebSocketChannel> protect(*this); // The client can close the channel, potentially removing the last reference. 451 while (!m_suspended && m_client && !m_buffer.isEmpty()) 452 if (!processBuffer()) 453 break; 454 if (!m_suspended && m_client && m_closed && m_handle) 455 didCloseSocketStream(m_handle.get()); 456} 457 458void WebSocketChannel::startClosingHandshake(int code, const String& reason) 459{ 460 LOG(Network, "WebSocketChannel %p startClosingHandshake() code=%d m_receivedClosingHandshake=%d", this, m_closing, m_receivedClosingHandshake); 461 if (m_closing) 462 return; 463 ASSERT(m_handle); 464 465 Vector<char> buf; 466 if (!m_receivedClosingHandshake && code != CloseEventCodeNotSpecified) { 467 unsigned char highByte = code >> 8; 468 unsigned char lowByte = code; 469 buf.append(static_cast<char>(highByte)); 470 buf.append(static_cast<char>(lowByte)); 471 buf.append(reason.utf8().data(), reason.utf8().length()); 472 } 473 enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size()); 474 processOutgoingFrameQueue(); 475 476 m_closing = true; 477 if (m_client) 478 m_client->didStartClosingHandshake(); 479} 480 481void WebSocketChannel::closingTimerFired(Timer<WebSocketChannel>* timer) 482{ 483 LOG(Network, "WebSocketChannel %p closingTimerFired()", this); 484 ASSERT_UNUSED(timer, &m_closingTimer == timer); 485 if (m_handle) 486 m_handle->disconnect(); 487} 488 489 490bool WebSocketChannel::processFrame() 491{ 492 ASSERT(!m_buffer.isEmpty()); 493 494 WebSocketFrame frame; 495 const char* frameEnd; 496 String errorString; 497 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffer.data(), m_buffer.size(), frame, frameEnd, errorString); 498 if (result == WebSocketFrame::FrameIncomplete) 499 return false; 500 if (result == WebSocketFrame::FrameError) { 501 fail(errorString); 502 return false; 503 } 504 505 ASSERT(m_buffer.data() < frameEnd); 506 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); 507 508 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); 509 if (!inflateResult->succeeded()) { 510 fail(inflateResult->failureReason()); 511 return false; 512 } 513 514 // Validate the frame data. 515 if (WebSocketFrame::isReservedOpCode(frame.opCode)) { 516 fail("Unrecognized frame opcode: " + String::number(frame.opCode)); 517 return false; 518 } 519 520 if (frame.reserved2 || frame.reserved3) { 521 fail("One or more reserved bits are on: reserved2 = " + String::number(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3)); 522 return false; 523 } 524 525 if (frame.masked) { 526 fail("A server must not mask any frames that it sends to the client."); 527 return false; 528 } 529 530 // All control frames must not be fragmented. 531 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { 532 fail("Received fragmented control frame: opcode = " + String::number(frame.opCode)); 533 return false; 534 } 535 536 // All control frames must have a payload of 125 bytes or less, which means the frame must not contain 537 // the "extended payload length" field. 538 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsExtendedLengthField(frame.payloadLength)) { 539 fail("Received control frame having too long payload: " + String::number(frame.payloadLength) + " bytes"); 540 return false; 541 } 542 543 // A new data frame is received before the previous continuous frame finishes. 544 // Note that control frames are allowed to come in the middle of continuous frames. 545 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) { 546 fail("Received new data frame but previous continuous frame is unfinished."); 547 return false; 548 } 549 550 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame); 551 552 switch (frame.opCode) { 553 case WebSocketFrame::OpCodeContinuation: 554 // An unexpected continuation frame is received without any leading frame. 555 if (!m_hasContinuousFrame) { 556 fail("Received unexpected continuation frame."); 557 return false; 558 } 559 m_continuousFrameData.append(frame.payload, frame.payloadLength); 560 skipBuffer(frameEnd - m_buffer.data()); 561 if (frame.final) { 562 // onmessage handler may eventually call the other methods of this channel, 563 // so we should pretend that we have finished to read this frame and 564 // make sure that the member variables are in a consistent state before 565 // the handler is invoked. 566 // Vector<char>::swap() is used here to clear m_continuousFrameData. 567 OwnPtr<Vector<char>> continuousFrameData = adoptPtr(new Vector<char>); 568 m_continuousFrameData.swap(*continuousFrameData); 569 m_hasContinuousFrame = false; 570 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { 571 String message; 572 if (continuousFrameData->size()) 573 message = String::fromUTF8(continuousFrameData->data(), continuousFrameData->size()); 574 else 575 message = ""; 576 if (message.isNull()) 577 fail("Could not decode a text frame as UTF-8."); 578 else 579 m_client->didReceiveMessage(message); 580 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) 581 m_client->didReceiveBinaryData(continuousFrameData.release()); 582 } 583 break; 584 585 case WebSocketFrame::OpCodeText: 586 if (frame.final) { 587 String message; 588 if (frame.payloadLength) 589 message = String::fromUTF8(frame.payload, frame.payloadLength); 590 else 591 message = ""; 592 skipBuffer(frameEnd - m_buffer.data()); 593 if (message.isNull()) 594 fail("Could not decode a text frame as UTF-8."); 595 else 596 m_client->didReceiveMessage(message); 597 } else { 598 m_hasContinuousFrame = true; 599 m_continuousFrameOpCode = WebSocketFrame::OpCodeText; 600 ASSERT(m_continuousFrameData.isEmpty()); 601 m_continuousFrameData.append(frame.payload, frame.payloadLength); 602 skipBuffer(frameEnd - m_buffer.data()); 603 } 604 break; 605 606 case WebSocketFrame::OpCodeBinary: 607 if (frame.final) { 608 OwnPtr<Vector<char>> binaryData = adoptPtr(new Vector<char>(frame.payloadLength)); 609 memcpy(binaryData->data(), frame.payload, frame.payloadLength); 610 skipBuffer(frameEnd - m_buffer.data()); 611 m_client->didReceiveBinaryData(binaryData.release()); 612 } else { 613 m_hasContinuousFrame = true; 614 m_continuousFrameOpCode = WebSocketFrame::OpCodeBinary; 615 ASSERT(m_continuousFrameData.isEmpty()); 616 m_continuousFrameData.append(frame.payload, frame.payloadLength); 617 skipBuffer(frameEnd - m_buffer.data()); 618 } 619 break; 620 621 case WebSocketFrame::OpCodeClose: 622 if (!frame.payloadLength) 623 m_closeEventCode = CloseEventCodeNoStatusRcvd; 624 else if (frame.payloadLength == 1) { 625 m_closeEventCode = CloseEventCodeAbnormalClosure; 626 fail("Received a broken close frame containing an invalid size body."); 627 return false; 628 } else { 629 unsigned char highByte = static_cast<unsigned char>(frame.payload[0]); 630 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]); 631 m_closeEventCode = highByte << 8 | lowByte; 632 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCode == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHandshake) { 633 m_closeEventCode = CloseEventCodeAbnormalClosure; 634 fail("Received a broken close frame containing a reserved status code."); 635 return false; 636 } 637 } 638 if (frame.payloadLength >= 3) 639 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2); 640 else 641 m_closeEventReason = ""; 642 skipBuffer(frameEnd - m_buffer.data()); 643 m_receivedClosingHandshake = true; 644 startClosingHandshake(m_closeEventCode, m_closeEventReason); 645 if (m_closing) { 646 m_outgoingFrameQueueStatus = OutgoingFrameQueueClosing; 647 processOutgoingFrameQueue(); 648 } 649 break; 650 651 case WebSocketFrame::OpCodePing: 652 enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength); 653 skipBuffer(frameEnd - m_buffer.data()); 654 processOutgoingFrameQueue(); 655 break; 656 657 case WebSocketFrame::OpCodePong: 658 // A server may send a pong in response to our ping, or an unsolicited pong which is not associated with 659 // any specific ping. Either way, there's nothing to do on receipt of pong. 660 skipBuffer(frameEnd - m_buffer.data()); 661 break; 662 663 default: 664 ASSERT_NOT_REACHED(); 665 skipBuffer(frameEnd - m_buffer.data()); 666 break; 667 } 668 669 return !m_buffer.isEmpty(); 670} 671 672void WebSocketChannel::enqueueTextFrame(const CString& string) 673{ 674 ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 675 OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 676 frame->opCode = WebSocketFrame::OpCodeText; 677 frame->frameType = QueuedFrameTypeString; 678 frame->stringData = string; 679 m_outgoingFrameQueue.append(frame.release()); 680} 681 682void WebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 683{ 684 ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 685 OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 686 frame->opCode = opCode; 687 frame->frameType = QueuedFrameTypeVector; 688 frame->vectorData.resize(dataLength); 689 if (dataLength) 690 memcpy(frame->vectorData.data(), data, dataLength); 691 m_outgoingFrameQueue.append(frame.release()); 692} 693 694void WebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, Blob& blob) 695{ 696 ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 697 OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 698 frame->opCode = opCode; 699 frame->frameType = QueuedFrameTypeBlob; 700 frame->blobData = &blob; 701 m_outgoingFrameQueue.append(frame.release()); 702} 703 704void WebSocketChannel::processOutgoingFrameQueue() 705{ 706 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) 707 return; 708 709 while (!m_outgoingFrameQueue.isEmpty()) { 710 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); 711 switch (frame->frameType) { 712 case QueuedFrameTypeString: { 713 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->stringData.length())) 714 fail("Failed to send WebSocket frame."); 715 break; 716 } 717 718 case QueuedFrameTypeVector: 719 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vectorData.size())) 720 fail("Failed to send WebSocket frame."); 721 break; 722 723 case QueuedFrameTypeBlob: { 724 switch (m_blobLoaderStatus) { 725 case BlobLoaderNotStarted: 726 ref(); // Will be derefed after didFinishLoading() or didFail(). 727 ASSERT(!m_blobLoader); 728 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadAsArrayBuffer, this)); 729 m_blobLoaderStatus = BlobLoaderStarted; 730 m_blobLoader->start(m_document, frame->blobData.get()); 731 m_outgoingFrameQueue.prepend(frame.release()); 732 return; 733 734 case BlobLoaderStarted: 735 case BlobLoaderFailed: 736 m_outgoingFrameQueue.prepend(frame.release()); 737 return; 738 739 case BlobLoaderFinished: { 740 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); 741 m_blobLoader.clear(); 742 m_blobLoaderStatus = BlobLoaderNotStarted; 743 if (!sendFrame(frame->opCode, static_cast<const char*>(result->data()), result->byteLength())) 744 fail("Failed to send WebSocket frame."); 745 break; 746 } 747 } 748 break; 749 } 750 751 default: 752 ASSERT_NOT_REACHED(); 753 break; 754 } 755 } 756 757 ASSERT(m_outgoingFrameQueue.isEmpty()); 758 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosing) { 759 m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed; 760 m_handle->close(); 761 } 762} 763 764void WebSocketChannel::abortOutgoingFrameQueue() 765{ 766 m_outgoingFrameQueue.clear(); 767 m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed; 768 if (m_blobLoaderStatus == BlobLoaderStarted) { 769 m_blobLoader->cancel(); 770 didFail(FileError::ABORT_ERR); 771 } 772} 773 774bool WebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 775{ 776 ASSERT(m_handle); 777 ASSERT(!m_suspended); 778 779 WebSocketFrame frame(opCode, true, false, true, data, dataLength); 780 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, frame); 781 782 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); 783 if (!deflateResult->succeeded()) { 784 fail(deflateResult->failureReason()); 785 return false; 786 } 787 788 Vector<char> frameData; 789 frame.makeFrameData(frameData); 790 791 return m_handle->send(frameData.data(), frameData.size()); 792} 793 794} // namespace WebCore 795 796#endif // ENABLE(WEB_SOCKETS) 797