Instead of listening on TCP sockets, and proxying connections there, make the webdav server accept new connections from stream. The streams are user-space GIOStream pipe, one side is connected to the Spice webdav channel muxer/demuxer, the other side is a SoupSocket client. This makes the server not exposed any local public access, avoid the need for server threads, or proxying the connections through system sockets. --- gtk/channel-webdav.c | 83 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/gtk/channel-webdav.c b/gtk/channel-webdav.c index 8cf53cf..95c0521 100644 --- a/gtk/channel-webdav.c +++ b/gtk/channel-webdav.c @@ -24,6 +24,7 @@ #include "spice-marshal.h" #include "glib-compat.h" #include "vmcstream.h" +#include "giopipe.h" /** * SECTION:channel-webdav @@ -185,8 +186,7 @@ typedef struct Client { guint refs; SpiceWebdavChannel *self; - GIOStream *conn; - OutputQueue *output; + GIOStream *pipe; gint64 id; GCancellable *cancellable; @@ -204,9 +204,8 @@ client_unref(Client *client) return; g_free(client->mux.buf); - output_queue_free(client->output); - g_object_unref(client->conn); + g_object_unref(client->pipe); g_object_unref(client->cancellable); g_free(client); @@ -289,7 +288,7 @@ static void client_start_read(SpiceWebdavChannel *self, Client *client) { GInputStream *input; - input = g_io_stream_get_input_stream(G_IO_STREAM(client->conn)); + input = g_io_stream_get_input_stream(G_IO_STREAM(client->pipe)); g_input_stream_read_async(input, client->mux.buf, MAX_MUX_SIZE, G_PRIORITY_DEFAULT, client->cancellable, server_reply_cb, client_ref(client)); @@ -297,43 +296,71 @@ static void client_start_read(SpiceWebdavChannel *self, Client *client) static void start_demux(SpiceWebdavChannel *self); -static void pushed_client_cb(OutputQueue *q, gpointer user_data) +static void demux_to_client_finish(SpiceWebdavChannel *self, + Client *client, gssize size) { - Client *client = user_data; - SpiceWebdavChannel *self = client->self; SpiceWebdavChannelPrivate *c = self->priv; + if (size <= 0) { + remove_client(self, client); + } + c->demuxing = FALSE; start_demux(self); } +static void demux_to_client_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + Client *client = user_data; + SpiceWebdavChannelPrivate *c = client->self->priv; + GError *error = NULL; + gssize size; + + size = g_output_stream_write_finish(G_OUTPUT_STREAM(source), result, &error); + + if (error) { + CHANNEL_DEBUG(client->self, "write failed: %s", error->message); + g_clear_error(&error); + } + + g_warn_if_fail(size == c->demux.size); + demux_to_client_finish(client->self, client, size); +} + static void demux_to_client(SpiceWebdavChannel *self, - Client *client) + Client *client) { SpiceWebdavChannelPrivate *c = self->priv; gssize size = c->demux.size; CHANNEL_DEBUG(self, "pushing %"G_GSSIZE_FORMAT" to client %p", size, client); - if (size != 0) { - output_queue_push(client->output, (guint8 *)c->demux.buf, size, - (GFunc)pushed_client_cb, client); + if (size > 0) { + g_output_stream_write_async(g_io_stream_get_output_stream(client->pipe), + c->demux.buf, size, G_PRIORITY_DEFAULT, + c->cancellable, demux_to_client_cb, client); + return; } else { - remove_client(self, client); - c->demuxing = FALSE; - start_demux(self); + demux_to_client_finish(self, client, size); } } static void start_client(SpiceWebdavChannel *self) { +#ifdef USE_PHODAV SpiceWebdavChannelPrivate *c = self->priv; - GOutputStream *output; Client *client; + GIOStream *peer = NULL; + SpiceSession *session; + SoupServer *server; + GSocketAddress *addr; + GError *error = NULL; + + session = spice_channel_get_session(SPICE_CHANNEL(self)); + server = phodav_server_get_soup_server(spice_session_get_webdav_server(session)); 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; @@ -341,15 +368,29 @@ static void start_client(SpiceWebdavChannel *self) client->mux.id = GINT64_TO_LE(client->id); client->mux.buf = g_malloc0(MAX_MUX_SIZE); client->cancellable = g_cancellable_new(); + spice_make_pipe(&client->pipe, &peer); - 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); + addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); + if (!soup_server_accept_iostream(server, peer, addr, addr, &error)) + goto fail; - client_start_read(self, client); g_hash_table_insert(c->clients, &client->id, client); + client_start_read(self, client); demux_to_client(self, client); + + g_clear_object(&addr); + return; + +fail: + if (error) + CHANNEL_DEBUG(self, "failed to start client: %s", error->message); + + g_clear_object(&addr); + g_clear_object(&peer); + g_clear_error(&error); + client_unref(client); +#endif } static void data_read_cb(GObject *source_object, -- 2.1.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel