[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