• 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 "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 
33 typedef struct {
34   const char *string;
35   GInetAddress *address;
36 } TestAddress;
37 
38 typedef struct {
39   const char *mask_string;
40   GInetAddressMask *mask;
41   TestAddress *addresses;
42 } TestMask;
43 
44 TestAddress 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 };
54 TestMask net127 = { "127.0.0.0/8", NULL, net127addrs };
55 
56 TestAddress net10addrs[] = {
57   { "10.0.0.1", NULL },
58   { "10.0.0.2", NULL },
59   { "10.0.0.255", NULL },
60   { NULL, NULL }
61 };
62 TestMask net10 = { "10.0.0.0/24", NULL, net10addrs };
63 
64 TestAddress net192addrs[] = {
65   { "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 };
72 TestMask net192 = { "192.168.0.0/20", NULL, net192addrs };
73 
74 TestAddress netlocal6addrs[] = {
75   { "::1", NULL },
76   { NULL, NULL }
77 };
78 TestMask netlocal6 = { "::1/128", NULL, netlocal6addrs };
79 
80 TestAddress netfe80addrs[] = {
81   { "fe80::", NULL },
82   { "fe80::1", NULL },
83   { "fe80::21b:77ff:fea2:972a", NULL },
84   { NULL, NULL }
85 };
86 TestMask netfe80 = { "fe80::/64", NULL, netfe80addrs };
87 
88 TestAddress unmatched[] = {
89   { "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 
103 GInetAddressMask *ip4_default, *ip6_default;
104 
105 static void
notify_handler(GObject * object,GParamSpec * pspec,gpointer user_data)106 notify_handler (GObject    *object,
107                 GParamSpec *pspec,
108                 gpointer    user_data)
109 {
110   gboolean *emitted = user_data;
111 
112   *emitted = TRUE;
113 }
114 
115 static void
network_changed_handler(GNetworkMonitor * monitor,gboolean available,gpointer user_data)116 network_changed_handler (GNetworkMonitor *monitor,
117                          gboolean         available,
118                          gpointer         user_data)
119 {
120   gboolean *emitted = user_data;
121 
122   *emitted = TRUE;
123 }
124 
125 static void
assert_signals(GNetworkMonitor * monitor,gboolean should_emit_notify,gboolean should_emit_network_changed,gboolean expected_network_available)126 assert_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 (monitor, h1);
144   g_signal_handler_disconnect (monitor, 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 
152 typedef struct {
153   GNetworkMonitor *monitor;
154   GMainLoop       *loop;
155   GSocketAddress  *sockaddr;
156   gboolean         should_be_reachable;
157 } CanReachData;
158 
159 static void
reach_cb(GObject * source,GAsyncResult * res,gpointer user_data)160 reach_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 (data->monitor, res, &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 (&error);
176     }
177   g_assert (reachable == data->should_be_reachable);
178 
179   g_main_loop_quit (data->loop);
180 }
181 
182 static gboolean
test_reach_async(gpointer user_data)183 test_reach_async (gpointer user_data)
184 {
185   CanReachData *data = user_data;
186 
187   g_network_monitor_can_reach_async (data->monitor,
188                                      G_SOCKET_CONNECTABLE (data->sockaddr),
189                                      NULL,
190                                      reach_cb,
191                                      data);
192   return G_SOURCE_REMOVE;
193 }
194 
195 static void
run_tests(GNetworkMonitor * monitor,TestAddress * addresses,gboolean should_be_reachable)196 run_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 (addresses[i].address, 0);
212       reachable = g_network_monitor_can_reach (monitor,
213                                                G_SOCKET_CONNECTABLE (sockaddr),
214                                                NULL, &error);
215       data.sockaddr = sockaddr;
216       data.should_be_reachable = should_be_reachable;
217 
218       g_idle_add (test_reach_async, &data);
219       g_main_loop_run (data.loop);
220 
221       g_object_unref (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 (&error);
229         }
230     }
231 
232   g_main_loop_unref (data.loop);
233 }
234 
235 static void
test_default(void)236 test_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);
246   g_assert_no_error (error);
247 
248   /* In the default configuration, all addresses are reachable */
249   run_tests (monitor, net127.addresses, TRUE);
250   run_tests (monitor, net10.addresses, TRUE);
251   run_tests (monitor, net192.addresses, TRUE);
252   run_tests (monitor, netlocal6.addresses, TRUE);
253   run_tests (monitor, netfe80.addresses, TRUE);
254   run_tests (monitor, unmatched, TRUE);
255 
256   assert_signals (monitor, FALSE, FALSE, TRUE);
257 
258   g_object_unref (monitor);
259 }
260 
261 static void
test_remove_default(void)262 test_remove_default (void)
263 {
264   GNetworkMonitor *monitor;
265   GError *error = NULL;
266 
267   monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, &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                                          ip4_default);
273   assert_signals (monitor, FALSE, TRUE, TRUE);
274   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
275                                          ip6_default);
276   assert_signals (monitor, TRUE, TRUE, FALSE);
277 
278   /* Now nothing should be reachable */
279   run_tests (monitor, net127.addresses, FALSE);
280   run_tests (monitor, net10.addresses, FALSE);
281   run_tests (monitor, net192.addresses, FALSE);
282   run_tests (monitor, netlocal6.addresses, FALSE);
283   run_tests (monitor, netfe80.addresses, FALSE);
284   run_tests (monitor, unmatched, FALSE);
285 
286   g_object_unref (monitor);
287 }
288 
289 static void
test_add_networks(void)290 test_add_networks (void)
291 {
292   GNetworkMonitor *monitor;
293   GError *error = NULL;
294 
295   monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, &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                                          ip4_default);
301   assert_signals (monitor, FALSE, TRUE, TRUE);
302   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
303                                          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                                       net127.mask);
310   assert_signals (monitor, FALSE, TRUE, FALSE);
311 
312   run_tests (monitor, net127.addresses, TRUE);
313   run_tests (monitor, net10.addresses, FALSE);
314   run_tests (monitor, net192.addresses, FALSE);
315   run_tests (monitor, netlocal6.addresses, FALSE);
316   run_tests (monitor, netfe80.addresses, FALSE);
317   run_tests (monitor, unmatched, FALSE);
318 
319   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
320                                       net10.mask);
321   assert_signals (monitor, FALSE, TRUE, FALSE);
322   run_tests (monitor, net127.addresses, TRUE);
323   run_tests (monitor, net10.addresses, TRUE);
324   run_tests (monitor, net192.addresses, FALSE);
325   run_tests (monitor, netlocal6.addresses, FALSE);
326   run_tests (monitor, netfe80.addresses, FALSE);
327   run_tests (monitor, unmatched, FALSE);
328 
329   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
330                                       net192.mask);
331   assert_signals (monitor, FALSE, TRUE, FALSE);
332   run_tests (monitor, net127.addresses, TRUE);
333   run_tests (monitor, net10.addresses, TRUE);
334   run_tests (monitor, net192.addresses, TRUE);
335   run_tests (monitor, netlocal6.addresses, FALSE);
336   run_tests (monitor, netfe80.addresses, FALSE);
337   run_tests (monitor, unmatched, FALSE);
338 
339   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
340                                       netlocal6.mask);
341   assert_signals (monitor, FALSE, TRUE, FALSE);
342   run_tests (monitor, net127.addresses, TRUE);
343   run_tests (monitor, net10.addresses, TRUE);
344   run_tests (monitor, net192.addresses, TRUE);
345   run_tests (monitor, netlocal6.addresses, TRUE);
346   run_tests (monitor, netfe80.addresses, FALSE);
347   run_tests (monitor, unmatched, FALSE);
348 
349   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
350                                       netfe80.mask);
351   assert_signals (monitor, FALSE, TRUE, FALSE);
352   run_tests (monitor, net127.addresses, TRUE);
353   run_tests (monitor, net10.addresses, TRUE);
354   run_tests (monitor, net192.addresses, TRUE);
355   run_tests (monitor, netlocal6.addresses, TRUE);
356   run_tests (monitor, netfe80.addresses, TRUE);
357   run_tests (monitor, unmatched, FALSE);
358 
359   g_object_unref (monitor);
360 }
361 
362 static void
test_remove_networks(void)363 test_remove_networks (void)
364 {
365   GNetworkMonitor *monitor;
366   GError *error = NULL;
367 
368   monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, &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                                          ip4_default);
374   assert_signals (monitor, FALSE, TRUE, TRUE);
375   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
376                                          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                                       net127.mask);
382   assert_signals (monitor, FALSE, TRUE, FALSE);
383   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
384                                       net10.mask);
385   assert_signals (monitor, FALSE, TRUE, FALSE);
386   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
387                                       net192.mask);
388   assert_signals (monitor, FALSE, TRUE, FALSE);
389   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
390                                       netlocal6.mask);
391   assert_signals (monitor, FALSE, TRUE, FALSE);
392   g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
393                                       netfe80.mask);
394   assert_signals (monitor, FALSE, TRUE, FALSE);
395 
396   run_tests (monitor, net127.addresses, TRUE);
397   run_tests (monitor, net10.addresses, TRUE);
398   run_tests (monitor, net192.addresses, TRUE);
399   run_tests (monitor, netlocal6.addresses, TRUE);
400   run_tests (monitor, netfe80.addresses, TRUE);
401   run_tests (monitor, unmatched, FALSE);
402 
403   /* Now remove them one by one */
404   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
405                                          net127.mask);
406   assert_signals (monitor, FALSE, TRUE, FALSE);
407   run_tests (monitor, net127.addresses, FALSE);
408   run_tests (monitor, net10.addresses, TRUE);
409   run_tests (monitor, net192.addresses, TRUE);
410   run_tests (monitor, netlocal6.addresses, TRUE);
411   run_tests (monitor, netfe80.addresses, TRUE);
412   run_tests (monitor, unmatched, FALSE);
413 
414   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
415                                          net10.mask);
416   assert_signals (monitor, FALSE, TRUE, FALSE);
417   run_tests (monitor, net127.addresses, FALSE);
418   run_tests (monitor, net10.addresses, FALSE);
419   run_tests (monitor, net192.addresses, TRUE);
420   run_tests (monitor, netlocal6.addresses, TRUE);
421   run_tests (monitor, netfe80.addresses, TRUE);
422   run_tests (monitor, unmatched, FALSE);
423 
424   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
425                                          net192.mask);
426   assert_signals (monitor, FALSE, TRUE, FALSE);
427   run_tests (monitor, net127.addresses, FALSE);
428   run_tests (monitor, net10.addresses, FALSE);
429   run_tests (monitor, net192.addresses, FALSE);
430   run_tests (monitor, netlocal6.addresses, TRUE);
431   run_tests (monitor, netfe80.addresses, TRUE);
432   run_tests (monitor, unmatched, FALSE);
433 
434   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
435                                          netlocal6.mask);
436   assert_signals (monitor, FALSE, TRUE, FALSE);
437   run_tests (monitor, net127.addresses, FALSE);
438   run_tests (monitor, net10.addresses, FALSE);
439   run_tests (monitor, net192.addresses, FALSE);
440   run_tests (monitor, netlocal6.addresses, FALSE);
441   run_tests (monitor, netfe80.addresses, TRUE);
442   run_tests (monitor, unmatched, FALSE);
443 
444   g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
445                                          netfe80.mask);
446   assert_signals (monitor, FALSE, TRUE, FALSE);
447   run_tests (monitor, net127.addresses, FALSE);
448   run_tests (monitor, net10.addresses, FALSE);
449   run_tests (monitor, net192.addresses, FALSE);
450   run_tests (monitor, netlocal6.addresses, FALSE);
451   run_tests (monitor, netfe80.addresses, FALSE);
452   run_tests (monitor, unmatched, FALSE);
453 
454   g_object_unref (monitor);
455 }
456 
457 
458 static void
init_test(TestMask * test)459 init_test (TestMask *test)
460 {
461   GError *error = NULL;
462   int i;
463 
464   test->mask = g_inet_address_mask_new_from_string (test->mask_string, &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 (test->addresses[i].string);
470       if (strchr (test->addresses[i].string, ':'))
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 
477 static void
cleanup_test(TestMask * test)478 cleanup_test (TestMask *test)
479 {
480   int i;
481 
482   g_object_unref (test->mask);
483   for (i = 0; test->addresses[i].string; i++)
484     g_object_unref (test->addresses[i].address);
485 }
486 
487 static void
watch_network_changed(GNetworkMonitor * monitor,gboolean available,gpointer user_data)488 watch_network_changed (GNetworkMonitor *monitor,
489                        gboolean         available,
490                        gpointer         user_data)
491 {
492   g_print ("Network is %s\n", available ? "up" : "down");
493 }
494 
495 static void
watch_connectivity_changed(GNetworkMonitor * monitor,GParamSpec * pspec,gpointer user_data)496 watch_connectivity_changed (GNetworkMonitor *monitor,
497 			    GParamSpec      *pspec,
498 			    gpointer         user_data)
499 {
500   g_print ("Connectivity is %d\n", g_network_monitor_get_connectivity (monitor));
501 }
502 
503 static void
watch_metered_changed(GNetworkMonitor * monitor,GParamSpec * pspec,gpointer user_data)504 watch_metered_changed (GNetworkMonitor *monitor,
505                        GParamSpec      *pspec,
506                        gpointer         user_data)
507 {
508   g_print ("Metered is %d\n", g_network_monitor_get_network_metered (monitor));
509 }
510 
511 static void
do_watch_network(void)512 do_watch_network (void)
513 {
514   GNetworkMonitor *monitor = g_network_monitor_get_default ();
515   GMainLoop *loop;
516 
517   g_print ("Monitoring via %s\n", g_type_name_from_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, 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 
533 int
main(int argc,char ** argv)534 main (int argc, char **argv)
535 {
536   int ret;
537 
538   if (argc == 2 && !strcmp (argv[1], "--watch"))
539     {
540       do_watch_network ();
541       return 0;
542     }
543 
544   g_test_init (&argc, &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 ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE);
555 
556   init_test (&net127);
557   init_test (&net10);
558   init_test (&net192);
559   init_test (&netlocal6);
560   init_test (&netfe80);
561   ip4_default = g_inet_address_mask_new_from_string ("0.0.0.0/0", NULL);
562   ip6_default = g_inet_address_mask_new_from_string ("::/0", NULL);
563 
564   g_test_add_func ("/network-monitor/default", test_default);
565   g_test_add_func ("/network-monitor/remove_default", test_remove_default);
566   g_test_add_func ("/network-monitor/add_networks", test_add_networks);
567   g_test_add_func ("/network-monitor/remove_networks", test_remove_networks);
568 
569   ret = g_test_run ();
570 
571   cleanup_test (&net127);
572   cleanup_test (&net10);
573   cleanup_test (&net192);
574   cleanup_test (&netlocal6);
575   cleanup_test (&netfe80);
576   g_object_unref (ip4_default);
577   g_object_unref (ip6_default);
578 
579   return ret;
580 }
581