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
Attachment:
pgpDTe3CYoVKf.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel