| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 #include "wtf/text/CString.h" | 65 #include "wtf/text/CString.h" |
| 66 #include "wtf/text/StringHash.h" | 66 #include "wtf/text/StringHash.h" |
| 67 #include "wtf/text/WTFString.h" | 67 #include "wtf/text/WTFString.h" |
| 68 | 68 |
| 69 using namespace std; | 69 using namespace std; |
| 70 | 70 |
| 71 namespace WebCore { | 71 namespace WebCore { |
| 72 | 72 |
| 73 const double TCPMaximumSegmentLifetime = 2 * 60.0; | 73 const double TCPMaximumSegmentLifetime = 2 * 60.0; |
| 74 | 74 |
| 75 MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSo
cketChannelClient* client) | 75 MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSo
cketChannelClient* client, const ScriptCallFrame& callFrame) |
| 76 : m_document(document) | 76 : m_document(document) |
| 77 , m_client(client) | 77 , m_client(client) |
| 78 , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired) | 78 , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired) |
| 79 , m_suspended(false) | 79 , m_suspended(false) |
| 80 , m_closing(false) | 80 , m_closing(false) |
| 81 , m_didFailOfClientAlreadyRun(false) | 81 , m_didFailOfClientAlreadyRun(false) |
| 82 , m_receivedClosingHandshake(false) | 82 , m_receivedClosingHandshake(false) |
| 83 , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) | 83 , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) |
| 84 , m_closed(false) | 84 , m_closed(false) |
| 85 , m_shouldDiscardReceivedData(false) | 85 , m_shouldDiscardReceivedData(false) |
| 86 , m_unhandledBufferedAmount(0) | 86 , m_unhandledBufferedAmount(0) |
| 87 , m_identifier(0) | 87 , m_identifier(0) |
| 88 , m_hasContinuousFrame(false) | 88 , m_hasContinuousFrame(false) |
| 89 , m_closeEventCode(CloseEventCodeAbnormalClosure) | 89 , m_closeEventCode(CloseEventCodeAbnormalClosure) |
| 90 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) | 90 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) |
| 91 , m_blobLoaderStatus(BlobLoaderNotStarted) | 91 , m_blobLoaderStatus(BlobLoaderNotStarted) |
| 92 , m_callFrameAtConnection("", "", 0) | 92 , m_callFrameAtConnection(callFrame) |
| 93 { | 93 { |
| 94 if (Page* page = m_document->page()) | 94 if (Page* page = m_document->page()) |
| 95 m_identifier = createUniqueIdentifier(); | 95 m_identifier = createUniqueIdentifier(); |
| 96 } | 96 } |
| 97 | 97 |
| 98 MainThreadWebSocketChannel::~MainThreadWebSocketChannel() | 98 MainThreadWebSocketChannel::~MainThreadWebSocketChannel() |
| 99 { | 99 { |
| 100 } | 100 } |
| 101 | 101 |
| 102 void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol
) | 102 void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol
) |
| 103 { | 103 { |
| 104 LOG(Network, "MainThreadWebSocketChannel %p connect()", this); | 104 LOG(Network, "MainThreadWebSocketChannel %p connect()", this); |
| 105 ASSERT(!m_handle); | 105 ASSERT(!m_handle); |
| 106 ASSERT(!m_suspended); | 106 ASSERT(!m_suspended); |
| 107 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); | 107 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); |
| 108 m_handshake->reset(); | 108 m_handshake->reset(); |
| 109 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor(
)); | 109 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor(
)); |
| 110 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) | 110 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) |
| 111 m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionPr
ocessor()); | 111 m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionPr
ocessor()); |
| 112 if (m_identifier) | 112 if (m_identifier) |
| 113 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, u
rl, m_document->url(), protocol); | 113 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, u
rl, m_document->url(), protocol); |
| 114 ref(); | 114 ref(); |
| 115 m_handle = SocketStreamHandle::create(m_handshake->url(), this); | 115 m_handle = SocketStreamHandle::create(m_handshake->url(), this); |
| 116 RefPtr<ScriptCallStack> callstack = createScriptCallStack(1, true); | 116 RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); |
| 117 m_callFrameAtConnection = callstack && callstack->size() > 0 ? callstack->at
(0) : ScriptCallFrame("", "", 0); | 117 if (callStack && callStack->size() > 0) |
| 118 m_callFrameAtConnection = callStack->at(0); |
| 118 } | 119 } |
| 119 | 120 |
| 120 String MainThreadWebSocketChannel::subprotocol() | 121 String MainThreadWebSocketChannel::subprotocol() |
| 121 { | 122 { |
| 122 LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this); | 123 LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this); |
| 123 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) | 124 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) |
| 124 return ""; | 125 return ""; |
| 125 String serverProtocol = m_handshake->serverWebSocketProtocol(); | 126 String serverProtocol = m_handshake->serverWebSocketProtocol(); |
| 126 if (serverProtocol.isNull()) | 127 if (serverProtocol.isNull()) |
| 127 return ""; | 128 return ""; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 { | 191 { |
| 191 LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", th
is, code, reason.utf8().data()); | 192 LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", th
is, code, reason.utf8().data()); |
| 192 ASSERT(!m_suspended); | 193 ASSERT(!m_suspended); |
| 193 if (!m_handle) | 194 if (!m_handle) |
| 194 return; | 195 return; |
| 195 startClosingHandshake(code, reason); | 196 startClosingHandshake(code, reason); |
| 196 if (m_closing && !m_closingTimer.isActive()) | 197 if (m_closing && !m_closingTimer.isActive()) |
| 197 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); | 198 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); |
| 198 } | 199 } |
| 199 | 200 |
| 200 void MainThreadWebSocketChannel::fail(const String& reason) | 201 void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level) |
| 202 { |
| 203 fail(reason, level, PassOwnPtr<CallStackWrapper>()); |
| 204 } |
| 205 |
| 206 void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level,
PassOwnPtr<CallStackWrapper> wrapper) |
| 201 { | 207 { |
| 202 LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reaso
n.utf8().data()); | 208 LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reaso
n.utf8().data()); |
| 203 ASSERT(!m_suspended); | 209 ASSERT(!m_suspended); |
| 204 if (m_document) { | 210 if (m_document) { |
| 205 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_id
entifier, reason); | 211 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_id
entifier, reason); |
| 206 const String message = "WebSocket connection to '" + m_handshake->url().
elidedString() + "' failed: " + reason; | 212 const String message = "WebSocket connection to '" + m_handshake->url().
elidedString() + "' failed: " + reason; |
| 207 RefPtr<ScriptCallStack> callstack = createScriptCallStack(1, true); | 213 RefPtr<ScriptCallStack> callStack = wrapper ? wrapper->createCallStack()
: 0; |
| 208 if (callstack && callstack->size() > 0) { | 214 if (callStack && callStack->size() > 0) { |
| 209 // We are in a JS callstack. | 215 String url = callStack->at(0).sourceURL(); |
| 210 // So, the addConsoleMessage method will show the stack appropriatel
y. | 216 unsigned lineNumber = callStack->at(0).lineNumber(); |
| 211 m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, me
ssage); | 217 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMessage(
JSMessageSource, level, message, url, lineNumber); |
| 212 } else { | 218 } else { |
| 213 // We are not in a JS callstack. | 219 RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); |
| 214 // Then show the source file and the line number at the connection i
nitiation. | 220 if (callStack && callStack->size() > 0) { |
| 215 const String& url = m_callFrameAtConnection.sourceURL(); | 221 // We are in a JS callstack. |
| 216 unsigned lineNumber = m_callFrameAtConnection.lineNumber(); | 222 // So, the addConsoleMessage method will show the stack appropri
ately. |
| 217 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMessage(
JSMessageSource, ErrorMessageLevel, message, url, lineNumber, 0, 0); | 223 m_document->addConsoleMessage(JSMessageSource, level, message); |
| 224 } else { |
| 225 // We are not in a JS callstack. |
| 226 // Then show the source file and the line number at the connecti
on initiation. |
| 227 const String& url = m_callFrameAtConnection.sourceURL(); |
| 228 unsigned lineNumber = m_callFrameAtConnection.lineNumber(); |
| 229 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMess
age(JSMessageSource, level, message, url, lineNumber); |
| 230 } |
| 218 } | 231 } |
| 219 } | 232 } |
| 233 failInternal(); |
| 234 } |
| 220 | 235 |
| 236 void MainThreadWebSocketChannel::failInternal() |
| 237 { |
| 221 // Hybi-10 specification explicitly states we must not continue to handle in
coming data | 238 // Hybi-10 specification explicitly states we must not continue to handle in
coming data |
| 222 // once the WebSocket connection is failed (section 7.1.7). | 239 // once the WebSocket connection is failed (section 7.1.7). |
| 223 RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close th
e channel, potentially removing the last reference. | 240 RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close th
e channel, potentially removing the last reference. |
| 224 m_shouldDiscardReceivedData = true; | 241 m_shouldDiscardReceivedData = true; |
| 225 if (!m_buffer.isEmpty()) | 242 if (!m_buffer.isEmpty()) |
| 226 skipBuffer(m_buffer.size()); // Save memory. | 243 skipBuffer(m_buffer.size()); // Save memory. |
| 227 m_deflateFramer.didFail(); | 244 m_deflateFramer.didFail(); |
| 228 m_perMessageDeflate.didFail(); | 245 m_perMessageDeflate.didFail(); |
| 229 m_hasContinuousFrame = false; | 246 m_hasContinuousFrame = false; |
| 230 m_continuousFrameData.clear(); | 247 m_continuousFrameData.clear(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) | 290 void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) |
| 274 { | 291 { |
| 275 LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); | 292 LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); |
| 276 ASSERT(handle == m_handle); | 293 ASSERT(handle == m_handle); |
| 277 if (!m_document) | 294 if (!m_document) |
| 278 return; | 295 return; |
| 279 if (m_identifier) | 296 if (m_identifier) |
| 280 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document,
m_identifier, *m_handshake->clientHandshakeRequest()); | 297 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document,
m_identifier, *m_handshake->clientHandshakeRequest()); |
| 281 CString handshakeMessage = m_handshake->clientHandshakeMessage(); | 298 CString handshakeMessage = m_handshake->clientHandshakeMessage(); |
| 282 if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) | 299 if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) |
| 283 fail("Failed to send WebSocket handshake."); | 300 failAsError("Failed to send WebSocket handshake."); |
| 284 } | 301 } |
| 285 | 302 |
| 286 void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle
) | 303 void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle
) |
| 287 { | 304 { |
| 288 LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); | 305 LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); |
| 289 if (m_identifier && m_document) | 306 if (m_identifier && m_document) |
| 290 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); | 307 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); |
| 291 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); | 308 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); |
| 292 m_closed = true; | 309 m_closed = true; |
| 293 if (m_closingTimer.isActive()) | 310 if (m_closingTimer.isActive()) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 321 } | 338 } |
| 322 if (!m_client) { | 339 if (!m_client) { |
| 323 m_shouldDiscardReceivedData = true; | 340 m_shouldDiscardReceivedData = true; |
| 324 handle->disconnect(); | 341 handle->disconnect(); |
| 325 return; | 342 return; |
| 326 } | 343 } |
| 327 if (m_shouldDiscardReceivedData) | 344 if (m_shouldDiscardReceivedData) |
| 328 return; | 345 return; |
| 329 if (!appendToBuffer(data, len)) { | 346 if (!appendToBuffer(data, len)) { |
| 330 m_shouldDiscardReceivedData = true; | 347 m_shouldDiscardReceivedData = true; |
| 331 fail("Ran out of memory while receiving WebSocket data."); | 348 failAsError("Ran out of memory while receiving WebSocket data."); |
| 332 return; | 349 return; |
| 333 } | 350 } |
| 334 while (!m_suspended && m_client && !m_buffer.isEmpty()) | 351 while (!m_suspended && m_client && !m_buffer.isEmpty()) |
| 335 if (!processBuffer()) | 352 if (!processBuffer()) |
| 336 break; | 353 break; |
| 337 } | 354 } |
| 338 | 355 |
| 339 void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, si
ze_t bufferedAmount) | 356 void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, si
ze_t bufferedAmount) |
| 340 { | 357 { |
| 341 if (m_client) | 358 if (m_client) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 deref(); | 409 deref(); |
| 393 } | 410 } |
| 394 | 411 |
| 395 void MainThreadWebSocketChannel::didFail(int errorCode) | 412 void MainThreadWebSocketChannel::didFail(int errorCode) |
| 396 { | 413 { |
| 397 LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, e
rrorCode); | 414 LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, e
rrorCode); |
| 398 ASSERT(m_blobLoader); | 415 ASSERT(m_blobLoader); |
| 399 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); | 416 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); |
| 400 m_blobLoader.clear(); | 417 m_blobLoader.clear(); |
| 401 m_blobLoaderStatus = BlobLoaderFailed; | 418 m_blobLoaderStatus = BlobLoaderFailed; |
| 402 fail("Failed to load Blob: error code = " + String::number(errorCode)); // F
IXME: Generate human-friendly reason message. | 419 failAsError("Failed to load Blob: error code = " + String::number(errorCode)
); // FIXME: Generate human-friendly reason message. |
| 403 deref(); | 420 deref(); |
| 404 } | 421 } |
| 405 | 422 |
| 406 bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) | 423 bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) |
| 407 { | 424 { |
| 408 size_t newBufferSize = m_buffer.size() + len; | 425 size_t newBufferSize = m_buffer.size() + len; |
| 409 if (newBufferSize < m_buffer.size()) { | 426 if (newBufferSize < m_buffer.size()) { |
| 410 LOG(Network, "MainThreadWebSocketChannel %p appendToBuffer() Buffer over
flow (%lu bytes already in receive buffer and appending %lu bytes)", this, stati
c_cast<unsigned long>(m_buffer.size()), static_cast<unsigned long>(len)); | 427 LOG(Network, "MainThreadWebSocketChannel %p appendToBuffer() Buffer over
flow (%lu bytes already in receive buffer and appending %lu bytes)", this, stati
c_cast<unsigned long>(m_buffer.size()), static_cast<unsigned long>(len)); |
| 411 return false; | 428 return false; |
| 412 } | 429 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 LOG(Network, "MainThreadWebSocketChannel %p Connected", this); | 472 LOG(Network, "MainThreadWebSocketChannel %p Connected", this); |
| 456 skipBuffer(headerLength); | 473 skipBuffer(headerLength); |
| 457 m_client->didConnect(); | 474 m_client->didConnect(); |
| 458 LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m
_buffer", this, static_cast<unsigned long>(m_buffer.size())); | 475 LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m
_buffer", this, static_cast<unsigned long>(m_buffer.size())); |
| 459 return !m_buffer.isEmpty(); | 476 return !m_buffer.isEmpty(); |
| 460 } | 477 } |
| 461 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); | 478 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); |
| 462 LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); | 479 LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); |
| 463 skipBuffer(headerLength); | 480 skipBuffer(headerLength); |
| 464 m_shouldDiscardReceivedData = true; | 481 m_shouldDiscardReceivedData = true; |
| 465 fail(m_handshake->failureReason()); | 482 failAsError(m_handshake->failureReason()); |
| 466 return false; | 483 return false; |
| 467 } | 484 } |
| 468 if (m_handshake->mode() != WebSocketHandshake::Connected) | 485 if (m_handshake->mode() != WebSocketHandshake::Connected) |
| 469 return false; | 486 return false; |
| 470 | 487 |
| 471 return processFrame(); | 488 return processFrame(); |
| 472 } | 489 } |
| 473 | 490 |
| 474 void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann
el>* timer) | 491 void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann
el>* timer) |
| 475 { | 492 { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 { | 536 { |
| 520 ASSERT(!m_buffer.isEmpty()); | 537 ASSERT(!m_buffer.isEmpty()); |
| 521 | 538 |
| 522 WebSocketFrame frame; | 539 WebSocketFrame frame; |
| 523 const char* frameEnd; | 540 const char* frameEnd; |
| 524 String errorString; | 541 String errorString; |
| 525 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffe
r.data(), m_buffer.size(), frame, frameEnd, errorString); | 542 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffe
r.data(), m_buffer.size(), frame, frameEnd, errorString); |
| 526 if (result == WebSocketFrame::FrameIncomplete) | 543 if (result == WebSocketFrame::FrameIncomplete) |
| 527 return false; | 544 return false; |
| 528 if (result == WebSocketFrame::FrameError) { | 545 if (result == WebSocketFrame::FrameError) { |
| 529 fail(errorString); | 546 failAsError(errorString); |
| 530 return false; | 547 return false; |
| 531 } | 548 } |
| 532 | 549 |
| 533 ASSERT(m_buffer.data() < frameEnd); | 550 ASSERT(m_buffer.data() < frameEnd); |
| 534 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); | 551 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); |
| 535 | 552 |
| 536 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); | 553 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); |
| 537 if (!inflateResult->succeeded()) { | 554 if (!inflateResult->succeeded()) { |
| 538 fail(inflateResult->failureReason()); | 555 failAsError(inflateResult->failureReason()); |
| 539 return false; | 556 return false; |
| 540 } | 557 } |
| 541 if (!m_perMessageDeflate.inflate(frame)) { | 558 if (!m_perMessageDeflate.inflate(frame)) { |
| 542 fail(m_perMessageDeflate.failureReason()); | 559 failAsError(m_perMessageDeflate.failureReason()); |
| 543 return false; | 560 return false; |
| 544 } | 561 } |
| 545 | 562 |
| 546 // Validate the frame data. | 563 // Validate the frame data. |
| 547 if (WebSocketFrame::isReservedOpCode(frame.opCode)) { | 564 if (WebSocketFrame::isReservedOpCode(frame.opCode)) { |
| 548 fail("Unrecognized frame opcode: " + String::number(frame.opCode)); | 565 failAsError("Unrecognized frame opcode: " + String::number(frame.opCode)
); |
| 549 return false; | 566 return false; |
| 550 } | 567 } |
| 551 | 568 |
| 552 if (frame.compress || frame.reserved2 || frame.reserved3) { | 569 if (frame.compress || frame.reserved2 || frame.reserved3) { |
| 553 fail("One or more reserved bits are on: reserved1 = " + String::number(f
rame.compress) + ", reserved2 = " + String::number(frame.reserved2) + ", reserve
d3 = " + String::number(frame.reserved3)); | 570 failAsError("One or more reserved bits are on: reserved1 = " + String::n
umber(frame.compress) + ", reserved2 = " + String::number(frame.reserved2) + ",
reserved3 = " + String::number(frame.reserved3)); |
| 554 return false; | 571 return false; |
| 555 } | 572 } |
| 556 | 573 |
| 557 if (frame.masked) { | 574 if (frame.masked) { |
| 558 fail("A server must not mask any frames that it sends to the client."); | 575 failAsError("A server must not mask any frames that it sends to the clie
nt."); |
| 559 return false; | 576 return false; |
| 560 } | 577 } |
| 561 | 578 |
| 562 // All control frames must not be fragmented. | 579 // All control frames must not be fragmented. |
| 563 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { | 580 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { |
| 564 fail("Received fragmented control frame: opcode = " + String::number(fra
me.opCode)); | 581 failAsError("Received fragmented control frame: opcode = " + String::num
ber(frame.opCode)); |
| 565 return false; | 582 return false; |
| 566 } | 583 } |
| 567 | 584 |
| 568 // All control frames must have a payload of 125 bytes or less, which means
the frame must not contain | 585 // All control frames must have a payload of 125 bytes or less, which means
the frame must not contain |
| 569 // the "extended payload length" field. | 586 // the "extended payload length" field. |
| 570 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsEx
tendedLengthField(frame.payloadLength)) { | 587 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsEx
tendedLengthField(frame.payloadLength)) { |
| 571 fail("Received control frame having too long payload: " + String::number
(frame.payloadLength) + " bytes"); | 588 failAsError("Received control frame having too long payload: " + String:
:number(frame.payloadLength) + " bytes"); |
| 572 return false; | 589 return false; |
| 573 } | 590 } |
| 574 | 591 |
| 575 // A new data frame is received before the previous continuous frame finishe
s. | 592 // A new data frame is received before the previous continuous frame finishe
s. |
| 576 // Note that control frames are allowed to come in the middle of continuous
frames. | 593 // Note that control frames are allowed to come in the middle of continuous
frames. |
| 577 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuati
on && !WebSocketFrame::isControlOpCode(frame.opCode)) { | 594 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuati
on && !WebSocketFrame::isControlOpCode(frame.opCode)) { |
| 578 fail("Received new data frame but previous continuous frame is unfinishe
d."); | 595 failAsError("Received new data frame but previous continuous frame is un
finished."); |
| 579 return false; | 596 return false; |
| 580 } | 597 } |
| 581 | 598 |
| 582 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier,
frame); | 599 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier,
frame); |
| 583 | 600 |
| 584 switch (frame.opCode) { | 601 switch (frame.opCode) { |
| 585 case WebSocketFrame::OpCodeContinuation: | 602 case WebSocketFrame::OpCodeContinuation: |
| 586 // An unexpected continuation frame is received without any leading fram
e. | 603 // An unexpected continuation frame is received without any leading fram
e. |
| 587 if (!m_hasContinuousFrame) { | 604 if (!m_hasContinuousFrame) { |
| 588 fail("Received unexpected continuation frame."); | 605 failAsError("Received unexpected continuation frame."); |
| 589 return false; | 606 return false; |
| 590 } | 607 } |
| 591 m_continuousFrameData.append(frame.payload, frame.payloadLength); | 608 m_continuousFrameData.append(frame.payload, frame.payloadLength); |
| 592 skipBuffer(frameEnd - m_buffer.data()); | 609 skipBuffer(frameEnd - m_buffer.data()); |
| 593 if (frame.final) { | 610 if (frame.final) { |
| 594 // onmessage handler may eventually call the other methods of this c
hannel, | 611 // onmessage handler may eventually call the other methods of this c
hannel, |
| 595 // so we should pretend that we have finished to read this frame and | 612 // so we should pretend that we have finished to read this frame and |
| 596 // make sure that the member variables are in a consistent state bef
ore | 613 // make sure that the member variables are in a consistent state bef
ore |
| 597 // the handler is invoked. | 614 // the handler is invoked. |
| 598 // Vector<char>::swap() is used here to clear m_continuousFrameData. | 615 // Vector<char>::swap() is used here to clear m_continuousFrameData. |
| 599 OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char
>); | 616 OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char
>); |
| 600 m_continuousFrameData.swap(*continuousFrameData); | 617 m_continuousFrameData.swap(*continuousFrameData); |
| 601 m_hasContinuousFrame = false; | 618 m_hasContinuousFrame = false; |
| 602 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { | 619 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { |
| 603 String message; | 620 String message; |
| 604 if (continuousFrameData->size()) | 621 if (continuousFrameData->size()) |
| 605 message = String::fromUTF8(continuousFrameData->data(), cont
inuousFrameData->size()); | 622 message = String::fromUTF8(continuousFrameData->data(), cont
inuousFrameData->size()); |
| 606 else | 623 else |
| 607 message = ""; | 624 message = ""; |
| 608 if (message.isNull()) | 625 if (message.isNull()) |
| 609 fail("Could not decode a text frame as UTF-8."); | 626 failAsError("Could not decode a text frame as UTF-8."); |
| 610 else | 627 else |
| 611 m_client->didReceiveMessage(message); | 628 m_client->didReceiveMessage(message); |
| 612 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) | 629 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) |
| 613 m_client->didReceiveBinaryData(continuousFrameData.release()); | 630 m_client->didReceiveBinaryData(continuousFrameData.release()); |
| 614 } | 631 } |
| 615 break; | 632 break; |
| 616 | 633 |
| 617 case WebSocketFrame::OpCodeText: | 634 case WebSocketFrame::OpCodeText: |
| 618 if (frame.final) { | 635 if (frame.final) { |
| 619 String message; | 636 String message; |
| 620 if (frame.payloadLength) | 637 if (frame.payloadLength) |
| 621 message = String::fromUTF8(frame.payload, frame.payloadLength); | 638 message = String::fromUTF8(frame.payload, frame.payloadLength); |
| 622 else | 639 else |
| 623 message = ""; | 640 message = ""; |
| 624 skipBuffer(frameEnd - m_buffer.data()); | 641 skipBuffer(frameEnd - m_buffer.data()); |
| 625 if (message.isNull()) | 642 if (message.isNull()) |
| 626 fail("Could not decode a text frame as UTF-8."); | 643 failAsError("Could not decode a text frame as UTF-8."); |
| 627 else | 644 else |
| 628 m_client->didReceiveMessage(message); | 645 m_client->didReceiveMessage(message); |
| 629 } else { | 646 } else { |
| 630 m_hasContinuousFrame = true; | 647 m_hasContinuousFrame = true; |
| 631 m_continuousFrameOpCode = WebSocketFrame::OpCodeText; | 648 m_continuousFrameOpCode = WebSocketFrame::OpCodeText; |
| 632 ASSERT(m_continuousFrameData.isEmpty()); | 649 ASSERT(m_continuousFrameData.isEmpty()); |
| 633 m_continuousFrameData.append(frame.payload, frame.payloadLength); | 650 m_continuousFrameData.append(frame.payload, frame.payloadLength); |
| 634 skipBuffer(frameEnd - m_buffer.data()); | 651 skipBuffer(frameEnd - m_buffer.data()); |
| 635 } | 652 } |
| 636 break; | 653 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 648 m_continuousFrameData.append(frame.payload, frame.payloadLength); | 665 m_continuousFrameData.append(frame.payload, frame.payloadLength); |
| 649 skipBuffer(frameEnd - m_buffer.data()); | 666 skipBuffer(frameEnd - m_buffer.data()); |
| 650 } | 667 } |
| 651 break; | 668 break; |
| 652 | 669 |
| 653 case WebSocketFrame::OpCodeClose: | 670 case WebSocketFrame::OpCodeClose: |
| 654 if (!frame.payloadLength) | 671 if (!frame.payloadLength) |
| 655 m_closeEventCode = CloseEventCodeNoStatusRcvd; | 672 m_closeEventCode = CloseEventCodeNoStatusRcvd; |
| 656 else if (frame.payloadLength == 1) { | 673 else if (frame.payloadLength == 1) { |
| 657 m_closeEventCode = CloseEventCodeAbnormalClosure; | 674 m_closeEventCode = CloseEventCodeAbnormalClosure; |
| 658 fail("Received a broken close frame containing an invalid size body.
"); | 675 failAsError("Received a broken close frame containing an invalid siz
e body."); |
| 659 return false; | 676 return false; |
| 660 } else { | 677 } else { |
| 661 unsigned char highByte = static_cast<unsigned char>(frame.payload[0]
); | 678 unsigned char highByte = static_cast<unsigned char>(frame.payload[0]
); |
| 662 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1])
; | 679 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1])
; |
| 663 m_closeEventCode = highByte << 8 | lowByte; | 680 m_closeEventCode = highByte << 8 | lowByte; |
| 664 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCo
de == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHand
shake) { | 681 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCo
de == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHand
shake) { |
| 665 m_closeEventCode = CloseEventCodeAbnormalClosure; | 682 m_closeEventCode = CloseEventCodeAbnormalClosure; |
| 666 fail("Received a broken close frame containing a reserved status
code."); | 683 failAsError("Received a broken close frame containing a reserved
status code."); |
| 667 return false; | 684 return false; |
| 668 } | 685 } |
| 669 } | 686 } |
| 670 if (frame.payloadLength >= 3) | 687 if (frame.payloadLength >= 3) |
| 671 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.paylo
adLength - 2); | 688 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.paylo
adLength - 2); |
| 672 else | 689 else |
| 673 m_closeEventReason = ""; | 690 m_closeEventReason = ""; |
| 674 skipBuffer(frameEnd - m_buffer.data()); | 691 skipBuffer(frameEnd - m_buffer.data()); |
| 675 m_receivedClosingHandshake = true; | 692 m_receivedClosingHandshake = true; |
| 676 startClosingHandshake(m_closeEventCode, m_closeEventReason); | 693 startClosingHandshake(m_closeEventCode, m_closeEventReason); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 void MainThreadWebSocketChannel::processOutgoingFrameQueue() | 754 void MainThreadWebSocketChannel::processOutgoingFrameQueue() |
| 738 { | 755 { |
| 739 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) | 756 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) |
| 740 return; | 757 return; |
| 741 | 758 |
| 742 while (!m_outgoingFrameQueue.isEmpty()) { | 759 while (!m_outgoingFrameQueue.isEmpty()) { |
| 743 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); | 760 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); |
| 744 switch (frame->frameType) { | 761 switch (frame->frameType) { |
| 745 case QueuedFrameTypeString: { | 762 case QueuedFrameTypeString: { |
| 746 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->strin
gData.length())) | 763 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->strin
gData.length())) |
| 747 fail("Failed to send WebSocket frame."); | 764 failAsError("Failed to send WebSocket frame."); |
| 748 break; | 765 break; |
| 749 } | 766 } |
| 750 | 767 |
| 751 case QueuedFrameTypeVector: | 768 case QueuedFrameTypeVector: |
| 752 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vecto
rData.size())) | 769 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vecto
rData.size())) |
| 753 fail("Failed to send WebSocket frame."); | 770 failAsError("Failed to send WebSocket frame."); |
| 754 break; | 771 break; |
| 755 | 772 |
| 756 case QueuedFrameTypeBlob: { | 773 case QueuedFrameTypeBlob: { |
| 757 switch (m_blobLoaderStatus) { | 774 switch (m_blobLoaderStatus) { |
| 758 case BlobLoaderNotStarted: | 775 case BlobLoaderNotStarted: |
| 759 ref(); // Will be derefed after didFinishLoading() or didFail(). | 776 ref(); // Will be derefed after didFinishLoading() or didFail(). |
| 760 ASSERT(!m_blobLoader); | 777 ASSERT(!m_blobLoader); |
| 761 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::R
eadAsArrayBuffer, this)); | 778 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::R
eadAsArrayBuffer, this)); |
| 762 m_blobLoaderStatus = BlobLoaderStarted; | 779 m_blobLoaderStatus = BlobLoaderStarted; |
| 763 m_blobLoader->start(m_document, frame->blobData.get()); | 780 m_blobLoader->start(m_document, frame->blobData.get()); |
| 764 m_outgoingFrameQueue.prepend(frame.release()); | 781 m_outgoingFrameQueue.prepend(frame.release()); |
| 765 return; | 782 return; |
| 766 | 783 |
| 767 case BlobLoaderStarted: | 784 case BlobLoaderStarted: |
| 768 case BlobLoaderFailed: | 785 case BlobLoaderFailed: |
| 769 m_outgoingFrameQueue.prepend(frame.release()); | 786 m_outgoingFrameQueue.prepend(frame.release()); |
| 770 return; | 787 return; |
| 771 | 788 |
| 772 case BlobLoaderFinished: { | 789 case BlobLoaderFinished: { |
| 773 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); | 790 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); |
| 774 m_blobLoader.clear(); | 791 m_blobLoader.clear(); |
| 775 m_blobLoaderStatus = BlobLoaderNotStarted; | 792 m_blobLoaderStatus = BlobLoaderNotStarted; |
| 776 if (!sendFrame(frame->opCode, static_cast<const char*>(result->d
ata()), result->byteLength())) | 793 if (!sendFrame(frame->opCode, static_cast<const char*>(result->d
ata()), result->byteLength())) |
| 777 fail("Failed to send WebSocket frame."); | 794 failAsError("Failed to send WebSocket frame."); |
| 778 break; | 795 break; |
| 779 } | 796 } |
| 780 } | 797 } |
| 781 break; | 798 break; |
| 782 } | 799 } |
| 783 | 800 |
| 784 default: | 801 default: |
| 785 ASSERT_NOT_REACHED(); | 802 ASSERT_NOT_REACHED(); |
| 786 break; | 803 break; |
| 787 } | 804 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 807 bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const
char* data, size_t dataLength) | 824 bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const
char* data, size_t dataLength) |
| 808 { | 825 { |
| 809 ASSERT(m_handle); | 826 ASSERT(m_handle); |
| 810 ASSERT(!m_suspended); | 827 ASSERT(!m_suspended); |
| 811 | 828 |
| 812 WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSo
cketFrame::Masked); | 829 WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSo
cketFrame::Masked); |
| 813 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, fr
ame); | 830 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, fr
ame); |
| 814 | 831 |
| 815 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); | 832 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); |
| 816 if (!deflateResult->succeeded()) { | 833 if (!deflateResult->succeeded()) { |
| 817 fail(deflateResult->failureReason()); | 834 failAsError(deflateResult->failureReason()); |
| 818 return false; | 835 return false; |
| 819 } | 836 } |
| 820 | 837 |
| 821 if (!m_perMessageDeflate.deflate(frame)) { | 838 if (!m_perMessageDeflate.deflate(frame)) { |
| 822 fail(m_perMessageDeflate.failureReason()); | 839 failAsError(m_perMessageDeflate.failureReason()); |
| 823 return false; | 840 return false; |
| 824 } | 841 } |
| 825 | 842 |
| 826 Vector<char> frameData; | 843 Vector<char> frameData; |
| 827 frame.makeFrameData(frameData); | 844 frame.makeFrameData(frameData); |
| 828 | 845 |
| 829 m_perMessageDeflate.resetDeflateBuffer(); | 846 m_perMessageDeflate.resetDeflateBuffer(); |
| 830 return m_handle->send(frameData.data(), frameData.size()); | 847 return m_handle->send(frameData.data(), frameData.size()); |
| 831 } | 848 } |
| 832 | 849 |
| 833 } // namespace WebCore | 850 } // namespace WebCore |
| OLD | NEW |