[Spice-devel] [PATCH spice-gtk 2/5] Use libphodav-2 (breaks webdav server temporarily)

Marc-André Lureau marcandre.lureau at redhat.com
Fri Feb 20 16:40:13 PST 2015


This change breaks webdav server, since libphodav-2 no longer
set up a TCP service running in a thread. It's up to the client
to decide how best to accept and handle new connections.

This commits remove all the hacks related to proxying the incoming
connections to a TCP socket, and protected with a magic sequence.

The following commit will use GIOStream pipes to handle each client
connections.
---
 configure.ac         |   2 +-
 gtk/channel-webdav.c | 187 +++------------------------------------------------
 gtk/spice-session.c  |  41 ++++++-----
 3 files changed, 29 insertions(+), 201 deletions(-)

diff --git a/configure.ac b/configure.ac
index d98e502..84cf568 100644
--- a/configure.ac
+++ b/configure.ac
@@ -278,7 +278,7 @@ AC_ARG_ENABLE([webdav],
 if test "x$enable_webdav" = "xno"; then
   have_phodav="no"
 else
-  PKG_CHECK_MODULES(PHODAV, [libphodav-1.0 glib-2.0 >= 2.43.90], [have_phodav=yes], [have_phodav=no])
+  PKG_CHECK_MODULES(PHODAV, [libphodav-2.0 glib-2.0 >= 2.43.90 libsoup-2.4 >= 2.50], [have_phodav=yes], [have_phodav=no])
   AC_SUBST(PHODAV_CFLAGS)
   AC_SUBST(PHODAV_LIBS)
 
diff --git a/gtk/channel-webdav.c b/gtk/channel-webdav.c
index 75b027b..8cf53cf 100644
--- a/gtk/channel-webdav.c
+++ b/gtk/channel-webdav.c
@@ -25,8 +25,6 @@
 #include "glib-compat.h"
 #include "vmcstream.h"
 
-static PhodavServer* phodav_server_get(SpiceSession *session, gint *port);
-
 /**
  * SECTION:channel-webdav
  * @short_description: exports a directory
@@ -187,7 +185,7 @@ typedef struct Client
 {
     guint refs;
     SpiceWebdavChannel *self;
-    GSocketConnection *conn;
+    GIOStream *conn;
     OutputQueue *output;
     gint64 id;
     GCancellable *cancellable;
@@ -327,102 +325,31 @@ static void demux_to_client(SpiceWebdavChannel *self,
     }
 }
 
-static void magic_written(GObject *source_object,
-                          GAsyncResult *res,
-                          gpointer user_data)
-{
-    Client *client = user_data;
-    SpiceWebdavChannel *self = client->self;
-    SpiceWebdavChannelPrivate *c = self->priv;
-    gssize bytes_written;
-    GError *err = NULL;
-
-    bytes_written = g_output_stream_write_finish(G_OUTPUT_STREAM(source_object),
-                                                 res, &err);
-
-    if (err || bytes_written != WEBDAV_MAGIC_SIZE)
-        goto error;
-
-    client_start_read(self, client);
-    g_hash_table_insert(c->clients, &client->id, client);
-
-    demux_to_client(self, client);
-
-    return;
-
-error:
-    if (err) {
-        g_critical("socket creation failed %s", err->message);
-        g_clear_error(&err);
-    }
-    if (client) {
-        client_unref(client);
-    }
-}
-
-static void client_connected(GObject *source_object,
-                             GAsyncResult *res,
-                             gpointer user_data)
+static void start_client(SpiceWebdavChannel *self)
 {
-    SpiceWebdavChannel *self = user_data;
     SpiceWebdavChannelPrivate *c = self->priv;
-    GSocketClient *sclient = G_SOCKET_CLIENT(source_object);
-    GError *err = NULL;
-    GSocketConnection *conn;
-    SpiceSession *session;
-    Client *client = NULL;
     GOutputStream *output;
+    Client *client;
 
-    session = spice_channel_get_session(SPICE_CHANNEL(self));
-
-    conn = g_socket_client_connect_to_host_finish(sclient, res, &err);
-    g_object_unref(sclient);
-    if (err)
-        goto error;
+    CHANNEL_DEBUG(self, "starting client %" G_GINT64_FORMAT, c->demux.client);
 
+    /* FIXME: connect to server */
     client = g_new0(Client, 1);
     client->refs = 1;
     client->id = c->demux.client;
     client->self = self;
-    client->conn = conn;
     client->mux.id = GINT64_TO_LE(client->id);
     client->mux.buf = g_malloc0(MAX_MUX_SIZE);
     client->cancellable = g_cancellable_new();
 
-    output = g_buffered_output_stream_new(g_io_stream_get_output_stream(G_IO_STREAM(conn)));
+    output = g_buffered_output_stream_new(g_io_stream_get_output_stream(G_IO_STREAM(client->conn)));
     client->output = output_queue_new(output);
     g_object_unref(output);
 
-    g_output_stream_write_async(g_io_stream_get_output_stream(G_IO_STREAM(conn)),
-                                spice_session_get_webdav_magic(session), WEBDAV_MAGIC_SIZE,
-                                G_PRIORITY_DEFAULT, c->cancellable,
-                                magic_written, client);
-    return;
-
-error:
-    if (err) {
-        g_critical("socket creation failed %s", err->message);
-        g_clear_error(&err);
-    }
-    if (client) {
-        client_unref(client);
-    }
-}
-
-static void start_client(SpiceWebdavChannel *self)
-{
-    SpiceWebdavChannelPrivate *c = self->priv;
-    GSocketClient *sclient;
-    gint davport = -1;
-    SpiceSession *session;
-
-    session = spice_channel_get_session(SPICE_CHANNEL(self));
-    phodav_server_get(session, &davport);
-    CHANNEL_DEBUG(self, "starting client %" G_GINT64_FORMAT, c->demux.client);
+    client_start_read(self, client);
+    g_hash_table_insert(c->clients, &client->id, client);
 
-    sclient = g_socket_client_new();
-    g_socket_client_connect_to_host_async(sclient, "localhost", davport,
-                                          c->cancellable, client_connected, self);
+    demux_to_client(self, client);
 }
 
 static void data_read_cb(GObject *source_object,
@@ -639,99 +566,3 @@ static void spice_webdav_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
     else
         g_return_if_reached();
 }
-
-
-
-#ifdef USE_PHODAV
-static void new_connection(SoupSocket *sock,
-                           SoupSocket *new,
-                           gpointer    user_data)
-{
-    SpiceSession *session = user_data;
-    SoupAddress *addr;
-    GSocketAddress *gaddr;
-    GInetAddress *iaddr;
-    guint port;
-    guint8 magic[WEBDAV_MAGIC_SIZE];
-    gsize nread;
-    gboolean success = FALSE;
-    SoupSocketIOStatus status;
-
-    /* note: this is sync calls, since webdav server is in a seperate thread */
-    addr = soup_socket_get_remote_address(new);
-    gaddr = soup_address_get_gsockaddr(addr);
-    iaddr = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(gaddr));
-    port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(gaddr));
-
-    SPICE_DEBUG("port %d %p", port, iaddr);
-    if (!g_inet_address_get_is_loopback(iaddr)) {
-        g_warn_if_reached();
-        goto end;
-    }
-
-    g_object_set(new, "non-blocking", FALSE, NULL);
-    status = soup_socket_read(new, magic, sizeof(magic), &nread, NULL, NULL);
-    if (status != SOUP_SOCKET_OK) {
-        g_warning("bad initial socket read: %d", status);
-        goto end;
-    }
-    g_object_set(new, "non-blocking", TRUE, NULL);
-
-    /* check we got the right magic */
-    if (memcmp(spice_session_get_webdav_magic(session), magic, sizeof(magic))) {
-        g_warn_if_reached();
-        goto end;
-    }
-
-    success = TRUE;
-
-end:
-    if (!success) {
-        g_warn_if_reached();
-        soup_socket_disconnect(new);
-        g_signal_stop_emission_by_name(sock, "new_connection");
-    }
-    g_object_unref(gaddr);
-}
-
-G_GNUC_INTERNAL
-PhodavServer* channel_webdav_server_new(SpiceSession *session)
-{
-    PhodavServer *dav;
-    SoupServer *server;
-    SoupSocket *listener;
-    const char *shared_dir;
-
-    shared_dir = spice_session_get_shared_dir(session);
-    if (shared_dir == NULL) {
-        g_debug("No shared dir set, not creating webdav channel");
-        return NULL;
-    }
-
-    dav = phodav_server_new(0, shared_dir);
-
-    server = phodav_server_get_soup_server(dav);
-    listener = soup_server_get_listener(server);
-    spice_g_signal_connect_object(listener, "new_connection",
-                                  G_CALLBACK(new_connection), session,
-                                  0);
-
-    return dav;
-}
-#endif /* USE_PHODAV */
-
-static PhodavServer* phodav_server_get(SpiceSession *session, gint *port)
-{
-    g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
-
-#ifdef USE_PHODAV
-    PhodavServer *server = spice_session_get_webdav_server(session);
-
-    if (port)
-        *port = phodav_server_get_port(server);
-
-    return server;
-#else
-    g_return_val_if_reached(NULL);
-#endif
-}
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 82ea55f..ab7b25c 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -122,7 +122,6 @@ struct _SpiceSessionPrivate {
     SpiceUsbDeviceManager *usb_manager;
     SpicePlaybackChannel *playback_channel;
     PhodavServer      *webdav;
-    guint8             webdav_magic[WEBDAV_MAGIC_SIZE];
 };
 
 
@@ -2604,36 +2603,34 @@ gboolean spice_session_get_smartcard_enabled(SpiceSession *session)
 }
 
 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;
-}
-
-G_GNUC_INTERNAL
 PhodavServer* spice_session_get_webdav_server(SpiceSession *session)
 {
+    SpiceSessionPrivate *priv;
+
     g_return_val_if_fail(SPICE_IS_SESSION(session), NULL);
+    priv = session->priv;
 
 #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);
+    static GMutex mutex;
 
-        session->priv->webdav = channel_webdav_server_new(session);
-        if (session->priv->webdav != NULL) {
-            phodav_server_run(session->priv->webdav);
-        }
+    const gchar *shared_dir = spice_session_get_shared_dir(session);
+    if (shared_dir == NULL) {
+        g_debug("No shared dir set, not creating webdav server");
+        return NULL;
     }
-    g_static_mutex_unlock(&mutex);
+
+    g_mutex_lock(&mutex);
+
+    if (priv->webdav)
+        goto end;
+
+    priv->webdav = phodav_server_new(shared_dir);
+
+ end:
+    g_mutex_unlock(&mutex);
 #endif
 
-    return session->priv->webdav;
+    return priv->webdav;
 }
 
 /**
-- 
2.1.0



More information about the Spice-devel mailing list