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