mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 08:22:16 +01:00 
			
		
		
		
	In the async case, a failed DNS lookup was causing the proxy resolution to bail out immediately, rather than just moving on to the next potential proxy (which might not need us to do the DNS lookup beforehand). Fix that.
		
			
				
	
	
		
			744 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			744 lines
		
	
	
		
			17 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 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, write to the
 | |
|  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 | |
|  * Boston, MA 02111-1307, USA.
 | |
|  *
 | |
|  * 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 "gsimpleasyncresult.h"
 | |
| #include "gresolver.h"
 | |
| #include "gsocketaddress.h"
 | |
| #include "gsocketaddressenumerator.h"
 | |
| #include "gsocketconnectable.h"
 | |
| 
 | |
| G_DEFINE_TYPE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR);
 | |
| 
 | |
| #define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv)
 | |
| 
 | |
| enum
 | |
| {
 | |
|   PROP_0,
 | |
|   PROP_URI,
 | |
|   PROP_CONNECTABLE
 | |
| };
 | |
| 
 | |
| struct _GProxyAddressEnumeratorPrivate
 | |
| {
 | |
|   /* Destination address */
 | |
|   GSocketConnectable *connectable;
 | |
|   gchar		     *dest_uri;
 | |
|   gchar		     *dest_hostname;
 | |
|   guint16	      dest_port;
 | |
|   GList              *dest_ips;
 | |
| 
 | |
|   /* Proxy enumeration */
 | |
|   gchar			  **proxies;
 | |
|   gchar			  **next_proxy;
 | |
|   GSocketAddressEnumerator *addr_enum;
 | |
|   GSocketAddress           *proxy_address;
 | |
|   gchar			   *proxy_type;
 | |
|   gchar			   *proxy_username;
 | |
|   gchar			   *proxy_password;
 | |
|   gboolean                  supports_hostname;
 | |
|   GList			   *next_dest_ip;
 | |
|   GError                   *last_error;
 | |
| 
 | |
|   /* Async attributes */
 | |
|   GSimpleAsyncResult *simple;
 | |
|   GCancellable       *cancellable;
 | |
| };
 | |
| 
 | |
| static void
 | |
| save_userinfo (GProxyAddressEnumeratorPrivate *priv,
 | |
| 	       const gchar *proxy)
 | |
| {
 | |
|   gchar *userinfo;
 | |
| 
 | |
|   if (priv->proxy_username)
 | |
|     {
 | |
|       g_free (priv->proxy_username);
 | |
|       priv->proxy_username = NULL;
 | |
|     }
 | |
| 
 | |
|   if (priv->proxy_password)
 | |
|     {
 | |
|       g_free (priv->proxy_password);
 | |
|       priv->proxy_password = NULL;
 | |
|     }
 | |
|   
 | |
|   if (_g_uri_parse_authority (proxy, NULL, NULL, &userinfo))
 | |
|     {
 | |
|       if (userinfo)
 | |
| 	{
 | |
| 	  gchar **split = g_strsplit (userinfo, ":", 2);
 | |
| 
 | |
| 	  if (split[0] != NULL)
 | |
| 	    {
 | |
| 	      priv->proxy_username = g_uri_unescape_string (split[0], NULL);
 | |
| 	      if (split[1] != NULL)
 | |
| 		priv->proxy_password = g_uri_unescape_string (split[1], NULL);
 | |
| 	    }
 | |
| 
 | |
| 	  g_strfreev (split);
 | |
| 	  g_free (userinfo);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| next_enumerator (GProxyAddressEnumeratorPrivate *priv)
 | |
| {
 | |
|   if (priv->proxy_address)
 | |
|     return;
 | |
| 
 | |
|   while (priv->addr_enum == NULL && *priv->next_proxy)
 | |
|     {
 | |
|       GSocketConnectable *connectable = NULL;
 | |
|       const gchar *proxy_uri;
 | |
|       GProxy *proxy;
 | |
| 
 | |
|       proxy_uri = *priv->next_proxy++;
 | |
|       g_free (priv->proxy_type);
 | |
|       priv->proxy_type = g_uri_parse_scheme (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 (proxy_uri, 0, &error);
 | |
| 
 | |
| 	  if (error)
 | |
| 	    {
 | |
| 	      g_warning ("Invalid proxy URI '%s': %s",
 | |
| 			 proxy_uri, error->message);
 | |
| 	      g_error_free (error);
 | |
| 	    }
 | |
| 
 | |
| 	  save_userinfo (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)
 | |
|     {
 | |
|       GProxyResolver *resolver = g_proxy_resolver_get_default ();
 | |
|       priv->proxies = g_proxy_resolver_lookup (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;
 | |
|       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);
 | |
| 	}
 | |
| 	
 | |
| 		 		  
 | |
|       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_proxy_address_new (inetaddr, port,
 | |
| 				    priv->proxy_type,
 | |
| 				    dest_hostname, priv->dest_port,
 | |
| 				    priv->proxy_username,
 | |
| 				    priv->proxy_password);
 | |
| 
 | |
|       g_free (dest_hostname);
 | |
| 
 | |
|       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 (GProxyAddressEnumeratorPrivate *priv)
 | |
| {
 | |
|   GSimpleAsyncResult *simple = priv->simple;
 | |
| 
 | |
|   if (priv->cancellable)
 | |
|     {
 | |
|       g_object_unref (priv->cancellable);
 | |
|       priv->cancellable = NULL;
 | |
|     }
 | |
| 
 | |
|   priv->simple = NULL;
 | |
| 
 | |
|   if (priv->last_error)
 | |
|     {
 | |
|       g_simple_async_result_take_error (simple, priv->last_error);
 | |
|       priv->last_error = NULL;
 | |
|     }
 | |
| 
 | |
|   g_simple_async_result_complete (simple);
 | |
|   g_object_unref (simple);
 | |
| }
 | |
| 
 | |
| static void
 | |
| save_result (GProxyAddressEnumeratorPrivate *priv)
 | |
| {
 | |
|   GSocketAddress *result;
 | |
| 
 | |
|   if (strcmp ("direct", priv->proxy_type) == 0)
 | |
|     {
 | |
|       result = priv->proxy_address;
 | |
|       priv->proxy_address = NULL;
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       gchar *dest_hostname;
 | |
|       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);
 | |
| 	}
 | |
| 
 | |
|       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_proxy_address_new (inetaddr, port,
 | |
| 				    priv->proxy_type,
 | |
| 				    dest_hostname, priv->dest_port,
 | |
| 				    priv->proxy_username,
 | |
| 				    priv->proxy_password);
 | |
| 
 | |
|       g_free (dest_hostname);
 | |
| 
 | |
|       if (priv->supports_hostname || priv->next_dest_ip == NULL)
 | |
| 	{
 | |
| 	  g_object_unref (priv->proxy_address);
 | |
| 	  priv->proxy_address = NULL;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   g_simple_async_result_set_op_res_gpointer (priv->simple,
 | |
| 					     result,
 | |
| 					     g_object_unref);
 | |
| }
 | |
| 
 | |
| static void address_enumerate_cb (GObject      *object,
 | |
| 				  GAsyncResult *result,
 | |
| 				  gpointer	user_data);
 | |
| 
 | |
| static void
 | |
| next_proxy (GProxyAddressEnumeratorPrivate *priv)
 | |
| {
 | |
|   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,
 | |
| 						  priv->cancellable,
 | |
| 						  address_enumerate_cb,
 | |
| 						  priv);
 | |
| 	  return;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   complete_async (priv);
 | |
| }
 | |
| 
 | |
| static void
 | |
| dest_hostname_lookup_cb (GObject           *object,
 | |
| 			 GAsyncResult      *result,
 | |
| 			 gpointer           user_data)
 | |
| {
 | |
|   GProxyAddressEnumeratorPrivate *priv = user_data;
 | |
| 
 | |
|   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)
 | |
|     {
 | |
|       save_result (priv);
 | |
|       complete_async (priv);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       g_clear_object (&priv->proxy_address);
 | |
|       next_proxy (priv);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| address_enumerate_cb (GObject	   *object,
 | |
| 		      GAsyncResult *result,
 | |
| 		      gpointer	    user_data)
 | |
| {
 | |
|   GProxyAddressEnumeratorPrivate *priv = user_data;
 | |
| 
 | |
|   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,
 | |
| 					   priv->cancellable,
 | |
| 					   dest_hostname_lookup_cb,
 | |
| 					   priv);
 | |
| 	  g_object_unref (resolver);
 | |
| 	  return;
 | |
| 	}
 | |
| 
 | |
|       save_result (priv);
 | |
|       complete_async (priv);
 | |
|     }
 | |
|   else
 | |
|     next_proxy (priv);
 | |
| }
 | |
| 
 | |
| static void
 | |
| proxy_lookup_cb (GObject      *object,
 | |
| 		 GAsyncResult *result,
 | |
| 		 gpointer      user_data)
 | |
| {
 | |
|   GError *error = NULL;
 | |
|   GProxyAddressEnumeratorPrivate *priv = user_data;
 | |
|   GSimpleAsyncResult *simple = priv->simple;
 | |
| 
 | |
|   priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
 | |
| 						  result,
 | |
| 						  &error);
 | |
|   priv->next_proxy = priv->proxies;
 | |
| 
 | |
|   if (error)
 | |
|     {
 | |
|       g_simple_async_result_take_error (simple, error);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       next_enumerator (priv);
 | |
|       if (priv->addr_enum)
 | |
| 	{
 | |
| 	  g_socket_address_enumerator_next_async (priv->addr_enum,
 | |
| 						  priv->cancellable,
 | |
| 						  address_enumerate_cb,
 | |
| 						  priv);
 | |
| 	  return;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   complete_async (priv); 
 | |
| }
 | |
| 
 | |
| static void
 | |
| g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
 | |
| 				       GCancellable             *cancellable,
 | |
| 				       GAsyncReadyCallback       callback,
 | |
| 				       gpointer                  user_data)
 | |
| {
 | |
|   GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
 | |
| 
 | |
|   g_return_if_fail (priv->simple == NULL);
 | |
|   g_return_if_fail (priv->cancellable == NULL);
 | |
| 
 | |
|   priv->simple = g_simple_async_result_new (G_OBJECT (enumerator),
 | |
| 					    callback, user_data,
 | |
| 					    g_proxy_address_enumerator_next_async);
 | |
| 
 | |
|   priv->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 | |
| 
 | |
|   if (priv->proxies == NULL)
 | |
|     {
 | |
|       GProxyResolver *resolver = g_proxy_resolver_get_default ();
 | |
|       g_proxy_resolver_lookup_async (resolver,
 | |
| 				     priv->dest_uri,
 | |
| 				     cancellable,
 | |
| 				     proxy_lookup_cb,
 | |
| 				     priv);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|   if (priv->addr_enum)
 | |
|     {
 | |
|       if (priv->proxy_address)
 | |
| 	{
 | |
| 	  save_result (priv);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  g_socket_address_enumerator_next_async (priv->addr_enum,
 | |
| 						  cancellable,
 | |
| 						  address_enumerate_cb,
 | |
| 						  priv);
 | |
| 	  return;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   g_simple_async_result_complete_in_idle (priv->simple);
 | |
| 
 | |
|   g_object_unref (priv->simple);
 | |
|   priv->simple = NULL;
 | |
| 
 | |
|   if (priv->cancellable)
 | |
|     {
 | |
|       g_object_unref (priv->cancellable);
 | |
|       priv->cancellable = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static GSocketAddress *
 | |
| g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator  *enumerator,
 | |
| 					GAsyncResult              *result,
 | |
| 					GError                   **error)
 | |
| {
 | |
|   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
 | |
|   GSocketAddress *address;
 | |
| 
 | |
|   if (g_simple_async_result_propagate_error (simple, error))
 | |
|     return NULL;
 | |
| 
 | |
|   address = g_simple_async_result_get_op_res_gpointer (simple);
 | |
|   if (address)
 | |
|     g_object_ref (address);
 | |
| 
 | |
|   return address;
 | |
| }
 | |
| 
 | |
| 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_CONNECTABLE:
 | |
| 	g_value_set_object (value, priv->connectable);
 | |
| 	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:
 | |
| 	  {
 | |
| 	    const gchar *uri;
 | |
| 
 | |
| 	    g_free (priv->dest_hostname);
 | |
| 	    priv->dest_hostname = NULL;
 | |
| 	    priv->dest_port = 0;
 | |
| 
 | |
| 	    g_free (priv->dest_uri);
 | |
| 	    priv->dest_uri = NULL;
 | |
| 
 | |
| 	    uri = g_value_get_string (value);
 | |
| 
 | |
| 	    if (uri)
 | |
| 	      {
 | |
| 		GSocketConnectable *conn;
 | |
| 
 | |
| 		conn = g_network_address_parse_uri (uri, 0, NULL);
 | |
| 		if (conn)
 | |
| 		  {
 | |
| 		    guint port;
 | |
| 
 | |
| 		    priv->dest_uri = g_strdup (uri);
 | |
| 		    
 | |
| 		    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'", uri);
 | |
| 	      }
 | |
| 
 | |
| 	    break;
 | |
| 	  }
 | |
| 
 | |
|       case PROP_CONNECTABLE:
 | |
| 	  priv->connectable = g_value_dup_object (value);
 | |
| 	  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);
 | |
| 
 | |
|   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);
 | |
| 
 | |
|   if (priv->cancellable)
 | |
|     g_object_unref (priv->cancellable);
 | |
| 
 | |
|   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_TYPE_INSTANCE_GET_PRIVATE (self,
 | |
| 					    G_TYPE_PROXY_ADDRESS_ENUMERATOR,
 | |
| 					    GProxyAddressEnumeratorPrivate);
 | |
| }
 | |
| 
 | |
| 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);
 | |
| 
 | |
|   g_type_class_add_private (enumerator_class,
 | |
| 			    sizeof (GProxyAddressEnumeratorPrivate));
 | |
| 
 | |
|   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));
 | |
| 
 | |
|   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));
 | |
| }
 |