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

source code of gtk/subprojects/glib/gio/tests/proxy.c