[Spice-devel] [PATCH spice-gtk 3/5] webdav: use a pipe to connect to server
Christophe Fergeau
cfergeau at redhat.com
Mon Feb 23 06:57:42 PST 2015
On Sat, Feb 21, 2015 at 01:40:14AM +0100, Marc-André Lureau wrote:
> 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);
Is it required to pass this fake 127.0.0.1 address?
soup_server_accept_iostream says it can accept NULL local/remote
addresses.
> + if (!soup_server_accept_iostream(server, peer, addr, addr, &error))
> + goto fail;
Looks good otherwise from a cursory look (iow trusting that it has been
tested and works ok).
Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20150223/e5d97c00/attachment-0001.sig>
More information about the Spice-devel
mailing list