import libsoup-2.62.3-2.el8
This commit is contained in:
parent
c8ab009314
commit
cd534d36f3
@ -0,0 +1,95 @@
|
|||||||
|
From d9c729aa5a7991182fa7bdb8d94442f8f0cf055b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Carlos Garcia Campos <cgarcia@igalia.com>
|
||||||
|
Date: Fri, 19 Jul 2019 14:56:05 +0200
|
||||||
|
Subject: [PATCH] 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."
|
||||||
|
---
|
||||||
|
libsoup/soup-websocket-connection.c | 3 ++
|
||||||
|
tests/websocket-test.c | 48 +++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 51 insertions(+)
|
||||||
|
|
||||||
|
diff --git libsoup/soup-websocket-connection.c libsoup/soup-websocket-connection.c
|
||||||
|
--- a/libsoup/soup-websocket-connection.c
|
||||||
|
+++ b/libsoup/soup-websocket-connection.c
|
||||||
|
@@ -690,6 +690,9 @@
|
||||||
|
SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
GBytes *message;
|
||||||
|
|
||||||
|
+ if (pv->close_sent && pv->close_received)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
if (control) {
|
||||||
|
/* Control frames must never be fragmented */
|
||||||
|
if (!fin) {
|
||||||
|
--- a/tests/websocket-test.c
|
||||||
|
+++ b/tests/websocket-test.c
|
||||||
|
@@ -707,6 +707,49 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Test *test = user_data;
|
||||||
|
@@ -918,6 +961,11 @@
|
||||||
|
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,
|
@ -0,0 +1,152 @@
|
|||||||
|
From 109bb2f692c746bc63a0ade8737b584aecb0b1ad Mon Sep 17 00:00:00 2001
|
||||||
|
From: Carlos Garcia Campos <cgarcia@igalia.com>
|
||||||
|
Date: Thu, 27 Jun 2019 16:03:21 +0200
|
||||||
|
Subject: [PATCH] WebSockets: allow null characters in text messages data
|
||||||
|
|
||||||
|
RFC 6455 says that text messages should contains valid UTF-8, and null
|
||||||
|
characters valid according to RFC 3629. However, we are using
|
||||||
|
g_utf8_validate(), which considers null characters as errors, to
|
||||||
|
validate WebSockets text messages. This patch adds an internal
|
||||||
|
utf8_validate() function based on g_utf8_validate() but allowing null
|
||||||
|
characters and just returning a gboolean since we are always ignoring
|
||||||
|
the end parameter in case of errors.
|
||||||
|
soup_websocket_connection_send_text() assumes the given text is null
|
||||||
|
terminated, so we need a new public function to allow sending text
|
||||||
|
messages containing null characters. This patch adds
|
||||||
|
soup_websocket_connection_send_message() that receives a
|
||||||
|
SoupWebsocketDataType and GBytes, which is consistent with
|
||||||
|
SoupWebsocketConnection::message signal.
|
||||||
|
|
||||||
|
For RHEL backport, drop the addition of soup_websocket_connection_send_message()
|
||||||
|
as we don't need it and don't want to expose new API.
|
||||||
|
diff --git libsoup/soup-websocket-connection.c libsoup/soup-websocket-connection.c
|
||||||
|
index 66bd6871..67a98731 100644
|
||||||
|
--- a/libsoup/soup-websocket-connection.c
|
||||||
|
+++ b/libsoup/soup-websocket-connection.c
|
||||||
|
@@ -155,6 +155,82 @@
|
||||||
|
|
||||||
|
static void protocol_error_and_close (SoupWebsocketConnection *self);
|
||||||
|
|
||||||
|
+/* Code below is based on g_utf8_validate() implementation,
|
||||||
|
+ * but handling NULL characters as valid, as expected by
|
||||||
|
+ * WebSockets and compliant with RFC 3629.
|
||||||
|
+ */
|
||||||
|
+#define VALIDATE_BYTE(mask, expect) \
|
||||||
|
+ G_STMT_START { \
|
||||||
|
+ if (G_UNLIKELY((*(guchar *)p & (mask)) != (expect))) \
|
||||||
|
+ return FALSE; \
|
||||||
|
+ } G_STMT_END
|
||||||
|
+
|
||||||
|
+/* see IETF RFC 3629 Section 4 */
|
||||||
|
+static gboolean
|
||||||
|
+utf8_validate (const char *str,
|
||||||
|
+ gsize max_len)
|
||||||
|
+
|
||||||
|
+{
|
||||||
|
+ const gchar *p;
|
||||||
|
+
|
||||||
|
+ for (p = str; ((p - str) < max_len); p++) {
|
||||||
|
+ if (*(guchar *)p < 128)
|
||||||
|
+ /* done */;
|
||||||
|
+ else {
|
||||||
|
+ if (*(guchar *)p < 0xe0) { /* 110xxxxx */
|
||||||
|
+ if (G_UNLIKELY (max_len - (p - str) < 2))
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
+ if (G_UNLIKELY (*(guchar *)p < 0xc2))
|
||||||
|
+ return FALSE;
|
||||||
|
+ } else {
|
||||||
|
+ if (*(guchar *)p < 0xf0) { /* 1110xxxx */
|
||||||
|
+ if (G_UNLIKELY (max_len - (p - str) < 3))
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
+ switch (*(guchar *)p++ & 0x0f) {
|
||||||
|
+ case 0:
|
||||||
|
+ VALIDATE_BYTE(0xe0, 0xa0); /* 0xa0 ... 0xbf */
|
||||||
|
+ break;
|
||||||
|
+ case 0x0d:
|
||||||
|
+ VALIDATE_BYTE(0xe0, 0x80); /* 0x80 ... 0x9f */
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ VALIDATE_BYTE(0xc0, 0x80); /* 10xxxxxx */
|
||||||
|
+ }
|
||||||
|
+ } else if (*(guchar *)p < 0xf5) { /* 11110xxx excluding out-of-range */
|
||||||
|
+ if (G_UNLIKELY (max_len - (p - str) < 4))
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
+ switch (*(guchar *)p++ & 0x07) {
|
||||||
|
+ case 0:
|
||||||
|
+ VALIDATE_BYTE(0xc0, 0x80); /* 10xxxxxx */
|
||||||
|
+ if (G_UNLIKELY((*(guchar *)p & 0x30) == 0))
|
||||||
|
+ return FALSE;
|
||||||
|
+ break;
|
||||||
|
+ case 4:
|
||||||
|
+ VALIDATE_BYTE(0xf0, 0x80); /* 0x80 ... 0x8f */
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ VALIDATE_BYTE(0xc0, 0x80); /* 10xxxxxx */
|
||||||
|
+ }
|
||||||
|
+ p++;
|
||||||
|
+ VALIDATE_BYTE(0xc0, 0x80); /* 10xxxxxx */
|
||||||
|
+ } else {
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p++;
|
||||||
|
+ VALIDATE_BYTE(0xc0, 0x80); /* 10xxxxxx */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return TRUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#undef VALIDATE_BYTE
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
frame_free (gpointer data)
|
||||||
|
{
|
||||||
|
@@ -629,7 +705,7 @@
|
||||||
|
data += 2;
|
||||||
|
len -= 2;
|
||||||
|
|
||||||
|
- if (!g_utf8_validate ((char *)data, len, NULL)) {
|
||||||
|
+ if (!utf8_validate ((const char *)data, len)) {
|
||||||
|
g_debug ("received non-UTF8 close data: %d '%.*s' %d", (int)len, (int)len, (char *)data, (int)data[0]);
|
||||||
|
protocol_error_and_close (self);
|
||||||
|
return;
|
||||||
|
@@ -777,9 +853,8 @@
|
||||||
|
/* Actually deliver the message? */
|
||||||
|
if (fin) {
|
||||||
|
if (pv->message_opcode == 0x01 &&
|
||||||
|
- !g_utf8_validate((char *)pv->message_data->data,
|
||||||
|
- pv->message_data->len,
|
||||||
|
- NULL)) {
|
||||||
|
+ !utf8_validate((const char *)pv->message_data->data,
|
||||||
|
+ pv->message_data->len)) {
|
||||||
|
|
||||||
|
g_debug ("received invalid non-UTF8 text data");
|
||||||
|
|
||||||
|
@@ -1699,7 +1774,9 @@
|
||||||
|
* @self: the WebSocket
|
||||||
|
* @text: the message contents
|
||||||
|
*
|
||||||
|
- * Send a text (UTF-8) message to the peer.
|
||||||
|
+ * Send a %NULL-terminated text (UTF-8) message to the peer. If you need
|
||||||
|
+ * to send text messages containing %NULL characters use
|
||||||
|
+ * soup_websocket_connection_send_message() instead.
|
||||||
|
*
|
||||||
|
* The message is queued to be sent and will be sent when the main loop
|
||||||
|
* is run.
|
||||||
|
@@ -1717,7 +1794,7 @@
|
||||||
|
g_return_if_fail (text != NULL);
|
||||||
|
|
||||||
|
length = strlen (text);
|
||||||
|
- g_return_if_fail (g_utf8_validate (text, length, NULL));
|
||||||
|
+ g_return_if_fail (utf8_validate (text, length));
|
||||||
|
|
||||||
|
send_message (self, SOUP_WEBSOCKET_QUEUE_NORMAL, 0x01, (const guint8 *) text, length);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
299
SOURCES/0003-WebSockets-only-poll-IO-stream-when-needed.patch
Normal file
299
SOURCES/0003-WebSockets-only-poll-IO-stream-when-needed.patch
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
From 35f1bac5ff9ec694e64b65e51f0e7a3226aa3aaf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Carlos Garcia Campos <cgarcia@igalia.com>
|
||||||
|
Date: Wed, 28 Aug 2019 10:51:18 +0200
|
||||||
|
Subject: [PATCH] WebSockets: only poll IO stream when needed
|
||||||
|
|
||||||
|
Instead of having two pollable sources constantly running, always try to
|
||||||
|
read/write without blocking and start polling if the operation returns
|
||||||
|
G_IO_ERROR_WOULD_BLOCK. This patch also fixes test
|
||||||
|
/websocket/direct/close-after-close that was passing but not actually
|
||||||
|
testing what we wanted, because the client close was never sent. When
|
||||||
|
the mutex is released, the frame has been queued, but not sent.
|
||||||
|
|
||||||
|
diff --git libsoup/soup-websocket-connection.c libsoup/soup-websocket-connection.c
|
||||||
|
index 345040fe..6afbbe67 100644
|
||||||
|
--- a/libsoup/soup-websocket-connection.c
|
||||||
|
+++ b/libsoup/soup-websocket-connection.c
|
||||||
|
@@ -147,6 +147,7 @@
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT 128 * 1024
|
||||||
|
+#define READ_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (SoupWebsocketConnection, soup_websocket_connection, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
@@ -155,6 +156,11 @@
|
||||||
|
|
||||||
|
static void protocol_error_and_close (SoupWebsocketConnection *self);
|
||||||
|
|
||||||
|
+static gboolean on_web_socket_input (GObject *pollable_stream,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+static gboolean on_web_socket_output (GObject *pollable_stream,
|
||||||
|
+ gpointer user_data);
|
||||||
|
+
|
||||||
|
/* Code below is based on g_utf8_validate() implementation,
|
||||||
|
* but handling NULL characters as valid, as expected by
|
||||||
|
* WebSockets and compliant with RFC 3629.
|
||||||
|
@@ -283,7 +289,20 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-stop_input (SoupWebsocketConnection *self)
|
||||||
|
+soup_websocket_connection_start_input_source (SoupWebsocketConnection *self)
|
||||||
|
+{
|
||||||
|
+ SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
+
|
||||||
|
+ if (pv->input_source)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ pv->input_source = g_pollable_input_stream_create_source (pv->input, NULL);
|
||||||
|
+ g_source_set_callback (pv->input_source, (GSourceFunc)on_web_socket_input, self, NULL);
|
||||||
|
+ g_source_attach (pv->input_source, pv->main_context);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+soup_websocket_connection_stop_input_source (SoupWebsocketConnection *self)
|
||||||
|
{
|
||||||
|
SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
|
||||||
|
@@ -296,7 +315,20 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-stop_output (SoupWebsocketConnection *self)
|
||||||
|
+soup_websocket_connection_start_output_source (SoupWebsocketConnection *self)
|
||||||
|
+{
|
||||||
|
+ SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
+
|
||||||
|
+ if (pv->output_source)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ pv->output_source = g_pollable_output_stream_create_source (pv->output, NULL);
|
||||||
|
+ g_source_set_callback (pv->output_source, (GSourceFunc)on_web_socket_output, self, NULL);
|
||||||
|
+ g_source_attach (pv->output_source, pv->main_context);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+soup_websocket_connection_stop_output_source (SoupWebsocketConnection *self)
|
||||||
|
{
|
||||||
|
SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
|
||||||
|
@@ -341,8 +373,8 @@
|
||||||
|
close_io_stop_timeout (self);
|
||||||
|
|
||||||
|
if (!pv->io_closing) {
|
||||||
|
- stop_input (self);
|
||||||
|
- stop_output (self);
|
||||||
|
+ soup_websocket_connection_stop_input_source (self);
|
||||||
|
+ soup_websocket_connection_stop_output_source (self);
|
||||||
|
pv->io_closing = TRUE;
|
||||||
|
g_debug ("closing io stream");
|
||||||
|
g_io_stream_close_async (pv->io_stream, G_PRIORITY_DEFAULT,
|
||||||
|
@@ -359,7 +391,7 @@
|
||||||
|
GSocket *socket;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
- stop_output (self);
|
||||||
|
+ soup_websocket_connection_stop_output_source (self);
|
||||||
|
|
||||||
|
if (G_IS_SOCKET_CONNECTION (pv->io_stream)) {
|
||||||
|
socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (pv->io_stream));
|
||||||
|
@@ -612,9 +644,6 @@
|
||||||
|
self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? "server" : "client",
|
||||||
|
payload_len, self->pv->max_incoming_payload_size);
|
||||||
|
emit_error_and_close (self, error, TRUE);
|
||||||
|
-
|
||||||
|
- /* The input is in an invalid state now */
|
||||||
|
- stop_input (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -981,32 +1010,31 @@
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static gboolean
|
||||||
|
-on_web_socket_input (GObject *pollable_stream,
|
||||||
|
- gpointer user_data)
|
||||||
|
+static void
|
||||||
|
+soup_websocket_connection_read (SoupWebsocketConnection *self)
|
||||||
|
{
|
||||||
|
- SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data);
|
||||||
|
SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean end = FALSE;
|
||||||
|
gssize count;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
+ soup_websocket_connection_stop_input_source (self);
|
||||||
|
+
|
||||||
|
do {
|
||||||
|
len = pv->incoming->len;
|
||||||
|
- g_byte_array_set_size (pv->incoming, len + 1024);
|
||||||
|
+ g_byte_array_set_size (pv->incoming, len + READ_BUFFER_SIZE);
|
||||||
|
|
||||||
|
count = g_pollable_input_stream_read_nonblocking (pv->input,
|
||||||
|
pv->incoming->data + len,
|
||||||
|
- 1024, NULL, &error);
|
||||||
|
-
|
||||||
|
+ READ_BUFFER_SIZE, NULL, &error);
|
||||||
|
if (count < 0) {
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
|
||||||
|
g_error_free (error);
|
||||||
|
count = 0;
|
||||||
|
} else {
|
||||||
|
emit_error_and_close (self, error, TRUE);
|
||||||
|
- return TRUE;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
} else if (count == 0) {
|
||||||
|
end = TRUE;
|
||||||
|
@@ -1026,16 +1054,24 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
close_io_stream (self);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return TRUE;
|
||||||
|
+ soup_websocket_connection_start_input_source (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
-on_web_socket_output (GObject *pollable_stream,
|
||||||
|
- gpointer user_data)
|
||||||
|
+on_web_socket_input (GObject *pollable_stream,
|
||||||
|
+ gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ soup_websocket_connection_read (SOUP_WEBSOCKET_CONNECTION (user_data));
|
||||||
|
+
|
||||||
|
+ return G_SOURCE_REMOVE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+soup_websocket_connection_write (SoupWebsocketConnection *self)
|
||||||
|
{
|
||||||
|
- SoupWebsocketConnection *self = SOUP_WEBSOCKET_CONNECTION (user_data);
|
||||||
|
SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
const guint8 *data;
|
||||||
|
GError *error = NULL;
|
||||||
|
@@ -1043,19 +1079,18 @@
|
||||||
|
gssize count;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
+ soup_websocket_connection_stop_output_source (self);
|
||||||
|
+
|
||||||
|
if (soup_websocket_connection_get_state (self) == SOUP_WEBSOCKET_STATE_CLOSED) {
|
||||||
|
g_debug ("Ignoring message since the connection is closed");
|
||||||
|
- stop_output (self);
|
||||||
|
- return TRUE;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame = g_queue_peek_head (&pv->outgoing);
|
||||||
|
|
||||||
|
/* No more frames to send */
|
||||||
|
- if (frame == NULL) {
|
||||||
|
- stop_output (self);
|
||||||
|
- return TRUE;
|
||||||
|
- }
|
||||||
|
+ if (frame == NULL)
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
data = g_bytes_get_data (frame->data, &len);
|
||||||
|
g_assert (len > 0);
|
||||||
|
@@ -1075,7 +1110,7 @@
|
||||||
|
frame->pending = TRUE;
|
||||||
|
} else {
|
||||||
|
emit_error_and_close (self, error, TRUE);
|
||||||
|
- return FALSE;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1093,23 +1128,21 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame_free (frame);
|
||||||
|
+
|
||||||
|
+ if (g_queue_is_empty (&pv->outgoing))
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return TRUE;
|
||||||
|
+ soup_websocket_connection_start_output_source (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-start_output (SoupWebsocketConnection *self)
|
||||||
|
+static gboolean
|
||||||
|
+on_web_socket_output (GObject *pollable_stream,
|
||||||
|
+ gpointer user_data)
|
||||||
|
{
|
||||||
|
- SoupWebsocketConnectionPrivate *pv = self->pv;
|
||||||
|
-
|
||||||
|
- if (pv->output_source)
|
||||||
|
- return;
|
||||||
|
+ soup_websocket_connection_write (SOUP_WEBSOCKET_CONNECTION (user_data));
|
||||||
|
|
||||||
|
- g_debug ("starting output source");
|
||||||
|
- pv->output_source = g_pollable_output_stream_create_source (pv->output, NULL);
|
||||||
|
- g_source_set_callback (pv->output_source, (GSourceFunc)on_web_socket_output, self, NULL);
|
||||||
|
- g_source_attach (pv->output_source, pv->main_context);
|
||||||
|
+ return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1150,7 +1183,7 @@
|
||||||
|
g_queue_push_tail (&pv->outgoing, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
- start_output (self);
|
||||||
|
+ soup_websocket_connection_write (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -1175,9 +1208,7 @@
|
||||||
|
pv->output = G_POLLABLE_OUTPUT_STREAM (os);
|
||||||
|
g_return_if_fail (g_pollable_output_stream_can_poll (pv->output));
|
||||||
|
|
||||||
|
- pv->input_source = g_pollable_input_stream_create_source (pv->input, NULL);
|
||||||
|
- g_source_set_callback (pv->input_source, (GSourceFunc)on_web_socket_input, self, NULL);
|
||||||
|
- g_source_attach (pv->input_source, pv->main_context);
|
||||||
|
+ soup_websocket_connection_start_input_source (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
diff --git tests/websocket-test.c tests/websocket-test.c
|
||||||
|
index 146fdf82..26d064df 100644
|
||||||
|
--- a/tests/websocket-test.c
|
||||||
|
+++ b/tests/websocket-test.c
|
||||||
|
@@ -733,6 +733,7 @@
|
||||||
|
const char frames[] =
|
||||||
|
"\x88\x09\x03\xe8""reason1"
|
||||||
|
"\x88\x09\x03\xe8""reason2";
|
||||||
|
+ GSocket *socket;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_mutex_lock (&test->mutex);
|
||||||
|
@@ -742,7 +743,8 @@
|
||||||
|
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);
|
||||||
|
+ socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (test->raw_server));
|
||||||
|
+ g_socket_shutdown (socket, FALSE, TRUE, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
@@ -766,6 +768,7 @@
|
||||||
|
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");
|
||||||
|
+ g_io_stream_close (test->raw_server, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
Name: libsoup
|
Name: libsoup
|
||||||
Version: 2.62.3
|
Version: 2.62.3
|
||||||
Release: 1%{?dist}
|
Release: 2%{?dist}
|
||||||
Summary: Soup, an HTTP library implementation
|
Summary: Soup, an HTTP library implementation
|
||||||
|
|
||||||
License: LGPLv2
|
License: LGPLv2
|
||||||
URL: https://wiki.gnome.org/Projects/libsoup
|
URL: https://wiki.gnome.org/Projects/libsoup
|
||||||
Source0: https://download.gnome.org/sources/%{name}/2.62/%{name}-%{version}.tar.xz
|
Source0: https://download.gnome.org/sources/%{name}/2.62/%{name}-%{version}.tar.xz
|
||||||
|
|
||||||
|
Patch0001: 0001-WebSockets-ignore-any-messages-after-close-has-been-.patch
|
||||||
|
Patch0002: 0002-WebSockets-allow-null-characters-in-text-messages-da.patch
|
||||||
|
Patch0003: 0003-WebSockets-only-poll-IO-stream-when-needed.patch
|
||||||
|
|
||||||
BuildRequires: chrpath
|
BuildRequires: chrpath
|
||||||
BuildRequires: glib2-devel >= %{glib2_version}
|
BuildRequires: glib2-devel >= %{glib2_version}
|
||||||
BuildRequires: glib-networking
|
BuildRequires: glib-networking
|
||||||
@ -82,6 +86,9 @@ chrpath --delete $RPM_BUILD_ROOT%{_libdir}/*.so
|
|||||||
%{_datadir}/vala/vapi/libsoup-2.4.vapi
|
%{_datadir}/vala/vapi/libsoup-2.4.vapi
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Aug 27 2020 Martin Pitt <mpitt@redhat.com> - 2.62.3-2
|
||||||
|
- Some WebSocket fixes to unbreak cockpit-desktop (rhbz#1872270)
|
||||||
|
|
||||||
* Fri Aug 10 2018 Kalev Lember <klember@redhat.com> - 2.62.3-1
|
* Fri Aug 10 2018 Kalev Lember <klember@redhat.com> - 2.62.3-1
|
||||||
- Update to 2.62.3
|
- Update to 2.62.3
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user