glib/gio/gnetworkmonitor.c
Christian Hergert 18a33f72db introspection: use (nullable) or (optional) instead of (allow-none)
If we have an input parameter (or return value) we need to use (nullable).
However, if it is an (inout) or (out) parameter, (optional) is sufficient.

It looks like (nullable) could be used for everything according to the
Annotation documentation, but (optional) is more specific.
2016-11-22 14:14:37 -08:00

409 lines
14 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
*/
/**
* GNetworkMonitorInterface:
* @g_iface: The parent interface.
* @network_changed: the virtual function pointer for the
* GNetworkMonitor::network-changed signal.
* @can_reach: the virtual function pointer for g_network_monitor_can_reach()
* @can_reach_async: the virtual function pointer for
* g_network_monitor_can_reach_async()
* @can_reach_finish: the virtual function pointer for
* g_network_monitor_can_reach_finish()
*
* The virtual function table for #GNetworkMonitor.
*
* 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.
*
* Returns: 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_get_network_metered:
* @monitor: the #GNetworkMonitor
*
* Checks if the network is metered.
* See #GNetworkMonitor:network-metered for more details.
*
* Returns: whether the connection is metered
*
* Since: 2.46
*/
gboolean
g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
{
gboolean metered = FALSE;
g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
return metered;
}
/**
* g_network_monitor_get_connectivity:
* @monitor: the #GNetworkMonitor
*
* Gets a more detailed networking state than
* g_network_monitor_get_network_available().
*
* If #GNetworkMonitor:network-available is %FALSE, then the
* connectivity state will be %G_NETWORK_CONNECTIVITY_LOCAL.
*
* If #GNetworkMonitor:network-available is %TRUE, then the
* connectivity state will be %G_NETWORK_CONNECTIVITY_FULL (if there
* is full Internet connectivity), %G_NETWORK_CONNECTIVITY_LIMITED (if
* the host has a default route, but appears to be unable to actually
* reach the full Internet), or %G_NETWORK_CONNECTIVITY_PORTAL (if the
* host is trapped behind a "captive portal" that requires some sort
* of login or acknowledgement before allowing full Internet access).
*
* Note that in the case of %G_NETWORK_CONNECTIVITY_LIMITED and
* %G_NETWORK_CONNECTIVITY_PORTAL, it is possible that some sites are
* reachable but others are not. In this case, applications can
* attempt to connect to remote servers, but should gracefully fall
* back to their "offline" behavior if the connection attempt fails.
*
* Return value: the network connectivity state
*
* Since: 2.44
*/
GNetworkConnectivity
g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
{
GNetworkConnectivity connectivity;
g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
return connectivity;
}
/**
* g_network_monitor_can_reach:
* @monitor: a #GNetworkMonitor
* @connectable: a #GSocketConnectable
* @cancellable: (nullable): 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().
*
* Returns: %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);
g_task_set_source_tag (task, g_network_monitor_real_can_reach_async);
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: (nullable): 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().
*
* Returns: %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
* not 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));
/**
* GNetworkMonitor:network-metered:
*
* Whether the network is considered metered. That is, whether the
* system has traffic flowing through the default connection that is
* subject to limitations set by service providers. For example, traffic
* might be billed by the amount of data transmitted, or there might be a
* quota on the amount of traffic per month. This is typical with tethered
* connections (3G and 4G) and in such situations, bandwidth intensive
* applications may wish to avoid network activity where possible if it will
* cost the user money or use up their limited quota.
*
* If more information is required about specific devices then the
* system network management API should be used instead (for example,
* NetworkManager or ConnMan).
*
* If this information is not available then no networks will be
* marked as metered.
*
* See also #GNetworkMonitor:network-available.
*
* Since: 2.46
*/
g_object_interface_install_property (iface,
g_param_spec_boolean ("network-metered",
P_("Network metered"),
P_("Whether the network is metered"),
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GNetworkMonitor:connectivity:
*
* More detailed information about the host's network connectivity.
* See g_network_monitor_get_connectivity() and
* #GNetworkConnectivity for more details.
*
* Since: 2.44
*/
g_object_interface_install_property (iface,
g_param_spec_enum ("connectivity",
P_("Network connectivity"),
P_("Level of network connectivity"),
G_TYPE_NETWORK_CONNECTIVITY,
G_NETWORK_CONNECTIVITY_FULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}