[glib] GNetworkMonitorBase: implement can_reach_async
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] GNetworkMonitorBase: implement can_reach_async
- Date: Wed, 20 Feb 2013 12:34:35 +0000 (UTC)
commit 9670d06a660cd27a30a339798f4af1ce4c5abb29
Author: Dan Winship <danw gnome org>
Date: Tue Feb 19 16:12:30 2013 -0500
GNetworkMonitorBase: implement can_reach_async
Implement the g_network_monitor_can_reach_async() rather than falling
back to the default implementation, which calls the sync version (not
in a thread).
https://bugzilla.gnome.org/show_bug.cgi?id=694181
gio/gnetworkmonitorbase.c | 130 ++++++++++++++++++++++++++++++++++++++------
1 files changed, 112 insertions(+), 18 deletions(-)
---
diff --git a/gio/gnetworkmonitorbase.c b/gio/gnetworkmonitorbase.c
index 5baf5fd..f363e02 100644
--- a/gio/gnetworkmonitorbase.c
+++ b/gio/gnetworkmonitorbase.c
@@ -30,6 +30,7 @@
#include "gnetworkmonitor.h"
#include "gsocketaddressenumerator.h"
#include "gsocketconnectable.h"
+#include "gtask.h"
#include "glibintl.h"
static void g_network_monitor_base_iface_init (GNetworkMonitorInterface *iface);
@@ -159,16 +160,36 @@ g_network_monitor_base_class_init (GNetworkMonitorBaseClass *monitor_class)
}
static gboolean
+g_network_monitor_base_can_reach_sockaddr (GNetworkMonitorBase *base,
+ GSocketAddress *sockaddr)
+{
+ GInetAddress *iaddr;
+ int i;
+
+ if (!G_IS_INET_SOCKET_ADDRESS (sockaddr))
+ return FALSE;
+
+ iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (sockaddr));
+ for (i = 0; i < base->priv->networks->len; i++)
+ {
+ if (g_inet_address_mask_matches (base->priv->networks->pdata[i], iaddr))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
GSocketConnectable *connectable,
GCancellable *cancellable,
GError **error)
{
- GNetworkMonitorBasePrivate *priv = G_NETWORK_MONITOR_BASE (monitor)->priv;
+ GNetworkMonitorBase *base = G_NETWORK_MONITOR_BASE (monitor);
GSocketAddressEnumerator *enumerator;
GSocketAddress *addr;
- if (priv->networks->len == 0)
+ if (base->priv->networks->len == 0)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
_("Network unreachable"));
@@ -184,8 +205,8 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
return FALSE;
}
- if (priv->have_ipv4_default_route &&
- priv->have_ipv6_default_route)
+ if (base->priv->have_ipv4_default_route &&
+ base->priv->have_ipv6_default_route)
{
g_object_unref (enumerator);
g_object_unref (addr);
@@ -194,21 +215,11 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
while (addr)
{
- if (G_IS_INET_SOCKET_ADDRESS (addr))
+ if (g_network_monitor_base_can_reach_sockaddr (base, addr))
{
- GInetAddress *iaddr;
- int i;
-
- iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
- for (i = 0; i < priv->networks->len; i++)
- {
- if (g_inet_address_mask_matches (priv->networks->pdata[i], iaddr))
- {
- g_object_unref (addr);
- g_object_unref (enumerator);
- return TRUE;
- }
- }
+ g_object_unref (addr);
+ g_object_unref (enumerator);
+ return TRUE;
}
g_object_unref (addr);
@@ -225,9 +236,92 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
}
static void
+can_reach_async_got_address (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSocketAddressEnumerator *enumerator = G_SOCKET_ADDRESS_ENUMERATOR (object);
+ GTask *task = user_data;
+ GNetworkMonitorBase *base = g_task_get_source_object (task);
+ GSocketAddress *addr;
+ GError *error = NULL;
+
+ addr = g_socket_address_enumerator_next_finish (enumerator, result, &error);
+ if (!addr)
+ {
+ if (error)
+ {
+ /* Either the user cancelled, or DNS resolution failed */
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+ else
+ {
+ /* Resolved all addresses, none matched */
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
+ _("Host unreachable"));
+ g_object_unref (task);
+ return;
+ }
+ }
+
+ if (g_network_monitor_base_can_reach_sockaddr (base, addr))
+ {
+ g_object_unref (addr);
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+ }
+ g_object_unref (addr);
+
+ g_socket_address_enumerator_next_async (enumerator,
+ g_task_get_cancellable (task),
+ can_reach_async_got_address, task);
+}
+
+static void
+g_network_monitor_base_can_reach_async (GNetworkMonitor *monitor,
+ GSocketConnectable *connectable,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ GSocketAddressEnumerator *enumerator;
+
+ task = g_task_new (monitor, cancellable, callback, user_data);
+
+ if (G_NETWORK_MONITOR_BASE (monitor)->priv->networks->len == 0)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
+ _("Network unreachable"));
+ g_object_unref (task);
+ return;
+ }
+
+ enumerator = g_socket_connectable_proxy_enumerate (connectable);
+ g_socket_address_enumerator_next_async (enumerator, cancellable,
+ can_reach_async_got_address, task);
+ g_object_unref (enumerator);
+}
+
+static gboolean
+g_network_monitor_base_can_reach_finish (GNetworkMonitor *monitor,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
g_network_monitor_base_iface_init (GNetworkMonitorInterface *monitor_iface)
{
monitor_iface->can_reach = g_network_monitor_base_can_reach;
+ monitor_iface->can_reach_async = g_network_monitor_base_can_reach_async;
+ monitor_iface->can_reach_finish = g_network_monitor_base_can_reach_finish;
network_changed_signal = g_signal_lookup ("network-changed", G_TYPE_NETWORK_MONITOR);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]