From 7c3a23b9c121b816c551d2560df9ee2bc63f2555 Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Tue, 9 May 2017 15:21:20 -0700 Subject: [PATCH] inspector: handle socket close before close frame This change handles clients that respond to close request with a TCP close instead of close response. PR-URL: https://github.com/nodejs/node/pull/12937 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- src/inspector_socket.cc | 4 ++++ test/cctest/test_inspector_socket.cc | 32 +++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index 6edc08248b6a85..495cb3b3aa3e99 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -335,6 +335,10 @@ static void websockets_data_cb(uv_stream_t* stream, ssize_t nread, if (!inspector->shutting_down && inspector->ws_state->read_cb) { inspector->ws_state->read_cb(stream, nread, nullptr); } + if (inspector->ws_state->close_sent && + !inspector->ws_state->received_close) { + shutdown_complete(inspector); // invoke callback + } } else { #if DUMP_READS printf("%s read %ld bytes\n", __FUNCTION__, nread); diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc index b61fbd2cd6475d..609053a6cd0803 100644 --- a/test/cctest/test_inspector_socket.cc +++ b/test/cctest/test_inspector_socket.cc @@ -35,6 +35,8 @@ static std::string last_path; // NOLINT(runtime/string) static void (*handshake_delegate)(enum inspector_handshake_event state, const std::string& path, bool* should_continue); +static const char SERVER_CLOSE_FRAME[] = {'\x88', '\x00'}; + struct read_expects { const char* expected; @@ -879,7 +881,6 @@ TEST_F(InspectorSocketTest, Send1Mb) { // 3. Close const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', '\x0E', '\x1E', '\xFA'}; - const char SERVER_CLOSE_FRAME[] = {'\x88', '\x00'}; do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); expect_on_client(SERVER_CLOSE_FRAME, sizeof(SERVER_CLOSE_FRAME)); GTEST_ASSERT_EQ(0, uv_is_active( @@ -906,4 +907,33 @@ TEST_F(InspectorSocketTest, ErrorCleansUpTheSocket) { EXPECT_EQ(UV_EPROTO, err); } +static void ServerClosedByClient_cb(InspectorSocket* socket, int code) { + *static_cast(socket->data) = true; +} + +TEST_F(InspectorSocketTest, NoCloseResponseFromClinet) { + ASSERT_TRUE(connected); + ASSERT_FALSE(inspector_ready); + do_write(const_cast(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); + SPIN_WHILE(!inspector_ready); + expect_handshake(); + + // 2. Brief exchange + const char SERVER_MESSAGE[] = "abcd"; + const char CLIENT_FRAME[] = {'\x81', '\x04', 'a', 'b', 'c', 'd'}; + inspector_write(&inspector, SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); + expect_on_client(CLIENT_FRAME, sizeof(CLIENT_FRAME)); + + bool closed = false; + + inspector.data = &closed; + inspector_close(&inspector, ServerClosedByClient_cb); + expect_on_client(SERVER_CLOSE_FRAME, sizeof(SERVER_CLOSE_FRAME)); + uv_close(reinterpret_cast(&client_socket), nullptr); + SPIN_WHILE(!closed); + inspector.data = nullptr; + GTEST_ASSERT_EQ(0, uv_is_active( + reinterpret_cast(&client_socket))); +} + } // anonymous namespace