Looked ok from a quick look, just a few notes: - it does not seem to apply to master (not that surprising) - the URI parsing code is very basic (will fail on ipv6 addresses in [] for example), but I don't think it's worth spending time polishing one more URI parsing implementation Christophe On Fri, Aug 24, 2012 at 03:58:17PM +0200, Marc-André Lureau wrote: > Allow to connect to a Spice server via a HTTP proxy with CONNECT > method. spice-gtk will use the SPICE_PROXY environment variable, which > can currently only have the following syntax: [http://]hostname[:port] > > This is paving the way to more proxies support (socks4/socks5). > > This code is now entirely sync (it was not even completely async), the > following patch will make it all async again. > > Bump glib dependency to 2.26. > > Tested with Squid, locally only. > --- > configure.ac | 2 +- > gtk/spice-session.c | 128 ++++++++++++++++++++++++++++++---------------------- > 2 files changed, 76 insertions(+), 54 deletions(-) > > diff --git a/configure.ac b/configure.ac > index 38ceeab..f4cdef4 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -243,7 +243,7 @@ else > EXTERNAL_PNP_IDS="$with_pnp_ids_path" > fi > > -PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.22) > +PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.26) > AC_SUBST(GLIB2_CFLAGS) > AC_SUBST(GLIB2_LIBS) > > diff --git a/gtk/spice-session.c b/gtk/spice-session.c > index 5f8847e..ae70b73 100644 > --- a/gtk/spice-session.c > +++ b/gtk/spice-session.c > @@ -1511,43 +1511,59 @@ gboolean spice_session_has_channel_type(SpiceSession *session, gint type) > /* ------------------------------------------------------------------ */ > /* private functions */ > > -static GSocket *channel_connect_socket(SpiceChannel *channel, > - GSocketAddress *sockaddr, > - GError **error) > +static GSocketAddress* get_proxy_address(SpiceSession *session, guint port, GError **error) > { > - SpiceChannelPrivate *c = channel->priv; > - GSocket *sock = g_socket_new(g_socket_address_get_family(sockaddr), > - G_SOCKET_TYPE_STREAM, > - G_SOCKET_PROTOCOL_DEFAULT, > - error); > + SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session); > + GSocketAddress *address = NULL; > + const gchar *proxy = g_getenv("SPICE_PROXY"); > + GList *addresses = NULL, *it; > > - if (!sock) > + if (proxy == NULL) > return NULL; > > - g_socket_set_blocking(sock, FALSE); > - g_socket_set_keepalive(sock, TRUE); > + /* 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; > + } > + } > > - if (!g_socket_connect(sock, sockaddr, NULL, error)) { > - if (*error && (*error)->code == G_IO_ERROR_PENDING) { > - g_clear_error(error); > - SPICE_DEBUG("Socket pending"); > - g_coroutine_socket_wait(&c->coroutine, sock, G_IO_OUT | G_IO_ERR | G_IO_HUP); > + addresses = g_resolver_lookup_by_name(g_resolver_get_default(), > + proxy_host, NULL, error); > + if (*error != NULL) > + goto end; > > - if (!g_socket_check_connect_result(sock, error)) { > - SPICE_DEBUG("Failed to connect %s", (*error)->message); > - g_object_unref(sock); > - return NULL; > - } > - } else { > - SPICE_DEBUG("Socket error: %s", *error ? (*error)->message : "unknown"); > - g_object_unref(sock); > - return NULL; > - } > + /* FIXME: iterate over all addresses > + * gproxy makes it quite unconvenient to deal with hostname, > + * it would make sense to do it once earlier? > + */ > + 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); > + if (address != NULL) > + break; > } > > - SPICE_DEBUG("Finally connected"); > +end: > + g_resolver_free_addresses(addresses); > + g_strfreev(proxyv); > > - return sock; > + return address; > } > > /* coroutine context */ > @@ -1556,11 +1572,12 @@ GSocket* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *ch > gboolean use_tls) > { > SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session); > - GSocketConnectable *addr; > - GSocketAddressEnumerator *enumerator; > - GSocketAddress *sockaddr; > - GError *conn_error = NULL; > - GSocket *sock = NULL; > + GSocketClient *client = NULL; > + GSocketConnection *connection = NULL; > + GSocketAddress *address = NULL; > + GSocketConnectable *connectable = NULL; > + GSocket *socket = NULL; > + GError *error = NULL; > int port; > > if ((use_tls && !s->tls_port) || (!use_tls && !s->port)) > @@ -1568,29 +1585,34 @@ GSocket* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *ch > > port = atoi(use_tls ? s->tls_port : s->port); > > - SPICE_DEBUG("Resolving host %s %d", s->host, 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; > + } > > - addr = g_network_address_new(s->host, port); > + if (address != NULL) > + connectable = G_SOCKET_CONNECTABLE(address); > + else > + connectable = g_network_address_new(s->host, port); > > - enumerator = g_socket_connectable_enumerate (addr); > - g_object_unref (addr); > + connection = g_socket_client_connect(client, connectable, NULL, &error); > + if (connection == NULL) > + goto end; > > - /* Try each sockaddr until we succeed. Record the first > - * connection error, but not any further ones (since they'll probably > - * be basically the same as the first). > - */ > - while (!sock && > - (sockaddr = g_socket_address_enumerator_next(enumerator, NULL, &conn_error))) { > - SPICE_DEBUG("Trying one socket"); > - g_clear_error(&conn_error); > - sock = channel_connect_socket(channel, sockaddr, &conn_error); > - if (conn_error != NULL) > - SPICE_DEBUG("%s", conn_error->message); > - g_object_unref(sockaddr); > - } > - g_object_unref(enumerator); > - g_clear_error(&conn_error); > - return sock; > + socket = g_socket_connection_get_socket(connection); > + g_socket_set_blocking(socket, FALSE); > + g_socket_set_keepalive(socket, TRUE); > + g_object_ref(socket); > + > +end: > + g_clear_object(&connection); > + g_clear_object(&connectable); > + g_clear_object(&client); > + > + return socket; > } > > > -- > 1.7.11.4 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpV14XP8L_pq.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel