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