LCOV - code coverage report
Current view: top level - gio - gnetworkmonitor.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 64.3 % 56 36
Test Date: 2026-09-08 05:12:32 Functions: 63.6 % 11 7
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GIO - GLib Input, Output and Streaming Library
       2                 :             :  *
       3                 :             :  * Copyright 2011 Red Hat, Inc
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :             :  *
       7                 :             :  * This library is free software; you can redistribute it and/or
       8                 :             :  * modify it under the terms of the GNU Lesser General Public
       9                 :             :  * License as published by the Free Software Foundation; either
      10                 :             :  * version 2.1 of the License, or (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This library is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :  * Lesser General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU Lesser General
      18                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  */
      20                 :             : 
      21                 :             : #include "config.h"
      22                 :             : #include "glib.h"
      23                 :             : #include "glibintl.h"
      24                 :             : 
      25                 :             : #include "gnetworkmonitor.h"
      26                 :             : #include "ginetaddress.h"
      27                 :             : #include "ginetsocketaddress.h"
      28                 :             : #include "ginitable.h"
      29                 :             : #include "gioenumtypes.h"
      30                 :             : #include "giomodule-priv.h"
      31                 :             : #include "gtask.h"
      32                 :             : 
      33                 :             : /**
      34                 :             :  * GNetworkMonitor:
      35                 :             :  *
      36                 :             :  * `GNetworkMonitor` provides an easy-to-use cross-platform API
      37                 :             :  * for monitoring network connectivity. On Linux, the available
      38                 :             :  * implementations are based on the kernel's netlink interface and
      39                 :             :  * on NetworkManager.
      40                 :             :  *
      41                 :             :  * There is also an implementation for use inside Flatpak sandboxes.
      42                 :             :  *
      43                 :             :  * Since: 2.32
      44                 :             :  */
      45                 :             : 
      46                 :             : /**
      47                 :             :  * GNetworkMonitorInterface:
      48                 :             :  * @g_iface: The parent interface.
      49                 :             :  * @network_changed: the virtual function pointer for the
      50                 :             :  *  GNetworkMonitor::network-changed signal.
      51                 :             :  * @can_reach: the virtual function pointer for g_network_monitor_can_reach()
      52                 :             :  * @can_reach_async: the virtual function pointer for
      53                 :             :  *  g_network_monitor_can_reach_async()
      54                 :             :  * @can_reach_finish: the virtual function pointer for
      55                 :             :  *  g_network_monitor_can_reach_finish()
      56                 :             :  *
      57                 :             :  * The virtual function table for #GNetworkMonitor.
      58                 :             :  *
      59                 :             :  * Since: 2.32
      60                 :             :  */
      61                 :             : 
      62                 :        2619 : G_DEFINE_INTERFACE_WITH_CODE (GNetworkMonitor, g_network_monitor, G_TYPE_OBJECT,
      63                 :          66 :                               g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_INITABLE))
      64                 :             : 
      65                 :             : 
      66                 :             : enum {
      67                 :             :   NETWORK_CHANGED,
      68                 :             :   LAST_SIGNAL
      69                 :             : };
      70                 :             : 
      71                 :             : static guint signals[LAST_SIGNAL] = { 0 };
      72                 :             : static GNetworkMonitor *network_monitor_default_singleton = NULL;  /* (owned) (atomic) */
      73                 :             : 
      74                 :             : /**
      75                 :             :  * g_network_monitor_get_default:
      76                 :             :  *
      77                 :             :  * Gets the default #GNetworkMonitor for the system.
      78                 :             :  *
      79                 :             :  * Some implementations complete their initialization asynchronously:
      80                 :             :  * properties such as #GNetworkMonitor:network-available may start at their
      81                 :             :  * default values and update shortly afterwards, with notify emissions, once
      82                 :             :  * the state is resolved from the thread-default main context of this first
      83                 :             :  * call.
      84                 :             :  *
      85                 :             :  * Returns: (not nullable) (transfer none): a #GNetworkMonitor, which will be
      86                 :             :  *     a dummy object if no network monitor is available
      87                 :             :  *
      88                 :             :  * Since: 2.32
      89                 :             :  */
      90                 :             : GNetworkMonitor *
      91                 :          46 : g_network_monitor_get_default (void)
      92                 :             : {
      93                 :          46 :   if (g_once_init_enter_pointer (&network_monitor_default_singleton))
      94                 :             :     {
      95                 :             :       GNetworkMonitor *singleton;
      96                 :             : 
      97                 :          44 :       singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
      98                 :             :                                             "GIO_USE_NETWORK_MONITOR",
      99                 :             :                                             NULL);
     100                 :             : 
     101                 :          44 :       g_once_init_leave_pointer (&network_monitor_default_singleton, singleton);
     102                 :          22 :     }
     103                 :             : 
     104                 :          46 :   return network_monitor_default_singleton;
     105                 :             : }
     106                 :             : 
     107                 :             : /**
     108                 :             :  * g_network_monitor_get_network_available:
     109                 :             :  * @monitor: the #GNetworkMonitor
     110                 :             :  *
     111                 :             :  * Checks if the network is available. "Available" here means that the
     112                 :             :  * system has a default route available for at least one of IPv4 or
     113                 :             :  * IPv6. It does not necessarily imply that the public Internet is
     114                 :             :  * reachable. See #GNetworkMonitor:network-available for more details.
     115                 :             :  *
     116                 :             :  * Returns: whether the network is available
     117                 :             :  *
     118                 :             :  * Since: 2.32
     119                 :             :  */
     120                 :             : gboolean
     121                 :          50 : g_network_monitor_get_network_available (GNetworkMonitor *monitor)
     122                 :             : {
     123                 :          50 :   gboolean available = FALSE;
     124                 :             : 
     125                 :          50 :   g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
     126                 :          50 :   return available;
     127                 :             : }
     128                 :             : 
     129                 :             : /**
     130                 :             :  * g_network_monitor_get_network_metered:
     131                 :             :  * @monitor: the #GNetworkMonitor
     132                 :             :  *
     133                 :             :  * Checks if the network is metered.
     134                 :             :  * See #GNetworkMonitor:network-metered for more details.
     135                 :             :  *
     136                 :             :  * Returns: whether the connection is metered
     137                 :             :  *
     138                 :             :  * Since: 2.46
     139                 :             :  */
     140                 :             : gboolean
     141                 :           0 : g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
     142                 :             : {
     143                 :           0 :   gboolean metered = FALSE;
     144                 :             : 
     145                 :           0 :   g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
     146                 :           0 :   return metered;
     147                 :             : }
     148                 :             : 
     149                 :             : /**
     150                 :             :  * g_network_monitor_get_connectivity:
     151                 :             :  * @monitor: the #GNetworkMonitor
     152                 :             :  *
     153                 :             :  * Gets a more detailed networking state than
     154                 :             :  * g_network_monitor_get_network_available().
     155                 :             :  *
     156                 :             :  * If #GNetworkMonitor:network-available is %FALSE, then the
     157                 :             :  * connectivity state will be %G_NETWORK_CONNECTIVITY_LOCAL.
     158                 :             :  *
     159                 :             :  * If #GNetworkMonitor:network-available is %TRUE, then the
     160                 :             :  * connectivity state will be %G_NETWORK_CONNECTIVITY_FULL (if there
     161                 :             :  * is full Internet connectivity), %G_NETWORK_CONNECTIVITY_LIMITED (if
     162                 :             :  * the host has a default route, but appears to be unable to actually
     163                 :             :  * reach the full Internet), or %G_NETWORK_CONNECTIVITY_PORTAL (if the
     164                 :             :  * host is trapped behind a "captive portal" that requires some sort
     165                 :             :  * of login or acknowledgement before allowing full Internet access).
     166                 :             :  *
     167                 :             :  * Note that in the case of %G_NETWORK_CONNECTIVITY_LIMITED and
     168                 :             :  * %G_NETWORK_CONNECTIVITY_PORTAL, it is possible that some sites are
     169                 :             :  * reachable but others are not. In this case, applications can
     170                 :             :  * attempt to connect to remote servers, but should gracefully fall
     171                 :             :  * back to their "offline" behavior if the connection attempt fails.
     172                 :             :  *
     173                 :             :  * Return value: the network connectivity state
     174                 :             :  *
     175                 :             :  * Since: 2.44
     176                 :             :  */
     177                 :             : GNetworkConnectivity
     178                 :           0 : g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
     179                 :             : {
     180                 :             :   GNetworkConnectivity connectivity;
     181                 :             : 
     182                 :           0 :   g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
     183                 :             : 
     184                 :           0 :   return connectivity;
     185                 :             : }
     186                 :             : 
     187                 :             : /**
     188                 :             :  * g_network_monitor_can_reach:
     189                 :             :  * @monitor: a #GNetworkMonitor
     190                 :             :  * @connectable: a #GSocketConnectable
     191                 :             :  * @cancellable: (nullable): a #GCancellable, or %NULL
     192                 :             :  * @error: return location for a #GError, or %NULL
     193                 :             :  *
     194                 :             :  * Attempts to determine whether or not the host pointed to by
     195                 :             :  * @connectable can be reached, without actually trying to connect to
     196                 :             :  * it.
     197                 :             :  *
     198                 :             :  * This may return %TRUE even when #GNetworkMonitor:network-available
     199                 :             :  * is %FALSE, if, for example, @monitor can determine that
     200                 :             :  * @connectable refers to a host on a local network.
     201                 :             :  *
     202                 :             :  * If @monitor believes that an attempt to connect to @connectable
     203                 :             :  * will succeed, it will return %TRUE. Otherwise, it will return
     204                 :             :  * %FALSE and set @error to an appropriate error (such as
     205                 :             :  * %G_IO_ERROR_HOST_UNREACHABLE).
     206                 :             :  *
     207                 :             :  * Note that although this does not attempt to connect to
     208                 :             :  * @connectable, it may still block for a brief period of time (eg,
     209                 :             :  * trying to do multicast DNS on the local network), so if you do not
     210                 :             :  * want to block, you should use g_network_monitor_can_reach_async().
     211                 :             :  *
     212                 :             :  * Returns: %TRUE if @connectable is reachable, %FALSE if not.
     213                 :             :  *
     214                 :             :  * Since: 2.32
     215                 :             :  */
     216                 :             : gboolean
     217                 :         496 : g_network_monitor_can_reach (GNetworkMonitor     *monitor,
     218                 :             :                              GSocketConnectable  *connectable,
     219                 :             :                              GCancellable        *cancellable,
     220                 :             :                              GError             **error)
     221                 :             : {
     222                 :             :   GNetworkMonitorInterface *iface;
     223                 :             : 
     224                 :         496 :   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
     225                 :         496 :   return iface->can_reach (monitor, connectable, cancellable, error);
     226                 :             : }
     227                 :             : 
     228                 :             : static void
     229                 :           0 : g_network_monitor_real_can_reach_async (GNetworkMonitor     *monitor,
     230                 :             :                                         GSocketConnectable  *connectable,
     231                 :             :                                         GCancellable        *cancellable,
     232                 :             :                                         GAsyncReadyCallback  callback,
     233                 :             :                                         gpointer             user_data)
     234                 :             : {
     235                 :             :   GTask *task;
     236                 :           0 :   GError *error = NULL;
     237                 :             : 
     238                 :           0 :   task = g_task_new (monitor, cancellable, callback, user_data);
     239                 :           0 :   g_task_set_source_tag (task, g_network_monitor_real_can_reach_async);
     240                 :             : 
     241                 :           0 :   if (g_network_monitor_can_reach (monitor, connectable, cancellable, &error))
     242                 :           0 :     g_task_return_boolean (task, TRUE);
     243                 :             :   else
     244                 :           0 :     g_task_return_error (task, error);
     245                 :           0 :   g_object_unref (task);
     246                 :           0 : }
     247                 :             : 
     248                 :             : /**
     249                 :             :  * g_network_monitor_can_reach_async:
     250                 :             :  * @monitor: a #GNetworkMonitor
     251                 :             :  * @connectable: a #GSocketConnectable
     252                 :             :  * @cancellable: (nullable): a #GCancellable, or %NULL
     253                 :             :  * @callback: (scope async): a #GAsyncReadyCallback
     254                 :             :  *     to call when the request is satisfied
     255                 :             :  * @user_data: the data to pass to callback function
     256                 :             :  *
     257                 :             :  * Asynchronously attempts to determine whether or not the host
     258                 :             :  * pointed to by @connectable can be reached, without actually
     259                 :             :  * trying to connect to it.
     260                 :             :  *
     261                 :             :  * For more details, see g_network_monitor_can_reach().
     262                 :             :  *
     263                 :             :  * When the operation is finished, @callback will be called.
     264                 :             :  * You can then call g_network_monitor_can_reach_finish()
     265                 :             :  * to get the result of the operation.
     266                 :             :  */
     267                 :             : void
     268                 :         496 : g_network_monitor_can_reach_async (GNetworkMonitor     *monitor,
     269                 :             :                                    GSocketConnectable  *connectable,
     270                 :             :                                    GCancellable        *cancellable,
     271                 :             :                                    GAsyncReadyCallback  callback,
     272                 :             :                                    gpointer             user_data)
     273                 :             : {
     274                 :             :   GNetworkMonitorInterface *iface;
     275                 :             : 
     276                 :         496 :   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
     277                 :         496 :   iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
     278                 :         496 : }
     279                 :             : 
     280                 :             : static gboolean
     281                 :           0 : g_network_monitor_real_can_reach_finish (GNetworkMonitor  *monitor,
     282                 :             :                                          GAsyncResult     *result,
     283                 :             :                                          GError          **error)
     284                 :             : {
     285                 :           0 :   g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE);
     286                 :             : 
     287                 :           0 :   return g_task_propagate_boolean (G_TASK (result), error);
     288                 :           0 : }
     289                 :             : 
     290                 :             : /**
     291                 :             :  * g_network_monitor_can_reach_finish:
     292                 :             :  * @monitor: a #GNetworkMonitor
     293                 :             :  * @result: a #GAsyncResult
     294                 :             :  * @error: return location for errors, or %NULL
     295                 :             :  *
     296                 :             :  * Finishes an async network connectivity test.
     297                 :             :  * See g_network_monitor_can_reach_async().
     298                 :             :  *
     299                 :             :  * Returns: %TRUE if network is reachable, %FALSE if not.
     300                 :             :  */
     301                 :             : gboolean
     302                 :         496 : g_network_monitor_can_reach_finish (GNetworkMonitor     *monitor,
     303                 :             :                                     GAsyncResult        *result,
     304                 :             :                                     GError             **error)
     305                 :             : {
     306                 :             :   GNetworkMonitorInterface *iface;
     307                 :             : 
     308                 :         496 :   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
     309                 :         496 :   return iface->can_reach_finish (monitor, result, error);
     310                 :             : }
     311                 :             : 
     312                 :             : static void
     313                 :          46 : g_network_monitor_default_init (GNetworkMonitorInterface *iface)
     314                 :             : {
     315                 :          46 :   iface->can_reach_async  = g_network_monitor_real_can_reach_async;
     316                 :          46 :   iface->can_reach_finish = g_network_monitor_real_can_reach_finish;
     317                 :             : 
     318                 :             :   /**
     319                 :             :    * GNetworkMonitor::network-changed:
     320                 :             :    * @monitor: a #GNetworkMonitor
     321                 :             :    * @network_available: the current value of #GNetworkMonitor:network-available
     322                 :             :    *
     323                 :             :    * Emitted when the network configuration changes.
     324                 :             :    *
     325                 :             :    * Since: 2.32
     326                 :             :    */
     327                 :          46 :   signals[NETWORK_CHANGED] =
     328                 :          69 :     g_signal_new (I_("network-changed"),
     329                 :          23 :                   G_TYPE_NETWORK_MONITOR,
     330                 :             :                   G_SIGNAL_RUN_LAST,
     331                 :             :                   G_STRUCT_OFFSET (GNetworkMonitorInterface, network_changed),
     332                 :             :                   NULL, NULL,
     333                 :             :                   NULL,
     334                 :             :                   G_TYPE_NONE, 1,
     335                 :             :                   G_TYPE_BOOLEAN);
     336                 :             : 
     337                 :             :   /**
     338                 :             :    * GNetworkMonitor:network-available:
     339                 :             :    *
     340                 :             :    * Whether the network is considered available. That is, whether the
     341                 :             :    * system has a default route for at least one of IPv4 or IPv6.
     342                 :             :    *
     343                 :             :    * Real-world networks are of course much more complicated than
     344                 :             :    * this; the machine may be connected to a wifi hotspot that
     345                 :             :    * requires payment before allowing traffic through, or may be
     346                 :             :    * connected to a functioning router that has lost its own upstream
     347                 :             :    * connectivity. Some hosts might only be accessible when a VPN is
     348                 :             :    * active. Other hosts might only be accessible when the VPN is
     349                 :             :    * not active. Thus, it is best to use g_network_monitor_can_reach()
     350                 :             :    * or g_network_monitor_can_reach_async() to test for reachability
     351                 :             :    * on a host-by-host basis. (On the other hand, when the property is
     352                 :             :    * %FALSE, the application can reasonably expect that no remote
     353                 :             :    * hosts at all are reachable, and should indicate this to the user
     354                 :             :    * in its UI.)
     355                 :             :    *
     356                 :             :    * See also #GNetworkMonitor::network-changed.
     357                 :             :    *
     358                 :             :    * Since: 2.32
     359                 :             :    */
     360                 :          69 :   g_object_interface_install_property (iface,
     361                 :          23 :                                        g_param_spec_boolean ("network-available", NULL, NULL,
     362                 :             :                                                              FALSE,
     363                 :             :                                                              G_PARAM_READABLE |
     364                 :             :                                                              G_PARAM_STATIC_STRINGS));
     365                 :             : 
     366                 :             :   /**
     367                 :             :    * GNetworkMonitor:network-metered:
     368                 :             :    *
     369                 :             :    * Whether the network is considered metered.
     370                 :             :    *
     371                 :             :    * That is, whether the
     372                 :             :    * system has traffic flowing through the default connection that is
     373                 :             :    * subject to limitations set by service providers. For example, traffic
     374                 :             :    * might be billed by the amount of data transmitted, or there might be a
     375                 :             :    * quota on the amount of traffic per month. This is typical with tethered
     376                 :             :    * connections (3G and 4G) and in such situations, bandwidth intensive
     377                 :             :    * applications may wish to avoid network activity where possible if it will
     378                 :             :    * cost the user money or use up their limited quota. Anything more than a
     379                 :             :    * few hundreds of kilobytes of data usage per hour should be avoided without
     380                 :             :    * asking permission from the user.
     381                 :             :    *
     382                 :             :    * If more information is required about specific devices then the
     383                 :             :    * system network management API should be used instead (for example,
     384                 :             :    * NetworkManager or ConnMan).
     385                 :             :    *
     386                 :             :    * If this information is not available then no networks will be
     387                 :             :    * marked as metered.
     388                 :             :    *
     389                 :             :    * See also #GNetworkMonitor:network-available.
     390                 :             :    *
     391                 :             :    * Since: 2.46
     392                 :             :    */
     393                 :          69 :   g_object_interface_install_property (iface,
     394                 :          23 :                                        g_param_spec_boolean ("network-metered", NULL, NULL,
     395                 :             :                                                              FALSE,
     396                 :             :                                                              G_PARAM_READABLE |
     397                 :             :                                                              G_PARAM_STATIC_STRINGS));
     398                 :             : 
     399                 :             :   /**
     400                 :             :    * GNetworkMonitor:connectivity:
     401                 :             :    *
     402                 :             :    * More detailed information about the host's network connectivity.
     403                 :             :    * See g_network_monitor_get_connectivity() and
     404                 :             :    * #GNetworkConnectivity for more details.
     405                 :             :    *
     406                 :             :    * Since: 2.44
     407                 :             :    */
     408                 :          69 :   g_object_interface_install_property (iface,
     409                 :          23 :                                        g_param_spec_enum ("connectivity", NULL, NULL,
     410                 :          23 :                                                           G_TYPE_NETWORK_CONNECTIVITY,
     411                 :             :                                                           G_NETWORK_CONNECTIVITY_FULL,
     412                 :             :                                                           G_PARAM_READABLE |
     413                 :             :                                                           G_PARAM_STATIC_STRINGS));
     414                 :          46 : }
        

Generated by: LCOV version 2.0-1