OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 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 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 | 221 |
222 const char* WebSocket::subprotocolSeperator() | 222 const char* WebSocket::subprotocolSeperator() |
223 { | 223 { |
224 return ", "; | 224 return ", "; |
225 } | 225 } |
226 | 226 |
227 WebSocket::WebSocket(ExecutionContext* context) | 227 WebSocket::WebSocket(ExecutionContext* context) |
228 : ActiveDOMObject(context) | 228 : ActiveDOMObject(context) |
229 , m_state(CONNECTING) | 229 , m_state(CONNECTING) |
230 , m_bufferedAmount(0) | 230 , m_bufferedAmount(0) |
| 231 , m_consumedBufferedAmount(0) |
231 , m_bufferedAmountAfterClose(0) | 232 , m_bufferedAmountAfterClose(0) |
232 , m_binaryType(BinaryTypeBlob) | 233 , m_binaryType(BinaryTypeBlob) |
233 , m_subprotocol("") | 234 , m_subprotocol("") |
234 , m_extensions("") | 235 , m_extensions("") |
235 , m_eventQueue(EventQueue::create(this)) | 236 , m_eventQueue(EventQueue::create(this)) |
| 237 , m_bufferedAmountConsumeTimer(this, &WebSocket::reflectBufferedAmountConsum
ption) |
236 { | 238 { |
237 ScriptWrappable::init(this); | 239 ScriptWrappable::init(this); |
238 } | 240 } |
239 | 241 |
240 WebSocket::~WebSocket() | 242 WebSocket::~WebSocket() |
241 { | 243 { |
242 ASSERT(!m_channel); | 244 ASSERT(!m_channel); |
243 } | 245 } |
244 | 246 |
245 void WebSocket::logError(const String& message) | 247 void WebSocket::logError(const String& message) |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 } | 368 } |
367 | 369 |
368 void WebSocket::updateBufferedAmountAfterClose(unsigned long payloadSize) | 370 void WebSocket::updateBufferedAmountAfterClose(unsigned long payloadSize) |
369 { | 371 { |
370 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, payload
Size); | 372 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, payload
Size); |
371 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, getFram
ingOverhead(payloadSize)); | 373 m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, getFram
ingOverhead(payloadSize)); |
372 | 374 |
373 logError("WebSocket is already in CLOSING or CLOSED state."); | 375 logError("WebSocket is already in CLOSING or CLOSED state."); |
374 } | 376 } |
375 | 377 |
| 378 void WebSocket::reflectBufferedAmountConsumption(Timer<WebSocket>*) |
| 379 { |
| 380 ASSERT(m_bufferedAmount >= m_consumedBufferedAmount); |
| 381 WTF_LOG(Network, "WebSocket %p reflectBufferedAmountConsumption() %lu => %lu
", this, m_bufferedAmount, m_bufferedAmount - m_consumedBufferedAmount); |
| 382 |
| 383 m_bufferedAmount -= m_consumedBufferedAmount; |
| 384 m_consumedBufferedAmount = 0; |
| 385 } |
| 386 |
376 void WebSocket::releaseChannel() | 387 void WebSocket::releaseChannel() |
377 { | 388 { |
378 ASSERT(m_channel); | 389 ASSERT(m_channel); |
379 m_channel->disconnect(); | 390 m_channel->disconnect(); |
380 m_channel = nullptr; | 391 m_channel = nullptr; |
381 } | 392 } |
382 | 393 |
383 void WebSocket::send(const String& message, ExceptionState& exceptionState) | 394 void WebSocket::send(const String& message, ExceptionState& exceptionState) |
384 { | 395 { |
385 WTF_LOG(Network, "WebSocket %p send() Sending String '%s'", this, message.ut
f8().data()); | 396 WTF_LOG(Network, "WebSocket %p send() Sending String '%s'", this, message.ut
f8().data()); |
386 if (m_state == CONNECTING) { | 397 if (m_state == CONNECTING) { |
387 setInvalidStateErrorForSendMethod(exceptionState); | 398 setInvalidStateErrorForSendMethod(exceptionState); |
388 return; | 399 return; |
389 } | 400 } |
390 // No exception is raised if the connection was once established but has sub
sequently been closed. | 401 // No exception is raised if the connection was once established but has sub
sequently been closed. |
391 if (m_state == CLOSING || m_state == CLOSED) { | 402 if (m_state == CLOSING || m_state == CLOSED) { |
392 updateBufferedAmountAfterClose(message.utf8().length()); | 403 updateBufferedAmountAfterClose(message.utf8().length()); |
393 return; | 404 return; |
394 } | 405 } |
395 ASSERT(m_channel); | 406 ASSERT(m_channel); |
| 407 m_bufferedAmount += message.utf8().length(); |
396 handleSendResult(m_channel->send(message), exceptionState, WebSocketSendType
String); | 408 handleSendResult(m_channel->send(message), exceptionState, WebSocketSendType
String); |
397 } | 409 } |
398 | 410 |
399 void WebSocket::send(ArrayBuffer* binaryData, ExceptionState& exceptionState) | 411 void WebSocket::send(ArrayBuffer* binaryData, ExceptionState& exceptionState) |
400 { | 412 { |
401 WTF_LOG(Network, "WebSocket %p send() Sending ArrayBuffer %p", this, binaryD
ata); | 413 WTF_LOG(Network, "WebSocket %p send() Sending ArrayBuffer %p", this, binaryD
ata); |
402 ASSERT(binaryData); | 414 ASSERT(binaryData); |
403 if (m_state == CONNECTING) { | 415 if (m_state == CONNECTING) { |
404 setInvalidStateErrorForSendMethod(exceptionState); | 416 setInvalidStateErrorForSendMethod(exceptionState); |
405 return; | 417 return; |
406 } | 418 } |
407 if (m_state == CLOSING || m_state == CLOSED) { | 419 if (m_state == CLOSING || m_state == CLOSED) { |
408 updateBufferedAmountAfterClose(binaryData->byteLength()); | 420 updateBufferedAmountAfterClose(binaryData->byteLength()); |
409 return; | 421 return; |
410 } | 422 } |
411 ASSERT(m_channel); | 423 ASSERT(m_channel); |
| 424 m_bufferedAmount += binaryData->byteLength(); |
412 handleSendResult(m_channel->send(*binaryData, 0, binaryData->byteLength()),
exceptionState, WebSocketSendTypeArrayBuffer); | 425 handleSendResult(m_channel->send(*binaryData, 0, binaryData->byteLength()),
exceptionState, WebSocketSendTypeArrayBuffer); |
413 } | 426 } |
414 | 427 |
415 void WebSocket::send(ArrayBufferView* arrayBufferView, ExceptionState& exception
State) | 428 void WebSocket::send(ArrayBufferView* arrayBufferView, ExceptionState& exception
State) |
416 { | 429 { |
417 WTF_LOG(Network, "WebSocket %p send() Sending ArrayBufferView %p", this, arr
ayBufferView); | 430 WTF_LOG(Network, "WebSocket %p send() Sending ArrayBufferView %p", this, arr
ayBufferView); |
418 ASSERT(arrayBufferView); | 431 ASSERT(arrayBufferView); |
419 if (m_state == CONNECTING) { | 432 if (m_state == CONNECTING) { |
420 setInvalidStateErrorForSendMethod(exceptionState); | 433 setInvalidStateErrorForSendMethod(exceptionState); |
421 return; | 434 return; |
422 } | 435 } |
423 if (m_state == CLOSING || m_state == CLOSED) { | 436 if (m_state == CLOSING || m_state == CLOSED) { |
424 updateBufferedAmountAfterClose(arrayBufferView->byteLength()); | 437 updateBufferedAmountAfterClose(arrayBufferView->byteLength()); |
425 return; | 438 return; |
426 } | 439 } |
427 ASSERT(m_channel); | 440 ASSERT(m_channel); |
| 441 m_bufferedAmount += arrayBufferView->byteLength(); |
428 RefPtr<ArrayBuffer> arrayBuffer(arrayBufferView->buffer()); | 442 RefPtr<ArrayBuffer> arrayBuffer(arrayBufferView->buffer()); |
429 handleSendResult(m_channel->send(*arrayBuffer, arrayBufferView->byteOffset()
, arrayBufferView->byteLength()), exceptionState, WebSocketSendTypeArrayBufferVi
ew); | 443 handleSendResult(m_channel->send(*arrayBuffer, arrayBufferView->byteOffset()
, arrayBufferView->byteLength()), exceptionState, WebSocketSendTypeArrayBufferVi
ew); |
430 } | 444 } |
431 | 445 |
432 void WebSocket::send(Blob* binaryData, ExceptionState& exceptionState) | 446 void WebSocket::send(Blob* binaryData, ExceptionState& exceptionState) |
433 { | 447 { |
434 WTF_LOG(Network, "WebSocket %p send() Sending Blob '%s'", this, binaryData->
uuid().utf8().data()); | 448 WTF_LOG(Network, "WebSocket %p send() Sending Blob '%s'", this, binaryData->
uuid().utf8().data()); |
435 ASSERT(binaryData); | 449 ASSERT(binaryData); |
436 if (m_state == CONNECTING) { | 450 if (m_state == CONNECTING) { |
437 setInvalidStateErrorForSendMethod(exceptionState); | 451 setInvalidStateErrorForSendMethod(exceptionState); |
438 return; | 452 return; |
439 } | 453 } |
440 if (m_state == CLOSING || m_state == CLOSED) { | 454 if (m_state == CLOSING || m_state == CLOSED) { |
441 updateBufferedAmountAfterClose(static_cast<unsigned long>(binaryData->si
ze())); | 455 updateBufferedAmountAfterClose(static_cast<unsigned long>(binaryData->si
ze())); |
442 return; | 456 return; |
443 } | 457 } |
| 458 m_bufferedAmount += binaryData->size(); |
444 ASSERT(m_channel); | 459 ASSERT(m_channel); |
445 handleSendResult(m_channel->send(binaryData->blobDataHandle()), exceptionSta
te, WebSocketSendTypeBlob); | 460 handleSendResult(m_channel->send(binaryData->blobDataHandle()), exceptionSta
te, WebSocketSendTypeBlob); |
446 } | 461 } |
447 | 462 |
448 void WebSocket::close(unsigned short code, const String& reason, ExceptionState&
exceptionState) | 463 void WebSocket::close(unsigned short code, const String& reason, ExceptionState&
exceptionState) |
449 { | 464 { |
450 closeInternal(code, reason, exceptionState); | 465 closeInternal(code, reason, exceptionState); |
451 } | 466 } |
452 | 467 |
453 void WebSocket::close(ExceptionState& exceptionState) | 468 void WebSocket::close(ExceptionState& exceptionState) |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 } | 648 } |
634 } | 649 } |
635 | 650 |
636 void WebSocket::didReceiveMessageError() | 651 void WebSocket::didReceiveMessageError() |
637 { | 652 { |
638 WTF_LOG(Network, "WebSocket %p didReceiveMessageError()", this); | 653 WTF_LOG(Network, "WebSocket %p didReceiveMessageError()", this); |
639 m_state = CLOSED; | 654 m_state = CLOSED; |
640 m_eventQueue->dispatch(Event::create(EventTypeNames::error)); | 655 m_eventQueue->dispatch(Event::create(EventTypeNames::error)); |
641 } | 656 } |
642 | 657 |
643 void WebSocket::didUpdateBufferedAmount(unsigned long bufferedAmount) | 658 void WebSocket::didConsumeBufferedAmount(unsigned long consumed) |
644 { | 659 { |
645 WTF_LOG(Network, "WebSocket %p didUpdateBufferedAmount() New bufferedAmount
is %lu", this, bufferedAmount); | 660 ASSERT(m_bufferedAmount >= consumed); |
| 661 WTF_LOG(Network, "WebSocket %p didConsumeBufferedAmount(%lu)", this, consume
d); |
646 if (m_state == CLOSED) | 662 if (m_state == CLOSED) |
647 return; | 663 return; |
648 m_bufferedAmount = bufferedAmount; | 664 m_consumedBufferedAmount += consumed; |
| 665 if (!m_bufferedAmountConsumeTimer.isActive()) |
| 666 m_bufferedAmountConsumeTimer.startOneShot(0, FROM_HERE); |
649 } | 667 } |
650 | 668 |
651 void WebSocket::didStartClosingHandshake() | 669 void WebSocket::didStartClosingHandshake() |
652 { | 670 { |
653 WTF_LOG(Network, "WebSocket %p didStartClosingHandshake()", this); | 671 WTF_LOG(Network, "WebSocket %p didStartClosingHandshake()", this); |
654 m_state = CLOSING; | 672 m_state = CLOSING; |
655 } | 673 } |
656 | 674 |
657 void WebSocket::didClose(unsigned long unhandledBufferedAmount, ClosingHandshake
CompletionStatus closingHandshakeCompletion, unsigned short code, const String&
reason) | 675 void WebSocket::didClose(ClosingHandshakeCompletionStatus closingHandshakeComple
tion, unsigned short code, const String& reason) |
658 { | 676 { |
659 WTF_LOG(Network, "WebSocket %p didClose()", this); | 677 WTF_LOG(Network, "WebSocket %p didClose()", this); |
660 if (!m_channel) | 678 if (!m_channel) |
661 return; | 679 return; |
662 bool wasClean = m_state == CLOSING && !unhandledBufferedAmount && closingHan
dshakeCompletion == ClosingHandshakeComplete && code != WebSocketChannel::CloseE
ventCodeAbnormalClosure; | 680 bool hasAllDataConsumed = m_bufferedAmount == m_consumedBufferedAmount; |
| 681 bool wasClean = m_state == CLOSING && hasAllDataConsumed && closingHandshake
Completion == ClosingHandshakeComplete && code != WebSocketChannel::CloseEventCo
deAbnormalClosure; |
| 682 m_state = CLOSED; |
663 | 683 |
664 m_state = CLOSED; | |
665 m_bufferedAmount = unhandledBufferedAmount; | |
666 m_eventQueue->dispatch(CloseEvent::create(wasClean, code, reason)); | 684 m_eventQueue->dispatch(CloseEvent::create(wasClean, code, reason)); |
667 releaseChannel(); | 685 releaseChannel(); |
668 } | 686 } |
669 | 687 |
670 size_t WebSocket::getFramingOverhead(size_t payloadSize) | 688 size_t WebSocket::getFramingOverhead(size_t payloadSize) |
671 { | 689 { |
672 static const size_t hybiBaseFramingOverhead = 2; // Every frame has at least
two-byte header. | 690 static const size_t hybiBaseFramingOverhead = 2; // Every frame has at least
two-byte header. |
673 static const size_t hybiMaskingKeyLength = 4; // Every frame from client mus
t have masking key. | 691 static const size_t hybiMaskingKeyLength = 4; // Every frame from client mus
t have masking key. |
674 static const size_t minimumPayloadSizeWithTwoByteExtendedPayloadLength = 126
; | 692 static const size_t minimumPayloadSizeWithTwoByteExtendedPayloadLength = 126
; |
675 static const size_t minimumPayloadSizeWithEightByteExtendedPayloadLength = 0
x10000; | 693 static const size_t minimumPayloadSizeWithEightByteExtendedPayloadLength = 0
x10000; |
676 size_t overhead = hybiBaseFramingOverhead + hybiMaskingKeyLength; | 694 size_t overhead = hybiBaseFramingOverhead + hybiMaskingKeyLength; |
677 if (payloadSize >= minimumPayloadSizeWithEightByteExtendedPayloadLength) | 695 if (payloadSize >= minimumPayloadSizeWithEightByteExtendedPayloadLength) |
678 overhead += 8; | 696 overhead += 8; |
679 else if (payloadSize >= minimumPayloadSizeWithTwoByteExtendedPayloadLength) | 697 else if (payloadSize >= minimumPayloadSizeWithTwoByteExtendedPayloadLength) |
680 overhead += 2; | 698 overhead += 2; |
681 return overhead; | 699 return overhead; |
682 } | 700 } |
683 | 701 |
684 void WebSocket::trace(Visitor* visitor) | 702 void WebSocket::trace(Visitor* visitor) |
685 { | 703 { |
686 visitor->trace(m_channel); | 704 visitor->trace(m_channel); |
687 visitor->trace(m_eventQueue); | 705 visitor->trace(m_eventQueue); |
688 EventTargetWithInlineData::trace(visitor); | 706 EventTargetWithInlineData::trace(visitor); |
689 } | 707 } |
690 | 708 |
691 } // namespace WebCore | 709 } // namespace WebCore |
OLD | NEW |