mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
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
This commit is contained in:
parent
4ca3d80ff3
commit
9670d06a66
@ -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);
|
||||
@ -158,17 +159,37 @@ g_network_monitor_base_class_init (GNetworkMonitorBaseClass *monitor_class)
|
||||
g_object_class_override_property (gobject_class, PROP_NETWORK_AVAILABLE, "network-available");
|
||||
}
|
||||
|
||||
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);
|
||||
@ -224,10 +235,93 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user