Coverage Report

Created: 2025-07-01 07:09

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