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 : 1386 : 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 : 21 : g_network_monitor_get_default (void)
86 : : {
87 : 21 : if (g_once_init_enter_pointer (&network_monitor_default_singleton))
88 : : {
89 : : GNetworkMonitor *singleton;
90 : :
91 : 21 : singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
92 : : "GIO_USE_NETWORK_MONITOR",
93 : : NULL);
94 : :
95 : 21 : g_once_init_leave_pointer (&network_monitor_default_singleton, singleton);
96 : : }
97 : :
98 : 21 : 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 : 25 : g_network_monitor_get_network_available (GNetworkMonitor *monitor)
116 : : {
117 : 25 : gboolean available = FALSE;
118 : :
119 : 25 : g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
120 : 25 : 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 : 0 : g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
136 : : {
137 : 0 : gboolean metered = FALSE;
138 : :
139 : 0 : g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
140 : 0 : 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 : 0 : g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
173 : : {
174 : : GNetworkConnectivity connectivity;
175 : :
176 : 0 : g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
177 : :
178 : 0 : 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 : 247 : g_network_monitor_can_reach (GNetworkMonitor *monitor,
212 : : GSocketConnectable *connectable,
213 : : GCancellable *cancellable,
214 : : GError **error)
215 : : {
216 : : GNetworkMonitorInterface *iface;
217 : :
218 : 247 : iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
219 : 247 : return iface->can_reach (monitor, connectable, cancellable, error);
220 : : }
221 : :
222 : : static void
223 : 0 : 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 : 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 : : 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 : 247 : 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 : 247 : iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
271 : 247 : iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
272 : 247 : }
273 : :
274 : : static gboolean
275 : 0 : g_network_monitor_real_can_reach_finish (GNetworkMonitor *monitor,
276 : : GAsyncResult *result,
277 : : GError **error)
278 : : {
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 : : }
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 : 247 : g_network_monitor_can_reach_finish (GNetworkMonitor *monitor,
297 : : GAsyncResult *result,
298 : : GError **error)
299 : : {
300 : : GNetworkMonitorInterface *iface;
301 : :
302 : 247 : iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
303 : 247 : return iface->can_reach_finish (monitor, result, error);
304 : : }
305 : :
306 : : static void
307 : 22 : g_network_monitor_default_init (GNetworkMonitorInterface *iface)
308 : : {
309 : 22 : iface->can_reach_async = g_network_monitor_real_can_reach_async;
310 : 22 : 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 : 22 : signals[NETWORK_CHANGED] =
322 : 22 : 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 : 22 : 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 : 22 : 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 : 22 : 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 : 22 : }
|