[Spice-commits] 5 commits - server/cursor-channel.c server/dcc.c server/dcc.h server/dcc-send.c server/display-channel.c server/inputs-channel.c server/inputs-channel-client.c server/main-channel.c server/main-channel-client.c server/red-channel.c server/red-channel.h server/red-qxl.c server/reds.c server/red-worker.c server/smartcard.c server/sound.c server/spicevmc.c server/stream.c

Jonathon Jongsma jjongsma at kemper.freedesktop.org
Tue Aug 30 21:54:07 UTC 2016


 server/cursor-channel.c        |    4 +-
 server/dcc-send.c              |   10 +++--
 server/dcc.c                   |   13 +++----
 server/dcc.h                   |    2 -
 server/display-channel.c       |    3 -
 server/inputs-channel-client.c |    2 -
 server/inputs-channel.c        |   14 +++----
 server/main-channel-client.c   |   74 ++++++++++++++++++++++++-----------------
 server/main-channel.c          |   37 ++++++++++++--------
 server/red-channel.c           |   43 +++++++++++++++++------
 server/red-channel.h           |    5 ++
 server/red-qxl.c               |   24 +++++++------
 server/red-worker.c            |    3 +
 server/reds.c                  |   22 +++++++-----
 server/smartcard.c             |   15 +++++---
 server/sound.c                 |   29 +++++++++-------
 server/spicevmc.c              |   28 +++++++++------
 server/stream.c                |   19 ++++++----
 18 files changed, 212 insertions(+), 135 deletions(-)

New commits:
commit d529bfd4f04ae74c7fa1b49345859c63a378b75a
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Wed Aug 24 11:37:57 2016 -0500

    Use red_channel_client_get_stream()
    
    Don't touch the rcc struct directly. Improve encapsulation to help
    prepare for separating RedChannelClient to a separate file.

diff --git a/server/spicevmc.c b/server/spicevmc.c
index 4e9dd0d..c79e7bb 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -127,7 +127,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(red_channel_client_get_stream(state->rcc)) == AF_UNIX) {
         /* AF_LOCAL - data will not be compressed */
         return NULL;
     }
commit 66c57006021702449ccd6b4d904e3309411f4a89
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Fri Aug 19 17:04:51 2016 -0500

    Don't poke RedChannelClient::send_data from RedChannel
    
    More preparation for separating RedChannelClient into a separate file.
    Rename function slightly for improved readability:
     red_channel_client_blocked() -> red_channel_client_is_blocked()

diff --git a/server/red-channel.c b/server/red-channel.c
index 870296c..bf290b1 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -1908,7 +1908,7 @@ int red_channel_all_blocked(RedChannel *channel)
     }
     for (link = channel->clients; link != NULL; link = link->next) {
         rcc = link->data;
-        if (!rcc->send_data.blocked) {
+        if (!red_channel_client_is_blocked(rcc)) {
             return FALSE;
         }
     }
@@ -1921,14 +1921,14 @@ int red_channel_any_blocked(RedChannel *channel)
     RedChannelClient *rcc;
 
     FOREACH_CLIENT(channel, link, next, rcc) {
-        if (rcc->send_data.blocked) {
+        if (red_channel_client_is_blocked(rcc)) {
             return TRUE;
         }
     }
     return FALSE;
 }
 
-int red_channel_client_blocked(RedChannelClient *rcc)
+int red_channel_client_is_blocked(RedChannelClient *rcc)
 {
     return rcc && rcc->send_data.blocked;
 }
@@ -2311,7 +2311,7 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
     uint64_t end_time;
     int blocked;
 
-    if (!red_channel_client_blocked(rcc)) {
+    if (!red_channel_client_is_blocked(rcc)) {
         return TRUE;
     }
     if (timeout != -1) {
@@ -2325,7 +2325,7 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
         usleep(CHANNEL_BLOCKED_SLEEP_DURATION);
         red_channel_client_receive(rcc);
         red_channel_client_send(rcc);
-    } while ((blocked = red_channel_client_blocked(rcc)) &&
+    } while ((blocked = red_channel_client_is_blocked(rcc)) &&
              (timeout == -1 || spice_get_monotonic_time_ns() < end_time));
 
     if (blocked) {
@@ -2371,7 +2371,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
     mark_item->item_in_pipe = &item_in_pipe;
     red_channel_client_pipe_add_after(rcc, &mark_item->base, item);
 
-    if (red_channel_client_blocked(rcc)) {
+    if (red_channel_client_is_blocked(rcc)) {
         red_channel_client_receive(rcc);
         red_channel_client_send(rcc);
     }
@@ -2432,7 +2432,7 @@ int red_channel_wait_all_sent(RedChannel *channel,
 
 void red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc)
 {
-    if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) {
+    if (red_channel_client_is_blocked(rcc) || rcc->pipe_size > 0) {
         red_channel_client_disconnect(rcc);
     } else {
         spice_assert(red_channel_client_no_item_being_sent(rcc));
diff --git a/server/red-channel.h b/server/red-channel.h
index e528d08..370f6a7 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -500,7 +500,7 @@ int red_channel_all_blocked(RedChannel *channel);
 /* return TRUE if any of the connected clients to this channel are blocked */
 int red_channel_any_blocked(RedChannel *channel);
 
-int red_channel_client_blocked(RedChannelClient *rcc);
+int red_channel_client_is_blocked(RedChannelClient *rcc);
 
 /* helper for channels that have complex logic that can possibly ready a send */
 int red_channel_client_send_message_pending(RedChannelClient *rcc);
commit 7b8087a71d1465069da56cc37aa10a5e93f8fa9b
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Fri Aug 19 16:52:08 2016 -0500

    Add red_channel_client_(set|is)_destroying()
    
    Encapsulate the structure a bit more and avoid poking into it from other
    class implementations. Getting ready to split RedChannelClient out to a
    separate file.

diff --git a/server/red-channel.c b/server/red-channel.c
index 615c2a3..870296c 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -2111,7 +2111,7 @@ void red_client_destroy(RedClient *client)
         // is not synchronous.
         rcc = link->data;
         channel = red_channel_client_get_channel(rcc);
-        rcc->destroying = 1;
+        red_channel_client_set_destroying(rcc);
         // some channels may be in other threads. However we currently
         // assume disconnect is synchronous (we changed the dispatcher
         // to wait for disconnection)
@@ -2448,3 +2448,13 @@ RedChannel* red_channel_client_get_channel(RedChannelClient *rcc)
 {
     return rcc->channel;
 }
+
+gboolean red_channel_client_is_destroying(RedChannelClient *rcc)
+{
+    return rcc->destroying;
+}
+
+void red_channel_client_set_destroying(RedChannelClient *rcc)
+{
+    rcc->destroying = TRUE;
+}
diff --git a/server/red-channel.h b/server/red-channel.h
index 039ac09..e528d08 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -629,5 +629,7 @@ int red_channel_wait_all_sent(RedChannel *channel,
                               int64_t timeout);
 void red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc);
 RedChannel* red_channel_client_get_channel(RedChannelClient *rcc);
+gboolean red_channel_client_is_destroying(RedChannelClient *rcc);
+void red_channel_client_set_destroying(RedChannelClient *rcc);
 
 #endif
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 5e310a6..4e9dd0d 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -306,7 +306,7 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
 
     /* Don't destroy the rcc if it is already being destroyed, as then
        red_client_destroy/red_channel_client_destroy will already do this! */
-    if (!rcc->destroying)
+    if (!red_channel_client_is_destroying(rcc))
         red_channel_client_destroy(rcc);
 
     state->rcc = NULL;
commit 2fa1c1e3fd230cd756b33e94be27515b070f47bc
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Thu Aug 18 13:12:03 2016 -0500

    Use red_channel_client_get_client() everywhere
    
    Instead of having all other classes poke into the RedChannelClient
    struct to get the RedClient associated with the channel client, call the
    accessor function. This commit allows us to encapsulate RedChannelClient
    and move it to its own file soon.

diff --git a/server/dcc.c b/server/dcc.c
index 9c3ab64..8eca28b 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -892,18 +892,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,
+                                                client,
                                                 init->glz_dictionary_id,
                                                 init->glz_dictionary_window_size);
     spice_return_val_if_fail(success, FALSE);
@@ -1007,7 +1008,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);
 }
@@ -1083,7 +1084,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(red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc)),
                                          migrate_data->pixmap_cache_id, -1);
     spice_return_val_if_fail(dcc->pixmap_cache, FALSE);
 
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 7a96a57..12151a7 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -335,7 +335,8 @@ 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(&mcc->base);
+    spice_printerr("client %p connected: %d seamless %d", client, success, seamless);
     if (mcc->mig_wait_connect) {
         RedChannel *channel = red_channel_client_get_channel(&mcc->base);
         MainChannel *main_channel = SPICE_CONTAINEROF(channel, MainChannel, base);
@@ -349,7 +350,7 @@ void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
         }
     } else {
         if (success) {
-            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);
         }
     }
@@ -432,7 +433,8 @@ void main_channel_client_handle_pong(MainChannelClient *mcc, SpiceMsgPing *ping,
 
 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(&mcc->base);
+    if (!red_client_during_migrate_at_target(client)) {
         spice_printerr("unexpected SPICE_MSGC_MIGRATE_END");
         return;
     }
@@ -442,13 +444,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)
 {
     if (mcc->mig_wait_connect) {
-        spice_printerr("client %p cancel wait connect", mcc->base.client);
+        spice_printerr("client %p cancel wait connect",
+                       red_channel_client_get_client(&mcc->base));
         mcc->mig_wait_connect = FALSE;
         mcc->mig_connect_ok = FALSE;
     }
@@ -475,20 +478,21 @@ gboolean main_channel_client_migrate_src_complete(MainChannelClient *mcc,
                                                   gboolean success)
 {
     gboolean ret = FALSE;
+    RedClient *client = red_channel_client_get_client(&mcc->base);
     int semi_seamless_support = red_channel_client_test_remote_cap(&mcc->base,
                                                                    SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
     if (semi_seamless_support && mcc->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);
         }
     }
@@ -607,10 +611,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(&mcc->base);
     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->mig_wait_prev_complete = TRUE;
         mcc->mig_wait_prev_try_seamless = TRUE;
     } else {
@@ -865,7 +870,7 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
         base->type != RED_PIPE_ITEM_TYPE_MAIN_INIT) {
         spice_printerr("Init msg for client %p was not sent yet "
                        "(client is probably during semi-seamless migration). Ignoring msg type %d",
-                   rcc->client, base->type);
+                       red_channel_client_get_client(rcc), base->type);
         return;
     }
     switch (base->type) {
diff --git a/server/main-channel.c b/server/main-channel.c
index 7c6c1f7..8bb874b 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -37,7 +37,8 @@ static void main_channel_client_on_disconnect(RedChannelClient *rcc)
 {
     RedsState *reds = red_channel_get_server(red_channel_client_get_channel(rcc));
     spice_printerr("rcc=%p", rcc);
-    main_dispatcher_client_disconnect(reds_get_main_dispatcher(reds), rcc->client);
+    main_dispatcher_client_disconnect(reds_get_main_dispatcher(reds),
+                                      red_channel_client_get_client(rcc));
 }
 
 RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t connection_id)
@@ -48,7 +49,7 @@ RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t c
     FOREACH_CLIENT(main_chan, link, next, rcc) {
         MainChannelClient *mcc = (MainChannelClient*) rcc;
         if (main_channel_client_get_connection_id(mcc) == connection_id) {
-            return rcc->client;
+            return red_channel_client_get_client(rcc);
         }
     }
     return NULL;
@@ -56,7 +57,8 @@ RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t c
 
 static void main_channel_push_channels(MainChannelClient *mcc)
 {
-    if (red_client_during_migrate_at_target((main_channel_client_get_base(mcc))->client)) {
+    RedChannelClient *rcc = main_channel_client_get_base(mcc);
+    if (red_client_during_migrate_at_target(red_channel_client_get_client(rcc))) {
         spice_printerr("warning: ignoring unexpected SPICE_MSGC_MAIN_ATTACH_CHANNELS"
                    "during migration");
         return;
diff --git a/server/reds.c b/server/reds.c
index 32068ac..74f7727 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1042,12 +1042,14 @@ void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, uint32_t
 {
     RedCharDevice *dev_state = RED_CHAR_DEVICE(reds->agent_dev);
     RedChannelClient *rcc;
+    RedClient *client;
 
     if (!reds->vdagent) {
         return;
     }
     spice_assert(reds->vdagent->st && reds->vdagent->st == dev_state);
     rcc = main_channel_client_get_base(mcc);
+    client = red_channel_client_get_client(rcc);
     reds->agent_dev->priv->client_agent_started = TRUE;
     /*
      * Note that in older releases, send_tokens were set to ~0 on both client
@@ -1056,11 +1058,11 @@ void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, uint32_t
      * and vice versa, the sending from the server to the client won't have
      * flow control, but will have no other problem.
      */
-    if (!red_char_device_client_exists(dev_state, rcc->client)) {
+    if (!red_char_device_client_exists(dev_state, client)) {
         int client_added;
 
         client_added = red_char_device_client_add(dev_state,
-                                                  rcc->client,
+                                                  client,
                                                   TRUE, /* flow control */
                                                   REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
                                                   REDS_AGENT_WINDOW_SIZE,
@@ -1074,7 +1076,7 @@ void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, uint32_t
         }
     } else {
         red_char_device_send_to_client_tokens_set(dev_state,
-                                                  rcc->client,
+                                                  client,
                                                   num_tokens);
     }
 
@@ -1086,12 +1088,13 @@ void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, uint32_t
 
 void reds_on_main_agent_tokens(RedsState *reds, MainChannelClient *mcc, uint32_t num_tokens)
 {
+    RedClient *client = red_channel_client_get_client(main_channel_client_get_base(mcc));
     if (!reds->vdagent) {
         return;
     }
     spice_assert(reds->vdagent->st);
     red_char_device_send_to_client_tokens_add(reds->vdagent->st,
-                                                main_channel_client_get_base(mcc)->client,
+                                                client,
                                                 num_tokens);
 }
 
@@ -1112,7 +1115,7 @@ uint8_t *reds_get_agent_data_buffer(RedsState *reds, MainChannelClient *mcc, siz
     }
 
     spice_assert(dev->priv->recv_from_client_buf == NULL);
-    client = main_channel_client_get_base(mcc)->client;
+    client = red_channel_client_get_client(main_channel_client_get_base(mcc));
     dev->priv->recv_from_client_buf = red_char_device_write_buffer_get(RED_CHAR_DEVICE(dev),
                                                                        client,
                                                                        size + sizeof(VDIChunkHeader));
@@ -1483,9 +1486,9 @@ int reds_handle_migrate_data(RedsState *reds, MainChannelClient *mcc,
     } else {
         spice_debug("agent was not attached on the source host");
         if (reds->vdagent) {
+            RedClient *client = red_channel_client_get_client(main_channel_client_get_base(mcc));
             /* red_char_device_client_remove disables waiting for migration data */
-            red_char_device_client_remove(RED_CHAR_DEVICE(agent_dev),
-                                          main_channel_client_get_base(mcc)->client);
+            red_char_device_client_remove(RED_CHAR_DEVICE(agent_dev), client);
             main_channel_push_agent_connected(reds->main_channel);
         }
     }
@@ -1929,10 +1932,11 @@ int reds_on_migrate_dst_set_seamless(RedsState *reds, MainChannelClient *mcc, ui
         reds->dst_do_seamless_migrate = FALSE;
     } else {
         RedChannelClient *rcc = main_channel_client_get_base(mcc);
+        RedClient *client = red_channel_client_get_client(rcc);
 
-        red_client_set_migration_seamless(rcc->client);
+        red_client_set_migration_seamless(client);
         /* linking all the channels that have been connected before migration handshake */
-        reds->dst_do_seamless_migrate = reds_link_mig_target_channels(reds, rcc->client);
+        reds->dst_do_seamless_migrate = reds_link_mig_target_channels(reds, client);
     }
     return reds->dst_do_seamless_migrate;
 }
diff --git a/server/smartcard.c b/server/smartcard.c
index b69ac17..a8a16c7 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -172,7 +172,8 @@ static void smartcard_send_msg_to_client(RedPipeItem *msg,
 {
     RedCharDeviceSmartcard *dev = opaque;
 
-    spice_assert(dev->priv->scc && dev->priv->scc->base.client == client);
+    spice_assert(dev->priv->scc &&
+                 red_channel_client_get_client(&dev->priv->scc->base) == client);
     red_pipe_item_ref(msg);
     smartcard_channel_client_pipe_add_push(&dev->priv->scc->base, msg);
 }
@@ -187,7 +188,8 @@ static void smartcard_remove_client(RedClient *client, void *opaque)
     RedCharDeviceSmartcard *dev = opaque;
 
     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 &&
+                 red_channel_client_get_client(&dev->priv->scc->base) == client);
     red_channel_client_shutdown(&dev->priv->scc->base);
 }
 
@@ -318,7 +320,7 @@ static void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_de
     dev->priv->scc = scc;
     scc->smartcard = dev;
     client_added = red_char_device_client_add(RED_CHAR_DEVICE(dev),
-                                              scc->base.client,
+                                              red_channel_client_get_client(&scc->base),
                                               FALSE, /* no flow control yet */
                                               0, /* send queue size */
                                               ~0,
@@ -364,7 +366,8 @@ static void smartcard_char_device_detach_client(SmartCardChannelClient *scc)
     }
     dev = scc->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(&scc->base));
     scc->smartcard = NULL;
     dev->priv->scc = NULL;
 }
@@ -393,7 +396,9 @@ static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
         dev = scc->smartcard;
         spice_assert(dev->priv->scc || scc->smartcard);
         spice_assert(!scc->write_buf);
-        scc->write_buf = red_char_device_write_buffer_get(RED_CHAR_DEVICE(dev), rcc->client, size);
+        scc->write_buf = red_char_device_write_buffer_get(RED_CHAR_DEVICE(dev),
+                                                          red_channel_client_get_client(rcc),
+                                                          size);
 
         if (!scc->write_buf) {
             spice_error("failed to allocate write buffer");
diff --git a/server/sound.c b/server/sound.c
index 06fab7f..84cbab4 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -1143,7 +1143,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)) {
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 08b3730..5e310a6 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -211,7 +211,7 @@ static void spicevmc_chardev_send_msg_to_client(RedPipeItem *msg,
 {
     SpiceVmcState *state = opaque;
 
-    spice_assert(state->rcc->client == client);
+    spice_assert(red_channel_client_get_client(state->rcc) == client);
     red_pipe_item_ref(msg);
     red_channel_client_pipe_add_push(state->rcc, msg);
 }
@@ -255,7 +255,8 @@ static void spicevmc_char_dev_remove_client(RedClient *client, void *opaque)
     SpiceVmcState *state = opaque;
 
     spice_printerr("vmc state %p, client %p", state, client);
-    spice_assert(state->rcc && state->rcc->client == client);
+    spice_assert(state->rcc &&
+                 red_channel_client_get_client(state->rcc) == client);
 
     red_channel_client_shutdown(state->rcc);
 }
@@ -283,6 +284,7 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
 {
     SpiceVmcState *state;
     SpiceCharDeviceInterface *sif;
+    RedClient *client = red_channel_client_get_client(rcc);
 
     if (!rcc) {
         return;
@@ -294,11 +296,11 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
     red_char_device_write_buffer_release(state->chardev, &state->recv_from_client_buf);
 
     if (state->chardev) {
-        if (red_char_device_client_exists(state->chardev, rcc->client)) {
-            red_char_device_client_remove(state->chardev, rcc->client);
+        if (red_char_device_client_exists(state->chardev, client)) {
+            red_char_device_client_remove(state->chardev, client);
         } else {
             spice_printerr("client %p have already been removed from char dev %p",
-                           rcc->client, state->chardev);
+                           client, state->chardev);
         }
     }
 
@@ -349,7 +351,8 @@ 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,
+                                                 red_channel_client_get_client(rcc),
                                                  compressed_data_msg->uncompressed_size);
     if (!write_buf) {
         return FALSE;
@@ -424,6 +427,7 @@ static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                        uint32_t size)
 {
     SpiceVmcState *state;
+    RedClient *client = red_channel_client_get_client(rcc);
 
     state = spicevmc_red_channel_client_get_state(rcc);
 
@@ -432,7 +436,7 @@ static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
         assert(!state->recv_from_client_buf);
 
         state->recv_from_client_buf = red_char_device_write_buffer_get(state->chardev,
-                                                                       rcc->client,
+                                                                       client,
                                                                        size);
         if (!state->recv_from_client_buf) {
             spice_error("failed to allocate write buffer");
diff --git a/server/stream.c b/server/stream.c
index d302168..4819723 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -634,7 +634,7 @@ static uint64_t get_initial_bit_rate(DisplayChannelClient *dcc, Stream *stream)
         MainChannelClient *mcc;
         uint64_t net_test_bit_rate;
 
-        mcc = red_client_get_main(RED_CHANNEL_CLIENT(dcc)->client);
+        mcc = red_client_get_main(red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc)));
         net_test_bit_rate = main_channel_client_is_network_info_initialized(mcc) ?
                                 main_channel_client_get_bitrate_per_sec(mcc) :
                                 0;
@@ -663,10 +663,11 @@ static uint32_t get_roundtrip_ms(void *opaque)
 {
     StreamAgent *agent = opaque;
     int roundtrip;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(agent->dcc);
 
-    roundtrip = red_channel_client_get_roundtrip_ms(RED_CHANNEL_CLIENT(agent->dcc));
+    roundtrip = red_channel_client_get_roundtrip_ms(rcc);
     if (roundtrip < 0) {
-        MainChannelClient *mcc = red_client_get_main(RED_CHANNEL_CLIENT(agent->dcc)->client);
+        MainChannelClient *mcc = red_client_get_main(red_channel_client_get_client(rcc));
 
         /*
          * the main channel client roundtrip might not have been
@@ -697,10 +698,10 @@ static void update_client_playback_delay(void *opaque, uint32_t delay_ms)
     dcc_update_streams_max_latency(dcc, agent);
 
     agent->client_required_latency = delay_ms;
-    if (delay_ms > dcc_get_max_stream_latency(agent->dcc)) {
-        dcc_set_max_stream_latency(agent->dcc, delay_ms);
+    if (delay_ms > dcc_get_max_stream_latency(dcc)) {
+        dcc_set_max_stream_latency(dcc, delay_ms);
     }
-    spice_debug("resetting client latency: %u", dcc_get_max_stream_latency(agent->dcc));
+    spice_debug("resetting client latency: %u", dcc_get_max_stream_latency(dcc));
     main_dispatcher_set_mm_time_latency(reds_get_main_dispatcher(reds),
                                         client,
                                         dcc_get_max_stream_latency(agent->dcc));
commit d5d59d0858e84e1979646092e718915dd5d63412
Author: Jonathon Jongsma <jjongsma at redhat.com>
Date:   Wed Aug 17 17:11:06 2016 -0500

    Add red_channel_client_get_channel()
    
    Don't poke into the structure to get the channel
    
    This prepares for encapsulating RedChannelClient a bit more and
    separating it into its own source file.

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index dac929a..1e753c7 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -235,7 +235,7 @@ static void red_marshall_cursor_init(CursorChannelClient *ccc, SpiceMarshaller *
     AddBufInfo info;
 
     spice_assert(rcc);
-    cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base);
+    cursor_channel = (CursorChannel*)red_channel_client_get_channel(rcc);
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT, NULL);
     msg.visible = cursor_channel->cursor_visible;
@@ -253,7 +253,7 @@ static void cursor_marshall(CursorChannelClient *ccc,
                             RedCursorPipeItem *cursor_pipe_item)
 {
     RedChannelClient *rcc = RED_CHANNEL_CLIENT(ccc);
-    CursorChannel *cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base);
+    CursorChannel *cursor_channel = (CursorChannel*)red_channel_client_get_channel(rcc);
     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..999b44b 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -195,8 +195,8 @@ 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);
     DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
+    DisplayChannel *display_channel = DCC_TO_DC(dcc);
 
     if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
         spice_assert(image->descriptor.width * image->descriptor.height > 0);
@@ -1834,7 +1834,7 @@ 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 = DCC_TO_DC(dcc);
 
     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 +2137,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
@@ -2227,11 +2228,12 @@ static void marshall_upgrade(RedChannelClient *rcc, SpiceMarshaller *m,
                              RedUpgradeItem *item)
 {
     DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     RedDrawable *red_drawable;
     SpiceMsgDisplayDrawCopy copy;
     SpiceMarshaller *src_bitmap_out, *mask_bitmap_out;
 
-    spice_assert(rcc && rcc->channel && item && item->drawable);
+    spice_assert(channel && item && item->drawable);
     red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_COPY, &item->base);
 
     red_drawable = item->drawable->red_drawable;
diff --git a/server/dcc.c b/server/dcc.c
index d387e8b..9c3ab64 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -157,7 +157,7 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
         return;
     }
     surface = &display->surfaces[surface_id];
-    create = red_surface_create_item_new(RED_CHANNEL_CLIENT(dcc)->channel,
+    create = red_surface_create_item_new(RED_CHANNEL(display),
                                          surface_id, surface->context.width,
                                          surface->context.height,
                                          surface->context.format, flags);
@@ -549,7 +549,7 @@ void dcc_push_monitors_config(DisplayChannelClient *dcc)
         return;
     }
 
-    mci = red_monitors_config_item_new(dcc->base.channel,
+    mci = red_monitors_config_item_new(red_channel_client_get_channel(&dcc->base),
                                        monitors_config_ref(dc->monitors_config));
     red_channel_client_pipe_add(&dcc->base, &mci->pipe_item);
     red_channel_client_push(&dcc->base);
diff --git a/server/dcc.h b/server/dcc.h
index 672fb2f..0659ce7 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -59,7 +59,7 @@ typedef struct FreeList {
 
 typedef struct DisplayChannelClient DisplayChannelClient;
 
-#define DCC_TO_DC(dcc) ((DisplayChannel*)((RedChannelClient*)dcc)->channel)
+#define DCC_TO_DC(dcc) ((DisplayChannel*)red_channel_client_get_channel((RedChannelClient*)dcc))
 #define RCC_TO_DCC(rcc) ((DisplayChannelClient*)rcc)
 
 typedef struct RedSurfaceCreateItem {
diff --git a/server/display-channel.c b/server/display-channel.c
index 5e0a004..74c7dc0 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1858,8 +1858,7 @@ static void on_disconnect(RedChannelClient *rcc)
 
 static int handle_migrate_flush_mark(RedChannelClient *rcc)
 {
-    DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
-    RedChannel *channel = RED_CHANNEL(display_channel);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
     red_channel_pipes_add_type(channel, RED_PIPE_ITEM_TYPE_MIGRATE_DATA);
     return TRUE;
diff --git a/server/inputs-channel-client.c b/server/inputs-channel-client.c
index 2f8acec..bdbcf5c 100644
--- a/server/inputs-channel-client.c
+++ b/server/inputs-channel-client.c
@@ -75,7 +75,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(&icc->base);
 
     if (++icc->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
         !inputs_channel_is_src_during_migrate(inputs_channel)) {
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index 69d0391..c28273a 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -155,7 +155,7 @@ static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                  uint16_t type,
                                                  uint32_t size)
 {
-    InputsChannel *inputs_channel = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
+    InputsChannel *inputs_channel = (InputsChannel*)red_channel_client_get_channel(rcc);
 
     if (size > RECEIVE_BUF_SIZE) {
         spice_printerr("error: too large incoming message");
@@ -263,7 +263,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:
-            ((InputsChannel*)rcc->channel)->src_during_migrate = FALSE;
+            ((InputsChannel*)red_channel_client_get_channel(rcc))->src_during_migrate = FALSE;
             inputs_channel_client_send_migrate_data(rcc, m, base);
             break;
         default:
@@ -276,7 +276,7 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
 static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type,
                                         void *message)
 {
-    InputsChannel *inputs_channel = (InputsChannel *)rcc->channel;
+    InputsChannel *inputs_channel = (InputsChannel *)red_channel_client_get_channel(rcc);
     InputsChannelClient *icc = (InputsChannelClient *)rcc;
     uint32_t i;
     RedsState *reds = red_channel_get_server(&inputs_channel->base);
@@ -462,13 +462,13 @@ static void inputs_channel_on_disconnect(RedChannelClient *rcc)
     if (!rcc) {
         return;
     }
-    inputs_release_keys(SPICE_CONTAINEROF(rcc->channel, InputsChannel, base));
+    inputs_release_keys((InputsChannel*)red_channel_client_get_channel(rcc));
 }
 
 static void inputs_pipe_add_init(RedChannelClient *rcc)
 {
     RedInputsInitPipeItem *item = spice_malloc(sizeof(RedInputsInitPipeItem));
-    InputsChannel *inputs = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
+    InputsChannel *inputs = (InputsChannel*)red_channel_client_get_channel(rcc);
 
     red_pipe_item_init(&item->base, RED_PIPE_ITEM_INPUTS_INIT);
     item->modifiers = kbd_get_leds(inputs_channel_get_keyboard(inputs));
@@ -515,7 +515,7 @@ static void inputs_connect(RedChannel *channel, RedClient *client,
 
 static void inputs_migrate(RedChannelClient *rcc)
 {
-    InputsChannel *inputs = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
+    InputsChannel *inputs = (InputsChannel*)red_channel_client_get_channel(rcc);
     inputs->src_during_migrate = TRUE;
     red_channel_client_default_migrate(rcc);
 }
@@ -552,7 +552,7 @@ static int inputs_channel_handle_migrate_data(RedChannelClient *rcc,
                                               void *message)
 {
     InputsChannelClient *icc = (InputsChannelClient*)rcc;
-    InputsChannel *inputs = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
+    InputsChannel *inputs = (InputsChannel*)red_channel_client_get_channel(rcc);
     SpiceMigrateDataHeader *header;
     SpiceMigrateDataInputs *mig_data;
 
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index acf1bd4..7a96a57 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -337,14 +337,15 @@ void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
 {
     spice_printerr("client %p connected: %d seamless %d", mcc->base.client, success, seamless);
     if (mcc->mig_wait_connect) {
-        MainChannel *main_channel = SPICE_CONTAINEROF(mcc->base.channel, MainChannel, base);
+        RedChannel *channel = red_channel_client_get_channel(&mcc->base);
+        MainChannel *main_channel = SPICE_CONTAINEROF(channel, MainChannel, base);
 
         mcc->mig_wait_connect = FALSE;
         mcc->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) {
@@ -357,7 +358,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(&mcc->base);
+    if (reds_on_migrate_dst_set_seamless(channel->reds, mcc, src_version)) {
         mcc->seamless_mig_dst = TRUE;
         red_channel_client_pipe_add_empty_msg(&mcc->base,
                                              SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK);
@@ -424,7 +426,7 @@ 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
 }
 
@@ -457,7 +459,8 @@ void main_channel_client_migrate_dst_complete(MainChannelClient *mcc)
 {
     if (mcc->mig_wait_prev_complete) {
         if (mcc->mig_wait_prev_try_seamless) {
-            spice_assert(g_list_length(mcc->base.channel->clients) == 1);
+            RedChannel *channel = red_channel_client_get_channel(&mcc->base);
+            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 {
@@ -499,6 +502,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(&mcc->base);
     spice_printerr("");
     if (!opt) {
         main_channel_client_push_ping(mcc, 0);
@@ -506,9 +510,9 @@ static void do_ping_client(MainChannelClient *mcc,
         if (has_interval && interval > 0) {
             mcc->ping_interval = interval * MSEC_PER_SEC;
         }
-        reds_core_timer_start(mcc->base.channel->reds, mcc->ping_timer, mcc->ping_interval);
+        reds_core_timer_start(channel->reds, mcc->ping_timer, mcc->ping_interval);
     } else if (!strcmp(opt, "off")) {
-        reds_core_timer_cancel(mcc->base.channel->reds, mcc->ping_timer);
+        reds_core_timer_cancel(channel->reds, mcc->ping_timer);
     } else {
         return;
     }
@@ -517,14 +521,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(&mcc->base);
 
     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->ping_timer);
+        reds_core_timer_cancel(channel->reds, mcc->ping_timer);
         return;
     }
     do_ping_client(mcc, NULL, 0, 0);
-    reds_core_timer_start(mcc->base.channel->reds, mcc->ping_timer, mcc->ping_interval);
+    reds_core_timer_start(channel->reds, mcc->ping_timer, mcc->ping_interval);
 }
 #endif /* RED_STATISTICS */
 
@@ -572,14 +577,15 @@ 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 = (MainChannel*)red_channel_client_get_channel(rcc);
     if (red_channel_client_test_remote_cap(rcc,
                                            SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE)) {
         RedClient *client = red_channel_client_get_client(rcc);
@@ -636,9 +642,10 @@ static void main_channel_marshall_channels(RedChannelClient *rcc,
                                            RedPipeItem *item)
 {
     SpiceMsgChannels* channels_info;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_CHANNELS_LIST, item);
-    channels_info = reds_msg_channels_new(rcc->channel->reds);
+    channels_info = reds_msg_channels_new(channel->reds);
     spice_marshall_msg_main_channels_list(m, channels_info);
     free(channels_info);
 }
@@ -711,8 +718,9 @@ static void main_channel_marshall_migrate_data_item(RedChannelClient *rcc,
                                                     SpiceMarshaller *m,
                                                     RedPipeItem *item)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, item);
-    reds_marshall_migrate_data(rcc->channel->reds, m); // TODO: from reds split. ugly separation.
+    reds_marshall_migrate_data(channel->reds, m); // TODO: from reds split. ugly separation.
 }
 
 static void main_channel_marshall_init(RedChannelClient *rcc,
@@ -720,7 +728,7 @@ static void main_channel_marshall_init(RedChannelClient *rcc,
                                        RedInitPipeItem *item)
 {
     SpiceMsgMainInit init; // TODO - remove this copy, make RedInitPipeItem reuse SpiceMsgMainInit
-
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_INIT, &item->base);
     init.session_id = item->connection_id;
@@ -730,7 +738,7 @@ static void main_channel_marshall_init(RedChannelClient *rcc,
     if (item->is_client_mouse_allowed) {
         init.supported_mouse_modes |= SPICE_MOUSE_MODE_CLIENT;
     }
-    init.agent_connected = reds_has_vdagent(rcc->channel->reds);
+    init.agent_connected = reds_has_vdagent(channel->reds);
     init.agent_tokens = REDS_AGENT_WINDOW_SIZE;
     init.multi_media_time = item->multi_media_time;
     init.ram_hint = item->ram_hint;
@@ -772,11 +780,12 @@ static void main_channel_fill_migrate_dst_info(MainChannel *main_channel,
 static void main_channel_marshall_migrate_begin(SpiceMarshaller *m, RedChannelClient *rcc,
                                                 RedPipeItem *item)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     SpiceMsgMainMigrationBegin migrate;
     MainChannel *main_ch;
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_MIGRATE_BEGIN, item);
-    main_ch = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+    main_ch = SPICE_CONTAINEROF(channel, MainChannel, base);
     main_channel_fill_migrate_dst_info(main_ch, &migrate.dst_info);
     spice_marshall_msg_main_migrate_begin(m, &migrate);
 }
@@ -785,11 +794,12 @@ static void main_channel_marshall_migrate_begin_seamless(SpiceMarshaller *m,
                                                          RedChannelClient *rcc,
                                                          RedPipeItem *item)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     SpiceMsgMainMigrateBeginSeamless migrate_seamless;
     MainChannel *main_ch;
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS, item);
-    main_ch = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+    main_ch = SPICE_CONTAINEROF(channel, MainChannel, base);
     main_channel_fill_migrate_dst_info(main_ch, &migrate_seamless.dst_info);
     migrate_seamless.src_mig_version = SPICE_MIGRATION_PROTOCOL_VERSION;
     spice_marshall_msg_main_migrate_begin_seamless(m, &migrate_seamless);
@@ -809,12 +819,13 @@ static void main_channel_marshall_multi_media_time(RedChannelClient *rcc,
 static void main_channel_marshall_migrate_switch(SpiceMarshaller *m, RedChannelClient *rcc,
                                                  RedPipeItem *item)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     SpiceMsgMainMigrationSwitchHost migrate;
     MainChannel *main_ch;
 
     spice_printerr("");
     red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST, item);
-    main_ch = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+    main_ch = SPICE_CONTAINEROF(channel, MainChannel, base);
     migrate.port = main_ch->mig_target.port;
     migrate.sport = main_ch->mig_target.sport;
     migrate.host_size = strlen(main_ch->mig_target.host) + 1;
diff --git a/server/main-channel.c b/server/main-channel.c
index 42195e6..7c6c1f7 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -35,7 +35,7 @@ int main_channel_is_connected(MainChannel *main_chan)
  */
 static void main_channel_client_on_disconnect(RedChannelClient *rcc)
 {
-    RedsState *reds = red_channel_get_server(rcc->channel);
+    RedsState *reds = red_channel_get_server(red_channel_client_get_channel(rcc));
     spice_printerr("rcc=%p", rcc);
     main_dispatcher_client_disconnect(reds_get_main_dispatcher(reds), rcc->client);
 }
@@ -98,11 +98,12 @@ static void main_channel_push_migrate_data_item(MainChannel *main_chan)
 static int main_channel_handle_migrate_data(RedChannelClient *rcc,
     uint32_t size, void *message)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     MainChannelClient *mcc = (MainChannelClient*)rcc;
     SpiceMigrateDataHeader *header = (SpiceMigrateDataHeader *)message;
 
     /* not supported with multi-clients */
-    spice_assert(g_list_length(rcc->channel->clients) == 1);
+    spice_assert(g_list_length(channel->clients) == 1);
 
     if (size < sizeof(SpiceMigrateDataHeader) + sizeof(SpiceMigrateDataMain)) {
         spice_printerr("bad message size %u", size);
@@ -114,7 +115,7 @@ static int main_channel_handle_migrate_data(RedChannelClient *rcc,
         spice_error("bad header");
         return FALSE;
     }
-    return reds_handle_migrate_data(rcc->channel->reds, mcc, (SpiceMigrateDataMain *)(header + 1), size);
+    return reds_handle_migrate_data(channel->reds, mcc, (SpiceMigrateDataMain *)(header + 1), size);
 }
 
 void main_channel_push_multi_media_time(MainChannel *main_chan, int time)
@@ -151,7 +152,8 @@ void main_channel_migrate_switch(MainChannel *main_chan, RedsMigSpice *mig_targe
 static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type,
                                       void *message)
 {
-    MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
+    MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base);
     MainChannelClient *mcc = (MainChannelClient*)rcc;
 
     switch (type) {
@@ -163,18 +165,18 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint
             return FALSE;
         }
         tokens = (SpiceMsgcMainAgentStart *)message;
-        reds_on_main_agent_start(rcc->channel->reds, mcc, tokens->num_tokens);
+        reds_on_main_agent_start(channel->reds, mcc, tokens->num_tokens);
         break;
     }
     case SPICE_MSGC_MAIN_AGENT_DATA: {
-        reds_on_main_agent_data(rcc->channel->reds, mcc, message, size);
+        reds_on_main_agent_data(channel->reds, mcc, message, size);
         break;
     }
     case SPICE_MSGC_MAIN_AGENT_TOKEN: {
         SpiceMsgcMainAgentTokens *tokens;
 
         tokens = (SpiceMsgcMainAgentTokens *)message;
-        reds_on_main_agent_tokens(rcc->channel->reds, mcc, tokens->num_tokens);
+        reds_on_main_agent_tokens(channel->reds, mcc, tokens->num_tokens);
         break;
     }
     case SPICE_MSGC_MAIN_ATTACH_CHANNELS:
@@ -198,7 +200,7 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint
             ((SpiceMsgcMainMigrateDstDoSeamless *)message)->src_version);
         break;
     case SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST:
-        reds_on_main_mouse_mode_request(rcc->channel->reds, message, size);
+        reds_on_main_mouse_mode_request(channel->reds, message, size);
         break;
     case SPICE_MSGC_PONG: {
         main_channel_client_handle_pong(mcc, (SpiceMsgPing *)message, size);
@@ -219,11 +221,12 @@ static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                uint16_t type,
                                                uint32_t size)
 {
-    MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
+    MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base);
     MainChannelClient *mcc = (MainChannelClient*)rcc;
 
     if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
-        return reds_get_agent_data_buffer(rcc->channel->reds, mcc, size);
+        return reds_get_agent_data_buffer(channel->reds, mcc, size);
     } else {
         return main_chan->recv_buf;
     }
@@ -234,8 +237,9 @@ static void main_channel_release_msg_rcv_buf(RedChannelClient *rcc,
                                                uint32_t size,
                                                uint8_t *msg)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
-        reds_release_agent_data_buffer(rcc->channel->reds, msg);
+        reds_release_agent_data_buffer(channel->reds, msg);
     }
 }
 
@@ -246,8 +250,9 @@ static int main_channel_config_socket(RedChannelClient *rcc)
 
 static int main_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
 {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
     spice_debug(NULL);
-    main_channel_push_migrate_data_item(SPICE_CONTAINEROF(rcc->channel,
+    main_channel_push_migrate_data_item(SPICE_CONTAINEROF(channel,
                                         MainChannel, base));
     return TRUE;
 }
diff --git a/server/red-channel.c b/server/red-channel.c
index a02c51a..615c2a3 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -2069,6 +2069,7 @@ void red_client_migrate(RedClient *client)
 {
     GList *link, *next;
     RedChannelClient *rcc;
+    RedChannel *channel;
 
     spice_printerr("migrate client with #channels %d", g_list_length(client->channels));
     if (!pthread_equal(pthread_self(), client->thread_id)) {
@@ -2081,8 +2082,9 @@ void red_client_migrate(RedClient *client)
     while (link) {
         next = link->next;
         rcc = link->data;
+        channel = red_channel_client_get_channel(rcc);
         if (red_channel_client_is_connected(rcc)) {
-            rcc->channel->client_cbs.migrate(rcc);
+            channel->client_cbs.migrate(rcc);
         }
         link = next;
     }
@@ -2103,17 +2105,19 @@ void red_client_destroy(RedClient *client)
     }
     link = client->channels;
     while (link) {
+        RedChannel *channel;
         next = link->next;
         // some channels may be in other threads, so disconnection
         // is not synchronous.
         rcc = link->data;
+        channel = red_channel_client_get_channel(rcc);
         rcc->destroying = 1;
         // some channels may be in other threads. However we currently
         // assume disconnect is synchronous (we changed the dispatcher
         // to wait for disconnection)
         // TODO: should we go back to async. For this we need to use
         // ref count for channel clients.
-        rcc->channel->client_cbs.disconnect(rcc);
+        channel->client_cbs.disconnect(rcc);
         spice_assert(ring_is_empty(&rcc->pipe));
         spice_assert(rcc->pipe_size == 0);
         spice_assert(rcc->send_data.size == 0);
@@ -2131,8 +2135,10 @@ static RedChannelClient *red_client_get_channel(RedClient *client, int type, int
     RedChannelClient *ret = NULL;
 
     for (link = client->channels; link != NULL; link = link->next) {
+        RedChannel *channel;
         rcc = link->data;
-        if (rcc->channel->type == type && rcc->channel->id == id) {
+        channel = red_channel_client_get_channel(rcc);
+        if (channel->type == type && channel->id == id) {
             ret = rcc;
             break;
         }
@@ -2437,3 +2443,8 @@ RedsState* red_channel_get_server(RedChannel *channel)
 {
     return channel->reds;
 }
+
+RedChannel* red_channel_client_get_channel(RedChannelClient *rcc)
+{
+    return rcc->channel;
+}
diff --git a/server/red-channel.h b/server/red-channel.h
index 5b38f57..039ac09 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -628,5 +628,6 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
 int red_channel_wait_all_sent(RedChannel *channel,
                               int64_t timeout);
 void red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc);
+RedChannel* red_channel_client_get_channel(RedChannelClient *rcc);
 
 #endif
diff --git a/server/red-qxl.c b/server/red-qxl.c
index 2a4fa52..e517b41 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -102,12 +102,13 @@ static void red_qxl_disconnect_display_peer(RedChannelClient *rcc)
 {
     RedWorkerMessageDisplayDisconnect payload;
     Dispatcher *dispatcher;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    if (!rcc->channel) {
+    if (!channel) {
         return;
     }
 
-    dispatcher = (Dispatcher *)rcc->channel->data;
+    dispatcher = (Dispatcher *)channel->data;
 
     spice_printerr("");
     payload.rcc = rcc;
@@ -123,11 +124,12 @@ static void red_qxl_display_migrate(RedChannelClient *rcc)
 {
     RedWorkerMessageDisplayMigrate payload;
     Dispatcher *dispatcher;
-    if (!rcc->channel) {
+    RedChannel *channel = red_channel_client_get_channel(rcc);
+    if (!channel) {
         return;
     }
-    dispatcher = (Dispatcher *)rcc->channel->data;
-    spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id);
+    dispatcher = (Dispatcher *)channel->data;
+    spice_printerr("channel type %u id %u", channel->type, channel->id);
     payload.rcc = rcc;
     dispatcher_send_message(dispatcher,
                             RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
@@ -162,12 +164,13 @@ static void red_qxl_disconnect_cursor_peer(RedChannelClient *rcc)
 {
     RedWorkerMessageCursorDisconnect payload;
     Dispatcher *dispatcher;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    if (!rcc->channel) {
+    if (!channel) {
         return;
     }
 
-    dispatcher = (Dispatcher *)rcc->channel->data;
+    dispatcher = (Dispatcher *)channel->data;
     spice_printerr("");
     payload.rcc = rcc;
 
@@ -180,12 +183,13 @@ static void red_qxl_cursor_migrate(RedChannelClient *rcc)
 {
     RedWorkerMessageCursorMigrate payload;
     Dispatcher *dispatcher;
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    if (!rcc->channel) {
+    if (!channel) {
         return;
     }
-    dispatcher = (Dispatcher *)rcc->channel->data;
-    spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id);
+    dispatcher = (Dispatcher *)channel->data;
+    spice_printerr("channel type %u id %u", channel->type, channel->id);
     payload.rcc = rcc;
     dispatcher_send_message(dispatcher,
                             RED_WORKER_MESSAGE_CURSOR_MIGRATE,
diff --git a/server/red-worker.c b/server/red-worker.c
index 34a8bff..590412b 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -101,7 +101,8 @@ static int display_is_connected(RedWorker *worker)
 
 static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
 {
-    CommonGraphicsChannel *common = SPICE_CONTAINEROF(rcc->channel, CommonGraphicsChannel, base);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
+    CommonGraphicsChannel *common = SPICE_CONTAINEROF(channel, CommonGraphicsChannel, base);
 
     /* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is dynamic */
     if (type == SPICE_MSGC_MIGRATE_DATA) {
diff --git a/server/sound.c b/server/sound.c
index 8335101..06fab7f 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -212,14 +212,16 @@ static void snd_disconnect_channel(SndChannel *channel)
 {
     SndWorker *worker;
     RedsState *reds;
+    RedChannel *red_channel;
 
     if (!channel || !channel->stream) {
         spice_debug("not connected");
         return;
     }
+    red_channel = red_channel_client_get_channel(channel->channel_client);
     reds = snd_channel_get_server(channel);
     spice_debug("SndChannel=%p rcc=%p type=%d",
-                 channel, channel->channel_client, channel->channel_client->channel->type);
+                 channel, channel->channel_client, red_channel->type);
     worker = channel->worker;
     channel->cleanup(channel);
     red_channel_client_disconnect(worker->connection->channel_client);
@@ -992,12 +994,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);
@@ -1261,11 +1264,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);
@@ -1490,10 +1494,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 953d193..08b3730 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -218,7 +218,8 @@ static void spicevmc_chardev_send_msg_to_client(RedPipeItem *msg,
 
 static SpiceVmcState *spicevmc_red_channel_client_get_state(RedChannelClient *rcc)
 {
-    return SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
+    return SPICE_CONTAINEROF(channel, SpiceVmcState, channel);
 }
 
 static void spicevmc_port_send_init(RedChannelClient *rcc)
@@ -263,8 +264,9 @@ static int spicevmc_red_channel_client_config_socket(RedChannelClient *rcc)
 {
     int delay_val = 1;
     RedsStream *stream = red_channel_client_get_stream(rcc);
+    RedChannel *channel = red_channel_client_get_channel(rcc);
 
-    if (rcc->channel->type == SPICE_CHANNEL_USBREDIR) {
+    if (channel->type == SPICE_CHANNEL_USBREDIR) {
         if (setsockopt(stream->socket, IPPROTO_TCP, TCP_NODELAY,
                 &delay_val, sizeof(delay_val)) != 0) {
             if (errno != ENOTSUP && errno != ENOPROTOOPT) {
diff --git a/server/stream.c b/server/stream.c
index e070202..d302168 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -690,7 +690,9 @@ static void update_client_playback_delay(void *opaque, uint32_t delay_ms)
 {
     StreamAgent *agent = opaque;
     DisplayChannelClient *dcc = agent->dcc;
-    RedsState *reds = red_channel_get_server(RED_CHANNEL_CLIENT(dcc)->channel);
+    RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(dcc));
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc));
+    RedsState *reds = red_channel_get_server(channel);
 
     dcc_update_streams_max_latency(dcc, agent);
 
@@ -700,7 +702,7 @@ static void update_client_playback_delay(void *opaque, uint32_t delay_ms)
     }
     spice_debug("resetting client latency: %u", dcc_get_max_stream_latency(agent->dcc));
     main_dispatcher_set_mm_time_latency(reds_get_main_dispatcher(reds),
-                                        RED_CHANNEL_CLIENT(agent->dcc)->client,
+                                        client,
                                         dcc_get_max_stream_latency(agent->dcc));
 }
 


More information about the Spice-commits mailing list