[Spice-commits] 3 commits - server/Makefile.am server/cursor-channel-client.c server/cursor-channel-client.h server/cursor-channel.c server/cursor-channel.h server/dcc.c server/dcc.h server/inputs-channel-client.c server/inputs-channel-client.h server/inputs-channel.c server/main-channel-client.c server/main-channel-client.h server/main-channel.c server/main-channel.h server/red-channel-capabilities.c server/red-channel-capabilities.h server/red-channel-client.c server/red-channel-client.h server/red-channel.c server/red-channel.h server/red-qxl.c server/red-qxl.h server/red-worker.c server/reds.c server/smartcard-channel-client.c server/smartcard-channel-client.h server/smartcard.c server/sound.c server/spicevmc.c

Frediano Ziglio fziglio at kemper.freedesktop.org
Thu Mar 2 15:36:18 UTC 2017


 server/Makefile.am                |    2 
 server/cursor-channel-client.c    |   22 ----------
 server/cursor-channel-client.h    |    4 -
 server/cursor-channel.c           |    6 --
 server/cursor-channel.h           |    3 -
 server/dcc.c                      |   22 ----------
 server/dcc.h                      |    5 --
 server/inputs-channel-client.c    |   23 ----------
 server/inputs-channel-client.h    |    5 --
 server/inputs-channel.c           |    7 ---
 server/main-channel-client.c      |   22 ----------
 server/main-channel-client.h      |    3 -
 server/main-channel.c             |    7 ---
 server/main-channel.h             |    4 -
 server/red-channel-capabilities.c |   68 ++++++++++++++++++++++++++++++++
 server/red-channel-capabilities.h |   51 ++++++++++++++++++++++++
 server/red-channel-client.c       |   80 +++-----------------------------------
 server/red-channel-client.h       |    3 -
 server/red-channel.c              |   19 ++-------
 server/red-channel.h              |   15 +------
 server/red-qxl.c                  |   24 ++---------
 server/red-qxl.h                  |   10 ----
 server/red-worker.c               |   12 +----
 server/reds.c                     |   41 +++++++++++++------
 server/smartcard-channel-client.c |   22 ----------
 server/smartcard-channel-client.h |    3 -
 server/smartcard.c                |    6 --
 server/sound.c                    |   37 +++--------------
 server/spicevmc.c                 |   11 ++---
 29 files changed, 217 insertions(+), 320 deletions(-)

New commits:
commit afc4171c9827d4f0d5f4ba9577813cf6b2399164
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Mon Feb 27 20:40:30 2017 +0000

    red-channel: Use RedChannelCapabilities directly to pass capabilities
    
    For each channel there are two set of capabilities, one
    for the common ones and one for the specific ones.
    A single set were almost always passed using 2 arguments,
    a number of elements and an array but then before using
    these were converted to a GArray.
    Use a single structure (already available) to pass all
    channel capabilites using a single argument.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/cursor-channel-client.c b/server/cursor-channel-client.c
index 56efd1e..1a05f73 100644
--- a/server/cursor-channel-client.c
+++ b/server/cursor-channel-client.c
@@ -93,21 +93,9 @@ void cursor_channel_client_migrate(RedChannelClient *rcc)
 
 CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor, RedClient *client, RedsStream *stream,
                                                int mig_target,
-                                               uint32_t *common_caps, int num_common_caps,
-                                               uint32_t *caps, int num_caps)
+                                               RedChannelCapabilities *caps)
 {
     CursorChannelClient *rcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
-
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
 
     rcc = g_initable_new(TYPE_CURSOR_CHANNEL_CLIENT,
                          NULL, NULL,
@@ -115,16 +103,10 @@ CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor, RedClient
                          "client", client,
                          "stream", stream,
                          "monitor-latency", FALSE,
-                         "common-caps", common_caps_array,
-                         "caps", caps_array,
+                         "caps", caps,
                          NULL);
     common_graphics_channel_set_during_target_migrate(COMMON_GRAPHICS_CHANNEL(cursor), mig_target);
 
-    if (caps_array)
-        g_array_unref(caps_array);
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-
     return rcc;
 }
 
diff --git a/server/cursor-channel-client.h b/server/cursor-channel-client.h
index d1dd31d..e2aa3a8 100644
--- a/server/cursor-channel-client.h
+++ b/server/cursor-channel-client.h
@@ -63,9 +63,7 @@ CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor,
                                                RedClient *client,
                                                RedsStream *stream,
                                                int mig_target,
-                                               uint32_t *common_caps,
-                                               int num_common_caps,
-                                               uint32_t *caps, int num_caps);
+                                               RedChannelCapabilities *caps);
 
 void cursor_channel_client_reset_cursor_cache(RedChannelClient *rcc);
 void cursor_channel_client_on_disconnect(RedChannelClient *rcc);
diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index fe56098..9d21962 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -406,8 +406,7 @@ void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode)
 
 void cursor_channel_connect(CursorChannel *cursor, RedClient *client, RedsStream *stream,
                             int migrate,
-                            uint32_t *common_caps, int num_common_caps,
-                            uint32_t *caps, int num_caps)
+                            RedChannelCapabilities *caps)
 {
     CursorChannelClient *ccc;
 
@@ -416,8 +415,7 @@ void cursor_channel_connect(CursorChannel *cursor, RedClient *client, RedsStream
     spice_debug("add cursor channel client");
     ccc = cursor_channel_client_new(cursor, client, stream,
                                     migrate,
-                                    common_caps, num_common_caps,
-                                    caps, num_caps);
+                                    caps);
     spice_return_if_fail(ccc != NULL);
 
     RedChannelClient *rcc = RED_CHANNEL_CLIENT(ccc);
diff --git a/server/cursor-channel.h b/server/cursor-channel.h
index ec9d44f..6bf8486 100644
--- a/server/cursor-channel.h
+++ b/server/cursor-channel.h
@@ -75,8 +75,7 @@ void                 cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32
 void                 cursor_channel_connect     (CursorChannel *cursor, RedClient *client,
                                                  RedsStream *stream,
                                                  int migrate,
-                                                 uint32_t *common_caps, int num_common_caps,
-                                                 uint32_t *caps, int num_caps);
+                                                 RedChannelCapabilities *caps);
 
 /**
  * Migrate a client channel from a CursorChannel.
diff --git a/server/dcc.c b/server/dcc.c
index e32004d..ba43c6c 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -482,25 +482,13 @@ static void dcc_init_stream_agents(DisplayChannelClient *dcc)
 DisplayChannelClient *dcc_new(DisplayChannel *display,
                               RedClient *client, RedsStream *stream,
                               int mig_target,
-                              uint32_t *common_caps, int num_common_caps,
-                              uint32_t *caps, int num_caps,
+                              RedChannelCapabilities *caps,
                               SpiceImageCompression image_compression,
                               spice_wan_compression_t jpeg_state,
                               spice_wan_compression_t zlib_glz_state)
 
 {
     DisplayChannelClient *dcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
-
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
 
     dcc = g_initable_new(TYPE_DISPLAY_CHANNEL_CLIENT,
                          NULL, NULL,
@@ -508,8 +496,7 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
                          "client", client,
                          "stream", stream,
                          "monitor-latency", TRUE,
-                         "common-caps", common_caps_array,
-                         "caps", caps_array,
+                         "caps", caps,
                          "image-compression", image_compression,
                          "jpeg-state", jpeg_state,
                          "zlib-glz-state", zlib_glz_state,
@@ -518,11 +505,6 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
     common_graphics_channel_set_during_target_migrate(COMMON_GRAPHICS_CHANNEL(display), mig_target);
     dcc->priv->id = common_graphics_channel_get_qxl(COMMON_GRAPHICS_CHANNEL(display))->id;
 
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-    if (caps_array)
-        g_array_unref(caps_array);
-
     return dcc;
 }
 
diff --git a/server/dcc.h b/server/dcc.h
index ebdbb8d..71fdfac 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -134,10 +134,7 @@ DisplayChannelClient*      dcc_new                                   (DisplayCha
                                                                       RedClient *client,
                                                                       RedsStream *stream,
                                                                       int mig_target,
-                                                                      uint32_t *common_caps,
-                                                                      int num_common_caps,
-                                                                      uint32_t *caps,
-                                                                      int num_caps,
+                                                                      RedChannelCapabilities *caps,
                                                                       SpiceImageCompression image_compression,
                                                                       spice_wan_compression_t jpeg_state,
                                                                       spice_wan_compression_t zlib_glz_state);
diff --git a/server/inputs-channel-client.c b/server/inputs-channel-client.c
index 4a534e8..72b5c39 100644
--- a/server/inputs-channel-client.c
+++ b/server/inputs-channel-client.c
@@ -48,38 +48,19 @@ RedChannelClient* inputs_channel_client_create(RedChannel *channel,
                                                RedClient *client,
                                                RedsStream *stream,
                                                int monitor_latency,
-                                               int num_common_caps,
-                                               uint32_t *common_caps,
-                                               int num_caps,
-                                               uint32_t *caps)
+                                               RedChannelCapabilities *caps)
 {
     RedChannelClient *rcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
 
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
     rcc = g_initable_new(TYPE_INPUTS_CHANNEL_CLIENT,
                          NULL, NULL,
                          "channel", channel,
                          "client", client,
                          "stream", stream,
                          "monitor-latency", monitor_latency,
-                         "caps", caps_array,
-                         "common-caps", common_caps_array,
+                         "caps", caps,
                          NULL);
 
-    if (caps_array)
-        g_array_unref(caps_array);
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-
     return rcc;
 }
 
diff --git a/server/inputs-channel-client.h b/server/inputs-channel-client.h
index 7550b3c..ba08dbf 100644
--- a/server/inputs-channel-client.h
+++ b/server/inputs-channel-client.h
@@ -60,10 +60,7 @@ RedChannelClient* inputs_channel_client_create(RedChannel *channel,
                                                RedClient *client,
                                                RedsStream *stream,
                                                int monitor_latency,
-                                               int num_common_caps,
-                                               uint32_t *common_caps,
-                                               int num_caps,
-                                               uint32_t *caps);
+                                               RedChannelCapabilities *caps);
 
 uint16_t inputs_channel_client_get_motion_count(InputsChannelClient* self);
 /* only for migration */
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index ed92e71..ec297a2 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -486,8 +486,7 @@ static void inputs_pipe_add_init(RedChannelClient *rcc)
 
 static void inputs_connect(RedChannel *channel, RedClient *client,
                            RedsStream *stream, int migration,
-                           int num_common_caps, uint32_t *common_caps,
-                           int num_caps, uint32_t *caps)
+                           RedChannelCapabilities *caps)
 {
     RedChannelClient *rcc;
 
@@ -497,9 +496,7 @@ static void inputs_connect(RedChannel *channel, RedClient *client,
     }
 
     spice_printerr("inputs channel client create");
-    rcc = inputs_channel_client_create(channel, client, stream, FALSE,
-                                       num_common_caps, common_caps,
-                                       num_caps, caps);
+    rcc = inputs_channel_client_create(channel, client, stream, FALSE, caps);
     if (!rcc) {
         return;
     }
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 6aace29..2b68407 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -651,21 +651,9 @@ static void ping_timer_cb(void *opaque)
 
 MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient *client,
                                               RedsStream *stream, uint32_t connection_id,
-                                              int num_common_caps, uint32_t *common_caps,
-                                              int num_caps, uint32_t *caps)
+                                              RedChannelCapabilities *caps)
 {
     MainChannelClient *mcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
-
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
 
     mcc = g_initable_new(TYPE_MAIN_CHANNEL_CLIENT,
                          NULL, NULL,
@@ -673,16 +661,10 @@ MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient
                          "client", client,
                          "stream", stream,
                          "monitor-latency", FALSE,
-                         "caps", caps_array,
-                         "common-caps", common_caps_array,
+                         "caps", caps,
                          "connection-id", connection_id,
                          NULL);
 
-    if (caps_array)
-        g_array_unref(caps_array);
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-
     return mcc;
 }
 
diff --git a/server/main-channel-client.h b/server/main-channel-client.h
index 14fb419..9c7009d 100644
--- a/server/main-channel-client.h
+++ b/server/main-channel-client.h
@@ -58,8 +58,7 @@ GType main_channel_client_get_type(void) G_GNUC_CONST;
 
 MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient *client,
                                               RedsStream *stream, uint32_t connection_id,
-                                              int num_common_caps, uint32_t *common_caps,
-                                              int num_caps, uint32_t *caps);
+                                              RedChannelCapabilities *caps);
 
 void main_channel_client_push_agent_tokens(MainChannelClient *mcc, uint32_t num_tokens);
 void main_channel_client_push_agent_data(MainChannelClient *mcc, uint8_t* data, size_t len,
diff --git a/server/main-channel.c b/server/main-channel.c
index 3a6e6cd..307c80f 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -287,8 +287,7 @@ static int main_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
 
 MainChannelClient *main_channel_link(MainChannel *channel, RedClient *client,
                                      RedsStream *stream, uint32_t connection_id, int migration,
-                                     int num_common_caps, uint32_t *common_caps, int num_caps,
-                                     uint32_t *caps)
+                                     RedChannelCapabilities *caps)
 {
     MainChannelClient *mcc;
 
@@ -298,9 +297,7 @@ MainChannelClient *main_channel_link(MainChannel *channel, RedClient *client,
     // into usage somewhere (not an issue until we return migration to it's
     // former glory)
     spice_printerr("add main channel client");
-    mcc = main_channel_client_create(channel, client, stream, connection_id,
-                                     num_common_caps, common_caps,
-                                     num_caps, caps);
+    mcc = main_channel_client_create(channel, client, stream, connection_id, caps);
     return mcc;
 }
 
diff --git a/server/main-channel.h b/server/main-channel.h
index b70649c..0209024 100644
--- a/server/main-channel.h
+++ b/server/main-channel.h
@@ -59,8 +59,8 @@ MainChannel *main_channel_new(RedsState *reds);
 RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t link_id);
 /* This is a 'clone' from the reds.h Channel.link callback to allow passing link_id */
 MainChannelClient *main_channel_link(MainChannel *, RedClient *client,
-     RedsStream *stream, uint32_t link_id, int migration, int num_common_caps,
-     uint32_t *common_caps, int num_caps, uint32_t *caps);
+     RedsStream *stream, uint32_t link_id, int migration,
+     RedChannelCapabilities *caps);
 void main_channel_push_mouse_mode(MainChannel *main_chan, int current_mode, int is_client_mouse_allowed);
 void main_channel_push_agent_connected(MainChannel *main_chan);
 void main_channel_push_agent_disconnected(MainChannel *main_chan);
diff --git a/server/red-channel-capabilities.c b/server/red-channel-capabilities.c
index eacb338..c08cc1a 100644
--- a/server/red-channel-capabilities.c
+++ b/server/red-channel-capabilities.c
@@ -62,7 +62,7 @@ static void red_channel_capabilities_free(RedChannelCapabilities *caps)
 SPICE_CONSTRUCTOR_FUNC(red_channel_capabilities_construct)
 {
     red_channel_capabilities_type =
-        g_boxed_type_register_static("red_channel_capabilities_type",
+        g_boxed_type_register_static("RedChannelCapabilities",
                                      (GBoxedCopyFunc) red_channel_capabilities_dup,
                                      (GBoxedFreeFunc) red_channel_capabilities_free);
 }
diff --git a/server/red-channel-client.c b/server/red-channel-client.c
index b6d67e7..441d20b 100644
--- a/server/red-channel-client.c
+++ b/server/red-channel-client.c
@@ -153,7 +153,6 @@ struct RedChannelClientPrivate
 static const SpiceDataHeaderOpaque full_header_wrapper;
 static const SpiceDataHeaderOpaque mini_header_wrapper;
 static void red_channel_client_clear_sent_item(RedChannelClient *rcc);
-static void red_channel_client_destroy_remote_caps(RedChannelClient* rcc);
 static void red_channel_client_initable_interface_init(GInitableIface *iface);
 static void red_channel_client_set_message_serial(RedChannelClient *channel, uint64_t);
 
@@ -188,7 +187,6 @@ enum {
     PROP_CHANNEL,
     PROP_CLIENT,
     PROP_MONITOR_LATENCY,
-    PROP_COMMON_CAPS,
     PROP_CAPS
 };
 
@@ -315,25 +313,12 @@ red_channel_client_set_property(GObject *object,
         case PROP_MONITOR_LATENCY:
             self->priv->monitor_latency = g_value_get_boolean(value);
             break;
-        case PROP_COMMON_CAPS:
-            {
-                GArray *caps = g_value_get_boxed(value);
-                if (caps) {
-                    self->priv->remote_caps.num_common_caps = caps->len;
-                    free(self->priv->remote_caps.common_caps);
-                    self->priv->remote_caps.common_caps =
-                        spice_memdup(caps->data, caps->len * sizeof(uint32_t));
-                }
-            }
-            break;
         case PROP_CAPS:
             {
-                GArray *caps = g_value_get_boxed(value);
+                RedChannelCapabilities *caps = g_value_get_boxed(value);
                 if (caps) {
-                    self->priv->remote_caps.num_caps = caps->len;
-                    free(self->priv->remote_caps.caps);
-                    self->priv->remote_caps.caps =
-                        spice_memdup(caps->data, caps->len * sizeof(uint32_t));
+                    red_channel_capabilities_reset(&self->priv->remote_caps);
+                    red_channel_capabilities_init(&self->priv->remote_caps, caps);
                 }
             }
             break;
@@ -358,7 +343,7 @@ red_channel_client_finalize(GObject *object)
         spice_marshaller_destroy(self->priv->send_data.urgent.marshaller);
     }
 
-    red_channel_client_destroy_remote_caps(self);
+    red_channel_capabilities_reset(&self->priv->remote_caps);
     if (self->priv->channel) {
         g_object_unref(self->priv->channel);
     }
@@ -434,17 +419,9 @@ static void red_channel_client_class_init(RedChannelClientClass *klass)
                                 | G_PARAM_CONSTRUCT_ONLY);
     g_object_class_install_property(object_class, PROP_MONITOR_LATENCY, spec);
 
-    spec = g_param_spec_boxed("common-caps", "common-caps",
-                              "Common Capabilities",
-                              G_TYPE_ARRAY,
-                              G_PARAM_STATIC_STRINGS
-                              | G_PARAM_WRITABLE
-                              | G_PARAM_CONSTRUCT_ONLY);
-    g_object_class_install_property(object_class, PROP_COMMON_CAPS, spec);
-
     spec = g_param_spec_boxed("caps", "caps",
                               "Capabilities",
-                              G_TYPE_ARRAY,
+                              RED_TYPE_CHANNEL_CAPABILITIES,
                               G_PARAM_STATIC_STRINGS
                               | G_PARAM_WRITABLE
                               | G_PARAM_CONSTRUCT_ONLY);
@@ -686,14 +663,6 @@ static gboolean red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeIte
     return g_queue_remove(&rcc->priv->pipe, item);
 }
 
-static void red_channel_client_destroy_remote_caps(RedChannelClient* rcc)
-{
-    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->priv->remote_caps.common_caps,
@@ -997,36 +966,19 @@ cleanup:
 RedChannelClient *red_channel_client_create(RedChannel *channel, RedClient *client,
                                             RedsStream *stream,
                                             int monitor_latency,
-                                            int num_common_caps, uint32_t *common_caps,
-                                            int num_caps, uint32_t *caps)
+                                            RedChannelCapabilities *caps)
 {
     RedChannelClient *rcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
 
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
     rcc = g_initable_new(RED_TYPE_CHANNEL_CLIENT,
                          NULL, NULL,
                          "channel", channel,
                          "client", client,
                          "stream", stream,
                          "monitor-latency", monitor_latency,
-                         "caps", caps_array,
-                         "common-caps", common_caps_array,
+                         "caps", caps,
                          NULL);
 
-    if (caps_array)
-        g_array_unref(caps_array);
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-
     return rcc;
 }
 
diff --git a/server/red-channel-client.h b/server/red-channel-client.h
index 474a5cd..1450089 100644
--- a/server/red-channel-client.h
+++ b/server/red-channel-client.h
@@ -50,8 +50,7 @@ GType red_channel_client_get_type(void) G_GNUC_CONST;
 RedChannelClient *red_channel_client_create(RedChannel *channel,
                                             RedClient *client, RedsStream *stream,
                                             int monitor_latency,
-                                            int num_common_caps, uint32_t *common_caps,
-                                            int num_caps, uint32_t *caps);
+                                            RedChannelCapabilities *caps);
 
 gboolean red_channel_client_is_connected(RedChannelClient *rcc);
 void red_channel_client_default_migrate(RedChannelClient *rcc);
diff --git a/server/red-channel.c b/server/red-channel.c
index 8fe0d33..d78c628 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -183,13 +183,7 @@ red_channel_finalize(GObject *object)
 {
     RedChannel *self = RED_CHANNEL(object);
 
-    if (self->priv->local_caps.num_common_caps) {
-        free(self->priv->local_caps.common_caps);
-    }
-
-    if (self->priv->local_caps.num_caps) {
-        free(self->priv->local_caps.caps);
-    }
+    red_channel_capabilities_reset(&self->priv->local_caps);
 
     G_OBJECT_CLASS(red_channel_parent_class)->finalize(object);
 }
@@ -219,8 +213,7 @@ red_channel_constructed(GObject *object)
 static void red_channel_client_default_connect(RedChannel *channel, RedClient *client,
                                                RedsStream *stream,
                                                int migration,
-                                               int num_common_caps, uint32_t *common_caps,
-                                               int num_caps, uint32_t *caps)
+                                               RedChannelCapabilities *caps)
 {
     spice_error("not implemented");
 }
@@ -513,12 +506,10 @@ void red_channel_disconnect(RedChannel *channel)
 }
 
 void red_channel_connect(RedChannel *channel, RedClient *client,
-                         RedsStream *stream, int migration, int num_common_caps,
-                         uint32_t *common_caps, int num_caps, uint32_t *caps)
+                         RedsStream *stream, int migration,
+                         RedChannelCapabilities *caps)
 {
-    channel->priv->client_cbs.connect(channel, client, stream, migration,
-                                      num_common_caps, common_caps, num_caps,
-                                      caps);
+    channel->priv->client_cbs.connect(channel, client, stream, migration, caps);
 }
 
 void red_channel_apply_clients(RedChannel *channel, channel_client_callback cb)
diff --git a/server/red-channel.h b/server/red-channel.h
index 6cee35f..e076e2a 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -61,8 +61,7 @@ typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient
 
 
 typedef void (*channel_client_connect_proc)(RedChannel *channel, RedClient *client, RedsStream *stream,
-                                            int migration, int num_common_caps, uint32_t *common_caps,
-                                            int num_caps, uint32_t *caps);
+                                            int migration, RedChannelCapabilities *caps);
 typedef void (*channel_client_disconnect_proc)(RedChannelClient *base);
 typedef void (*channel_client_migrate_proc)(RedChannelClient *base);
 
@@ -209,8 +208,8 @@ void red_channel_send(RedChannel *channel);
 // For red_worker
 void red_channel_disconnect(RedChannel *channel);
 void red_channel_connect(RedChannel *channel, RedClient *client,
-                         RedsStream *stream, int migration, int num_common_caps,
-                         uint32_t *common_caps, int num_caps, uint32_t *caps);
+                         RedsStream *stream, int migration,
+                         RedChannelCapabilities *caps);
 
 /* return the sum of all the rcc pipe size */
 uint32_t red_channel_max_pipe_size(RedChannel *channel);
diff --git a/server/red-qxl.c b/server/red-qxl.c
index b6b3770..53f3338 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -76,8 +76,7 @@ int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor)
 
 static void red_qxl_set_display_peer(RedChannel *channel, RedClient *client,
                                      RedsStream *stream, int migration,
-                                     int num_common_caps, uint32_t *common_caps, int num_caps,
-                                     uint32_t *caps)
+                                     RedChannelCapabilities *caps)
 {
     RedWorkerMessageDisplayConnect payload = {0,};
     Dispatcher *dispatcher;
@@ -87,13 +86,7 @@ static void red_qxl_set_display_peer(RedChannel *channel, RedClient *client,
     payload.client = client;
     payload.stream = stream;
     payload.migration = migration;
-    payload.num_common_caps = num_common_caps;
-    payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
-    payload.num_caps = num_caps;
-    payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);
-
-    memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
-    memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
+    red_channel_capabilities_init(&payload.caps, caps);
 
     dispatcher_send_message(dispatcher,
                             RED_WORKER_MESSAGE_DISPLAY_CONNECT,
@@ -142,9 +135,8 @@ static void red_qxl_display_migrate(RedChannelClient *rcc)
 }
 
 static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient *client, RedsStream *stream,
-                                    int migration, int num_common_caps,
-                                    uint32_t *common_caps, int num_caps,
-                                    uint32_t *caps)
+                                    int migration,
+                                    RedChannelCapabilities *caps)
 {
     RedWorkerMessageCursorConnect payload = {0,};
     Dispatcher *dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), "dispatcher");
@@ -152,13 +144,7 @@ static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient *client, Reds
     payload.client = client;
     payload.stream = stream;
     payload.migration = migration;
-    payload.num_common_caps = num_common_caps;
-    payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
-    payload.num_caps = num_caps;
-    payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);
-
-    memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
-    memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
+    red_channel_capabilities_init(&payload.caps, caps);
 
     dispatcher_send_message(dispatcher,
                             RED_WORKER_MESSAGE_CURSOR_CONNECT,
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 0c9498a..26e329d 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -126,11 +126,8 @@ enum {
 typedef struct RedWorkerMessageDisplayConnect {
     RedClient * client;
     RedsStream * stream;
-    uint32_t *common_caps; // red_worker should free
-    uint32_t *caps;        // red_worker should free
+    RedChannelCapabilities caps;   // red_worker should reset
     int migration;
-    int num_common_caps;
-    int num_caps;
 } RedWorkerMessageDisplayConnect;
 
 typedef struct RedWorkerMessageDisplayDisconnect {
@@ -145,10 +142,7 @@ typedef struct RedWorkerMessageCursorConnect {
     RedClient *client;
     RedsStream *stream;
     int migration;
-    uint32_t *common_caps; // red_worker should free
-    int num_common_caps;
-    uint32_t *caps;        // red_worker should free
-    int num_caps;
+    RedChannelCapabilities caps;   // red_worker should reset
 } RedWorkerMessageCursorConnect;
 
 typedef struct RedWorkerMessageCursorDisconnect {
diff --git a/server/red-worker.c b/server/red-worker.c
index 8735cd1..250c115 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -735,8 +735,7 @@ static void handle_dev_display_connect(void *opaque, void *payload)
     spice_debug("connect new client");
     spice_return_if_fail(display);
 
-    dcc = dcc_new(display, msg->client, msg->stream, msg->migration,
-                  msg->common_caps, msg->num_common_caps, msg->caps, msg->num_caps,
+    dcc = dcc_new(display, msg->client, msg->stream, msg->migration, &msg->caps,
                   worker->image_compression, worker->jpeg_state, worker->zlib_glz_state);
     if (!dcc) {
         return;
@@ -745,8 +744,7 @@ static void handle_dev_display_connect(void *opaque, void *payload)
     guest_set_client_capabilities(worker);
     dcc_start(dcc);
 
-    free(msg->caps);
-    free(msg->common_caps);
+    red_channel_capabilities_reset(&msg->caps);
 }
 
 static void handle_dev_display_disconnect(void *opaque, void *payload)
@@ -832,10 +830,8 @@ static void handle_dev_cursor_connect(void *opaque, void *payload)
     spice_debug("cursor connect");
     cursor_channel_connect(worker->cursor_channel,
                            msg->client, msg->stream, msg->migration,
-                           msg->common_caps, msg->num_common_caps,
-                           msg->caps, msg->num_caps);
-    free(msg->caps);
-    free(msg->common_caps);
+                           &msg->caps);
+    red_channel_capabilities_reset(&msg->caps);
 }
 
 static void handle_dev_cursor_disconnect(void *opaque, void *payload)
diff --git a/server/reds.c b/server/reds.c
index f99dfda..f7a32f8 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1675,6 +1675,26 @@ static RedClient *reds_get_client(RedsState *reds)
     return reds->clients->data;
 }
 
+static void
+red_channel_capabilities_init_from_link_message(RedChannelCapabilities *caps,
+                                                const SpiceLinkMess *link_mess)
+{
+    const uint32_t *raw_caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset);
+
+    caps->num_common_caps = link_mess->num_common_caps;
+    caps->common_caps = NULL;
+    if (caps->num_common_caps) {
+        caps->common_caps = spice_memdup(raw_caps,
+                                         link_mess->num_common_caps * sizeof(uint32_t));
+    }
+    caps->num_caps = link_mess->num_channel_caps;
+    caps->caps = NULL;
+    if (link_mess->num_channel_caps) {
+        caps->caps = spice_memdup(raw_caps + link_mess->num_common_caps,
+                                  link_mess->num_channel_caps * sizeof(uint32_t));
+    }
+}
+
 // TODO: now that main is a separate channel this should
 // actually be joined with reds_handle_other_links, become reds_handle_link
 static void reds_handle_main_link(RedsState *reds, RedLinkInfo *link)
@@ -1682,10 +1702,10 @@ static void reds_handle_main_link(RedsState *reds, RedLinkInfo *link)
     RedClient *client;
     RedsStream *stream;
     SpiceLinkMess *link_mess;
-    uint32_t *caps;
     uint32_t connection_id;
     MainChannelClient *mcc;
     int mig_target = FALSE;
+    RedChannelCapabilities caps;
 
     spice_debug(NULL);
     spice_assert(reds->main_channel);
@@ -1717,14 +1737,14 @@ static void reds_handle_main_link(RedsState *reds, RedLinkInfo *link)
     link->stream = NULL;
     link->link_mess = NULL;
     reds_link_free(link);
-    caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset);
     client = red_client_new(reds, mig_target);
     reds->clients = g_list_prepend(reds->clients, client);
+
+    red_channel_capabilities_init_from_link_message(&caps, link_mess);
     mcc = main_channel_link(reds->main_channel, client,
                             stream, connection_id, mig_target,
-                            link_mess->num_common_caps,
-                            link_mess->num_common_caps ? caps : NULL, link_mess->num_channel_caps,
-                            link_mess->num_channel_caps ? caps + link_mess->num_common_caps : NULL);
+                            &caps);
+    red_channel_capabilities_reset(&caps);
     spice_debug("NEW Client %p mcc %p connect-id %d", client, mcc, connection_id);
     free(link_mess);
     red_client_set_main(client, mcc);
@@ -1784,20 +1804,17 @@ static void reds_channel_do_link(RedChannel *channel, RedClient *client,
                                  SpiceLinkMess *link_msg,
                                  RedsStream *stream)
 {
-    uint32_t *caps;
+    RedChannelCapabilities caps;
 
     spice_assert(channel);
     spice_assert(link_msg);
     spice_assert(stream);
 
-    caps = (uint32_t *)((uint8_t *)link_msg + link_msg->caps_offset);
+    red_channel_capabilities_init_from_link_message(&caps, link_msg);
     red_channel_connect(channel, client, stream,
                         red_client_during_migrate_at_target(client),
-                        link_msg->num_common_caps,
-                        link_msg->num_common_caps ? caps : NULL,
-                        link_msg->num_channel_caps,
-                        link_msg->num_channel_caps ?
-                        caps + link_msg->num_common_caps : NULL);
+                        &caps);
+    red_channel_capabilities_reset(&caps);
 }
 
 /*
diff --git a/server/smartcard-channel-client.c b/server/smartcard-channel-client.c
index 6234844..04c5c04 100644
--- a/server/smartcard-channel-client.c
+++ b/server/smartcard-channel-client.c
@@ -103,21 +103,9 @@ smart_card_channel_client_init(SmartCardChannelClient *self)
 SmartCardChannelClient* smartcard_channel_client_create(RedChannel *channel,
                                                         RedClient *client, RedsStream *stream,
                                                         int monitor_latency,
-                                                        int num_common_caps, uint32_t *common_caps,
-                                                        int num_caps, uint32_t *caps)
+                                                        RedChannelCapabilities *caps)
 {
     SmartCardChannelClient *rcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
-
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
 
     rcc = g_initable_new(TYPE_SMARTCARD_CHANNEL_CLIENT,
                          NULL, NULL,
@@ -125,15 +113,9 @@ SmartCardChannelClient* smartcard_channel_client_create(RedChannel *channel,
                          "client", client,
                          "stream", stream,
                          "monitor-latency", monitor_latency,
-                         "caps", caps_array,
-                         "common-caps", common_caps_array,
+                         "caps", caps,
                          NULL);
 
-    if (caps_array)
-        g_array_unref(caps_array);
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-
     return rcc;
 }
 
diff --git a/server/smartcard-channel-client.h b/server/smartcard-channel-client.h
index 9350d7a..84181a4 100644
--- a/server/smartcard-channel-client.h
+++ b/server/smartcard-channel-client.h
@@ -58,8 +58,7 @@ GType smart_card_channel_client_get_type(void) G_GNUC_CONST;
 SmartCardChannelClient* smartcard_channel_client_create(RedChannel *channel,
                                                         RedClient *client, RedsStream *stream,
                                                         int monitor_latency,
-                                                        int num_common_caps, uint32_t *common_caps,
-                                                        int num_caps, uint32_t *caps);
+                                                        RedChannelCapabilities *caps);
 
 uint8_t* smartcard_channel_client_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                     uint16_t type,
diff --git a/server/smartcard.c b/server/smartcard.c
index 8f12fd9..7b8ad01 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -528,8 +528,7 @@ int smartcard_char_device_handle_migrate_data(RedCharDeviceSmartcard *smartcard,
 
 static void smartcard_connect_client(RedChannel *channel, RedClient *client,
                                      RedsStream *stream, int migration,
-                                     int num_common_caps, uint32_t *common_caps,
-                                     int num_caps, uint32_t *caps)
+                                     RedChannelCapabilities *caps)
 {
     SpiceCharDeviceInstance *char_device =
             smartcard_readers_get_unattached();
@@ -540,8 +539,7 @@ static void smartcard_connect_client(RedChannel *channel, RedClient *client,
                                           client,
                                           stream,
                                           FALSE,
-                                          num_common_caps, common_caps,
-                                          num_caps, caps);
+                                          caps);
 
     if (!scc) {
         return;
diff --git a/server/sound.c b/server/sound.c
index 770e223..2e614f0 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -1079,11 +1079,9 @@ playback_channel_client_constructed(GObject *object)
 }
 
 static void snd_set_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
-                         int num_common_caps, uint32_t *common_caps,
-                         int num_caps, uint32_t *caps, GType type)
+                         RedChannelCapabilities *caps, GType type)
 {
     SndChannel *channel = SND_CHANNEL(red_channel);
-    GArray *common_caps_array = NULL, *caps_array = NULL;
     SndChannelClient *snd_client;
 
     if (channel->connection) {
@@ -1091,40 +1089,21 @@ static void snd_set_peer(RedChannel *red_channel, RedClient *client, RedsStream
         channel->connection = NULL;
     }
 
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
-
     snd_client = g_initable_new(type,
                                 NULL, NULL,
                                 "channel", channel,
                                 "client", client,
                                 "stream", stream,
-                                "caps", caps_array,
-                                "common-caps", common_caps_array,
+                                "caps", caps,
                                 NULL);
     g_warn_if_fail(snd_client != NULL);
-
-    if (caps_array) {
-        g_array_unref(caps_array);
-    }
-    if (common_caps_array) {
-        g_array_unref(common_caps_array);
-    }
 }
 
 static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
-                                  G_GNUC_UNUSED int migration, int num_common_caps, uint32_t *common_caps,
-                                  int num_caps, uint32_t *caps)
+                                  G_GNUC_UNUSED int migration,
+                                  RedChannelCapabilities *caps)
 {
-    snd_set_peer(red_channel, client, stream,
-                 num_common_caps, common_caps, num_caps, caps,
+    snd_set_peer(red_channel, client, stream, caps,
                  TYPE_PLAYBACK_CHANNEL_CLIENT);
 }
 
@@ -1302,11 +1281,9 @@ record_channel_client_constructed(GObject *object)
 
 static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
                                 G_GNUC_UNUSED int migration,
-                                int num_common_caps, uint32_t *common_caps,
-                                int num_caps, uint32_t *caps)
+                                RedChannelCapabilities *caps)
 {
-    snd_set_peer(red_channel, client, stream,
-                 num_common_caps, common_caps, num_caps, caps,
+    snd_set_peer(red_channel, client, stream, caps,
                  TYPE_RECORD_CHANNEL_CLIENT);
 }
 
diff --git a/server/spicevmc.c b/server/spicevmc.c
index abb0b52..3951fa2 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -182,8 +182,8 @@ static void red_vmc_channel_port_init(RedVmcChannelPort *self)
 G_DEFINE_TYPE(RedVmcChannelPort, red_vmc_channel_port, RED_TYPE_VMC_CHANNEL)
 
 static void spicevmc_connect(RedChannel *channel, RedClient *client,
-                             RedsStream *stream, int migration, int num_common_caps,
-                             uint32_t *common_caps, int num_caps, uint32_t *caps);
+                             RedsStream *stream, int migration,
+                             RedChannelCapabilities *caps);
 
 static void
 red_vmc_channel_constructed(GObject *object)
@@ -764,8 +764,8 @@ red_vmc_channel_port_class_init(RedVmcChannelPortClass *klass)
 }
 
 static void spicevmc_connect(RedChannel *channel, RedClient *client,
-    RedsStream *stream, int migration, int num_common_caps,
-    uint32_t *common_caps, int num_caps, uint32_t *caps)
+    RedsStream *stream, int migration,
+    RedChannelCapabilities *caps)
 {
     RedChannelClient *rcc;
     RedVmcChannel *vmc_channel;
@@ -786,8 +786,7 @@ static void spicevmc_connect(RedChannel *channel, RedClient *client,
         return;
     }
 
-    rcc = red_channel_client_create(channel, client, stream, FALSE,
-                                    num_common_caps, common_caps, num_caps, caps);
+    rcc = red_channel_client_create(channel, client, stream, FALSE, caps);
     if (!rcc) {
         return;
     }
commit 89a722ce03c7b64c77b53462604394df96bd2a23
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Thu Mar 2 00:23:53 2017 +0000

    red-channel: Separate RedChannelCapabilities
    
    Add function to initialize and destroy this type.
    Add GType type for boxing it.
    These changes a in preparation for next patch.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Christophe Fergeau <cfergeau at redhat.com>

diff --git a/server/Makefile.am b/server/Makefile.am
index a043660..49c0822 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -101,6 +101,8 @@ libserver_la_SOURCES =				\
 	red-channel.h				\
 	red-channel-client.c			\
 	red-channel-client.h			\
+	red-channel-capabilities.c		\
+	red-channel-capabilities.h		\
 	red-client.c				\
 	red-client.h				\
 	red-common.h				\
diff --git a/server/red-channel-capabilities.c b/server/red-channel-capabilities.c
new file mode 100644
index 0000000..eacb338
--- /dev/null
+++ b/server/red-channel-capabilities.c
@@ -0,0 +1,68 @@
+/*
+   Copyright (C) 2017 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <common/mem.h>
+#include <common/macros.h>
+
+#include "red-channel-capabilities.h"
+
+GType red_channel_capabilities_type;
+
+void red_channel_capabilities_init(RedChannelCapabilities *dest,
+                                   const RedChannelCapabilities *caps)
+{
+    *dest = *caps;
+    if (caps->common_caps) {
+        dest->common_caps = spice_memdup(caps->common_caps,
+                                         caps->num_common_caps * sizeof(uint32_t));
+    }
+    if (caps->num_caps) {
+        dest->caps = spice_memdup(caps->caps, caps->num_caps * sizeof(uint32_t));
+    }
+}
+
+void red_channel_capabilities_reset(RedChannelCapabilities *caps)
+{
+    free(caps->common_caps);
+    free(caps->caps);
+    memset(caps, 0, sizeof(*caps));
+}
+
+static RedChannelCapabilities *red_channel_capabilities_dup(const RedChannelCapabilities *caps)
+{
+    RedChannelCapabilities *res = spice_new(RedChannelCapabilities, 1);
+    red_channel_capabilities_init(res, caps);
+    return res;
+}
+
+static void red_channel_capabilities_free(RedChannelCapabilities *caps)
+{
+    red_channel_capabilities_reset(caps);
+    free(caps);
+}
+
+SPICE_CONSTRUCTOR_FUNC(red_channel_capabilities_construct)
+{
+    red_channel_capabilities_type =
+        g_boxed_type_register_static("red_channel_capabilities_type",
+                                     (GBoxedCopyFunc) red_channel_capabilities_dup,
+                                     (GBoxedFreeFunc) red_channel_capabilities_free);
+}
diff --git a/server/red-channel-capabilities.h b/server/red-channel-capabilities.h
new file mode 100644
index 0000000..f590eb2
--- /dev/null
+++ b/server/red-channel-capabilities.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009-2017 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef RED_CHANNEL_CAPABILITIES_H_
+#define RED_CHANNEL_CAPABILITIES_H_
+
+#include <stdint.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* Holds channel capabilities.
+ * Channel capabilities are composed by a common part
+ * and a specific one. */
+typedef struct RedChannelCapabilities {
+    int num_common_caps;
+    uint32_t *common_caps;
+    int num_caps;
+    uint32_t *caps;
+} RedChannelCapabilities;
+
+/* Initialize the structure based on a previous one. */
+void red_channel_capabilities_init(RedChannelCapabilities *dest,
+                                   const RedChannelCapabilities *caps);
+
+/* Reset capabilities.
+ * All resources are freed by this function. */
+void red_channel_capabilities_reset(RedChannelCapabilities *caps);
+
+/* GObject type that can be used to box RedChannelCapabilities */
+extern GType red_channel_capabilities_type;
+#define RED_TYPE_CHANNEL_CAPABILITIES red_channel_capabilities_type
+
+G_END_DECLS
+
+#endif
diff --git a/server/red-channel.h b/server/red-channel.h
index 79aee01..6cee35f 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -34,6 +34,7 @@
 #include "reds-stream.h"
 #include "stat.h"
 #include "red-pipe-item.h"
+#include "red-channel-capabilities.h"
 
 G_BEGIN_DECLS
 
@@ -135,13 +136,6 @@ struct RedChannelClass
 
 /* Red Channel interface */
 
-typedef struct RedChannelCapabilities {
-    int num_common_caps;
-    uint32_t *common_caps;
-    int num_caps;
-    uint32_t *caps;
-} RedChannelCapabilities;
-
 GType red_channel_get_type(void) G_GNUC_CONST;
 
 void red_channel_add_client(RedChannel *channel, RedChannelClient *rcc);
commit 5b3f79f8a7fd5698d58d25521877891218411b3a
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Wed Mar 1 22:53:22 2017 +0000

    red-channel-client: Make capabilities property write only
    
    These properties are not read and code is broken (the content of
    the array would be uninitialized).
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Christophe Fergeau <cfergeau at redhat.com>

diff --git a/server/red-channel-client.c b/server/red-channel-client.c
index cd4b64e..b6d67e7 100644
--- a/server/red-channel-client.c
+++ b/server/red-channel-client.c
@@ -286,22 +286,6 @@ red_channel_client_get_property(GObject *object,
         case PROP_MONITOR_LATENCY:
             g_value_set_boolean(value, self->priv->monitor_latency);
             break;
-        case PROP_COMMON_CAPS:
-            {
-                GArray *arr = g_array_sized_new(FALSE, FALSE,
-                                                sizeof(*self->priv->remote_caps.common_caps),
-                                                self->priv->remote_caps.num_common_caps);
-                g_value_take_boxed(value, arr);
-            }
-            break;
-        case PROP_CAPS:
-            {
-                GArray *arr = g_array_sized_new(FALSE, FALSE,
-                                                sizeof(*self->priv->remote_caps.caps),
-                                                self->priv->remote_caps.num_caps);
-                g_value_take_boxed(value, arr);
-            }
-            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
     }
@@ -454,7 +438,7 @@ static void red_channel_client_class_init(RedChannelClientClass *klass)
                               "Common Capabilities",
                               G_TYPE_ARRAY,
                               G_PARAM_STATIC_STRINGS
-                              | G_PARAM_READWRITE
+                              | G_PARAM_WRITABLE
                               | G_PARAM_CONSTRUCT_ONLY);
     g_object_class_install_property(object_class, PROP_COMMON_CAPS, spec);
 
@@ -462,7 +446,7 @@ static void red_channel_client_class_init(RedChannelClientClass *klass)
                               "Capabilities",
                               G_TYPE_ARRAY,
                               G_PARAM_STATIC_STRINGS
-                              | G_PARAM_READWRITE
+                              | G_PARAM_WRITABLE
                               | G_PARAM_CONSTRUCT_ONLY);
     g_object_class_install_property(object_class, PROP_CAPS, spec);
 }


More information about the Spice-commits mailing list