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