[Spice-devel] [PATCH 07/11] Add RedChannelClientPrivate struct

Jonathon Jongsma jjongsma at redhat.com
Tue Aug 9 15:33:01 UTC 2016


Encapsulate private data and prepare for port to GObject
---
 server/cursor-channel.c             |   3 +-
 server/dcc-send.c                   |  22 +-
 server/dcc.c                        |  24 +-
 server/inputs-channel-client.c      |   2 +-
 server/main-channel-client.c        |  56 ++--
 server/red-channel-client-private.h |  15 +-
 server/red-channel-client.c         | 569 ++++++++++++++++++------------------
 server/smartcard.c                  |  17 +-
 server/sound.c                      |  32 +-
 server/spicevmc.c                   |   4 +-
 10 files changed, 397 insertions(+), 347 deletions(-)

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 591d68f..97aa0bb 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -215,7 +215,8 @@ static void cursor_marshall(CursorChannelClient *ccc,
                             RedCursorPipeItem *cursor_pipe_item)
 {
     RedChannelClient *rcc = RED_CHANNEL_CLIENT(ccc);
-    CursorChannel *cursor_channel = SPICE_CONTAINEROF(red_channel_client_get_channel(rcc), CursorChannel, common.base);
+    CursorChannel *cursor_channel = SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
+                                                      CursorChannel, common.base);
     CursorItem *item = cursor_pipe_item->cursor_item;
     RedPipeItem *pipe_item = &cursor_pipe_item->base;
     RedCursorCmd *cmd;
diff --git a/server/dcc-send.c b/server/dcc-send.c
index 406907b..da11bd3 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -188,14 +188,15 @@ static int is_brush_lossy(RedChannelClient *rcc, SpiceBrush *brush,
 
 static RedPipeItem *dcc_get_tail(DisplayChannelClient *dcc)
 {
-    return (RedPipeItem*)ring_get_tail(&RED_CHANNEL_CLIENT(dcc)->pipe);
+    return (RedPipeItem*)ring_get_tail(&RED_CHANNEL_CLIENT(dcc)->priv->pipe);
 }
 
 static void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc,
                                                   SpiceImage *image, SpiceImage *io_image,
                                                   int is_lossy)
 {
-    DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+    DisplayChannel *display_channel = SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
+                                                        DisplayChannel, common.base);
     DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
 
     if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
@@ -441,7 +442,7 @@ static FillBitsType fill_bits(DisplayChannelClient *dcc, SpiceMarshaller *m,
         /* Images must be added to the cache only after they are compressed
            in order to prevent starvation in the client between pixmap_cache and
            global dictionary (in cases of multiple monitors) */
-        if (reds_stream_get_family(rcc->stream) == AF_UNIX ||
+        if (reds_stream_get_family(rcc->priv->stream) == AF_UNIX ||
             !dcc_compress_image(dcc, &image, &simage->u.bitmap,
                                 drawable, can_lossy, &comp_send_data)) {
             SpicePalette *palette;
@@ -620,7 +621,7 @@ static int pipe_rendered_drawables_intersect_with_areas(DisplayChannelClient *dc
     Ring *pipe;
 
     spice_assert(num_surfaces);
-    pipe = &RED_CHANNEL_CLIENT(dcc)->pipe;
+    pipe = &RED_CHANNEL_CLIENT(dcc)->priv->pipe;
 
     for (pipe_item = (RedPipeItem *)ring_get_head(pipe);
          pipe_item;
@@ -712,7 +713,7 @@ static void red_pipe_replace_rendered_drawables_with_images(DisplayChannelClient
     resent_areas[0] = *first_area;
     num_resent = 1;
 
-    pipe = &RED_CHANNEL_CLIENT(dcc)->pipe;
+    pipe = &RED_CHANNEL_CLIENT(dcc)->priv->pipe;
 
     // going from the oldest to the newest
     for (pipe_item = (RedPipeItem *)ring_get_tail(pipe);
@@ -1834,7 +1835,8 @@ static void display_channel_marshall_migrate_data(RedChannelClient *rcc,
     DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
     SpiceMigrateDataDisplay display_data = {0,};
 
-    display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+    display_channel = SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
+                                        DisplayChannel, common.base);
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, NULL);
     spice_marshaller_add_uint32(base_marshaller, SPICE_MIGRATE_DATA_DISPLAY_MAGIC);
@@ -2137,7 +2139,8 @@ static void marshall_qxl_drawable(RedChannelClient *rcc,
     spice_return_if_fail(rcc);
 
     Drawable *item = dpi->drawable;
-    DisplayChannel *display = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+    DisplayChannel *display = SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
+                                                DisplayChannel, common.base);
 
     spice_return_if_fail(display);
     /* allow sized frames to be streamed, even if they where replaced by another frame, since
@@ -2230,8 +2233,9 @@ static void marshall_upgrade(RedChannelClient *rcc, SpiceMarshaller *m,
     RedDrawable *red_drawable;
     SpiceMsgDisplayDrawCopy copy;
     SpiceMarshaller *src_bitmap_out, *mask_bitmap_out;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    spice_assert(rcc && rcc->channel && item && item->drawable);
+    spice_assert(rcc && channel && item && item->drawable);
     red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_COPY, &item->base);
 
     red_drawable = item->drawable->red_drawable;
@@ -2365,7 +2369,7 @@ static void begin_send_message(RedChannelClient *rcc)
         }
         free_list->wait.header.wait_count = sync_count;
 
-        if (rcc->is_mini_header) {
+        if (rcc->priv->is_mini_header) {
             send_free_list(rcc);
         } else {
             send_free_list_legacy(rcc);
diff --git a/server/dcc.c b/server/dcc.c
index d387e8b..fb71794 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -76,7 +76,7 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
        no other drawable depends on them */
 
     rcc = RED_CHANNEL_CLIENT(dcc);
-    ring = &rcc->pipe;
+    ring = &rcc->priv->pipe;
     item = (RedPipeItem *) ring;
     while ((item = (RedPipeItem *)ring_next(ring, &item->link))) {
         Drawable *drawable;
@@ -141,6 +141,7 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
 {
     DisplayChannel *display;
     RedSurface *surface;
+    RedChannel *channel;
     RedSurfaceCreateItem *create;
     uint32_t flags;
 
@@ -156,8 +157,9 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
         dcc->surface_client_created[surface_id]) {
         return;
     }
+    channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(dcc));
     surface = &display->surfaces[surface_id];
-    create = red_surface_create_item_new(RED_CHANNEL_CLIENT(dcc)->channel,
+    create = red_surface_create_item_new(channel,
                                          surface_id, surface->context.width,
                                          surface->context.height,
                                          surface->context.format, flags);
@@ -459,7 +461,7 @@ void dcc_start(DisplayChannelClient *dcc)
         dcc_create_all_streams(dcc);
     }
 
-    if (reds_stream_is_plain_unix(rcc->stream) &&
+    if (reds_stream_is_plain_unix(red_channel_client_get_stream(rcc)) &&
         red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_GL_SCANOUT)) {
         red_channel_client_pipe_add(rcc, dcc_gl_scanout_item_new(rcc, NULL, 0));
         dcc_push_monitors_config(dcc);
@@ -538,6 +540,7 @@ void dcc_push_monitors_config(DisplayChannelClient *dcc)
     DisplayChannel *dc = DCC_TO_DC(dcc);
     MonitorsConfig *monitors_config = dc->monitors_config;
     RedMonitorsConfigItem *mci;
+    RedChannel *channel;
 
     if (monitors_config == NULL) {
         spice_warning("monitors_config is NULL");
@@ -549,7 +552,8 @@ void dcc_push_monitors_config(DisplayChannelClient *dcc)
         return;
     }
 
-    mci = red_monitors_config_item_new(dcc->base.channel,
+    channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(dcc));
+    mci = red_monitors_config_item_new(channel,
                                        monitors_config_ref(dc->monitors_config));
     red_channel_client_pipe_add(&dcc->base, &mci->pipe_item);
     red_channel_client_push(&dcc->base);
@@ -573,7 +577,7 @@ RedPipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
     spice_return_val_if_fail(item != NULL, NULL);
 
     /* FIXME: on !unix peer, start streaming with a video codec */
-    if (!reds_stream_is_plain_unix(rcc->stream) ||
+    if (!reds_stream_is_plain_unix(red_channel_client_get_stream(rcc)) ||
         !red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_GL_SCANOUT)) {
         spice_printerr("FIXME: client does not support GL scanout");
         red_channel_client_disconnect(rcc);
@@ -892,18 +896,19 @@ int dcc_pixmap_cache_unlocked_add(DisplayChannelClient *dcc, uint64_t id,
 static int dcc_handle_init(DisplayChannelClient *dcc, SpiceMsgcDisplayInit *init)
 {
     gboolean success;
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc));
 
     spice_return_val_if_fail(dcc->expect_init, FALSE);
     dcc->expect_init = FALSE;
 
     spice_return_val_if_fail(!dcc->pixmap_cache, FALSE);
-    dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client,
+    dcc->pixmap_cache = pixmap_cache_get(client,
                                          init->pixmap_cache_id,
                                          init->pixmap_cache_size);
     spice_return_val_if_fail(dcc->pixmap_cache, FALSE);
 
     success = image_encoders_get_glz_dictionary(&dcc->encoders,
-                                                RED_CHANNEL_CLIENT(dcc)->client,
+                                                red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc)),
                                                 init->glz_dictionary_id,
                                                 init->glz_dictionary_window_size);
     spice_return_val_if_fail(success, FALSE);
@@ -1007,7 +1012,7 @@ static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc,
                                              SpiceMigrateDataDisplay *migrate)
 {
     return image_encoders_restore_glz_dictionary(&dcc->encoders,
-                                                 RED_CHANNEL_CLIENT(dcc)->client,
+                                                 red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc)),
                                                  migrate->glz_dict_id,
                                                  &migrate->glz_dict_data);
 }
@@ -1066,6 +1071,7 @@ static int restore_surfaces_lossy(DisplayChannelClient *dcc,
 
 int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *message)
 {
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc));
     DisplayChannel *display = DCC_TO_DC(dcc);
     int surfaces_restored = FALSE;
     SpiceMigrateDataHeader *header = (SpiceMigrateDataHeader *)message;
@@ -1083,7 +1089,7 @@ int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *mess
      * channel client that froze the cache on the src size receives the migrate
      * data and unfreezes the cache by setting its size > 0 and by triggering
      * pixmap_cache_reset */
-    dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client,
+    dcc->pixmap_cache = pixmap_cache_get(client,
                                          migrate_data->pixmap_cache_id, -1);
     spice_return_val_if_fail(dcc->pixmap_cache, FALSE);
 
diff --git a/server/inputs-channel-client.c b/server/inputs-channel-client.c
index 8a4b4dd..6712508 100644
--- a/server/inputs-channel-client.c
+++ b/server/inputs-channel-client.c
@@ -86,7 +86,7 @@ void inputs_channel_client_handle_migrate_data(InputsChannelClient *icc,
 
 void inputs_channel_client_on_mouse_motion(InputsChannelClient *icc)
 {
-    InputsChannel *inputs_channel = (InputsChannel *)icc->base.channel;
+    InputsChannel *inputs_channel = (InputsChannel *)red_channel_client_get_channel(RED_CHANNEL_CLIENT(icc));
 
     if (++icc->priv->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
         !inputs_channel_is_src_during_migrate(inputs_channel)) {
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 4481168..23cf439 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -343,21 +343,23 @@ void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
                                                   int success,
                                                   int seamless)
 {
-    spice_printerr("client %p connected: %d seamless %d", mcc->base.client, success, seamless);
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(mcc));
+    RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(mcc));
+    spice_printerr("client %p connected: %d seamless %d", client, success, seamless);
     if (mcc->priv->mig_wait_connect) {
-        MainChannel *main_channel = SPICE_CONTAINEROF(mcc->base.channel, MainChannel, base);
+        MainChannel *main_channel = SPICE_CONTAINEROF(channel, MainChannel, base);
 
         mcc->priv->mig_wait_connect = FALSE;
         mcc->priv->mig_connect_ok = success;
         spice_assert(main_channel->num_clients_mig_wait);
         spice_assert(!seamless || main_channel->num_clients_mig_wait == 1);
         if (!--main_channel->num_clients_mig_wait) {
-            reds_on_main_migrate_connected(mcc->base.channel->reds, seamless && success);
+            reds_on_main_migrate_connected(channel->reds, seamless && success);
         }
     } else {
         if (success) {
-            spice_printerr("client %p MIGRATE_CANCEL", mcc->base.client);
-            red_channel_client_pipe_add_empty_msg(&mcc->base, SPICE_MSG_MAIN_MIGRATE_CANCEL);
+            spice_printerr("client %p MIGRATE_CANCEL", client);
+            red_channel_client_pipe_add_empty_msg(RED_CHANNEL_CLIENT(mcc), SPICE_MSG_MAIN_MIGRATE_CANCEL);
         }
     }
 }
@@ -365,7 +367,8 @@ void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
 void main_channel_client_handle_migrate_dst_do_seamless(MainChannelClient *mcc,
                                                         uint32_t src_version)
 {
-    if (reds_on_migrate_dst_set_seamless(mcc->base.channel->reds, mcc, src_version)) {
+    RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(mcc));
+    if (reds_on_migrate_dst_set_seamless(channel->reds, mcc, src_version)) {
         mcc->priv->seamless_mig_dst = TRUE;
         red_channel_client_pipe_add_empty_msg(&mcc->base,
                                              SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK);
@@ -432,13 +435,14 @@ void main_channel_client_handle_pong(MainChannelClient *mcc, SpiceMsgPing *ping,
         red_channel_client_handle_message(rcc, size, SPICE_MSGC_PONG, ping);
     }
 #ifdef RED_STATISTICS
-    stat_update_value(rcc->channel->reds, roundtrip);
+    stat_update_value(red_channel_client_get_channel(rcc)->reds, roundtrip);
 #endif
 }
 
 void main_channel_client_handle_migrate_end(MainChannelClient *mcc)
 {
-    if (!red_client_during_migrate_at_target(mcc->base.client)) {
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(mcc));
+    if (!red_client_during_migrate_at_target(client)) {
         spice_printerr("unexpected SPICE_MSGC_MIGRATE_END");
         return;
     }
@@ -448,13 +452,14 @@ void main_channel_client_handle_migrate_end(MainChannelClient *mcc)
                    "client does not support semi-seamless migration");
             return;
     }
-    red_client_semi_seamless_migrate_complete(mcc->base.client);
+    red_client_semi_seamless_migrate_complete(client);
 }
 
 void main_channel_client_migrate_cancel_wait(MainChannelClient *mcc)
 {
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(mcc));
     if (mcc->priv->mig_wait_connect) {
-        spice_printerr("client %p cancel wait connect", mcc->base.client);
+        spice_printerr("client %p cancel wait connect", client);
         mcc->priv->mig_wait_connect = FALSE;
         mcc->priv->mig_connect_ok = FALSE;
     }
@@ -463,9 +468,10 @@ void main_channel_client_migrate_cancel_wait(MainChannelClient *mcc)
 
 void main_channel_client_migrate_dst_complete(MainChannelClient *mcc)
 {
+    RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(mcc));
     if (mcc->priv->mig_wait_prev_complete) {
         if (mcc->priv->mig_wait_prev_try_seamless) {
-            spice_assert(g_list_length(mcc->base.channel->clients) == 1);
+            spice_assert(g_list_length(channel->clients) == 1);
             red_channel_client_pipe_add_type(&mcc->base,
                                              RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_BEGIN_SEAMLESS);
         } else {
@@ -479,21 +485,22 @@ void main_channel_client_migrate_dst_complete(MainChannelClient *mcc)
 gboolean main_channel_client_migrate_src_complete(MainChannelClient *mcc,
                                                   gboolean success)
 {
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(mcc));
     gboolean ret = FALSE;
     int semi_seamless_support = red_channel_client_test_remote_cap(&mcc->base,
                                                                    SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
     if (semi_seamless_support && mcc->priv->mig_connect_ok) {
         if (success) {
-            spice_printerr("client %p MIGRATE_END", mcc->base.client);
+            spice_printerr("client %p MIGRATE_END", client);
             red_channel_client_pipe_add_empty_msg(&mcc->base, SPICE_MSG_MAIN_MIGRATE_END);
             ret = TRUE;
         } else {
-            spice_printerr("client %p MIGRATE_CANCEL", mcc->base.client);
+            spice_printerr("client %p MIGRATE_CANCEL", client);
             red_channel_client_pipe_add_empty_msg(&mcc->base, SPICE_MSG_MAIN_MIGRATE_CANCEL);
         }
     } else {
         if (success) {
-            spice_printerr("client %p SWITCH_HOST", mcc->base.client);
+            spice_printerr("client %p SWITCH_HOST", client);
             red_channel_client_pipe_add_type(&mcc->base, RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_SWITCH_HOST);
         }
     }
@@ -507,6 +514,7 @@ gboolean main_channel_client_migrate_src_complete(MainChannelClient *mcc,
 static void do_ping_client(MainChannelClient *mcc,
     const char *opt, int has_interval, int interval)
 {
+    RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(mcc));
     spice_printerr("");
     if (!opt) {
         main_channel_client_push_ping(mcc, 0);
@@ -514,9 +522,9 @@ static void do_ping_client(MainChannelClient *mcc,
         if (has_interval && interval > 0) {
             mcc->priv->ping_interval = interval * MSEC_PER_SEC;
         }
-        reds_core_timer_start(mcc->base.channel->reds, mcc->priv->ping_timer, mcc->priv->ping_interval);
+        reds_core_timer_start(channel->reds, mcc->priv->ping_timer, mcc->priv->ping_interval);
     } else if (!strcmp(opt, "off")) {
-        reds_core_timer_cancel(mcc->base.channel->reds, mcc->priv->ping_timer);
+        reds_core_timer_cancel(channel->reds, mcc->priv->ping_timer);
     } else {
         return;
     }
@@ -525,14 +533,15 @@ static void do_ping_client(MainChannelClient *mcc,
 static void ping_timer_cb(void *opaque)
 {
     MainChannelClient *mcc = opaque;
+    RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(mcc));
 
     if (!red_channel_client_is_connected(&mcc->base)) {
         spice_printerr("not connected to peer, ping off");
-        reds_core_timer_cancel(mcc->base.channel->reds, mcc->priv->ping_timer);
+        reds_core_timer_cancel(channel->reds, mcc->priv->ping_timer);
         return;
     }
     do_ping_client(mcc, NULL, 0, 0);
-    reds_core_timer_start(mcc->base.channel->reds, mcc->priv->ping_timer, mcc->priv->ping_interval);
+    reds_core_timer_start(channel->reds, mcc->priv->ping_timer, mcc->priv->ping_interval);
 }
 #endif /* RED_STATISTICS */
 
@@ -581,14 +590,16 @@ uint64_t main_channel_client_get_roundtrip_ms(MainChannelClient *mcc)
 
 void main_channel_client_migrate(RedChannelClient *rcc)
 {
-    reds_on_main_channel_migrate(rcc->channel->reds, SPICE_CONTAINEROF(rcc, MainChannelClient, base));
+    RedChannel *channel = red_channel_client_get_channel(rcc);
+    reds_on_main_channel_migrate(channel->reds, SPICE_CONTAINEROF(rcc, MainChannelClient, base));
     red_channel_client_default_migrate(rcc);
 }
 
 gboolean main_channel_client_connect_semi_seamless(MainChannelClient *mcc)
 {
     RedChannelClient *rcc = main_channel_client_get_base(mcc);
-    MainChannel* main_channel = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+    MainChannel* main_channel = SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
+                                                  MainChannel, base);
     if (red_channel_client_test_remote_cap(rcc,
                                            SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE)) {
         RedClient *client = red_channel_client_get_client(rcc);
@@ -610,10 +621,11 @@ gboolean main_channel_client_connect_semi_seamless(MainChannelClient *mcc)
 
 void main_channel_client_connect_seamless(MainChannelClient *mcc)
 {
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(mcc));
     spice_assert(red_channel_client_test_remote_cap(&mcc->base,
                                                     SPICE_MAIN_CAP_SEAMLESS_MIGRATE));
-    if (red_client_during_migrate_at_target(mcc->base.client)) {
-        spice_printerr("client %p: wait till previous migration completes", mcc->base.client);
+    if (red_client_during_migrate_at_target(client)) {
+        spice_printerr("client %p: wait till previous migration completes", client);
         mcc->priv->mig_wait_prev_complete = TRUE;
         mcc->priv->mig_wait_prev_try_seamless = TRUE;
     } else {
diff --git a/server/red-channel-client-private.h b/server/red-channel-client-private.h
index 4ad4d90..2e73279 100644
--- a/server/red-channel-client-private.h
+++ b/server/red-channel-client-private.h
@@ -21,7 +21,18 @@
 #include "red-channel-client.h"
 #include "red-channel.h"
 
-struct RedChannelClient {
+typedef struct RedChannelClientPrivate RedChannelClientPrivate;
+struct RedChannelClient
+{
+    /* protected */
+    OutgoingHandler outgoing;
+    IncomingHandler incoming;
+
+    RedChannelClientPrivate *priv;
+};
+
+struct RedChannelClientPrivate
+{
     RedChannel *channel;
     RedClient  *client;
     RedsStream *stream;
@@ -57,8 +68,6 @@ struct RedChannelClient {
         } urgent;
     } send_data;
 
-    OutgoingHandler outgoing;
-    IncomingHandler incoming;
     int during_send;
     int id; // debugging purposes
     Ring pipe;
diff --git a/server/red-channel-client.c b/server/red-channel-client.c
index 908dc85..82afac8 100644
--- a/server/red-channel-client.c
+++ b/server/red-channel-client.c
@@ -65,34 +65,34 @@ typedef struct MarkerPipeItem {
 
 static void red_channel_client_start_ping_timer(RedChannelClient *rcc, uint32_t timeout)
 {
-    if (!rcc->latency_monitor.timer) {
+    if (!rcc->priv->latency_monitor.timer) {
         return;
     }
-    if (rcc->latency_monitor.state != PING_STATE_NONE) {
+    if (rcc->priv->latency_monitor.state != PING_STATE_NONE) {
         return;
     }
-    rcc->latency_monitor.state = PING_STATE_TIMER;
-    rcc->channel->core->timer_start(rcc->latency_monitor.timer, timeout);
+    rcc->priv->latency_monitor.state = PING_STATE_TIMER;
+    rcc->priv->channel->core->timer_start(rcc->priv->latency_monitor.timer, timeout);
 }
 
 static void red_channel_client_cancel_ping_timer(RedChannelClient *rcc)
 {
-    if (!rcc->latency_monitor.timer) {
+    if (!rcc->priv->latency_monitor.timer) {
         return;
     }
-    if (rcc->latency_monitor.state != PING_STATE_TIMER) {
+    if (rcc->priv->latency_monitor.state != PING_STATE_TIMER) {
         return;
     }
 
-    rcc->channel->core->timer_cancel(rcc->latency_monitor.timer);
-    rcc->latency_monitor.state = PING_STATE_NONE;
+    rcc->priv->channel->core->timer_cancel(rcc->priv->latency_monitor.timer);
+    rcc->priv->latency_monitor.state = PING_STATE_NONE;
 }
 
 static void red_channel_client_restart_ping_timer(RedChannelClient *rcc)
 {
     uint64_t passed, timeout;
 
-    passed = (spice_get_monotonic_time_ns() - rcc->latency_monitor.last_pong_time) / NSEC_PER_MILLISEC;
+    passed = (spice_get_monotonic_time_ns() - rcc->priv->latency_monitor.last_pong_time) / NSEC_PER_MILLISEC;
     timeout = PING_TEST_IDLE_NET_TIMEOUT_MS;
     if (passed  < PING_TEST_TIMEOUT_MS) {
         timeout += PING_TEST_TIMEOUT_MS - passed;
@@ -103,7 +103,7 @@ static void red_channel_client_restart_ping_timer(RedChannelClient *rcc)
 
 RedChannel* red_channel_client_get_channel(RedChannelClient* rcc)
 {
-    return rcc->channel;
+    return rcc->priv->channel;
 }
 
 IncomingHandler* red_channel_client_get_incoming_handler(RedChannelClient *rcc)
@@ -115,18 +115,18 @@ void red_channel_client_on_output(void *opaque, int n)
 {
     RedChannelClient *rcc = opaque;
 
-    if (rcc->connectivity_monitor.timer) {
-        rcc->connectivity_monitor.out_bytes += n;
+    if (rcc->priv->connectivity_monitor.timer) {
+        rcc->priv->connectivity_monitor.out_bytes += n;
     }
-    stat_inc_counter(reds, rcc->channel->out_bytes_counter, n);
+    stat_inc_counter(reds, rcc->priv->channel->out_bytes_counter, n);
 }
 
 void red_channel_client_on_input(void *opaque, int n)
 {
     RedChannelClient *rcc = opaque;
 
-    if (rcc->connectivity_monitor.timer) {
-        rcc->connectivity_monitor.in_bytes += n;
+    if (rcc->priv->connectivity_monitor.timer) {
+        rcc->priv->connectivity_monitor.in_bytes += n;
     }
 }
 
@@ -134,7 +134,7 @@ int red_channel_client_get_out_msg_size(void *opaque)
 {
     RedChannelClient *rcc = (RedChannelClient *)opaque;
 
-    return rcc->send_data.size;
+    return rcc->priv->send_data.size;
 }
 
 void red_channel_client_prepare_out_msg(void *opaque, struct iovec *vec,
@@ -142,7 +142,7 @@ void red_channel_client_prepare_out_msg(void *opaque, struct iovec *vec,
 {
     RedChannelClient *rcc = (RedChannelClient *)opaque;
 
-    *vec_size = spice_marshaller_fill_iovec(rcc->send_data.marshaller,
+    *vec_size = spice_marshaller_fill_iovec(rcc->priv->send_data.marshaller,
                                             vec, IOV_MAX, pos);
 }
 
@@ -150,46 +150,46 @@ void red_channel_client_on_out_block(void *opaque)
 {
     RedChannelClient *rcc = (RedChannelClient *)opaque;
 
-    rcc->send_data.blocked = TRUE;
-    rcc->channel->core->watch_update_mask(rcc->stream->watch,
-                                     SPICE_WATCH_EVENT_READ |
-                                     SPICE_WATCH_EVENT_WRITE);
+    rcc->priv->send_data.blocked = TRUE;
+    rcc->priv->channel->core->watch_update_mask(rcc->priv->stream->watch,
+                                                SPICE_WATCH_EVENT_READ |
+                                                SPICE_WATCH_EVENT_WRITE);
 }
 
 static inline int red_channel_client_urgent_marshaller_is_active(RedChannelClient *rcc)
 {
-    return (rcc->send_data.marshaller == rcc->send_data.urgent.marshaller);
+    return (rcc->priv->send_data.marshaller == rcc->priv->send_data.urgent.marshaller);
 }
 
 static void red_channel_client_reset_send_data(RedChannelClient *rcc)
 {
-    spice_marshaller_reset(rcc->send_data.marshaller);
-    rcc->send_data.header.data = spice_marshaller_reserve_space(rcc->send_data.marshaller,
-                                                                rcc->send_data.header.header_size);
-    spice_marshaller_set_base(rcc->send_data.marshaller, rcc->send_data.header.header_size);
-    rcc->send_data.header.set_msg_type(&rcc->send_data.header, 0);
-    rcc->send_data.header.set_msg_size(&rcc->send_data.header, 0);
+    spice_marshaller_reset(rcc->priv->send_data.marshaller);
+    rcc->priv->send_data.header.data = spice_marshaller_reserve_space(rcc->priv->send_data.marshaller,
+                                                                      rcc->priv->send_data.header.header_size);
+    spice_marshaller_set_base(rcc->priv->send_data.marshaller, rcc->priv->send_data.header.header_size);
+    rcc->priv->send_data.header.set_msg_type(&rcc->priv->send_data.header, 0);
+    rcc->priv->send_data.header.set_msg_size(&rcc->priv->send_data.header, 0);
 
     /* Keeping the serial consecutive: resetting it if reset_send_data
      * has been called before, but no message has been sent since then.
      */
-    if (rcc->send_data.last_sent_serial != rcc->send_data.serial) {
-        spice_assert(rcc->send_data.serial - rcc->send_data.last_sent_serial == 1);
+    if (rcc->priv->send_data.last_sent_serial != rcc->priv->send_data.serial) {
+        spice_assert(rcc->priv->send_data.serial - rcc->priv->send_data.last_sent_serial == 1);
         /*  When the urgent marshaller is active, the serial was incremented by
          *  the call to reset_send_data that was made for the main marshaller.
          *  The urgent msg receives this serial, and the main msg serial is
-         *  the following one. Thus, (rcc->send_data.serial - rcc->send_data.last_sent_serial)
+         *  the following one. Thus, (rcc->priv->send_data.serial - rcc->priv->send_data.last_sent_serial)
          *  should be 1 in this case*/
         if (!red_channel_client_urgent_marshaller_is_active(rcc)) {
-            rcc->send_data.serial = rcc->send_data.last_sent_serial;
+            rcc->priv->send_data.serial = rcc->priv->send_data.last_sent_serial;
         }
     }
-    rcc->send_data.serial++;
+    rcc->priv->send_data.serial++;
 
-    if (!rcc->is_mini_header) {
-        spice_assert(rcc->send_data.marshaller != rcc->send_data.urgent.marshaller);
-        rcc->send_data.header.set_msg_sub_list(&rcc->send_data.header, 0);
-        rcc->send_data.header.set_msg_serial(&rcc->send_data.header, rcc->send_data.serial);
+    if (!rcc->priv->is_mini_header) {
+        spice_assert(rcc->priv->send_data.marshaller != rcc->priv->send_data.urgent.marshaller);
+        rcc->priv->send_data.header.set_msg_sub_list(&rcc->priv->send_data.header, 0);
+        rcc->priv->send_data.header.set_msg_serial(&rcc->priv->send_data.header, rcc->priv->send_data.serial);
     }
 }
 
@@ -199,11 +199,11 @@ static void red_channel_client_send_set_ack(RedChannelClient *rcc)
 
     spice_assert(rcc);
     red_channel_client_init_send_data(rcc, SPICE_MSG_SET_ACK, NULL);
-    ack.generation = ++rcc->ack_data.generation;
-    ack.window = rcc->ack_data.client_window;
-    rcc->ack_data.messages_window = 0;
+    ack.generation = ++rcc->priv->ack_data.generation;
+    ack.window = rcc->priv->ack_data.client_window;
+    rcc->priv->ack_data.messages_window = 0;
 
-    spice_marshall_msg_set_ack(rcc->send_data.marshaller, &ack);
+    spice_marshall_msg_set_ack(rcc->priv->send_data.marshaller, &ack);
 
     red_channel_client_begin_send_message(rcc);
 }
@@ -213,10 +213,10 @@ static void red_channel_client_send_migrate(RedChannelClient *rcc)
     SpiceMsgMigrate migrate;
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, NULL);
-    migrate.flags = rcc->channel->migration_flags;
-    spice_marshall_msg_migrate(rcc->send_data.marshaller, &migrate);
-    if (rcc->channel->migration_flags & SPICE_MIGRATE_NEED_FLUSH) {
-        rcc->wait_migrate_flush_mark = TRUE;
+    migrate.flags = rcc->priv->channel->migration_flags;
+    spice_marshall_msg_migrate(rcc->priv->send_data.marshaller, &migrate);
+    if (rcc->priv->channel->migration_flags & SPICE_MIGRATE_NEED_FLUSH) {
+        rcc->priv->wait_migrate_flush_mark = TRUE;
     }
 
     red_channel_client_begin_send_message(rcc);
@@ -226,25 +226,25 @@ static void red_channel_client_send_ping(RedChannelClient *rcc)
 {
     SpiceMsgPing ping;
 
-    if (!rcc->latency_monitor.warmup_was_sent) { // latency test start
+    if (!rcc->priv->latency_monitor.warmup_was_sent) { // latency test start
         int delay_val;
         socklen_t opt_size = sizeof(delay_val);
 
-        rcc->latency_monitor.warmup_was_sent = TRUE;
+        rcc->priv->latency_monitor.warmup_was_sent = TRUE;
         /*
          * When testing latency, TCP_NODELAY must be switched on, otherwise,
          * sending the ping message is delayed by Nagle algorithm, and the
          * roundtrip measurment is less accurate (bigger).
          */
-        rcc->latency_monitor.tcp_nodelay = 1;
-        if (getsockopt(rcc->stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
+        rcc->priv->latency_monitor.tcp_nodelay = 1;
+        if (getsockopt(rcc->priv->stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
                        &opt_size) == -1) {
             spice_warning("getsockopt failed, %s", strerror(errno));
         }  else {
-            rcc->latency_monitor.tcp_nodelay = delay_val;
+            rcc->priv->latency_monitor.tcp_nodelay = delay_val;
             if (!delay_val) {
                 delay_val = 1;
-                if (setsockopt(rcc->stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
+                if (setsockopt(rcc->priv->stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
                                sizeof(delay_val)) == -1) {
                    if (errno != ENOTSUP) {
                         spice_warning("setsockopt failed, %s", strerror(errno));
@@ -255,9 +255,9 @@ static void red_channel_client_send_ping(RedChannelClient *rcc)
     }
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_PING, NULL);
-    ping.id = rcc->latency_monitor.id;
+    ping.id = rcc->priv->latency_monitor.id;
     ping.timestamp = spice_get_monotonic_time_ns();
-    spice_marshall_msg_ping(rcc->send_data.marshaller, &ping);
+    spice_marshall_msg_ping(rcc->priv->send_data.marshaller, &ping);
     red_channel_client_begin_send_message(rcc);
 }
 
@@ -289,7 +289,7 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite
         case RED_PIPE_ITEM_TYPE_MARKER:
             break;
         default:
-            rcc->channel->channel_cbs.send_item(rcc, item);
+            rcc->priv->channel->channel_cbs.send_item(rcc, item);
             break;
     }
     red_pipe_item_unref(item);
@@ -297,21 +297,22 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite
 
 static inline void red_channel_client_release_sent_item(RedChannelClient *rcc)
 {
-    if (rcc->send_data.item) {
-        red_pipe_item_unref(rcc->send_data.item);
-        rcc->send_data.item = NULL;
+    if (rcc->priv->send_data.item) {
+        red_pipe_item_unref(rcc->priv->send_data.item);
+        rcc->priv->send_data.item = NULL;
     }
 }
 
 static void red_channel_client_restore_main_sender(RedChannelClient *rcc)
 {
-    spice_marshaller_reset(rcc->send_data.urgent.marshaller);
-    rcc->send_data.marshaller = rcc->send_data.main.marshaller;
-    rcc->send_data.header.data = rcc->send_data.main.header_data;
-    if (!rcc->is_mini_header) {
-        rcc->send_data.header.set_msg_serial(&rcc->send_data.header, rcc->send_data.serial);
+    spice_marshaller_reset(rcc->priv->send_data.urgent.marshaller);
+    rcc->priv->send_data.marshaller = rcc->priv->send_data.main.marshaller;
+    rcc->priv->send_data.header.data = rcc->priv->send_data.main.header_data;
+    if (!rcc->priv->is_mini_header) {
+        rcc->priv->send_data.header.set_msg_serial(&rcc->priv->send_data.header,
+                                                   rcc->priv->send_data.serial);
     }
-    rcc->send_data.item = rcc->send_data.main.item;
+    rcc->priv->send_data.item = rcc->priv->send_data.main.item;
 }
 
 void red_channel_client_on_out_msg_done(void *opaque)
@@ -319,10 +320,10 @@ void red_channel_client_on_out_msg_done(void *opaque)
     RedChannelClient *rcc = (RedChannelClient *)opaque;
     int fd;
 
-    rcc->send_data.size = 0;
+    rcc->priv->send_data.size = 0;
 
-    if (spice_marshaller_get_fd(rcc->send_data.marshaller, &fd)) {
-        if (reds_stream_send_msgfd(rcc->stream, fd) < 0) {
+    if (spice_marshaller_get_fd(rcc->priv->send_data.marshaller, &fd)) {
+        if (reds_stream_send_msgfd(rcc->priv->stream, fd) < 0) {
             perror("sendfd");
             red_channel_client_disconnect(rcc);
             if (fd != -1)
@@ -334,18 +335,20 @@ void red_channel_client_on_out_msg_done(void *opaque)
     }
 
     red_channel_client_release_sent_item(rcc);
-    if (rcc->send_data.blocked) {
-        rcc->send_data.blocked = FALSE;
-        rcc->channel->core->watch_update_mask(rcc->stream->watch,
-                                         SPICE_WATCH_EVENT_READ);
+    if (rcc->priv->send_data.blocked) {
+        rcc->priv->send_data.blocked = FALSE;
+        rcc->priv->channel->core->watch_update_mask(rcc->priv->stream->watch,
+                                                    SPICE_WATCH_EVENT_READ);
     }
 
     if (red_channel_client_urgent_marshaller_is_active(rcc)) {
         red_channel_client_restore_main_sender(rcc);
-        spice_assert(rcc->send_data.header.data != NULL);
+        spice_assert(rcc->priv->send_data.header.data != NULL);
         red_channel_client_begin_send_message(rcc);
     } else {
-        if (rcc->latency_monitor.timer && !rcc->send_data.blocked && rcc->pipe_size == 0) {
+        if (rcc->priv->latency_monitor.timer
+            && !rcc->priv->send_data.blocked
+            && rcc->priv->pipe_size == 0) {
             /* It is possible that the socket will become idle, so we may be able to test latency */
             red_channel_client_restart_ping_timer(rcc);
         }
@@ -355,7 +358,7 @@ void red_channel_client_on_out_msg_done(void *opaque)
 
 static void red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeItem *item)
 {
-    rcc->pipe_size--;
+    rcc->priv->pipe_size--;
     ring_remove(&item->link);
 }
 
@@ -363,41 +366,43 @@ static void red_channel_client_set_remote_caps(RedChannelClient* rcc,
                                                int num_common_caps, uint32_t *common_caps,
                                                int num_caps, uint32_t *caps)
 {
-    rcc->remote_caps.num_common_caps = num_common_caps;
-    rcc->remote_caps.common_caps = spice_memdup(common_caps, num_common_caps * sizeof(uint32_t));
+    rcc->priv->remote_caps.num_common_caps = num_common_caps;
+    rcc->priv->remote_caps.common_caps = spice_memdup(common_caps,
+                                                      num_common_caps *
+                                                      sizeof(uint32_t));
 
-    rcc->remote_caps.num_caps = num_caps;
-    rcc->remote_caps.caps = spice_memdup(caps, num_caps * sizeof(uint32_t));
+    rcc->priv->remote_caps.num_caps = num_caps;
+    rcc->priv->remote_caps.caps = spice_memdup(caps, num_caps * sizeof(uint32_t));
 }
 
 static void red_channel_client_destroy_remote_caps(RedChannelClient* rcc)
 {
-    rcc->remote_caps.num_common_caps = 0;
-    free(rcc->remote_caps.common_caps);
-    rcc->remote_caps.num_caps = 0;
-    free(rcc->remote_caps.caps);
+    rcc->priv->remote_caps.num_common_caps = 0;
+    free(rcc->priv->remote_caps.common_caps);
+    rcc->priv->remote_caps.num_caps = 0;
+    free(rcc->priv->remote_caps.caps);
 }
 
 int red_channel_client_test_remote_common_cap(RedChannelClient *rcc, uint32_t cap)
 {
-    return test_capability(rcc->remote_caps.common_caps,
-                           rcc->remote_caps.num_common_caps,
+    return test_capability(rcc->priv->remote_caps.common_caps,
+                           rcc->priv->remote_caps.num_common_caps,
                            cap);
 }
 
 int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap)
 {
-    return test_capability(rcc->remote_caps.caps,
-                           rcc->remote_caps.num_caps,
+    return test_capability(rcc->priv->remote_caps.caps,
+                           rcc->priv->remote_caps.num_caps,
                            cap);
 }
 
 static void red_channel_client_push_ping(RedChannelClient *rcc)
 {
-    spice_assert(rcc->latency_monitor.state == PING_STATE_NONE);
-    rcc->latency_monitor.state = PING_STATE_WARMUP;
-    rcc->latency_monitor.warmup_was_sent = FALSE;
-    rcc->latency_monitor.id = rand();
+    spice_assert(rcc->priv->latency_monitor.state == PING_STATE_NONE);
+    rcc->priv->latency_monitor.state = PING_STATE_WARMUP;
+    rcc->priv->latency_monitor.warmup_was_sent = FALSE;
+    rcc->priv->latency_monitor.id = rand();
     red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_PING);
     red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_PING);
 }
@@ -406,7 +411,7 @@ static void red_channel_client_ping_timer(void *opaque)
 {
     RedChannelClient *rcc = opaque;
 
-    spice_assert(rcc->latency_monitor.state == PING_STATE_TIMER);
+    spice_assert(rcc->priv->latency_monitor.state == PING_STATE_TIMER);
     red_channel_client_cancel_ping_timer(rcc);
 
 #ifdef HAVE_LINUX_SOCKIOS_H /* SIOCOUTQ is a Linux only ioctl on sockets. */
@@ -414,7 +419,7 @@ static void red_channel_client_ping_timer(void *opaque)
         int so_unsent_size = 0;
 
         /* retrieving the occupied size of the socket's tcp snd buffer (unacked + unsent) */
-        if (ioctl(rcc->stream->socket, SIOCOUTQ, &so_unsent_size) == -1) {
+        if (ioctl(rcc->priv->stream->socket, SIOCOUTQ, &so_unsent_size) == -1) {
             spice_printerr("ioctl(SIOCOUTQ) failed, %s", strerror(errno));
         }
         if (so_unsent_size > 0) {
@@ -432,8 +437,8 @@ static void red_channel_client_ping_timer(void *opaque)
 
 static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc)
 {
-    return (rcc->channel->handle_acks &&
-            (rcc->ack_data.messages_window > rcc->ack_data.client_window * 2));
+    return (rcc->priv->channel->handle_acks &&
+            (rcc->priv->ack_data.messages_window > rcc->priv->ack_data.client_window * 2));
 }
 
 /*
@@ -451,12 +456,12 @@ static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc)
 static void red_channel_client_connectivity_timer(void *opaque)
 {
     RedChannelClient *rcc = opaque;
-    RedChannelClientConnectivityMonitor *monitor = &rcc->connectivity_monitor;
+    RedChannelClientConnectivityMonitor *monitor = &rcc->priv->connectivity_monitor;
     int is_alive = TRUE;
 
     if (monitor->state == CONNECTIVITY_STATE_BLOCKED) {
         if (monitor->in_bytes == 0 && monitor->out_bytes == 0) {
-            if (!rcc->send_data.blocked && !red_channel_client_waiting_for_ack(rcc)) {
+            if (!rcc->priv->send_data.blocked && !red_channel_client_waiting_for_ack(rcc)) {
                 spice_error("mismatch between rcc-state and connectivity-state");
             }
             spice_debug("rcc is blocked; connection is idle");
@@ -464,8 +469,8 @@ static void red_channel_client_connectivity_timer(void *opaque)
         }
     } else if (monitor->state == CONNECTIVITY_STATE_WAIT_PONG) {
         if (monitor->in_bytes == 0) {
-            if (rcc->latency_monitor.state != PING_STATE_WARMUP &&
-                rcc->latency_monitor.state != PING_STATE_LATENCY) {
+            if (rcc->priv->latency_monitor.state != PING_STATE_WARMUP &&
+                rcc->priv->latency_monitor.state != PING_STATE_LATENCY) {
                 spice_error("mismatch between rcc-state and connectivity-state");
             }
             spice_debug("rcc waits for pong; connection is idle");
@@ -476,20 +481,20 @@ static void red_channel_client_connectivity_timer(void *opaque)
     if (is_alive) {
         monitor->in_bytes = 0;
         monitor->out_bytes = 0;
-        if (rcc->send_data.blocked || red_channel_client_waiting_for_ack(rcc)) {
+        if (rcc->priv->send_data.blocked || red_channel_client_waiting_for_ack(rcc)) {
             monitor->state = CONNECTIVITY_STATE_BLOCKED;
-        } else if (rcc->latency_monitor.state == PING_STATE_WARMUP ||
-                   rcc->latency_monitor.state == PING_STATE_LATENCY) {
+        } else if (rcc->priv->latency_monitor.state == PING_STATE_WARMUP ||
+                   rcc->priv->latency_monitor.state == PING_STATE_LATENCY) {
             monitor->state = CONNECTIVITY_STATE_WAIT_PONG;
         } else {
              monitor->state = CONNECTIVITY_STATE_CONNECTED;
         }
-        rcc->channel->core->timer_start(rcc->connectivity_monitor.timer,
-                                        rcc->connectivity_monitor.timeout);
+        rcc->priv->channel->core->timer_start(rcc->priv->connectivity_monitor.timer,
+                                              rcc->priv->connectivity_monitor.timeout);
     } else {
         monitor->state = CONNECTIVITY_STATE_DISCONNECTED;
         spice_warning("rcc %p on channel %d:%d has been unresponsive for more than %u ms, disconnecting",
-                      rcc, rcc->channel->type, rcc->channel->id, monitor->timeout);
+                      rcc, rcc->priv->channel->type, rcc->priv->channel->id, monitor->timeout);
         red_channel_client_disconnect(rcc);
     }
 }
@@ -507,22 +512,22 @@ void red_channel_client_start_connectivity_monitoring(RedChannelClient *rcc, uin
      * channel-client even if there are no ongoing channel specific messages
      * on this channel.
      */
-    if (rcc->latency_monitor.timer == NULL) {
-        rcc->latency_monitor.timer = rcc->channel->core->timer_add(
-            rcc->channel->core, red_channel_client_ping_timer, rcc);
-        if (!red_client_during_migrate_at_target(rcc->client)) {
+    if (rcc->priv->latency_monitor.timer == NULL) {
+        rcc->priv->latency_monitor.timer = rcc->priv->channel->core->timer_add(
+            rcc->priv->channel->core, red_channel_client_ping_timer, rcc);
+        if (!red_client_during_migrate_at_target(rcc->priv->client)) {
             red_channel_client_start_ping_timer(rcc, PING_TEST_IDLE_NET_TIMEOUT_MS);
         }
-        rcc->latency_monitor.roundtrip = -1;
-    }
-    if (rcc->connectivity_monitor.timer == NULL) {
-        rcc->connectivity_monitor.state = CONNECTIVITY_STATE_CONNECTED;
-        rcc->connectivity_monitor.timer = rcc->channel->core->timer_add(
-            rcc->channel->core, red_channel_client_connectivity_timer, rcc);
-        rcc->connectivity_monitor.timeout = timeout_ms;
-        if (!red_client_during_migrate_at_target(rcc->client)) {
-           rcc->channel->core->timer_start(rcc->connectivity_monitor.timer,
-                                           rcc->connectivity_monitor.timeout);
+        rcc->priv->latency_monitor.roundtrip = -1;
+    }
+    if (rcc->priv->connectivity_monitor.timer == NULL) {
+        rcc->priv->connectivity_monitor.state = CONNECTIVITY_STATE_CONNECTED;
+        rcc->priv->connectivity_monitor.timer = rcc->priv->channel->core->timer_add(
+            rcc->priv->channel->core, red_channel_client_connectivity_timer, rcc);
+        rcc->priv->connectivity_monitor.timeout = timeout_ms;
+        if (!red_client_during_migrate_at_target(rcc->priv->client)) {
+           rcc->priv->channel->core->timer_start(rcc->priv->connectivity_monitor.timer,
+                                                 rcc->priv->connectivity_monitor.timeout);
         }
     }
 }
@@ -641,18 +646,19 @@ RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedCl
     }
     spice_assert(stream && channel && size >= sizeof(RedChannelClient));
     rcc = spice_malloc0(size);
-    rcc->stream = stream;
-    rcc->channel = channel;
-    rcc->client = client;
-    rcc->refs = 1;
-    rcc->ack_data.messages_window = ~0;  // blocks send message (maybe use send_data.blocked +
-                                             // block flags)
-    rcc->ack_data.client_generation = ~0;
-    rcc->ack_data.client_window = CLIENT_ACK_WINDOW;
-    rcc->send_data.main.marshaller = spice_marshaller_new();
-    rcc->send_data.urgent.marshaller = spice_marshaller_new();
-
-    rcc->send_data.marshaller = rcc->send_data.main.marshaller;
+    rcc->priv = g_new0(RedChannelClientPrivate, 1);
+    rcc->priv->stream = stream;
+    rcc->priv->channel = channel;
+    rcc->priv->client = client;
+    rcc->priv->refs = 1;
+    rcc->priv->ack_data.messages_window = ~0;  // blocks send message (maybe use send_data.blocked +
+                                               // block flags)
+    rcc->priv->ack_data.client_generation = ~0;
+    rcc->priv->ack_data.client_window = CLIENT_ACK_WINDOW;
+    rcc->priv->send_data.main.marshaller = spice_marshaller_new();
+    rcc->priv->send_data.urgent.marshaller = spice_marshaller_new();
+
+    rcc->priv->send_data.marshaller = rcc->priv->send_data.main.marshaller;
 
     rcc->incoming.opaque = rcc;
     rcc->incoming.cb = &channel->incoming_cb;
@@ -665,12 +671,12 @@ RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedCl
     red_channel_client_set_remote_caps(rcc, num_common_caps, common_caps, num_caps, caps);
     if (red_channel_client_test_remote_common_cap(rcc, SPICE_COMMON_CAP_MINI_HEADER)) {
         rcc->incoming.header = mini_header_wrapper;
-        rcc->send_data.header = mini_header_wrapper;
-        rcc->is_mini_header = TRUE;
+        rcc->priv->send_data.header = mini_header_wrapper;
+        rcc->priv->is_mini_header = TRUE;
     } else {
         rcc->incoming.header = full_header_wrapper;
-        rcc->send_data.header = full_header_wrapper;
-        rcc->is_mini_header = FALSE;
+        rcc->priv->send_data.header = full_header_wrapper;
+        rcc->priv->is_mini_header = FALSE;
     }
 
     rcc->incoming.header.data = rcc->incoming.header_buf;
@@ -680,26 +686,26 @@ RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedCl
         goto error;
     }
 
-    ring_init(&rcc->pipe);
-    rcc->pipe_size = 0;
+    ring_init(&rcc->priv->pipe);
+    rcc->priv->pipe_size = 0;
 
     stream->watch = channel->core->watch_add(channel->core,
                                            stream->socket,
                                            SPICE_WATCH_EVENT_READ,
                                            red_channel_client_event, rcc);
-    rcc->id = g_list_length(channel->clients);
+    rcc->priv->id = g_list_length(channel->clients);
     red_channel_add_client(channel, rcc);
     red_client_add_channel(client, rcc);
     red_channel_ref(channel);
     pthread_mutex_unlock(&client->lock);
 
     if (monitor_latency && reds_stream_get_family(stream) != AF_UNIX) {
-        rcc->latency_monitor.timer = channel->core->timer_add(
+        rcc->priv->latency_monitor.timer = channel->core->timer_add(
             channel->core, red_channel_client_ping_timer, rcc);
         if (!client->during_target_migrate) {
             red_channel_client_start_ping_timer(rcc, PING_TEST_IDLE_NET_TIMEOUT_MS);
         }
-        rcc->latency_monitor.roundtrip = -1;
+        rcc->priv->latency_monitor.roundtrip = -1;
     }
 
     return rcc;
@@ -725,27 +731,28 @@ RedChannelClient *red_channel_client_create_dummy(int size,
         goto error;
     }
     rcc = spice_malloc0(size);
-    rcc->refs = 1;
-    rcc->client = client;
-    rcc->channel = channel;
+    rcc->priv = g_new0(RedChannelClientPrivate, 1);
+    rcc->priv->refs = 1;
+    rcc->priv->client = client;
+    rcc->priv->channel = channel;
     red_channel_ref(channel);
     red_channel_client_set_remote_caps(rcc, num_common_caps, common_caps, num_caps, caps);
     if (red_channel_client_test_remote_common_cap(rcc, SPICE_COMMON_CAP_MINI_HEADER)) {
         rcc->incoming.header = mini_header_wrapper;
-        rcc->send_data.header = mini_header_wrapper;
-        rcc->is_mini_header = TRUE;
+        rcc->priv->send_data.header = mini_header_wrapper;
+        rcc->priv->is_mini_header = TRUE;
     } else {
         rcc->incoming.header = full_header_wrapper;
-        rcc->send_data.header = full_header_wrapper;
-        rcc->is_mini_header = FALSE;
+        rcc->priv->send_data.header = full_header_wrapper;
+        rcc->priv->is_mini_header = FALSE;
     }
 
     rcc->incoming.header.data = rcc->incoming.header_buf;
     rcc->incoming.serial = 1;
-    ring_init(&rcc->pipe);
+    ring_init(&rcc->priv->pipe);
 
-    rcc->dummy = TRUE;
-    rcc->dummy_connected = TRUE;
+    rcc->priv->dummy = TRUE;
+    rcc->priv->dummy_connected = TRUE;
     red_channel_add_client(channel, rcc);
     red_client_add_channel(client, rcc);
     pthread_mutex_unlock(&client->lock);
@@ -757,79 +764,79 @@ error:
 
 void red_channel_client_seamless_migration_done(RedChannelClient *rcc)
 {
-    rcc->wait_migrate_data = FALSE;
+    rcc->priv->wait_migrate_data = FALSE;
 
-    if (red_client_seamless_migration_done_for_channel(rcc->client)) {
-        if (rcc->latency_monitor.timer) {
+    if (red_client_seamless_migration_done_for_channel(rcc->priv->client)) {
+        if (rcc->priv->latency_monitor.timer) {
             red_channel_client_start_ping_timer(rcc, PING_TEST_IDLE_NET_TIMEOUT_MS);
         }
-        if (rcc->connectivity_monitor.timer) {
-            rcc->channel->core->timer_start(rcc->connectivity_monitor.timer,
-                                            rcc->connectivity_monitor.timeout);
+        if (rcc->priv->connectivity_monitor.timer) {
+            rcc->priv->channel->core->timer_start(rcc->priv->connectivity_monitor.timer,
+                                                  rcc->priv->connectivity_monitor.timeout);
         }
     }
 }
 
 void red_channel_client_semi_seamless_migration_complete(RedChannelClient *rcc)
 {
-    if (rcc->latency_monitor.timer) {
+    if (rcc->priv->latency_monitor.timer) {
         red_channel_client_start_ping_timer(rcc, PING_TEST_IDLE_NET_TIMEOUT_MS);
     }
 }
 
 int red_channel_client_is_waiting_for_migrate_data(RedChannelClient *rcc)
 {
-    return rcc->wait_migrate_data;
+    return rcc->priv->wait_migrate_data;
 }
 
 void red_channel_client_default_migrate(RedChannelClient *rcc)
 {
-    if (rcc->latency_monitor.timer) {
+    if (rcc->priv->latency_monitor.timer) {
         red_channel_client_cancel_ping_timer(rcc);
-        rcc->channel->core->timer_remove(rcc->latency_monitor.timer);
-        rcc->latency_monitor.timer = NULL;
+        rcc->priv->channel->core->timer_remove(rcc->priv->latency_monitor.timer);
+        rcc->priv->latency_monitor.timer = NULL;
     }
-    if (rcc->connectivity_monitor.timer) {
-       rcc->channel->core->timer_remove(rcc->connectivity_monitor.timer);
-        rcc->connectivity_monitor.timer = NULL;
+    if (rcc->priv->connectivity_monitor.timer) {
+       rcc->priv->channel->core->timer_remove(rcc->priv->connectivity_monitor.timer);
+        rcc->priv->connectivity_monitor.timer = NULL;
     }
     red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_MIGRATE);
 }
 
 void red_channel_client_ref(RedChannelClient *rcc)
 {
-    rcc->refs++;
+    rcc->priv->refs++;
 }
 
 void red_channel_client_unref(RedChannelClient *rcc)
 {
-    if (--rcc->refs != 0) {
+    if (--rcc->priv->refs != 0) {
         return;
     }
 
     spice_debug("destroy rcc=%p", rcc);
 
-    reds_stream_free(rcc->stream);
-    rcc->stream = NULL;
+    reds_stream_free(rcc->priv->stream);
+    rcc->priv->stream = NULL;
 
-    if (rcc->send_data.main.marshaller) {
-        spice_marshaller_destroy(rcc->send_data.main.marshaller);
+    if (rcc->priv->send_data.main.marshaller) {
+        spice_marshaller_destroy(rcc->priv->send_data.main.marshaller);
     }
 
-    if (rcc->send_data.urgent.marshaller) {
-        spice_marshaller_destroy(rcc->send_data.urgent.marshaller);
+    if (rcc->priv->send_data.urgent.marshaller) {
+        spice_marshaller_destroy(rcc->priv->send_data.urgent.marshaller);
     }
 
     red_channel_client_destroy_remote_caps(rcc);
-    if (rcc->channel) {
-        red_channel_unref(rcc->channel);
+    if (rcc->priv->channel) {
+        red_channel_unref(rcc->priv->channel);
     }
     free(rcc);
 }
 
 void red_channel_client_destroy(RedChannelClient *rcc)
 {
-    rcc->destroying = TRUE;
+    rcc->priv->destroying = TRUE;
     red_channel_client_disconnect(rcc);
     red_client_remove_channel(rcc);
     red_channel_client_unref(rcc);
@@ -837,11 +844,11 @@ void red_channel_client_destroy(RedChannelClient *rcc)
 
 void red_channel_client_shutdown(RedChannelClient *rcc)
 {
-    if (rcc->stream && !rcc->stream->shutdown) {
-        rcc->channel->core->watch_remove(rcc->stream->watch);
-        rcc->stream->watch = NULL;
-        shutdown(rcc->stream->socket, SHUT_RDWR);
-        rcc->stream->shutdown = TRUE;
+    if (rcc->priv->stream && !rcc->priv->stream->shutdown) {
+        rcc->priv->channel->core->watch_remove(rcc->priv->stream->watch);
+        rcc->priv->stream->watch = NULL;
+        shutdown(rcc->priv->stream->socket, SHUT_RDWR);
+        rcc->priv->stream->shutdown = TRUE;
     }
 }
 
@@ -1025,14 +1032,14 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
 void red_channel_client_receive(RedChannelClient *rcc)
 {
     red_channel_client_ref(rcc);
-    red_peer_handle_incoming(rcc->stream, &rcc->incoming);
+    red_peer_handle_incoming(rcc->priv->stream, &rcc->incoming);
     red_channel_client_unref(rcc);
 }
 
 void red_channel_client_send(RedChannelClient *rcc)
 {
     red_channel_client_ref(rcc);
-    red_peer_handle_outgoing(rcc->stream, &rcc->outgoing);
+    red_peer_handle_outgoing(rcc->priv->stream, &rcc->outgoing);
     red_channel_client_unref(rcc);
 }
 
@@ -1040,9 +1047,9 @@ static inline RedPipeItem *red_channel_client_pipe_item_get(RedChannelClient *rc
 {
     RedPipeItem *item;
 
-    if (!rcc || rcc->send_data.blocked
+    if (!rcc || rcc->priv->send_data.blocked
              || red_channel_client_waiting_for_ack(rcc)
-             || !(item = (RedPipeItem *)ring_get_tail(&rcc->pipe))) {
+             || !(item = (RedPipeItem *)ring_get_tail(&rcc->priv->pipe))) {
         return NULL;
     }
     red_channel_client_pipe_remove(rcc, item);
@@ -1053,44 +1060,44 @@ void red_channel_client_push(RedChannelClient *rcc)
 {
     RedPipeItem *pipe_item;
 
-    if (!rcc->during_send) {
-        rcc->during_send = TRUE;
+    if (!rcc->priv->during_send) {
+        rcc->priv->during_send = TRUE;
     } else {
         return;
     }
     red_channel_client_ref(rcc);
-    if (rcc->send_data.blocked) {
+    if (rcc->priv->send_data.blocked) {
         red_channel_client_send(rcc);
     }
 
-    if (!red_channel_client_no_item_being_sent(rcc) && !rcc->send_data.blocked) {
-        rcc->send_data.blocked = TRUE;
+    if (!red_channel_client_no_item_being_sent(rcc) && !rcc->priv->send_data.blocked) {
+        rcc->priv->send_data.blocked = TRUE;
         spice_printerr("ERROR: an item waiting to be sent and not blocked");
     }
 
     while ((pipe_item = red_channel_client_pipe_item_get(rcc))) {
         red_channel_client_send_item(rcc, pipe_item);
     }
-    if (red_channel_client_no_item_being_sent(rcc) && ring_is_empty(&rcc->pipe)
-        && rcc->stream->watch) {
-        rcc->channel->core->watch_update_mask(rcc->stream->watch,
-                                              SPICE_WATCH_EVENT_READ);
+    if (red_channel_client_no_item_being_sent(rcc) && ring_is_empty(&rcc->priv->pipe)
+        && rcc->priv->stream->watch) {
+        rcc->priv->channel->core->watch_update_mask(rcc->priv->stream->watch,
+                                                    SPICE_WATCH_EVENT_READ);
     }
-    rcc->during_send = FALSE;
+    rcc->priv->during_send = FALSE;
     red_channel_client_unref(rcc);
 }
 
 int red_channel_client_get_roundtrip_ms(RedChannelClient *rcc)
 {
-    if (rcc->latency_monitor.roundtrip < 0) {
-        return rcc->latency_monitor.roundtrip;
+    if (rcc->priv->latency_monitor.roundtrip < 0) {
+        return rcc->priv->latency_monitor.roundtrip;
     }
-    return rcc->latency_monitor.roundtrip / NSEC_PER_MILLISEC;
+    return rcc->priv->latency_monitor.roundtrip / NSEC_PER_MILLISEC;
 }
 
 void red_channel_client_init_outgoing_messages_window(RedChannelClient *rcc)
 {
-    rcc->ack_data.messages_window = 0;
+    rcc->priv->ack_data.messages_window = 0;
     red_channel_client_push(rcc);
 }
 
@@ -1100,27 +1107,27 @@ static void red_channel_client_handle_pong(RedChannelClient *rcc, SpiceMsgPing *
 
     /* ignoring unexpected pongs, or post-migration pongs for pings that
      * started just before migration */
-    if (ping->id != rcc->latency_monitor.id) {
+    if (ping->id != rcc->priv->latency_monitor.id) {
         spice_warning("ping-id (%u)!= pong-id %u",
-                      rcc->latency_monitor.id, ping->id);
+                      rcc->priv->latency_monitor.id, ping->id);
         return;
     }
 
     now = spice_get_monotonic_time_ns();
 
-    if (rcc->latency_monitor.state == PING_STATE_WARMUP) {
-        rcc->latency_monitor.state = PING_STATE_LATENCY;
+    if (rcc->priv->latency_monitor.state == PING_STATE_WARMUP) {
+        rcc->priv->latency_monitor.state = PING_STATE_LATENCY;
         return;
-    } else if (rcc->latency_monitor.state != PING_STATE_LATENCY) {
+    } else if (rcc->priv->latency_monitor.state != PING_STATE_LATENCY) {
         spice_warning("unexpected");
         return;
     }
 
     /* set TCP_NODELAY=0, in case we reverted it for the test*/
-    if (!rcc->latency_monitor.tcp_nodelay) {
+    if (!rcc->priv->latency_monitor.tcp_nodelay) {
         int delay_val = 0;
 
-        if (setsockopt(rcc->stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
+        if (setsockopt(rcc->priv->stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
                        sizeof(delay_val)) == -1) {
             if (errno != ENOTSUP) {
                 spice_warning("setsockopt failed, %s", strerror(errno));
@@ -1134,14 +1141,14 @@ static void red_channel_client_handle_pong(RedChannelClient *rcc, SpiceMsgPing *
      *  threads or processes that are utilizing the network. We update the roundtrip
      *  measurement with the minimal value we encountered till now.
      */
-    if (rcc->latency_monitor.roundtrip < 0 ||
-        now - ping->timestamp < rcc->latency_monitor.roundtrip) {
-        rcc->latency_monitor.roundtrip = now - ping->timestamp;
-        spice_debug("update roundtrip %.2f(ms)", ((double)rcc->latency_monitor.roundtrip)/NSEC_PER_MILLISEC);
+    if (rcc->priv->latency_monitor.roundtrip < 0 ||
+        now - ping->timestamp < rcc->priv->latency_monitor.roundtrip) {
+        rcc->priv->latency_monitor.roundtrip = now - ping->timestamp;
+        spice_debug("update roundtrip %.2f(ms)", ((double)rcc->priv->latency_monitor.roundtrip)/NSEC_PER_MILLISEC);
     }
 
-    rcc->latency_monitor.last_pong_time = now;
-    rcc->latency_monitor.state = PING_STATE_NONE;
+    rcc->priv->latency_monitor.last_pong_time = now;
+    rcc->priv->latency_monitor.state = PING_STATE_NONE;
     red_channel_client_start_ping_timer(rcc, PING_TEST_TIMEOUT_MS);
 }
 
@@ -1193,23 +1200,23 @@ int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
             spice_printerr("bad message size");
             return FALSE;
         }
-        rcc->ack_data.client_generation = *(uint32_t *)(message);
+        rcc->priv->ack_data.client_generation = *(uint32_t *)(message);
         break;
     case SPICE_MSGC_ACK:
-        if (rcc->ack_data.client_generation == rcc->ack_data.generation) {
-            rcc->ack_data.messages_window -= rcc->ack_data.client_window;
+        if (rcc->priv->ack_data.client_generation == rcc->priv->ack_data.generation) {
+            rcc->priv->ack_data.messages_window -= rcc->priv->ack_data.client_window;
             red_channel_client_push(rcc);
         }
         break;
     case SPICE_MSGC_DISCONNECTING:
         break;
     case SPICE_MSGC_MIGRATE_FLUSH_MARK:
-        if (!rcc->wait_migrate_flush_mark) {
+        if (!rcc->priv->wait_migrate_flush_mark) {
             spice_error("unexpected flush mark");
             return FALSE;
         }
         red_channel_handle_migrate_flush_mark(rcc);
-        rcc->wait_migrate_flush_mark = FALSE;
+        rcc->priv->wait_migrate_flush_mark = FALSE;
         break;
     case SPICE_MSGC_MIGRATE_DATA:
         red_channel_handle_migrate_data(rcc, size, message);
@@ -1228,8 +1235,8 @@ void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type,
 {
     spice_assert(red_channel_client_no_item_being_sent(rcc));
     spice_assert(msg_type != 0);
-    rcc->send_data.header.set_msg_type(&rcc->send_data.header, msg_type);
-    rcc->send_data.item = item;
+    rcc->priv->send_data.header.set_msg_type(&rcc->priv->send_data.header, msg_type);
+    rcc->priv->send_data.item = item;
     if (item) {
         red_pipe_item_ref(item);
     }
@@ -1237,10 +1244,10 @@ void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type,
 
 void red_channel_client_begin_send_message(RedChannelClient *rcc)
 {
-    SpiceMarshaller *m = rcc->send_data.marshaller;
+    SpiceMarshaller *m = rcc->priv->send_data.marshaller;
 
     // TODO - better check: type in channel_allowed_types. Better: type in channel_allowed_types(channel_state)
-    if (rcc->send_data.header.get_msg_type(&rcc->send_data.header) == 0) {
+    if (rcc->priv->send_data.header.get_msg_type(&rcc->priv->send_data.header) == 0) {
         spice_printerr("BUG: header->type == 0");
         return;
     }
@@ -1249,37 +1256,38 @@ void red_channel_client_begin_send_message(RedChannelClient *rcc)
     red_channel_client_cancel_ping_timer(rcc);
 
     spice_marshaller_flush(m);
-    rcc->send_data.size = spice_marshaller_get_total_size(m);
-    rcc->send_data.header.set_msg_size(&rcc->send_data.header,
-                                       rcc->send_data.size - rcc->send_data.header.header_size);
-    rcc->ack_data.messages_window++;
-    rcc->send_data.last_sent_serial = rcc->send_data.serial;
-    rcc->send_data.header.data = NULL; /* avoid writing to this until we have a new message */
+    rcc->priv->send_data.size = spice_marshaller_get_total_size(m);
+    rcc->priv->send_data.header.set_msg_size(&rcc->priv->send_data.header,
+                                             rcc->priv->send_data.size -
+                                             rcc->priv->send_data.header.header_size);
+    rcc->priv->ack_data.messages_window++;
+    rcc->priv->send_data.last_sent_serial = rcc->priv->send_data.serial;
+    rcc->priv->send_data.header.data = NULL; /* avoid writing to this until we have a new message */
     red_channel_client_send(rcc);
 }
 
 SpiceMarshaller *red_channel_client_switch_to_urgent_sender(RedChannelClient *rcc)
 {
     spice_assert(red_channel_client_no_item_being_sent(rcc));
-    spice_assert(rcc->send_data.header.data != NULL);
-    rcc->send_data.main.header_data = rcc->send_data.header.data;
-    rcc->send_data.main.item = rcc->send_data.item;
+    spice_assert(rcc->priv->send_data.header.data != NULL);
+    rcc->priv->send_data.main.header_data = rcc->priv->send_data.header.data;
+    rcc->priv->send_data.main.item = rcc->priv->send_data.item;
 
-    rcc->send_data.marshaller = rcc->send_data.urgent.marshaller;
-    rcc->send_data.item = NULL;
+    rcc->priv->send_data.marshaller = rcc->priv->send_data.urgent.marshaller;
+    rcc->priv->send_data.item = NULL;
     red_channel_client_reset_send_data(rcc);
-    return rcc->send_data.marshaller;
+    return rcc->priv->send_data.marshaller;
 }
 
 uint64_t red_channel_client_get_message_serial(RedChannelClient *rcc)
 {
-    return rcc->send_data.serial;
+    return rcc->priv->send_data.serial;
 }
 
 void red_channel_client_set_message_serial(RedChannelClient *rcc, uint64_t serial)
 {
-    rcc->send_data.last_sent_serial = serial;
-    rcc->send_data.serial = serial;
+    rcc->priv->send_data.last_sent_serial = serial;
+    rcc->priv->send_data.serial = serial;
 }
 
 static inline gboolean client_pipe_add(RedChannelClient *rcc, RedPipeItem *item, RingItem *pos)
@@ -1290,12 +1298,12 @@ static inline gboolean client_pipe_add(RedChannelClient *rcc, RedPipeItem *item,
         red_pipe_item_unref(item);
         return FALSE;
     }
-    if (ring_is_empty(&rcc->pipe) && rcc->stream->watch) {
-        rcc->channel->core->watch_update_mask(rcc->stream->watch,
-                                         SPICE_WATCH_EVENT_READ |
-                                         SPICE_WATCH_EVENT_WRITE);
+    if (ring_is_empty(&rcc->priv->pipe) && rcc->priv->stream->watch) {
+        rcc->priv->channel->core->watch_update_mask(rcc->priv->stream->watch,
+                                                    SPICE_WATCH_EVENT_READ |
+                                                    SPICE_WATCH_EVENT_WRITE);
     }
-    rcc->pipe_size++;
+    rcc->priv->pipe_size++;
     ring_add(pos, &item->link);
     return TRUE;
 }
@@ -1303,7 +1311,7 @@ static inline gboolean client_pipe_add(RedChannelClient *rcc, RedPipeItem *item,
 void red_channel_client_pipe_add(RedChannelClient *rcc, RedPipeItem *item)
 {
 
-    client_pipe_add(rcc, item, &rcc->pipe);
+    client_pipe_add(rcc, item, &rcc->priv->pipe);
 }
 
 void red_channel_client_pipe_add_push(RedChannelClient *rcc, RedPipeItem *item)
@@ -1329,12 +1337,12 @@ int red_channel_client_pipe_item_is_linked(RedChannelClient *rcc,
 void red_channel_client_pipe_add_tail(RedChannelClient *rcc,
                                       RedPipeItem *item)
 {
-    client_pipe_add(rcc, item, rcc->pipe.prev);
+    client_pipe_add(rcc, item, rcc->priv->pipe.prev);
 }
 
 void red_channel_client_pipe_add_tail_and_push(RedChannelClient *rcc, RedPipeItem *item)
 {
-    if (client_pipe_add(rcc, item, rcc->pipe.prev)) {
+    if (client_pipe_add(rcc, item, rcc->priv->pipe.prev)) {
         red_channel_client_push(rcc);
     }
 }
@@ -1361,29 +1369,29 @@ void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type)
 gboolean red_channel_client_pipe_is_empty(RedChannelClient *rcc)
 {
     g_return_val_if_fail(rcc != NULL, TRUE);
-    return (rcc->pipe_size == 0) && (ring_is_empty(&rcc->pipe));
+    return (rcc->priv->pipe_size == 0) && (ring_is_empty(&rcc->priv->pipe));
 }
 
 uint32_t red_channel_client_get_pipe_size(RedChannelClient *rcc)
 {
-    return rcc->pipe_size;
+    return rcc->priv->pipe_size;
 }
 
 int red_channel_client_is_connected(RedChannelClient *rcc)
 {
-    if (!rcc->dummy) {
-        return rcc->channel
-            && (g_list_find(rcc->channel->clients, rcc) != NULL);
+    if (!rcc->priv->dummy) {
+        return rcc->priv->channel
+            && (g_list_find(rcc->priv->channel->clients, rcc) != NULL);
     } else {
-        return rcc->dummy_connected;
+        return rcc->priv->dummy_connected;
     }
 }
 
 static void red_channel_client_clear_sent_item(RedChannelClient *rcc)
 {
     red_channel_client_release_sent_item(rcc);
-    rcc->send_data.blocked = FALSE;
-    rcc->send_data.size = 0;
+    rcc->priv->send_data.blocked = FALSE;
+    rcc->priv->send_data.size = 0;
 }
 
 static void red_channel_client_pipe_clear(RedChannelClient *rcc)
@@ -1393,21 +1401,21 @@ static void red_channel_client_pipe_clear(RedChannelClient *rcc)
     if (rcc) {
         red_channel_client_clear_sent_item(rcc);
     }
-    while ((item = (RedPipeItem *)ring_get_head(&rcc->pipe))) {
+    while ((item = (RedPipeItem *)ring_get_head(&rcc->priv->pipe))) {
         ring_remove(&item->link);
         red_pipe_item_unref(item);
     }
-    rcc->pipe_size = 0;
+    rcc->priv->pipe_size = 0;
 }
 
 void red_channel_client_ack_zero_messages_window(RedChannelClient *rcc)
 {
-    rcc->ack_data.messages_window = 0;
+    rcc->priv->ack_data.messages_window = 0;
 }
 
 void red_channel_client_ack_set_client_window(RedChannelClient *rcc, int client_window)
 {
-    rcc->ack_data.client_window = client_window;
+    rcc->priv->ack_data.client_window = client_window;
 }
 
 void red_channel_client_push_set_ack(RedChannelClient *rcc)
@@ -1419,20 +1427,20 @@ static void red_channel_client_disconnect_dummy(RedChannelClient *rcc)
 {
     RedChannel *channel = red_channel_client_get_channel(rcc);
     GList *link;
-    spice_assert(rcc->dummy);
+    spice_assert(rcc->priv->dummy);
     if (channel && (link = g_list_find(channel->clients, rcc))) {
         spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, channel,
                        channel->type, channel->id);
         red_channel_remove_client(channel, link->data);
     }
-    rcc->dummy_connected = FALSE;
+    rcc->priv->dummy_connected = FALSE;
 }
 
 void red_channel_client_disconnect(RedChannelClient *rcc)
 {
-    RedChannel *channel = rcc->channel;
+    RedChannel *channel = rcc->priv->channel;
 
-    if (rcc->dummy) {
+    if (rcc->priv->dummy) {
         red_channel_client_disconnect_dummy(rcc);
         return;
     }
@@ -1442,17 +1450,17 @@ void red_channel_client_disconnect(RedChannelClient *rcc)
     spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, channel,
                    channel->type, channel->id);
     red_channel_client_pipe_clear(rcc);
-    if (rcc->stream->watch) {
-        channel->core->watch_remove(rcc->stream->watch);
-        rcc->stream->watch = NULL;
+    if (rcc->priv->stream->watch) {
+        channel->core->watch_remove(rcc->priv->stream->watch);
+        rcc->priv->stream->watch = NULL;
     }
-    if (rcc->latency_monitor.timer) {
-        channel->core->timer_remove(rcc->latency_monitor.timer);
-        rcc->latency_monitor.timer = NULL;
+    if (rcc->priv->latency_monitor.timer) {
+        channel->core->timer_remove(rcc->priv->latency_monitor.timer);
+        rcc->priv->latency_monitor.timer = NULL;
     }
-    if (rcc->connectivity_monitor.timer) {
-        channel->core->timer_remove(rcc->connectivity_monitor.timer);
-        rcc->connectivity_monitor.timer = NULL;
+    if (rcc->priv->connectivity_monitor.timer) {
+        channel->core->timer_remove(rcc->priv->connectivity_monitor.timer);
+        rcc->priv->connectivity_monitor.timer = NULL;
     }
     red_channel_remove_client(channel, rcc);
     channel->channel_cbs.on_disconnect(rcc);
@@ -1460,32 +1468,32 @@ void red_channel_client_disconnect(RedChannelClient *rcc)
 
 int red_channel_client_is_blocked(RedChannelClient *rcc)
 {
-    return rcc && rcc->send_data.blocked;
+    return rcc && rcc->priv->send_data.blocked;
 }
 
 int red_channel_client_send_message_pending(RedChannelClient *rcc)
 {
-    return rcc->send_data.header.get_msg_type(&rcc->send_data.header) != 0;
+    return rcc->priv->send_data.header.get_msg_type(&rcc->priv->send_data.header) != 0;
 }
 
 SpiceMarshaller *red_channel_client_get_marshaller(RedChannelClient *rcc)
 {
-    return rcc->send_data.marshaller;
+    return rcc->priv->send_data.marshaller;
 }
 
 RedsStream *red_channel_client_get_stream(RedChannelClient *rcc)
 {
-    return rcc->stream;
+    return rcc->priv->stream;
 }
 
 RedClient *red_channel_client_get_client(RedChannelClient *rcc)
 {
-    return rcc->client;
+    return rcc->priv->client;
 }
 
 void red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_list)
 {
-    rcc->send_data.header.set_msg_sub_list(&rcc->send_data.header, sub_list);
+    rcc->priv->send_data.header.set_msg_sub_list(&rcc->priv->send_data.header, sub_list);
 }
 
 static void marker_pipe_item_free(RedPipeItem *base)
@@ -1581,7 +1589,7 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
 
 void red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc)
 {
-    if (red_channel_client_is_blocked(rcc) || rcc->pipe_size > 0) {
+    if (red_channel_client_is_blocked(rcc) || rcc->priv->pipe_size > 0) {
         red_channel_client_disconnect(rcc);
     } else {
         spice_assert(red_channel_client_no_item_being_sent(rcc));
@@ -1590,7 +1598,7 @@ void red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc)
 
 gboolean red_channel_client_no_item_being_sent(RedChannelClient *rcc)
 {
-    return !rcc || (rcc->send_data.size == 0);
+    return !rcc || (rcc->priv->send_data.size == 0);
 }
 
 void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc,
@@ -1605,22 +1613,23 @@ gboolean red_channel_client_set_migration_seamless(RedChannelClient *rcc)
 {
     gboolean ret = FALSE;
 
-    if (rcc->channel->migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) {
-        rcc->wait_migrate_data = TRUE;
+    if (rcc->priv->channel->migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) {
+        rcc->priv->wait_migrate_data = TRUE;
         ret = TRUE;
     }
-    spice_debug("channel type %d id %d rcc %p wait data %d", rcc->channel->type, rcc->channel->id, rcc,
-        rcc->wait_migrate_data);
+    spice_debug("channel type %d id %d rcc %p wait data %d", rcc->priv->channel->type,
+                rcc->priv->channel->id, rcc,
+                rcc->priv->wait_migrate_data);
 
     return ret;
 }
 
 void red_channel_client_set_destroying(RedChannelClient *rcc)
 {
-    rcc->destroying = TRUE;
+    rcc->priv->destroying = TRUE;
 }
 
 gboolean red_channel_client_is_destroying(RedChannelClient *rcc)
 {
-    return rcc->destroying;
+    return rcc->priv->destroying;
 }
diff --git a/server/smartcard.c b/server/smartcard.c
index 4bb0b05..504e3c3 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -177,8 +177,8 @@ static void smartcard_send_msg_to_client(RedPipeItem *msg,
                                          void *opaque)
 {
     RedCharDeviceSmartcard *dev = opaque;
-
-    spice_assert(dev->priv->scc && dev->priv->scc->base.client == client);
+    RedClient *this_client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dev->priv->scc));
+    spice_assert(dev->priv->scc && this_client == client);
     red_pipe_item_ref(msg);
     smartcard_channel_client_pipe_add_push(&dev->priv->scc->base, msg);
 }
@@ -191,9 +191,10 @@ static void smartcard_send_tokens_to_client(RedClient *client, uint32_t tokens,
 static void smartcard_remove_client(RedClient *client, void *opaque)
 {
     RedCharDeviceSmartcard *dev = opaque;
+    RedClient *this_client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dev->priv->scc));
 
     spice_printerr("smartcard  dev %p, client %p", dev, client);
-    spice_assert(dev->priv->scc && dev->priv->scc->base.client == client);
+    spice_assert(dev->priv->scc && this_client == client);
     red_channel_client_shutdown(&dev->priv->scc->base);
 }
 
@@ -324,7 +325,7 @@ static void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_de
     dev->priv->scc = scc;
     scc->priv->smartcard = dev;
     client_added = red_char_device_client_add(RED_CHAR_DEVICE(dev),
-                                              scc->base.client,
+                                              red_channel_client_get_client(RED_CHANNEL_CLIENT(scc)),
                                               FALSE, /* no flow control yet */
                                               0, /* send queue size */
                                               ~0,
@@ -370,7 +371,8 @@ static void smartcard_char_device_detach_client(SmartCardChannelClient *scc)
     }
     dev = scc->priv->smartcard;
     spice_assert(dev->priv->scc == scc);
-    red_char_device_client_remove(RED_CHAR_DEVICE(dev), scc->base.client);
+    red_char_device_client_remove(RED_CHAR_DEVICE(dev),
+                                  red_channel_client_get_client(RED_CHANNEL_CLIENT(scc)));
     scc->priv->smartcard = NULL;
     dev->priv->scc = NULL;
 }
@@ -385,6 +387,7 @@ static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                     uint32_t size)
 {
     SmartCardChannelClient *scc = SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base);
+    RedClient *client = red_channel_client_get_client(rcc);
 
     /* todo: only one reader is actually supported. When we fix the code to support
      * multiple readers, we will porbably associate different devices to
@@ -399,7 +402,9 @@ static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
         dev = scc->priv->smartcard;
         spice_assert(dev->priv->scc || scc->priv->smartcard);
         spice_assert(!scc->priv->write_buf);
-        scc->priv->write_buf = red_char_device_write_buffer_get(RED_CHAR_DEVICE(dev), rcc->client, size);
+        scc->priv->write_buf =
+            red_char_device_write_buffer_get(RED_CHAR_DEVICE(dev), client,
+                                             size);
 
         if (!scc->priv->write_buf) {
             spice_error("failed to allocate write buffer");
diff --git a/server/sound.c b/server/sound.c
index 279c927..7f1a2b5 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -34,6 +34,7 @@
 #include "main-channel.h"
 #include "reds.h"
 #include "red-qxl.h"
+/* FIXME: for now, allow sound channel access to private RedChannelClient data */
 #include "red-channel-client-private.h"
 #include "sound.h"
 #include <common/snd_codec.h>
@@ -523,7 +524,7 @@ static inline int snd_reset_send_data(SndChannel *channel, uint16_t verb)
         return FALSE;
     }
 
-    header = &channel->channel_client->send_data.header;
+    header = &channel->channel_client->priv->send_data.header;
     spice_marshaller_reset(channel->send_data.marshaller);
     header->data = spice_marshaller_reserve_space(channel->send_data.marshaller,
                                                   header->header_size);
@@ -533,7 +534,7 @@ static inline int snd_reset_send_data(SndChannel *channel, uint16_t verb)
     header->set_msg_size(header, 0);
     header->set_msg_type(header, verb);
     channel->send_data.serial++;
-    if (!channel->channel_client->is_mini_header) {
+    if (!channel->channel_client->priv->is_mini_header) {
         header->set_msg_serial(header, channel->send_data.serial);
         header->set_msg_sub_list(header, 0);
     }
@@ -543,7 +544,7 @@ static inline int snd_reset_send_data(SndChannel *channel, uint16_t verb)
 
 static int snd_begin_send_message(SndChannel *channel)
 {
-    SpiceDataHeaderOpaque *header = &channel->channel_client->send_data.header;
+    SpiceDataHeaderOpaque *header = &channel->channel_client->priv->send_data.header;
 
     spice_marshaller_flush(channel->send_data.marshaller);
     channel->send_data.size = spice_marshaller_get_total_size(channel->send_data.marshaller);
@@ -996,12 +997,13 @@ error1:
 static void snd_disconnect_channel_client(RedChannelClient *rcc)
 {
     SndWorker *worker;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    spice_assert(rcc->channel);
-    spice_assert(rcc->channel->data);
-    worker = (SndWorker *)rcc->channel->data;
+    spice_assert(channel);
+    spice_assert(channel->data);
+    worker = (SndWorker *)channel->data;
 
-    spice_debug("channel-type=%d", rcc->channel->type);
+    spice_debug("channel-type=%d", channel->type);
     if (worker->connection) {
         spice_assert(worker->connection->channel_client == rcc);
         snd_disconnect_channel(worker->connection);
@@ -1144,7 +1146,7 @@ void snd_set_playback_latency(RedClient *client, uint32_t latency)
 
     for (; now; now = now->next) {
         if (now->base_channel->type == SPICE_CHANNEL_PLAYBACK && now->connection &&
-            now->connection->channel_client->client == client) {
+            red_channel_client_get_client(now->connection->channel_client) == client) {
 
             if (red_channel_client_test_remote_cap(now->connection->channel_client,
                 SPICE_PLAYBACK_CAP_LATENCY)) {
@@ -1265,11 +1267,12 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt
 static void snd_record_migrate_channel_client(RedChannelClient *rcc)
 {
     SndWorker *worker;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
     spice_debug(NULL);
-    spice_assert(rcc->channel);
-    spice_assert(rcc->channel->data);
-    worker = (SndWorker *)rcc->channel->data;
+    spice_assert(channel);
+    spice_assert(channel->data);
+    worker = (SndWorker *)channel->data;
 
     if (worker->connection) {
         spice_assert(worker->connection->channel_client == rcc);
@@ -1494,10 +1497,11 @@ static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStre
 static void snd_playback_migrate_channel_client(RedChannelClient *rcc)
 {
     SndWorker *worker;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    spice_assert(rcc->channel);
-    spice_assert(rcc->channel->data);
-    worker = (SndWorker *)rcc->channel->data;
+    spice_assert(channel);
+    spice_assert(channel->data);
+    worker = (SndWorker *)channel->data;
     spice_debug(NULL);
 
     if (worker->connection) {
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 9e34251..d09a0c7 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -129,7 +129,7 @@ static RedVmcPipeItem* try_compress_lz4(SpiceVmcState *state, int n, RedVmcPipeI
     RedVmcPipeItem *msg_item_compressed;
     int compressed_data_count;
 
-    if (reds_stream_get_family(state->rcc->stream) == AF_UNIX) {
+    if (reds_stream_get_family(state->rcc->priv->stream) == AF_UNIX) {
         /* AF_LOCAL - data will not be compressed */
         return NULL;
     }
@@ -353,7 +353,7 @@ static int handle_compressed_msg(SpiceVmcState *state, RedChannelClient *rcc,
     int decompressed_size;
     RedCharDeviceWriteBuffer *write_buf;
 
-    write_buf = red_char_device_write_buffer_get(state->chardev, rcc->client,
+    write_buf = red_char_device_write_buffer_get(state->chardev, rcc->priv->client,
                                                  compressed_data_msg->uncompressed_size);
     if (!write_buf) {
         return FALSE;
-- 
2.7.4



More information about the Spice-devel mailing list