[Spice-commits] 10 commits - gtk/spice-channel-priv.h gtk/spice-channel.c gtk/spice-session.c gtk/spicy.c

Marc-André Lureau elmarco at kemper.freedesktop.org
Tue Jan 27 08:27:01 PST 2015


 gtk/spice-channel-priv.h |    3 -
 gtk/spice-channel.c      |   54 ++++++++++--------
 gtk/spice-session.c      |  136 +++++++++++++++++++++++++++++++++++------------
 gtk/spicy.c              |   16 +++--
 4 files changed, 147 insertions(+), 62 deletions(-)

New commits:
commit a86867b5b5b67ce662fecd33d03c7c26a90d4a7e
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 15:24:13 2015 +0100

    spicy: deal with spice+unix:// URI

diff --git a/gtk/spicy.c b/gtk/spicy.c
index 2fcd529..4bc6ddb 100644
--- a/gtk/spicy.c
+++ b/gtk/spicy.c
@@ -1193,10 +1193,14 @@ static void recent_add(SpiceSession *session)
     g_object_get(session, "uri", &uri, NULL);
     SPICE_DEBUG("%s: %s", __FUNCTION__, uri);
 
-    g_return_if_fail(g_str_has_prefix(uri, "spice://"));
-
     recent = gtk_recent_manager_get_default();
-    meta.display_name = uri + 8;
+    if (g_str_has_prefix(uri, "spice://"))
+        meta.display_name = uri + 8;
+    else if (g_str_has_prefix(uri, "spice+unix://"))
+        meta.display_name = uri + 13;
+    else
+        g_return_if_reached();
+
     if (!gtk_recent_manager_add_full(recent, uri, &meta))
         g_warning("Recent item couldn't be added successfully");
 
@@ -1788,7 +1792,7 @@ int main(int argc, char *argv[])
     GOptionContext *context;
     spice_connection *conn;
     gchar *conf_file, *conf;
-    char *host = NULL, *port = NULL, *tls_port = NULL;
+    char *host = NULL, *port = NULL, *tls_port = NULL, *unix_path = NULL;
 
 #if !GLIB_CHECK_VERSION(2,31,18)
     g_thread_init(NULL);
@@ -1853,13 +1857,14 @@ int main(int argc, char *argv[])
     spice_cmdline_session_setup(conn->session);
 
     g_object_get(conn->session,
+                 "unix-path", &unix_path,
                  "host", &host,
                  "port", &port,
                  "tls-port", &tls_port,
                  NULL);
     /* If user doesn't provide hostname and port, show the dialog window
        instead of connecting to server automatically */
-    if (host == NULL || (port == NULL && tls_port == NULL)) {
+    if ((host == NULL || (port == NULL && tls_port == NULL)) && unix_path == NULL) {
         int ret = connect_dialog(conn->session);
         if (ret != 0) {
             exit(0);
@@ -1868,6 +1873,7 @@ int main(int argc, char *argv[])
     g_free(host);
     g_free(port);
     g_free(tls_port);
+    g_free(unix_path);
 
     watch_stdin();
 
commit 183fa11f7c83e561fff8741d8c1d9ef5c20b9dcd
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 15:25:52 2015 +0100

    session: teach spice_uri_create() about UNIX path

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 6eac9f8..50ad291 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -357,7 +357,9 @@ static gchar* spice_uri_create(SpiceSession *session)
 {
     SpiceSessionPrivate *s = session->priv;
 
-    if (s->host != NULL) {
+    if (s->unix_path != NULL) {
+        return g_strdup_printf(URI_SCHEME_SPICE_UNIX "%s", s->unix_path);
+    } else if (s->host != NULL) {
         g_return_val_if_fail(s->port != NULL || s->tls_port != NULL, NULL);
 
         GString *str = g_string_new(URI_SCHEME_SPICE);
commit 5693ba53356d371a0da575a2caa1bc1c83906117
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 27 14:29:35 2015 +0100

    session: prettify query parameters
    
    Use & as parameters separators, this is more usual. Remove
    trailing one, no further parameters are useful anyway.

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 45ae6b8..6eac9f8 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -365,10 +365,10 @@ static gchar* spice_uri_create(SpiceSession *session)
         g_string_append(str, s->host);
         g_string_append(str, "?");
         if (s->port != NULL) {
-            g_string_append_printf(str, "port=%s;", s->port);
+            g_string_append_printf(str, "port=%s&", s->port);
         }
         if (s->tls_port != NULL) {
-            g_string_append_printf(str, "tls-port=%s;", s->tls_port);
+            g_string_append_printf(str, "tls-port=%s", s->tls_port);
         }
         return g_string_free(str, FALSE);
     }
commit 69d1e63d38d3e4636c43da2f88fb7d7fbc5e1799
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 15:25:34 2015 +0100

    session: return allocated string from spice_uri_create()
    
    This allows more flexible string building.

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index f546ef2..45ae6b8 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -353,21 +353,27 @@ spice_session_finalize(GObject *gobject)
 #define URI_QUERY_START ";?"
 #define URI_QUERY_SEP   ";&"
 
-static int spice_uri_create(SpiceSession *session, char *dest, int len)
+static gchar* spice_uri_create(SpiceSession *session)
 {
     SpiceSessionPrivate *s = session->priv;
-    int pos = 0;
 
-    if (s->host == NULL || (s->port == NULL && s->tls_port == NULL)) {
-        return 0;
+    if (s->host != NULL) {
+        g_return_val_if_fail(s->port != NULL || s->tls_port != NULL, NULL);
+
+        GString *str = g_string_new(URI_SCHEME_SPICE);
+
+        g_string_append(str, s->host);
+        g_string_append(str, "?");
+        if (s->port != NULL) {
+            g_string_append_printf(str, "port=%s;", s->port);
+        }
+        if (s->tls_port != NULL) {
+            g_string_append_printf(str, "tls-port=%s;", s->tls_port);
+        }
+        return g_string_free(str, FALSE);
     }
 
-    pos += snprintf(dest + pos, len-pos, "spice://%s?", s->host);
-    if (s->port && strlen(s->port))
-        pos += snprintf(dest + pos, len - pos, "port=%s;", s->port);
-    if (s->tls_port && strlen(s->tls_port))
-        pos += snprintf(dest + pos, len - pos, "tls-port=%s;", s->tls_port);
-    return pos;
+    g_return_val_if_reached(NULL);
 }
 
 static int spice_parse_uri(SpiceSession *session, const char *original_uri)
@@ -532,8 +538,6 @@ static void spice_session_get_property(GObject    *gobject,
 {
     SpiceSession *session = SPICE_SESSION(gobject);
     SpiceSessionPrivate *s = session->priv;
-    char buf[256];
-    int len;
 
     switch (prop_id) {
     case PROP_HOST:
@@ -564,8 +568,7 @@ static void spice_session_get_property(GObject    *gobject,
         g_value_set_int(value, s->protocol);
 	break;
     case PROP_URI:
-        len = spice_uri_create(session, buf, sizeof(buf));
-        g_value_set_string(value, len ? buf : NULL);
+        g_value_take_string(value, spice_uri_create(session));
         break;
     case PROP_CLIENT_SOCKETS:
         g_value_set_boolean(value, s->client_provided_sockets);
commit 720f33d512f185610b0b0e94de67473a00beac05
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 15:23:43 2015 +0100

    session: parse spice+unix:// URI

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index f9e1fed..f546ef2 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -349,6 +349,7 @@ spice_session_finalize(GObject *gobject)
 }
 
 #define URI_SCHEME_SPICE "spice://"
+#define URI_SCHEME_SPICE_UNIX "spice+unix://"
 #define URI_QUERY_START ";?"
 #define URI_QUERY_SEP   ";&"
 
@@ -383,10 +384,15 @@ static int spice_parse_uri(SpiceSession *session, const char *original_uri)
 
     uri = g_strdup(original_uri);
 
+    if (g_str_has_prefix(uri, URI_SCHEME_SPICE_UNIX)) {
+        path = uri + strlen(URI_SCHEME_SPICE_UNIX);
+        goto end;
+    }
+
     /* Break up the URI into its various parts, scheme, authority,
      * path (ignored) and query
      */
-    if (strncmp(uri, URI_SCHEME_SPICE, strlen(URI_SCHEME_SPICE)) != 0) {
+    if (!g_str_has_prefix(uri, URI_SCHEME_SPICE)) {
         g_warning("Expected a URI scheme of '%s' in URI '%s'",
                   URI_SCHEME_SPICE, uri);
         goto fail;
@@ -449,6 +455,7 @@ static int spice_parse_uri(SpiceSession *session, const char *original_uri)
         /* don't fail, just ignore */
     }
     unescaped_path = g_uri_unescape_string(path, NULL);
+    path = NULL;
 
     while (query && query[0] != '\0') {
         gchar key[32], value[128];
@@ -489,14 +496,17 @@ static int spice_parse_uri(SpiceSession *session, const char *original_uri)
         goto fail;
     }
 
+end:
     /* parsed ok -> apply */
     g_free(uri);
     g_free(unescaped_path);
+    g_free(s->unix_path);
     g_free(s->host);
     g_free(s->port);
     g_free(s->tls_port);
     g_free(s->username);
     g_free(s->password);
+    s->unix_path = g_strdup(path);
     s->host = host;
     s->port = port;
     s->tls_port = tls_port;
commit 5ee3202923458751d1af722acc4d5a8438a3072c
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 15:26:22 2015 +0100

    session: connect to UNIX path

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 98708c8..f9e1fed 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -19,7 +19,9 @@
 
 #include <gio/gio.h>
 #include <glib.h>
-
+#ifdef G_OS_UNIX
+#include <gio/gunixsocketaddress.h>
+#endif
 #include "common/ring.h"
 
 #include "spice-client.h"
@@ -1980,21 +1982,36 @@ static gboolean open_host_idle_cb(gpointer data)
         return FALSE;
     }
 
-    if (open_host->proxy)
+    if (open_host->proxy) {
         g_resolver_lookup_by_name_async(g_resolver_get_default(),
                                         spice_uri_get_hostname(open_host->proxy),
                                         open_host->cancellable,
                                         proxy_lookup_ready, open_host);
-    else
-    {
-        GSocketConnectable *address;
+    } else {
+        GSocketConnectable *address = NULL;
+
+        if (s->unix_path) {
+            SPICE_DEBUG("open unix path %s", s->unix_path);
+#ifdef G_OS_UNIX
+            address = G_SOCKET_CONNECTABLE(g_unix_socket_address_new(s->unix_path));
+#else
+            g_set_error_literal(&open_host->error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                                "Unix path unsupported on this platform");
+#endif
+        } else {
+            SPICE_DEBUG("open host %s:%d", s->host, open_host->port);
+            address = g_network_address_new(s->host, open_host->port);
+        }
+
+        if (address == NULL || open_host->error != NULL) {
+            coroutine_yieldto(open_host->from, NULL);
+            return FALSE;
+        }
 
-        address = g_network_address_new(s->host, open_host->port);
         open_host_connectable_connect(open_host, address);
         g_object_unref(address);
     }
 
-    SPICE_DEBUG("open host %s:%d", s->host, open_host->port);
     if (open_host->proxy != NULL) {
         gchar *str = spice_uri_to_string(open_host->proxy);
         SPICE_DEBUG("(with proxy %s)", str);
@@ -2028,15 +2045,22 @@ GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceC
         spice_strv_contains(s->secure_channels, name))
         *use_tls = TRUE;
 
-    port = *use_tls ? s->tls_port : s->port;
-    if (port == NULL)
-        return NULL;
-
-    open_host.port = strtol(port, &endptr, 10);
-    if (*port == '\0' || *endptr != '\0' ||
-        open_host.port <= 0 || open_host.port > G_MAXUINT16) {
-        g_warning("Invalid port value %s", port);
-        return NULL;
+    if (s->unix_path) {
+        if (*use_tls) {
+            CHANNEL_DEBUG(channel, "No TLS for Unix sockets");
+            return NULL;
+        }
+    } else {
+        port = *use_tls ? s->tls_port : s->port;
+        if (port == NULL)
+            return NULL;
+
+        open_host.port = strtol(port, &endptr, 10);
+        if (*port == '\0' || *endptr != '\0' ||
+            open_host.port <= 0 || open_host.port > G_MAXUINT16) {
+            g_warning("Invalid port value %s", port);
+            return NULL;
+        }
     }
 
     open_host.client = g_socket_client_new();
commit c2e3110607cb63a0bd1fd09aa6ba0ec921dc5a23
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 15:21:26 2015 +0100

    session: add unix-path property

diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index d7f014c..98708c8 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -45,6 +45,7 @@ struct channel {
 
 struct _SpiceSessionPrivate {
     char              *host;
+    char              *unix_path;
     char              *port;
     char              *tls_port;
     char              *username;
@@ -197,7 +198,8 @@ enum {
     PROP_PROXY,
     PROP_SECURE_CHANNELS,
     PROP_SHARED_DIR,
-    PROP_USERNAME
+    PROP_USERNAME,
+    PROP_UNIX_PATH,
 };
 
 /* signals */
@@ -318,6 +320,7 @@ spice_session_finalize(GObject *gobject)
     SpiceSessionPrivate *s = session->priv;
 
     /* release stuff */
+    g_free(s->unix_path);
     g_free(s->host);
     g_free(s->port);
     g_free(s->tls_port);
@@ -524,6 +527,9 @@ static void spice_session_get_property(GObject    *gobject,
     case PROP_HOST:
         g_value_set_string(value, s->host);
 	break;
+    case PROP_UNIX_PATH:
+        g_value_set_string(value, s->unix_path);
+        break;
     case PROP_PORT:
         g_value_set_string(value, s->port);
 	break;
@@ -635,6 +641,10 @@ static void spice_session_set_property(GObject      *gobject,
         g_free(s->host);
         s->host = g_value_dup_string(value);
         break;
+    case PROP_UNIX_PATH:
+        g_free(s->unix_path);
+        s->unix_path = g_value_dup_string(value);
+        break;
     case PROP_PORT:
         g_free(s->port);
         s->port = g_value_dup_string(value);
@@ -779,6 +789,23 @@ static void spice_session_class_init(SpiceSessionClass *klass)
                              G_PARAM_STATIC_STRINGS));
 
     /**
+     * SpiceSession:unix-path:
+     *
+     * Path of the Unix socket to connect to
+     *
+     * Since: 0.28
+     **/
+    g_object_class_install_property
+        (gobject_class, PROP_UNIX_PATH,
+         g_param_spec_string("unix-path",
+                             "Unix path",
+                             "Unix path",
+                             NULL,
+                             G_PARAM_READWRITE |
+                             G_PARAM_CONSTRUCT |
+                             G_PARAM_STATIC_STRINGS));
+
+    /**
      * SpiceSession:port:
      *
      * Port to connect to for unencrypted sessions
@@ -1359,6 +1386,7 @@ SpiceSession *spice_session_new_from_session(SpiceSession *session)
     g_clear_object(&c->proxy);
 
     g_warn_if_fail(c->host == NULL);
+    g_warn_if_fail(c->unix_path == NULL);
     g_warn_if_fail(c->tls_port == NULL);
     g_warn_if_fail(c->username == NULL);
     g_warn_if_fail(c->password == NULL);
@@ -1371,6 +1399,7 @@ SpiceSession *spice_session_new_from_session(SpiceSession *session)
 
     g_object_get(session,
                  "host", &c->host,
+                 "unix-path", &c->unix_path,
                  "tls-port", &c->tls_port,
                  "username", &c->username,
                  "password", &c->password,
@@ -1544,6 +1573,10 @@ void spice_session_start_migrating(SpiceSession *session,
     s->tls_port = m->tls_port;
     m->tls_port = tmp;
 
+    tmp = s->unix_path;
+    s->unix_path = m->unix_path;
+    m->unix_path = tmp;
+
     g_warn_if_fail(ring_get_length(&s->channels) == ring_get_length(&m->channels));
 
     SPICE_DEBUG("migration channels left:%d (in migration:%d)",
commit 61f70b689044ea53f4103e79a128af640c003f48
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 16:33:52 2015 +0100

    channel: reset connection state on error
    
    Fix regression introduced in 6b475802, to permit reconnection on error,
    the channel state must be < STATE_CONNECTING. Since the error is
    reported after coroutine exits and channel is reset, the state can be
    modified before throwing the error now.

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 99065d3..eec63b1 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -2184,6 +2184,7 @@ static gboolean spice_channel_delayed_unref(gpointer data)
     g_return_val_if_fail(c->coroutine.coroutine.exited == TRUE, FALSE);
 
     if (c->event != SPICE_CHANNEL_NONE) {
+        c->state = SPICE_CHANNEL_STATE_UNCONNECTED;
         g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, c->event);
         c->event = SPICE_CHANNEL_NONE;
         g_clear_error(&c->error);
commit 26b7767d4831be91ccc3c922276b04118f8b3277
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 17:26:18 2015 +0100

    channel: reset tls state when client calls connect
    
    The channel TLS state is kept during disconnection and reset, for
    automatic reconnection and migrations reasons. However, when
    spice_channel_connect() is called by client, it should first try
    non-TLS connection.

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 204b250..99065d3 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -55,6 +55,7 @@ static void channel_disconnect(SpiceChannel *channel);
 static void channel_reset(SpiceChannel *channel, gboolean migrating);
 static void spice_channel_reset_capabilities(SpiceChannel *channel);
 static void spice_channel_send_migration_handshake(SpiceChannel *channel);
+static gboolean channel_connect(SpiceChannel *channel, gboolean tls);
 
 /**
  * SECTION:spice-channel
@@ -2433,7 +2434,7 @@ cleanup:
 
     if (c->state == SPICE_CHANNEL_STATE_RECONNECTING) {
         g_warn_if_fail(c->event == SPICE_CHANNEL_NONE);
-        spice_channel_connect(channel);
+        channel_connect(channel, c->tls);
         g_object_unref(channel);
     } else
         g_idle_add(spice_channel_delayed_unref, data);
@@ -2465,7 +2466,7 @@ static gboolean connect_delayed(gpointer data)
 }
 
 /* any context */
-static gboolean channel_connect(SpiceChannel *channel)
+static gboolean channel_connect(SpiceChannel *channel, gboolean tls)
 {
     SpiceChannelPrivate *c = channel->priv;
 
@@ -2478,6 +2479,7 @@ static gboolean channel_connect(SpiceChannel *channel)
     }
 
     c->state = SPICE_CHANNEL_STATE_CONNECTING;
+    c->tls = tls;
 
     if (spice_session_get_client_provided_socket(c->session)) {
         if (c->fd == -1) {
@@ -2519,7 +2521,7 @@ gboolean spice_channel_connect(SpiceChannel *channel)
 
     g_return_val_if_fail(channel->priv->fd == -1, FALSE);
 
-    return channel_connect(channel);
+    return channel_connect(channel, FALSE);
 }
 
 /**
@@ -2552,7 +2554,7 @@ gboolean spice_channel_open_fd(SpiceChannel *channel, int fd)
 
     c->fd = fd;
 
-    return channel_connect(channel);
+    return channel_connect(channel, FALSE);
 }
 
 /* system or coroutine context */
@@ -2651,7 +2653,7 @@ static void channel_disconnect(SpiceChannel *channel)
     g_return_if_fail(SPICE_IS_CHANNEL(channel));
 
     if (c->state == SPICE_CHANNEL_STATE_SWITCHING) {
-        spice_channel_connect(channel);
+        channel_connect(channel, c->tls);
         spice_session_set_migration_state(spice_channel_get_session(channel),
                                           SPICE_SESSION_MIGRATION_NONE);
     }
commit 940c5f59f97861a33010c1fde5d8bce38d9f6c68
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jan 13 14:51:31 2015 +0100

    channel: delay event report to after coroutine exit
    
    Move to a common place error reporting, after the coroutine exits.

diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index bd7f490..d70cf86 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -66,7 +66,6 @@ struct _SpiceMsgIn {
 
 enum spice_channel_state {
     SPICE_CHANNEL_STATE_UNCONNECTED = 0,
-    SPICE_CHANNEL_STATE_FAILED_AUTHENTICATION,
     SPICE_CHANNEL_STATE_RECONNECTING,
     SPICE_CHANNEL_STATE_CONNECTING,
     SPICE_CHANNEL_STATE_READY,
@@ -110,6 +109,8 @@ struct _SpiceChannelPrivate {
 
     char                        name[16];
     enum spice_channel_state    state;
+    SpiceChannelEvent           event;
+
     spice_parse_channel_func_t  parser;
     SpiceMessageMarshallers     *marshallers;
     guint                       channel_watch;
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index fb7b0d5..204b250 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -1067,7 +1067,7 @@ static void spice_channel_failed_authentication(SpiceChannel *channel)
                             SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD,
                             _("Authentication failed: password is required"));
 
-    c->state = SPICE_CHANNEL_STATE_FAILED_AUTHENTICATION;
+    c->event = SPICE_CHANNEL_ERROR_AUTH;
 
     c->has_error = TRUE; /* force disconnect */
 }
@@ -1083,7 +1083,7 @@ static gboolean spice_channel_recv_auth(SpiceChannel *channel)
     if (rc != sizeof(link_res)) {
         CHANNEL_DEBUG(channel, "incomplete auth reply (%d/%" G_GSIZE_FORMAT ")",
                     rc, sizeof(link_res));
-        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
+        c->event = SPICE_CHANNEL_ERROR_LINK;
         return FALSE;
     }
 
@@ -1223,7 +1223,7 @@ error:
         return FALSE;
     }
 
-    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
+    c->event = SPICE_CHANNEL_ERROR_LINK;
     return FALSE;
 }
 
@@ -1694,8 +1694,7 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel)
     if (c->peer_pos != c->peer_hdr.size) {
         g_critical("%s: %s: incomplete link reply (%d/%d)",
                   c->name, __FUNCTION__, rc, c->peer_hdr.size);
-        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
-        return FALSE;
+        goto error;
     }
     switch (c->peer_msg->error) {
     case SPICE_LINK_ERR_OK:
@@ -1764,7 +1763,7 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel)
 
 error:
     SPICE_CHANNEL_GET_CLASS(channel)->channel_disconnect(channel);
-    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_LINK);
+    c->event = SPICE_CHANNEL_ERROR_LINK;
     return FALSE;
 }
 
@@ -2154,12 +2153,15 @@ static gboolean spice_channel_iterate(SpiceChannel *channel)
         /* We don't want to report an error if the socket was closed gracefully
          * on the other end (VM shutdown) */
         ret = g_socket_condition_check(c->sock, G_IO_IN | G_IO_ERR | G_IO_HUP);
+
         if (ret & (G_IO_ERR|G_IO_HUP)) {
             CHANNEL_DEBUG(channel, "channel got error");
+
             if (c->state > SPICE_CHANNEL_STATE_CONNECTING) {
-                g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0,
-                                        c->state == SPICE_CHANNEL_STATE_READY ?
-                                        SPICE_CHANNEL_ERROR_IO : SPICE_CHANNEL_ERROR_LINK);
+                if (c->state == SPICE_CHANNEL_STATE_READY)
+                    c->event = SPICE_CHANNEL_ERROR_IO;
+                else
+                    c->event = SPICE_CHANNEL_ERROR_LINK;
             }
         }
         return FALSE;
@@ -2180,8 +2182,9 @@ static gboolean spice_channel_delayed_unref(gpointer data)
 
     g_return_val_if_fail(c->coroutine.coroutine.exited == TRUE, FALSE);
 
-    if (c->state == SPICE_CHANNEL_STATE_FAILED_AUTHENTICATION) {
-        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_AUTH);
+    if (c->event != SPICE_CHANNEL_NONE) {
+        g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, c->event);
+        c->event = SPICE_CHANNEL_NONE;
         g_clear_error(&c->error);
     }
 
@@ -2292,13 +2295,13 @@ static void *spice_channel_coroutine(void *data)
     if (spice_session_get_client_provided_socket(c->session)) {
         if (c->fd < 0) {
             g_critical("fd not provided!");
-            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_CONNECT);
+            c->event = SPICE_CHANNEL_ERROR_CONNECT;
             goto cleanup;
         }
 
         if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) {
                 CHANNEL_DEBUG(channel, "Failed to open socket from fd %d", c->fd);
-                g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_CONNECT);
+                c->event = SPICE_CHANNEL_ERROR_CONNECT;
                 goto cleanup;
         }
 
@@ -2318,8 +2321,7 @@ reconnect:
             goto reconnect;
         } else {
             CHANNEL_DEBUG(channel, "Connect error");
-            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_CONNECT);
-            g_clear_error(&c->error);
+            c->event = SPICE_CHANNEL_ERROR_CONNECT;
             goto cleanup;
         }
     }
@@ -2331,7 +2333,7 @@ reconnect:
         c->ctx = SSL_CTX_new(SSLv23_method());
         if (c->ctx == NULL) {
             g_critical("SSL_CTX_new failed");
-            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
+            c->event = SPICE_CHANNEL_ERROR_TLS;
             goto cleanup;
         }
 
@@ -2347,7 +2349,7 @@ reconnect:
                     g_warning("only pubkey active");
                     verify = SPICE_SESSION_VERIFY_PUBKEY;
                 } else {
-                    g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
+                    c->event = SPICE_CHANNEL_ERROR_TLS;
                     goto cleanup;
                 }
             }
@@ -2365,7 +2367,7 @@ reconnect:
         c->ssl = SSL_new(c->ctx);
         if (c->ssl == NULL) {
             g_critical("SSL_new failed");
-            g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
+            c->event = SPICE_CHANNEL_ERROR_TLS;
             goto cleanup;
         }
 
@@ -2394,7 +2396,7 @@ ssl_reconnect:
             } else {
                 g_warning("%s: SSL_connect: %s",
                           c->name, ERR_error_string(rc, NULL));
-                g_coroutine_signal_emit(channel, signals[SPICE_CHANNEL_EVENT], 0, SPICE_CHANNEL_ERROR_TLS);
+                c->event = SPICE_CHANNEL_ERROR_TLS;
                 goto cleanup;
             }
         }
@@ -2430,6 +2432,7 @@ cleanup:
     SPICE_CHANNEL_GET_CLASS(channel)->channel_disconnect(channel);
 
     if (c->state == SPICE_CHANNEL_STATE_RECONNECTING) {
+        g_warn_if_fail(c->event == SPICE_CHANNEL_NONE);
         spice_channel_connect(channel);
         g_object_unref(channel);
     } else


More information about the Spice-commits mailing list