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