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