mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-04 01:58:54 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			763 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			763 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* GIO - GLib Input, Output and Streaming Library
 | 
						|
 *
 | 
						|
 * Copyright (C) 2010 Collabora, Ltd.
 | 
						|
 *
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Lesser General Public
 | 
						|
 * License as published by the Free Software Foundation; either
 | 
						|
 * version 2.1 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This library is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Lesser General
 | 
						|
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
						|
 *
 | 
						|
 * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
#include "gproxyaddressenumerator.h"
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include "gasyncresult.h"
 | 
						|
#include "ginetaddress.h"
 | 
						|
#include "glibintl.h"
 | 
						|
#include "gnetworkaddress.h"
 | 
						|
#include "gnetworkingprivate.h"
 | 
						|
#include "gproxy.h"
 | 
						|
#include "gproxyaddress.h"
 | 
						|
#include "gproxyresolver.h"
 | 
						|
#include "gtask.h"
 | 
						|
#include "gresolver.h"
 | 
						|
#include "gsocketaddress.h"
 | 
						|
#include "gsocketaddressenumerator.h"
 | 
						|
#include "gsocketconnectable.h"
 | 
						|
 | 
						|
/**
 | 
						|
 * SECTION:gproxyaddressenumerator
 | 
						|
 * @short_description: Proxy wrapper enumerator for socket addresses
 | 
						|
 * @include: gio/gio.h
 | 
						|
 *
 | 
						|
 * #GProxyAddressEnumerator is a wrapper around #GSocketAddressEnumerator which
 | 
						|
 * takes the #GSocketAddress instances returned by the #GSocketAddressEnumerator
 | 
						|
 * and wraps them in #GProxyAddress instances, using the given
 | 
						|
 * #GProxyAddressEnumerator:proxy-resolver.
 | 
						|
 *
 | 
						|
 * This enumerator will be returned (for example, by
 | 
						|
 * g_socket_connectable_enumerate()) as appropriate when a proxy is configured;
 | 
						|
 * there should be no need to manually wrap a #GSocketAddressEnumerator instance
 | 
						|
 * with one.
 | 
						|
 */
 | 
						|
 | 
						|
#define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv)
 | 
						|
 | 
						|
enum
 | 
						|
{
 | 
						|
  PROP_0,
 | 
						|
  PROP_URI,
 | 
						|
  PROP_DEFAULT_PORT,
 | 
						|
  PROP_CONNECTABLE,
 | 
						|
  PROP_PROXY_RESOLVER
 | 
						|
};
 | 
						|
 | 
						|
struct _GProxyAddressEnumeratorPrivate
 | 
						|
{
 | 
						|
  /* Destination address */
 | 
						|
  GSocketConnectable *connectable;
 | 
						|
  gchar              *dest_uri;
 | 
						|
  guint16             default_port;
 | 
						|
  gchar              *dest_hostname;
 | 
						|
  guint16             dest_port;
 | 
						|
  GList              *dest_ips;
 | 
						|
 | 
						|
  /* Proxy enumeration */
 | 
						|
  GProxyResolver           *proxy_resolver;
 | 
						|
  gchar                   **proxies;
 | 
						|
  gchar                   **next_proxy;
 | 
						|
  GSocketAddressEnumerator *addr_enum;
 | 
						|
  GSocketAddress           *proxy_address;
 | 
						|
  const gchar              *proxy_uri;
 | 
						|
  gchar                    *proxy_type;
 | 
						|
  gchar                    *proxy_username;
 | 
						|
  gchar                    *proxy_password;
 | 
						|
  gboolean                  supports_hostname;
 | 
						|
  GList                    *next_dest_ip;
 | 
						|
  GError                   *last_error;
 | 
						|
};
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_PRIVATE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
 | 
						|
 | 
						|
static void
 | 
						|
save_userinfo (GProxyAddressEnumeratorPrivate *priv,
 | 
						|
               const gchar *proxy)
 | 
						|
{
 | 
						|
  g_clear_pointer (&priv->proxy_username, g_free);
 | 
						|
  g_clear_pointer (&priv->proxy_password, g_free);
 | 
						|
 | 
						|
  g_uri_split_with_user (proxy, G_URI_FLAGS_HAS_PASSWORD, NULL,
 | 
						|
                         &priv->proxy_username, &priv->proxy_password,
 | 
						|
                         NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
next_enumerator (GProxyAddressEnumeratorPrivate *priv)
 | 
						|
{
 | 
						|
  if (priv->proxy_address)
 | 
						|
    return;
 | 
						|
 | 
						|
  while (priv->addr_enum == NULL && *priv->next_proxy)
 | 
						|
    {
 | 
						|
      GSocketConnectable *connectable = NULL;
 | 
						|
      GProxy *proxy;
 | 
						|
 | 
						|
      priv->proxy_uri = *priv->next_proxy++;
 | 
						|
      g_free (priv->proxy_type);
 | 
						|
      priv->proxy_type = g_uri_parse_scheme (priv->proxy_uri);
 | 
						|
 | 
						|
      if (priv->proxy_type == NULL)
 | 
						|
	continue;
 | 
						|
 | 
						|
      /* Assumes hostnames are supported for unknown protocols */
 | 
						|
      priv->supports_hostname = TRUE;
 | 
						|
      proxy = g_proxy_get_default_for_protocol (priv->proxy_type);
 | 
						|
      if (proxy)
 | 
						|
        {
 | 
						|
	  priv->supports_hostname = g_proxy_supports_hostname (proxy);
 | 
						|
	  g_object_unref (proxy);
 | 
						|
        }
 | 
						|
 | 
						|
      if (strcmp ("direct", priv->proxy_type) == 0)
 | 
						|
	{
 | 
						|
	  if (priv->connectable)
 | 
						|
	    connectable = g_object_ref (priv->connectable);
 | 
						|
	  else
 | 
						|
	    connectable = g_network_address_new (priv->dest_hostname,
 | 
						|
						 priv->dest_port);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  GError *error = NULL;
 | 
						|
 | 
						|
	  connectable = g_network_address_parse_uri (priv->proxy_uri, 0, &error);
 | 
						|
 | 
						|
	  if (error)
 | 
						|
	    {
 | 
						|
	      g_warning ("Invalid proxy URI '%s': %s",
 | 
						|
			 priv->proxy_uri, error->message);
 | 
						|
	      g_error_free (error);
 | 
						|
	    }
 | 
						|
 | 
						|
	  save_userinfo (priv, priv->proxy_uri);
 | 
						|
	}
 | 
						|
 | 
						|
      if (connectable)
 | 
						|
	{
 | 
						|
	  priv->addr_enum = g_socket_connectable_enumerate (connectable);
 | 
						|
	  g_object_unref (connectable);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static GSocketAddress *
 | 
						|
g_proxy_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
 | 
						|
				 GCancellable              *cancellable,
 | 
						|
				 GError                   **error)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
 | 
						|
  GSocketAddress *result = NULL;
 | 
						|
  GError *first_error = NULL;
 | 
						|
 | 
						|
  if (priv->proxies == NULL)
 | 
						|
    {
 | 
						|
      priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
 | 
						|
					       priv->dest_uri,
 | 
						|
					       cancellable,
 | 
						|
					       error);
 | 
						|
      priv->next_proxy = priv->proxies;
 | 
						|
 | 
						|
      if (priv->proxies == NULL)
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  while (result == NULL && (*priv->next_proxy || priv->addr_enum))
 | 
						|
    {
 | 
						|
      gchar *dest_hostname;
 | 
						|
      gchar *dest_protocol;
 | 
						|
      GInetSocketAddress *inetsaddr;
 | 
						|
      GInetAddress *inetaddr;
 | 
						|
      guint16 port;
 | 
						|
 | 
						|
      next_enumerator (priv);
 | 
						|
 | 
						|
      if (!priv->addr_enum)
 | 
						|
	continue;
 | 
						|
 | 
						|
      if (priv->proxy_address == NULL)
 | 
						|
	{
 | 
						|
	  priv->proxy_address = g_socket_address_enumerator_next (
 | 
						|
				    priv->addr_enum,
 | 
						|
				    cancellable,
 | 
						|
				    first_error ? NULL : &first_error);
 | 
						|
	}
 | 
						|
 | 
						|
      if (priv->proxy_address == NULL)
 | 
						|
	{
 | 
						|
	  g_object_unref (priv->addr_enum);
 | 
						|
	  priv->addr_enum = NULL;
 | 
						|
 | 
						|
	  if (priv->dest_ips)
 | 
						|
	    {
 | 
						|
	      g_resolver_free_addresses (priv->dest_ips);
 | 
						|
	      priv->dest_ips = NULL;
 | 
						|
	    }
 | 
						|
 | 
						|
	  continue;
 | 
						|
	}
 | 
						|
 | 
						|
      if (strcmp ("direct", priv->proxy_type) == 0)
 | 
						|
	{
 | 
						|
	  result = priv->proxy_address;
 | 
						|
	  priv->proxy_address = NULL;
 | 
						|
	  continue;
 | 
						|
	}
 | 
						|
 | 
						|
      if (!priv->supports_hostname)
 | 
						|
	{
 | 
						|
	  GInetAddress *dest_ip;
 | 
						|
 | 
						|
	  if (!priv->dest_ips)
 | 
						|
	    {
 | 
						|
	      GResolver *resolver;
 | 
						|
 | 
						|
	      resolver = g_resolver_get_default();
 | 
						|
	      priv->dest_ips = g_resolver_lookup_by_name (resolver,
 | 
						|
							  priv->dest_hostname,
 | 
						|
							  cancellable,
 | 
						|
							  first_error ? NULL : &first_error);
 | 
						|
	      g_object_unref (resolver);
 | 
						|
 | 
						|
	      if (!priv->dest_ips)
 | 
						|
		{
 | 
						|
		  g_object_unref (priv->proxy_address);
 | 
						|
		  priv->proxy_address = NULL;
 | 
						|
		  continue;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (!priv->next_dest_ip)
 | 
						|
	    priv->next_dest_ip = priv->dest_ips;
 | 
						|
	
 | 
						|
	  dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
 | 
						|
	  dest_hostname = g_inet_address_to_string (dest_ip);
 | 
						|
 | 
						|
	  priv->next_dest_ip = g_list_next (priv->next_dest_ip);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  dest_hostname = g_strdup (priv->dest_hostname);
 | 
						|
	}
 | 
						|
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
 | 
						|
		 		  
 | 
						|
      g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address),
 | 
						|
			    NULL);
 | 
						|
 | 
						|
      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
 | 
						|
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
 | 
						|
      port = g_inet_socket_address_get_port (inetsaddr);
 | 
						|
 | 
						|
      result = g_object_new (G_TYPE_PROXY_ADDRESS,
 | 
						|
			     "address", inetaddr,
 | 
						|
			     "port", port,
 | 
						|
			     "protocol", priv->proxy_type,
 | 
						|
			     "destination-protocol", dest_protocol,
 | 
						|
			     "destination-hostname", dest_hostname,
 | 
						|
			     "destination-port", priv->dest_port,
 | 
						|
			     "username", priv->proxy_username,
 | 
						|
			     "password", priv->proxy_password,
 | 
						|
			     "uri", priv->proxy_uri,
 | 
						|
			     NULL);
 | 
						|
      g_free (dest_hostname);
 | 
						|
      g_free (dest_protocol);
 | 
						|
 | 
						|
      if (priv->supports_hostname || priv->next_dest_ip == NULL)
 | 
						|
	{
 | 
						|
	  g_object_unref (priv->proxy_address);
 | 
						|
	  priv->proxy_address = NULL;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  if (result == NULL && first_error)
 | 
						|
    g_propagate_error (error, first_error);
 | 
						|
  else if (first_error)
 | 
						|
    g_error_free (first_error);
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
complete_async (GTask *task)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
 | 
						|
 | 
						|
  if (priv->last_error)
 | 
						|
    {
 | 
						|
      g_task_return_error (task, priv->last_error);
 | 
						|
      priv->last_error = NULL;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    g_task_return_pointer (task, NULL, NULL);
 | 
						|
 | 
						|
  g_object_unref (task);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
return_result (GTask *task)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
 | 
						|
  GSocketAddress *result;
 | 
						|
 | 
						|
  if (strcmp ("direct", priv->proxy_type) == 0)
 | 
						|
    {
 | 
						|
      result = priv->proxy_address;
 | 
						|
      priv->proxy_address = NULL;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      gchar *dest_hostname, *dest_protocol;
 | 
						|
      GInetSocketAddress *inetsaddr;
 | 
						|
      GInetAddress *inetaddr;
 | 
						|
      guint16 port;
 | 
						|
 | 
						|
      if (!priv->supports_hostname)
 | 
						|
	{
 | 
						|
	  GInetAddress *dest_ip;
 | 
						|
 | 
						|
	  if (!priv->next_dest_ip)
 | 
						|
	    priv->next_dest_ip = priv->dest_ips;
 | 
						|
 | 
						|
	  dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
 | 
						|
	  dest_hostname = g_inet_address_to_string (dest_ip);
 | 
						|
 | 
						|
	  priv->next_dest_ip = g_list_next (priv->next_dest_ip);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  dest_hostname = g_strdup (priv->dest_hostname);
 | 
						|
	}
 | 
						|
      dest_protocol = g_uri_parse_scheme (priv->dest_uri);
 | 
						|
 | 
						|
      g_return_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
 | 
						|
 | 
						|
      inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
 | 
						|
      inetaddr = g_inet_socket_address_get_address (inetsaddr);
 | 
						|
      port = g_inet_socket_address_get_port (inetsaddr);
 | 
						|
 | 
						|
      result = g_object_new (G_TYPE_PROXY_ADDRESS,
 | 
						|
			     "address", inetaddr,
 | 
						|
			     "port", port,
 | 
						|
			     "protocol", priv->proxy_type,
 | 
						|
			     "destination-protocol", dest_protocol,
 | 
						|
			     "destination-hostname", dest_hostname,
 | 
						|
			     "destination-port", priv->dest_port,
 | 
						|
			     "username", priv->proxy_username,
 | 
						|
			     "password", priv->proxy_password,
 | 
						|
			     "uri", priv->proxy_uri,
 | 
						|
			     NULL);
 | 
						|
      g_free (dest_hostname);
 | 
						|
      g_free (dest_protocol);
 | 
						|
 | 
						|
      if (priv->supports_hostname || priv->next_dest_ip == NULL)
 | 
						|
	{
 | 
						|
	  g_object_unref (priv->proxy_address);
 | 
						|
	  priv->proxy_address = NULL;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  g_task_return_pointer (task, result, g_object_unref);
 | 
						|
  g_object_unref (task);
 | 
						|
}
 | 
						|
 | 
						|
static void address_enumerate_cb (GObject      *object,
 | 
						|
				  GAsyncResult *result,
 | 
						|
				  gpointer	user_data);
 | 
						|
 | 
						|
static void
 | 
						|
next_proxy (GTask *task)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
 | 
						|
 | 
						|
  if (*priv->next_proxy)
 | 
						|
    {
 | 
						|
      g_object_unref (priv->addr_enum);
 | 
						|
      priv->addr_enum = NULL;
 | 
						|
 | 
						|
      if (priv->dest_ips)
 | 
						|
	{
 | 
						|
	  g_resolver_free_addresses (priv->dest_ips);
 | 
						|
	  priv->dest_ips = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
      next_enumerator (priv);
 | 
						|
 | 
						|
      if (priv->addr_enum)
 | 
						|
	{
 | 
						|
	  g_socket_address_enumerator_next_async (priv->addr_enum,
 | 
						|
						  g_task_get_cancellable (task),
 | 
						|
						  address_enumerate_cb,
 | 
						|
						  task);
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  complete_async (task);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
dest_hostname_lookup_cb (GObject           *object,
 | 
						|
			 GAsyncResult      *result,
 | 
						|
			 gpointer           user_data)
 | 
						|
{
 | 
						|
  GTask *task = user_data;
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
 | 
						|
 | 
						|
  g_clear_error (&priv->last_error);
 | 
						|
  priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
 | 
						|
						     result,
 | 
						|
						     &priv->last_error);
 | 
						|
  if (priv->dest_ips)
 | 
						|
    return_result (task);
 | 
						|
  else
 | 
						|
    {
 | 
						|
      g_clear_object (&priv->proxy_address);
 | 
						|
      next_proxy (task);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
address_enumerate_cb (GObject	   *object,
 | 
						|
		      GAsyncResult *result,
 | 
						|
		      gpointer	    user_data)
 | 
						|
{
 | 
						|
  GTask *task = user_data;
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
 | 
						|
 | 
						|
  g_clear_error (&priv->last_error);
 | 
						|
  priv->proxy_address =
 | 
						|
    g_socket_address_enumerator_next_finish (priv->addr_enum,
 | 
						|
					     result,
 | 
						|
					     &priv->last_error);
 | 
						|
  if (priv->proxy_address)
 | 
						|
    {
 | 
						|
      if (!priv->supports_hostname && !priv->dest_ips)
 | 
						|
	{
 | 
						|
	  GResolver *resolver;
 | 
						|
	  resolver = g_resolver_get_default();
 | 
						|
	  g_resolver_lookup_by_name_async (resolver,
 | 
						|
					   priv->dest_hostname,
 | 
						|
					   g_task_get_cancellable (task),
 | 
						|
					   dest_hostname_lookup_cb,
 | 
						|
					   task);
 | 
						|
	  g_object_unref (resolver);
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
 | 
						|
      return_result (task);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    next_proxy (task);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
proxy_lookup_cb (GObject      *object,
 | 
						|
		 GAsyncResult *result,
 | 
						|
		 gpointer      user_data)
 | 
						|
{
 | 
						|
  GTask *task = user_data;
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
 | 
						|
 | 
						|
  g_clear_error (&priv->last_error);
 | 
						|
  priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
 | 
						|
						  result,
 | 
						|
						  &priv->last_error);
 | 
						|
  priv->next_proxy = priv->proxies;
 | 
						|
 | 
						|
  if (priv->last_error)
 | 
						|
    {
 | 
						|
      complete_async (task);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      next_enumerator (priv);
 | 
						|
      if (priv->addr_enum)
 | 
						|
	{
 | 
						|
	  g_socket_address_enumerator_next_async (priv->addr_enum,
 | 
						|
						  g_task_get_cancellable (task),
 | 
						|
						  address_enumerate_cb,
 | 
						|
						  task);
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  complete_async (task);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
 | 
						|
				       GCancellable             *cancellable,
 | 
						|
				       GAsyncReadyCallback       callback,
 | 
						|
				       gpointer                  user_data)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
 | 
						|
  GTask *task;
 | 
						|
 | 
						|
  task = g_task_new (enumerator, cancellable, callback, user_data);
 | 
						|
  g_task_set_source_tag (task, g_proxy_address_enumerator_next_async);
 | 
						|
  g_task_set_task_data (task, priv, NULL);
 | 
						|
 | 
						|
  if (priv->proxies == NULL)
 | 
						|
    {
 | 
						|
      g_proxy_resolver_lookup_async (priv->proxy_resolver,
 | 
						|
				     priv->dest_uri,
 | 
						|
				     cancellable,
 | 
						|
				     proxy_lookup_cb,
 | 
						|
				     task);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
  if (priv->addr_enum)
 | 
						|
    {
 | 
						|
      if (priv->proxy_address)
 | 
						|
	{
 | 
						|
	  return_result (task);
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  g_socket_address_enumerator_next_async (priv->addr_enum,
 | 
						|
						  cancellable,
 | 
						|
						  address_enumerate_cb,
 | 
						|
						  task);
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  complete_async (task);
 | 
						|
}
 | 
						|
 | 
						|
static GSocketAddress *
 | 
						|
g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
 | 
						|
					GAsyncResult              *result,
 | 
						|
					GError                   **error)
 | 
						|
{
 | 
						|
  g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
 | 
						|
 | 
						|
  return g_task_propagate_pointer (G_TASK (result), error);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_constructed (GObject *object)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
 | 
						|
  GSocketConnectable *conn;
 | 
						|
  guint port;
 | 
						|
 | 
						|
  if (priv->dest_uri)
 | 
						|
    {
 | 
						|
      conn = g_network_address_parse_uri (priv->dest_uri, priv->default_port, NULL);
 | 
						|
      if (conn)
 | 
						|
        {
 | 
						|
          g_object_get (conn,
 | 
						|
                        "hostname", &priv->dest_hostname,
 | 
						|
                        "port", &port,
 | 
						|
                        NULL);
 | 
						|
          priv->dest_port = port;
 | 
						|
 | 
						|
          g_object_unref (conn);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        g_warning ("Invalid URI '%s'", priv->dest_uri);
 | 
						|
    }
 | 
						|
 | 
						|
  G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->constructed (object);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_get_property (GObject        *object,
 | 
						|
                                         guint           property_id,
 | 
						|
                                         GValue         *value,
 | 
						|
                                         GParamSpec     *pspec)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
 | 
						|
  switch (property_id)
 | 
						|
    {
 | 
						|
    case PROP_URI:
 | 
						|
      g_value_set_string (value, priv->dest_uri);
 | 
						|
      break;
 | 
						|
 | 
						|
    case PROP_DEFAULT_PORT:
 | 
						|
      g_value_set_uint (value, priv->default_port);
 | 
						|
      break;
 | 
						|
 | 
						|
    case PROP_CONNECTABLE:
 | 
						|
      g_value_set_object (value, priv->connectable);
 | 
						|
      break;
 | 
						|
 | 
						|
    case PROP_PROXY_RESOLVER:
 | 
						|
      g_value_set_object (value, priv->proxy_resolver);
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_set_property (GObject        *object,
 | 
						|
                                         guint           property_id,
 | 
						|
                                         const GValue   *value,
 | 
						|
                                         GParamSpec     *pspec)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
 | 
						|
  switch (property_id)
 | 
						|
    {
 | 
						|
    case PROP_URI:
 | 
						|
      priv->dest_uri = g_value_dup_string (value);
 | 
						|
      break;
 | 
						|
 | 
						|
    case PROP_DEFAULT_PORT:
 | 
						|
      priv->default_port = g_value_get_uint (value);
 | 
						|
      break;
 | 
						|
 | 
						|
    case PROP_CONNECTABLE:
 | 
						|
      priv->connectable = g_value_dup_object (value);
 | 
						|
      break;
 | 
						|
 | 
						|
    case PROP_PROXY_RESOLVER:
 | 
						|
      if (priv->proxy_resolver)
 | 
						|
        g_object_unref (priv->proxy_resolver);
 | 
						|
      priv->proxy_resolver = g_value_get_object (value);
 | 
						|
      if (!priv->proxy_resolver)
 | 
						|
        priv->proxy_resolver = g_proxy_resolver_get_default ();
 | 
						|
      g_object_ref (priv->proxy_resolver);
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_finalize (GObject *object)
 | 
						|
{
 | 
						|
  GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
 | 
						|
 | 
						|
  if (priv->connectable)
 | 
						|
    g_object_unref (priv->connectable);
 | 
						|
 | 
						|
  if (priv->proxy_resolver)
 | 
						|
    g_object_unref (priv->proxy_resolver);
 | 
						|
 | 
						|
  g_free (priv->dest_uri);
 | 
						|
  g_free (priv->dest_hostname);
 | 
						|
 | 
						|
  if (priv->dest_ips)
 | 
						|
    g_resolver_free_addresses (priv->dest_ips);
 | 
						|
 | 
						|
  g_strfreev (priv->proxies);
 | 
						|
 | 
						|
  if (priv->addr_enum)
 | 
						|
    g_object_unref (priv->addr_enum);
 | 
						|
 | 
						|
  g_free (priv->proxy_type);
 | 
						|
  g_free (priv->proxy_username);
 | 
						|
  g_free (priv->proxy_password);
 | 
						|
 | 
						|
  g_clear_error (&priv->last_error);
 | 
						|
 | 
						|
  G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_init (GProxyAddressEnumerator *self)
 | 
						|
{
 | 
						|
  self->priv = g_proxy_address_enumerator_get_instance_private (self);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class)
 | 
						|
{
 | 
						|
  GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class);
 | 
						|
  GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class);
 | 
						|
 | 
						|
  object_class->constructed = g_proxy_address_enumerator_constructed;
 | 
						|
  object_class->set_property = g_proxy_address_enumerator_set_property;
 | 
						|
  object_class->get_property = g_proxy_address_enumerator_get_property;
 | 
						|
  object_class->finalize = g_proxy_address_enumerator_finalize;
 | 
						|
 | 
						|
  enumerator_class->next = g_proxy_address_enumerator_next;
 | 
						|
  enumerator_class->next_async = g_proxy_address_enumerator_next_async;
 | 
						|
  enumerator_class->next_finish = g_proxy_address_enumerator_next_finish;
 | 
						|
 | 
						|
  g_object_class_install_property (object_class,
 | 
						|
				   PROP_URI,
 | 
						|
				   g_param_spec_string ("uri",
 | 
						|
							P_("URI"),
 | 
						|
							P_("The destination URI, use none:// for generic socket"),
 | 
						|
							NULL,
 | 
						|
							G_PARAM_READWRITE |
 | 
						|
							G_PARAM_CONSTRUCT_ONLY |
 | 
						|
							G_PARAM_STATIC_STRINGS));
 | 
						|
 | 
						|
  /**
 | 
						|
   * GProxyAddressEnumerator:default-port:
 | 
						|
   *
 | 
						|
   * The default port to use if #GProxyAddressEnumerator:uri does not
 | 
						|
   * specify one.
 | 
						|
   *
 | 
						|
   * Since: 2.38
 | 
						|
   */
 | 
						|
  g_object_class_install_property (object_class,
 | 
						|
				   PROP_DEFAULT_PORT,
 | 
						|
				   g_param_spec_uint ("default-port",
 | 
						|
                                                      P_("Default port"),
 | 
						|
                                                      P_("The default port to use if uri does not specify one"),
 | 
						|
                                                      0, 65535, 0,
 | 
						|
                                                      G_PARAM_READWRITE |
 | 
						|
                                                      G_PARAM_CONSTRUCT_ONLY |
 | 
						|
                                                      G_PARAM_STATIC_STRINGS));
 | 
						|
 | 
						|
  g_object_class_install_property (object_class,
 | 
						|
				   PROP_CONNECTABLE,
 | 
						|
				   g_param_spec_object ("connectable",
 | 
						|
							P_("Connectable"),
 | 
						|
							P_("The connectable being enumerated."),
 | 
						|
							G_TYPE_SOCKET_CONNECTABLE,
 | 
						|
							G_PARAM_READWRITE |
 | 
						|
							G_PARAM_CONSTRUCT_ONLY |
 | 
						|
							G_PARAM_STATIC_STRINGS));
 | 
						|
 | 
						|
  /**
 | 
						|
   * GProxyAddressEnumerator:proxy-resolver:
 | 
						|
   *
 | 
						|
   * The proxy resolver to use.
 | 
						|
   *
 | 
						|
   * Since: 2.36
 | 
						|
   */
 | 
						|
  g_object_class_install_property (object_class,
 | 
						|
                                   PROP_PROXY_RESOLVER,
 | 
						|
                                   g_param_spec_object ("proxy-resolver",
 | 
						|
                                                        P_("Proxy resolver"),
 | 
						|
                                                        P_("The proxy resolver to use."),
 | 
						|
                                                        G_TYPE_PROXY_RESOLVER,
 | 
						|
                                                        G_PARAM_READWRITE |
 | 
						|
                                                        G_PARAM_CONSTRUCT |
 | 
						|
                                                        G_PARAM_STATIC_STRINGS));
 | 
						|
}
 |