mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56: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 "gnetworkmonitor.h"
|
||||||
#include "gsocketaddressenumerator.h"
|
#include "gsocketaddressenumerator.h"
|
||||||
#include "gsocketconnectable.h"
|
#include "gsocketconnectable.h"
|
||||||
|
#include "gtask.h"
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
static void g_network_monitor_base_iface_init (GNetworkMonitorInterface *iface);
|
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");
|
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
|
static gboolean
|
||||||
g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
|
g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
|
||||||
GSocketConnectable *connectable,
|
GSocketConnectable *connectable,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GNetworkMonitorBasePrivate *priv = G_NETWORK_MONITOR_BASE (monitor)->priv;
|
GNetworkMonitorBase *base = G_NETWORK_MONITOR_BASE (monitor);
|
||||||
GSocketAddressEnumerator *enumerator;
|
GSocketAddressEnumerator *enumerator;
|
||||||
GSocketAddress *addr;
|
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,
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
|
||||||
_("Network unreachable"));
|
_("Network unreachable"));
|
||||||
@ -184,8 +205,8 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->have_ipv4_default_route &&
|
if (base->priv->have_ipv4_default_route &&
|
||||||
priv->have_ipv6_default_route)
|
base->priv->have_ipv6_default_route)
|
||||||
{
|
{
|
||||||
g_object_unref (enumerator);
|
g_object_unref (enumerator);
|
||||||
g_object_unref (addr);
|
g_object_unref (addr);
|
||||||
@ -194,22 +215,12 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
|
|||||||
|
|
||||||
while (addr)
|
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 (addr);
|
||||||
g_object_unref (enumerator);
|
g_object_unref (enumerator);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (addr);
|
g_object_unref (addr);
|
||||||
addr = g_socket_address_enumerator_next (enumerator, cancellable, error);
|
addr = g_socket_address_enumerator_next (enumerator, cancellable, error);
|
||||||
@ -224,10 +235,93 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
|
|||||||
return FALSE;
|
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
|
static void
|
||||||
g_network_monitor_base_iface_init (GNetworkMonitorInterface *monitor_iface)
|
g_network_monitor_base_iface_init (GNetworkMonitorInterface *monitor_iface)
|
||||||
{
|
{
|
||||||
monitor_iface->can_reach = g_network_monitor_base_can_reach;
|
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);
|
network_changed_signal = g_signal_lookup ("network-changed", G_TYPE_NETWORK_MONITOR);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user