On Fri, Aug 24, 2012 at 03:58:19PM +0200, Marc-André Lureau wrote: > The previous patches (introducing GSocketClient & GProxy usage) turned > the code into only sync calls. This would be much nicer to review if the GProxy changes were done separately I think, or folded into patch 4/6 Christophe > > By using async() variants of resolve & connect functions, make the > open host connection asynchronous again. > --- > gtk/spice-session.c | 195 +++++++++++++++++++++++++++++++++------------------- > 1 file changed, 123 insertions(+), 72 deletions(-) > > diff --git a/gtk/spice-session.c b/gtk/spice-session.c > index ae70b73..1688c58 100644 > --- a/gtk/spice-session.c > +++ b/gtk/spice-session.c > @@ -28,6 +28,7 @@ > #include "gio-coroutine.h" > #include "glib-compat.h" > #include "wocky-http-proxy.h" > +#include "spice-proxy.h" > > struct channel { > SpiceChannel *channel; > @@ -1511,59 +1512,123 @@ gboolean spice_session_has_channel_type(SpiceSession *session, gint type) > /* ------------------------------------------------------------------ */ > /* private functions */ > > -static GSocketAddress* get_proxy_address(SpiceSession *session, guint port, GError **error) > +static SpiceProxy* get_proxy(GError **error) > { > - SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session); > - GSocketAddress *address = NULL; > - const gchar *proxy = g_getenv("SPICE_PROXY"); > - GList *addresses = NULL, *it; > + SpiceProxy *proxy; > > - if (proxy == NULL) > + const gchar *proxy_env = g_getenv("SPICE_PROXY"); > + if (proxy_env == NULL || strlen(proxy_env) == 0) > return NULL; > > - /* FIXME: use GUri when it is ready... */ > - if (g_ascii_strncasecmp("http://", proxy, 7) == 0) > - proxy += 7; > - > - gchar **proxyv = g_strsplit(proxy, ":", 0); > - guint16 pport = 3128; > - const gchar *proxy_host = NULL, *proxy_port = NULL; > - > - proxy_host = proxyv[0]; > - if (proxy_host != NULL) > - proxy_port = proxyv[1]; > - > - if (proxy_port != NULL) { > - char *endptr; > - pport = strtoul(proxy_port, &endptr, 10); > - if (*endptr != '\0') { > - g_set_error(error, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, > - "Invalid proxy port: %s", proxy_port); > - goto end; > - } > - } > + proxy = spice_proxy_new(); > + if (!spice_proxy_parse(proxy, proxy_env, error)) > + g_clear_object(&proxy); > + > + return proxy; > +} > + > +typedef struct spice_open_host spice_open_host; > > - addresses = g_resolver_lookup_by_name(g_resolver_get_default(), > - proxy_host, NULL, error); > - if (*error != NULL) > +struct spice_open_host { > + struct coroutine *from; > + SpiceSession *session; > + SpiceChannel *channel; > + SpiceProxy *proxy; > + int port; > + GCancellable *cancellable; > + GError *error; > + GSocket *socket; > +}; > + > +static void socket_client_connect_ready(GObject *source_object, GAsyncResult *result, > + gpointer data) > +{ > + GSocketClient *client = G_SOCKET_CLIENT(source_object); > + spice_open_host *open_host = data; > + GSocketConnection *connection = NULL; > + > + SPICE_DEBUG("connect ready"); > + connection = g_socket_client_connect_finish(client, result, &open_host->error); > + if (connection == NULL) > goto end; > > - /* FIXME: iterate over all addresses > - * gproxy makes it quite unconvenient to deal with hostname, > - * it would make sense to do it once earlier? > - */ > + open_host->socket = g_socket_connection_get_socket(connection); > + g_object_ref(open_host->socket); > + > +end: > + g_object_unref(connection); > + g_object_unref(client); > + > + coroutine_yieldto(open_host->from, NULL); > +} > + > +/* main context */ > +static void open_host_connectable_connect(spice_open_host *open_host, GSocketConnectable *connectable) > +{ > + GSocketClient *client; > + > + SPICE_DEBUG("connecting %p...", open_host); > + client = g_socket_client_new(); > + g_socket_client_connect_async(client, connectable, open_host->cancellable, > + socket_client_connect_ready, open_host); > +} > + > +/* main context */ > +static void proxy_lookup_ready(GObject *source_object, GAsyncResult *result, > + gpointer data) > +{ > + spice_open_host *open_host = data; > + SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(open_host->session); > + GList *addresses = NULL, *it; > + GSocketAddress *address; > + > + SPICE_DEBUG("proxy lookup ready"); > + addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object), > + result, &open_host->error); > + if (addresses == NULL || open_host->error) { > + coroutine_yieldto(open_host->from, NULL); > + return; > + } > + > for (it = addresses; it != NULL; it = it->next) { > - address = g_proxy_address_new(G_INET_ADDRESS(it->data), pport, "http", > - s->host, port, NULL, NULL); > + address = g_proxy_address_new(G_INET_ADDRESS(it->data), > + spice_proxy_get_port(open_host->proxy), "http", > + s->host, open_host->port, NULL, NULL); > if (address != NULL) > break; > } > > -end: > + open_host_connectable_connect(open_host, G_SOCKET_CONNECTABLE(address)); > g_resolver_free_addresses(addresses); > - g_strfreev(proxyv); > +} > + > +/* main context */ > +static gboolean open_host_idle_cb(gpointer data) > +{ > + spice_open_host *open_host = data; > + SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(open_host->session); > + > + g_return_val_if_fail(open_host != NULL, FALSE); > + g_return_val_if_fail(open_host->socket == NULL, FALSE); > + > + open_host->proxy = get_proxy(&open_host->error); > + if (open_host->proxy) { > + g_resolver_lookup_by_name_async(g_resolver_get_default(), > + spice_proxy_get_hostname(open_host->proxy), > + open_host->cancellable, > + proxy_lookup_ready, open_host); > + } else if (open_host->error != NULL) { > + coroutine_yieldto(open_host->from, NULL); > + return FALSE; > + } else > + open_host_connectable_connect(open_host, > + g_network_address_new(s->host, open_host->port)); > + > + SPICE_DEBUG("open host %s:%d", s->host, open_host->port); > + if (open_host->proxy != NULL) > + SPICE_DEBUG("(with proxy %p)", open_host->proxy); > > - return address; > + return FALSE; > } > > /* coroutine context */ > @@ -1572,47 +1637,33 @@ GSocket* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *ch > gboolean use_tls) > { > SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session); > - GSocketClient *client = NULL; > - GSocketConnection *connection = NULL; > - GSocketAddress *address = NULL; > - GSocketConnectable *connectable = NULL; > - GSocket *socket = NULL; > - GError *error = NULL; > - int port; > + spice_open_host open_host = { 0, }; > > if ((use_tls && !s->tls_port) || (!use_tls && !s->port)) > return NULL; > > - port = atoi(use_tls ? s->tls_port : s->port); > - > - /* FIXME: make all of this async again */ > - client = g_socket_client_new(); > - address = get_proxy_address(session, port, &error); > - if (error != NULL) { > - g_critical("%s", error->message); > - goto end; > - } > + open_host.from = coroutine_self(); > + open_host.session = session; > + open_host.channel = channel; > + open_host.port = atoi(use_tls ? s->tls_port : s->port); > + g_idle_add(open_host_idle_cb, &open_host); > > - if (address != NULL) > - connectable = G_SOCKET_CONNECTABLE(address); > - else > - connectable = g_network_address_new(s->host, port); > + /* switch to main loop and wait for connection */ > + coroutine_yield(NULL); > + if (open_host.error != NULL) { > + g_return_val_if_fail(open_host.socket == NULL, NULL); > > - connection = g_socket_client_connect(client, connectable, NULL, &error); > - if (connection == NULL) > - goto end; > - > - socket = g_socket_connection_get_socket(connection); > - g_socket_set_blocking(socket, FALSE); > - g_socket_set_keepalive(socket, TRUE); > - g_object_ref(socket); > + g_warning("%s", open_host.error->message); > + g_clear_error(&open_host.error); > + } else { > + g_return_val_if_fail(open_host.socket != NULL, NULL); > > -end: > - g_clear_object(&connection); > - g_clear_object(&connectable); > - g_clear_object(&client); > + g_socket_set_blocking(open_host.socket, FALSE); > + g_socket_set_keepalive(open_host.socket, TRUE); > + } > > - return socket; > + g_clear_object(&open_host.proxy); > + return open_host.socket; > } > > > -- > 1.7.11.4 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpf4xg61yZRW.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel