[Spice-devel] [PATCH spice-gtk 11/14] channel: talk to giostream instead of gsocket

Marc-André Lureau marcandre.lureau at gmail.com
Wed Feb 12 02:19:09 PST 2014


From: Marc-André Lureau <marcandre.lureau at redhat.com>

---
 gtk/spice-channel-priv.h |  4 ++-
 gtk/spice-channel.c      | 81 +++++++++++++++++++++++++++++++-----------------
 2 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index 35704ea..00893c3 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -80,8 +80,10 @@ struct _SpiceChannelPrivate {
     SSL_CTX                     *ctx;
     SSL                         *ssl;
     SpiceOpenSSLVerify          *sslverify;
-    GSocket                     *sock;
+    GSocket                     *socket;
     GSocketConnection           *conn;
+    GInputStream                *in;
+    GOutputStream               *out;
 
 #if HAVE_SASL
     sasl_conn_t                 *sasl_conn;
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 7bcb0b8..b1e049d 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -763,7 +763,8 @@ static void spice_channel_flush_wire(SpiceChannel *channel,
     GIOCondition cond;
 
     while (offset < datalen) {
-        int ret;
+        gssize ret;
+        GError *error = NULL;
 
         if (c->has_error) return;
 
@@ -779,9 +780,12 @@ static void spice_channel_flush_wire(SpiceChannel *channel,
                 ret = -1;
             }
         } else {
-            GError *error = NULL;
-            ret = g_socket_send(c->sock, ptr+offset, datalen-offset,
-                                NULL, &error);
+#if GLIB_CHECK_VERSION(2, 28, 0)
+            ret = g_pollable_output_stream_write_nonblocking(G_POLLABLE_OUTPUT_STREAM(c->out),
+                                                             ptr+offset, datalen-offset, NULL, &error);
+#else
+            ret = g_socket_send(c->socket, ptr+offset, datalen-offset, NULL, &error);
+#endif
             if (ret < 0) {
                 if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
                     cond = G_IO_OUT;
@@ -794,7 +798,8 @@ static void spice_channel_flush_wire(SpiceChannel *channel,
         }
         if (ret == -1) {
             if (cond != 0) {
-                g_coroutine_socket_wait(&c->coroutine, c->sock, cond);
+                // TODO: should use g_pollable_input/output_stream_create_source() in 2.28 ?
+                g_coroutine_socket_wait(&c->coroutine, c->socket, cond);
                 continue;
             } else {
                 CHANNEL_DEBUG(channel, "Closing the channel: spice_channel_flush %d", errno);
@@ -888,7 +893,7 @@ static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out)
 static int spice_channel_read_wire(SpiceChannel *channel, void *data, size_t len)
 {
     SpiceChannelPrivate *c = channel->priv;
-    int ret;
+    gssize ret;
     GIOCondition cond;
 
 reread:
@@ -908,7 +913,13 @@ reread:
         }
     } else {
         GError *error = NULL;
-        ret = g_socket_receive(c->sock, data, len, NULL, &error);
+#if GLIB_CHECK_VERSION(2, 28, 0)
+        ret = g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(c->in),
+                                                       data, len, NULL, &error);
+#else
+        ret = g_socket_receive(c->socket,
+                               data, len, NULL, &error);
+#endif
         if (ret < 0) {
             if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
                 cond = G_IO_IN;
@@ -922,7 +933,8 @@ reread:
 
     if (ret == -1) {
         if (cond != 0) {
-            g_coroutine_socket_wait(&c->coroutine, c->sock, cond);
+            // TODO: should use g_pollable_input/output_stream_create_source() ?
+            g_coroutine_socket_wait(&c->coroutine, c->socket, cond);
             goto reread;
         } else {
             c->has_error = TRUE;
@@ -1351,7 +1363,7 @@ static gboolean spice_channel_perform_auth_sasl(SpiceChannel *channel)
     }
 
     /* Get local address in form  IPADDR:PORT */
-    addr = g_socket_get_local_address(c->sock, NULL);
+    addr = g_socket_get_local_address(c->socket, NULL);
     if (!addr) {
         g_critical("failed to get local address");
         goto error;
@@ -1363,7 +1375,7 @@ static gboolean spice_channel_perform_auth_sasl(SpiceChannel *channel)
     g_clear_object(&addr);
 
     /* Get remote address in form  IPADDR:PORT */
-    addr = g_socket_get_remote_address(c->sock, NULL);
+    addr = g_socket_get_remote_address(c->socket, NULL);
     if (!addr) {
         g_critical("failed to get peer address");
         goto error;
@@ -2062,14 +2074,17 @@ static void spice_channel_iterate_read(SpiceChannel *channel)
 {
     SpiceChannelPrivate *c = channel->priv;
 
-    g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_IN);
+    g_coroutine_socket_wait(&c->coroutine, c->socket, G_IO_IN);
 
     /* treat all incoming data (block on message completion) */
     while (!c->has_error &&
            c->state != SPICE_CHANNEL_STATE_MIGRATING &&
-           g_socket_condition_check(c->sock, G_IO_IN) & G_IO_IN) {
-
-        do
+#if GLIB_CHECK_VERSION(2, 28, 0)
+           g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(c->in))
+#else
+           g_socket_condition_check(c->sock, G_IO_IN) & G_IO_IN
+#endif
+    ) { do
             spice_channel_recv_msg(channel,
                                    (handler_msg_in)SPICE_CHANNEL_GET_CLASS(channel)->handle_msg, NULL);
 #if HAVE_SASL
@@ -2228,17 +2243,19 @@ static void *spice_channel_coroutine(void *data)
             goto cleanup;
         }
 
-        if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) {
+        if (!(c->socket = g_socket_new_from_fd(c->fd, NULL))) {
                 CHANNEL_DEBUG(channel, "Failed to open socket from fd %d", c->fd);
                 emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT);
                 goto cleanup;
         }
 
-        g_socket_set_blocking(c->sock, FALSE);
-        g_socket_set_keepalive(c->sock, TRUE);
+        g_socket_set_blocking(c->socket, FALSE);
+        g_socket_set_keepalive(c->socket, TRUE);
+        c->conn = g_socket_connection_factory_create_connection(c->socket);
         goto connected;
     }
 
+
 reconnect:
     c->conn = spice_session_channel_open_host(c->session, channel, &c->tls);
     if (c->conn == NULL) {
@@ -2252,7 +2269,7 @@ reconnect:
             goto cleanup;
         }
     }
-    c->sock = g_object_ref(g_socket_connection_get_socket(c->conn));
+    c->socket = g_object_ref(g_socket_connection_get_socket(c->conn));
 
     c->has_error = FALSE;
 
@@ -2299,7 +2316,11 @@ reconnect:
         }
 
 
-        BIO *bio = bio_new_gsocket(c->sock);
+#if GLIB_CHECK_VERSION(2, 28, 0)
+        BIO *bio = bio_new_giostream(G_IO_STREAM(c->conn));
+#else
+        BIO *bio = bio_new_gsocket(c->socket);
+#endif
         SSL_set_bio(c->ssl, bio, bio);
 
         {
@@ -2318,7 +2339,7 @@ ssl_reconnect:
         if (rc <= 0) {
             rc = SSL_get_error(c->ssl, rc);
             if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) {
-                g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP);
+                g_coroutine_socket_wait(&c->coroutine, c->socket, G_IO_OUT|G_IO_ERR|G_IO_HUP);
                 goto ssl_reconnect;
             } else {
                 g_warning("%s: SSL_connect: %s",
@@ -2330,7 +2351,10 @@ ssl_reconnect:
     }
 
 connected:
-    rc = setsockopt(g_socket_get_fd(c->sock), IPPROTO_TCP, TCP_NODELAY,
+    c->in = g_io_stream_get_input_stream(G_IO_STREAM(c->conn));
+    c->out = g_io_stream_get_output_stream(G_IO_STREAM(c->conn));
+
+    rc = setsockopt(g_socket_get_fd(c->socket), IPPROTO_TCP, TCP_NODELAY,
                     (const char*)&delay_val, sizeof(delay_val));
     if ((rc != 0)
 #ifdef ENOTSUP
@@ -2415,7 +2439,7 @@ static gboolean channel_connect(SpiceChannel *channel)
     c->state = SPICE_CHANNEL_STATE_CONNECTING;
     c->xmit_queue_blocked = FALSE;
 
-    g_return_val_if_fail(c->sock == NULL, FALSE);
+    g_return_val_if_fail(c->socket == NULL, FALSE);
     g_object_ref(G_OBJECT(channel)); /* Unref'd when co-routine exits */
 
     /* we connect in idle, to let previous coroutine exit, if present */
@@ -2503,10 +2527,9 @@ static void channel_reset(SpiceChannel *channel, gboolean migrating)
         g_object_unref(c->conn);
         c->conn = NULL;
     }
-    if (c->sock) {
-        g_object_unref(c->sock);
-        c->sock = NULL;
-    }
+
+    g_clear_object(&c->socket);
+
     c->fd = -1;
 
     free(c->peer_msg);
@@ -2722,7 +2745,7 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap
     g_return_if_fail(s != NULL);
 
     g_return_if_fail(s->session != NULL);
-    g_return_if_fail(s->sock != NULL);
+    g_return_if_fail(s->socket != NULL);
 
 #define SWAP(Field) ({                          \
     typeof (c->Field) Field = c->Field;         \
@@ -2732,8 +2755,10 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap
 
     /* TODO: split channel in 2 objects: a controller and a swappable
        state object */
+    SWAP(socket);
     SWAP(conn);
-    SWAP(sock);
+    SWAP(in);
+    SWAP(out);
     SWAP(ctx);
     SWAP(ssl);
     SWAP(sslverify);
-- 
1.8.4.2



More information about the Spice-devel mailing list