(root)/
glib-2.79.0/
gio/
tests/
proxy.c
       1  /* GLib testing framework examples and tests
       2   *
       3   * Copyright (C) 2010 Collabora, Ltd.
       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   * Authors: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
      21   */
      22  
      23  #include "config.h"
      24  
      25  #include <stdio.h>
      26  #include <stdlib.h>
      27  #include <string.h>
      28  
      29  #include <gio/gio.h>
      30  #include <glib.h>
      31  
      32  #include "glibintl.h"
      33  
      34  #ifdef G_OS_UNIX
      35  #include "gio/gunixsocketaddress.h"
      36  #endif
      37  
      38  static const gchar *info = NULL;
      39  static GCancellable *cancellable = NULL;
      40  static gint return_value = 0;
      41  
      42  static G_NORETURN void
      43  usage (void)
      44  {
      45    fprintf (stderr, "Usage: proxy [-s] (uri|host:port|ip:port|path|srv/protocol/domain)\n");
      46    fprintf (stderr, "       Use -t to enable threading.\n");
      47    fprintf (stderr, "       Use -s to do synchronous lookups.\n");
      48    fprintf (stderr, "       Use -c to cancel operation.\n");
      49    fprintf (stderr, "       Use -e to use enumerator.\n");
      50    fprintf (stderr, "       Use -inet to use GInetSocketAddress enumerator (ip:port).\n");
      51  #ifdef G_OS_UNIX
      52    fprintf (stderr, "       Use -unix to use GUnixSocketAddress enumerator (path).\n");
      53  #endif
      54    fprintf (stderr, "       Use -proxyaddr tp use GProxyAddress enumerator "
      55                     "(ip:port:protocol:dest_host:dest_port[:username[:password]]).\n");
      56    fprintf (stderr, "       Use -netaddr to use GNetworkAddress enumerator (host:port).\n");
      57    fprintf (stderr, "       Use -neturi to use GNetworkAddress enumerator (uri).\n");
      58    fprintf (stderr, "       Use -netsrv to use GNetworkService enumerator (srv/protocol/domain).\n");
      59    fprintf (stderr, "       Use -connect to create a connection using GSocketClient object (uri).\n");
      60    exit (1);
      61  }
      62  
      63  static void
      64  print_and_free_error (GError *error)
      65  {
      66    fprintf (stderr, "Failed to obtain proxies: %s\n", error->message);
      67    g_error_free (error);
      68    return_value = 1;
      69  }
      70  
      71  static void
      72  print_proxies (const gchar *local_info, gchar **proxies)
      73  {
      74    printf ("Proxies for URI '%s' are:\n", local_info);
      75  
      76    if (proxies == NULL || proxies[0] == NULL)
      77      printf ("\tnone\n");
      78    else
      79      for (; proxies[0]; proxies++)
      80        printf ("\t%s\n", proxies[0]);
      81  }
      82  
      83  static void
      84  _proxy_lookup_cb (GObject *source_object,
      85  		  GAsyncResult *result,
      86  		  gpointer user_data)
      87  {
      88    GError *error = NULL;
      89    gchar **proxies;
      90    GMainLoop *loop = user_data;
      91  
      92    proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (source_object),
      93  					    result,
      94  					    &error);
      95    if (error)
      96      {
      97        print_and_free_error (error);
      98      }
      99    else
     100      {
     101        print_proxies (info, proxies);
     102        g_strfreev (proxies);
     103      }
     104  
     105    g_main_loop_quit (loop);
     106  }
     107  
     108  static void
     109  use_resolver (gboolean synchronous)
     110  {
     111    GProxyResolver *resolver;
     112  
     113    resolver = g_proxy_resolver_get_default ();
     114  
     115    if (synchronous)
     116      {
     117        GError *error = NULL;
     118        gchar **proxies;
     119  
     120        proxies = g_proxy_resolver_lookup (resolver, info, cancellable, &error);
     121  
     122        if (error)
     123  	  print_and_free_error (error);
     124        else
     125  	  print_proxies (info, proxies);
     126  
     127        g_strfreev (proxies);
     128      }
     129    else
     130      {
     131        GMainLoop *loop = g_main_loop_new (NULL, FALSE);
     132  
     133        g_proxy_resolver_lookup_async (resolver,
     134  				     info,
     135  				     cancellable,
     136  				     _proxy_lookup_cb,
     137  				     loop);
     138  
     139        g_main_loop_run (loop);
     140        g_main_loop_unref (loop);
     141      }
     142  }
     143  
     144  static void
     145  print_proxy_address (GSocketAddress *sockaddr)
     146  {
     147    GProxyAddress *proxy = NULL;
     148  
     149    if (sockaddr == NULL)
     150      {
     151        printf ("\tdirect://\n");
     152        return;
     153      }
     154  
     155    if (G_IS_PROXY_ADDRESS (sockaddr))
     156      {
     157        proxy = G_PROXY_ADDRESS (sockaddr);
     158        printf ("\t%s://", g_proxy_address_get_protocol(proxy));
     159      }
     160    else
     161      {
     162        printf ("\tdirect://");
     163      }
     164  
     165    if (G_IS_INET_SOCKET_ADDRESS (sockaddr))
     166      {
     167        GInetAddress *inetaddr;
     168        guint port;
     169        gchar *addr;
     170  
     171        g_object_get (sockaddr,
     172  		    "address", &inetaddr,
     173  		    "port", &port,
     174  		    NULL);
     175  
     176        addr = g_inet_address_to_string (inetaddr);
     177  
     178        printf ("%s:%u", addr, port);
     179  
     180        g_free (addr);
     181      }
     182  
     183    if (proxy)
     184      {
     185        if (g_proxy_address_get_username(proxy))
     186          printf (" (Username: %s  Password: %s)",
     187                  g_proxy_address_get_username(proxy),
     188                  g_proxy_address_get_password(proxy));
     189        printf (" (Hostname: %s, Port: %i)",
     190                g_proxy_address_get_destination_hostname (proxy),
     191                g_proxy_address_get_destination_port (proxy));
     192      }
     193  
     194    printf ("\n");
     195  }
     196  
     197  static void
     198  _proxy_enumerate_cb (GObject *object,
     199  		     GAsyncResult *result,
     200  		     gpointer user_data)
     201  {
     202    GError *error = NULL;
     203    GMainLoop *loop = user_data;
     204    GSocketAddressEnumerator *enumerator = G_SOCKET_ADDRESS_ENUMERATOR (object);
     205    GSocketAddress *sockaddr;
     206  
     207    sockaddr = g_socket_address_enumerator_next_finish (enumerator,
     208  						      result,
     209  						      &error);
     210    if (sockaddr)
     211      {
     212        print_proxy_address (sockaddr);
     213        g_socket_address_enumerator_next_async (enumerator,
     214                                                cancellable,
     215  					      _proxy_enumerate_cb,
     216  					      loop);
     217        g_object_unref (sockaddr);
     218      }
     219    else
     220      {
     221        if (error)
     222  	print_and_free_error (error);
     223  
     224        g_main_loop_quit (loop);
     225      }
     226  }
     227  
     228  static void
     229  run_with_enumerator (gboolean synchronous, GSocketAddressEnumerator *enumerator)
     230  {
     231    GError *error = NULL;
     232  
     233    if (synchronous)
     234      {
     235        GSocketAddress *sockaddr;
     236  
     237        while ((sockaddr = g_socket_address_enumerator_next (enumerator,
     238  							   cancellable,
     239  							   &error)))
     240  	{
     241  	  print_proxy_address (sockaddr);
     242  	  g_object_unref (sockaddr);
     243  	}
     244  
     245        if (error)
     246  	print_and_free_error (error);
     247      }
     248    else
     249      {
     250        GMainLoop *loop = g_main_loop_new (NULL, FALSE);
     251  
     252        g_socket_address_enumerator_next_async (enumerator,
     253                                                cancellable,
     254  					      _proxy_enumerate_cb,
     255  					      loop);
     256        g_main_loop_run (loop);
     257        g_main_loop_unref (loop);
     258      }
     259  }
     260  
     261  static void
     262  use_enumerator (gboolean synchronous)
     263  {
     264    GSocketAddressEnumerator *enumerator;
     265  
     266    enumerator = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
     267  			     "uri", info,
     268  			     NULL);
     269  
     270    printf ("Proxies for URI '%s' are:\n", info);
     271    run_with_enumerator (synchronous, enumerator);
     272  
     273    g_object_unref (enumerator);
     274  }
     275  
     276  static void
     277  use_inet_address (gboolean synchronous)
     278  {
     279    GSocketAddressEnumerator *enumerator;
     280    GSocketAddress *sockaddr;
     281    GInetAddress *addr = NULL;
     282    guint port = 0;
     283    gchar **ip_and_port;
     284  
     285    ip_and_port = g_strsplit (info, ":", 2);
     286  
     287    if (ip_and_port[0])
     288      {
     289        addr = g_inet_address_new_from_string (ip_and_port[0]);
     290        if (ip_and_port [1])
     291  	port = strtoul (ip_and_port [1], NULL, 10);
     292      }
     293  
     294    g_strfreev (ip_and_port);
     295  
     296    if (addr == NULL || port <= 0 || port >= 65535)
     297      {
     298        fprintf (stderr, "Bad 'ip:port' parameter '%s'\n", info);
     299        if (addr)
     300  	g_object_unref (addr);
     301        return_value = 1;
     302        return;
     303      }
     304  
     305    sockaddr = g_inet_socket_address_new (addr, port);
     306    g_object_unref (addr);
     307  
     308    enumerator =
     309      g_socket_connectable_proxy_enumerate (G_SOCKET_CONNECTABLE (sockaddr));
     310    g_object_unref (sockaddr);
     311  
     312    printf ("Proxies for ip and port '%s' are:\n", info);
     313    run_with_enumerator (synchronous, enumerator);
     314  
     315    g_object_unref (enumerator);
     316  }
     317  
     318  #ifdef G_OS_UNIX
     319  static void
     320  use_unix_address (gboolean synchronous)
     321  {
     322    GSocketAddressEnumerator *enumerator;
     323    GSocketAddress *sockaddr;
     324  
     325    sockaddr = g_unix_socket_address_new_with_type (info, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT);
     326  
     327    if (sockaddr == NULL)
     328      {
     329        fprintf (stderr, "Failed to create unix socket with name '%s'\n", info);
     330        return_value = 1;
     331        return;
     332      }
     333  
     334    enumerator =
     335      g_socket_connectable_proxy_enumerate (G_SOCKET_CONNECTABLE (sockaddr));
     336    g_object_unref (sockaddr);
     337  
     338    printf ("Proxies for path '%s' are:\n", info);
     339    run_with_enumerator (synchronous, enumerator);
     340  
     341    g_object_unref (enumerator);
     342  }
     343  #endif
     344  
     345  static void
     346  use_proxy_address (gboolean synchronous)
     347  {
     348    GSocketAddressEnumerator *enumerator;
     349    GSocketAddress *sockaddr;
     350    GInetAddress *addr;
     351    guint port = 0;
     352    gchar *protocol;
     353    gchar *dest_host;
     354    guint dest_port;
     355    gchar *username = NULL;
     356    gchar *password = NULL;
     357    gchar **split_info;
     358  
     359    split_info = g_strsplit (info, ":", 7);
     360  
     361    if (!split_info[0]
     362        || !split_info[1]
     363        || !split_info[2]
     364        || !split_info[3]
     365        || !split_info[4])
     366      {
     367        fprintf (stderr, "Bad 'ip:port:protocol:dest_host:dest_port' parameter '%s'\n", info);
     368        return_value = 1;
     369        return;
     370      }
     371  
     372    addr = g_inet_address_new_from_string (split_info[0]);
     373    port = strtoul (split_info [1], NULL, 10);
     374    protocol = g_strdup (split_info[2]);
     375    dest_host = g_strdup (split_info[3]);
     376    dest_port = strtoul (split_info[4], NULL, 10);
     377   
     378    if (split_info[5])
     379      {
     380        username = g_strdup (split_info[5]);
     381        if (split_info[6])
     382          password = g_strdup (split_info[6]);
     383      }
     384  
     385    g_strfreev (split_info);
     386  
     387    sockaddr = g_proxy_address_new (addr, port,
     388                                    protocol, dest_host, dest_port,
     389                                    username, password);
     390    
     391    g_object_unref (addr);
     392    g_free (protocol);
     393    g_free (dest_host);
     394    g_free (username);
     395    g_free (password);
     396  
     397    enumerator =
     398      g_socket_connectable_proxy_enumerate (G_SOCKET_CONNECTABLE (sockaddr));
     399    g_object_unref (sockaddr);
     400  
     401    printf ("Proxies for ip and port '%s' are:\n", info);
     402    run_with_enumerator (synchronous, enumerator);
     403  
     404    g_object_unref (enumerator);
     405  }
     406  
     407  static void
     408  use_network_address (gboolean synchronous)
     409  {
     410    GError *error = NULL;
     411    GSocketAddressEnumerator *enumerator;
     412    GSocketConnectable *connectable;
     413  
     414    connectable = g_network_address_parse (info, -1, &error);
     415  
     416    if (error)
     417      {
     418        print_and_free_error (error);
     419        return;
     420      }
     421  
     422    enumerator = g_socket_connectable_proxy_enumerate (connectable);
     423    g_object_unref (connectable);
     424  
     425    printf ("Proxies for hostname and port '%s' are:\n", info);
     426    run_with_enumerator (synchronous, enumerator);
     427  
     428    g_object_unref (enumerator);
     429  }
     430  
     431  static void
     432  use_network_uri (gboolean synchronous)
     433  {
     434    GError *error = NULL;
     435    GSocketAddressEnumerator *enumerator;
     436    GSocketConnectable *connectable;
     437  
     438    connectable = g_network_address_parse_uri (info, 0, &error);
     439  
     440    if (error)
     441      {
     442        print_and_free_error (error);
     443        return;
     444      }
     445  
     446    enumerator = g_socket_connectable_proxy_enumerate (connectable);
     447    g_object_unref (connectable);
     448  
     449    printf ("Proxies for URI '%s' are:\n", info);
     450    run_with_enumerator (synchronous, enumerator);
     451  
     452    g_object_unref (enumerator);
     453  }
     454  
     455  static void
     456  use_network_service (gboolean synchronous)
     457  {
     458    GSocketAddressEnumerator *enumerator;
     459    GSocketConnectable *connectable = NULL;
     460    gchar **split;
     461  
     462    split = g_strsplit (info, "/", 3);
     463  
     464    if (split[0] && split[1] && split[2])
     465      connectable = g_network_service_new (split[0], split[1], split[2]);
     466  
     467    g_strfreev (split);
     468  
     469    if (connectable == NULL)
     470      {
     471         fprintf (stderr, "Bad 'srv/protocol/domain' parameter '%s'\n", info);
     472         return_value = 1;
     473         return;
     474      }
     475  
     476    enumerator = g_socket_connectable_proxy_enumerate (connectable);
     477    g_object_unref (connectable);
     478  
     479    printf ("Proxies for hostname and port '%s' are:\n", info);
     480    run_with_enumerator (synchronous, enumerator);
     481  
     482    g_object_unref (enumerator);
     483  }
     484  
     485  static void
     486  _socket_connect_cb (GObject *object,
     487  		    GAsyncResult *result,
     488  		    gpointer user_data)
     489  {
     490    GError *error = NULL;
     491    GMainLoop *loop = user_data;
     492    GSocketClient *client = G_SOCKET_CLIENT (object);
     493    GSocketConnection *connection;
     494  
     495    connection = g_socket_client_connect_to_uri_finish (client,
     496  						      result,
     497  						      &error);
     498    if (connection)
     499      {
     500        GSocketAddress *proxy_addr;
     501        proxy_addr = g_socket_connection_get_remote_address (connection, NULL);
     502        print_proxy_address (proxy_addr);
     503      }
     504    else
     505      {
     506        print_and_free_error (error);
     507      }
     508  
     509    g_main_loop_quit (loop);
     510  }
     511  
     512  static void
     513  use_socket_client (gboolean synchronous)
     514  {
     515    GError *error = NULL;
     516    GSocketClient *client;
     517  
     518    client = g_socket_client_new ();
     519  
     520    printf ("Proxies for URI '%s' are:\n", info);
     521  
     522    if (synchronous)
     523      {
     524        GSocketConnection *connection;
     525        GSocketAddress *proxy_addr;
     526  
     527        connection = g_socket_client_connect_to_uri (client,
     528  						   info,
     529  						   0,
     530        						   cancellable,
     531  						   &error);
     532  
     533        if (connection)
     534  	{
     535  	  proxy_addr = g_socket_connection_get_remote_address (connection, NULL);
     536  	  print_proxy_address (proxy_addr);
     537  	}
     538        else
     539  	{
     540  	  print_and_free_error (error);
     541  	}
     542      }
     543    else
     544      {
     545        GMainLoop *loop = g_main_loop_new (NULL, FALSE);
     546  
     547        g_socket_client_connect_to_uri_async (client,
     548  					    info,
     549  					    0,
     550  					    cancellable,
     551  					    _socket_connect_cb,
     552  					    loop);
     553  
     554        g_main_loop_run (loop);
     555        g_main_loop_unref (loop);
     556      }
     557  
     558    g_object_unref (client);
     559  }
     560  
     561  typedef enum
     562  {
     563    USE_RESOLVER,
     564    USE_ENUMERATOR,
     565  #ifdef G_OS_UNIX
     566    USE_UNIX_SOCKET_ADDRESS,
     567  #endif
     568    USE_INET_SOCKET_ADDRESS,
     569    USE_PROXY_ADDRESS,
     570    USE_NETWORK_ADDRESS,
     571    USE_NETWORK_URI,
     572    USE_NETWORK_SERVICE,
     573    USE_SOCKET_CLIENT,
     574  } ProxyTestType;
     575  
     576  gint
     577  main (gint argc, gchar **argv)
     578  {
     579    gboolean synchronous = FALSE;
     580    gboolean cancel = FALSE;
     581    ProxyTestType type = USE_RESOLVER;
     582  
     583    while (argc >= 2 && argv[1][0] == '-')
     584      {
     585        if (!strcmp (argv[1], "-s"))
     586          synchronous = TRUE;
     587        else if (!strcmp (argv[1], "-c"))
     588          cancel = TRUE;
     589        else if (!strcmp (argv[1], "-e"))
     590          type = USE_ENUMERATOR;
     591        else if (!strcmp (argv[1], "-inet"))
     592          type = USE_INET_SOCKET_ADDRESS;
     593  #ifdef G_OS_UNIX
     594        else if (!strcmp (argv[1], "-unix"))
     595          type = USE_UNIX_SOCKET_ADDRESS;
     596  #endif
     597        else if (!strcmp (argv[1], "-proxyaddr"))
     598          type = USE_PROXY_ADDRESS;
     599        else if (!strcmp (argv[1], "-netaddr"))
     600          type = USE_NETWORK_ADDRESS;
     601        else if (!strcmp (argv[1], "-neturi"))
     602          type = USE_NETWORK_URI;
     603        else if (!strcmp (argv[1], "-netsrv"))
     604          type = USE_NETWORK_SERVICE;
     605        else if (!strcmp (argv[1], "-connect"))
     606          type = USE_SOCKET_CLIENT;
     607        else
     608  	usage ();
     609  
     610        argv++;
     611        argc--;
     612      }
     613  
     614    if (argc != 2)
     615      usage ();
     616  
     617    /* Save URI for asynchronous callback */
     618    info = argv[1];
     619  
     620    if (cancel)
     621      {
     622        cancellable = g_cancellable_new ();
     623        g_cancellable_cancel (cancellable);
     624      }
     625  
     626    switch (type)
     627      {
     628      case USE_RESOLVER:
     629        use_resolver (synchronous);
     630        break;
     631      case USE_ENUMERATOR:
     632        use_enumerator (synchronous);
     633        break;
     634      case USE_INET_SOCKET_ADDRESS:
     635        use_inet_address (synchronous);
     636        break;
     637  #ifdef G_OS_UNIX
     638      case USE_UNIX_SOCKET_ADDRESS:
     639        use_unix_address (synchronous);
     640        break;
     641  #endif
     642      case USE_PROXY_ADDRESS:
     643        use_proxy_address (synchronous);
     644        break;
     645      case USE_NETWORK_ADDRESS:
     646        use_network_address (synchronous);
     647        break;
     648      case USE_NETWORK_URI:
     649        use_network_uri (synchronous);
     650        break;
     651      case USE_NETWORK_SERVICE:
     652        use_network_service (synchronous);
     653        break;
     654      case USE_SOCKET_CLIENT:
     655        use_socket_client (synchronous);
     656        break;
     657      }
     658  
     659    return return_value;
     660  }