Changeset 87464 in webkit
- Timestamp:
- May 26, 2011 8:24:02 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 21 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r87461 r87464 1 2011-05-26 Yuta Kitamura <yutak@chromium.org> 2 3 Reviewed by Kent Tamura. 4 5 WebSocket closing handshake 6 https://bugs.webkit.org/show_bug.cgi?id=35721 7 8 * http/tests/websocket/tests/client-close-expected.txt: Added. 9 * http/tests/websocket/tests/client-close.html: Added. Test client-initiated close. 10 * http/tests/websocket/tests/client-close_wsh.py: Added. 11 * http/tests/websocket/tests/close-before-open-expected.txt: Add a new console message. 12 * http/tests/websocket/tests/close-event-expected.txt: 13 * http/tests/websocket/tests/close-event.html: Test if closeEvent.wasClean is true. 14 * http/tests/websocket/tests/close-unref-websocket-expected.txt: Add a new console message. 15 * http/tests/websocket/tests/frame-length-longer-than-buffer_wsh.py: 16 We need to stop pywebsocket from starting the closing handshake. Otherwise, pywebsocket 17 waits for a close frame to arrive and this test will time out. 18 * http/tests/websocket/tests/server-close-expected.txt: Added. 19 * http/tests/websocket/tests/server-close.html: Added. Test server-initiated close. 20 * http/tests/websocket/tests/server-close_wsh.py: Added. 21 * http/tests/websocket/tests/websocket-event-target-expected.txt: Add a new console message. 22 1 23 2011-05-26 MORITA Hajime <morrita@google.com> 2 24 -
trunk/LayoutTests/http/tests/websocket/tests/client-close-expected.txt
r87463 r87464 1 Test if Web Socket fires close event when WebSocket is opened and closed fore open event is received.1 WebSocket: Test client-initiated close. 2 2 3 3 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". 4 4 5 closed 5 Connected 6 Closed 7 PASS closeEvent.wasClean is true 6 8 PASS successfullyParsed is true 7 9 -
trunk/LayoutTests/http/tests/websocket/tests/client-close.html
r87463 r87464 9 9 <div id="console"></div> 10 10 <script type="text/javascript"> 11 description(" Make sure WebSocket fires CloseEvent when closed.");11 description("WebSocket: Test client-initiated close."); 12 12 13 13 window.jsTestIsAsync = true; 14 14 15 var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/simple"); 15 var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/client-close"); 16 var closeEvent; 16 17 17 18 ws.onopen = function() 18 19 { 19 debug("WebSocket is open"); 20 debug("Connected"); 21 ws.close(); 20 22 }; 21 23 22 24 ws.onmessage = function(messageEvent) 23 25 { 24 debug("Received: '" + messageEvent.data + "'");26 debug("Received: " + messageEvent.data); 25 27 }; 26 28 27 var closeEvent;28 var closeEventType;29 29 ws.onclose = function(event) 30 30 { 31 31 debug("Closed"); 32 32 closeEvent = event; 33 closeEventType = closeEvent.type; 34 shouldBe("closeEventType", '"close"') 35 shouldBeTrue("'wasClean' in closeEvent"); 36 shouldBeTrue("Object.getPrototypeOf(closeEvent) === CloseEvent.prototype"); 37 shouldBeTrue("Object.getPrototypeOf(closeEvent) !== Event.prototype"); 33 shouldBeTrue("closeEvent.wasClean"); 38 34 finishJSTest(); 39 35 }; -
trunk/LayoutTests/http/tests/websocket/tests/close-before-open-expected.txt
r87135 r87464 1 CONSOLE MESSAGE: line 0: WebSocket is closed before the connection is established. 1 2 Test if Web Socket fires close event when WebSocket is opened and closed fore open event is received. 2 3 -
trunk/LayoutTests/http/tests/websocket/tests/close-event-expected.txt
r86315 r87464 8 8 PASS closeEventType is "close" 9 9 PASS 'wasClean' in closeEvent is true 10 PASS closeEvent.wasClean is true 10 11 PASS Object.getPrototypeOf(closeEvent) === CloseEvent.prototype is true 11 12 PASS Object.getPrototypeOf(closeEvent) !== Event.prototype is true -
trunk/LayoutTests/http/tests/websocket/tests/close-event.html
r86315 r87464 34 34 shouldBe("closeEventType", '"close"') 35 35 shouldBeTrue("'wasClean' in closeEvent"); 36 shouldBeTrue("closeEvent.wasClean"); 36 37 shouldBeTrue("Object.getPrototypeOf(closeEvent) === CloseEvent.prototype"); 37 38 shouldBeTrue("Object.getPrototypeOf(closeEvent) !== Event.prototype"); -
trunk/LayoutTests/http/tests/websocket/tests/close-unref-websocket-expected.txt
r82088 r87464 1 CONSOLE MESSAGE: line 0: WebSocket is closed before the connection is established. 1 2 Test if Web Socket is closed while handshaking and unreferenced, it should fire close event at most once. 2 3 -
trunk/LayoutTests/http/tests/websocket/tests/frame-length-longer-than-buffer_wsh.py
r51829 r87464 1 1 def web_socket_do_extra_handshake(request): 2 pass2 pass 3 3 4 4 def web_socket_transfer_data(request): 5 msg = "\0hello\xff"6 msg += "\x80\x81\x01" # skip 1*128+1 bytes.7 msg += "\x01\xff"8 msg += "\0should be skipped\xff"9 request.connection.write(msg)10 print msg5 msg = "\0hello\xff" 6 msg += "\x80\x81\x01" # Skip 1*128+1 bytes. 7 msg += "\x01\xff" 8 msg += "\0should be skipped\xff" 9 request.connection.write(msg) 10 raise Exception("Abort the connection") # Prevents pywebsocket from starting closing handshake. -
trunk/LayoutTests/http/tests/websocket/tests/server-close-expected.txt
r87463 r87464 1 Test if Web Socket fires close event when WebSocket is opened and closed fore open event is received.1 WebSocket: Test server-initiated close. 2 2 3 3 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". 4 4 5 closed 5 Connected 6 Closed 7 PASS closeEvent.wasClean is true 6 8 PASS successfullyParsed is true 7 9 -
trunk/LayoutTests/http/tests/websocket/tests/server-close.html
r87463 r87464 9 9 <div id="console"></div> 10 10 <script type="text/javascript"> 11 description(" Make sure WebSocket fires CloseEvent when closed.");11 description("WebSocket: Test server-initiated close."); 12 12 13 13 window.jsTestIsAsync = true; 14 14 15 var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/simple"); 15 var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/server-close"); 16 var closeEvent; 16 17 17 18 ws.onopen = function() 18 19 { 19 debug(" WebSocket is open");20 debug("Connected"); 20 21 }; 21 22 22 23 ws.onmessage = function(messageEvent) 23 24 { 24 debug("Received: '" + messageEvent.data + "'");25 debug("Received: " + messageEvent.data); 25 26 }; 26 27 27 var closeEvent;28 var closeEventType;29 28 ws.onclose = function(event) 30 29 { 31 30 debug("Closed"); 32 31 closeEvent = event; 33 closeEventType = closeEvent.type; 34 shouldBe("closeEventType", '"close"') 35 shouldBeTrue("'wasClean' in closeEvent"); 36 shouldBeTrue("Object.getPrototypeOf(closeEvent) === CloseEvent.prototype"); 37 shouldBeTrue("Object.getPrototypeOf(closeEvent) !== Event.prototype"); 32 shouldBeTrue("closeEvent.wasClean"); 38 33 finishJSTest(); 39 34 }; -
trunk/LayoutTests/http/tests/websocket/tests/websocket-event-target-expected.txt
r53676 r87464 1 CONSOLE MESSAGE: line 0: WebSocket is closed before the connection is established. 1 2 Make sure WebSocket object acts as EventTarget. 2 3 -
trunk/Source/WebCore/ChangeLog
r87462 r87464 1 2011-05-26 Yuta Kitamura <yutak@chromium.org> 2 3 Reviewed by Kent Tamura. 4 5 WebSocket closing handshake 6 https://bugs.webkit.org/show_bug.cgi?id=35721 7 8 Implement WebSocket closing handshake based on Ian Hickson's 9 WebSocket protocol draft 76. 10 11 Tests: http/tests/websocket/tests/client-close.html 12 http/tests/websocket/tests/server-close.html 13 14 * platform/network/SocketStreamHandleBase.cpp: 15 (WebCore::SocketStreamHandleBase::send): 16 Do not send a message if we are in Closing state. 17 (WebCore::SocketStreamHandleBase::close): 18 Do not disconnect if we have pending data which have not been sent yet. 19 In this case, the actual disconnection will happen in sendPendingData(). 20 (WebCore::SocketStreamHandleBase::disconnect): 21 Renamed from close(). Disconnect the connection immediately. 22 (WebCore::SocketStreamHandleBase::sendPendingData): 23 * platform/network/SocketStreamHandleBase.h: 24 * websockets/ThreadableWebSocketChannelClientWrapper.cpp: 25 Add didStartClosingHandshake(). Add a function argument (ClosingHandshakeCompletionStatus) 26 to didClose(). 27 (WebCore::ThreadableWebSocketChannelClientWrapper::didStartClosingHandshake): 28 (WebCore::ThreadableWebSocketChannelClientWrapper::didClose): 29 (WebCore::ThreadableWebSocketChannelClientWrapper::didStartClosingHandshakeCallback): 30 (WebCore::ThreadableWebSocketChannelClientWrapper::didCloseCallback): 31 * websockets/ThreadableWebSocketChannelClientWrapper.h: 32 * websockets/WebSocket.cpp: 33 (WebCore::WebSocket::send): 34 (WebCore::WebSocket::close): 35 Fail if close() is attempted before the connection is established. 36 Otherwise, set the state to CLOSING and start the closing handshake. 37 (WebCore::WebSocket::bufferedAmount): 38 If the state is CLOSING, we need to consider buffered data in m_channel and sent after close(). 39 (WebCore::WebSocket::didConnect): 40 (WebCore::WebSocket::didReceiveMessage): 41 We need to invoke message event in CLOSING state as well as OPEN state. 42 (WebCore::WebSocket::didReceiveMessageError): 43 (WebCore::WebSocket::didStartClosingHandshake): 44 (WebCore::WebSocket::didClose): 45 * websockets/WebSocket.h: 46 * websockets/WebSocketChannel.cpp: 47 (WebCore::WebSocketChannel::WebSocketChannel): 48 (WebCore::WebSocketChannel::close): 49 Start the closing handshake. 50 (WebCore::WebSocketChannel::disconnect): 51 Disconnect the socket stream, instead of close. 52 (WebCore::WebSocketChannel::didClose): 53 (WebCore::WebSocketChannel::didReceiveData): Ditto. 54 (WebCore::WebSocketChannel::didFail): Ditto. 55 (WebCore::WebSocketChannel::processBuffer): 56 Ditto. 57 Handle 0xFF 0x00 byte sequence, and discard received data once the closing handshake has started. 58 (WebCore::WebSocketChannel::startClosingHandshake): 59 Send 0xFF 0x00 byte sequence. 60 (WebCore::WebSocketChannel::closingTimerFired): 61 Disconnect the socket stream if the closing handshake has timed out. 62 * websockets/WebSocketChannel.h: 63 m_closing is true if "the WebSocket closing handshake has started" (as stated in the protocol 64 specification). 65 * websockets/WebSocketChannelClient.h: 66 (WebCore::WebSocketChannelClient::didStartClosingHandshake): Added. 67 (WebCore::WebSocketChannelClient::didClose): Add closingHandshakeCompletion parameter. 68 * websockets/WorkerThreadableWebSocketChannel.cpp: 69 Add closingHandshakeCompletion parameter to didClose(), and add didStartClosingHandshake(). 70 (WebCore::WorkerThreadableWebSocketChannel::Peer::close): 71 (WebCore::workerContextDidStartClosingHandshake): 72 (WebCore::WorkerThreadableWebSocketChannel::Peer::didStartClosingHandshake): 73 (WebCore::workerContextDidClose): 74 (WebCore::WorkerThreadableWebSocketChannel::Peer::didClose): 75 * websockets/WorkerThreadableWebSocketChannel.h: 76 1 77 2011-05-26 David Levin <levin@chromium.org> 2 78 -
trunk/Source/WebCore/platform/network/SocketStreamHandleBase.cpp
r51934 r87464 53 53 bool SocketStreamHandleBase::send(const char* data, int length) 54 54 { 55 if (m_state == Connecting )55 if (m_state == Connecting || m_state == Closing) 56 56 return false; 57 57 if (!m_buffer.isEmpty()) { … … 79 79 void SocketStreamHandleBase::close() 80 80 { 81 if (m_state == Closed) 82 return; 83 m_state = Closing; 84 if (!m_buffer.isEmpty()) 85 return; 86 disconnect(); 87 } 88 89 void SocketStreamHandleBase::disconnect() 90 { 81 91 RefPtr<SocketStreamHandle> protect(static_cast<SocketStreamHandle*>(this)); // platformClose calls the client, which may make the handle get deallocated immediately. 82 92 … … 93 103 bool SocketStreamHandleBase::sendPendingData() 94 104 { 95 if (m_state != Open )105 if (m_state != Open && m_state != Closing) 96 106 return false; 97 if (m_buffer.isEmpty()) 98 return false; 107 if (m_buffer.isEmpty()) { 108 if (m_state == Open) 109 return false; 110 if (m_state == Closing) { 111 disconnect(); 112 return false; 113 } 114 } 99 115 int bytesWritten = platformSend(m_buffer.data(), m_buffer.size()); 100 116 if (bytesWritten <= 0) -
trunk/Source/WebCore/platform/network/SocketStreamHandleBase.h
r86732 r87464 49 49 50 50 bool send(const char* data, int length); 51 void close(); 51 void close(); // Disconnect after all data in buffer are sent. 52 void disconnect(); 52 53 int bufferedAmount() const { return m_buffer.size(); } 53 54 -
trunk/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.cpp
r86829 r87464 111 111 } 112 112 113 void ThreadableWebSocketChannelClientWrapper::did Close(unsigned long unhandledBufferedAmount)113 void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshake() 114 114 { 115 m_pendingTasks.append(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::didCloseCallback, AllowCrossThreadAccess(this), unhandledBufferedAmount)); 115 m_pendingTasks.append(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::didStartClosingHandshakeCallback, AllowCrossThreadAccess(this))); 116 if (!m_suspended) 117 processPendingTasks(); 118 } 119 120 void ThreadableWebSocketChannelClientWrapper::didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion) 121 { 122 m_pendingTasks.append(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::didCloseCallback, AllowCrossThreadAccess(this), unhandledBufferedAmount, closingHandshakeCompletion)); 116 123 if (!m_suspended) 117 124 processPendingTasks(); … … 152 159 } 153 160 154 void ThreadableWebSocketChannelClientWrapper::did CloseCallback(ScriptExecutionContext* context, RefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, unsigned long unhandledBufferedAmount)161 void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshakeCallback(ScriptExecutionContext* context, RefPtr<ThreadableWebSocketChannelClientWrapper> wrapper) 155 162 { 156 163 ASSERT_UNUSED(context, !context); 157 164 if (wrapper->m_client) 158 wrapper->m_client->didClose(unhandledBufferedAmount); 165 wrapper->m_client->didStartClosingHandshake(); 166 } 167 168 void ThreadableWebSocketChannelClientWrapper::didCloseCallback(ScriptExecutionContext* context, RefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion) 169 { 170 ASSERT_UNUSED(context, !context); 171 if (wrapper->m_client) 172 wrapper->m_client->didClose(unhandledBufferedAmount, closingHandshakeCompletion); 159 173 } 160 174 -
trunk/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.h
r86829 r87464 36 36 #include "PlatformString.h" 37 37 #include "ScriptExecutionContext.h" 38 #include "WebSocketChannelClient.h" 38 39 #include <wtf/Forward.h> 39 40 #include <wtf/OwnPtr.h> … … 63 64 void didConnect(); 64 65 void didReceiveMessage(const String& message); 65 void didClose(unsigned long unhandledBufferedAmount); 66 void didStartClosingHandshake(); 67 void didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus); 66 68 67 69 void suspend(); … … 74 76 static void didConnectCallback(ScriptExecutionContext*, RefPtr<ThreadableWebSocketChannelClientWrapper>); 75 77 static void didReceiveMessageCallback(ScriptExecutionContext*, RefPtr<ThreadableWebSocketChannelClientWrapper>, String message); 76 static void didCloseCallback(ScriptExecutionContext*, RefPtr<ThreadableWebSocketChannelClientWrapper>, unsigned long unhandledBufferedAmount); 78 static void didStartClosingHandshakeCallback(ScriptExecutionContext*, RefPtr<ThreadableWebSocketChannelClientWrapper>); 79 static void didCloseCallback(ScriptExecutionContext*, RefPtr<ThreadableWebSocketChannelClientWrapper>, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus); 77 80 78 81 WebSocketChannelClient* m_client; -
trunk/Source/WebCore/websockets/WebSocket.cpp
r86542 r87464 165 165 } 166 166 // No exception is raised if the connection was once established but has subsequently been closed. 167 if (m_state == CLOS ED) {167 if (m_state == CLOSING || m_state == CLOSED) { 168 168 m_bufferedAmountAfterClose += message.utf8().length() + 2; // 2 for frameing 169 169 return false; … … 177 177 { 178 178 LOG(Network, "WebSocket %p close", this); 179 if (m_state == CLOSED) 180 return; 181 m_state = CLOSED; 179 if (m_state == CLOSING || m_state == CLOSED) 180 return; 181 if (m_state == CONNECTING) { 182 m_state = CLOSING; 183 m_channel->fail("WebSocket is closed before the connection is established."); 184 return; 185 } 186 m_state = CLOSING; 182 187 m_bufferedAmountAfterClose = m_channel->bufferedAmount(); 183 188 // didClose notification may be already queued, which we will inadvertently process while waiting for bufferedAmount() to return. … … 201 206 if (m_state == OPEN) 202 207 return m_channel->bufferedAmount(); 208 else if (m_state == CLOSING) 209 return m_channel->bufferedAmount() + m_bufferedAmountAfterClose; 203 210 return m_bufferedAmountAfterClose; 204 211 } … … 250 257 LOG(Network, "WebSocket %p didConnect", this); 251 258 if (m_state != CONNECTING) { 252 didClose(0 );259 didClose(0, ClosingHandshakeIncomplete); 253 260 return; 254 261 } … … 261 268 { 262 269 LOG(Network, "WebSocket %p didReceiveMessage %s", this, msg.utf8().data()); 263 if (m_state != OPEN )270 if (m_state != OPEN && m_state != CLOSING) 264 271 return; 265 272 ASSERT(scriptExecutionContext()); … … 272 279 { 273 280 LOG(Network, "WebSocket %p didReceiveErrorMessage", this); 274 if (m_state != OPEN )281 if (m_state != OPEN && m_state != CLOSING) 275 282 return; 276 283 ASSERT(scriptExecutionContext()); … … 278 285 } 279 286 280 void WebSocket::didClose(unsigned long unhandledBufferedAmount) 287 void WebSocket::didStartClosingHandshake() 288 { 289 LOG(Network, "WebSocket %p didStartClosingHandshake", this); 290 m_state = CLOSING; 291 } 292 293 void WebSocket::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion) 281 294 { 282 295 LOG(Network, "WebSocket %p didClose", this); 283 296 if (!m_channel) 284 297 return; 298 bool wasClean = m_state == CLOSING && !unhandledBufferedAmount && closingHandshakeCompletion == ClosingHandshakeComplete; 285 299 m_state = CLOSED; 286 300 m_bufferedAmountAfterClose += unhandledBufferedAmount; 287 301 ASSERT(scriptExecutionContext()); 288 302 RefPtr<CloseEvent> event = CloseEvent::create(false); 289 event->initCloseEvent(eventNames().closeEvent, false, false, false);303 event->initCloseEvent(eventNames().closeEvent, false, false, wasClean); 290 304 dispatchEvent(event); 291 305 if (m_channel) { -
trunk/Source/WebCore/websockets/WebSocket.h
r86732 r87464 96 96 virtual void didReceiveMessage(const String& message); 97 97 virtual void didReceiveMessageError(); 98 virtual void didClose(unsigned long unhandledBufferedAmount); 98 virtual void didStartClosingHandshake(); 99 virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus); 99 100 100 101 private: -
trunk/Source/WebCore/websockets/WebSocketChannel.cpp
r87282 r87464 57 57 namespace WebCore { 58 58 59 const double TCPMaximumSegmentLifetime = 2 * 60.0; 60 59 61 WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketChannelClient* client, const KURL& url, const String& protocol) 60 62 : m_context(context) … … 65 67 , m_resumeTimer(this, &WebSocketChannel::resumeTimerFired) 66 68 , m_suspended(false) 69 , m_closing(false) 70 , m_receivedClosingHandshake(false) 71 , m_closingTimer(this, &WebSocketChannel::closingTimerFired) 67 72 , m_closed(false) 68 73 , m_shouldDiscardReceivedData(false) … … 118 123 LOG(Network, "WebSocketChannel %p close", this); 119 124 ASSERT(!m_suspended); 120 if (m_handle) 121 m_handle->close(); // will call didClose() 125 if (!m_handle) 126 return; 127 startClosingHandshake(); 128 if (m_closing && !m_closingTimer.isActive()) 129 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); 122 130 } 123 131 … … 141 149 m_context = 0; 142 150 if (m_handle) 143 m_handle-> close();151 m_handle->disconnect(); 144 152 } 145 153 … … 176 184 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 177 185 m_closed = true; 186 if (m_closingTimer.isActive()) 187 m_closingTimer.stop(); 178 188 if (m_handle) { 179 189 m_unhandledBufferedAmount = m_handle->bufferedAmount(); … … 185 195 m_handle = 0; 186 196 if (client) 187 client->didClose(m_unhandledBufferedAmount );197 client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete); 188 198 } 189 199 deref(); … … 198 208 return; 199 209 } 210 if (len <= 0) { 211 handle->disconnect(); 212 return; 213 } 200 214 if (!m_client) { 201 215 m_shouldDiscardReceivedData = true; 202 handle-> close();216 handle->disconnect(); 203 217 return; 204 218 } … … 234 248 } 235 249 m_shouldDiscardReceivedData = true; 236 handle-> close();250 handle->disconnect(); 237 251 } 238 252 … … 282 296 ASSERT(m_client); 283 297 ASSERT(m_buffer); 298 LOG(Network, "WebSocketChannel %p processBuffer %lu", this, static_cast<unsigned long>(m_bufferSize)); 299 284 300 if (m_shouldDiscardReceivedData) 285 301 return false; 302 303 if (m_receivedClosingHandshake) { 304 skipBuffer(m_bufferSize); 305 return false; 306 } 307 308 RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. 286 309 287 310 if (m_handshake.mode() == WebSocketHandshake::Incomplete) { … … 312 335 m_shouldDiscardReceivedData = true; 313 336 if (!m_closed) 314 m_handle-> close();337 m_handle->disconnect(); 315 338 return false; 316 339 } … … 363 386 } 364 387 ASSERT(p + length >= p); 365 if (p + length < end) {388 if (p + length <= end) { 366 389 p += length; 367 390 nextFrame = p; 368 391 ASSERT(nextFrame > m_buffer); 369 392 skipBuffer(nextFrame - m_buffer); 370 m_client->didReceiveMessageError(); 393 if (frameByte == 0xff && !length) { 394 m_receivedClosingHandshake = true; 395 startClosingHandshake(); 396 if (m_closing) 397 m_handle->close(); // close after sending FF 00. 398 } else 399 m_client->didReceiveMessageError(); 371 400 return m_buffer; 372 401 } … … 406 435 } 407 436 437 void WebSocketChannel::startClosingHandshake() 438 { 439 LOG(Network, "WebSocketChannel %p closing %d %d", this, m_closing, m_receivedClosingHandshake); 440 if (m_closing) 441 return; 442 ASSERT(m_handle); 443 Vector<char> buf; 444 buf.append('\xff'); 445 buf.append('\0'); 446 if (!m_handle->send(buf.data(), buf.size())) { 447 m_handle->disconnect(); 448 return; 449 } 450 m_closing = true; 451 if (m_client) 452 m_client->didStartClosingHandshake(); 453 } 454 455 void WebSocketChannel::closingTimerFired(Timer<WebSocketChannel>* timer) 456 { 457 LOG(Network, "WebSocketChannel %p closing timer", this); 458 ASSERT_UNUSED(timer, &m_closingTimer == timer); 459 if (m_handle) 460 m_handle->disconnect(); 461 } 462 408 463 } // namespace WebCore 409 464 -
trunk/Source/WebCore/websockets/WebSocketChannel.h
r87139 r87464 58 58 virtual bool send(const String& message); 59 59 virtual unsigned long bufferedAmount() const; 60 virtual void close(); 60 virtual void close(); // Start closing handshake. 61 61 virtual void fail(const String& reason); 62 62 virtual void disconnect(); … … 86 86 bool processBuffer(); 87 87 void resumeTimerFired(Timer<WebSocketChannel>* timer); 88 void startClosingHandshake(); 89 void closingTimerFired(Timer<WebSocketChannel>*); 88 90 89 91 ScriptExecutionContext* m_context; … … 96 98 Timer<WebSocketChannel> m_resumeTimer; 97 99 bool m_suspended; 100 bool m_closing; 101 bool m_receivedClosingHandshake; 102 Timer<WebSocketChannel> m_closingTimer; 98 103 bool m_closed; 99 104 bool m_shouldDiscardReceivedData; -
trunk/Source/WebCore/websockets/WebSocketChannelClient.h
r55573 r87464 42 42 virtual void didReceiveMessage(const String&) { } 43 43 virtual void didReceiveMessageError() { } 44 virtual void didClose(unsigned long /* unhandledBufferedAmount */) { } 44 virtual void didStartClosingHandshake() { } 45 enum ClosingHandshakeCompletionStatus { 46 ClosingHandshakeIncomplete, 47 ClosingHandshakeComplete 48 }; 49 virtual void didClose(unsigned long /* unhandledBufferedAmount */, ClosingHandshakeCompletionStatus) { } 45 50 46 51 protected: -
trunk/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.cpp
r87139 r87464 175 175 return; 176 176 m_mainWebSocketChannel->close(); 177 m_mainWebSocketChannel = 0;178 177 } 179 178 … … 235 234 } 236 235 237 static void workerContextDidClose(ScriptExecutionContext* context, RefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long unhandledBufferedAmount) 238 { 239 ASSERT_UNUSED(context, context->isWorkerContext()); 240 workerClientWrapper->didClose(unhandledBufferedAmount); 241 } 242 243 void WorkerThreadableWebSocketChannel::Peer::didClose(unsigned long unhandledBufferedAmount) 236 static void workerContextDidStartClosingHandshake(ScriptExecutionContext* context, RefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) 237 { 238 ASSERT_UNUSED(context, context->isWorkerContext()); 239 workerClientWrapper->didStartClosingHandshake(); 240 } 241 242 void WorkerThreadableWebSocketChannel::Peer::didStartClosingHandshake() 243 { 244 ASSERT(isMainThread()); 245 m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidStartClosingHandshake, m_workerClientWrapper), m_taskMode); 246 } 247 248 static void workerContextDidClose(ScriptExecutionContext* context, RefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion) 249 { 250 ASSERT_UNUSED(context, context->isWorkerContext()); 251 workerClientWrapper->didClose(unhandledBufferedAmount, closingHandshakeCompletion); 252 } 253 254 void WorkerThreadableWebSocketChannel::Peer::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion) 244 255 { 245 256 ASSERT(isMainThread()); 246 257 m_mainWebSocketChannel = 0; 247 m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidClose, m_workerClientWrapper, unhandledBufferedAmount ), m_taskMode);258 m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidClose, m_workerClientWrapper, unhandledBufferedAmount, closingHandshakeCompletion), m_taskMode); 248 259 } 249 260 -
trunk/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.h
r87139 r87464 100 100 virtual void didConnect(); 101 101 virtual void didReceiveMessage(const String& message); 102 virtual void didClose(unsigned long unhandledBufferedAmount); 102 virtual void didStartClosingHandshake(); 103 virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus); 103 104 104 105 private: -
trunk/Tools/ChangeLog
r87452 r87464 1 2011-05-26 Yuta Kitamura <yutak@chromium.org> 2 3 Reviewed by Kent Tamura. 4 5 WebSocket closing handshake 6 https://bugs.webkit.org/show_bug.cgi?id=35721 7 8 * Scripts/webkitpy/thirdparty/__init__.py: 9 Pull in pywebsocket 0.6b1. We need to update pywebsocket 10 to get the right behavior of closing handshake. 11 1 12 2011-05-26 Qi Zhang <qi.2.zhang@nokia.com> 2 13 -
trunk/Tools/Scripts/webkitpy/thirdparty/__init__.py
r85080 r87464 124 124 pywebsocket_dir = self._fs.join(_AUTOINSTALLED_DIR, "pywebsocket") 125 125 installer = AutoInstaller(target_dir=pywebsocket_dir) 126 installer.install(url="http://pywebsocket.googlecode.com/files/mod_pywebsocket-0. 5.2.tar.gz",127 url_subpath="pywebsocket-0. 5.2/src/mod_pywebsocket")126 installer.install(url="http://pywebsocket.googlecode.com/files/mod_pywebsocket-0.6b1.tar.gz", 127 url_subpath="pywebsocket-0.6b1/src/mod_pywebsocket") 128 128 129 129 def _install(self, url, url_subpath):
Note: See TracChangeset
for help on using the changeset viewer.