Revert "GIOScheduler: Avoid constant iteration over pending job list"
[platform/upstream/glib.git] / gio / gnetworkmonitor.c
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 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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
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 "gsimpleasyncresult.h"
32
33 /**
34  * SECTION:gnetworkmonitor
35  * @title: GNetworkMonitor
36  * @short_description: Network status monitor
37  * @include: gio/gio.h
38  *
39  * #GNetworkMonitor provides an easy-to-use cross-platform API
40  * for monitoring network connectivity. On Linux, the implementation
41  * is based on the kernels netlink interface.
42  */
43
44 /**
45  * GNetworkMonitor:
46  *
47  * #GNetworkMonitor monitors the status of network connections and
48  * indicates when a possibly-user-visible change has occurred.
49  *
50  * Since: 2.32
51  */
52
53 G_DEFINE_INTERFACE_WITH_CODE (GNetworkMonitor, g_network_monitor, G_TYPE_OBJECT,
54                               g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_INITABLE);)
55
56
57 enum {
58   NETWORK_CHANGED,
59   LAST_SIGNAL
60 };
61
62 static guint signals[LAST_SIGNAL] = { 0 };
63
64 /**
65  * g_network_monitor_get_default:
66  *
67  * Gets the default #GNetworkMonitor for the system.
68  *
69  * Returns: (transfer none): a #GNetworkMonitor
70  *
71  * Since: 2.32
72  */
73 GNetworkMonitor *
74 g_network_monitor_get_default (void)
75 {
76   return _g_io_module_get_default (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
77                                    "GIO_USE_NETWORK_MONITOR",
78                                    NULL);
79 }
80
81 /**
82  * g_network_monitor_get_network_available:
83  * @monitor: the #GNetworkMonitor
84  *
85  * Checks if the network is available. "Available" here means that the
86  * system has a default route available for at least one of IPv4 or
87  * IPv6. It does not necessarily imply that the public Internet is
88  * reachable. See #GNetworkMonitor:network-available for more details.
89  *
90  * Return value: whether the network is available
91  *
92  * Since: 2.32
93  */
94 gboolean
95 g_network_monitor_get_network_available (GNetworkMonitor *monitor)
96 {
97   gboolean available = FALSE;
98
99   g_object_get (G_OBJECT (monitor), "network-available", &available, NULL);
100   return available;
101 }
102
103 /**
104  * g_network_monitor_can_reach:
105  * @monitor: a #GNetworkMonitor
106  * @connectable: a #GSocketConnectable
107  * @cancellable: (allow-none): a #GCancellable, or %NULL
108  * @error: return location for a #GError, or %NULL
109  *
110  * Attempts to determine whether or not the host pointed to by
111  * @connectable can be reached, without actually trying to connect to
112  * it.
113  *
114  * This may return %TRUE even when #GNetworkMonitor:network-available
115  * is %FALSE, if, for example, @monitor can determine that
116  * @connectable refers to a host on a local network.
117  *
118  * If @monitor believes that an attempt to connect to @connectable
119  * will succeed, it will return %TRUE. Otherwise, it will return
120  * %FALSE and set @error to an appropriate error (such as
121  * %G_IO_ERROR_HOST_UNREACHABLE).
122  *
123  * Note that although this does not attempt to connect to
124  * @connectable, it may still block for a brief period of time (eg,
125  * trying to do multicast DNS on the local network), so if you do not
126  * want to block, you should use g_network_monitor_can_reach_async().
127  *
128  * Return value: %TRUE if @connectable is reachable, %FALSE if not.
129  *
130  * Since: 2.32
131  */
132 gboolean
133 g_network_monitor_can_reach (GNetworkMonitor     *monitor,
134                              GSocketConnectable  *connectable,
135                              GCancellable        *cancellable,
136                              GError             **error)
137 {
138   GNetworkMonitorInterface *iface;
139
140   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
141   return iface->can_reach (monitor, connectable, cancellable, error);
142 }
143
144 static void
145 g_network_monitor_real_can_reach_async (GNetworkMonitor     *monitor,
146                                         GSocketConnectable  *connectable,
147                                         GCancellable        *cancellable,
148                                         GAsyncReadyCallback  callback,
149                                         gpointer             user_data)
150 {
151   GSimpleAsyncResult *simple;
152   GError *error = NULL;
153
154   simple = g_simple_async_result_new (G_OBJECT (monitor),
155                                       callback, user_data,
156                                       g_network_monitor_real_can_reach_async);
157   if (g_network_monitor_can_reach (monitor, connectable, cancellable, &error))
158     g_simple_async_result_set_op_res_gboolean (simple, TRUE);
159   else
160     g_simple_async_result_take_error (simple, error);
161   g_simple_async_result_complete_in_idle (simple);
162   g_object_unref (simple);
163 }
164
165 /**
166  * g_network_monitor_can_reach_async:
167  * @monitor: a #GNetworkMonitor
168  * @connectable: a #GSocketConnectable
169  * @cancellable: (allow-none): a #GCancellable, or %NULL
170  * @callback: (scope async): a #GAsyncReadyCallback to call when the
171  *     request is satisfied
172  * @user_data: (closure): the data to pass to callback function
173  *
174  * Asynchronously attempts to determine whether or not the host
175  * pointed to by @connectable can be reached, without actually
176  * trying to connect to it.
177  *
178  * For more details, see g_network_monitor_can_reach().
179  *
180  * When the operation is finished, @callback will be called.
181  * You can then call g_network_monitor_can_reach_finish()
182  * to get the result of the operation.
183  */
184 void
185 g_network_monitor_can_reach_async (GNetworkMonitor     *monitor,
186                                    GSocketConnectable  *connectable,
187                                    GCancellable        *cancellable,
188                                    GAsyncReadyCallback  callback,
189                                    gpointer             user_data)
190 {
191   GNetworkMonitorInterface *iface;
192
193   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
194   iface->can_reach_async (monitor, connectable, cancellable, callback, user_data);
195 }
196
197 static gboolean
198 g_network_monitor_real_can_reach_finish (GNetworkMonitor  *monitor,
199                                          GAsyncResult     *result,
200                                          GError          **error)
201 {
202   GSimpleAsyncResult *simple;
203
204   g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (monitor), g_network_monitor_real_can_reach_async), FALSE);
205
206   simple = G_SIMPLE_ASYNC_RESULT (result);
207   if (g_simple_async_result_propagate_error (simple, error))
208     return FALSE;
209   else
210     return g_simple_async_result_get_op_res_gboolean (simple);
211 }
212
213 /**
214  * g_network_monitor_can_reach_finish:
215  * @monitor: a #GNetworkMonitor
216  * @result: a #GAsyncResult
217  * @error: return location for errors, or %NULL
218  *
219  * Finishes an async network connectivity test.
220  * See g_network_monitor_can_reach_async().
221  *
222  * Return value: %TRUE if network is reachable, %FALSE if not.
223  */
224 gboolean
225 g_network_monitor_can_reach_finish (GNetworkMonitor     *monitor,
226                                     GAsyncResult        *result,
227                                     GError             **error)
228 {
229   GNetworkMonitorInterface *iface;
230
231   iface = G_NETWORK_MONITOR_GET_INTERFACE (monitor);
232   return iface->can_reach_finish (monitor, result, error);
233 }
234
235 static void
236 g_network_monitor_default_init (GNetworkMonitorInterface *iface)
237 {
238   iface->can_reach_async  = g_network_monitor_real_can_reach_async;
239   iface->can_reach_finish = g_network_monitor_real_can_reach_finish;
240
241   /**
242    * GNetworkMonitor::network-changed:
243    * @monitor: a #GNetworkMonitor
244    * @available: the current value of #GNetworkMonitor:network-available
245    *
246    * Emitted when the network configuration changes. If @available is
247    * %TRUE, then some hosts may be reachable that were not reachable
248    * before, while others that were reachable before may no longer be
249    * reachable. If @available is %FALSE, then no remote hosts are
250    * reachable.
251    *
252    * Since: 2.32
253    */
254   signals[NETWORK_CHANGED] =
255     g_signal_new (I_("network-changed"),
256                   G_TYPE_NETWORK_MONITOR,
257                   G_SIGNAL_RUN_LAST,
258                   G_STRUCT_OFFSET (GNetworkMonitorInterface, network_changed),
259                   NULL, NULL,
260                   g_cclosure_marshal_VOID__BOOLEAN,
261                   G_TYPE_NONE, 1,
262                   G_TYPE_BOOLEAN);
263
264   /**
265    * GNetworkMonitor:network-available:
266    *
267    * Whether the network is considered available. That is, whether the
268    * system has a default route for at least one of IPv4 or IPv6.
269    *
270    * Real-world networks are of course much more complicated than
271    * this; the machine may be connected to a wifi hotspot that
272    * requires payment before allowing traffic through, or may be
273    * connected to a functioning router that has lost its own upstream
274    * connectivity. Some hosts might only be accessible when a VPN is
275    * active. Other hosts might only be accessible when the VPN is
276    * <emphasis>not</emphasis> active. Thus, it is best to use
277    * g_network_monitor_can_reach() or
278    * g_network_monitor_can_reach_async() to test for reachability on a
279    * host-by-host basis. (On the other hand, when the property is
280    * %FALSE, the application can reasonably expect that no remote
281    * hosts at all are reachable, and should indicate this to the user
282    * in its UI.)
283    *
284    * See also #GNetworkMonitor::network-changed.
285    *
286    * Since: 2.32
287    */
288   g_object_interface_install_property (iface,
289                                        g_param_spec_boolean ("network-available",
290                                                              P_("Network available"),
291                                                              P_("Whether the network is available"),
292                                                              FALSE,
293                                                              G_PARAM_READABLE |
294                                                              G_PARAM_STATIC_STRINGS));
295 }