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 |