[Spice-devel] [PATCH spice-gtk 4/6] session: allow to connect via HTTP CONNECT proxy
Christophe Fergeau
cfergeau at redhat.com
Thu Oct 18 08:56:53 PDT 2012
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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20121018/bb0131d5/attachment-0001.pgp>
More information about the Spice-devel
mailing list