gio: fix error handling in async case of GProxyAddressEnumerator
authorDan Winship <danw@gnome.org>
Sun, 22 Apr 2012 19:20:14 +0000 (15:20 -0400)
committerDan Winship <danw@gnome.org>
Sun, 22 Apr 2012 19:23:40 +0000 (15:23 -0400)
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.

gio/gproxyaddressenumerator.c

index b7bc04d..e4167db 100644 (file)
@@ -69,6 +69,7 @@ struct _GProxyAddressEnumeratorPrivate
   gchar                           *proxy_password;
   gboolean                  supports_hostname;
   GList                           *next_dest_ip;
+  GError                   *last_error;
 
   /* Async attributes */
   GSimpleAsyncResult *simple;
@@ -316,6 +317,13 @@ complete_async (GProxyAddressEnumeratorPrivate *priv)
     }
 
   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);
 }
@@ -380,24 +388,60 @@ save_result (GProxyAddressEnumeratorPrivate *priv)
                                             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)
 {
-  GError *error = NULL;
   GProxyAddressEnumeratorPrivate *priv = user_data;
-  GSimpleAsyncResult *simple = priv->simple;
 
+  g_clear_error (&priv->last_error);
   priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
                                                     result,
-                                                    &error);
+                                                    &priv->last_error);
   if (priv->dest_ips)
-    save_result (priv);
+    {
+      save_result (priv);
+      complete_async (priv);
+    }
   else
-    g_simple_async_result_take_error (simple, error);
-
-  complete_async (priv); 
+    {
+      g_clear_object (&priv->proxy_address);
+      next_proxy (priv);
+    }
 }
 
 static void
@@ -405,14 +449,13 @@ address_enumerate_cb (GObject        *object,
                      GAsyncResult *result,
                      gpointer      user_data)
 {
-  GError *error = NULL;
   GProxyAddressEnumeratorPrivate *priv = user_data;
-  GSimpleAsyncResult *simple = priv->simple;
 
+  g_clear_error (&priv->last_error);
   priv->proxy_address =
     g_socket_address_enumerator_next_finish (priv->addr_enum,
                                             result,
-                                            &error);
+                                            &priv->last_error);
   if (priv->proxy_address)
     {
       if (!priv->supports_hostname && !priv->dest_ips)
@@ -429,34 +472,10 @@ address_enumerate_cb (GObject        *object,
        }
 
       save_result (priv);
+      complete_async (priv);
     }
-  else 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;
-       }
-    }
-
-  if (error)
-    g_simple_async_result_take_error (simple, error);
-
-  complete_async (priv); 
+  else
+    next_proxy (priv);
 }
 
 static void
@@ -672,6 +691,8 @@ g_proxy_address_enumerator_finalize (GObject *object)
   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);
 }