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 "gio.h"
20
21/* hack */
22#define GIO_COMPILATION
23#include "gnetworkmonitorbase.h"
24
25#include <string.h>
26
27/* Test data; the GInetAddresses and GInetAddressMasks get filled in
28 * in main(). Each address in a TestAddress matches the mask in its
29 * corresponding TestMask, and none of them match any of the other
30 * masks. The addresses in unmatched don't match any of the masks.
31 */
32
33typedef struct {
34 const char *string;
35 GInetAddress *address;
36} TestAddress;
37
38typedef struct {
39 const char *mask_string;
40 GInetAddressMask *mask;
41 TestAddress *addresses;
42} TestMask;
43
44TestAddress net127addrs[] = {
45 { "127.0.0.1", NULL },
46 { "127.0.0.2", NULL },
47 { "127.0.0.255", NULL },
48 { "127.0.1.0", NULL },
49 { "127.0.255.0", NULL },
50 { "127.0.255.0", NULL },
51 { "127.255.255.255", NULL },
52 { NULL, NULL }
53};
54TestMask net127 = { "127.0.0.0/8", NULL, net127addrs };
55
56TestAddress net10addrs[] = {
57 { .string: "10.0.0.1", NULL },
58 { "10.0.0.2", NULL },
59 { "10.0.0.255", NULL },
60 { NULL, NULL }
61};
62TestMask net10 = { "10.0.0.0/24", NULL, net10addrs };
63
64TestAddress net192addrs[] = {
65 { .string: "192.168.0.1", NULL },
66 { "192.168.0.2", NULL },
67 { "192.168.0.255", NULL },
68 { "192.168.1.0", NULL },
69 { "192.168.15.0", NULL },
70 { NULL, NULL }
71};
72TestMask net192 = { "192.168.0.0/20", NULL, net192addrs };
73
74TestAddress netlocal6addrs[] = {
75 { .string: "::1", NULL },
76 { NULL, NULL }
77};
78TestMask netlocal6 = { "::1/128", NULL, netlocal6addrs };
79
80TestAddress netfe80addrs[] = {
81 { .string: "fe80::", NULL },
82 { "fe80::1", NULL },
83 { "fe80::21b:77ff:fea2:972a", NULL },
84 { NULL, NULL }
85};
86TestMask netfe80 = { "fe80::/64", NULL, netfe80addrs };
87
88TestAddress unmatched[] = {
89 { .string: "10.0.1.0", NULL },
90 { "10.0.255.0", NULL },
91 { "10.255.255.255", NULL },
92 { "192.168.16.0", NULL },
93 { "192.168.255.0", NULL },
94 { "192.169.0.0", NULL },
95 { "192.255.255.255", NULL },
96 { "::2", NULL },
97 { "1::1", NULL },
98 { "fe80::1:0:0:0:0", NULL },
99 { "fe80:8000::0:0:0:0", NULL },
100 { NULL, NULL }
101};
102
103GInetAddressMask *ip4_default, *ip6_default;
104
105static void
106notify_handler (GObject *object,
107 GParamSpec *pspec,
108 gpointer user_data)
109{
110 gboolean *emitted = user_data;
111
112 *emitted = TRUE;
113}
114
115static void
116network_changed_handler (GNetworkMonitor *monitor,
117 gboolean available,
118 gpointer user_data)
119{
120 gboolean *emitted = user_data;
121
122 *emitted = TRUE;
123}
124
125static void
126assert_signals (GNetworkMonitor *monitor,
127 gboolean should_emit_notify,
128 gboolean should_emit_network_changed,
129 gboolean expected_network_available)
130{
131 gboolean emitted_notify = FALSE, emitted_network_changed = FALSE;
132 guint h1, h2;
133
134 h1 = g_signal_connect (monitor, "notify::network-available",
135 G_CALLBACK (notify_handler),
136 &emitted_notify);
137 h2 = g_signal_connect (monitor, "network-changed",
138 G_CALLBACK (network_changed_handler),
139 &emitted_network_changed);
140
141 g_main_context_iteration (NULL, FALSE);
142
143 g_signal_handler_disconnect (instance: monitor, handler_id: h1);
144 g_signal_handler_disconnect (instance: monitor, handler_id: h2);
145
146 g_assert (emitted_notify == should_emit_notify);
147 g_assert (emitted_network_changed == should_emit_network_changed);
148
149 g_assert (g_network_monitor_get_network_available (monitor) == expected_network_available);
150}
151
152typedef struct {
153 GNetworkMonitor *monitor;
154 GMainLoop *loop;
155 GSocketAddress *sockaddr;
156 gboolean should_be_reachable;
157} CanReachData;
158
159static void
160reach_cb (GObject *source,
161 GAsyncResult *res,
162 gpointer user_data)
163{
164 GError *error = NULL;
165 gboolean reachable;
166 CanReachData *data = user_data;
167
168 reachable = g_network_monitor_can_reach_finish (monitor: data->monitor, result: res, error: &error);
169
170 if (data->should_be_reachable)
171 g_assert_no_error (error);
172 else
173 {
174 g_assert (error != NULL);
175 g_clear_error (err: &error);
176 }
177 g_assert (reachable == data->should_be_reachable);
178
179 g_main_loop_quit (loop: data->loop);
180}
181
182static gboolean
183test_reach_async (gpointer user_data)
184{
185 CanReachData *data = user_data;
186
187 g_network_monitor_can_reach_async (monitor: data->monitor,
188 G_SOCKET_CONNECTABLE (data->sockaddr),
189 NULL,
190 callback: reach_cb,
191 user_data: data);
192 return G_SOURCE_REMOVE;
193}
194
195static void
196run_tests (GNetworkMonitor *monitor,
197 TestAddress *addresses,
198 gboolean should_be_reachable)
199{
200 GError *error = NULL;
201 int i;
202 gboolean reachable;
203 GSocketAddress *sockaddr;
204 CanReachData data;
205
206 data.monitor = monitor;
207 data.loop = g_main_loop_new (NULL, FALSE);
208
209 for (i = 0; addresses[i].address; i++)
210 {
211 sockaddr = g_inet_socket_address_new (address: addresses[i].address, port: 0);
212 reachable = g_network_monitor_can_reach (monitor,
213 G_SOCKET_CONNECTABLE (sockaddr),
214 NULL, error: &error);
215 data.sockaddr = sockaddr;
216 data.should_be_reachable = should_be_reachable;
217
218 g_idle_add (function: test_reach_async, data: &data);
219 g_main_loop_run (loop: data.loop);
220
221 g_object_unref (object: sockaddr);
222 g_assert_cmpint (reachable, ==, should_be_reachable);
223 if (should_be_reachable)
224 g_assert_no_error (error);
225 else
226 {
227 g_assert (error != NULL);
228 g_clear_error (err: &error);
229 }
230 }
231
232 g_main_loop_unref (loop: data.loop);
233}
234
235static void
236test_default (void)
237{
238 GNetworkMonitor *monitor, *m;
239 GError *error = NULL;
240
241 m = g_network_monitor_get_default ();
242 g_assert (G_IS_NETWORK_MONITOR (m));
243
244 monitor = g_object_new (G_TYPE_NETWORK_MONITOR_BASE, NULL);
245 g_initable_init (G_INITABLE (monitor), NULL, error: &error);
246 g_assert_no_error (error);
247
248 /* In the default configuration, all addresses are reachable */
249 run_tests (monitor, addresses: net127.addresses, TRUE);
250 run_tests (monitor, addresses: net10.addresses, TRUE);
251 run_tests (monitor, addresses: net192.addresses, TRUE);
252 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
253 run_tests (monitor, addresses: netfe80.addresses, TRUE);
254 run_tests (monitor, addresses: unmatched, TRUE);
255
256 assert_signals (monitor, FALSE, FALSE, TRUE);
257
258 g_object_unref (object: monitor);
259}
260
261static void
262test_remove_default (void)
263{
264 GNetworkMonitor *monitor;
265 GError *error = NULL;
266
267 monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, error: &error, NULL);
268 g_assert_no_error (error);
269 assert_signals (monitor, FALSE, FALSE, TRUE);
270
271 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
272 network: ip4_default);
273 assert_signals (monitor, FALSE, TRUE, TRUE);
274 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
275 network: ip6_default);
276 assert_signals (monitor, TRUE, TRUE, FALSE);
277
278 /* Now nothing should be reachable */
279 run_tests (monitor, addresses: net127.addresses, FALSE);
280 run_tests (monitor, addresses: net10.addresses, FALSE);
281 run_tests (monitor, addresses: net192.addresses, FALSE);
282 run_tests (monitor, addresses: netlocal6.addresses, FALSE);
283 run_tests (monitor, addresses: netfe80.addresses, FALSE);
284 run_tests (monitor, addresses: unmatched, FALSE);
285
286 g_object_unref (object: monitor);
287}
288
289static void
290test_add_networks (void)
291{
292 GNetworkMonitor *monitor;
293 GError *error = NULL;
294
295 monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, error: &error, NULL);
296 g_assert_no_error (error);
297 assert_signals (monitor, FALSE, FALSE, TRUE);
298
299 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
300 network: ip4_default);
301 assert_signals (monitor, FALSE, TRUE, TRUE);
302 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
303 network: ip6_default);
304 assert_signals (monitor, TRUE, TRUE, FALSE);
305
306 /* Now add the masks one by one */
307
308 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
309 network: net127.mask);
310 assert_signals (monitor, FALSE, TRUE, FALSE);
311
312 run_tests (monitor, addresses: net127.addresses, TRUE);
313 run_tests (monitor, addresses: net10.addresses, FALSE);
314 run_tests (monitor, addresses: net192.addresses, FALSE);
315 run_tests (monitor, addresses: netlocal6.addresses, FALSE);
316 run_tests (monitor, addresses: netfe80.addresses, FALSE);
317 run_tests (monitor, addresses: unmatched, FALSE);
318
319 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
320 network: net10.mask);
321 assert_signals (monitor, FALSE, TRUE, FALSE);
322 run_tests (monitor, addresses: net127.addresses, TRUE);
323 run_tests (monitor, addresses: net10.addresses, TRUE);
324 run_tests (monitor, addresses: net192.addresses, FALSE);
325 run_tests (monitor, addresses: netlocal6.addresses, FALSE);
326 run_tests (monitor, addresses: netfe80.addresses, FALSE);
327 run_tests (monitor, addresses: unmatched, FALSE);
328
329 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
330 network: net192.mask);
331 assert_signals (monitor, FALSE, TRUE, FALSE);
332 run_tests (monitor, addresses: net127.addresses, TRUE);
333 run_tests (monitor, addresses: net10.addresses, TRUE);
334 run_tests (monitor, addresses: net192.addresses, TRUE);
335 run_tests (monitor, addresses: netlocal6.addresses, FALSE);
336 run_tests (monitor, addresses: netfe80.addresses, FALSE);
337 run_tests (monitor, addresses: unmatched, FALSE);
338
339 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
340 network: netlocal6.mask);
341 assert_signals (monitor, FALSE, TRUE, FALSE);
342 run_tests (monitor, addresses: net127.addresses, TRUE);
343 run_tests (monitor, addresses: net10.addresses, TRUE);
344 run_tests (monitor, addresses: net192.addresses, TRUE);
345 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
346 run_tests (monitor, addresses: netfe80.addresses, FALSE);
347 run_tests (monitor, addresses: unmatched, FALSE);
348
349 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
350 network: netfe80.mask);
351 assert_signals (monitor, FALSE, TRUE, FALSE);
352 run_tests (monitor, addresses: net127.addresses, TRUE);
353 run_tests (monitor, addresses: net10.addresses, TRUE);
354 run_tests (monitor, addresses: net192.addresses, TRUE);
355 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
356 run_tests (monitor, addresses: netfe80.addresses, TRUE);
357 run_tests (monitor, addresses: unmatched, FALSE);
358
359 g_object_unref (object: monitor);
360}
361
362static void
363test_remove_networks (void)
364{
365 GNetworkMonitor *monitor;
366 GError *error = NULL;
367
368 monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, error: &error, NULL);
369 g_assert_no_error (error);
370 assert_signals (monitor, FALSE, FALSE, TRUE);
371
372 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
373 network: ip4_default);
374 assert_signals (monitor, FALSE, TRUE, TRUE);
375 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
376 network: ip6_default);
377 assert_signals (monitor, TRUE, TRUE, FALSE);
378
379 /* First add them */
380 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
381 network: net127.mask);
382 assert_signals (monitor, FALSE, TRUE, FALSE);
383 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
384 network: net10.mask);
385 assert_signals (monitor, FALSE, TRUE, FALSE);
386 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
387 network: net192.mask);
388 assert_signals (monitor, FALSE, TRUE, FALSE);
389 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
390 network: netlocal6.mask);
391 assert_signals (monitor, FALSE, TRUE, FALSE);
392 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
393 network: netfe80.mask);
394 assert_signals (monitor, FALSE, TRUE, FALSE);
395
396 run_tests (monitor, addresses: net127.addresses, TRUE);
397 run_tests (monitor, addresses: net10.addresses, TRUE);
398 run_tests (monitor, addresses: net192.addresses, TRUE);
399 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
400 run_tests (monitor, addresses: netfe80.addresses, TRUE);
401 run_tests (monitor, addresses: unmatched, FALSE);
402
403 /* Now remove them one by one */
404 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
405 network: net127.mask);
406 assert_signals (monitor, FALSE, TRUE, FALSE);
407 run_tests (monitor, addresses: net127.addresses, FALSE);
408 run_tests (monitor, addresses: net10.addresses, TRUE);
409 run_tests (monitor, addresses: net192.addresses, TRUE);
410 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
411 run_tests (monitor, addresses: netfe80.addresses, TRUE);
412 run_tests (monitor, addresses: unmatched, FALSE);
413
414 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
415 network: net10.mask);
416 assert_signals (monitor, FALSE, TRUE, FALSE);
417 run_tests (monitor, addresses: net127.addresses, FALSE);
418 run_tests (monitor, addresses: net10.addresses, FALSE);
419 run_tests (monitor, addresses: net192.addresses, TRUE);
420 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
421 run_tests (monitor, addresses: netfe80.addresses, TRUE);
422 run_tests (monitor, addresses: unmatched, FALSE);
423
424 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
425 network: net192.mask);
426 assert_signals (monitor, FALSE, TRUE, FALSE);
427 run_tests (monitor, addresses: net127.addresses, FALSE);
428 run_tests (monitor, addresses: net10.addresses, FALSE);
429 run_tests (monitor, addresses: net192.addresses, FALSE);
430 run_tests (monitor, addresses: netlocal6.addresses, TRUE);
431 run_tests (monitor, addresses: netfe80.addresses, TRUE);
432 run_tests (monitor, addresses: unmatched, FALSE);
433
434 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
435 network: netlocal6.mask);
436 assert_signals (monitor, FALSE, TRUE, FALSE);
437 run_tests (monitor, addresses: net127.addresses, FALSE);
438 run_tests (monitor, addresses: net10.addresses, FALSE);
439 run_tests (monitor, addresses: net192.addresses, FALSE);
440 run_tests (monitor, addresses: netlocal6.addresses, FALSE);
441 run_tests (monitor, addresses: netfe80.addresses, TRUE);
442 run_tests (monitor, addresses: unmatched, FALSE);
443
444 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
445 network: netfe80.mask);
446 assert_signals (monitor, FALSE, TRUE, FALSE);
447 run_tests (monitor, addresses: net127.addresses, FALSE);
448 run_tests (monitor, addresses: net10.addresses, FALSE);
449 run_tests (monitor, addresses: net192.addresses, FALSE);
450 run_tests (monitor, addresses: netlocal6.addresses, FALSE);
451 run_tests (monitor, addresses: netfe80.addresses, FALSE);
452 run_tests (monitor, addresses: unmatched, FALSE);
453
454 g_object_unref (object: monitor);
455}
456
457
458static void
459init_test (TestMask *test)
460{
461 GError *error = NULL;
462 int i;
463
464 test->mask = g_inet_address_mask_new_from_string (mask_string: test->mask_string, error: &error);
465 g_assert_no_error (error);
466
467 for (i = 0; test->addresses[i].string; i++)
468 {
469 test->addresses[i].address = g_inet_address_new_from_string (string: test->addresses[i].string);
470 if (strchr (s: test->addresses[i].string, c: ':'))
471 g_assert_cmpint (g_inet_address_get_family (test->addresses[i].address), ==, G_SOCKET_FAMILY_IPV6);
472 else
473 g_assert_cmpint (g_inet_address_get_family (test->addresses[i].address), ==, G_SOCKET_FAMILY_IPV4);
474 }
475}
476
477static void
478cleanup_test (TestMask *test)
479{
480 int i;
481
482 g_object_unref (object: test->mask);
483 for (i = 0; test->addresses[i].string; i++)
484 g_object_unref (object: test->addresses[i].address);
485}
486
487static void
488watch_network_changed (GNetworkMonitor *monitor,
489 gboolean available,
490 gpointer user_data)
491{
492 g_print (format: "Network is %s\n", available ? "up" : "down");
493}
494
495static void
496watch_connectivity_changed (GNetworkMonitor *monitor,
497 GParamSpec *pspec,
498 gpointer user_data)
499{
500 g_print (format: "Connectivity is %d\n", g_network_monitor_get_connectivity (monitor));
501}
502
503static void
504watch_metered_changed (GNetworkMonitor *monitor,
505 GParamSpec *pspec,
506 gpointer user_data)
507{
508 g_print (format: "Metered is %d\n", g_network_monitor_get_network_metered (monitor));
509}
510
511static void
512do_watch_network (void)
513{
514 GNetworkMonitor *monitor = g_network_monitor_get_default ();
515 GMainLoop *loop;
516
517 g_print (format: "Monitoring via %s\n", g_type_name_from_instance (instance: (GTypeInstance *) monitor));
518
519 g_signal_connect (monitor, "network-changed",
520 G_CALLBACK (watch_network_changed), NULL);
521 g_signal_connect (monitor, "notify::connectivity",
522 G_CALLBACK (watch_connectivity_changed), NULL);
523 g_signal_connect (monitor, "notify::network-metered",
524 G_CALLBACK (watch_metered_changed), NULL);
525 watch_network_changed (monitor, available: g_network_monitor_get_network_available (monitor), NULL);
526 watch_connectivity_changed (monitor, NULL, NULL);
527 watch_metered_changed (monitor, NULL, NULL);
528
529 loop = g_main_loop_new (NULL, FALSE);
530 g_main_loop_run (loop);
531}
532
533int
534main (int argc, char **argv)
535{
536 int ret;
537
538 if (argc == 2 && !strcmp (s1: argv[1], s2: "--watch"))
539 {
540 do_watch_network ();
541 return 0;
542 }
543
544 g_test_init (argc: &argc, argv: &argv, NULL);
545
546 /* GNetworkMonitor will resolve addresses through a proxy if one is set and a
547 * GIO module is available to handle it. In these tests we deliberately
548 * change the idea of a reachable network to exclude the proxy, which will
549 * lead to negative results. We're not trying to test the proxy-resolving
550 * functionality (that would be for e.g. glib-networking's testsuite), so
551 * let's just use the dummy proxy resolver, which always pretends the
552 * passed-in URL is directly resolvable.
553 */
554 g_setenv (variable: "GIO_USE_PROXY_RESOLVER", value: "dummy", TRUE);
555
556 init_test (test: &net127);
557 init_test (test: &net10);
558 init_test (test: &net192);
559 init_test (test: &netlocal6);
560 init_test (test: &netfe80);
561 ip4_default = g_inet_address_mask_new_from_string (mask_string: "0.0.0.0/0", NULL);
562 ip6_default = g_inet_address_mask_new_from_string (mask_string: "::/0", NULL);
563
564 g_test_add_func (testpath: "/network-monitor/default", test_func: test_default);
565 g_test_add_func (testpath: "/network-monitor/remove_default", test_func: test_remove_default);
566 g_test_add_func (testpath: "/network-monitor/add_networks", test_func: test_add_networks);
567 g_test_add_func (testpath: "/network-monitor/remove_networks", test_func: test_remove_networks);
568
569 ret = g_test_run ();
570
571 cleanup_test (test: &net127);
572 cleanup_test (test: &net10);
573 cleanup_test (test: &net192);
574 cleanup_test (test: &netlocal6);
575 cleanup_test (test: &netfe80);
576 g_object_unref (object: ip4_default);
577 g_object_unref (object: ip6_default);
578
579 return ret;
580}
581

source code of gtk/subprojects/glib/gio/tests/network-monitor.c