Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/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
 * 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
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
g_network_monitor_get_default (void)
86
0
{
87
0
  if (g_once_init_enter_pointer (&network_monitor_default_singleton))
88
0
    {
89
0
      GNetworkMonitor *singleton;
90
91
0
      singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
92
0
                                            "GIO_USE_NETWORK_MONITOR",
93
0
                                            NULL);
94
95
0
      g_once_init_leave_pointer (&network_monitor_default_singleton, singleton);
96
0
    }
97
98
0
  return network_monitor_default_singleton;
99
0
}
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
g_network_monitor_get_network_available (GNetworkMonitor *monitor)
116
0
{
117
0
  gboolean available = FALSE;
118
119
0
  g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
120
0
  return available;
121
0
}
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
g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
136
0
{
137
0
  gboolean metered = FALSE;
138
139
0
  g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
140
0
  return metered;
141
0
}
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
g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
173
0
{
174
0
  GNetworkConnectivity connectivity;
175
176
0
  g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
177
178
0
  return connectivity;
179
0
}
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
g_network_monitor_can_reach (GNetworkMonitor     *monitor,
212
                             GSocketConnectable  *connectable,
213
                             GCancellable        *cancellable,
214
                             GError             **error)
215
0
{
216
0
  GNetworkMonitorInterface *iface;
217
218
0
  iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
219
0
  return iface->can_reach (monitor, connectable, cancellable, error);
220
0
}
221
222
static void
223
g_network_monitor_real_can_reach_async (GNetworkMonitor     *monitor,
224
                                        GSocketConnectable  *connectable,
225
                                        GCancellable        *cancellable,
226
                                        GAsyncReadyCallback  callback,
227
                                        gpointer             user_data)
228
0
{
229
0
  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
0
  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
g_network_monitor_can_reach_async (GNetworkMonitor     *monitor,
263
                                   GSocketConnectable  *connectable,
264
                                   GCancellable        *cancellable,
265
                                   GAsyncReadyCallback  callback,
266
                                   gpointer             user_data)
267
0
{
268
0
  GNetworkMonitorInterface *iface;
269
270
0
  iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
271
0
  iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
272
0
}
273
274
static gboolean
275
g_network_monitor_real_can_reach_finish (GNetworkMonitor  *monitor,
276
                                         GAsyncResult     *result,
277
                                         GError          **error)
278
0
{
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
0
}
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
g_network_monitor_can_reach_finish (GNetworkMonitor     *monitor,
297
                                    GAsyncResult        *result,
298
                                    GError             **error)
299
0
{
300
0
  GNetworkMonitorInterface *iface;
301
302
0
  iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
303
0
  return iface->can_reach_finish (monitor, result, error);
304
0
}
305
306
static void
307
g_network_monitor_default_init (GNetworkMonitorInterface *iface)
308
0
{
309
0
  iface->can_reach_async  = g_network_monitor_real_can_reach_async;
310
0
  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
0
  signals[NETWORK_CHANGED] =
322
0
    g_signal_new (I_("network-changed"),
323
0
                  G_TYPE_NETWORK_MONITOR,
324
0
                  G_SIGNAL_RUN_LAST,
325
0
                  G_STRUCT_OFFSET (GNetworkMonitorInterface, network_changed),
326
0
                  NULL, NULL,
327
0
                  NULL,
328
0
                  G_TYPE_NONE, 1,
329
0
                  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
0
  g_object_interface_install_property (iface,
355
0
                                       g_param_spec_boolean ("network-available", NULL, NULL,
356
0
                                                             FALSE,
357
0
                                                             G_PARAM_READABLE |
358
0
                                                             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
0
  g_object_interface_install_property (iface,
388
0
                                       g_param_spec_boolean ("network-metered", NULL, NULL,
389
0
                                                             FALSE,
390
0
                                                             G_PARAM_READABLE |
391
0
                                                             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
0
  g_object_interface_install_property (iface,
403
0
                                       g_param_spec_enum ("connectivity", NULL, NULL,
404
0
                                                          G_TYPE_NETWORK_CONNECTIVITY,
405
0
                                                          G_NETWORK_CONNECTIVITY_FULL,
406
0
                                                          G_PARAM_READABLE |
407
0
                                                          G_PARAM_STATIC_STRINGS));
408
0
}