LCOV - code coverage report
Current view: top level - glib/gio - gnetworkmonitor.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 29 48 60.4 %
Date: 2024-04-16 05:15:53 Functions: 7 11 63.6 %
Branches: 8 16 50.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   [ +  +  +  -  :       1360 : G_DEFINE_INTERFACE_WITH_CODE (GNetworkMonitor, g_network_monitor, G_TYPE_OBJECT,
                   +  + ]
      63                 :            :                               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                 :            :  * Returns: (not nullable) (transfer none): a #GNetworkMonitor, which will be
      80                 :            :  *     a dummy object if no network monitor is available
      81                 :            :  *
      82                 :            :  * Since: 2.32
      83                 :            :  */
      84                 :            : GNetworkMonitor *
      85                 :         21 : g_network_monitor_get_default (void)
      86                 :            : {
      87   [ +  -  +  -  :         21 :   if (g_once_init_enter_pointer (&network_monitor_default_singleton))
                   +  - ]
      88                 :            :     {
      89                 :            :       GNetworkMonitor *singleton;
      90                 :            : 
      91                 :         21 :       singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
      92                 :            :                                             "GIO_USE_NETWORK_MONITOR",
      93                 :            :                                             NULL);
      94                 :            : 
      95                 :         21 :       g_once_init_leave_pointer (&network_monitor_default_singleton, singleton);
      96                 :            :     }
      97                 :            : 
      98                 :         21 :   return network_monitor_default_singleton;
      99                 :            : }
     100                 :            : 
     101                 :            : /**
     102                 :            :  * g_network_monitor_get_network_available:
     103                 :            :  * @monitor: the #GNetworkMonitor
     104                 :            :  *
     105                 :            :  * Checks if the network is available. "Available" here means that the
     106                 :            :  * system has a default route available for at least one of IPv4 or
     107                 :            :  * IPv6. It does not necessarily imply that the public Internet is
     108                 :            :  * reachable. See #GNetworkMonitor:network-available for more details.
     109                 :            :  *
     110                 :            :  * Returns: whether the network is available
     111                 :            :  *
     112                 :            :  * Since: 2.32
     113                 :            :  */
     114                 :            : gboolean
     115                 :         25 : g_network_monitor_get_network_available (GNetworkMonitor *monitor)
     116                 :            : {
     117                 :         25 :   gboolean available = FALSE;
     118                 :            : 
     119                 :         25 :   g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
     120                 :         25 :   return available;
     121                 :            : }
     122                 :            : 
     123                 :            : /**
     124                 :            :  * g_network_monitor_get_network_metered:
     125                 :            :  * @monitor: the #GNetworkMonitor
     126                 :            :  *
     127                 :            :  * Checks if the network is metered.
     128                 :            :  * See #GNetworkMonitor:network-metered for more details.
     129                 :            :  *
     130                 :            :  * Returns: whether the connection is metered
     131                 :            :  *
     132                 :            :  * Since: 2.46
     133                 :            :  */
     134                 :            : gboolean
     135                 :          0 : g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
     136                 :            : {
     137                 :          0 :   gboolean metered = FALSE;
     138                 :            : 
     139                 :          0 :   g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
     140                 :          0 :   return metered;
     141                 :            : }
     142                 :            : 
     143                 :            : /**
     144                 :            :  * g_network_monitor_get_connectivity:
     145                 :            :  * @monitor: the #GNetworkMonitor
     146                 :            :  *
     147                 :            :  * Gets a more detailed networking state than
     148                 :            :  * g_network_monitor_get_network_available().
     149                 :            :  *
     150                 :            :  * If #GNetworkMonitor:network-available is %FALSE, then the
     151                 :            :  * connectivity state will be %G_NETWORK_CONNECTIVITY_LOCAL.
     152                 :            :  *
     153                 :            :  * If #GNetworkMonitor:network-available is %TRUE, then the
     154                 :            :  * connectivity state will be %G_NETWORK_CONNECTIVITY_FULL (if there
     155                 :            :  * is full Internet connectivity), %G_NETWORK_CONNECTIVITY_LIMITED (if
     156                 :            :  * the host has a default route, but appears to be unable to actually
     157                 :            :  * reach the full Internet), or %G_NETWORK_CONNECTIVITY_PORTAL (if the
     158                 :            :  * host is trapped behind a "captive portal" that requires some sort
     159                 :            :  * of login or acknowledgement before allowing full Internet access).
     160                 :            :  *
     161                 :            :  * Note that in the case of %G_NETWORK_CONNECTIVITY_LIMITED and
     162                 :            :  * %G_NETWORK_CONNECTIVITY_PORTAL, it is possible that some sites are
     163                 :            :  * reachable but others are not. In this case, applications can
     164                 :            :  * attempt to connect to remote servers, but should gracefully fall
     165                 :            :  * back to their "offline" behavior if the connection attempt fails.
     166                 :            :  *
     167                 :            :  * Return value: the network connectivity state
     168                 :            :  *
     169                 :            :  * Since: 2.44
     170                 :            :  */
     171                 :            : GNetworkConnectivity
     172                 :          0 : g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
     173                 :            : {
     174                 :            :   GNetworkConnectivity connectivity;
     175                 :            : 
     176                 :          0 :   g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
     177                 :            : 
     178                 :          0 :   return connectivity;
     179                 :            : }
     180                 :            : 
     181                 :            : /**
     182                 :            :  * g_network_monitor_can_reach:
     183                 :            :  * @monitor: a #GNetworkMonitor
     184                 :            :  * @connectable: a #GSocketConnectable
     185                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
     186                 :            :  * @error: return location for a #GError, or %NULL
     187                 :            :  *
     188                 :            :  * Attempts to determine whether or not the host pointed to by
     189                 :            :  * @connectable can be reached, without actually trying to connect to
     190                 :            :  * it.
     191                 :            :  *
     192                 :            :  * This may return %TRUE even when #GNetworkMonitor:network-available
     193                 :            :  * is %FALSE, if, for example, @monitor can determine that
     194                 :            :  * @connectable refers to a host on a local network.
     195                 :            :  *
     196                 :            :  * If @monitor believes that an attempt to connect to @connectable
     197                 :            :  * will succeed, it will return %TRUE. Otherwise, it will return
     198                 :            :  * %FALSE and set @error to an appropriate error (such as
     199                 :            :  * %G_IO_ERROR_HOST_UNREACHABLE).
     200                 :            :  *
     201                 :            :  * Note that although this does not attempt to connect to
     202                 :            :  * @connectable, it may still block for a brief period of time (eg,
     203                 :            :  * trying to do multicast DNS on the local network), so if you do not
     204                 :            :  * want to block, you should use g_network_monitor_can_reach_async().
     205                 :            :  *
     206                 :            :  * Returns: %TRUE if @connectable is reachable, %FALSE if not.
     207                 :            :  *
     208                 :            :  * Since: 2.32
     209                 :            :  */
     210                 :            : gboolean
     211                 :        247 : g_network_monitor_can_reach (GNetworkMonitor     *monitor,
     212                 :            :                              GSocketConnectable  *connectable,
     213                 :            :                              GCancellable        *cancellable,
     214                 :            :                              GError             **error)
     215                 :            : {
     216                 :            :   GNetworkMonitorInterface *iface;
     217                 :            : 
     218                 :        247 :   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
     219                 :        247 :   return iface->can_reach (monitor, connectable, cancellable, error);
     220                 :            : }
     221                 :            : 
     222                 :            : static void
     223                 :          0 : g_network_monitor_real_can_reach_async (GNetworkMonitor     *monitor,
     224                 :            :                                         GSocketConnectable  *connectable,
     225                 :            :                                         GCancellable        *cancellable,
     226                 :            :                                         GAsyncReadyCallback  callback,
     227                 :            :                                         gpointer             user_data)
     228                 :            : {
     229                 :            :   GTask *task;
     230                 :          0 :   GError *error = NULL;
     231                 :            : 
     232                 :          0 :   task = g_task_new (monitor, cancellable, callback, user_data);
     233         [ #  # ]:          0 :   g_task_set_source_tag (task, g_network_monitor_real_can_reach_async);
     234                 :            : 
     235         [ #  # ]:          0 :   if (g_network_monitor_can_reach (monitor, connectable, cancellable, &error))
     236                 :          0 :     g_task_return_boolean (task, TRUE);
     237                 :            :   else
     238                 :          0 :     g_task_return_error (task, error);
     239                 :          0 :   g_object_unref (task);
     240                 :          0 : }
     241                 :            : 
     242                 :            : /**
     243                 :            :  * g_network_monitor_can_reach_async:
     244                 :            :  * @monitor: a #GNetworkMonitor
     245                 :            :  * @connectable: a #GSocketConnectable
     246                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
     247                 :            :  * @callback: (scope async): a #GAsyncReadyCallback
     248                 :            :  *     to call when the request is satisfied
     249                 :            :  * @user_data: the data to pass to callback function
     250                 :            :  *
     251                 :            :  * Asynchronously attempts to determine whether or not the host
     252                 :            :  * pointed to by @connectable can be reached, without actually
     253                 :            :  * trying to connect to it.
     254                 :            :  *
     255                 :            :  * For more details, see g_network_monitor_can_reach().
     256                 :            :  *
     257                 :            :  * When the operation is finished, @callback will be called.
     258                 :            :  * You can then call g_network_monitor_can_reach_finish()
     259                 :            :  * to get the result of the operation.
     260                 :            :  */
     261                 :            : void
     262                 :        247 : g_network_monitor_can_reach_async (GNetworkMonitor     *monitor,
     263                 :            :                                    GSocketConnectable  *connectable,
     264                 :            :                                    GCancellable        *cancellable,
     265                 :            :                                    GAsyncReadyCallback  callback,
     266                 :            :                                    gpointer             user_data)
     267                 :            : {
     268                 :            :   GNetworkMonitorInterface *iface;
     269                 :            : 
     270                 :        247 :   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
     271                 :        247 :   iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
     272                 :        247 : }
     273                 :            : 
     274                 :            : static gboolean
     275                 :          0 : g_network_monitor_real_can_reach_finish (GNetworkMonitor  *monitor,
     276                 :            :                                          GAsyncResult     *result,
     277                 :            :                                          GError          **error)
     278                 :            : {
     279                 :          0 :   g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE);
     280                 :            : 
     281                 :          0 :   return g_task_propagate_boolean (G_TASK (result), error);
     282                 :            : }
     283                 :            : 
     284                 :            : /**
     285                 :            :  * g_network_monitor_can_reach_finish:
     286                 :            :  * @monitor: a #GNetworkMonitor
     287                 :            :  * @result: a #GAsyncResult
     288                 :            :  * @error: return location for errors, or %NULL
     289                 :            :  *
     290                 :            :  * Finishes an async network connectivity test.
     291                 :            :  * See g_network_monitor_can_reach_async().
     292                 :            :  *
     293                 :            :  * Returns: %TRUE if network is reachable, %FALSE if not.
     294                 :            :  */
     295                 :            : gboolean
     296                 :        247 : g_network_monitor_can_reach_finish (GNetworkMonitor     *monitor,
     297                 :            :                                     GAsyncResult        *result,
     298                 :            :                                     GError             **error)
     299                 :            : {
     300                 :            :   GNetworkMonitorInterface *iface;
     301                 :            : 
     302                 :        247 :   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
     303                 :        247 :   return iface->can_reach_finish (monitor, result, error);
     304                 :            : }
     305                 :            : 
     306                 :            : static void
     307                 :         22 : g_network_monitor_default_init (GNetworkMonitorInterface *iface)
     308                 :            : {
     309                 :         22 :   iface->can_reach_async  = g_network_monitor_real_can_reach_async;
     310                 :         22 :   iface->can_reach_finish = g_network_monitor_real_can_reach_finish;
     311                 :            : 
     312                 :            :   /**
     313                 :            :    * GNetworkMonitor::network-changed:
     314                 :            :    * @monitor: a #GNetworkMonitor
     315                 :            :    * @network_available: the current value of #GNetworkMonitor:network-available
     316                 :            :    *
     317                 :            :    * Emitted when the network configuration changes.
     318                 :            :    *
     319                 :            :    * Since: 2.32
     320                 :            :    */
     321                 :         22 :   signals[NETWORK_CHANGED] =
     322                 :         22 :     g_signal_new (I_("network-changed"),
     323                 :            :                   G_TYPE_NETWORK_MONITOR,
     324                 :            :                   G_SIGNAL_RUN_LAST,
     325                 :            :                   G_STRUCT_OFFSET (GNetworkMonitorInterface, network_changed),
     326                 :            :                   NULL, NULL,
     327                 :            :                   NULL,
     328                 :            :                   G_TYPE_NONE, 1,
     329                 :            :                   G_TYPE_BOOLEAN);
     330                 :            : 
     331                 :            :   /**
     332                 :            :    * GNetworkMonitor:network-available:
     333                 :            :    *
     334                 :            :    * Whether the network is considered available. That is, whether the
     335                 :            :    * system has a default route for at least one of IPv4 or IPv6.
     336                 :            :    *
     337                 :            :    * Real-world networks are of course much more complicated than
     338                 :            :    * this; the machine may be connected to a wifi hotspot that
     339                 :            :    * requires payment before allowing traffic through, or may be
     340                 :            :    * connected to a functioning router that has lost its own upstream
     341                 :            :    * connectivity. Some hosts might only be accessible when a VPN is
     342                 :            :    * active. Other hosts might only be accessible when the VPN is
     343                 :            :    * not active. Thus, it is best to use g_network_monitor_can_reach()
     344                 :            :    * or g_network_monitor_can_reach_async() to test for reachability
     345                 :            :    * on a host-by-host basis. (On the other hand, when the property is
     346                 :            :    * %FALSE, the application can reasonably expect that no remote
     347                 :            :    * hosts at all are reachable, and should indicate this to the user
     348                 :            :    * in its UI.)
     349                 :            :    *
     350                 :            :    * See also #GNetworkMonitor::network-changed.
     351                 :            :    *
     352                 :            :    * Since: 2.32
     353                 :            :    */
     354                 :         22 :   g_object_interface_install_property (iface,
     355                 :            :                                        g_param_spec_boolean ("network-available", NULL, NULL,
     356                 :            :                                                              FALSE,
     357                 :            :                                                              G_PARAM_READABLE |
     358                 :            :                                                              G_PARAM_STATIC_STRINGS));
     359                 :            : 
     360                 :            :   /**
     361                 :            :    * GNetworkMonitor:network-metered:
     362                 :            :    *
     363                 :            :    * Whether the network is considered metered.
     364                 :            :    *
     365                 :            :    * That is, whether the
     366                 :            :    * system has traffic flowing through the default connection that is
     367                 :            :    * subject to limitations set by service providers. For example, traffic
     368                 :            :    * might be billed by the amount of data transmitted, or there might be a
     369                 :            :    * quota on the amount of traffic per month. This is typical with tethered
     370                 :            :    * connections (3G and 4G) and in such situations, bandwidth intensive
     371                 :            :    * applications may wish to avoid network activity where possible if it will
     372                 :            :    * cost the user money or use up their limited quota. Anything more than a
     373                 :            :    * few hundreds of kilobytes of data usage per hour should be avoided without
     374                 :            :    * asking permission from the user.
     375                 :            :    *
     376                 :            :    * If more information is required about specific devices then the
     377                 :            :    * system network management API should be used instead (for example,
     378                 :            :    * NetworkManager or ConnMan).
     379                 :            :    *
     380                 :            :    * If this information is not available then no networks will be
     381                 :            :    * marked as metered.
     382                 :            :    *
     383                 :            :    * See also #GNetworkMonitor:network-available.
     384                 :            :    *
     385                 :            :    * Since: 2.46
     386                 :            :    */
     387                 :         22 :   g_object_interface_install_property (iface,
     388                 :            :                                        g_param_spec_boolean ("network-metered", NULL, NULL,
     389                 :            :                                                              FALSE,
     390                 :            :                                                              G_PARAM_READABLE |
     391                 :            :                                                              G_PARAM_STATIC_STRINGS));
     392                 :            : 
     393                 :            :   /**
     394                 :            :    * GNetworkMonitor:connectivity:
     395                 :            :    *
     396                 :            :    * More detailed information about the host's network connectivity.
     397                 :            :    * See g_network_monitor_get_connectivity() and
     398                 :            :    * #GNetworkConnectivity for more details.
     399                 :            :    *
     400                 :            :    * Since: 2.44
     401                 :            :    */
     402                 :         22 :   g_object_interface_install_property (iface,
     403                 :            :                                        g_param_spec_enum ("connectivity", NULL, NULL,
     404                 :            :                                                           G_TYPE_NETWORK_CONNECTIVITY,
     405                 :            :                                                           G_NETWORK_CONNECTIVITY_FULL,
     406                 :            :                                                           G_PARAM_READABLE |
     407                 :            :                                                           G_PARAM_STATIC_STRINGS));
     408                 :         22 : }

Generated by: LCOV version 1.14