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 {
87 if (g_once_init_enter_pointer (&network_monitor_default_singleton))
88 {
89 GNetworkMonitor *singleton;
90
91 singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
92 "GIO_USE_NETWORK_MONITOR",
93 NULL);
94
95 g_once_init_leave_pointer (&network_monitor_default_singleton, singleton);
96 }
97
98 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 g_network_monitor_get_network_available (GNetworkMonitor *monitor)
116 {
117 gboolean available = FALSE;
118
119 g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
120 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 g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
136 {
137 gboolean metered = FALSE;
138
139 g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
140 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 g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
173 {
174 GNetworkConnectivity connectivity;
175
176 g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
177
178 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 g_network_monitor_can_reach (GNetworkMonitor *monitor,
212 GSocketConnectable *connectable,
213 GCancellable *cancellable,
214 GError **error)
215 {
216 GNetworkMonitorInterface *iface;
217
218 iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
219 return iface->can_reach (monitor, connectable, cancellable, error);
220 }
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 {
229 GTask *task;
230 GError *error = NULL;
231
232 task = g_task_new (monitor, cancellable, callback, user_data);
233 g_task_set_source_tag (task, g_network_monitor_real_can_reach_async);
234
235 if (g_network_monitor_can_reach (monitor, connectable, cancellable, &error))
236 g_task_return_boolean (task, TRUE);
237 else
238 g_task_return_error (task, error);
239 g_object_unref (task);
240 }
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 {
268 GNetworkMonitorInterface *iface;
269
270 iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
271 iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
272 }
273
274 static gboolean
275 g_network_monitor_real_can_reach_finish (GNetworkMonitor *monitor,
276 GAsyncResult *result,
277 GError **error)
278 {
279 g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE);
280
281 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 g_network_monitor_can_reach_finish (GNetworkMonitor *monitor,
297 GAsyncResult *result,
298 GError **error)
299 {
300 GNetworkMonitorInterface *iface;
301
302 iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
303 return iface->can_reach_finish (monitor, result, error);
304 }
305
306 static void
307 g_network_monitor_default_init (GNetworkMonitorInterface *iface)
308 {
309 iface->can_reach_async = g_network_monitor_real_can_reach_async;
310 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 signals[NETWORK_CHANGED] =
322 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 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 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 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 }