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