[Spice-commits] 10 commits - server/cache-item.tmpl.c server/char-device.c server/cursor-channel.c server/dcc-encoders.c server/dcc-send.c server/dcc.c server/dcc.h server/dispatcher.c server/display-channel.c server/image-cache.c server/inputs-channel.c server/main-channel-client.c server/main-channel.c server/pixmap-cache.c server/red-channel.c server/red-channel.h server/red-pipe-item.c server/red-pipe-item.h server/red-replay-qxl.c server/reds.c server/smartcard.c server/spicevmc.c server/stream.c server/tree.c server/tree.h

Frediano Ziglio fziglio at kemper.freedesktop.org
Sat May 21 03:15:08 UTC 2016


 server/cache-item.tmpl.c     |    1 +
 server/char-device.c         |    2 +-
 server/cursor-channel.c      |   23 ++++++++---------------
 server/dcc-encoders.c        |    2 +-
 server/dcc-send.c            |   20 ++++++++------------
 server/dcc.c                 |   19 +++++++++++--------
 server/dcc.h                 |    2 +-
 server/dispatcher.c          |    3 +--
 server/display-channel.c     |   41 +++++++++++++++--------------------------
 server/image-cache.c         |    7 +++++--
 server/inputs-channel.c      |    5 -----
 server/main-channel-client.c |   16 ++++++++--------
 server/main-channel.c        |    5 -----
 server/pixmap-cache.c        |    3 ++-
 server/red-channel.c         |   36 ++++++++++++++++++++++++++++++------
 server/red-channel.h         |    3 +--
 server/red-pipe-item.c       |   12 ++++--------
 server/red-pipe-item.h       |   14 +++++++++-----
 server/red-replay-qxl.c      |    2 +-
 server/reds.c                |   36 ++++++++++++++++++------------------
 server/smartcard.c           |   20 +++++++-------------
 server/spicevmc.c            |   15 +++------------
 server/stream.c              |   17 ++++++++++-------
 server/tree.c                |   12 +++++++-----
 server/tree.h                |    8 ++++----
 25 files changed, 156 insertions(+), 168 deletions(-)

New commits:
commit 70f04bdab30e732a6b5ccc1e3b9ea4d37184a8c0
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 20 13:39:56 2016 +0100

    Get code more typesafe
    
    Scan remaining code searching for problems with structure
    layout assumptions in the code.
    Where code required some restructuring put some verify checks
    to make sure code won't compile if these assumptions are not
    in place anymore.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/cache-item.tmpl.c b/server/cache-item.tmpl.c
index 0617bea..0f22b35 100644
--- a/server/cache-item.tmpl.c
+++ b/server/cache-item.tmpl.c
@@ -93,6 +93,7 @@ static int FUNC_NAME(add)(CHANNELCLIENT *channel_client, uint64_t id, size_t siz
     item = spice_new(RedCacheItem, 1);
 
     channel_client->VAR_NAME(available) -= size;
+    verify(SPICE_OFFSETOF(RedCacheItem, u.cache_data.lru_link) == 0);
     while (channel_client->VAR_NAME(available) < 0) {
         RedCacheItem *tail = (RedCacheItem *)ring_get_tail(&channel_client->VAR_NAME(lru));
         if (!tail) {
diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index c257654..23a8cb8 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -321,10 +321,10 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
         cursor_marshall(rcc, m, SPICE_CONTAINEROF(pipe_item, RedCursorPipeItem, base));
         break;
     case RED_PIPE_ITEM_TYPE_INVAL_ONE:
-        red_marshall_inval(rcc, m, (RedCacheItem *)pipe_item);
+        red_marshall_inval(rcc, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data));
         break;
     case RED_PIPE_ITEM_TYPE_VERB:
-        red_marshall_verb(rcc, (RedVerbItem*)pipe_item);
+        red_marshall_verb(rcc, SPICE_CONTAINEROF(pipe_item, RedVerbItem, base));
         break;
     case RED_PIPE_ITEM_TYPE_CURSOR_INIT:
         red_reset_cursor_cache(rcc);
diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index f1dd1bb..65f5a17 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -624,7 +624,7 @@ static GlzSharedDictionary *find_glz_dictionary(RedClient *client, uint8_t dict_
 
     now = &glz_dictionary_list;
     while ((now = ring_next(&glz_dictionary_list, now))) {
-        GlzSharedDictionary *dict = (GlzSharedDictionary *)now;
+        GlzSharedDictionary *dict = SPICE_CONTAINEROF(now, GlzSharedDictionary, base);
         if ((dict->client == client) && (dict->id == dict_id)) {
             ret = dict;
             break;
diff --git a/server/dcc-send.c b/server/dcc-send.c
index 8ec22c8..193396a 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -2380,34 +2380,32 @@ void dcc_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
         break;
     }
     case RED_PIPE_ITEM_TYPE_INVAL_ONE:
-        marshall_inval_palette(rcc, m, (RedCacheItem *)pipe_item);
+        marshall_inval_palette(rcc, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data));
         break;
     case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
         StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base);
         marshall_stream_start(rcc, m, item->agent);
         break;
     }
-    case RED_PIPE_ITEM_TYPE_STREAM_CLIP: {
-        RedStreamClipItem* clip_item = (RedStreamClipItem *)pipe_item;
-        marshall_stream_clip(rcc, m, clip_item);
+    case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
+        marshall_stream_clip(rcc, m, SPICE_CONTAINEROF(pipe_item, RedStreamClipItem, base));
         break;
-    }
     case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
         StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base);
         marshall_stream_end(rcc, m, item->agent);
         break;
     }
     case RED_PIPE_ITEM_TYPE_UPGRADE:
-        marshall_upgrade(rcc, m, (RedUpgradeItem *)pipe_item);
+        marshall_upgrade(rcc, m, SPICE_CONTAINEROF(pipe_item, RedUpgradeItem, base));
         break;
     case RED_PIPE_ITEM_TYPE_VERB:
-        red_marshall_verb(rcc, (RedVerbItem*)pipe_item);
+        red_marshall_verb(rcc, SPICE_CONTAINEROF(pipe_item, RedVerbItem, base));
         break;
     case RED_PIPE_ITEM_TYPE_MIGRATE_DATA:
         display_channel_marshall_migrate_data(rcc, m);
         break;
     case RED_PIPE_ITEM_TYPE_IMAGE:
-        red_marshall_image(rcc, m, (RedImageItem *)pipe_item);
+        red_marshall_image(rcc, m, SPICE_CONTAINEROF(pipe_item, RedImageItem, base));
         break;
     case RED_PIPE_ITEM_TYPE_PIXMAP_SYNC:
         display_channel_marshall_pixmap_sync(rcc, m);
diff --git a/server/dcc.c b/server/dcc.c
index 20a8f11..e4af915 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -87,7 +87,7 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
             dpi = SPICE_CONTAINEROF(item, RedDrawablePipeItem, dpi_pipe_item);
             drawable = dpi->drawable;
         } else if (item->type == RED_PIPE_ITEM_TYPE_UPGRADE) {
-            drawable = ((RedUpgradeItem *)item)->drawable;
+            drawable = SPICE_CONTAINEROF(item, RedUpgradeItem, base)->drawable;
         } else {
             continue;
         }
@@ -530,7 +530,7 @@ static RedMonitorsConfigItem *red_monitors_config_item_new(RedChannel* channel,
 {
     RedMonitorsConfigItem *mci;
 
-    mci = (RedMonitorsConfigItem *)spice_malloc(sizeof(*mci));
+    mci = spice_new(RedMonitorsConfigItem, 1);
     mci->monitors_config = monitors_config;
 
     red_pipe_item_init_full(&mci->pipe_item, RED_PIPE_ITEM_TYPE_MONITORS_CONFIG,
@@ -1323,6 +1323,7 @@ int dcc_pixmap_cache_unlocked_add(DisplayChannelClient *dcc, uint64_t id,
         NewCacheItem *tail;
         NewCacheItem **now;
 
+        verify(SPICE_OFFSETOF(NewCacheItem, lru_link) == 0);
         if (!(tail = (NewCacheItem *)ring_get_tail(&cache->lru)) ||
                                                    tail->sync[dcc->id] == serial) {
             cache->available += size;
diff --git a/server/dispatcher.c b/server/dispatcher.c
index b9e23f6..8c55881 100644
--- a/server/dispatcher.c
+++ b/server/dispatcher.c
@@ -299,8 +299,7 @@ static int dispatcher_handle_single_read(Dispatcher *dispatcher)
             /* TODO: close socketpair? */
         }
     } else if (msg->ack == DISPATCHER_ASYNC && dispatcher->priv->handle_async_done) {
-        dispatcher->priv->handle_async_done(dispatcher->priv->opaque, type,
-                                      (void *)payload);
+        dispatcher->priv->handle_async_done(dispatcher->priv->opaque, type, payload);
     }
     return 1;
 }
diff --git a/server/display-channel.c b/server/display-channel.c
index 9f97911..96a6f2f 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -390,7 +390,7 @@ static void current_remove(DisplayChannel *display, TreeItem *item)
             drawable_remove_from_pipes(drawable);
             current_remove_drawable(display, drawable);
         } else {
-            Container *container = (Container *)now;
+            Container *container = CONTAINER(now);
 
             spice_assert(now->type == TREE_ITEM_TYPE_CONTAINER);
 
@@ -408,7 +408,7 @@ static void current_remove(DisplayChannel *display, TreeItem *item)
         if ((ring_item = ring_next(&container->items, ring_item))) {
             now = SPICE_CONTAINEROF(ring_item, TreeItem, siblings_link);
         } else {
-            now = (TreeItem *)container;
+            now = &container->base;
         }
     }
 }
@@ -433,7 +433,7 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
     if (other->type != TREE_ITEM_TYPE_DRAWABLE) {
         return FALSE;
     }
-    other_draw_item = (DrawItem *)other;
+    other_draw_item = DRAW_ITEM(other);
 
     if (item->shadow || other_draw_item->shadow || item->effect != other_draw_item->effect) {
         return FALSE;
@@ -530,7 +530,7 @@ static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem *item
     region_and(&and_rgn, &item->rgn);
     if (!region_is_empty(&and_rgn)) {
         if (IS_DRAW_ITEM(item)) {
-            DrawItem *draw = (DrawItem *)item;
+            DrawItem *draw = DRAW_ITEM(item);
 
             if (draw->effect == QXL_EFFECT_OPAQUE) {
                 region_exclude(rgn, &and_rgn);
@@ -551,8 +551,8 @@ static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem *item
                     region_exclude(&shadow->on_hold, &and_rgn);
                     region_or(rgn, &and_rgn);
                     // in flat representation of current, shadow is always his owner next
-                    if (!tree_item_contained_by((TreeItem*)shadow, *top_ring)) {
-                        *top_ring = tree_item_container_items((TreeItem*)shadow, ring);
+                    if (!tree_item_contained_by(&shadow->base, *top_ring)) {
+                        *top_ring = tree_item_container_items(&shadow->base, ring);
                     }
                 }
             } else {
@@ -571,8 +571,8 @@ static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem *item
                 region_exclude(rgn, &and_rgn);
                 if ((shadow = tree_item_find_shadow(item))) {
                     region_or(rgn, &shadow->on_hold);
-                    if (!tree_item_contained_by((TreeItem*)shadow, *top_ring)) {
-                        *top_ring = tree_item_container_items((TreeItem*)shadow, ring);
+                    if (!tree_item_contained_by(&shadow->base, *top_ring)) {
+                        *top_ring = tree_item_container_items(&shadow->base, ring);
                     }
                 }
             }
@@ -580,7 +580,7 @@ static void __exclude_region(DisplayChannel *display, Ring *ring, TreeItem *item
             Shadow *shadow;
 
             spice_assert(item->type == TREE_ITEM_TYPE_SHADOW);
-            shadow = (Shadow *)item;
+            shadow = SHADOW(item);
             region_exclude(rgn, &and_rgn);
             region_or(&shadow->on_hold, &and_rgn);
         }
@@ -615,13 +615,14 @@ static void exclude_region(DisplayChannel *display, Ring *ring, RingItem *ring_i
                 ring_item = now->siblings_link.prev;
                 current_remove(display, now);
                 if (last && *last == now) {
+                    verify(SPICE_OFFSETOF(TreeItem, siblings_link) == 0);
                     *last = (TreeItem *)ring_next(ring, ring_item);
                 }
             } else if (now->type == TREE_ITEM_TYPE_CONTAINER) {
-                Container *container = (Container *)now;
+                Container *container = CONTAINER(now);
                 if ((ring_item = ring_get_head(&container->items))) {
                     ring = &container->items;
-                    spice_assert(((TreeItem *)ring_item)->container);
+                    spice_assert(SPICE_CONTAINEROF(ring_item, TreeItem, siblings_link)->container);
                     continue;
                 }
                 ring_item = &now->siblings_link;
@@ -633,6 +634,7 @@ static void exclude_region(DisplayChannel *display, Ring *ring, RingItem *ring_i
             }
         }
 
+        verify(SPICE_OFFSETOF(TreeItem, siblings_link) == 0);
         while ((last && *last == (TreeItem *)ring_item) ||
                !(ring_item = ring_next(ring, ring_item))) {
             if (ring == top_ring) {
@@ -755,7 +757,7 @@ static int current_add(DisplayChannel *display, Ring *ring, Drawable *drawable)
                     exclude_base = NULL;
                 }
                 if (sibling->type == TREE_ITEM_TYPE_CONTAINER) {
-                    container = (Container *)sibling;
+                    container = CONTAINER(sibling);
                     ring = &container->items;
                     item->base.container = container;
                     now = ring_next(ring, ring);
diff --git a/server/image-cache.c b/server/image-cache.c
index 4237034..8fb090f 100644
--- a/server/image-cache.c
+++ b/server/image-cache.c
@@ -74,11 +74,12 @@ static void image_cache_remove(ImageCache *cache, ImageCacheItem *item)
 
 static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_image_t *image)
 {
-    ImageCache *cache = (ImageCache *)spice_cache;
+    ImageCache *cache = SPICE_CONTAINEROF(spice_cache, ImageCache, base);
     ImageCacheItem *item;
 
 #ifndef IMAGE_CACHE_AGE
     if (cache->num_items == IMAGE_CACHE_MAX_ITEMS) {
+        verify(SPICE_OFFSETOF(ImageCacheItem, lru_link) == 0);
         ImageCacheItem *tail = (ImageCacheItem *)ring_get_tail(&cache->lru);
         spice_assert(tail);
         image_cache_remove(cache, tail);
@@ -103,7 +104,7 @@ static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_im
 
 static pixman_image_t *image_cache_get(SpiceImageCache *spice_cache, uint64_t id)
 {
-    ImageCache *cache = (ImageCache *)spice_cache;
+    ImageCache *cache = SPICE_CONTAINEROF(spice_cache, ImageCache,base);
 
     ImageCacheItem *item = image_cache_find(cache, id);
     if (!item) {
@@ -133,6 +134,7 @@ void image_cache_reset(ImageCache *cache)
 {
     ImageCacheItem *item;
 
+    verify(SPICE_OFFSETOF(ImageCacheItem, lru_link) == 0);
     while ((item = (ImageCacheItem *)ring_get_head(&cache->lru))) {
         image_cache_remove(cache, item);
     }
@@ -145,6 +147,7 @@ void image_cache_reset(ImageCache *cache)
 
 void image_cache_aging(ImageCache *cache)
 {
+    verify(SPICE_OFFSETOF(ImageCacheItem, lru_link) == 0);
 #ifdef IMAGE_CACHE_AGE
     ImageCacheItem *item;
 
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 1ec6c82..6a314b6 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -116,10 +116,9 @@ static void main_notify_item_free(RedPipeItem *base)
     free(data);
 }
 
-static RedPipeItem *main_notify_item_new(void *data, int num)
+static RedPipeItem *main_notify_item_new(const char *msg, int num)
 {
     RedNotifyPipeItem *item = spice_malloc(sizeof(RedNotifyPipeItem));
-    const char *msg = data;
 
     red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY,
                             main_notify_item_free);
@@ -294,7 +293,7 @@ void main_channel_client_push_uuid(MainChannelClient *mcc, const uint8_t uuid[16
 
 void main_channel_client_push_notify(MainChannelClient *mcc, const char *msg)
 {
-    RedPipeItem *item = main_notify_item_new((void *)msg, 1);
+    RedPipeItem *item = main_notify_item_new(msg, 1);
     red_channel_client_pipe_add_push(&mcc->base, item);
 }
 
diff --git a/server/pixmap-cache.c b/server/pixmap-cache.c
index a485268..6b818d8 100644
--- a/server/pixmap-cache.c
+++ b/server/pixmap-cache.c
@@ -46,6 +46,7 @@ void pixmap_cache_clear(PixmapCache *cache)
         cache->freezed = FALSE;
     }
 
+    verify(SPICE_OFFSETOF(NewCacheItem, lru_link) == 0);
     while ((item = (NewCacheItem *)ring_get_head(&cache->lru))) {
         ring_remove(&item->lru_link);
         free(item);
@@ -113,7 +114,7 @@ PixmapCache *pixmap_cache_get(RedClient *client, uint8_t id, int64_t size)
 
     now = &pixmap_cache_list;
     while ((now = ring_next(&pixmap_cache_list, now))) {
-        PixmapCache *cache = (PixmapCache *)now;
+        PixmapCache *cache = SPICE_CONTAINEROF(now, PixmapCache, base);
         if ((cache->client == client) && (cache->id == id)) {
             ret = cache;
             ret->refs++;
diff --git a/server/red-replay-qxl.c b/server/red-replay-qxl.c
index 60e4183..17019f8 100644
--- a/server/red-replay-qxl.c
+++ b/server/red-replay-qxl.c
@@ -369,7 +369,7 @@ static QXLImage *red_replay_image(SpiceReplay *replay, uint32_t flags)
         return NULL;
     }
 
-    qxl = (QXLImage*)spice_malloc0(sizeof(QXLImage));
+    qxl = spice_new0(QXLImage, 1);
     replay_fscanf(replay, "descriptor.id %"PRIu64"\n", &qxl->descriptor.id);
     replay_fscanf(replay, "descriptor.type %d\n", &temp); qxl->descriptor.type = temp;
     replay_fscanf(replay, "descriptor.flags %d\n", &temp); qxl->descriptor.flags = temp;
diff --git a/server/smartcard.c b/server/smartcard.c
index 9280038..f68ce48 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -440,7 +440,7 @@ static void smartcard_channel_send_data(RedChannelClient *rcc, SpiceMarshaller *
 static void smartcard_channel_send_error(
     RedChannelClient *rcc, SpiceMarshaller *m, RedPipeItem *item)
 {
-    RedErrorItem* error_item = (RedErrorItem*)item;
+    RedErrorItem* error_item = SPICE_CONTAINEROF(item, RedErrorItem, base);
 
     smartcard_channel_send_data(rcc, m, item, &error_item->vheader);
 }
@@ -448,7 +448,7 @@ static void smartcard_channel_send_error(
 static void smartcard_channel_send_msg(RedChannelClient *rcc,
                                        SpiceMarshaller *m, RedPipeItem *item)
 {
-    RedMsgItem* msg_item = (RedMsgItem*)item;
+    RedMsgItem* msg_item = SPICE_CONTAINEROF(item, RedMsgItem, base);
 
     smartcard_channel_send_data(rcc, m, item, msg_item->vheader);
 }
diff --git a/server/tree.c b/server/tree.c
index 9e5a281..7da8d7d 100644
--- a/server/tree.c
+++ b/server/tree.c
@@ -153,7 +153,7 @@ static void dump_item(TreeItem *item, void *data)
     }
     case TREE_ITEM_TYPE_CONTAINER:
         di->level++;
-        di->container = (Container *)item;
+        di->container = CONTAINER(item);
         break;
     case TREE_ITEM_TYPE_SHADOW:
         break;
@@ -168,7 +168,7 @@ static void tree_foreach(TreeItem *item, void (*f)(TreeItem *, void *), void * d
     f(item, data);
 
     if (item->type == TREE_ITEM_TYPE_CONTAINER) {
-        Container *container = (Container*)item;
+        Container *container = CONTAINER(item);
         RingItem *it;
 
         RING_FOREACH(it, &container->items) {
@@ -240,6 +240,7 @@ void container_cleanup(Container *container)
     while (container && container->items.next == container->items.prev) {
         Container *next = container->base.container;
         if (container->items.next != &container->items) {
+            verify(SPICE_OFFSETOF(TreeItem, siblings_link) == 0);
             TreeItem *item = (TreeItem *)ring_get_head(&container->items);
             spice_assert(item);
             ring_remove(&item->siblings_link);
@@ -255,7 +256,8 @@ void container_cleanup(Container *container)
 Shadow* tree_item_find_shadow(TreeItem *item)
 {
     while (item->type == TREE_ITEM_TYPE_CONTAINER) {
-        if (!(item = (TreeItem *)ring_get_tail(&((Container *)item)->items))) {
+        verify(SPICE_OFFSETOF(TreeItem, siblings_link) == 0);
+        if (!(item = (TreeItem *)ring_get_tail(&CONTAINER(item)->items))) {
             return NULL;
         }
     }
@@ -264,7 +266,7 @@ Shadow* tree_item_find_shadow(TreeItem *item)
         return NULL;
     }
 
-    return ((DrawItem *)item)->shadow;
+    return DRAW_ITEM(item)->shadow;
 }
 
 Ring *tree_item_container_items(TreeItem *item, Ring *ring)
@@ -280,7 +282,7 @@ int tree_item_contained_by(TreeItem *item, Ring *ring)
         if (now == ring) {
             return TRUE;
         }
-    } while ((item = (TreeItem *)item->container));
+    } while ((item = &item->container->base));
 
     return FALSE;
 }
diff --git a/server/tree.h b/server/tree.h
index 5260ce8..e8da58d 100644
--- a/server/tree.h
+++ b/server/tree.h
@@ -54,7 +54,7 @@ struct Shadow {
 };
 
 #define IS_SHADOW(item) ((item)->type == TREE_ITEM_TYPE_SHADOW)
-#define SHADOW(item) ((Shadow*)(item))
+#define SHADOW(item) SPICE_CONTAINEROF(item, Shadow, base)
 
 struct Container {
     TreeItem base;
@@ -62,7 +62,7 @@ struct Container {
 };
 
 #define IS_CONTAINER(item) ((item)->type == TREE_ITEM_TYPE_CONTAINER)
-#define CONTAINER(item) ((Container*)(item))
+#define CONTAINER(item) SPICE_CONTAINEROF(item, Container, base)
 
 struct DrawItem {
     TreeItem base;
@@ -72,12 +72,12 @@ struct DrawItem {
 };
 
 #define IS_DRAW_ITEM(item) ((item)->type == TREE_ITEM_TYPE_DRAWABLE)
-#define DRAW_ITEM(item) ((DrawItem*)(item))
+#define DRAW_ITEM(item) SPICE_CONTAINEROF(item, DrawItem, base)
 
 static inline int is_opaque_item(TreeItem *item)
 {
     return item->type == TREE_ITEM_TYPE_CONTAINER ||
-        (IS_DRAW_ITEM(item) && ((DrawItem *)item)->effect == QXL_EFFECT_OPAQUE);
+        (IS_DRAW_ITEM(item) && DRAW_ITEM(item)->effect == QXL_EFFECT_OPAQUE);
 }
 
 void       tree_item_dump                           (TreeItem *item);
commit fb655ff4811a1c46feda83c4b5c969707b532ffb
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Sat May 14 12:51:07 2016 +0100

    reduce casts to RedPipeItem and RingItem
    
    Make code more type safe. This allow to move or delete structure
    fields more safely
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc.c b/server/dcc.c
index 33357cd..20a8f11 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -78,7 +78,7 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
     rcc = RED_CHANNEL_CLIENT(dcc);
     ring = &rcc->pipe;
     item = (RedPipeItem *) ring;
-    while ((item = (RedPipeItem *)ring_next(ring, (RingItem *)item))) {
+    while ((item = (RedPipeItem *)ring_next(ring, &item->link))) {
         Drawable *drawable;
         RedDrawablePipeItem *dpi = NULL;
         int depend_found = FALSE;
@@ -94,7 +94,7 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
 
         if (drawable->surface_id == surface_id) {
             RedPipeItem *tmp_item = item;
-            item = (RedPipeItem *)ring_prev(ring, (RingItem *)item);
+            item = (RedPipeItem *)ring_prev(ring, &item->link);
             red_channel_client_pipe_remove_and_release(rcc, tmp_item);
             if (!item) {
                 item = (RedPipeItem *)ring;
@@ -514,7 +514,7 @@ void dcc_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent)
     item->rects->num_rects = n_rects;
     region_ret_rects(&agent->clip, item->rects->rects, n_rects);
 
-    red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), (RedPipeItem *)item);
+    red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &item->base);
 }
 
 static void red_monitors_config_item_free(RedPipeItem *base)
diff --git a/server/reds.c b/server/reds.c
index fa9a79e..90911b4 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -888,7 +888,7 @@ static RedPipeItem *vdi_port_read_one_msg_from_device(SpiceCharDeviceInstance *s
                 dev->priv->read_state = VDI_PORT_READ_STATE_GET_BUFF;
             }
             if (vdi_port_read_buf_process(reds->agent_dev, dispatch_buf, &error)) {
-                return (RedPipeItem *)dispatch_buf;
+                return &dispatch_buf->base;
             } else {
                 if (error) {
                     reds_agent_remove(reds);
diff --git a/server/smartcard.c b/server/smartcard.c
index 2acddcf..9280038 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -160,7 +160,7 @@ static RedPipeItem *smartcard_read_msg_from_device(SpiceCharDeviceInstance *sin,
         dev->priv->buf_pos = dev->priv->buf;
         dev->priv->buf_used = remaining;
         if (msg_to_client) {
-            return (RedPipeItem *)msg_to_client;
+            return &msg_to_client->base;
         }
     }
     return NULL;
@@ -172,7 +172,7 @@ static void smartcard_send_msg_to_client(RedPipeItem *msg,
 {
     RedCharDeviceSmartcard *dev = opaque;
     spice_assert(dev->priv->scc && dev->priv->scc->base.client == client);
-    smartcard_channel_client_pipe_add_push(&dev->priv->scc->base, (RedPipeItem *)msg);
+    smartcard_channel_client_pipe_add_push(&dev->priv->scc->base, msg);
 
 }
 
diff --git a/server/spicevmc.c b/server/spicevmc.c
index f46b9e5..54c4f42 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -133,7 +133,7 @@ static RedPipeItem *spicevmc_chardev_read_msg_from_dev(SpiceCharDeviceInstance *
     if (n > 0) {
         spice_debug("read from dev %d", n);
         msg_item->buf_used = n;
-        return (RedPipeItem *)msg_item;
+        return &msg_item->base;
     } else {
         state->pipe_item = msg_item;
         return NULL;
@@ -145,11 +145,10 @@ static void spicevmc_chardev_send_msg_to_client(RedPipeItem *msg,
                                                 void *opaque)
 {
     SpiceVmcState *state = opaque;
-    RedVmcPipeItem *vmc_msg = SPICE_CONTAINEROF(msg, RedVmcPipeItem, base);
 
     spice_assert(state->rcc->client == client);
     red_pipe_item_ref(msg);
-    red_channel_client_pipe_add_push(state->rcc, (RedPipeItem *)vmc_msg);
+    red_channel_client_pipe_add_push(state->rcc, msg);
 }
 
 static SpiceVmcState *spicevmc_red_channel_client_get_state(RedChannelClient *rcc)
diff --git a/server/stream.c b/server/stream.c
index 74df254..be92289 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -177,7 +177,7 @@ void red_stream_clip_item_free(RedPipeItem *base)
 RedStreamClipItem *red_stream_clip_item_new(StreamAgent *agent)
 {
     RedStreamClipItem *item = spice_new(RedStreamClipItem, 1);
-    red_pipe_item_init_full((RedPipeItem *)item, RED_PIPE_ITEM_TYPE_STREAM_CLIP,
+    red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_STREAM_CLIP,
                             red_stream_clip_item_free);
 
     item->stream_agent = agent;
commit e8a9d3f2b9bc151f814e54ffdb01c3bc5b2c4298
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Sat May 14 12:49:43 2016 +0100

    rename RedVDIReadBug::parent to base
    
    All other classes using RedPipeItem as base use base as parent name
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/reds.c b/server/reds.c
index 74de7d5..fa9a79e 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -208,7 +208,7 @@ struct ChannelSecurityOptions {
 };
 
 typedef struct RedVDIReadBuf {
-    RedPipeItem parent;
+    RedPipeItem base;
     RedCharDeviceVDIPort *dev;
 
     int len;
@@ -523,7 +523,7 @@ static void reds_reset_vdp(RedsState *reds)
     dev->priv->receive_len = sizeof(dev->priv->vdi_chunk_header);
     dev->priv->message_receive_len = 0;
     if (dev->priv->current_read_buf) {
-        red_pipe_item_unref(&dev->priv->current_read_buf->parent);
+        red_pipe_item_unref(&dev->priv->current_read_buf->base);
         dev->priv->current_read_buf = NULL;
     }
     /* Reset read filter to start with clean state when the agent reconnects */
@@ -787,7 +787,7 @@ static void vdi_read_buf_init(RedVDIReadBuf *buf)
     /* Bogus pipe item type, we only need the RingItem and refcounting
      * from the base class and are not going to use the type
      */
-    red_pipe_item_init_full(&buf->parent, -1,
+    red_pipe_item_init_full(&buf->base, -1,
                             vdi_port_read_buf_free);
 }
 
@@ -801,9 +801,9 @@ static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev)
     }
 
     ring_remove(item);
-    buf = SPICE_CONTAINEROF(item, RedVDIReadBuf, parent.link);
+    buf = SPICE_CONTAINEROF(item, RedVDIReadBuf, base.link);
 
-    g_warn_if_fail(buf->parent.refcount == 0);
+    g_warn_if_fail(buf->base.refcount == 0);
     vdi_read_buf_init(buf);
 
     return buf;
@@ -811,10 +811,10 @@ static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev)
 
 static void vdi_port_read_buf_free(RedPipeItem *base)
 {
-    RedVDIReadBuf *buf = SPICE_CONTAINEROF(base, RedVDIReadBuf, parent);
+    RedVDIReadBuf *buf = SPICE_CONTAINEROF(base, RedVDIReadBuf, base);
 
-    g_warn_if_fail(buf->parent.refcount == 0);
-    ring_add(&buf->dev->priv->read_bufs, (RingItem *)buf);
+    g_warn_if_fail(buf->base.refcount == 0);
+    ring_add(&buf->dev->priv->read_bufs, &buf->base.link);
 
     /* read_one_msg_from_vdi_port may have never completed because the read_bufs
        ring was empty. So we call it again so it can complete its work if
@@ -893,7 +893,7 @@ static RedPipeItem *vdi_port_read_one_msg_from_device(SpiceCharDeviceInstance *s
                 if (error) {
                     reds_agent_remove(reds);
                 }
-                red_pipe_item_unref(&dispatch_buf->parent);
+                red_pipe_item_unref(&dispatch_buf->base);
             }
         }
         } /* END switch */
@@ -1271,7 +1271,7 @@ void reds_on_main_channel_migrate(RedsState *reds, MainChannelClient *mcc)
             if (error) {
                reds_agent_remove(reds);
             }
-            red_pipe_item_unref(&read_buf->parent);
+            red_pipe_item_unref(&read_buf->base);
         }
 
         spice_assert(agent_dev->priv->receive_len);
@@ -4351,7 +4351,7 @@ red_char_device_vdi_port_init(RedCharDeviceVDIPort *self)
         /* This ensures the newly created buffer is placed in the
          * RedCharDeviceVDIPort::read_bufs queue ready to be reused
          */
-        red_pipe_item_unref(&buf->parent);
+        red_pipe_item_unref(&buf->base);
     }
 }
 
commit ab69c3367f0ec8e1435026362aadec5c34ce716a
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 13 19:55:53 2016 +0100

    make red_pipe_item_unref more typesafe
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/char-device.c b/server/char-device.c
index b67e192..4a6e4c8 100644
--- a/server/char-device.c
+++ b/server/char-device.c
@@ -189,7 +189,7 @@ static void red_char_device_client_free(RedCharDevice *dev,
         dev_client->wait_for_tokens_timer = NULL;
     }
 
-    g_queue_free_full(dev_client->send_queue, red_pipe_item_unref);
+    g_queue_free_full(dev_client->send_queue, (GDestroyNotify)red_pipe_item_unref);
 
     /* remove write buffers that are associated with the client */
     spice_debug("write_queue_is_empty %d", ring_is_empty(&dev->priv->write_queue) && !dev->priv->cur_write_buf);
diff --git a/server/red-pipe-item.c b/server/red-pipe-item.c
index 74bf267..31262fa 100644
--- a/server/red-pipe-item.c
+++ b/server/red-pipe-item.c
@@ -29,10 +29,8 @@ RedPipeItem *red_pipe_item_ref(RedPipeItem *item)
     return item;
 }
 
-void red_pipe_item_unref(gpointer object)
+void red_pipe_item_unref(RedPipeItem *item)
 {
-    RedPipeItem *item = object;
-
     g_return_if_fail(item->refcount > 0);
 
     if (g_atomic_int_dec_and_test(&item->refcount)) {
diff --git a/server/red-pipe-item.h b/server/red-pipe-item.h
index 0138216..bf13b0b 100644
--- a/server/red-pipe-item.h
+++ b/server/red-pipe-item.h
@@ -37,7 +37,7 @@ typedef struct RedPipeItem {
 
 void red_pipe_item_init_full(RedPipeItem *item, int type, red_pipe_item_free_t free_func);
 RedPipeItem *red_pipe_item_ref(RedPipeItem *item);
-void red_pipe_item_unref(gpointer item);
+void red_pipe_item_unref(RedPipeItem *item);
 
 static inline int red_pipe_item_is_linked(RedPipeItem *item)
 {
diff --git a/server/reds.c b/server/reds.c
index 8ea6098..74de7d5 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -523,7 +523,7 @@ static void reds_reset_vdp(RedsState *reds)
     dev->priv->receive_len = sizeof(dev->priv->vdi_chunk_header);
     dev->priv->message_receive_len = 0;
     if (dev->priv->current_read_buf) {
-        red_pipe_item_unref(dev->priv->current_read_buf);
+        red_pipe_item_unref(&dev->priv->current_read_buf->parent);
         dev->priv->current_read_buf = NULL;
     }
     /* Reset read filter to start with clean state when the agent reconnects */
@@ -747,9 +747,7 @@ static void reds_agent_remove(RedsState *reds)
 
 static void vdi_port_read_buf_release(uint8_t *data, void *opaque)
 {
-    RedVDIReadBuf *buf = (RedVDIReadBuf *)opaque;
-
-    red_pipe_item_unref(buf);
+    red_pipe_item_unref((RedPipeItem *)opaque);
 }
 
 /* returns TRUE if the buffer can be forwarded */
@@ -895,7 +893,7 @@ static RedPipeItem *vdi_port_read_one_msg_from_device(SpiceCharDeviceInstance *s
                 if (error) {
                     reds_agent_remove(reds);
                 }
-                red_pipe_item_unref(dispatch_buf);
+                red_pipe_item_unref(&dispatch_buf->parent);
             }
         }
         } /* END switch */
@@ -1273,7 +1271,7 @@ void reds_on_main_channel_migrate(RedsState *reds, MainChannelClient *mcc)
             if (error) {
                reds_agent_remove(reds);
             }
-            red_pipe_item_unref(read_buf);
+            red_pipe_item_unref(&read_buf->parent);
         }
 
         spice_assert(agent_dev->priv->receive_len);
@@ -4353,7 +4351,7 @@ red_char_device_vdi_port_init(RedCharDeviceVDIPort *self)
         /* This ensures the newly created buffer is placed in the
          * RedCharDeviceVDIPort::read_bufs queue ready to be reused
          */
-        red_pipe_item_unref(buf);
+        red_pipe_item_unref(&buf->parent);
     }
 }
 
commit f75b69fdc8a5e6be00fc54d03e678dbef6ce374b
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 13 19:50:27 2016 +0100

    make red_pipe_item_ref more typesafe
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/red-pipe-item.c b/server/red-pipe-item.c
index cc0ab5a..74bf267 100644
--- a/server/red-pipe-item.c
+++ b/server/red-pipe-item.c
@@ -20,10 +20,8 @@
 #include "red-channel.h"
 #include "red-pipe-item.h"
 
-RedPipeItem *red_pipe_item_ref(gpointer object)
+RedPipeItem *red_pipe_item_ref(RedPipeItem *item)
 {
-    RedPipeItem *item = object;
-
     g_return_val_if_fail(item->refcount > 0, NULL);
 
     g_atomic_int_inc(&item->refcount);
diff --git a/server/red-pipe-item.h b/server/red-pipe-item.h
index 4b3d892..0138216 100644
--- a/server/red-pipe-item.h
+++ b/server/red-pipe-item.h
@@ -36,7 +36,7 @@ typedef struct RedPipeItem {
 } RedPipeItem;
 
 void red_pipe_item_init_full(RedPipeItem *item, int type, red_pipe_item_free_t free_func);
-RedPipeItem *red_pipe_item_ref(gpointer item);
+RedPipeItem *red_pipe_item_ref(RedPipeItem *item);
 void red_pipe_item_unref(gpointer item);
 
 static inline int red_pipe_item_is_linked(RedPipeItem *item)
diff --git a/server/reds.c b/server/reds.c
index 8a903b7..8ea6098 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -910,7 +910,7 @@ static void vdi_port_send_msg_to_client(RedPipeItem *msg,
 {
     RedVDIReadBuf *agent_data_buf = (RedVDIReadBuf *)msg;
 
-    red_pipe_item_ref(agent_data_buf);
+    red_pipe_item_ref(msg);
     main_channel_client_push_agent_data(red_client_get_main(client),
                                         agent_data_buf->data,
                                         agent_data_buf->len,
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 1e68909..f46b9e5 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -145,10 +145,10 @@ static void spicevmc_chardev_send_msg_to_client(RedPipeItem *msg,
                                                 void *opaque)
 {
     SpiceVmcState *state = opaque;
-    RedVmcPipeItem *vmc_msg = (RedVmcPipeItem *)msg;
+    RedVmcPipeItem *vmc_msg = SPICE_CONTAINEROF(msg, RedVmcPipeItem, base);
 
     spice_assert(state->rcc->client == client);
-    red_pipe_item_ref(vmc_msg);
+    red_pipe_item_ref(msg);
     red_channel_client_pipe_add_push(state->rcc, (RedPipeItem *)vmc_msg);
 }
 
commit 8d764488ca10953e947a4e5bf95bee9c383657dc
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 13 19:47:14 2016 +0100

    make red_pipe_item_init_full more typesafe
    
    Use a proper type for free callback
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 949cbc4..c257654 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -81,7 +81,7 @@ struct CursorChannelClient {
 #include "cache-item.tmpl.c"
 #undef CLIENT_CURSOR_CACHE
 
-static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item);
+static red_pipe_item_free_t cursor_pipe_item_free;
 
 static CursorItem *cursor_item_new(QXLInstance *qxl, RedCursorCmd *cmd)
 {
@@ -138,7 +138,7 @@ static RedPipeItem *new_cursor_pipe_item(RedChannelClient *rcc, void *data, int
     RedCursorPipeItem *item = spice_malloc0(sizeof(RedCursorPipeItem));
 
     red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_CURSOR,
-                            (GDestroyNotify)cursor_pipe_item_free);
+                            cursor_pipe_item_free);
     item->cursor_item = data;
     item->cursor_item->refs++;
     return &item->base;
@@ -204,9 +204,11 @@ void cursor_channel_disconnect(CursorChannel *cursor_channel)
 }
 
 
-static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item)
+static void cursor_pipe_item_free(RedPipeItem *base)
 {
-    spice_return_if_fail(pipe_item);
+    spice_return_if_fail(base);
+
+    RedCursorPipeItem *pipe_item = SPICE_CONTAINEROF(base, RedCursorPipeItem, base);
 
     spice_assert(!red_pipe_item_is_linked(&pipe_item->base));
 
diff --git a/server/dcc.c b/server/dcc.c
index b9e4eb3..33357cd 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -306,7 +306,7 @@ static RedDrawablePipeItem *red_drawable_pipe_item_new(DisplayChannelClient *dcc
     ring_item_init(&dpi->base);
     ring_add(&drawable->pipes, &dpi->base);
     red_pipe_item_init_full(&dpi->dpi_pipe_item, RED_PIPE_ITEM_TYPE_DRAW,
-                            (GDestroyNotify)red_drawable_pipe_item_free);
+                            red_drawable_pipe_item_free);
     drawable->refs++;
     return dpi;
 }
@@ -517,8 +517,10 @@ void dcc_stream_agent_clip(DisplayChannelClient* dcc, StreamAgent *agent)
     red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), (RedPipeItem *)item);
 }
 
-static void red_monitors_config_item_free(RedMonitorsConfigItem *item)
+static void red_monitors_config_item_free(RedPipeItem *base)
 {
+    RedMonitorsConfigItem *item = SPICE_CONTAINEROF(base, RedMonitorsConfigItem, pipe_item);
+
     monitors_config_unref(item->monitors_config);
     free(item);
 }
@@ -532,7 +534,7 @@ static RedMonitorsConfigItem *red_monitors_config_item_new(RedChannel* channel,
     mci->monitors_config = monitors_config;
 
     red_pipe_item_init_full(&mci->pipe_item, RED_PIPE_ITEM_TYPE_MONITORS_CONFIG,
-                            (GDestroyNotify)red_monitors_config_item_free);
+                            red_monitors_config_item_free);
     return mci;
 }
 
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 3b9782f..1ec6c82 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -109,8 +109,9 @@ static const uint8_t zero_page[ZERO_BUF_SIZE] = {0};
 
 static int main_channel_client_push_ping(MainChannelClient *mcc, int size);
 
-static void main_notify_item_free(RedNotifyPipeItem *data)
+static void main_notify_item_free(RedPipeItem *base)
 {
+    RedNotifyPipeItem *data = SPICE_CONTAINEROF(base, RedNotifyPipeItem, base);
     free(data->msg);
     free(data);
 }
@@ -121,7 +122,7 @@ static RedPipeItem *main_notify_item_new(void *data, int num)
     const char *msg = data;
 
     red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY,
-                            (GDestroyNotify)main_notify_item_free);
+                            main_notify_item_free);
     item->msg = spice_strdup(msg);
     return &item->base;
 }
@@ -181,8 +182,9 @@ void main_channel_client_push_agent_tokens(MainChannelClient *mcc, uint32_t num_
     red_channel_client_pipe_add_push(&mcc->base, item);
 }
 
-static void main_agent_data_item_free(RedAgentDataPipeItem *item)
+static void main_agent_data_item_free(RedPipeItem *base)
 {
+    RedAgentDataPipeItem *item = SPICE_CONTAINEROF(base, RedAgentDataPipeItem, base);
     item->free_data(item->data, item->opaque);
     free(item);
 }
@@ -194,7 +196,7 @@ static RedPipeItem *main_agent_data_item_new(uint8_t* data, size_t len,
     RedAgentDataPipeItem *item = spice_malloc(sizeof(RedAgentDataPipeItem));
 
     red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA,
-                            (GDestroyNotify)main_agent_data_item_free);
+                            main_agent_data_item_free);
     item->data = data;
     item->len = len;
     item->free_data = free_data;
diff --git a/server/red-channel.c b/server/red-channel.c
index d18e1b0..c00b655 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -2365,8 +2365,10 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
     }
 }
 
-static void marker_pipe_item_free(MarkerPipeItem *item)
+static void marker_pipe_item_free(RedPipeItem *base)
 {
+    MarkerPipeItem *item = SPICE_CONTAINEROF(base, MarkerPipeItem, base);
+
     if (item->item_in_pipe) {
         *item->item_in_pipe = FALSE;
     }
@@ -2392,7 +2394,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
     MarkerPipeItem *mark_item = spice_new0(MarkerPipeItem, 1);
 
     red_pipe_item_init_full(&mark_item->base, RED_PIPE_ITEM_TYPE_MARKER,
-                            (GDestroyNotify)marker_pipe_item_free);
+                            marker_pipe_item_free);
     item_in_pipe = TRUE;
     mark_item->item_in_pipe = &item_in_pipe;
     red_channel_client_pipe_add_after(rcc, &mark_item->base, item);
diff --git a/server/red-pipe-item.c b/server/red-pipe-item.c
index d9c60aa..cc0ab5a 100644
--- a/server/red-pipe-item.c
+++ b/server/red-pipe-item.c
@@ -44,10 +44,10 @@ void red_pipe_item_unref(gpointer object)
 
 void red_pipe_item_init_full(RedPipeItem *item,
                              gint type,
-                             GDestroyNotify free_func)
+                             red_pipe_item_free_t *free_func)
 {
     ring_item_init(&item->link);
     item->type = type;
     item->refcount = 1;
-    item->free_func = free_func ? free_func : (GDestroyNotify)free;
+    item->free_func = free_func ? free_func : (red_pipe_item_free_t *)free;
 }
diff --git a/server/red-pipe-item.h b/server/red-pipe-item.h
index 0ff4852..4b3d892 100644
--- a/server/red-pipe-item.h
+++ b/server/red-pipe-item.h
@@ -21,17 +21,21 @@
 #include <glib.h>
 #include <common/ring.h>
 
-typedef struct {
+struct RedPipeItem;
+
+typedef void red_pipe_item_free_t(struct RedPipeItem *item);
+
+typedef struct RedPipeItem {
     RingItem link;
     int type;
 
     /* private */
     int refcount;
 
-    GDestroyNotify free_func;
+    red_pipe_item_free_t *free_func;
 } RedPipeItem;
 
-void red_pipe_item_init_full(RedPipeItem *item, int type, GDestroyNotify free_func);
+void red_pipe_item_init_full(RedPipeItem *item, int type, red_pipe_item_free_t free_func);
 RedPipeItem *red_pipe_item_ref(gpointer item);
 void red_pipe_item_unref(gpointer item);
 
diff --git a/server/reds.c b/server/reds.c
index a1e589a..8a903b7 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -303,7 +303,7 @@ static uint32_t reds_qxl_ram_size(RedsState *reds);
 static int calc_compression_level(RedsState *reds);
 
 static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev);
-static void vdi_port_read_buf_free(RedVDIReadBuf *buf);
+static red_pipe_item_free_t vdi_port_read_buf_free;
 
 static ChannelSecurityOptions *reds_find_channel_security(RedsState *reds, int id)
 {
@@ -790,7 +790,7 @@ static void vdi_read_buf_init(RedVDIReadBuf *buf)
      * from the base class and are not going to use the type
      */
     red_pipe_item_init_full(&buf->parent, -1,
-                            (GDestroyNotify)vdi_port_read_buf_free);
+                            vdi_port_read_buf_free);
 }
 
 static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev)
@@ -811,8 +811,10 @@ static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev)
     return buf;
 }
 
-static void vdi_port_read_buf_free(RedVDIReadBuf *buf)
+static void vdi_port_read_buf_free(RedPipeItem *base)
 {
+    RedVDIReadBuf *buf = SPICE_CONTAINEROF(base, RedVDIReadBuf, parent);
+
     g_warn_if_fail(buf->parent.refcount == 0);
     ring_add(&buf->dev->priv->read_bufs, (RingItem *)buf);
 
diff --git a/server/smartcard.c b/server/smartcard.c
index c39aeae..2acddcf 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -537,8 +537,9 @@ static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCE
     smartcard_channel_client_pipe_add_push(rcc, &error_item->base);
 }
 
-static void smartcard_free_vsc_msg_item(RedMsgItem *item)
+static void smartcard_free_vsc_msg_item(RedPipeItem *base)
 {
+    RedMsgItem *item = SPICE_CONTAINEROF(base, RedMsgItem, base);
     free(item->vheader);
     free(item);
 }
@@ -549,7 +550,7 @@ static RedMsgItem *smartcard_get_vsc_msg_item(RedChannelClient *rcc,
     RedMsgItem *msg_item = spice_new0(RedMsgItem, 1);
 
     red_pipe_item_init_full(&msg_item->base, RED_PIPE_ITEM_TYPE_SMARTCARD_DATA,
-                            (GDestroyNotify)smartcard_free_vsc_msg_item);
+                            smartcard_free_vsc_msg_item);
     msg_item->vheader = vheader;
     return msg_item;
 }
diff --git a/server/stream.c b/server/stream.c
index 4c733de..74df254 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -76,7 +76,7 @@ static RedPipeItem *stream_create_destroy_item_new(StreamAgent *agent, gint type
     StreamCreateDestroyItem *item = spice_new0(StreamCreateDestroyItem, 1);
 
     red_pipe_item_init_full(&item->base, type,
-                            (GDestroyNotify)stream_create_destroy_item_release);
+                            stream_create_destroy_item_release);
     agent->stream->refs++;
     item->agent = agent;
     return &item->base;
@@ -161,9 +161,10 @@ void stream_agent_unref(DisplayChannel *display, StreamAgent *agent)
     stream_unref(display, agent->stream);
 }
 
-void red_stream_clip_item_free(RedStreamClipItem *item)
+void red_stream_clip_item_free(RedPipeItem *base)
 {
-    g_return_if_fail(item != NULL);
+    g_return_if_fail(base != NULL);
+    RedStreamClipItem *item = SPICE_CONTAINEROF(base, RedStreamClipItem, base);
     DisplayChannel *display = DCC_TO_DC(item->stream_agent->dcc);
 
     g_return_if_fail(item->base.refcount == 0);
@@ -177,7 +178,7 @@ RedStreamClipItem *red_stream_clip_item_new(StreamAgent *agent)
 {
     RedStreamClipItem *item = spice_new(RedStreamClipItem, 1);
     red_pipe_item_init_full((RedPipeItem *)item, RED_PIPE_ITEM_TYPE_STREAM_CLIP,
-                            (GDestroyNotify)red_stream_clip_item_free);
+                            red_stream_clip_item_free);
 
     item->stream_agent = agent;
     agent->stream->refs++;
@@ -785,8 +786,10 @@ void stream_agent_stop(StreamAgent *agent)
     }
 }
 
-static void red_upgrade_item_free(RedUpgradeItem *item)
+static void red_upgrade_item_free(RedPipeItem *base)
 {
+    RedUpgradeItem *item = SPICE_CONTAINEROF(base, RedUpgradeItem, base);
+
     g_return_if_fail(item != NULL);
     g_return_if_fail(item->base.refcount == 0);
 
@@ -836,7 +839,7 @@ static void dcc_detach_stream_gracefully(DisplayChannelClient *dcc,
         rcc = RED_CHANNEL_CLIENT(dcc);
         upgrade_item = spice_new(RedUpgradeItem, 1);
         red_pipe_item_init_full(&upgrade_item->base, RED_PIPE_ITEM_TYPE_UPGRADE,
-                                (GDestroyNotify)red_upgrade_item_free);
+                                red_upgrade_item_free);
         upgrade_item->drawable = stream->current;
         upgrade_item->drawable->refs++;
         n_rects = pixman_region32_n_rects(&upgrade_item->drawable->tree_item.base.rgn);
commit e960e00392d068e0566113862038a1faf34565f0
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 20 11:13:42 2016 +0100

    Use a marker instead of checking a RedPipeItem presence
    
    This avoids having to retain a pointer just to check item is still in
    the queue with ring_item_is_linked(&item->link).
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/red-channel.c b/server/red-channel.c
index 141e157..d18e1b0 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -49,6 +49,11 @@ typedef struct RedEmptyMsgPipeItem {
     int msg;
 } RedEmptyMsgPipeItem;
 
+typedef struct MarkerPipeItem {
+    RedPipeItem base;
+    gboolean *item_in_pipe;
+} MarkerPipeItem;
+
 #define PING_TEST_TIMEOUT_MS (MSEC_PER_SEC * 15)
 #define PING_TEST_IDLE_NET_TIMEOUT_MS (MSEC_PER_SEC / 10)
 
@@ -574,6 +579,8 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite
         case RED_PIPE_ITEM_TYPE_PING:
             red_channel_client_send_ping(rcc);
             break;
+        case RED_PIPE_ITEM_TYPE_MARKER:
+            break;
         default:
             rcc->channel->channel_cbs.send_item(rcc, item);
             break;
@@ -2358,13 +2365,21 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
     }
 }
 
+static void marker_pipe_item_free(MarkerPipeItem *item)
+{
+    if (item->item_in_pipe) {
+        *item->item_in_pipe = FALSE;
+    }
+    free(item);
+}
+
 /* TODO: more evil sync stuff. anything with the word wait in it's name. */
 int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
                                            RedPipeItem *item,
                                            int64_t timeout)
 {
     uint64_t end_time;
-    int item_in_pipe;
+    gboolean item_in_pipe;
 
     spice_info(NULL);
 
@@ -2374,7 +2389,13 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
         end_time = UINT64_MAX;
     }
 
-    red_pipe_item_ref(item);
+    MarkerPipeItem *mark_item = spice_new0(MarkerPipeItem, 1);
+
+    red_pipe_item_init_full(&mark_item->base, RED_PIPE_ITEM_TYPE_MARKER,
+                            (GDestroyNotify)marker_pipe_item_free);
+    item_in_pipe = TRUE;
+    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)) {
         red_channel_client_receive(rcc);
@@ -2382,7 +2403,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
     }
     red_channel_client_push(rcc);
 
-    while((item_in_pipe = ring_item_is_linked(&item->link)) &&
+    while(item_in_pipe &&
           (timeout == -1 || spice_get_monotonic_time_ns() < end_time)) {
         usleep(CHANNEL_BLOCKED_SLEEP_DURATION);
         red_channel_client_receive(rcc);
@@ -2390,8 +2411,9 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
         red_channel_client_push(rcc);
     }
 
-    red_pipe_item_unref(item);
     if (item_in_pipe) {
+        // still on the queue, make sure won't overwrite the stack variable
+        mark_item->item_in_pipe = NULL;
         spice_warning("timeout");
         return FALSE;
     } else {
diff --git a/server/red-channel.h b/server/red-channel.h
index 8e8845e..c4eb436 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -143,6 +143,7 @@ enum {
     RED_PIPE_ITEM_TYPE_MIGRATE,
     RED_PIPE_ITEM_TYPE_EMPTY_MSG,
     RED_PIPE_ITEM_TYPE_PING,
+    RED_PIPE_ITEM_TYPE_MARKER,
 
     RED_PIPE_ITEM_TYPE_CHANNEL_BASE=101,
 };
commit f12464b2f1d861a9565bfd6575f51fe332f79ee1
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 20 06:21:16 2016 +0100

    Call dcc_send_item directly
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/dcc-send.c b/server/dcc-send.c
index 05da07f..8ec22c8 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -2367,9 +2367,9 @@ static void reset_send_data(DisplayChannelClient *dcc)
     memset(dcc->send_data.free_list.sync, 0, sizeof(dcc->send_data.free_list.sync));
 }
 
-void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
+void dcc_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
 {
-    RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc);
+    DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
 
     reset_send_data(dcc);
diff --git a/server/dcc.h b/server/dcc.h
index 864a768..a11d25a 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -203,7 +203,7 @@ void                       dcc_append_drawable                       (DisplayCha
 void                       dcc_add_drawable_after                    (DisplayChannelClient *dcc,
                                                                       Drawable *drawable,
                                                                       RedPipeItem *pos);
-void                       dcc_send_item                             (DisplayChannelClient *dcc,
+void                       dcc_send_item                             (RedChannelClient *dcc,
                                                                       RedPipeItem *item);
 int                        dcc_clear_surface_drawables_from_pipe     (DisplayChannelClient *dcc,
                                                                       int surface_id,
diff --git a/server/display-channel.c b/server/display-channel.c
index b9ed285..9f97911 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1925,11 +1925,6 @@ static void on_disconnect(RedChannelClient *rcc)
                 display->glz_drawable_count);
 }
 
-static void send_item(RedChannelClient *rcc, RedPipeItem *item)
-{
-    dcc_send_item(RCC_TO_DCC(rcc), item);
-}
-
 static int handle_migrate_flush_mark(RedChannelClient *rcc)
 {
     DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
@@ -1969,7 +1964,7 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
     DisplayChannel *display;
     ChannelCbs cbs = {
         .on_disconnect = on_disconnect,
-        .send_item = send_item,
+        .send_item = dcc_send_item,
         .handle_migrate_flush_mark = handle_migrate_flush_mark,
         .handle_migrate_data = handle_migrate_data,
         .handle_migrate_data_get_serial = handle_migrate_data_get_serial
commit 27145ed9aa8966a01a81d347ed1488ba50abe6ef
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri May 20 09:01:16 2016 +0100

    Handle reference for RedPipeItem in RedChannel
    
    Remove the need to release the item inside send_item callbacks.
    This looks like a partial rollback of previous patch but is
    to make clear the intention of the change.
    The lifetime of items could extend a bit further but there
    are no cases this small lag should cause problems.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 104bf51..949cbc4 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -336,7 +336,6 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
         spice_error("invalid pipe item type");
     }
 
-    red_pipe_item_unref(pipe_item);
     red_channel_client_begin_send_message(rcc);
 }
 
diff --git a/server/dcc-send.c b/server/dcc-send.c
index f0f2e16..05da07f 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -2455,8 +2455,6 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
         spice_warn_if_reached();
     }
 
-    red_pipe_item_unref(pipe_item);
-
     // a message is pending
     if (red_channel_client_send_message_pending(rcc)) {
         begin_send_message(rcc);
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index 4f37695..197823d 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -289,7 +289,6 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
             spice_warning("invalid pipe iten %d", base->type);
             break;
     }
-    red_pipe_item_unref(base);
     red_channel_client_begin_send_message(rcc);
 }
 
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index 0b3163e..3b9782f 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -820,7 +820,6 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
         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_pipe_item_unref(base);
         return;
     }
     switch (base->type) {
@@ -888,6 +887,5 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
         default:
             break;
     };
-    red_pipe_item_unref(base);
     red_channel_client_begin_send_message(rcc);
 }
diff --git a/server/red-channel.c b/server/red-channel.c
index abdc3d0..141e157 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -576,7 +576,7 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite
             break;
         default:
             rcc->channel->channel_cbs.send_item(rcc, item);
-            return;
+            break;
     }
     red_pipe_item_unref(item);
 }
diff --git a/server/smartcard.c b/server/smartcard.c
index e68ccdc..c39aeae 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -498,10 +498,8 @@ static void smartcard_channel_send_item(RedChannelClient *rcc, RedPipeItem *item
         break;
     default:
         spice_error("bad pipe item %d", item->type);
-        red_pipe_item_unref(item);
         return;
     }
-    red_pipe_item_unref(item);
     red_channel_client_begin_send_message(rcc);
 }
 
diff --git a/server/spicevmc.c b/server/spicevmc.c
index be51d54..1e68909 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -425,10 +425,8 @@ static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
         break;
     default:
         spice_error("bad pipe item %d", item->type);
-        red_pipe_item_unref(item);
         return;
     }
-    red_pipe_item_unref(item);
     red_channel_client_begin_send_message(rcc);
 }
 
commit 138a11a163e8e005e01be96b5a5c5c27bdc2e404
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Sat May 21 03:51:50 2016 +0100

    Remove RedChannel::hold_item callback
    
    This is quite confusing and prone to errors.
    Use RedPipeItem reference counting instead.
    To compensate for the additional reference due to red_pipe_item_ref
    in RedChannel sub class with empty hold_item have to add a
    red_pipe_item_unref call in send_item.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index fa462c5..104bf51 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -340,13 +340,6 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
     red_channel_client_begin_send_message(rcc);
 }
 
-static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, RedPipeItem *item)
-{
-    spice_return_if_fail(item);
-
-    red_pipe_item_ref(item);
-}
-
 CursorChannel* cursor_channel_new(RedWorker *worker)
 {
     CursorChannel *cursor_channel;
@@ -354,7 +347,6 @@ CursorChannel* cursor_channel_new(RedWorker *worker)
     ChannelCbs cbs = {
         .on_disconnect =  cursor_channel_client_on_disconnect,
         .send_item = cursor_channel_send_item,
-        .hold_item = cursor_channel_hold_pipe_item,
     };
 
     spice_info("create cursor channel");
diff --git a/server/display-channel.c b/server/display-channel.c
index 3f414fd..b9ed285 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1930,13 +1930,6 @@ static void send_item(RedChannelClient *rcc, RedPipeItem *item)
     dcc_send_item(RCC_TO_DCC(rcc), item);
 }
 
-static void hold_item(RedChannelClient *rcc, RedPipeItem *item)
-{
-    spice_return_if_fail(item);
-
-    red_pipe_item_ref(item);
-}
-
 static int handle_migrate_flush_mark(RedChannelClient *rcc)
 {
     DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
@@ -1977,7 +1970,6 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
     ChannelCbs cbs = {
         .on_disconnect = on_disconnect,
         .send_item = send_item,
-        .hold_item = hold_item,
         .handle_migrate_flush_mark = handle_migrate_flush_mark,
         .handle_migrate_data = handle_migrate_data,
         .handle_migrate_data_get_serial = handle_migrate_data_get_serial
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index 2a3a733..4f37695 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -289,6 +289,7 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
             spice_warning("invalid pipe iten %d", base->type);
             break;
     }
+    red_pipe_item_unref(base);
     red_channel_client_begin_send_message(rcc);
 }
 
@@ -518,10 +519,6 @@ static int inputs_channel_config_socket(RedChannelClient *rcc)
     return TRUE;
 }
 
-static void inputs_channel_hold_pipe_item(RedChannelClient *rcc, RedPipeItem *item)
-{
-}
-
 static void inputs_connect(RedChannel *channel, RedClient *client,
                            RedsStream *stream, int migration,
                            int num_common_caps, uint32_t *common_caps,
@@ -620,7 +617,6 @@ InputsChannel* inputs_channel_new(RedsState *reds)
     channel_cbs.config_socket = inputs_channel_config_socket;
     channel_cbs.on_disconnect = inputs_channel_on_disconnect;
     channel_cbs.send_item = inputs_channel_send_item;
-    channel_cbs.hold_item = inputs_channel_hold_pipe_item;
     channel_cbs.alloc_recv_buf = inputs_channel_alloc_msg_rcv_buf;
     channel_cbs.release_recv_buf = inputs_channel_release_msg_rcv_buf;
     channel_cbs.handle_migrate_data = inputs_channel_handle_migrate_data;
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
index a8e8632..0b3163e 100644
--- a/server/main-channel-client.c
+++ b/server/main-channel-client.c
@@ -888,5 +888,6 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
         default:
             break;
     };
+    red_pipe_item_unref(base);
     red_channel_client_begin_send_message(rcc);
 }
diff --git a/server/main-channel.c b/server/main-channel.c
index 7b33346..be90803 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -273,10 +273,6 @@ static int main_channel_config_socket(RedChannelClient *rcc)
     return TRUE;
 }
 
-static void main_channel_hold_pipe_item(RedChannelClient *rcc, RedPipeItem *item)
-{
-}
-
 static int main_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
 {
     spice_debug(NULL);
@@ -333,7 +329,6 @@ MainChannel* main_channel_new(RedsState *reds)
     channel_cbs.config_socket = main_channel_config_socket;
     channel_cbs.on_disconnect = main_channel_client_on_disconnect;
     channel_cbs.send_item = main_channel_client_send_item;
-    channel_cbs.hold_item = main_channel_hold_pipe_item;
     channel_cbs.alloc_recv_buf = main_channel_alloc_msg_rcv_buf;
     channel_cbs.release_recv_buf = main_channel_release_msg_rcv_buf;
     channel_cbs.handle_migrate_flush_mark = main_channel_handle_migrate_flush_mark;
diff --git a/server/red-channel.c b/server/red-channel.c
index 2ec65e8..abdc3d0 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -1591,7 +1591,7 @@ void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type,
     rcc->send_data.header.set_msg_type(&rcc->send_data.header, msg_type);
     rcc->send_data.item = item;
     if (item) {
-        rcc->channel->channel_cbs.hold_item(rcc, item);
+        red_pipe_item_ref(item);
     }
 }
 
@@ -2374,7 +2374,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
         end_time = UINT64_MAX;
     }
 
-    rcc->channel->channel_cbs.hold_item(rcc, item);
+    red_pipe_item_ref(item);
 
     if (red_channel_client_blocked(rcc)) {
         red_channel_client_receive(rcc);
diff --git a/server/red-channel.h b/server/red-channel.h
index 63cb2d9..8e8845e 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -158,7 +158,6 @@ typedef void (*channel_release_msg_recv_buf_proc)(RedChannelClient *channel,
 typedef void (*channel_disconnect_proc)(RedChannelClient *rcc);
 typedef int (*channel_configure_socket_proc)(RedChannelClient *rcc);
 typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
-typedef void (*channel_hold_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
 typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc);
 typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc);
 
@@ -185,7 +184,6 @@ typedef struct {
     channel_configure_socket_proc config_socket;
     channel_disconnect_proc on_disconnect;
     channel_send_pipe_item_proc send_item;
-    channel_hold_pipe_item_proc hold_item;
     channel_alloc_msg_recv_buf_proc alloc_recv_buf;
     channel_release_msg_recv_buf_proc release_recv_buf;
     channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark;
diff --git a/server/smartcard.c b/server/smartcard.c
index a75f01c..e68ccdc 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -498,9 +498,10 @@ static void smartcard_channel_send_item(RedChannelClient *rcc, RedPipeItem *item
         break;
     default:
         spice_error("bad pipe item %d", item->type);
-        free(item);
+        red_pipe_item_unref(item);
         return;
     }
+    red_pipe_item_unref(item);
     red_channel_client_begin_send_message(rcc);
 }
 
@@ -737,11 +738,6 @@ static int smartcard_channel_handle_message(RedChannelClient *rcc,
     return TRUE;
 }
 
-static void smartcard_channel_hold_pipe_item(RedChannelClient *rcc,
-                                             RedPipeItem *item)
-{
-}
-
 static void smartcard_connect_client(RedChannel *channel, RedClient *client,
                                      RedsStream *stream, int migration,
                                      int num_common_caps, uint32_t *common_caps,
@@ -785,7 +781,6 @@ static void smartcard_init(RedsState *reds)
     channel_cbs.config_socket = smartcard_channel_client_config_socket;
     channel_cbs.on_disconnect = smartcard_channel_on_disconnect;
     channel_cbs.send_item = smartcard_channel_send_item;
-    channel_cbs.hold_item = smartcard_channel_hold_pipe_item;
     channel_cbs.alloc_recv_buf = smartcard_channel_alloc_msg_rcv_buf;
     channel_cbs.release_recv_buf = smartcard_channel_release_msg_rcv_buf;
     channel_cbs.handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark;
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 14d34b4..be51d54 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -355,12 +355,6 @@ static void spicevmc_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
     }
 }
 
-static void spicevmc_red_channel_hold_pipe_item(RedChannelClient *rcc,
-                                                RedPipeItem *item)
-{
-    /* NOOP */
-}
-
 static void spicevmc_red_channel_send_data(RedChannelClient *rcc,
                                            SpiceMarshaller *m,
                                            RedPipeItem *item)
@@ -434,6 +428,7 @@ static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
         red_pipe_item_unref(item);
         return;
     }
+    red_pipe_item_unref(item);
     red_channel_client_begin_send_message(rcc);
 }
 
@@ -497,7 +492,6 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
     channel_cbs.config_socket = spicevmc_red_channel_client_config_socket;
     channel_cbs.on_disconnect = spicevmc_red_channel_client_on_disconnect;
     channel_cbs.send_item = spicevmc_red_channel_send_item;
-    channel_cbs.hold_item = spicevmc_red_channel_hold_pipe_item;
     channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf;
     channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf;
     channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark;


More information about the Spice-commits mailing list