[Spice-commits] 22 commits - doc/reference gtk/channel-display.c gtk/channel-main.c gtk/channel-smartcard.c gtk/channel-webdav.c gtk/desktop-integration.c gtk/map-file gtk/spice-audio.c gtk/spice-channel.c gtk/spice-channel.h gtk/spice-glib-sym-file gtk/spice-gtk-session.c gtk/spice-session.c gtk/spice-session.h gtk/spice-session-priv.h gtk/usb-device-manager.c

Marc-André Lureau elmarco at kemper.freedesktop.org
Mon Dec 1 08:31:51 PST 2014


 doc/reference/spice-gtk-sections.txt |    1 
 gtk/channel-display.c                |    5 
 gtk/channel-main.c                   |   12 
 gtk/channel-smartcard.c              |   19 -
 gtk/channel-webdav.c                 |   34 --
 gtk/desktop-integration.c            |    7 
 gtk/map-file                         |    1 
 gtk/spice-audio.c                    |   50 ---
 gtk/spice-channel.c                  |   15 -
 gtk/spice-channel.h                  |    3 
 gtk/spice-glib-sym-file              |    1 
 gtk/spice-gtk-session.c              |    4 
 gtk/spice-session-priv.h             |   98 -------
 gtk/spice-session.c                  |  488 ++++++++++++++++++++++++++++-------
 gtk/spice-session.h                  |    1 
 gtk/usb-device-manager.c             |   64 +---
 16 files changed, 484 insertions(+), 319 deletions(-)

New commits:
commit 14dc8e170e71e4b860afe84cd20900b462e9b132
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 17:31:43 2014 +0100

    usb: keep USB context alive as long as channels exist
    
    It was assumed the session would remain alive as long as channel
    existed, so USB context would be valid too. Now that channels
    are removed from session, USB context may be destroyed before
    channels. This produces invalid read/write on USB context.
    Make sure the context is alive as long as USB channels are by
    adding a reference on USB manager.
    
    ==6939== Invalid write of size 4
    ==6939==    at 0x394B604482: libusb_set_debug (core.c:1850)
    ==6939==    by 0x3953A063D5: usbredirhost_open_full (usbredirhost.c:741)
    ==6939==    by 0x4EC7E2F:
    spice_usbredir_channel_set_context (channel-usbredir.c:212)
    ==6939==    by 0x4EC7AB6:
    spice_usbredir_channel_reset (channel-usbredir.c:125)
    ==6939==    by 0x4EACCDC: spice_channel_reset (spice-channel.c:2621)
    ==6939==    by 0x4EACDB4: channel_disconnect (spice-channel.c:2640)
    ==6939==    by 0x4EAC28F: spice_channel_coroutine (spice-channel.c:2423)
    ==6939==    by 0x4EE8B1C: coroutine_trampoline (coroutine_ucontext.c:63)
    ==6939==    by 0x4EE87D6: continuation_trampoline (continuation.c:55)
    ==6939==    by 0x3928247FEF: ??? (in /usr/lib64/libc-2.20.so)
    ==6939==    by 0x51E36FF: ??? (in
    /usr/local/stow/spice-gtk/lib/libspice-client-glib-2.0.so.8.5.0)
    ==6939==    by 0xCF0C18F: ???
    ==6939==  Address 0xff15f90 is 0 bytes inside a block of size 536 free'd
    ==6939==    at 0x4A07CE9: free (in
    /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==6939==    by 0x394B606466: libusb_exit (core.c:2041)
    ==6939==    by 0x4ECC590: spice_usb_device_manager_finalize (usb-device-manager.c:371)

diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index 7b27516..e11eae0 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -767,6 +767,14 @@ static void channel_new(SpiceSession *session, SpiceChannel *channel,
     g_ptr_array_add(self->priv->channels, channel);
 
     spice_usb_device_manager_check_redir_on_connect(self, channel);
+
+    /*
+     * add a reference to ourself, to make sure the libusb context is
+     * alive as long as the channel is.
+     * TODO: moving to gusb could help here too.
+     */
+    g_object_ref(self);
+    g_object_weak_ref(G_OBJECT(channel), (GWeakNotify)g_object_unref, self);
 }
 
 static void channel_destroy(SpiceSession *session, SpiceChannel *channel,
commit a56c7296a61df3aba35baa498d2b3d5afc2af6bc
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 17:51:58 2014 +0100

    usb: return early if channel is not usb
    
    Return early if channel is not USB, replace:
    
    if (SPICE_IS_USBREDIR_CHANNEL(channel)) {
        /* code */
    }
    
    with
    
    if (!SPICE_IS_USBREDIR_CHANNEL(channel))
        return;

diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index a7b1140..7b27516 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -758,14 +758,15 @@ static void channel_new(SpiceSession *session, SpiceChannel *channel,
 {
     SpiceUsbDeviceManager *self = user_data;
 
-    if (SPICE_IS_USBREDIR_CHANNEL(channel)) {
-        spice_usbredir_channel_set_context(SPICE_USBREDIR_CHANNEL(channel),
-                                           self->priv->context);
-        spice_channel_connect(channel);
-        g_ptr_array_add(self->priv->channels, channel);
+    if (!SPICE_IS_USBREDIR_CHANNEL(channel))
+        return;
 
-        spice_usb_device_manager_check_redir_on_connect(self, channel);
-    }
+    spice_usbredir_channel_set_context(SPICE_USBREDIR_CHANNEL(channel),
+                                       self->priv->context);
+    spice_channel_connect(channel);
+    g_ptr_array_add(self->priv->channels, channel);
+
+    spice_usb_device_manager_check_redir_on_connect(self, channel);
 }
 
 static void channel_destroy(SpiceSession *session, SpiceChannel *channel,
@@ -773,8 +774,10 @@ static void channel_destroy(SpiceSession *session, SpiceChannel *channel,
 {
     SpiceUsbDeviceManager *self = user_data;
 
-    if (SPICE_IS_USBREDIR_CHANNEL(channel))
-        g_ptr_array_remove(self->priv->channels, channel);
+    if (!SPICE_IS_USBREDIR_CHANNEL(channel))
+        return;
+
+    g_ptr_array_remove(self->priv->channels, channel);
 }
 
 static void spice_usb_device_manager_auto_connect_cb(GObject      *gobject,
commit ff25f3eacb1776a754147cd57c76882392382030
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 12 15:55:23 2014 +0100

    session: disconnect in idle
    
    This is a workaround for existing clients such as virt-viewer that do
    not hold a reference to their sessions when calling
    spice_session_disconnect() and crash now that channels are removed from
    session during the call. They expect disconnection events to be deferred
    instead, let's defer actual disconnection to idle time for public
    disconnect API for compatibility reasons (it is still recommended to fix
    client code, for eventual future iterations)

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index f87e7ea..ba4ec1d 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -99,7 +99,7 @@ struct _SpiceSessionPrivate {
     GList             *migration_left;
     SpiceSessionMigration migration_state;
     gboolean          full_migration; /* seamless migration indicator */
-    gooblean          disconnecting;
+    guint             disconnecting;
     gboolean          migrate_wait_init;
     guint             after_main_init;
     gboolean          for_migration;
@@ -258,6 +258,31 @@ static void spice_session_init(SpiceSession *session)
 }
 
 static void
+session_disconnect(SpiceSession *self)
+{
+    SpiceSessionPrivate *s;
+    struct channel *item;
+    RingItem *ring, *next;
+
+    s = self->priv;
+    s->cmain = NULL;
+
+    for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) {
+        next = ring_next(&s->channels, ring);
+        item = SPICE_CONTAINEROF(ring, struct channel, link);
+        spice_session_channel_destroy(self, item->channel);
+    }
+
+    s->connection_id = 0;
+
+    g_free(s->name);
+    s->name = NULL;
+    memset(s->uuid, 0, sizeof(s->uuid));
+
+    spice_session_abort_migration(self);
+}
+
+static void
 spice_session_dispose(GObject *gobject)
 {
     SpiceSession *session = SPICE_SESSION(gobject);
@@ -265,11 +290,12 @@ spice_session_dispose(GObject *gobject)
 
     SPICE_DEBUG("session dispose");
 
-    spice_session_disconnect(session);
+    session_disconnect(session);
 
     g_warn_if_fail(s->migration == NULL);
     g_warn_if_fail(s->migration_left == NULL);
     g_warn_if_fail(s->after_main_init == 0);
+    g_warn_if_fail(s->disconnecting == 0);
 
     g_clear_object(&s->audio_manager);
     g_clear_object(&s->usb_manager);
@@ -1384,7 +1410,7 @@ gboolean spice_session_connect(SpiceSession *session)
     s = session->priv;
     g_return_val_if_fail(!s->disconnecting, FALSE);
 
-    spice_session_disconnect(session);
+    session_disconnect(session);
 
     s->client_provided_sockets = FALSE;
 
@@ -1419,7 +1445,7 @@ gboolean spice_session_open_fd(SpiceSession *session, int fd)
     s = session->priv;
     g_return_val_if_fail(!s->disconnecting, FALSE);
 
-    spice_session_disconnect(session);
+    session_disconnect(session);
 
     s->client_provided_sockets = TRUE;
 
@@ -1576,7 +1602,7 @@ void spice_session_abort_migration(SpiceSession *session)
 end:
     g_list_free(s->migration_left);
     s->migration_left = NULL;
-    spice_session_disconnect(s->migration);
+    session_disconnect(s->migration);
     g_object_unref(s->migration);
     s->migration = NULL;
 
@@ -1616,7 +1642,7 @@ void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel)
 
     if (g_list_length(s->migration_left) == 0) {
         CHANNEL_DEBUG(channel, "migration: all channel migrated, success");
-        spice_session_disconnect(s->migration);
+        session_disconnect(s->migration);
         g_object_unref(s->migration);
         s->migration = NULL;
         spice_session_set_migration_state(session, SPICE_SESSION_MIGRATION_NONE);
@@ -1719,6 +1745,18 @@ gboolean spice_session_get_read_only(SpiceSession *self)
     return self->priv->read_only;
 }
 
+static gboolean session_disconnect_idle(SpiceSession *self)
+{
+    SpiceSessionPrivate *s = self->priv;
+
+    session_disconnect(self);
+    s->disconnecting = 0;
+
+    g_object_unref(self);
+
+    return G_SOURCE_REMOVE;
+}
+
 /**
  * spice_session_disconnect:
  * @session:
@@ -1728,37 +1766,17 @@ gboolean spice_session_get_read_only(SpiceSession *self)
 void spice_session_disconnect(SpiceSession *session)
 {
     SpiceSessionPrivate *s;
-    struct channel *item;
-    RingItem *ring, *next;
 
     g_return_if_fail(SPICE_IS_SESSION(session));
-    g_return_if_fail(session->priv != NULL);
 
     s = session->priv;
 
     SPICE_DEBUG("session: disconnecting %d", s->disconnecting);
-    if (s->disconnecting)
+    if (s->disconnecting != 0)
         return;
 
     g_object_ref(session);
-    s->disconnecting = TRUE;
-    s->cmain = NULL;
-
-    for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) {
-        next = ring_next(&s->channels, ring);
-        item = SPICE_CONTAINEROF(ring, struct channel, link);
-        spice_session_channel_destroy(session, item->channel);
-    }
-
-    s->connection_id = 0;
-
-    g_free(s->name);
-    s->name = NULL;
-    memset(s->uuid, 0, sizeof(s->uuid));
-
-    spice_session_abort_migration(session);
-    s->disconnecting = FALSE;
-    g_object_unref(session);
+    s->disconnecting = g_idle_add((GSourceFunc)session_disconnect_idle, session);
 }
 
 /**
commit 45f417a5f8329804f6d6cce1ba3aeefff3385f1d
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 12 15:55:23 2014 +0100

    session: keep a reference on disconnect
    
    It is idiomatic for client code to clean up its reference on channel
    disconnection. Keeping a reference during disconnect helps solving
    potential crashes if the session is unref'ed during callbacks.

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 8059f2f..f87e7ea 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1740,6 +1740,7 @@ void spice_session_disconnect(SpiceSession *session)
     if (s->disconnecting)
         return;
 
+    g_object_ref(session);
     s->disconnecting = TRUE;
     s->cmain = NULL;
 
@@ -1757,6 +1758,7 @@ void spice_session_disconnect(SpiceSession *session)
 
     spice_session_abort_migration(session);
     s->disconnecting = FALSE;
+    g_object_unref(session);
 }
 
 /**
commit 38bf189f0502a1f1570fb5825b571f45f2f47ba5
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 12 15:59:05 2014 +0100

    session: remove sticky disconnecting flag
    
    This used to help prevent double-unref when channel were considered part
    of the session as long as they lived. Now it shouldn't be required
    anymore

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index a7f128a..8059f2f 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1382,9 +1382,9 @@ gboolean spice_session_connect(SpiceSession *session)
     g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
 
     s = session->priv;
+    g_return_val_if_fail(!s->disconnecting, FALSE);
 
     spice_session_disconnect(session);
-    s->disconnecting = FALSE;
 
     s->client_provided_sockets = FALSE;
 
@@ -1417,9 +1417,9 @@ gboolean spice_session_open_fd(SpiceSession *session, int fd)
     g_return_val_if_fail(fd >= -1, FALSE);
 
     s = session->priv;
+    g_return_val_if_fail(!s->disconnecting, FALSE);
 
     spice_session_disconnect(session);
-    s->disconnecting = FALSE;
 
     s->client_provided_sockets = TRUE;
 
@@ -1756,8 +1756,7 @@ void spice_session_disconnect(SpiceSession *session)
     memset(s->uuid, 0, sizeof(s->uuid));
 
     spice_session_abort_migration(session);
-    /* we leave disconnecting = TRUE, so that spice_channel_disconnect()
-       is not called multiple times */
+    s->disconnecting = FALSE;
 }
 
 /**
commit 5b41e43d0b178219ce295478bf9b35ce122f29aa
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Sun Nov 9 21:55:18 2014 +0100

    channel: deprecate spice_channel_destroy()
    
    This function is somewhat useless, and dangerous since it is calling
    g_object_unref() behind your back (although this is mentioned in the
    doc, I consider this a bad practice).

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 7c18d87..ea0ed34 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -2038,8 +2038,12 @@ SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id)
  * spice_channel_destroy:
  * @channel:
  *
- * Disconnect and unref the @channel. Called by @spice_session_channel_destroy()
+ * Disconnect and unref the @channel.
  *
+ * Deprecated: 0.27: this function has been deprecated because it is
+ * misleading, the object is not actually destroyed. Instead, it is
+ * recommended to call explicitely spice_channel_disconnect() and
+ * g_object_unref().
  **/
 void spice_channel_destroy(SpiceChannel *channel)
 {
diff --git a/gtk/spice-channel.h b/gtk/spice-channel.h
index 1c303b4..8d07383 100644
--- a/gtk/spice-channel.h
+++ b/gtk/spice-channel.h
@@ -107,7 +107,6 @@ GType spice_channel_get_type(void);
 typedef void (*spice_msg_handler)(SpiceChannel *channel, SpiceMsgIn *in);
 
 SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id);
-void spice_channel_destroy(SpiceChannel *channel);
 gboolean spice_channel_connect(SpiceChannel *channel);
 gboolean spice_channel_open_fd(SpiceChannel *channel, int fd);
 void spice_channel_disconnect(SpiceChannel *channel, SpiceChannelEvent reason);
@@ -118,6 +117,8 @@ gboolean spice_channel_flush_finish(SpiceChannel *channel, GAsyncResult *result,
 #ifndef SPICE_DISABLE_DEPRECATED
 SPICE_DEPRECATED
 void spice_channel_set_capability(SpiceChannel *channel, guint32 cap);
+SPICE_DEPRECATED
+void spice_channel_destroy(SpiceChannel *channel);
 #endif
 
 const gchar* spice_channel_type_to_string(gint type);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 6c5e03a..a7f128a 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1756,9 +1756,8 @@ void spice_session_disconnect(SpiceSession *session)
     memset(s->uuid, 0, sizeof(s->uuid));
 
     spice_session_abort_migration(session);
-    /* we leave disconnecting = TRUE, so that spice_channel_destroy()
-       is not called multiple times on channels that are in pending
-       destroy state. */
+    /* we leave disconnecting = TRUE, so that spice_channel_disconnect()
+       is not called multiple times */
 }
 
 /**
@@ -2066,7 +2065,8 @@ static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *c
     g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_DESTROY], 0, channel);
 
     g_clear_object(&channel->priv->session);
-    spice_channel_destroy(channel);
+    spice_channel_disconnect(channel, SPICE_CHANNEL_NONE);
+    g_object_unref(channel);
 }
 
 G_GNUC_INTERNAL
commit 80f2f98b2c9e908c44c419af543a782804457bec
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 13:55:18 2014 +0100

    display: don't reschedule stream if disconnected from session
    
    Avoid the following critical when a channel is disconnected with a
    pending stream (the streams are cleared on channel reset, after
    coroutine exit)
    
      (process:17188): GSpice-CRITICAL **: spice_session_get_mm_time: assertion 'session != NULL' failed
    
      #0  0x00007ffff71c24e5 in spice_session_get_mm_time (session=0x0) at spice-session.c:1999
      #1  0x00007ffff71d438c in display_stream_schedule (st=0xa33040) at channel-display.c:1014
      #2  0x00007ffff71d4a09 in display_stream_render (st=0xa33040,
          st at entry=<error reading variable: value has been optimized out>) at channel-display.c:1165
      #3  0x0000003e1944a553 in g_timeout_dispatch (source=0xad64e0, callback=<optimized out>, user_data=<optimized out>) at gmain.c:4520
      #4  0x0000003e19449aeb in g_main_context_dispatch (context=0x6a32b0) at gmain.c:3111
      #5  0x0000003e19449aeb in g_main_context_dispatch (context=context at entry=0x6a32b0) at gmain.c:3710
      #6  0x0000003e19449e88 in g_main_context_iterate (context=0x6a32b0, block=block at entry=1, dispatch=dispatch at entry=1, self=<optimized out>) at gmain.c:3781
      #7  0x0000003e1944a1b2 in g_main_loop_run (loop=0x97e200) at gmain.c:3975
      #8  0x0000003e1c9ebb35 in gtk_main () at gtkmain.c:1207
      #9  0x0000000000430185 in main (argc=1, argv=0x7fffffffdcb8) at virt-viewer-main.c:119

diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index 940a5a7..17e2f6e 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -1003,15 +1003,16 @@ static void display_handle_stream_create(SpiceChannel *channel, SpiceMsgIn *in)
 /* coroutine or main context */
 static gboolean display_stream_schedule(display_stream *st)
 {
+    SpiceSession *session = spice_channel_get_session(st->channel);
     guint32 time, d;
     SpiceStreamDataHeader *op;
     SpiceMsgIn *in;
 
     SPICE_DEBUG("%s", __FUNCTION__);
-    if (st->timeout)
+    if (st->timeout || !session)
         return TRUE;
 
-    time = spice_session_get_mm_time(spice_channel_get_session(st->channel));
+    time = spice_session_get_mm_time(session);
     in = g_queue_peek_head(st->msgq);
 
     if (in == NULL) {
commit 8943d232995147214e39314ec375d3e6f3a91bff
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Sun Nov 9 21:47:41 2014 +0100

    session: remove channels on disconnect
    
    A channel is considered to be part of a session as long as it is
    alive. However, this model is problematic, since library user may hold
    channel references, and thus the channel will remain in the
    session. Calling spice_session_disconnect() several time will end up
    calling spice_channel_destroy(), releasing references that aren't owned
    by the session. This usually causes crashes, in particular with language
    bindings that do not deal well with a library model where objects can't
    be referenced at will.

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 154dacb..7c18d87 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -152,9 +152,6 @@ static void spice_channel_dispose(GObject *gobject)
 
     CHANNEL_DEBUG(channel, "%s %p", __FUNCTION__, gobject);
 
-    if (c->session)
-        spice_session_channel_destroy(c->session, channel);
-
     spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED);
 
     if (c->session) {
@@ -2041,7 +2038,7 @@ SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id)
  * spice_channel_destroy:
  * @channel:
  *
- * Disconnect and unref the @channel. Called by @spice_session_disconnect()
+ * Disconnect and unref the @channel. Called by @spice_session_channel_destroy()
  *
  **/
 void spice_channel_destroy(SpiceChannel *channel)
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 7fc71cf..46938ff 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -48,7 +48,6 @@ gboolean spice_session_get_client_provided_socket(SpiceSession *session);
 GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel,
                                                    gboolean *use_tls, GError **error);
 void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel);
-void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel);
 void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel);
 
 void spice_session_set_mm_time(SpiceSession *session, guint32 time);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 8527801..6c5e03a 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -210,6 +210,8 @@ enum {
 
 static guint signals[SPICE_SESSION_LAST_SIGNAL];
 
+static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel);
+
 static void update_proxy(SpiceSession *self, const gchar *str)
 {
     SpiceSessionPrivate *s = self->priv;
@@ -1462,8 +1464,10 @@ void spice_session_switching_disconnect(SpiceSession *self)
     for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) {
         next = ring_next(&s->channels, ring);
         item = SPICE_CONTAINEROF(ring, struct channel, link);
-        if (item->channel != s->cmain)
-            spice_channel_destroy(item->channel); /* /!\ item and channel are destroy() after this call */
+
+        if (item->channel == s->cmain)
+            continue;
+        spice_session_channel_destroy(self, item->channel);
     }
 
     g_warn_if_fail(!ring_is_empty(&s->channels)); /* ring_get_length() == 1 */
@@ -1742,7 +1746,7 @@ void spice_session_disconnect(SpiceSession *session)
     for (ring = ring_get_head(&s->channels); ring != NULL; ring = next) {
         next = ring_next(&s->channels, ring);
         item = SPICE_CONTAINEROF(ring, struct channel, link);
-        spice_channel_destroy(item->channel); /* /!\ item and channel are destroy() after this call */
+        spice_session_channel_destroy(session, item->channel);
     }
 
     s->connection_id = 0;
@@ -2030,8 +2034,7 @@ void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel)
     g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_NEW], 0, channel);
 }
 
-G_GNUC_INTERNAL
-void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
+static void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
 {
     g_return_if_fail(SPICE_IS_SESSION(session));
     g_return_if_fail(SPICE_IS_CHANNEL(channel));
@@ -2061,6 +2064,9 @@ void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
     free(item);
 
     g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_DESTROY], 0, channel);
+
+    g_clear_object(&channel->priv->session);
+    spice_channel_destroy(channel);
 }
 
 G_GNUC_INTERNAL
commit a67e5df1496812e6bc8405be95144f0eddc334b8
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 12:06:19 2014 +0100

    session: move SpiceSessionPrivate out of headers
    
    Make sure none of the SpiceSessionPrivate fields are accessed directly anymore

diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index c9efba3..7fc71cf 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -37,90 +37,8 @@ typedef struct _PhodavServer PhodavServer;
 
 G_BEGIN_DECLS
 
-#define IMAGES_CACHE_SIZE_DEFAULT (1024 * 1024 * 80)
-#define MIN_GLZ_WINDOW_SIZE_DEFAULT (1024 * 1024 * 12)
-#define MAX_GLZ_WINDOW_SIZE_DEFAULT MIN((LZ_MAX_WINDOW_SIZE * 4), 1024 * 1024 * 64)
 #define WEBDAV_MAGIC_SIZE 16
 
-struct _SpiceSessionPrivate {
-    char              *host;
-    char              *port;
-    char              *tls_port;
-    char              *username;
-    char              *password;
-    char              *ca_file;
-    char              *ciphers;
-    GByteArray        *pubkey;
-    GByteArray        *ca;
-    char              *cert_subject;
-    guint             verify;
-    gboolean          read_only;
-    SpiceURI          *proxy;
-    gchar             *shared_dir;
-
-    /* whether to enable audio */
-    gboolean          audio;
-
-    /* whether to enable smartcard event forwarding to the server */
-    gboolean          smartcard;
-
-    /* list of certificates to use for the software smartcard reader if
-     * enabled. For now, it has to contain exactly 3 certificates for
-     * the software reader to be functional
-     */
-    GStrv             smartcard_certificates;
-
-    /* path to the local certificate database to use to lookup the
-     * certificates stored in 'certificates'. If NULL, libcacard will
-     * fallback to using a default database.
-     */
-    char *            smartcard_db;
-
-    /* whether to enable USB redirection */
-    gboolean          usbredir;
-
-    /* Set when a usbredir channel has requested the keyboard grab to be
-       temporarily released (because it is going to invoke policykit) */
-    gboolean          inhibit_keyboard_grab;
-
-    GStrv             disable_effects;
-    GStrv             secure_channels;
-    gint              color_depth;
-
-    int               connection_id;
-    int               protocol;
-    SpiceChannel      *cmain; /* weak reference */
-    Ring              channels;
-    guint32           mm_time;
-    gboolean          client_provided_sockets;
-    guint64           mm_time_at_clock;
-    SpiceSession      *migration;
-    GList             *migration_left;
-    SpiceSessionMigration migration_state;
-    gboolean          full_migration; /* seamless migration indicator */
-    gboolean          disconnecting;
-    gboolean          migrate_wait_init;
-    guint             after_main_init;
-    gboolean          for_migration;
-
-    display_cache     *images;
-    display_cache     *palettes;
-    SpiceGlzDecoderWindow *glz_window;
-    int               images_cache_size;
-    int               glz_window_size;
-    uint32_t          pci_ram_size;
-    uint32_t          n_display_channels;
-    guint8            uuid[WEBDAV_MAGIC_SIZE];
-    gchar             *name;
-
-    /* associated objects */
-    SpiceAudio        *audio_manager;
-    SpiceUsbDeviceManager *usb_manager;
-    SpicePlaybackChannel *playback_channel;
-    PhodavServer      *webdav;
-    guint8             webdav_magic[16];
-};
-
 SpiceSession *spice_session_new_from_session(SpiceSession *session);
 
 void spice_session_set_connection_id(SpiceSession *session, int id);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 5ddcd5c..8527801 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -39,6 +39,90 @@ struct channel {
     RingItem          link;
 };
 
+#define IMAGES_CACHE_SIZE_DEFAULT (1024 * 1024 * 80)
+#define MIN_GLZ_WINDOW_SIZE_DEFAULT (1024 * 1024 * 12)
+#define MAX_GLZ_WINDOW_SIZE_DEFAULT MIN((LZ_MAX_WINDOW_SIZE * 4), 1024 * 1024 * 64)
+
+struct _SpiceSessionPrivate {
+    char              *host;
+    char              *port;
+    char              *tls_port;
+    char              *username;
+    char              *password;
+    char              *ca_file;
+    char              *ciphers;
+    GByteArray        *pubkey;
+    GByteArray        *ca;
+    char              *cert_subject;
+    guint             verify;
+    gboolean          read_only;
+    SpiceURI          *proxy;
+    gchar             *shared_dir;
+
+    /* whether to enable audio */
+    gboolean          audio;
+
+    /* whether to enable smartcard event forwarding to the server */
+    gboolean          smartcard;
+
+    /* list of certificates to use for the software smartcard reader if
+     * enabled. For now, it has to contain exactly 3 certificates for
+     * the software reader to be functional
+     */
+    GStrv             smartcard_certificates;
+
+    /* path to the local certificate database to use to lookup the
+     * certificates stored in 'certificates'. If NULL, libcacard will
+     * fallback to using a default database.
+     */
+    char *            smartcard_db;
+
+    /* whether to enable USB redirection */
+    gboolean          usbredir;
+
+    /* Set when a usbredir channel has requested the keyboard grab to be
+       temporarily released (because it is going to invoke policykit) */
+    gboolean          inhibit_keyboard_grab;
+
+    GStrv             disable_effects;
+    GStrv             secure_channels;
+    gint              color_depth;
+
+    int               connection_id;
+    int               protocol;
+    SpiceChannel      *cmain; /* weak reference */
+    Ring              channels;
+    guint32           mm_time;
+    gboolean          client_provided_sockets;
+    guint64           mm_time_at_clock;
+    SpiceSession      *migration;
+    GList             *migration_left;
+    SpiceSessionMigration migration_state;
+    gboolean          full_migration; /* seamless migration indicator */
+    gooblean          disconnecting;
+    gboolean          migrate_wait_init;
+    guint             after_main_init;
+    gboolean          for_migration;
+
+    display_cache     *images;
+    display_cache     *palettes;
+    SpiceGlzDecoderWindow *glz_window;
+    int               images_cache_size;
+    int               glz_window_size;
+    uint32_t          pci_ram_size;
+    uint32_t          n_display_channels;
+    guint8            uuid[16];
+    gchar             *name;
+
+    /* associated objects */
+    SpiceAudio        *audio_manager;
+    SpiceUsbDeviceManager *usb_manager;
+    SpicePlaybackChannel *playback_channel;
+    PhodavServer      *webdav;
+    guint8             webdav_magic[WEBDAV_MAGIC_SIZE];
+};
+
+
 /**
  * SECTION:spice-session
  * @short_description: handles connection details, and active channels
commit e0514dc3f8ebcdd2d97bcc5e561a391a0deae61f
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 12:02:06 2014 +0100

    gtk: do not require glib session private fields
    
    Use GObject object association for session helpers.
    
    GtkSession and DesktopIntegration are in the gtk library SpiceSession is
    in glib one. So far we had the SessionPriv structure shared between the
    two libraries, so they could fit their pointers there. But this is no
    longer possible when moving the private structure in .c. We could add
    more accessors, but they would need to be in public API, and this isn't
    supposed to be accessed by API users.

diff --git a/gtk/desktop-integration.c b/gtk/desktop-integration.c
index 145fa6a..c366fd0 100644
--- a/gtk/desktop-integration.c
+++ b/gtk/desktop-integration.c
@@ -187,9 +187,6 @@ static void spice_desktop_integration_class_init(SpiceDesktopIntegrationClass *k
     g_type_class_add_private(klass, sizeof(SpiceDesktopIntegrationPrivate));
 }
 
-/* ------------------------------------------------------------------ */
-/* public methods                                                     */
-
 SpiceDesktopIntegration *spice_desktop_integration_get(SpiceSession *session)
 {
     SpiceDesktopIntegration *self;
@@ -198,10 +195,10 @@ SpiceDesktopIntegration *spice_desktop_integration_get(SpiceSession *session)
     g_return_val_if_fail(session != NULL, NULL);
 
     g_static_mutex_lock(&mutex);
-    self = session->priv->desktop_integration;
+    self = g_object_get_data(G_OBJECT(session), "spice-desktop");
     if (self == NULL) {
         self = g_object_new(SPICE_TYPE_DESKTOP_INTEGRATION, NULL);
-        session->priv->desktop_integration = self;
+        g_object_set_data_full(G_OBJECT(session), "spice-desktop", self, g_object_unref);
     }
     g_static_mutex_unlock(&mutex);
 
diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index 701950d..de01358 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -1119,10 +1119,10 @@ SpiceGtkSession *spice_gtk_session_get(SpiceSession *session)
     static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
 
     g_static_mutex_lock(&mutex);
-    self = session->priv->gtk_session;
+    self = g_object_get_data(G_OBJECT(session), "spice-gtk-session");
     if (self == NULL) {
         self = g_object_new(SPICE_TYPE_GTK_SESSION, "session", session, NULL);
-        session->priv->gtk_session = self;
+        g_object_set_data_full(G_OBJECT(session), "spice-gtk-session", self, g_object_unref);
     }
     g_static_mutex_unlock(&mutex);
 
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 98c3f72..c9efba3 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -115,8 +115,6 @@ struct _SpiceSessionPrivate {
 
     /* associated objects */
     SpiceAudio        *audio_manager;
-    SpiceDesktopIntegration *desktop_integration;
-    SpiceGtkSession   *gtk_session;
     SpiceUsbDeviceManager *usb_manager;
     SpicePlaybackChannel *playback_channel;
     PhodavServer      *webdav;
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 02ebd74..5ddcd5c 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -186,8 +186,6 @@ spice_session_dispose(GObject *gobject)
     g_warn_if_fail(s->after_main_init == 0);
 
     g_clear_object(&s->audio_manager);
-    g_clear_object(&s->desktop_integration);
-    g_clear_object(&s->gtk_session);
     g_clear_object(&s->usb_manager);
     g_clear_object(&s->proxy);
     g_clear_object(&s->webdav);
commit e02733abe9b43b6b84da1e240bf037a656ab98c3
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 11:57:47 2014 +0100

    usb: move device manager initialization to session
    
    Use session accessors to initialize the device manager.
    Add missing session parameter check (public API).

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 2e837f2..02ebd74 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2347,6 +2347,40 @@ SpiceAudio *spice_audio_get(SpiceSession *session, GMainContext *context)
     return self;
 }
 
+/**
+ * spice_usb_device_manager_get:
+ * @session: #SpiceSession for which to get the #SpiceUsbDeviceManager
+ *
+ * Gets the #SpiceUsbDeviceManager associated with the passed in #SpiceSession.
+ * A new #SpiceUsbDeviceManager instance will be created the first time this
+ * function is called for a certain #SpiceSession.
+ *
+ * Note that this function returns a weak reference, which should not be used
+ * after the #SpiceSession itself has been unref-ed by the caller.
+ *
+ * Returns: (transfer none): a weak reference to the #SpiceUsbDeviceManager associated with the passed in #SpiceSession
+ */
+SpiceUsbDeviceManager *spice_usb_device_manager_get(SpiceSession *session,
+                                                    GError **err)
+{
+    SpiceUsbDeviceManager *self;
+    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
+
+    g_static_mutex_lock(&mutex);
+    self = session->priv->usb_manager;
+    if (self == NULL) {
+        self = g_initable_new(SPICE_TYPE_USB_DEVICE_MANAGER, NULL, err,
+                              "session", session, NULL);
+        session->priv->usb_manager = self;
+    }
+    g_static_mutex_unlock(&mutex);
+
+    return self;
+}
+
 G_GNUC_INTERNAL
 gboolean spice_session_get_audio_enabled(SpiceSession *session)
 {
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index f80b657..a7b1140 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -1300,39 +1300,6 @@ static SpiceUsbredirChannel *spice_usb_device_manager_get_channel_for_dev(
 /* public api                                                         */
 
 /**
- * spice_usb_device_manager_get:
- * @session: #SpiceSession for which to get the #SpiceUsbDeviceManager
- *
- * Gets the #SpiceUsbDeviceManager associated with the passed in #SpiceSession.
- * A new #SpiceUsbDeviceManager instance will be created the first time this
- * function is called for a certain #SpiceSession.
- *
- * Note that this function returns a weak reference, which should not be used
- * after the #SpiceSession itself has been unref-ed by the caller.
- *
- * Returns: (transfer none): a weak reference to the #SpiceUsbDeviceManager associated with the passed in #SpiceSession
- */
-SpiceUsbDeviceManager *spice_usb_device_manager_get(SpiceSession *session,
-                                                    GError **err)
-{
-    SpiceUsbDeviceManager *self;
-    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-
-    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
-
-    g_static_mutex_lock(&mutex);
-    self = session->priv->usb_manager;
-    if (self == NULL) {
-        self = g_initable_new(SPICE_TYPE_USB_DEVICE_MANAGER, NULL, err,
-                              "session", session, NULL);
-        session->priv->usb_manager = self;
-    }
-    g_static_mutex_unlock(&mutex);
-
-    return self;
-}
-
-/**
  * spice_usb_device_manager_get_devices_with_filter:
  * @manager: the #SpiceUsbDeviceManager manager
  * @filter: (allow-none): filter string for selecting which devices to return,
commit 5b0c345e744964e50a3c915ef5d756b7399c2b34
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 11:56:42 2014 +0100

    webdav: move initialization to session
    
    Use session accessors to initialize the webdav server

diff --git a/gtk/channel-webdav.c b/gtk/channel-webdav.c
index dbb8730..94f3ef3 100644
--- a/gtk/channel-webdav.c
+++ b/gtk/channel-webdav.c
@@ -694,19 +694,14 @@ end:
     g_object_unref(gaddr);
 }
 
-static PhodavServer* webdav_server_new(SpiceSession *session)
+G_GNUC_INTERNAL
+PhodavServer* channel_webdav_server_new(SpiceSession *session)
 {
     PhodavServer *dav;
     SoupServer *server;
     SoupSocket *listener;
-    int i;
-
-    g_warn_if_fail(!session->priv->webdav);
 
     dav = phodav_server_new(0, spice_session_get_shared_dir(session));
-    session->priv->webdav = dav;
-    for (i = 0; i < sizeof(session->priv->webdav_magic); i++)
-        session->priv->webdav_magic[i] = g_random_int_range(0, 255);
 
     server = phodav_server_get_soup_server(dav);
     listener = soup_server_get_listener(server);
@@ -723,21 +718,12 @@ static PhodavServer* phodav_server_get(SpiceSession *session, gint *port)
     g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
 
 #ifdef USE_PHODAV
-    PhodavServer *self = NULL;
-    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-
-    g_static_mutex_lock(&mutex);
-    self = session->priv->webdav;
-    if (self == NULL) {
-        self = webdav_server_new(session);
-        phodav_server_run(self);
-    }
-    g_static_mutex_unlock(&mutex);
+    PhodavServer *server = spice_session_get_webdav_server(session);
 
     if (port)
-        *port = phodav_server_get_port(self);
+        *port = phodav_server_get_port(server);
 
-    return self;
+    return server;
 #else
     g_return_val_if_reached(NULL);
 #endif
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 95fc078..98c3f72 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -178,6 +178,8 @@ gboolean spice_session_get_smartcard_enabled(SpiceSession *session);
 gboolean spice_session_get_usbredir_enabled(SpiceSession *session);
 
 const guint8* spice_session_get_webdav_magic(SpiceSession *session);
+PhodavServer *spice_session_get_webdav_server(SpiceSession *session);
+PhodavServer* channel_webdav_server_new(SpiceSession *session);
 guint spice_session_get_n_display_channels(SpiceSession *session);
 void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel);
 gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 5c1966e..2e837f2 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2379,6 +2379,29 @@ const guint8* spice_session_get_webdav_magic(SpiceSession *session)
     return session->priv->webdav_magic;
 }
 
+G_GNUC_INTERNAL
+PhodavServer* spice_session_get_webdav_server(SpiceSession *session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
+#ifdef USE_PHODAV
+    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+    int i;
+
+    g_static_mutex_lock(&mutex);
+    if (!session->priv->webdav) {
+        for (i = 0; i < sizeof(session->priv->webdav_magic); i++)
+            session->priv->webdav_magic[i] = g_random_int_range(0, 255);
+
+        session->priv->webdav = channel_webdav_server_new(session);
+        phodav_server_run(session->priv->webdav);
+    }
+    g_static_mutex_unlock(&mutex);
+#endif
+
+    return session->priv->webdav;
+}
+
 /**
  * spice_session_is_for_migration:
  * @session: a Spice session
commit a88a31902a0998ad38f0206ddb5ff6c0c6ea417b
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 18:11:01 2014 +0100

    Rename display_channels_count/n_display_channels

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index b62da60..7af4a2e 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1298,7 +1298,7 @@ static gboolean timer_set_display(gpointer data)
 
     /* ensure we have an explicit monitor configuration at least for
        number of display channels */
-    for (i = 0; i < spice_session_get_display_channels_count(session); i++)
+    for (i = 0; i < spice_session_get_n_display_channels(session); i++)
         if (!c->display[i].enabled_set) {
             SPICE_DEBUG("Not sending monitors config, missing monitors");
             return FALSE;
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index e150fc7..95fc078 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -109,7 +109,7 @@ struct _SpiceSessionPrivate {
     int               images_cache_size;
     int               glz_window_size;
     uint32_t          pci_ram_size;
-    uint32_t          display_channels_count;
+    uint32_t          n_display_channels;
     guint8            uuid[WEBDAV_MAGIC_SIZE];
     gchar             *name;
 
@@ -157,7 +157,7 @@ void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size);
 
 void spice_session_set_caches_hints(SpiceSession *session,
                                     uint32_t pci_ram_size,
-                                    uint32_t display_channels_count);
+                                    uint32_t n_display_channels);
 void spice_session_get_caches(SpiceSession *session,
                               display_cache **images,
                               SpiceGlzDecoderWindow **glz_window);
@@ -178,7 +178,7 @@ gboolean spice_session_get_smartcard_enabled(SpiceSession *session);
 gboolean spice_session_get_usbredir_enabled(SpiceSession *session);
 
 const guint8* spice_session_get_webdav_magic(SpiceSession *session);
-guint spice_session_get_display_channels_count(SpiceSession *session);
+guint spice_session_get_n_display_channels(SpiceSession *session);
 void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel);
 gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session);
 
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index a2e79bb..5c1966e 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2177,14 +2177,14 @@ void spice_session_get_caches(SpiceSession *session,
 G_GNUC_INTERNAL
 void spice_session_set_caches_hints(SpiceSession *session,
                                     uint32_t pci_ram_size,
-                                    uint32_t display_channels_count)
+                                    uint32_t n_display_channels)
 {
     g_return_if_fail(SPICE_IS_SESSION(session));
 
     SpiceSessionPrivate *s = session->priv;
 
     s->pci_ram_size = pci_ram_size;
-    s->display_channels_count = display_channels_count;
+    s->n_display_channels = n_display_channels;
 
     /* TODO: when setting cache and window size, we should consider the client's
      *       available memory and the number of display channels */
@@ -2199,11 +2199,11 @@ void spice_session_set_caches_hints(SpiceSession *session,
 }
 
 G_GNUC_INTERNAL
-guint spice_session_get_display_channels_count(SpiceSession *session)
+guint spice_session_get_n_display_channels(SpiceSession *session)
 {
     g_return_val_if_fail(session != NULL, 0);
 
-    return session->priv->display_channels_count;
+    return session->priv->n_display_channels;
 }
 
 G_GNUC_INTERNAL
commit 3623476d0dc6e4dcac24543a5918123db7b5a08f
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 11:52:13 2014 +0100

    session: add and use internal accessors
    
    Avoid dereferencing session private data directly, and use accessors
    instead.

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index bf7c204..b62da60 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1298,7 +1298,7 @@ static gboolean timer_set_display(gpointer data)
 
     /* ensure we have an explicit monitor configuration at least for
        number of display channels */
-    for (i = 0; i < session->priv->display_channels_count; i++)
+    for (i = 0; i < spice_session_get_display_channels_count(session); i++)
         if (!c->display[i].enabled_set) {
             SPICE_DEBUG("Not sending monitors config, missing monitors");
             return FALSE;
@@ -2132,7 +2132,8 @@ static gboolean migrate_connect(gpointer data)
 
     /* the migration process is in 2 steps, first the main channel and
        then the rest of the channels */
-    mig->session->priv->cmain = migrate_channel_connect(mig, SPICE_CHANNEL_MAIN, 0);
+    spice_session_set_main_channel(mig->session,
+                                   migrate_channel_connect(mig, SPICE_CHANNEL_MAIN, 0));
 
     return FALSE;
 }
@@ -2156,13 +2157,11 @@ static void main_migrate_connect(SpiceChannel *channel,
 
     CHANNEL_DEBUG(channel, "migrate connect");
     session = spice_channel_get_session(channel);
-    if (session->priv->migration != NULL)
-        goto end;
-
     mig.session = spice_session_new_from_session(session);
     if (mig.session == NULL)
         goto end;
-    session->priv->migration = mig.session;
+    if (!spice_session_set_migration_session(session, mig.session))
+        goto end;
 
     main_priv->migrate_data = &mig;
 
diff --git a/gtk/channel-webdav.c b/gtk/channel-webdav.c
index 0529b59..dbb8730 100644
--- a/gtk/channel-webdav.c
+++ b/gtk/channel-webdav.c
@@ -336,13 +336,11 @@ static void magic_written(GObject *source_object,
     SpiceWebdavChannelPrivate *c = self->priv;
     gssize bytes_written;
     GError *err = NULL;
-    SpiceSession *session;
 
-    session = spice_channel_get_session(SPICE_CHANNEL(self));
     bytes_written = g_output_stream_write_finish(G_OUTPUT_STREAM(source_object),
                                                  res, &err);
 
-    if (err || bytes_written != sizeof(session->priv->webdav_magic))
+    if (err || bytes_written != WEBDAV_MAGIC_SIZE)
         goto error;
 
     client_start_read(self, client);
@@ -396,7 +394,7 @@ static void client_connected(GObject *source_object,
     g_object_unref(output);
 
     g_output_stream_write_async(g_io_stream_get_output_stream(G_IO_STREAM(conn)),
-                                session->priv->webdav_magic, sizeof(session->priv->webdav_magic),
+                                spice_session_get_webdav_magic(session), WEBDAV_MAGIC_SIZE,
                                 G_PRIORITY_DEFAULT, c->cancellable,
                                 magic_written, client);
     return;
@@ -654,7 +652,7 @@ static void new_connection(SoupSocket *sock,
     GSocketAddress *gaddr;
     GInetAddress *iaddr;
     guint port;
-    guint8 magic[16];
+    guint8 magic[WEBDAV_MAGIC_SIZE];
     gsize nread;
     gboolean success = FALSE;
     SoupSocketIOStatus status;
@@ -680,7 +678,7 @@ static void new_connection(SoupSocket *sock,
     g_object_set(new, "non-blocking", TRUE, NULL);
 
     /* check we got the right magic */
-    if (memcmp(session->priv->webdav_magic, magic, sizeof(magic))) {
+    if (memcmp(spice_session_get_webdav_magic(session), magic, sizeof(magic))) {
         g_warn_if_reached();
         goto end;
     }
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 94f980f..154dacb 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -1987,7 +1987,7 @@ SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id)
         break;
     case SPICE_CHANNEL_PLAYBACK:
     case SPICE_CHANNEL_RECORD: {
-        if (!s->priv->audio) {
+        if (!spice_session_get_audio_enabled(s)) {
             g_debug("audio channel is disabled, not creating it");
             return NULL;
         }
@@ -1997,7 +1997,7 @@ SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id)
     }
 #ifdef USE_SMARTCARD
     case SPICE_CHANNEL_SMARTCARD: {
-        if (!s->priv->smartcard) {
+        if (!spice_session_get_smartcard_enabled(s)) {
             g_debug("smartcard channel is disabled, not creating it");
             return NULL;
         }
@@ -2007,7 +2007,7 @@ SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id)
 #endif
 #ifdef USE_USBREDIR
     case SPICE_CHANNEL_USBREDIR: {
-        if (!s->priv->usbredir) {
+        if (!spice_session_get_usbredir_enabled(s)) {
             g_debug("usbredir channel is disabled, not creating it");
             return NULL;
         }
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 6d8be8d..e150fc7 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -40,6 +40,7 @@ G_BEGIN_DECLS
 #define IMAGES_CACHE_SIZE_DEFAULT (1024 * 1024 * 80)
 #define MIN_GLZ_WINDOW_SIZE_DEFAULT (1024 * 1024 * 12)
 #define MAX_GLZ_WINDOW_SIZE_DEFAULT MIN((LZ_MAX_WINDOW_SIZE * 4), 1024 * 1024 * 64)
+#define WEBDAV_MAGIC_SIZE 16
 
 struct _SpiceSessionPrivate {
     char              *host;
@@ -109,7 +110,7 @@ struct _SpiceSessionPrivate {
     int               glz_window_size;
     uint32_t          pci_ram_size;
     uint32_t          display_channels_count;
-    guint8            uuid[16];
+    guint8            uuid[WEBDAV_MAGIC_SIZE];
     gchar             *name;
 
     /* associated objects */
@@ -173,6 +174,13 @@ void spice_session_sync_playback_latency(SpiceSession *session);
 const gchar* spice_session_get_shared_dir(SpiceSession *session);
 void spice_session_set_shared_dir(SpiceSession *session, const gchar *dir);
 gboolean spice_session_get_audio_enabled(SpiceSession *session);
+gboolean spice_session_get_smartcard_enabled(SpiceSession *session);
+gboolean spice_session_get_usbredir_enabled(SpiceSession *session);
+
+const guint8* spice_session_get_webdav_magic(SpiceSession *session);
+guint spice_session_get_display_channels_count(SpiceSession *session);
+void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel);
+gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session);
 
 G_END_DECLS
 
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 8b9655d..a2e79bb 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2199,6 +2199,14 @@ void spice_session_set_caches_hints(SpiceSession *session,
 }
 
 G_GNUC_INTERNAL
+guint spice_session_get_display_channels_count(SpiceSession *session)
+{
+    g_return_val_if_fail(session != NULL, 0);
+
+    return session->priv->display_channels_count;
+}
+
+G_GNUC_INTERNAL
 void spice_session_set_uuid(SpiceSession *session, guint8 uuid[16])
 {
     g_return_if_fail(SPICE_IS_SESSION(session));
@@ -2347,6 +2355,30 @@ gboolean spice_session_get_audio_enabled(SpiceSession *session)
     return session->priv->audio;
 }
 
+G_GNUC_INTERNAL
+gboolean spice_session_get_usbredir_enabled(SpiceSession *session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
+
+    return session->priv->usbredir;
+}
+
+G_GNUC_INTERNAL
+gboolean spice_session_get_smartcard_enabled(SpiceSession *session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
+
+    return session->priv->smartcard;
+}
+
+G_GNUC_INTERNAL
+const guint8* spice_session_get_webdav_magic(SpiceSession *session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
+    return session->priv->webdav_magic;
+}
+
 /**
  * spice_session_is_for_migration:
  * @session: a Spice session
@@ -2365,3 +2397,25 @@ gboolean spice_session_is_for_migration(SpiceSession *session)
 
     return session->priv->for_migration;
 }
+
+G_GNUC_INTERNAL
+void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel)
+{
+    g_return_if_fail(SPICE_IS_SESSION(session));
+    g_return_if_fail(SPICE_IS_CHANNEL(channel));
+    g_return_if_fail(session->priv->cmain == NULL);
+
+    session->priv->cmain = channel;
+}
+
+G_GNUC_INTERNAL
+gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
+    g_return_val_if_fail(SPICE_IS_SESSION(mig_session), FALSE);
+    g_return_val_if_fail(session->priv->migration == NULL, FALSE);
+
+    session->priv->migration = mig_session;
+
+    return TRUE;
+}
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index dbd3d1a..f80b657 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -1627,7 +1627,7 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager  *self,
     g_return_val_if_fail(device != NULL, FALSE);
     g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
-    if (!priv->session->priv->usbredir) {
+    if (!spice_session_get_usbredir_enabled(priv->session)) {
         g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
                             _("USB redirection is disabled"));
         return FALSE;
commit 74c3d288639a12838709ed2cd4881d386c3bc55b
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 18:19:50 2014 +0100

    session: set session for migration when connecting

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 490d21c..bf7c204 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -2073,7 +2073,6 @@ static gboolean migrate_connect(gpointer data)
     g_return_val_if_fail(c != NULL, FALSE);
     g_return_val_if_fail(mig->session != NULL, FALSE);
 
-    mig->session->priv->for_migration = true;
     spice_session_set_migration_state(mig->session, SPICE_SESSION_MIGRATION_CONNECTING);
 
     if ((c->peer_hdr.major_version == 1) &&
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index d1e1599..8b9655d 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2092,6 +2092,9 @@ void spice_session_set_migration_state(SpiceSession *session, SpiceSessionMigrat
 
     SpiceSessionPrivate *s = session->priv;
 
+    if (state == SPICE_SESSION_MIGRATION_CONNECTING)
+        s->for_migration = true;
+
     s->migration_state = state;
     g_coroutine_object_notify(G_OBJECT(session), "migration-state");
 }
commit 48373b267f750de0ef93cf569206b38597972e43
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 13:33:19 2014 +0100

    session: rename migration_copy/for_migration

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 6d06ee3..490d21c 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -2073,7 +2073,7 @@ static gboolean migrate_connect(gpointer data)
     g_return_val_if_fail(c != NULL, FALSE);
     g_return_val_if_fail(mig->session != NULL, FALSE);
 
-    mig->session->priv->migration_copy = true;
+    mig->session->priv->for_migration = true;
     spice_session_set_migration_state(mig->session, SPICE_SESSION_MIGRATION_CONNECTING);
 
     if ((c->peer_hdr.major_version == 1) &&
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 55e2ed2..6d8be8d 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -100,7 +100,7 @@ struct _SpiceSessionPrivate {
     gboolean          disconnecting;
     gboolean          migrate_wait_init;
     guint             after_main_init;
-    gboolean          migration_copy;
+    gboolean          for_migration;
 
     display_cache     *images;
     display_cache     *palettes;
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 9a043b6..d1e1599 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2360,5 +2360,5 @@ gboolean spice_session_is_for_migration(SpiceSession *session)
 {
     g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
 
-    return session->priv->migration_copy;
+    return session->priv->for_migration;
 }
commit b6f25f9c667de83803ebb3ccb22b3f17c98dd6be
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 11:43:02 2014 +0100

    smartcard: use spice_session_is_for_migration()

diff --git a/gtk/channel-smartcard.c b/gtk/channel-smartcard.c
index 243a8ce..8588ae0 100644
--- a/gtk/channel-smartcard.c
+++ b/gtk/channel-smartcard.c
@@ -136,7 +136,7 @@ static void spice_smartcard_channel_constructed(GObject *object)
     g_return_if_fail(s != NULL);
 
 #ifdef USE_SMARTCARD
-    if (!s->priv->migration_copy) {
+    if (!spice_session_is_for_migration(s)) {
         SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(object);
         SpiceSmartcardManager *manager = spice_smartcard_manager_get();
 
@@ -467,7 +467,7 @@ static void spice_smartcard_channel_up_cb(GObject *source_object,
 
 static void spice_smartcard_channel_up(SpiceChannel *channel)
 {
-    if (spice_channel_get_session(SPICE_CHANNEL(channel))->priv->migration_copy)
+    if (spice_session_is_for_migration(spice_channel_get_session(channel)))
         return;
 
     spice_smartcard_manager_init_async(spice_channel_get_session(channel),
commit 2a72a2c665d4d6ecd9861377f7dfb6223cf31c47
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 13:52:08 2014 +0100

    smartcard: do not initialize manager for migration session
    
    The migration session is temporary and shouldn't interact with system.

diff --git a/gtk/channel-smartcard.c b/gtk/channel-smartcard.c
index d27360c..243a8ce 100644
--- a/gtk/channel-smartcard.c
+++ b/gtk/channel-smartcard.c
@@ -452,23 +452,24 @@ static void spice_smartcard_channel_up_cb(GObject *source_object,
                                           gpointer user_data)
 {
     SpiceChannel *channel = SPICE_CHANNEL(user_data);
+    GError *error = NULL;
 
     g_return_if_fail(channel != NULL);
     g_return_if_fail(SPICE_IS_SESSION(source_object));
 
-    if (!spice_channel_get_session(SPICE_CHANNEL(channel))->priv->migration_copy) {
-        GError *error = NULL;
+    spice_smartcard_manager_init_finish(SPICE_SESSION(source_object),
+                                        res, &error);
+    if (error)
+        g_warning("%s", error->message);
 
-        spice_smartcard_manager_init_finish(SPICE_SESSION(source_object),
-                                            res, &error);
-        if (error)
-            g_warning("%s", error->message);
-        g_clear_error(&error);
-    }
+    g_clear_error(&error);
 }
 
 static void spice_smartcard_channel_up(SpiceChannel *channel)
 {
+    if (spice_channel_get_session(SPICE_CHANNEL(channel))->priv->migration_copy)
+        return;
+
     spice_smartcard_manager_init_async(spice_channel_get_session(channel),
                                        g_cancellable_new(),
                                        spice_smartcard_channel_up_cb,
commit 5811432f49fde1ae22e21d94cce638116e0b4c5d
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 11:37:34 2014 +0100

    Add spice_session_is_for_migration()

diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt
index caaa92c..141a32e 100644
--- a/doc/reference/spice-gtk-sections.txt
+++ b/doc/reference/spice-gtk-sections.txt
@@ -29,6 +29,7 @@ spice_session_get_channels
 spice_session_get_read_only
 spice_session_has_channel_type
 spice_session_get_proxy_uri
+spice_session_is_for_migration
 <SUBSECTION>
 SpiceSessionMigration
 SpiceSessionVerify
diff --git a/gtk/map-file b/gtk/map-file
index 3e9624f..d5a073f 100644
--- a/gtk/map-file
+++ b/gtk/map-file
@@ -86,6 +86,7 @@ spice_session_get_proxy_uri;
 spice_session_get_read_only;
 spice_session_get_type;
 spice_session_has_channel_type;
+spice_session_is_for_migration;
 spice_session_migration_get_type;
 spice_session_new;
 spice_session_open_fd;
diff --git a/gtk/spice-glib-sym-file b/gtk/spice-glib-sym-file
index 6ea8aeb..3a8da93 100644
--- a/gtk/spice-glib-sym-file
+++ b/gtk/spice-glib-sym-file
@@ -63,6 +63,7 @@ spice_session_get_proxy_uri
 spice_session_get_read_only
 spice_session_get_type
 spice_session_has_channel_type
+spice_session_is_for_migration
 spice_session_migration_get_type
 spice_session_new
 spice_session_open_fd
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 911bde2..9a043b6 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2343,3 +2343,22 @@ gboolean spice_session_get_audio_enabled(SpiceSession *session)
 
     return session->priv->audio;
 }
+
+/**
+ * spice_session_is_for_migration:
+ * @session: a Spice session
+ *
+ * During seamless migration, channels may be created to establish a
+ * connection with the target, but they are temporary and should only
+ * handle migration steps. In order to avoid other interactions with
+ * the client, channels should check this value.
+ *
+ * Returns: %TRUE if the session is a copy created during migration
+ * Since: 0.27
+ **/
+gboolean spice_session_is_for_migration(SpiceSession *session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
+
+    return session->priv->migration_copy;
+}
diff --git a/gtk/spice-session.h b/gtk/spice-session.h
index 4043a64..a79894f 100644
--- a/gtk/spice-session.h
+++ b/gtk/spice-session.h
@@ -96,6 +96,7 @@ GList *spice_session_get_channels(SpiceSession *session);
 gboolean spice_session_has_channel_type(SpiceSession *session, gint type);
 gboolean spice_session_get_read_only(SpiceSession *session);
 SpiceURI *spice_session_get_proxy_uri(SpiceSession *session);
+gboolean spice_session_is_for_migration(SpiceSession *session);
 
 G_END_DECLS
 
commit 2fad13d010c395b23d865c03f8045cd654c35dad
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Nov 25 11:33:55 2014 +0100

    session: protect internal functions against invalid args
    
    Make sure calling an internal session function returns with an error
    when called with a NULL pointer. This will help channel code when
    it is removed from session before being destructed.

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 948c238..911bde2 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1226,6 +1226,8 @@ SpiceSession *spice_session_new(void)
 G_GNUC_INTERNAL
 SpiceSession *spice_session_new_from_session(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
     SpiceSession *copy;
     SpiceSessionPrivate *c;
@@ -1294,7 +1296,6 @@ gboolean spice_session_connect(SpiceSession *session)
     SpiceSessionPrivate *s;
 
     g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
-    g_return_val_if_fail(session->priv != NULL, FALSE);
 
     s = session->priv;
 
@@ -1329,7 +1330,6 @@ gboolean spice_session_open_fd(SpiceSession *session, int fd)
     SpiceSessionPrivate *s;
 
     g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
-    g_return_val_if_fail(session->priv != NULL, FALSE);
     g_return_val_if_fail(fd >= -1, FALSE);
 
     s = session->priv;
@@ -1349,9 +1349,10 @@ gboolean spice_session_open_fd(SpiceSession *session, int fd)
 G_GNUC_INTERNAL
 gboolean spice_session_get_client_provided_socket(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, FALSE);
     return s->client_provided_sockets;
 }
 
@@ -1366,11 +1367,12 @@ static void cache_clear_all(SpiceSession *self)
 G_GNUC_INTERNAL
 void spice_session_switching_disconnect(SpiceSession *self)
 {
+    g_return_if_fail(SPICE_IS_SESSION(self));
+
     SpiceSessionPrivate *s = self->priv;
     struct channel *item;
     RingItem *ring, *next;
 
-    g_return_if_fail(s != NULL);
     g_return_if_fail(s->cmain != NULL);
 
     /* disconnect/destroy all but main channel */
@@ -1391,6 +1393,8 @@ G_GNUC_INTERNAL
 void spice_session_start_migrating(SpiceSession *session,
                                    gboolean full_migration)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
     SpiceSessionPrivate *m;
     gchar *tmp;
@@ -1426,12 +1430,12 @@ void spice_session_start_migrating(SpiceSession *session,
 G_GNUC_INTERNAL
 SpiceChannel* spice_session_lookup_channel(SpiceSession *session, gint id, gint type)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     RingItem *ring, *next;
     SpiceSessionPrivate *s = session->priv;
     struct channel *c;
 
-    g_return_val_if_fail(s != NULL, NULL);
-
     for (ring = ring_get_head(&s->channels);
          ring != NULL; ring = next) {
         next = ring_next(&s->channels, ring);
@@ -1453,12 +1457,12 @@ SpiceChannel* spice_session_lookup_channel(SpiceSession *session, gint id, gint
 G_GNUC_INTERNAL
 void spice_session_abort_migration(SpiceSession *session)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
     RingItem *ring, *next;
     struct channel *c;
 
-    g_return_if_fail(s != NULL);
-
     if (s->migration == NULL) {
         SPICE_DEBUG("no migration in progress");
         return;
@@ -1502,11 +1506,12 @@ end:
 G_GNUC_INTERNAL
 void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
     SpiceChannel *c;
     gint id, type;
 
-    g_return_if_fail(s != NULL);
     g_return_if_fail(s->migration != NULL);
     g_return_if_fail(SPICE_IS_CHANNEL(channel));
 
@@ -1556,6 +1561,8 @@ static gboolean after_main_init(gpointer data)
 G_GNUC_INTERNAL
 gboolean spice_session_migrate_after_main_init(SpiceSession *self)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(self), FALSE);
+
     SpiceSessionPrivate *s = self->priv;
 
     if (!s->migrate_wait_init)
@@ -1574,6 +1581,8 @@ gboolean spice_session_migrate_after_main_init(SpiceSession *self)
 G_GNUC_INTERNAL
 void spice_session_migrate_end(SpiceSession *self)
 {
+    g_return_if_fail(SPICE_IS_SESSION(self));
+
     SpiceSessionPrivate *s = self->priv;
     SpiceMsgOut *out;
     GList *l;
@@ -1853,6 +1862,8 @@ G_GNUC_INTERNAL
 GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel,
                                                    gboolean *use_tls, GError **error)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
     SpiceChannelPrivate *c = channel->priv;
     spice_open_host open_host = { 0, };
@@ -1905,11 +1916,12 @@ GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceC
 G_GNUC_INTERNAL
 void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+    g_return_if_fail(SPICE_IS_CHANNEL(channel));
+
     SpiceSessionPrivate *s = session->priv;
     struct channel *item;
 
-    g_return_if_fail(s != NULL);
-    g_return_if_fail(channel != NULL);
 
     item = g_new0(struct channel, 1);
     item->channel = channel;
@@ -1939,13 +1951,13 @@ void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel)
 G_GNUC_INTERNAL
 void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+    g_return_if_fail(SPICE_IS_CHANNEL(channel));
+
     SpiceSessionPrivate *s = session->priv;
     struct channel *item = NULL;
     RingItem *ring;
 
-    g_return_if_fail(s != NULL);
-    g_return_if_fail(channel != NULL);
-
     if (s->migration_left)
         s->migration_left = g_list_remove(s->migration_left, channel);
 
@@ -1972,9 +1984,9 @@ void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel)
 G_GNUC_INTERNAL
 void spice_session_set_connection_id(SpiceSession *session, int id)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_if_fail(SPICE_IS_SESSION(session));
 
-    g_return_if_fail(s != NULL);
+    SpiceSessionPrivate *s = session->priv;
 
     s->connection_id = id;
 }
@@ -1982,9 +1994,9 @@ void spice_session_set_connection_id(SpiceSession *session, int id)
 G_GNUC_INTERNAL
 int spice_session_get_connection_id(SpiceSession *session)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_val_if_fail(SPICE_IS_SESSION(session), -1);
 
-    g_return_val_if_fail(s != NULL, -1);
+    SpiceSessionPrivate *s = session->priv;
 
     return s->connection_id;
 }
@@ -1992,9 +2004,9 @@ int spice_session_get_connection_id(SpiceSession *session)
 G_GNUC_INTERNAL
 guint32 spice_session_get_mm_time(SpiceSession *session)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_val_if_fail(SPICE_IS_SESSION(session), 0);
 
-    g_return_val_if_fail(s != NULL, 0);
+    SpiceSessionPrivate *s = session->priv;
 
     /* FIXME: we may want to estimate the drift of clocks, and well,
        do something better than this trivial approach */
@@ -2006,11 +2018,11 @@ guint32 spice_session_get_mm_time(SpiceSession *session)
 G_GNUC_INTERNAL
 void spice_session_set_mm_time(SpiceSession *session, guint32 time)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
     guint32 old_time;
 
-    g_return_if_fail(s != NULL);
-
     old_time = spice_session_get_mm_time(session);
 
     s->mm_time = time;
@@ -2029,7 +2041,7 @@ void spice_session_set_port(SpiceSession *session, int port, gboolean tls)
     const char *prop = tls ? "tls-port" : "port";
     char *tmp;
 
-    g_return_if_fail(session != NULL);
+    g_return_if_fail(SPICE_IS_SESSION(session));
 
     /* old spicec client doesn't accept port == 0, see Migrate::start */
     tmp = port > 0 ? g_strdup_printf("%d", port) : NULL;
@@ -2040,12 +2052,12 @@ void spice_session_set_port(SpiceSession *session, int port, gboolean tls)
 G_GNUC_INTERNAL
 void spice_session_get_pubkey(SpiceSession *session, guint8 **pubkey, guint *size)
 {
-    SpiceSessionPrivate *s = session->priv;
-
-    g_return_if_fail(s != NULL);
+    g_return_if_fail(SPICE_IS_SESSION(session));
     g_return_if_fail(pubkey != NULL);
     g_return_if_fail(size != NULL);
 
+    SpiceSessionPrivate *s = session->priv;
+
     *pubkey = s->pubkey ? s->pubkey->data : NULL;
     *size = s->pubkey ? s->pubkey->len : 0;
 }
@@ -2053,12 +2065,12 @@ void spice_session_get_pubkey(SpiceSession *session, guint8 **pubkey, guint *siz
 G_GNUC_INTERNAL
 void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size)
 {
-    SpiceSessionPrivate *s = session->priv;
-
-    g_return_if_fail(s != NULL);
+    g_return_if_fail(SPICE_IS_SESSION(session));
     g_return_if_fail(ca != NULL);
     g_return_if_fail(size != NULL);
 
+    SpiceSessionPrivate *s = session->priv;
+
     *ca = s->ca ? s->ca->data : NULL;
     *size = s->ca ? s->ca->len : 0;
 }
@@ -2066,18 +2078,20 @@ void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size)
 G_GNUC_INTERNAL
 guint spice_session_get_verify(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), 0);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, 0);
     return s->verify;
 }
 
 G_GNUC_INTERNAL
 void spice_session_set_migration_state(SpiceSession *session, SpiceSessionMigration state)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_if_fail(s != NULL);
     s->migration_state = state;
     g_coroutine_object_notify(G_OBJECT(session), "migration-state");
 }
@@ -2085,54 +2099,60 @@ void spice_session_set_migration_state(SpiceSession *session, SpiceSessionMigrat
 G_GNUC_INTERNAL
 const gchar* spice_session_get_username(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, NULL);
     return s->username;
 }
 
 G_GNUC_INTERNAL
 const gchar* spice_session_get_password(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, NULL);
     return s->password;
 }
 
 G_GNUC_INTERNAL
 const gchar* spice_session_get_host(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, NULL);
     return s->host;
 }
 
 G_GNUC_INTERNAL
 const gchar* spice_session_get_cert_subject(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, NULL);
     return s->cert_subject;
 }
 
 G_GNUC_INTERNAL
 const gchar* spice_session_get_ciphers(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, NULL);
     return s->ciphers;
 }
 
 G_GNUC_INTERNAL
 const gchar* spice_session_get_ca_file(SpiceSession *session)
 {
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_val_if_fail(s != NULL, NULL);
     return s->ca_file;
 }
 
@@ -2141,9 +2161,9 @@ void spice_session_get_caches(SpiceSession *session,
                               display_cache **images,
                               SpiceGlzDecoderWindow **glz_window)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_if_fail(SPICE_IS_SESSION(session));
 
-    g_return_if_fail(s != NULL);
+    SpiceSessionPrivate *s = session->priv;
 
     if (images)
         *images = s->images;
@@ -2156,9 +2176,9 @@ void spice_session_set_caches_hints(SpiceSession *session,
                                     uint32_t pci_ram_size,
                                     uint32_t display_channels_count)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_if_fail(SPICE_IS_SESSION(session));
 
-    g_return_if_fail(s != NULL);
+    SpiceSessionPrivate *s = session->priv;
 
     s->pci_ram_size = pci_ram_size;
     s->display_channels_count = display_channels_count;
@@ -2178,9 +2198,10 @@ void spice_session_set_caches_hints(SpiceSession *session,
 G_GNUC_INTERNAL
 void spice_session_set_uuid(SpiceSession *session, guint8 uuid[16])
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_if_fail(s != NULL);
     memcpy(s->uuid, uuid, sizeof(s->uuid));
 
     g_coroutine_object_notify(G_OBJECT(session), "uuid");
@@ -2189,9 +2210,10 @@ void spice_session_set_uuid(SpiceSession *session, guint8 uuid[16])
 G_GNUC_INTERNAL
 void spice_session_set_name(SpiceSession *session, const gchar *name)
 {
+    g_return_if_fail(SPICE_IS_SESSION(session));
+
     SpiceSessionPrivate *s = session->priv;
 
-    g_return_if_fail(s != NULL);
     g_free(s->name);
     s->name = g_strdup(name);
 
@@ -2201,9 +2223,9 @@ void spice_session_set_name(SpiceSession *session, const gchar *name)
 G_GNUC_INTERNAL
 void spice_session_sync_playback_latency(SpiceSession *session)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_if_fail(SPICE_IS_SESSION(session));
 
-    g_return_if_fail(s != NULL);
+    SpiceSessionPrivate *s = session->priv;
 
     if (s->playback_channel &&
         spice_playback_channel_is_active(s->playback_channel)) {
@@ -2216,9 +2238,9 @@ void spice_session_sync_playback_latency(SpiceSession *session)
 G_GNUC_INTERNAL
 gboolean spice_session_is_playback_active(SpiceSession *session)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
 
-    g_return_val_if_fail(s != NULL, FALSE);
+    SpiceSessionPrivate *s = session->priv;
 
     return (s->playback_channel &&
         spice_playback_channel_is_active(s->playback_channel));
@@ -2227,9 +2249,9 @@ gboolean spice_session_is_playback_active(SpiceSession *session)
 G_GNUC_INTERNAL
 guint32 spice_session_get_playback_latency(SpiceSession *session)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_val_if_fail(SPICE_IS_SESSION(session), 0);
 
-    g_return_val_if_fail(s != NULL, 0);
+    SpiceSessionPrivate *s = session->priv;
 
     if (s->playback_channel &&
         spice_playback_channel_is_active(s->playback_channel)) {
@@ -2243,9 +2265,9 @@ guint32 spice_session_get_playback_latency(SpiceSession *session)
 G_GNUC_INTERNAL
 const gchar* spice_session_get_shared_dir(SpiceSession *session)
 {
-    SpiceSessionPrivate *s = session->priv;
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
 
-    g_return_val_if_fail(s != NULL, NULL);
+    SpiceSessionPrivate *s = session->priv;
 
     return s->shared_dir;
 }
@@ -2253,10 +2275,10 @@ const gchar* spice_session_get_shared_dir(SpiceSession *session)
 G_GNUC_INTERNAL
 void spice_session_set_shared_dir(SpiceSession *session, const gchar *dir)
 {
-    SpiceSessionPrivate *s = session->priv;
-
+    g_return_if_fail(SPICE_IS_SESSION(session));
     g_return_if_fail(dir != NULL);
-    g_return_if_fail(s != NULL);
+
+    SpiceSessionPrivate *s = session->priv;
 
     g_free(s->shared_dir);
     s->shared_dir = g_strdup(dir);
commit acf99be38c84e0eec4d87cfb1b207087f43a9460
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 13:26:38 2014 +0100

    audio: move spice_audio_get() to session

diff --git a/gtk/spice-audio.c b/gtk/spice-audio.c
index ce303f1..7754736 100644
--- a/gtk/spice-audio.c
+++ b/gtk/spice-audio.c
@@ -230,34 +230,3 @@ SpiceAudio *spice_audio_new(SpiceSession *session, GMainContext *context,
 
     return self;
 }
-
-/**
- * spice_audio_get:
- * @session: the #SpiceSession to connect to
- * @context: (allow-none): a #GMainContext to attach to (or %NULL for default).
- *
- * Gets the #SpiceAudio associated with the passed in #SpiceSession.
- * A new #SpiceAudio instance will be created the first time this
- * function is called for a certain #SpiceSession.
- *
- * Note that this function returns a weak reference, which should not be used
- * after the #SpiceSession itself has been unref-ed by the caller.
- *
- * Returns: (transfer none): a weak reference to a #SpiceAudio
- * instance or %NULL if failed.
- **/
-SpiceAudio *spice_audio_get(SpiceSession *session, GMainContext *context)
-{
-    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-    SpiceAudio *self;
-
-    g_static_mutex_lock(&mutex);
-    self = session->priv->audio_manager;
-    if (self == NULL) {
-        self = spice_audio_new(session, context, NULL);
-        session->priv->audio_manager = self;
-    }
-    g_static_mutex_unlock(&mutex);
-
-    return self;
-}
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index f729ae0..948c238 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -32,6 +32,7 @@
 #include "wocky-http-proxy.h"
 #include "spice-uri-priv.h"
 #include "channel-playback-priv.h"
+#include "spice-audio.h"
 
 struct channel {
     SpiceChannel      *channel;
@@ -2280,6 +2281,39 @@ SpiceURI *spice_session_get_proxy_uri(SpiceSession *session)
     return s->proxy;
 }
 
+/**
+ * spice_audio_get:
+ * @session: the #SpiceSession to connect to
+ * @context: (allow-none): a #GMainContext to attach to (or %NULL for default).
+ *
+ * Gets the #SpiceAudio associated with the passed in #SpiceSession.
+ * A new #SpiceAudio instance will be created the first time this
+ * function is called for a certain #SpiceSession.
+ *
+ * Note that this function returns a weak reference, which should not be used
+ * after the #SpiceSession itself has been unref-ed by the caller.
+ *
+ * Returns: (transfer none): a weak reference to a #SpiceAudio
+ * instance or %NULL if failed.
+ **/
+SpiceAudio *spice_audio_get(SpiceSession *session, GMainContext *context)
+{
+    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+    SpiceAudio *self;
+
+    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+
+    g_static_mutex_lock(&mutex);
+    self = session->priv->audio_manager;
+    if (self == NULL) {
+        self = spice_audio_new(session, context, NULL);
+        session->priv->audio_manager = self;
+    }
+    g_static_mutex_unlock(&mutex);
+
+    return self;
+}
+
 G_GNUC_INTERNAL
 gboolean spice_session_get_audio_enabled(SpiceSession *session)
 {
commit d29a23a82979bef25e8104b13f925fecc0961ee4
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Nov 26 13:25:51 2014 +0100

    audio: add accessor to check if audio is enabled

diff --git a/gtk/spice-audio.c b/gtk/spice-audio.c
index 638f667..ce303f1 100644
--- a/gtk/spice-audio.c
+++ b/gtk/spice-audio.c
@@ -166,17 +166,18 @@ static void connect_channel(SpiceAudio *self, SpiceChannel *channel)
 
 static void update_audio_channels(SpiceAudio *self, SpiceSession *session)
 {
-    if (session->priv->audio) {
-        GList *list, *tmp;
-
-        list = spice_session_get_channels(session);
-        for (tmp = g_list_first(list); tmp != NULL; tmp = g_list_next(tmp)) {
-            connect_channel(self, tmp->data);
-        }
-        g_list_free(list);
-    } else {
+    GList *list, *tmp;
+
+    if (!spice_session_get_audio_enabled(session)) {
         g_debug("FIXME: disconnect audio channels");
+        return;
+    }
+
+    list = spice_session_get_channels(session);
+    for (tmp = g_list_first(list); tmp != NULL; tmp = g_list_next(tmp)) {
+        connect_channel(self, tmp->data);
     }
+    g_list_free(list);
 }
 
 static void channel_new(SpiceSession *session, SpiceChannel *channel, SpiceAudio *self)
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 8e102e0..55e2ed2 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -172,6 +172,7 @@ guint32 spice_session_get_playback_latency(SpiceSession *session);
 void spice_session_sync_playback_latency(SpiceSession *session);
 const gchar* spice_session_get_shared_dir(SpiceSession *session);
 void spice_session_set_shared_dir(SpiceSession *session, const gchar *dir);
+gboolean spice_session_get_audio_enabled(SpiceSession *session);
 
 G_END_DECLS
 
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index c44a3e1..f729ae0 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2279,3 +2279,11 @@ SpiceURI *spice_session_get_proxy_uri(SpiceSession *session)
 
     return s->proxy;
 }
+
+G_GNUC_INTERNAL
+gboolean spice_session_get_audio_enabled(SpiceSession *session)
+{
+    g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
+
+    return session->priv->audio;
+}


More information about the Spice-commits mailing list