Coverage Report

Created: 2025-06-13 06:55

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