diff options
author | Italo Guerrieri <guerital@amazon.it> | 2017-12-28 15:06:50 +0100 |
---|---|---|
committer | Ignacio Casal Quinteiro <qignacio@amazon.com> | 2018-01-23 15:41:22 +0100 |
commit | d17d5ee2d05a658038e7313fd4fc587525ba37ad (patch) | |
tree | a69e3f01a685fb7ef499d9b52e9a319b45d2942c | |
parent | d3abf0cc20a75c17680b85bcb4d9b684c2a756b4 (diff) | |
download | libsoup-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.c | 40 |
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); } |