summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorItalo Guerrieri <guerital@amazon.it>2017-12-28 15:06:50 +0100
committerIgnacio Casal Quinteiro <qignacio@amazon.com>2018-01-23 15:41:22 +0100
commitd17d5ee2d05a658038e7313fd4fc587525ba37ad (patch)
treea69e3f01a685fb7ef499d9b52e9a319b45d2942c
parentd3abf0cc20a75c17680b85bcb4d9b684c2a756b4 (diff)
downloadlibsoup-d17d5ee2d05a658038e7313fd4fc587525ba37ad.tar.gz
Fix order control frame
Ensure that the control frames received are sent back in the order in which they arrived. Fix Autobahn test case 2.10. https://bugzilla.gnome.org/show_bug.cgi?id=792113
-rw-r--r--libsoup/soup-websocket-connection.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index 6408903d..369c2234 100644
--- a/libsoup/soup-websocket-connection.c
+++ b/libsoup/soup-websocket-connection.c
@@ -96,11 +96,17 @@ enum {
static guint signals[NUM_SIGNALS] = { 0, };
+typedef enum {
+ SOUP_WEBSOCKET_QUEUE_NORMAL = 0,
+ SOUP_WEBSOCKET_QUEUE_URGENT = 1 << 0,
+ SOUP_WEBSOCKET_QUEUE_LAST = 1 << 1,
+} SoupWebsocketQueueFlags;
+
typedef struct {
GBytes *data;
- gboolean last;
gsize sent;
gsize amount;
+ SoupWebsocketQueueFlags flags;
} Frame;
struct _SoupWebsocketConnectionPrivate {
@@ -143,12 +149,6 @@ struct _SoupWebsocketConnectionPrivate {
G_DEFINE_TYPE_WITH_PRIVATE (SoupWebsocketConnection, soup_websocket_connection, G_TYPE_OBJECT)
-typedef enum {
- SOUP_WEBSOCKET_QUEUE_NORMAL = 0,
- SOUP_WEBSOCKET_QUEUE_URGENT = 1 << 0,
- SOUP_WEBSOCKET_QUEUE_LAST = 1 << 1,
-} SoupWebsocketQueueFlags;
-
static void queue_frame (SoupWebsocketConnection *self, SoupWebsocketQueueFlags flags,
gpointer data, gsize len, gsize amount);
@@ -982,7 +982,7 @@ on_web_socket_output (GObject *pollable_stream,
g_debug ("sent frame");
g_queue_pop_head (&pv->outgoing);
- if (frame->last) {
+ if (frame->flags & SOUP_WEBSOCKET_QUEUE_LAST) {
if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) {
close_io_stream (self);
} else {
@@ -1019,7 +1019,6 @@ queue_frame (SoupWebsocketConnection *self,
{
SoupWebsocketConnectionPrivate *pv = self->pv;
Frame *frame;
- Frame *prev;
g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self));
g_return_if_fail (pv->close_sent == FALSE);
@@ -1029,21 +1028,22 @@ queue_frame (SoupWebsocketConnection *self,
frame = g_slice_new0 (Frame);
frame->data = g_bytes_new_take (data, len);
frame->amount = amount;
- frame->last = (flags & SOUP_WEBSOCKET_QUEUE_LAST) ? TRUE : FALSE;
+ frame->flags = flags;
/* If urgent put at front of queue */
if (flags & SOUP_WEBSOCKET_QUEUE_URGENT) {
- /* But we can't interrupt a message already partially sent */
- prev = g_queue_pop_head (&pv->outgoing);
- if (prev == NULL) {
- g_queue_push_head (&pv->outgoing, frame);
- } else if (prev->sent > 0) {
- g_queue_push_head (&pv->outgoing, frame);
- g_queue_push_head (&pv->outgoing, prev);
- } else {
- g_queue_push_head (&pv->outgoing, prev);
- g_queue_push_head (&pv->outgoing, frame);
+ GList *l;
+
+ /* Find out the first frame that is not urgent or partially sent */
+ for (l = g_queue_peek_head_link (&pv->outgoing); l != NULL; l = l->next) {
+ Frame *prev = l->data;
+
+ if (!(prev->flags & SOUP_WEBSOCKET_QUEUE_URGENT) &&
+ prev->sent == 0)
+ break;
}
+
+ g_queue_insert_before (&pv->outgoing, l, frame);
} else {
g_queue_push_tail (&pv->outgoing, frame);
}