• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
g_network_monitor_get_default(void)93 g_network_monitor_get_default (void)
94 {
95   if (g_once_init_enter (&network_monitor_default_singleton))
96     {
97       GNetworkMonitor *singleton;
98 
99       singleton = _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
100                                             "GIO_USE_NETWORK_MONITOR",
101                                             NULL);
102 
103       g_once_init_leave (&network_monitor_default_singleton, singleton);
104     }
105 
106   return network_monitor_default_singleton;
107 }
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
g_network_monitor_get_network_available(GNetworkMonitor * monitor)123 g_network_monitor_get_network_available (GNetworkMonitor *monitor)
124 {
125   gboolean available = FALSE;
126 
127   g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
128   return available;
129 }
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
g_network_monitor_get_network_metered(GNetworkMonitor * monitor)143 g_network_monitor_get_network_metered (GNetworkMonitor *monitor)
144 {
145   gboolean metered = FALSE;
146 
147   g_object_get (G_OBJECT (monitor), "network-metered", &metered, NULL);
148   return metered;
149 }
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
g_network_monitor_get_connectivity(GNetworkMonitor * monitor)180 g_network_monitor_get_connectivity (GNetworkMonitor *monitor)
181 {
182   GNetworkConnectivity connectivity;
183 
184   g_object_get (G_OBJECT (monitor), "connectivity", &connectivity, NULL);
185 
186   return connectivity;
187 }
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
g_network_monitor_can_reach(GNetworkMonitor * monitor,GSocketConnectable * connectable,GCancellable * cancellable,GError ** error)219 g_network_monitor_can_reach (GNetworkMonitor     *monitor,
220                              GSocketConnectable  *connectable,
221                              GCancellable        *cancellable,
222                              GError             **error)
223 {
224   GNetworkMonitorInterface *iface;
225 
226   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
227   return iface->can_reach (monitor, connectable, cancellable, error);
228 }
229 
230 static void
g_network_monitor_real_can_reach_async(GNetworkMonitor * monitor,GSocketConnectable * connectable,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)231 g_network_monitor_real_can_reach_async (GNetworkMonitor     *monitor,
232                                         GSocketConnectable  *connectable,
233                                         GCancellable        *cancellable,
234                                         GAsyncReadyCallback  callback,
235                                         gpointer             user_data)
236 {
237   GTask *task;
238   GError *error = NULL;
239 
240   task = g_task_new (monitor, cancellable, callback, user_data);
241   g_task_set_source_tag (task, g_network_monitor_real_can_reach_async);
242 
243   if (g_network_monitor_can_reach (monitor, connectable, cancellable, &error))
244     g_task_return_boolean (task, TRUE);
245   else
246     g_task_return_error (task, error);
247   g_object_unref (task);
248 }
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
g_network_monitor_can_reach_async(GNetworkMonitor * monitor,GSocketConnectable * connectable,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)270 g_network_monitor_can_reach_async (GNetworkMonitor     *monitor,
271                                    GSocketConnectable  *connectable,
272                                    GCancellable        *cancellable,
273                                    GAsyncReadyCallback  callback,
274                                    gpointer             user_data)
275 {
276   GNetworkMonitorInterface *iface;
277 
278   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
279   iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
280 }
281 
282 static gboolean
g_network_monitor_real_can_reach_finish(GNetworkMonitor * monitor,GAsyncResult * result,GError ** error)283 g_network_monitor_real_can_reach_finish (GNetworkMonitor  *monitor,
284                                          GAsyncResult     *result,
285                                          GError          **error)
286 {
287   g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE);
288 
289   return g_task_propagate_boolean (G_TASK (result), error);
290 }
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
g_network_monitor_can_reach_finish(GNetworkMonitor * monitor,GAsyncResult * result,GError ** error)304 g_network_monitor_can_reach_finish (GNetworkMonitor     *monitor,
305                                     GAsyncResult        *result,
306                                     GError             **error)
307 {
308   GNetworkMonitorInterface *iface;
309 
310   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
311   return iface->can_reach_finish (monitor, result, error);
312 }
313 
314 static void
g_network_monitor_default_init(GNetworkMonitorInterface * iface)315 g_network_monitor_default_init (GNetworkMonitorInterface *iface)
316 {
317   iface->can_reach_async  = g_network_monitor_real_can_reach_async;
318   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   signals[NETWORK_CHANGED] =
330     g_signal_new (I_("network-changed"),
331                   G_TYPE_NETWORK_MONITOR,
332                   G_SIGNAL_RUN_LAST,
333                   G_STRUCT_OFFSET (GNetworkMonitorInterface, network_changed),
334                   NULL, NULL,
335                   NULL,
336                   G_TYPE_NONE, 1,
337                   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   g_object_interface_install_property (iface,
363                                        g_param_spec_boolean ("network-available",
364                                                              P_("Network available"),
365                                                              P_("Whether the network is available"),
366                                                              FALSE,
367                                                              G_PARAM_READABLE |
368                                                              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   g_object_interface_install_property (iface,
394                                        g_param_spec_boolean ("network-metered",
395                                                              P_("Network metered"),
396                                                              P_("Whether the network is metered"),
397                                                              FALSE,
398                                                              G_PARAM_READABLE |
399                                                              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   g_object_interface_install_property (iface,
411                                        g_param_spec_enum ("connectivity",
412                                                           P_("Network connectivity"),
413                                                           P_("Level of network connectivity"),
414                                                           G_TYPE_NETWORK_CONNECTIVITY,
415                                                           G_NETWORK_CONNECTIVITY_FULL,
416                                                           G_PARAM_READABLE |
417                                                           G_PARAM_STATIC_STRINGS));
418 }
419