Commit d9c729aa authored by Carlos Garcia Campos's avatar Carlos Garcia Campos Committed by Carlos Garcia Campos
Browse files

WebSockets: ignore any messages after close has been sent and received

We currently ignore data frames when close has been received, but we
should also ignore any frame after close has been sent and received.
Currently, if we receive two close frames we end up with the code and
reason of the second frame, while the RFC says: "The WebSocket
Connection Close Code is defined as the status code contained in the
first Close control frame received by the application implementing
this protocol."
parent 7f335e97
Pipeline #97006 passed with stage
in 49 seconds
......@@ -772,6 +772,9 @@ process_contents (SoupWebsocketConnection *self,
SoupWebsocketConnectionPrivate *pv = self->pv;
GBytes *message;
if (pv->close_sent && pv->close_received)
return;
if (control) {
/* Control frames must never be fragmented */
if (!fin) {
......
......@@ -823,6 +823,49 @@ test_message_after_closing (Test *test,
g_bytes_unref (message);
}
static gpointer
close_after_close_server_thread (gpointer user_data)
{
Test *test = user_data;
gsize written;
const char frames[] =
"\x88\x09\x03\xe8""reason1"
"\x88\x09\x03\xe8""reason2";
GError *error = NULL;
g_mutex_lock (&test->mutex);
g_mutex_unlock (&test->mutex);
g_output_stream_write_all (g_io_stream_get_output_stream (test->raw_server),
frames, sizeof (frames) -1, &written, NULL, &error);
g_assert_no_error (error);
g_assert_cmpuint (written, ==, sizeof (frames) - 1);
g_io_stream_close (test->raw_server, NULL, &error);
g_assert_no_error (error);
return NULL;
}
static void
test_close_after_close (Test *test,
gconstpointer data)
{
GThread *thread;
g_mutex_lock (&test->mutex);
thread = g_thread_new ("close-after-close-thread", close_after_close_server_thread, test);
soup_websocket_connection_close (test->client, SOUP_WEBSOCKET_CLOSE_NORMAL, "reason1");
g_mutex_unlock (&test->mutex);
g_thread_join (thread);
WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
g_assert_cmpuint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_NORMAL);
g_assert_cmpstr (soup_websocket_connection_get_close_data (test->client), ==, "reason1");
}
static gpointer
timeout_server_thread (gpointer user_data)
{
......@@ -1217,6 +1260,11 @@ main (int argc,
test_message_after_closing,
teardown_soup_connection);
g_test_add ("/websocket/direct/close-after-close", Test, NULL,
setup_half_direct_connection,
test_close_after_close,
teardown_direct_connection);
g_test_add ("/websocket/direct/protocol-negotiate", Test, NULL, NULL,
test_protocol_negotiate_direct,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment