[Spice-commits] 4 commits - server/display-channel.c server/display-channel.h server/inputs-channel.c server/inputs-channel-client.c server/inputs-channel-client.h server/inputs-channel.h server/main-channel.c server/main-channel-client.c server/main-channel-client.h server/Makefile.am server/red-channel.c server/red-channel.h server/red-worker.c server/red-worker.h server/stream.c

Jonathon Jongsma jjongsma at kemper.freedesktop.org
Tue May 24 19:58:40 UTC 2016


 server/Makefile.am             |    2 
 server/display-channel.c       |   64 ++++++-------
 server/display-channel.h       |   16 +--
 server/inputs-channel-client.c |   87 ++++++++++++++++++
 server/inputs-channel-client.h |   48 ++++++++++
 server/inputs-channel.c        |   78 ++++------------
 server/inputs-channel.h        |    2 
 server/main-channel-client.c   |   43 +++++++--
 server/main-channel-client.h   |   15 +--
 server/main-channel.c          |   71 ++++-----------
 server/red-channel.c           |  193 +++++++++++++++++------------------------
 server/red-channel.h           |    3 
 server/red-worker.c            |    6 -
 server/red-worker.h            |   15 +--
 server/stream.c                |   23 ++--
 15 files changed, 370 insertions(+), 296 deletions(-)

New commits:
commit 4028fb1c794ef2a212f22b024b1c39f460439e7b
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Mon May 23 11:51:22 2016 +0100

    Replace RedChannel::clients with GList
    
    Instead of using a Ring, use a GList to store the list of channel
    clients. This allows us to iterate the clients without poking inside of
    the client struct to get the channel_link. This is required in order to
    make the RedChannelClient struct private.

diff --git a/server/display-channel.c b/server/display-channel.c
index 6460f57..6febcff 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -223,7 +223,7 @@ void display_channel_surface_unref(DisplayChannel *display, uint32_t surface_id)
     RedSurface *surface = &display->surfaces[surface_id];
     QXLInstance *qxl = display->common.qxl;
     DisplayChannelClient *dcc;
-    RingItem *link, *next;
+    GList *link, *next;
 
     if (--surface->refs != 0) {
         return;
@@ -256,7 +256,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
 {
     Ring *ring;
     RingItem *item;
-    RingItem *dcc_ring_item, *next;
+    GList *link, *next;
     DisplayChannelClient *dcc;
 
     if (!red_channel_is_connected(RED_CHANNEL(display))) {
@@ -280,7 +280,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
             continue;
         }
 
-        FOREACH_DCC(display, dcc_ring_item, next, dcc) {
+        FOREACH_DCC(display, link, next, dcc) {
             agent = &dcc->stream_agents[get_stream_id(display, stream)];
 
             if (region_intersects(&agent->vis_region, &drawable->tree_item.base.rgn)) {
@@ -295,10 +295,10 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
 static void pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
 {
     DisplayChannelClient *dcc;
-    RingItem *dcc_ring_item, *next;
+    GList *link, *next;
 
     spice_warn_if_fail(ring_is_empty(&drawable->pipes));
-    FOREACH_DCC(display, dcc_ring_item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         dcc_prepend_drawable(dcc, drawable);
     }
 }
@@ -320,9 +320,9 @@ static void pipes_add_drawable_after(DisplayChannel *display,
         return;
     }
     if (num_other_linked != display->common.base.clients_num) {
-        RingItem *item, *next;
+        GList *link, *next;
         spice_debug("TODO: not O(n^2)");
-        FOREACH_DCC(display, item, next, dcc) {
+        FOREACH_DCC(display, link, next, dcc) {
             int sent = 0;
             DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
                 if (dpi_pos_after->dcc == dcc) {
@@ -467,34 +467,32 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
 
             DisplayChannelClient *dcc;
             RedDrawablePipeItem *dpi;
-            RingItem *worker_ring_item, *dpi_ring_item;
+            RingItem *dpi_ring_item;
+            GList *link;
 
             other_drawable->refs++;
             current_remove_drawable(display, other_drawable);
 
             /* sending the drawable to clients that already received
              * (or will receive) other_drawable */
-            worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
+            link = RED_CHANNEL(display)->clients;
             dpi_ring_item = ring_get_head(&other_drawable->pipes);
             /* dpi contains a sublist of dcc's, ordered the same */
-            while (worker_ring_item) {
-                dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
-                                        common.base.channel_link);
+            while (link) {
+                dcc = link->data;
                 dpi = SPICE_UPCAST(RedDrawablePipeItem, dpi_ring_item);
-                while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
+                while (link && (!dpi || dcc != dpi->dcc)) {
                     dcc_prepend_drawable(dcc, drawable);
-                    worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
-                                                 worker_ring_item);
-                    dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
-                                            common.base.channel_link);
+                    link = link->next;
+                    if (link)
+                        dcc = link->data;
                 }
 
                 if (dpi_ring_item) {
                     dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
                 }
-                if (worker_ring_item) {
-                    worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
-                                                 worker_ring_item);
+                if (link) {
+                    link = link->next;
                 }
             }
             /* not sending other_drawable where possible */
@@ -1171,9 +1169,9 @@ int display_channel_wait_for_migrate_data(DisplayChannel *display)
     }
 
     spice_debug(NULL);
-    spice_warn_if_fail(channel->clients_num == 1);
+    spice_warn_if_fail(g_list_length(channel->clients) == 1);
 
-    rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients), RedChannelClient, channel_link);
+    rcc = g_list_nth_data(channel->clients, 0);
 
     red_channel_client_ref(rcc);
     for (;;) {
@@ -1210,24 +1208,24 @@ void display_channel_flush_all_surfaces(DisplayChannel *display)
 
 void display_channel_free_glz_drawables_to_free(DisplayChannel *display)
 {
-    RingItem *link, *next;
+    GList *link, *next;
     DisplayChannelClient *dcc;
 
     spice_return_if_fail(display);
 
-    DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) {
+    FOREACH_DCC(display, link, next, dcc) {
         dcc_free_glz_drawables_to_free(dcc);
     }
 }
 
 void display_channel_free_glz_drawables(DisplayChannel *display)
 {
-    RingItem *link, *next;
+    GList *link, *next;
     DisplayChannelClient *dcc;
 
     spice_return_if_fail(display);
 
-    DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) {
+    FOREACH_DCC(display, link, next, dcc) {
         dcc_free_glz_drawables(dcc);
     }
 }
@@ -1270,11 +1268,11 @@ void display_channel_free_some(DisplayChannel *display)
 {
     int n = 0;
     DisplayChannelClient *dcc;
-    RingItem *item, *next;
+    GList *link, *next;
 
     spice_debug("#draw=%d, #glz_draw=%d", display->drawable_count,
                 display->glz_drawable_count);
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
 
         if (glz_dict) {
@@ -1289,7 +1287,7 @@ void display_channel_free_some(DisplayChannel *display)
         free_one_drawable(display, TRUE);
     }
 
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
 
         if (glz_dict) {
@@ -1761,10 +1759,10 @@ void display_channel_update(DisplayChannel *display,
 static void clear_surface_drawables_from_pipes(DisplayChannel *display, int surface_id,
                                                int wait_if_used)
 {
-    RingItem *item, *next;
+    GList *link, *next;
     DisplayChannelClient *dcc;
 
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         if (!dcc_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used)) {
             red_channel_client_disconnect(RED_CHANNEL_CLIENT(dcc));
         }
@@ -1828,9 +1826,9 @@ void display_channel_destroy_surfaces(DisplayChannel *display)
 static void send_create_surface(DisplayChannel *display, int surface_id, int image_ready)
 {
     DisplayChannelClient *dcc;
-    RingItem *item, *next;
+    GList *link, *next;
 
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         dcc_create_surface(dcc, surface_id);
         if (image_ready)
             dcc_push_surface_image(dcc, surface_id);
diff --git a/server/display-channel.h b/server/display-channel.h
index 5aa13c1..4a28c66 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -226,14 +226,14 @@ struct DisplayChannel {
     stat_info_t lz4_stat;
 };
 
-#define LINK_TO_DCC(ptr) SPICE_CONTAINEROF(ptr, DisplayChannelClient,   \
-                                           common.base.channel_link)
-#define DCC_FOREACH_SAFE(link, next, dcc, channel)                      \
-    SAFE_FOREACH(link, next, channel,  &(channel)->clients, dcc, LINK_TO_DCC(link))
-
-
-#define FOREACH_DCC(display_channel, link, next, dcc)                   \
-    DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel))
+#define FOREACH_DCC(channel, _link, _next, _data)                   \
+    for (_link = (channel ? RED_CHANNEL(channel)->clients : NULL), \
+         _next = (_link ? _link->next : NULL), \
+         _data = (_link ? _link->data : NULL); \
+         _link; \
+         _link = _next, \
+         _next = (_link ? _link->next : NULL), \
+         _data = (_link ? _link->data : NULL))
 
 static inline int get_stream_id(DisplayChannel *display, Stream *stream)
 {
diff --git a/server/main-channel.c b/server/main-channel.c
index 1eec10c..5b8f7cf 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -42,12 +42,12 @@ static void main_channel_client_on_disconnect(RedChannelClient *rcc)
 
 RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t connection_id)
 {
-    RingItem *link;
+    GList *link;
     MainChannelClient *mcc;
     RedChannelClient *rcc;
 
-    RING_FOREACH(link, &main_chan->base.clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = main_chan->base.clients; link != NULL; link = link->next) {
+        rcc = link->data;
         mcc = (MainChannelClient*) rcc;
         if (main_channel_client_get_connection_id(mcc) == connection_id) {
             return rcc->client;
@@ -328,11 +328,10 @@ MainChannel* main_channel_new(RedsState *reds)
 
 static int main_channel_connect_semi_seamless(MainChannel *main_channel)
 {
-    RingItem *client_link;
+    GList *link;
 
-    RING_FOREACH(client_link, &main_channel->base.clients) {
-        RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
-                                                    channel_link);
+    for (link = main_channel->base.clients; link != NULL; link = link->next) {
+        RedChannelClient *rcc = link->data;
         MainChannelClient *mcc = (MainChannelClient*)rcc;
         if (main_channel_client_connect_semi_seamless(mcc))
             main_channel->num_clients_mig_wait++;
@@ -342,13 +341,12 @@ static int main_channel_connect_semi_seamless(MainChannel *main_channel)
 
 static int main_channel_connect_seamless(MainChannel *main_channel)
 {
-    RingItem *client_link;
+    GList *link;
 
-    spice_assert(main_channel->base.clients_num == 1);
+    spice_assert(g_list_length(main_channel->base.clients) == 1);
 
-    RING_FOREACH(client_link, &main_channel->base.clients) {
-        RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
-                                                    channel_link);
+    for (link = main_channel->base.clients; link != NULL; link = link->next) {
+        RedChannelClient *rcc = link->data;
         MainChannelClient *mcc = (MainChannelClient*)rcc;
         main_channel_client_connect_seamless(mcc);
         main_channel->num_clients_mig_wait++;
@@ -369,11 +367,9 @@ int main_channel_migrate_connect(MainChannel *main_channel, RedsMigSpice *mig_ta
     if (!try_seamless) {
         return main_channel_connect_semi_seamless(main_channel);
     } else {
-        RingItem *client_item;
         RedChannelClient *rcc;
 
-        client_item = ring_get_head(&main_channel->base.clients);
-        rcc = SPICE_CONTAINEROF(client_item, RedChannelClient, channel_link);
+        rcc = g_list_nth_data(main_channel->base.clients, 0);
 
         if (!red_channel_client_test_remote_cap(rcc,
                                                 SPICE_MAIN_CAP_SEAMLESS_MIGRATE)) {
@@ -387,11 +383,10 @@ int main_channel_migrate_connect(MainChannel *main_channel, RedsMigSpice *mig_ta
 
 void main_channel_migrate_cancel_wait(MainChannel *main_chan)
 {
-    RingItem *client_link;
+    GList *link;
 
-    RING_FOREACH(client_link, &main_chan->base.clients) {
-        RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
-                                                    channel_link);
+    for (link = main_chan->base.clients; link != NULL; link = link->next) {
+        RedChannelClient *rcc = link->data;
         MainChannelClient *mcc = (MainChannelClient*)rcc;
         main_channel_client_migrate_cancel_wait(mcc);
     }
@@ -400,19 +395,18 @@ void main_channel_migrate_cancel_wait(MainChannel *main_chan)
 
 int main_channel_migrate_src_complete(MainChannel *main_chan, int success)
 {
-    RingItem *client_link;
+    GList *link;
     int semi_seamless_count = 0;
 
     spice_printerr("");
 
-    if (ring_is_empty(&main_chan->base.clients)) {
+    if (!main_chan->base.clients) {
         spice_printerr("no peer connected");
         return 0;
     }
 
-    RING_FOREACH(client_link, &main_chan->base.clients) {
-        RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
-                                                    channel_link);
+    for (link = main_chan->base.clients; link != NULL; link = link->next) {
+        RedChannelClient *rcc = link->data;
         MainChannelClient *mcc = (MainChannelClient*)rcc;
         if (main_channel_client_migrate_src_complete(mcc, success))
             semi_seamless_count++;
diff --git a/server/red-channel.c b/server/red-channel.c
index 2f17b28..dd35c88 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -332,14 +332,7 @@ void red_channel_client_receive(RedChannelClient *rcc)
 
 void red_channel_receive(RedChannel *channel)
 {
-    RingItem *link;
-    RingItem *next;
-    RedChannelClient *rcc;
-
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
-        red_channel_client_receive(rcc);
-    }
+    g_list_foreach(channel->clients, (GFunc)red_channel_client_receive, NULL);
 }
 
 static void red_peer_handle_outgoing(RedsStream *stream, OutgoingHandler *handler)
@@ -644,8 +637,7 @@ static void red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeItem *i
 static void red_channel_add_client(RedChannel *channel, RedChannelClient *rcc)
 {
     spice_assert(rcc);
-    ring_add(&channel->clients, &rcc->channel_link);
-    channel->clients_num++;
+    channel->clients = g_list_prepend(channel->clients, rcc);
 }
 
 static void red_channel_client_set_remote_caps(RedChannelClient* rcc,
@@ -683,10 +675,10 @@ int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap)
 
 int red_channel_test_remote_common_cap(RedChannel *channel, uint32_t cap)
 {
-    RingItem *link;
+    GList *link;
 
-    RING_FOREACH(link, &channel->clients) {
-        RedChannelClient *rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        RedChannelClient *rcc = link->data;
 
         if (!red_channel_client_test_remote_common_cap(rcc, cap)) {
             return FALSE;
@@ -697,10 +689,10 @@ int red_channel_test_remote_common_cap(RedChannel *channel, uint32_t cap)
 
 int red_channel_test_remote_cap(RedChannel *channel, uint32_t cap)
 {
-    RingItem *link;
+    GList *link;
 
-    RING_FOREACH(link, &channel->clients) {
-        RedChannelClient *rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        RedChannelClient *rcc = link->data;
 
         if (!red_channel_client_test_remote_cap(rcc, cap)) {
             return FALSE;
@@ -908,7 +900,7 @@ RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedCl
                                            stream->socket,
                                            SPICE_WATCH_EVENT_READ,
                                            red_channel_client_event, rcc);
-    rcc->id = channel->clients_num;
+    rcc->id = g_list_length(channel->clients);
     red_channel_add_client(channel, rcc);
     red_client_add_channel(client, rcc);
     red_channel_ref(channel);
@@ -977,16 +969,17 @@ int red_channel_client_is_waiting_for_migrate_data(RedChannelClient *rcc)
 int red_channel_is_waiting_for_migrate_data(RedChannel *channel)
 {
     RedChannelClient *rcc;
+    guint n_clients = g_list_length(channel->clients);
 
     if (!red_channel_is_connected(channel)) {
         return FALSE;
     }
 
-    if (channel->clients_num > 1) {
+    if (n_clients > 1) {
         return FALSE;
     }
-    spice_assert(channel->clients_num == 1);
-    rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients), RedChannelClient, channel_link);
+    spice_assert(n_clients == 1);
+    rcc = g_list_nth_data(channel->clients, 0);
     return red_channel_client_is_waiting_for_migrate_data(rcc);
 }
 
@@ -1045,7 +1038,6 @@ RedChannel *red_channel_create(int size,
 
     channel->reds = reds;
     channel->core = core;
-    ring_init(&channel->clients);
 
     // TODO: send incoming_cb as parameters instead of duplicating?
     channel->incoming_cb.alloc_msg_buf = (alloc_msg_recv_buf_proc)channel_cbs->alloc_recv_buf;
@@ -1112,7 +1104,6 @@ RedChannel *red_channel_create_dummy(int size, RedsState *reds, uint32_t type, u
     channel->refs = 1;
     channel->reds = reds;
     channel->core = &dummy_core;
-    ring_init(&channel->clients);
     client_cbs.connect = red_channel_client_default_connect;
     client_cbs.disconnect = red_channel_client_default_disconnect;
     client_cbs.migrate = red_channel_client_default_migrate;
@@ -1279,17 +1270,11 @@ void red_channel_client_destroy(RedChannelClient *rcc)
 
 void red_channel_destroy(RedChannel *channel)
 {
-    RingItem *link;
-    RingItem *next;
-
     if (!channel) {
         return;
     }
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        red_channel_client_destroy(
-            SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
-    }
 
+    g_list_foreach(channel->clients, (GFunc)red_channel_client_destroy, NULL);
     red_channel_unref(channel);
 }
 
@@ -1312,12 +1297,7 @@ void red_channel_client_send(RedChannelClient *rcc)
 
 void red_channel_send(RedChannel *channel)
 {
-    RingItem *link;
-    RingItem *next;
-
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        red_channel_client_send(SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
-    }
+    g_list_foreach(channel->clients, (GFunc)red_channel_client_send, NULL);
 }
 
 static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc)
@@ -1372,17 +1352,11 @@ void red_channel_client_push(RedChannelClient *rcc)
 
 void red_channel_push(RedChannel *channel)
 {
-    RingItem *link;
-    RingItem *next;
-    RedChannelClient *rcc;
-
     if (!channel) {
         return;
     }
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
-        red_channel_client_push(rcc);
-    }
+
+    g_list_foreach(channel->clients, (GFunc)red_channel_client_push, NULL);
 }
 
 int red_channel_client_get_roundtrip_ms(RedChannelClient *rcc)
@@ -1403,13 +1377,7 @@ static void red_channel_client_init_outgoing_messages_window(RedChannelClient *r
 // specific
 void red_channel_init_outgoing_messages_window(RedChannel *channel)
 {
-    RingItem *link;
-    RingItem *next;
-
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        red_channel_client_init_outgoing_messages_window(
-            SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
-    }
+    g_list_foreach(channel->clients, (GFunc)red_channel_client_init_outgoing_messages_window, NULL);
 }
 
 static void red_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
@@ -1726,15 +1694,16 @@ void red_channel_client_pipe_add_type(RedChannelClient *rcc, int pipe_item_type)
     red_channel_client_push(rcc);
 }
 
-void red_channel_pipes_add_type(RedChannel *channel, int pipe_item_type)
+static void red_channel_client_pipe_add_type_proxy(gpointer data, gpointer user_data)
 {
-    RingItem *link, *next;
+    int type = GPOINTER_TO_INT(user_data);
+    red_channel_client_pipe_add_type(data, type);
+}
 
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        red_channel_client_pipe_add_type(
-            SPICE_CONTAINEROF(link, RedChannelClient, channel_link),
-            pipe_item_type);
-    }
+void red_channel_pipes_add_type(RedChannel *channel, int pipe_item_type)
+{
+    g_list_foreach(channel->clients, red_channel_client_pipe_add_type_proxy,
+                   GINT_TO_POINTER(pipe_item_type));
 }
 
 void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type)
@@ -1747,21 +1716,22 @@ void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type)
     red_channel_client_push(rcc);
 }
 
-void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
+static void red_channel_client_pipe_add_empty_msg_proxy(gpointer data, gpointer user_data)
 {
-    RingItem *link, *next;
+    int type = GPOINTER_TO_INT(user_data);
+    red_channel_client_pipe_add_empty_msg(data, type);
+}
 
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        red_channel_client_pipe_add_empty_msg(
-            SPICE_CONTAINEROF(link, RedChannelClient, channel_link),
-            msg_type);
-    }
+void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
+{
+    g_list_foreach(channel->clients, red_channel_client_pipe_add_empty_msg_proxy, GINT_TO_POINTER(msg_type));
 }
 
 int red_channel_client_is_connected(RedChannelClient *rcc)
 {
     if (!rcc->dummy) {
-        return ring_item_is_linked(&rcc->channel_link);
+        return rcc->channel
+            && (g_list_find(rcc->channel->clients, rcc) != NULL);
     } else {
         return rcc->dummy_connected;
     }
@@ -1769,7 +1739,7 @@ int red_channel_client_is_connected(RedChannelClient *rcc)
 
 int red_channel_is_connected(RedChannel *channel)
 {
-    return channel && (channel->clients_num > 0);
+    return channel && channel->clients;
 }
 
 static void red_channel_client_clear_sent_item(RedChannelClient *rcc)
@@ -1805,6 +1775,8 @@ void red_channel_client_ack_set_client_window(RedChannelClient *rcc, int client_
 
 static void red_channel_remove_client(RedChannelClient *rcc)
 {
+    GList *link;
+
     if (!pthread_equal(pthread_self(), rcc->channel->thread_id)) {
         spice_warning("channel type %d id %d - "
                       "channel->thread_id (0x%lx) != pthread_self (0x%lx)."
@@ -1813,11 +1785,11 @@ static void red_channel_remove_client(RedChannelClient *rcc)
                       rcc->channel->type, rcc->channel->id,
                       rcc->channel->thread_id, pthread_self());
     }
-    spice_return_if_fail(ring_item_is_linked(&rcc->channel_link));
+    spice_return_if_fail(rcc->channel);
+    link = g_list_find(rcc->channel->clients, rcc);
+    spice_return_if_fail(link != NULL);
 
-    ring_remove(&rcc->channel_link);
-    spice_assert(rcc->channel->clients_num > 0);
-    rcc->channel->clients_num--;
+    rcc->channel->clients = g_list_remove_link(rcc->channel->clients, link);
     // TODO: should we set rcc->channel to NULL???
 }
 
@@ -1831,11 +1803,12 @@ static void red_client_remove_channel(RedChannelClient *rcc)
 
 static void red_channel_client_disconnect_dummy(RedChannelClient *rcc)
 {
+    GList *link;
     spice_assert(rcc->dummy);
-    if (ring_item_is_linked(&rcc->channel_link)) {
+    if (rcc->channel && (link = g_list_find(rcc->channel->clients, rcc))) {
         spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, rcc->channel,
                        rcc->channel->type, rcc->channel->id);
-        red_channel_remove_client(rcc);
+        red_channel_remove_client(link->data);
     }
     rcc->dummy_connected = FALSE;
 }
@@ -1870,13 +1843,7 @@ void red_channel_client_disconnect(RedChannelClient *rcc)
 
 void red_channel_disconnect(RedChannel *channel)
 {
-    RingItem *link;
-    RingItem *next;
-
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        red_channel_client_disconnect(
-            SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
-    }
+    g_list_foreach(channel->clients, (GFunc)red_channel_client_disconnect, NULL);
 }
 
 RedChannelClient *red_channel_client_create_dummy(int size,
@@ -1926,26 +1893,24 @@ error:
 
 void red_channel_apply_clients(RedChannel *channel, channel_client_callback cb)
 {
-    RingItem *link;
-    RingItem *next;
-    RedChannelClient *rcc;
+    g_list_foreach(channel->clients, (GFunc)cb, NULL);
+}
 
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
-        cb(rcc);
-    }
+void red_channel_apply_clients_data(RedChannel *channel, channel_client_callback_data cb, void *data)
+{
+    g_list_foreach(channel->clients, (GFunc)cb, data);
 }
 
 int red_channel_all_blocked(RedChannel *channel)
 {
-    RingItem *link;
+    GList *link;
     RedChannelClient *rcc;
 
-    if (!channel || channel->clients_num == 0) {
+    if (!channel || !channel->clients) {
         return FALSE;
     }
-    RING_FOREACH(link, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        rcc = link->data;
         if (!rcc->send_data.blocked) {
             return FALSE;
         }
@@ -1955,11 +1920,11 @@ int red_channel_all_blocked(RedChannel *channel)
 
 int red_channel_any_blocked(RedChannel *channel)
 {
-    RingItem *link;
+    GList *link;
     RedChannelClient *rcc;
 
-    RING_FOREACH(link, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        rcc = link->data;
         if (rcc->send_data.blocked) {
             return TRUE;
         }
@@ -2002,20 +1967,23 @@ void red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_
 
 int red_channel_get_first_socket(RedChannel *channel)
 {
-    if (!channel || channel->clients_num == 0) {
+    RedChannelClient *rcc;
+
+    if (!channel || !channel->clients) {
         return -1;
     }
-    return SPICE_CONTAINEROF(ring_get_head(&channel->clients),
-                             RedChannelClient, channel_link)->stream->socket;
+    rcc = g_list_nth_data(channel->clients, 0);
+
+    return rcc->stream->socket;
 }
 
 int red_channel_no_item_being_sent(RedChannel *channel)
 {
-    RingItem *link;
+    GList *link;
     RedChannelClient *rcc;
 
-    RING_FOREACH(link, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        rcc = link->data;
         if (!red_channel_client_no_item_being_sent(rcc)) {
             return FALSE;
         }
@@ -2252,7 +2220,7 @@ static int red_channel_pipes_create_batch(RedChannel *channel,
                                 new_pipe_item_t creator, void *data,
                                 rcc_item_t pipe_add)
 {
-    RingItem *link, *next;
+    GList *link, *next;
     RedChannelClient *rcc;
     RedPipeItem *item;
     int num = 0, n = 0;
@@ -2260,13 +2228,16 @@ static int red_channel_pipes_create_batch(RedChannel *channel,
     spice_assert(creator != NULL);
     spice_assert(pipe_add != NULL);
 
-    RING_FOREACH_SAFE(link, next, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    link = channel->clients;
+    while (link != NULL) {
+        next = link->next;
+        rcc = link->data;
         item = (*creator)(rcc, data, num++);
         if (item) {
             (*pipe_add)(rcc, item);
             n++;
         }
+        link = next;
     }
 
     return n;
@@ -2296,12 +2267,12 @@ void red_channel_pipes_new_add_tail(RedChannel *channel, new_pipe_item_t creator
 
 uint32_t red_channel_max_pipe_size(RedChannel *channel)
 {
-    RingItem *link;
+    GList *link;
     RedChannelClient *rcc;
     uint32_t pipe_size = 0;
 
-    RING_FOREACH(link, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        rcc = link->data;
         pipe_size = MAX(pipe_size, rcc->pipe_size);
     }
     return pipe_size;
@@ -2309,12 +2280,12 @@ uint32_t red_channel_max_pipe_size(RedChannel *channel)
 
 uint32_t red_channel_min_pipe_size(RedChannel *channel)
 {
-    RingItem *link;
+    GList *link;
     RedChannelClient *rcc;
     uint32_t pipe_size = ~0;
 
-    RING_FOREACH(link, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        rcc = link->data;
         pipe_size = MIN(pipe_size, rcc->pipe_size);
     }
     return pipe_size == ~0 ? 0 : pipe_size;
@@ -2322,12 +2293,12 @@ uint32_t red_channel_min_pipe_size(RedChannel *channel)
 
 uint32_t red_channel_sum_pipes_size(RedChannel *channel)
 {
-    RingItem *link;
+    GList *link;
     RedChannelClient *rcc;
     uint32_t sum = 0;
 
-    RING_FOREACH(link, &channel->clients) {
-        rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
+    for (link = channel->clients; link != NULL; link = link->next) {
+        rcc = link->data;
         sum += rcc->pipe_size;
     }
     return sum;
diff --git a/server/red-channel.h b/server/red-channel.h
index c4eb436..1bf44a2 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -307,7 +307,7 @@ struct RedChannel {
     // However RCC still holds a reference to the Channel.
     // Maybe replace these logic with ref count?
     // TODO: rename to 'connected_clients'?
-    Ring clients;
+    GList *clients;
     uint32_t clients_num;
 
     OutgoingHandlerInterface outgoing_cb;
@@ -548,6 +548,7 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel);
 typedef void (*channel_client_callback)(RedChannelClient *rcc);
 typedef void (*channel_client_callback_data)(RedChannelClient *rcc, void *data);
 void red_channel_apply_clients(RedChannel *channel, channel_client_callback v);
+void red_channel_apply_clients_data(RedChannel *channel, channel_client_callback_data v, void * data);
 struct RedsState* red_channel_get_server(RedChannel *channel);
 
 struct RedClient {
diff --git a/server/red-worker.c b/server/red-worker.c
index 8d8073e..86f1645 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -500,7 +500,7 @@ static void guest_set_client_capabilities(RedWorker *worker)
     int i;
     DisplayChannelClient *dcc;
     RedChannelClient *rcc;
-    RingItem *link, *next;
+    GList *link, *next;
     uint8_t caps[SPICE_CAPABILITIES_SIZE] = { 0 };
     int caps_available[] = {
         SPICE_DISPLAY_CAP_SIZED_STREAM,
@@ -533,7 +533,7 @@ static void guest_set_client_capabilities(RedWorker *worker)
         for (i = 0 ; i < sizeof(caps_available) / sizeof(caps_available[0]); ++i) {
             SET_CAP(caps, caps_available[i]);
         }
-        DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(worker->display_channel)) {
+        FOREACH_DCC(worker->display_channel, link, next, dcc) {
             rcc = (RedChannelClient *)dcc;
             for (i = 0 ; i < sizeof(caps_available) / sizeof(caps_available[0]); ++i) {
                 if (!red_channel_client_test_remote_cap(rcc, caps_available[i]))
@@ -646,7 +646,7 @@ static void display_update_monitors_config(DisplayChannel *display,
 static void red_worker_push_monitors_config(RedWorker *worker)
 {
     DisplayChannelClient *dcc;
-    RingItem *item, *next;
+    GList *item, *next;
 
     FOREACH_DCC(worker->display_channel, item, next, dcc) {
         dcc_push_monitors_config(dcc);
diff --git a/server/red-worker.h b/server/red-worker.h
index d7525e0..63be8b5 100644
--- a/server/red-worker.h
+++ b/server/red-worker.h
@@ -75,19 +75,16 @@ static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb)
     red_channel_client_pipe_add(rcc, &item->base);
 }
 
-#define LINK_TO_RCC(ptr) SPICE_CONTAINEROF(ptr, RedChannelClient, channel_link)
-#define RCC_FOREACH_SAFE(link, next, rcc, channel) \
-    SAFE_FOREACH(link, next, channel,  &(channel)->clients, rcc, LINK_TO_RCC(link))
+static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer data)
+{
+    uint16_t verb = GPOINTER_TO_UINT(data);
+    red_pipe_add_verb(rcc, verb);
+}
 
 
 static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
 {
-    RedChannelClient *rcc;
-    RingItem *link, *next;
-
-    RCC_FOREACH_SAFE(link, next, rcc, channel) {
-        red_pipe_add_verb(rcc, verb);
-    }
+    red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy, GUINT_TO_POINTER(verb));
 }
 
 RedWorker* red_worker_new(QXLInstance *qxl,
diff --git a/server/stream.c b/server/stream.c
index 9a648c7..6193476 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -96,13 +96,13 @@ static RedPipeItem *stream_destroy_item_new(StreamAgent *agent)
 void stream_stop(DisplayChannel *display, Stream *stream)
 {
     DisplayChannelClient *dcc;
-    RingItem *item, *next;
+    GList *link, *next;
 
     spice_return_if_fail(ring_item_is_linked(&stream->link));
     spice_return_if_fail(!stream->current);
 
     spice_debug("stream %d", get_stream_id(display, stream));
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         StreamAgent *stream_agent;
 
         stream_agent = &dcc->stream_agents[get_stream_id(display, stream)];
@@ -289,7 +289,7 @@ static int is_next_stream_frame(DisplayChannel *display,
 static void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *stream)
 {
     DisplayChannelClient *dcc;
-    RingItem *item, *next;
+    GList *link, *next;
 
     spice_assert(drawable && stream);
     spice_assert(!drawable->stream && !stream->current);
@@ -308,7 +308,7 @@ static void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *s
         stream->num_input_frames++;
     }
 
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         StreamAgent *agent;
         QRegion clip_in_draw_dest;
 
@@ -350,6 +350,7 @@ static void before_reattach_stream(DisplayChannel *display,
     int index;
     StreamAgent *agent;
     RingItem *ring_item, *next;
+    GList *link, *link_next;
 
     spice_return_if_fail(stream->current);
 
@@ -385,7 +386,7 @@ static void before_reattach_stream(DisplayChannel *display,
     }
 
 
-    FOREACH_DCC(display, ring_item, next, dcc) {
+    FOREACH_DCC(display, link, link_next, dcc) {
         double drop_factor;
 
         agent = &dcc->stream_agents[index];
@@ -430,7 +431,7 @@ static Stream *display_channel_stream_try_new(DisplayChannel *display)
 static void display_channel_create_stream(DisplayChannel *display, Drawable *drawable)
 {
     DisplayChannelClient *dcc;
-    RingItem *dcc_ring_item, *next;
+    GList *link, *next;
     Stream *stream;
     SpiceRect* src_rect;
 
@@ -467,7 +468,7 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
     stream->input_fps_start_time = drawable->creation_time;
     display->streams_size_total += stream->width * stream->height;
     display->stream_count++;
-    FOREACH_DCC(display, dcc_ring_item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         dcc_create_stream(dcc, stream);
     }
     spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
@@ -870,10 +871,10 @@ clear_vis_region:
 static void detach_stream_gracefully(DisplayChannel *display, Stream *stream,
                                      Drawable *update_area_limit)
 {
-    RingItem *item, *next;
+    GList *link, *next;
     DisplayChannelClient *dcc;
 
-    FOREACH_DCC(display, item, next, dcc) {
+    FOREACH_DCC(display, link, next, dcc) {
         dcc_detach_stream_gracefully(dcc, stream, update_area_limit);
     }
     if (stream->current) {
@@ -895,7 +896,7 @@ void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *dr
 {
     Ring *ring = &display->streams;
     RingItem *item = ring_get_head(ring);
-    RingItem *dcc_ring_item, *next;
+    GList *link, *next;
     DisplayChannelClient *dcc;
     bool is_connected = red_channel_is_connected(RED_CHANNEL(display));
 
@@ -904,7 +905,7 @@ void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *dr
         int detach = 0;
         item = ring_next(ring, item);
 
-        FOREACH_DCC(display, dcc_ring_item, next, dcc) {
+        FOREACH_DCC(display, link, next, dcc) {
             StreamAgent *agent = &dcc->stream_agents[get_stream_id(display, stream)];
 
             if (region_intersects(&agent->vis_region, region)) {
commit 6c4e86cbe37c29602c31e951e0138d75cfc4c1b9
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Mon May 23 11:46:30 2016 +0100

    Move InputsChannelClient to a separate file
    
    Preparation for converting to GObject
    
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/Makefile.am b/server/Makefile.am
index 5a5c7e8..cca3b9b 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -80,6 +80,8 @@ libserver_la_SOURCES =				\
 	glz-encoder-priv.h	\
 	inputs-channel.c			\
 	inputs-channel.h			\
+	inputs-channel-client.c		\
+	inputs-channel-client.h		\
 	jpeg-encoder.c				\
 	jpeg-encoder.h				\
 	lz4-encoder.c				\
diff --git a/server/inputs-channel-client.c b/server/inputs-channel-client.c
new file mode 100644
index 0000000..f9dd6b2
--- /dev/null
+++ b/server/inputs-channel-client.c
@@ -0,0 +1,87 @@
+/*
+   Copyright (C) 2009-2015 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "inputs-channel-client.h"
+#include "inputs-channel.h"
+#include "migration-protocol.h"
+
+struct InputsChannelClient {
+    RedChannelClient base;
+    uint16_t motion_count;
+};
+
+RedChannelClient* inputs_channel_client_create(RedChannel *channel,
+                                               RedClient *client,
+                                               RedsStream *stream,
+                                               int monitor_latency,
+                                               int num_common_caps,
+                                               uint32_t *common_caps,
+                                               int num_caps,
+                                               uint32_t *caps)
+{
+    InputsChannelClient* icc =
+        (InputsChannelClient*)red_channel_client_create(sizeof(InputsChannelClient),
+                                                        channel, client,
+                                                        stream,
+                                                        monitor_latency,
+                                                        num_common_caps,
+                                                        common_caps, num_caps,
+                                                        caps);
+    if (icc)
+        icc->motion_count = 0;
+    return &icc->base;
+}
+
+void inputs_channel_client_send_migrate_data(RedChannelClient *rcc,
+                                             SpiceMarshaller *m,
+                                             RedPipeItem *item)
+{
+    InputsChannelClient *icc = SPICE_CONTAINEROF(rcc, InputsChannelClient, base);
+    InputsChannel *inputs = (InputsChannel*)rcc->channel;
+
+    inputs_channel_set_src_during_migrate(inputs, FALSE);
+    red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, item);
+
+    spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_INPUTS_MAGIC);
+    spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_INPUTS_VERSION);
+    spice_marshaller_add_uint16(m, icc->motion_count);
+}
+
+void inputs_channel_client_handle_migrate_data(InputsChannelClient *icc,
+                                               uint16_t motion_count)
+{
+    icc->motion_count = motion_count;
+
+    for (; icc->motion_count >= SPICE_INPUT_MOTION_ACK_BUNCH;
+           icc->motion_count -= SPICE_INPUT_MOTION_ACK_BUNCH) {
+        red_channel_client_pipe_add_type(&icc->base, RED_PIPE_ITEM_MOUSE_MOTION_ACK);
+    }
+}
+
+void inputs_channel_client_on_mouse_motion(InputsChannelClient *icc)
+{
+    InputsChannel *inputs_channel = (InputsChannel *)icc->base.channel;
+
+    if (++icc->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
+        !inputs_channel_is_src_during_migrate(inputs_channel)) {
+        red_channel_client_pipe_add_type(&icc->base, RED_PIPE_ITEM_MOUSE_MOTION_ACK);
+        icc->motion_count = 0;
+    }
+}
diff --git a/server/inputs-channel-client.h b/server/inputs-channel-client.h
new file mode 100644
index 0000000..e83cc29
--- /dev/null
+++ b/server/inputs-channel-client.h
@@ -0,0 +1,48 @@
+/*
+   Copyright (C) 2009-2015 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _INPUTS_CHANNEL_CLIENT_H_
+#define _INPUTS_CHANNEL_CLIENT_H_
+
+#include "red-channel.h"
+
+typedef struct InputsChannelClient InputsChannelClient;
+
+RedChannelClient* inputs_channel_client_create(RedChannel *channel,
+                                               RedClient *client,
+                                               RedsStream *stream,
+                                               int monitor_latency,
+                                               int num_common_caps,
+                                               uint32_t *common_caps,
+                                               int num_caps,
+                                               uint32_t *caps);
+
+void inputs_channel_client_send_migrate_data(RedChannelClient *rcc,
+                                             SpiceMarshaller *m,
+                                             RedPipeItem *item);
+void inputs_channel_client_handle_migrate_data(InputsChannelClient *icc,
+                                               uint16_t motion_count);
+void inputs_channel_client_on_mouse_motion(InputsChannelClient *icc);
+
+enum {
+    RED_PIPE_ITEM_INPUTS_INIT = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
+    RED_PIPE_ITEM_MOUSE_MOTION_ACK,
+    RED_PIPE_ITEM_KEY_MODIFIERS,
+    RED_PIPE_ITEM_MIGRATE_DATA,
+};
+
+#endif /* _INPUTS_CHANNEL_CLIENT_H_ */
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index eb07a6f..bdb8d6f 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -39,6 +39,7 @@
 #include "reds.h"
 #include "reds-stream.h"
 #include "red-channel.h"
+#include "inputs-channel-client.h"
 #include "main-channel-client.h"
 #include "inputs-channel.h"
 #include "migration-protocol.h"
@@ -99,11 +100,6 @@ RedsState* spice_tablet_state_get_server(SpiceTabletState *st)
     return st->reds;
 }
 
-typedef struct InputsChannelClient {
-    RedChannelClient base;
-    uint16_t motion_count;
-} InputsChannelClient;
-
 struct InputsChannel {
     RedChannel base;
     uint8_t recv_buf[RECEIVE_BUF_SIZE];
@@ -115,13 +111,6 @@ struct InputsChannel {
     SpiceTabletInstance *tablet;
 };
 
-enum {
-    RED_PIPE_ITEM_INPUTS_INIT = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
-    RED_PIPE_ITEM_MOUSE_MOTION_ACK,
-    RED_PIPE_ITEM_KEY_MODIFIERS,
-    RED_PIPE_ITEM_MIGRATE_DATA,
-};
-
 typedef struct RedInputsPipeItem {
     RedPipeItem base;
 } RedInputsPipeItem;
@@ -239,21 +228,6 @@ static RedPipeItem *red_inputs_key_modifiers_item_new(
     return &item->base;
 }
 
-static void inputs_channel_send_migrate_data(RedChannelClient *rcc,
-                                             SpiceMarshaller *m,
-                                             RedPipeItem *item)
-{
-    InputsChannelClient *icc = SPICE_CONTAINEROF(rcc, InputsChannelClient, base);
-    InputsChannel *inputs = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
-
-    inputs->src_during_migrate = FALSE;
-    red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, item);
-
-    spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_INPUTS_MAGIC);
-    spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_INPUTS_VERSION);
-    spice_marshaller_add_uint16(m, icc->motion_count);
-}
-
 static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
 {
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
@@ -283,7 +257,7 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
             red_channel_client_init_send_data(rcc, SPICE_MSG_INPUTS_MOUSE_MOTION_ACK, base);
             break;
         case RED_PIPE_ITEM_MIGRATE_DATA:
-            inputs_channel_send_migrate_data(rcc, m, base);
+            inputs_channel_client_send_migrate_data(rcc, m, base);
             break;
         default:
             spice_warning("invalid pipe iten %d", base->type);
@@ -331,11 +305,7 @@ static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, ui
         SpiceMouseInstance *mouse = inputs_channel_get_mouse(inputs_channel);
         SpiceMsgcMouseMotion *mouse_motion = message;
 
-        if (++icc->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
-            !inputs_channel->src_during_migrate) {
-            red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_MOUSE_MOTION_ACK);
-            icc->motion_count = 0;
-        }
+        inputs_channel_client_on_mouse_motion(icc);
         if (mouse && reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_SERVER) {
             SpiceMouseInterface *sif;
             sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface, base);
@@ -349,11 +319,7 @@ static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, ui
         SpiceMsgcMousePosition *pos = message;
         SpiceTabletInstance *tablet = inputs_channel_get_tablet(inputs_channel);
 
-        if (++icc->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
-            !inputs_channel->src_during_migrate) {
-            red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_MOUSE_MOTION_ACK);
-            icc->motion_count = 0;
-        }
+        inputs_channel_client_on_mouse_motion(icc);
         if (reds_get_mouse_mode(reds) != SPICE_MOUSE_MODE_CLIENT) {
             break;
         }
@@ -523,7 +489,7 @@ static void inputs_connect(RedChannel *channel, RedClient *client,
                            int num_common_caps, uint32_t *common_caps,
                            int num_caps, uint32_t *caps)
 {
-    InputsChannelClient *icc;
+    RedChannelClient *rcc;
 
     if (!reds_stream_is_ssl(stream) && !red_client_during_migrate_at_target(client)) {
         main_channel_client_push_notify(red_client_get_main(client),
@@ -531,18 +497,13 @@ static void inputs_connect(RedChannel *channel, RedClient *client,
     }
 
     spice_printerr("inputs channel client create");
-    icc = (InputsChannelClient*)red_channel_client_create(sizeof(InputsChannelClient),
-                                                          channel,
-                                                          client,
-                                                          stream,
-                                                          FALSE,
-                                                          num_common_caps, common_caps,
-                                                          num_caps, caps);
-    if (!icc) {
+    rcc = inputs_channel_client_create(channel, client, stream, FALSE,
+                                       num_common_caps, common_caps,
+                                       num_caps, caps);
+    if (!rcc) {
         return;
     }
-    icc->motion_count = 0;
-    inputs_pipe_add_init(&icc->base);
+    inputs_pipe_add_init(rcc);
 }
 
 static void inputs_migrate(RedChannelClient *rcc)
@@ -583,7 +544,7 @@ static int inputs_channel_handle_migrate_data(RedChannelClient *rcc,
                                               uint32_t size,
                                               void *message)
 {
-    InputsChannelClient *icc = SPICE_CONTAINEROF(rcc, InputsChannelClient, base);
+    InputsChannelClient *icc = (InputsChannelClient*)rcc;
     InputsChannel *inputs = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
     SpiceMigrateDataHeader *header;
     SpiceMigrateDataInputs *mig_data;
@@ -598,12 +559,7 @@ static int inputs_channel_handle_migrate_data(RedChannelClient *rcc,
         return FALSE;
     }
     key_modifiers_sender(inputs);
-    icc->motion_count = mig_data->motion_count;
-
-    for (; icc->motion_count >= SPICE_INPUT_MOTION_ACK_BUNCH;
-           icc->motion_count -= SPICE_INPUT_MOTION_ACK_BUNCH) {
-        red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_MOUSE_MOTION_ACK);
-    }
+    inputs_channel_client_handle_migrate_data(icc, mig_data->motion_count);
     return TRUE;
 }
 
@@ -709,3 +665,13 @@ void inputs_channel_detach_tablet(InputsChannel *inputs, SpiceTabletInstance *ta
     inputs->tablet = NULL;
 }
 
+gboolean inputs_channel_is_src_during_migrate(InputsChannel *inputs)
+{
+    return inputs->src_during_migrate;
+}
+
+void inputs_channel_set_src_during_migrate(InputsChannel *inputs,
+                                           gboolean value)
+{
+    inputs->src_during_migrate = value;
+}
diff --git a/server/inputs-channel.h b/server/inputs-channel.h
index 9213aec..5b12fad 100644
--- a/server/inputs-channel.h
+++ b/server/inputs-channel.h
@@ -43,5 +43,7 @@ int inputs_channel_has_tablet(InputsChannel *inputs);
 void inputs_channel_detach_tablet(InputsChannel *inputs, SpiceTabletInstance *tablet);
 RedsState* spice_tablet_state_get_server(SpiceTabletState *dev);
 RedsState* spice_kbd_state_get_server(SpiceKbdState *dev);
+gboolean inputs_channel_is_src_during_migrate(InputsChannel *inputs);
+void inputs_channel_set_src_during_migrate(InputsChannel *inputs, gboolean value);
 
 #endif
commit dbb6e71e8d6275ee8d9b8aa7b514c3fe2ea8ca69
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 6 10:34:53 2016 +0100

    change main_channel_marshall_mouse_mode call style
    
    Make the call more similar to other marshall function calls in the
    same function.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 4407e8b..2188ebb 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -866,12 +866,9 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
                 SPICE_UPCAST(RedPingPipeItem, base));
             break;
         case RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE:
-            {
-                RedMouseModePipeItem *item =
-                    SPICE_UPCAST(RedMouseModePipeItem, base);
-                main_channel_marshall_mouse_mode(rcc, m, item);
-                break;
-            }
+            main_channel_marshall_mouse_mode(rcc, m,
+                SPICE_UPCAST(RedMouseModePipeItem, base));
+            break;
         case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DISCONNECTED:
             main_channel_marshall_agent_disconnected(rcc, m, base);
             break;
commit e4a6a1477e23c213ed6bb9fab34e9d78710775bc
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 6 10:34:52 2016 +0100

    move all item creation in main-channel-client.c
    
    Move all core to create and destroy MainChannel pipe items in a single
    place.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 1e3c443..4407e8b 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -103,6 +103,17 @@ typedef struct RedNotifyPipeItem {
     char *msg;
 } RedNotifyPipeItem;
 
+typedef struct RedMouseModePipeItem {
+    RedPipeItem base;
+    int current_mode;
+    int is_client_mouse_allowed;
+} RedMouseModePipeItem;
+
+typedef struct RedMultiMediaTimePipeItem {
+    RedPipeItem base;
+    int time;
+} RedMultiMediaTimePipeItem;
+
 #define ZERO_BUF_SIZE 4096
 
 static const uint8_t zero_page[ZERO_BUF_SIZE] = {0};
@@ -297,6 +308,29 @@ void main_channel_client_push_notify(MainChannelClient *mcc, const char *msg)
     red_channel_client_pipe_add_push(&mcc->base, item);
 }
 
+RedPipeItem *main_mouse_mode_item_new(RedChannelClient *rcc, void *data, int num)
+{
+    RedMouseModePipeItem *item = spice_malloc(sizeof(RedMouseModePipeItem));
+    MainMouseModeItemInfo *info = data;
+
+    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE);
+    item->current_mode = info->current_mode;
+    item->is_client_mouse_allowed = info->is_client_mouse_allowed;
+    return &item->base;
+}
+
+RedPipeItem *main_multi_media_time_item_new(RedChannelClient *rcc,
+                                            void *data, int num)
+{
+    MainMultiMediaTimeItemInfo *info = data;
+    RedMultiMediaTimePipeItem *item;
+
+    item = spice_malloc(sizeof(RedMultiMediaTimePipeItem));
+    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_MULTI_MEDIA_TIME);
+    item->time = info->time;
+    return &item->base;
+}
+
 void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
                                                   int success,
                                                   int seamless)
diff --git a/server/main-channel-client.h b/server/main-channel-client.h
index e65a2fb..c74f847 100644
--- a/server/main-channel-client.h
+++ b/server/main-channel-client.h
@@ -93,15 +93,18 @@ enum {
     RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS,
 };
 
-typedef struct RedMouseModePipeItem {
-    RedPipeItem base;
+typedef struct MainMouseModeItemInfo {
     int current_mode;
     int is_client_mouse_allowed;
-} RedMouseModePipeItem;
+} MainMouseModeItemInfo;
 
-typedef struct RedMultiMediaTimePipeItem {
-    RedPipeItem base;
+RedPipeItem *main_mouse_mode_item_new(RedChannelClient *rcc, void *data, int num);
+
+typedef struct MainMultiMediaTimeItemInfo {
     int time;
-} RedMultiMediaTimePipeItem;
+} MainMultiMediaTimeItemInfo;
+
+RedPipeItem *main_multi_media_time_item_new(RedChannelClient *rcc,
+                                            void *data, int num);
 
 #endif /* __MAIN_CHANNEL_CLIENT_H__ */
diff --git a/server/main-channel.c b/server/main-channel.c
index be90803..1eec10c 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -56,33 +56,6 @@ RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t c
     return NULL;
 }
 
-typedef struct MainMouseModeItemInfo {
-    int current_mode;
-    int is_client_mouse_allowed;
-} MainMouseModeItemInfo;
-
-static RedPipeItem *main_mouse_mode_item_new(RedChannelClient *rcc, void *data, int num)
-{
-    RedMouseModePipeItem *item = spice_malloc(sizeof(RedMouseModePipeItem));
-    MainMouseModeItemInfo *info = data;
-
-    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE);
-    item->current_mode = info->current_mode;
-    item->is_client_mouse_allowed = info->is_client_mouse_allowed;
-    return &item->base;
-}
-
-static RedPipeItem *main_multi_media_time_item_new(RedChannelClient *rcc,
-                                                   void *data, int num)
-{
-    RedMultiMediaTimePipeItem *item, *info = data;
-
-    item = spice_malloc(sizeof(RedMultiMediaTimePipeItem));
-    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_MULTI_MEDIA_TIME);
-    item->time = info->time;
-    return &item->base;
-}
-
 static void main_channel_push_channels(MainChannelClient *mcc)
 {
     if (red_client_during_migrate_at_target((main_channel_client_get_base(mcc))->client)) {
@@ -148,7 +121,7 @@ static int main_channel_handle_migrate_data(RedChannelClient *rcc,
 
 void main_channel_push_multi_media_time(MainChannel *main_chan, int time)
 {
-    RedMultiMediaTimePipeItem info = {
+    MainMultiMediaTimeItemInfo info = {
         .time = time,
     };
 


More information about the Spice-commits mailing list