glib/gio/gnetworkmonitor.c
2014-01-31 14:31:55 +01:00

285 lines
9.8 KiB
C

/* GIO - GLib Input, Output and Streaming Library
*
* Copyright 2011 Red Hat, Inc
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "glib.h"
#include "glibintl.h"
#include "gnetworkmonitor.h"
#include "ginetaddress.h"
#include "ginetsocketaddress.h"
#include "ginitable.h"
#include "gioenumtypes.h"
#include "giomodule-priv.h"
#include "gtask.h"
/**
* SECTION:gnetworkmonitor
* @title: GNetworkMonitor
* @short_description: Network status monitor
* @include: gio/gio.h
*
* #GNetworkMonitor provides an easy-to-use cross-platform API
* for monitoring network connectivity. On Linux, the implementation
* is based on the kernel's netlink interface.
*/
/**
* GNetworkMonitor:
*
* #GNetworkMonitor monitors the status of network connections and
* indicates when a possibly-user-visible change has occurred.
*
* Since: 2.32
*/
G_DEFINE_INTERFACE_WITH_CODE (GNetworkMonitor, g_network_monitor, G_TYPE_OBJECT,
g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_INITABLE);)
enum {
NETWORK_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/**
* g_network_monitor_get_default:
*
* Gets the default #GNetworkMonitor for the system.
*
* Returns: (transfer none): a #GNetworkMonitor
*
* Since: 2.32
*/
GNetworkMonitor *
g_network_monitor_get_default (void)
{
return _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
"GIO_USE_NETWORK_MONITOR",
NULL);
}
/**
* g_network_monitor_get_network_available:
* @monitor: the #GNetworkMonitor
*
* Checks if the network is available. "Available" here means that the
* system has a default route available for at least one of IPv4 or
* IPv6. It does not necessarily imply that the public Internet is
* reachable. See #GNetworkMonitor:network-available for more details.
*
* Return value: whether the network is available
*
* Since: 2.32
*/
gboolean
g_network_monitor_get_network_available (GNetworkMonitor *monitor)
{
gboolean available = FALSE;
g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
return available;
}
/**
* g_network_monitor_can_reach:
* @monitor: a #GNetworkMonitor
* @connectable: a #GSocketConnectable
* @cancellable: (allow-none): a #GCancellable, or %NULL
* @error: return location for a #GError, or %NULL
*
* Attempts to determine whether or not the host pointed to by
* @connectable can be reached, without actually trying to connect to
* it.
*
* This may return %TRUE even when #GNetworkMonitor:network-available
* is %FALSE, if, for example, @monitor can determine that
* @connectable refers to a host on a local network.
*
* If @monitor believes that an attempt to connect to @connectable
* will succeed, it will return %TRUE. Otherwise, it will return
* %FALSE and set @error to an appropriate error (such as
* %G_IO_ERROR_HOST_UNREACHABLE).
*
* Note that although this does not attempt to connect to
* @connectable, it may still block for a brief period of time (eg,
* trying to do multicast DNS on the local network), so if you do not
* want to block, you should use g_network_monitor_can_reach_async().
*
* Return value: %TRUE if @connectable is reachable, %FALSE if not.
*
* Since: 2.32
*/
gboolean
g_network_monitor_can_reach (GNetworkMonitor *monitor,
GSocketConnectable *connectable,
GCancellable *cancellable,
GError **error)
{
GNetworkMonitorInterface *iface;
iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
return iface->can_reach (monitor, connectable, cancellable, error);
}
static void
g_network_monitor_real_can_reach_async (GNetworkMonitor *monitor,
GSocketConnectable *connectable,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
GError *error = NULL;
task = g_task_new (monitor, cancellable, callback, user_data);
if (g_network_monitor_can_reach (monitor, connectable, cancellable, &error))
g_task_return_boolean (task, TRUE);
else
g_task_return_error (task, error);
g_object_unref (task);
}
/**
* g_network_monitor_can_reach_async:
* @monitor: a #GNetworkMonitor
* @connectable: a #GSocketConnectable
* @cancellable: (allow-none): a #GCancellable, or %NULL
* @callback: (scope async): a #GAsyncReadyCallback to call when the
* request is satisfied
* @user_data: (closure): the data to pass to callback function
*
* Asynchronously attempts to determine whether or not the host
* pointed to by @connectable can be reached, without actually
* trying to connect to it.
*
* For more details, see g_network_monitor_can_reach().
*
* When the operation is finished, @callback will be called.
* You can then call g_network_monitor_can_reach_finish()
* to get the result of the operation.
*/
void
g_network_monitor_can_reach_async (GNetworkMonitor *monitor,
GSocketConnectable *connectable,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GNetworkMonitorInterface *iface;
iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
}
static gboolean
g_network_monitor_real_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);
}
/**
* g_network_monitor_can_reach_finish:
* @monitor: a #GNetworkMonitor
* @result: a #GAsyncResult
* @error: return location for errors, or %NULL
*
* Finishes an async network connectivity test.
* See g_network_monitor_can_reach_async().
*
* Return value: %TRUE if network is reachable, %FALSE if not.
*/
gboolean
g_network_monitor_can_reach_finish (GNetworkMonitor *monitor,
GAsyncResult *result,
GError **error)
{
GNetworkMonitorInterface *iface;
iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
return iface->can_reach_finish (monitor, result, error);
}
static void
g_network_monitor_default_init (GNetworkMonitorInterface *iface)
{
iface->can_reach_async = g_network_monitor_real_can_reach_async;
iface->can_reach_finish = g_network_monitor_real_can_reach_finish;
/**
* GNetworkMonitor::network-changed:
* @monitor: a #GNetworkMonitor
* @available: the current value of #GNetworkMonitor:network-available
*
* Emitted when the network configuration changes. If @available is
* %TRUE, then some hosts may be reachable that were not reachable
* before, while others that were reachable before may no longer be
* reachable. If @available is %FALSE, then no remote hosts are
* reachable.
*
* Since: 2.32
*/
signals[NETWORK_CHANGED] =
g_signal_new (I_("network-changed"),
G_TYPE_NETWORK_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GNetworkMonitorInterface, network_changed),
NULL, NULL,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1,
G_TYPE_BOOLEAN);
/**
* GNetworkMonitor:network-available:
*
* Whether the network is considered available. That is, whether the
* system has a default route for at least one of IPv4 or IPv6.
*
* Real-world networks are of course much more complicated than
* this; the machine may be connected to a wifi hotspot that
* requires payment before allowing traffic through, or may be
* connected to a functioning router that has lost its own upstream
* connectivity. Some hosts might only be accessible when a VPN is
* active. Other hosts might only be accessible when the VPN is
* <emphasis>not</emphasis> active. Thus, it is best to use
* g_network_monitor_can_reach() or
* g_network_monitor_can_reach_async() to test for reachability on a
* host-by-host basis. (On the other hand, when the property is
* %FALSE, the application can reasonably expect that no remote
* hosts at all are reachable, and should indicate this to the user
* in its UI.)
*
* See also #GNetworkMonitor::network-changed.
*
* Since: 2.32
*/
g_object_interface_install_property (iface,
g_param_spec_boolean ("network-available",
P_("Network available"),
P_("Whether the network is available"),
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}