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
36 static const gchar *info = NULL;
37 static GCancellable *cancellable = NULL;
38 static gint return_value = 0;
39
40 static G_NORETURN void
usage(void)41 usage (void)
42 {
43 fprintf (stderr, "Usage: proxy [-s] (uri|host:port|ip:port|path|srv/protocol/domain)\n");
44 fprintf (stderr, " Use -t to enable threading.\n");
45 fprintf (stderr, " Use -s to do synchronous lookups.\n");
46 fprintf (stderr, " Use -c to cancel operation.\n");
47 fprintf (stderr, " Use -e to use enumerator.\n");
48 fprintf (stderr, " Use -inet to use GInetSocketAddress enumerator (ip:port).\n");
49 #ifdef G_OS_UNIX
50 fprintf (stderr, " Use -unix to use GUnixSocketAddress enumerator (path).\n");
51 #endif
52 fprintf (stderr, " Use -proxyaddr tp use GProxyAddress enumerator "
53 "(ip:port:protocol:dest_host:dest_port[:username[:password]]).\n");
54 fprintf (stderr, " Use -netaddr to use GNetworkAddress enumerator (host:port).\n");
55 fprintf (stderr, " Use -neturi to use GNetworkAddress enumerator (uri).\n");
56 fprintf (stderr, " Use -netsrv to use GNetworkService enumerator (srv/protocol/domain).\n");
57 fprintf (stderr, " Use -connect to create a connection using GSocketClient object (uri).\n");
58 exit (1);
59 }
60
61 static void
print_and_free_error(GError * error)62 print_and_free_error (GError *error)
63 {
64 fprintf (stderr, "Failed to obtain proxies: %s\n", error->message);
65 g_error_free (error);
66 return_value = 1;
67 }
68
69 static void
print_proxies(const gchar * info,gchar ** proxies)70 print_proxies (const gchar *info, gchar **proxies)
71 {
72 printf ("Proxies for URI '%s' are:\n", info);
73
74 if (proxies == NULL || proxies[0] == NULL)
75 printf ("\tnone\n");
76 else
77 for (; proxies[0]; proxies++)
78 printf ("\t%s\n", proxies[0]);
79 }
80
81 static void
_proxy_lookup_cb(GObject * source_object,GAsyncResult * result,gpointer user_data)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);
93 if (error)
94 {
95 print_and_free_error (error);
96 }
97 else
98 {
99 print_proxies (info, proxies);
100 g_strfreev (proxies);
101 }
102
103 g_main_loop_quit (loop);
104 }
105
106 static void
use_resolver(gboolean synchronous)107 use_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, info, cancellable, &error);
119
120 if (error)
121 print_and_free_error (error);
122 else
123 print_proxies (info, proxies);
124
125 g_strfreev (proxies);
126 }
127 else
128 {
129 GMainLoop *loop = g_main_loop_new (NULL, FALSE);
130
131 g_proxy_resolver_lookup_async (resolver,
132 info,
133 cancellable,
134 _proxy_lookup_cb,
135 loop);
136
137 g_main_loop_run (loop);
138 g_main_loop_unref (loop);
139 }
140 }
141
142 static void
print_proxy_address(GSocketAddress * sockaddr)143 print_proxy_address (GSocketAddress *sockaddr)
144 {
145 GProxyAddress *proxy = NULL;
146
147 if (sockaddr == NULL)
148 {
149 printf ("\tdirect://\n");
150 return;
151 }
152
153 if (G_IS_PROXY_ADDRESS (sockaddr))
154 {
155 proxy = G_PROXY_ADDRESS (sockaddr);
156 printf ("\t%s://", g_proxy_address_get_protocol(proxy));
157 }
158 else
159 {
160 printf ("\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 (sockaddr,
170 "address", &inetaddr,
171 "port", &port,
172 NULL);
173
174 addr = g_inet_address_to_string (inetaddr);
175
176 printf ("%s:%u", addr, port);
177
178 g_free (addr);
179 }
180
181 if (proxy)
182 {
183 if (g_proxy_address_get_username(proxy))
184 printf (" (Username: %s Password: %s)",
185 g_proxy_address_get_username(proxy),
186 g_proxy_address_get_password(proxy));
187 printf (" (Hostname: %s, Port: %i)",
188 g_proxy_address_get_destination_hostname (proxy),
189 g_proxy_address_get_destination_port (proxy));
190 }
191
192 printf ("\n");
193 }
194
195 static void
_proxy_enumerate_cb(GObject * object,GAsyncResult * result,gpointer user_data)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);
208 if (sockaddr)
209 {
210 print_proxy_address (sockaddr);
211 g_socket_address_enumerator_next_async (enumerator,
212 cancellable,
213 _proxy_enumerate_cb,
214 loop);
215 g_object_unref (sockaddr);
216 }
217 else
218 {
219 if (error)
220 print_and_free_error (error);
221
222 g_main_loop_quit (loop);
223 }
224 }
225
226 static void
run_with_enumerator(gboolean synchronous,GSocketAddressEnumerator * enumerator)227 run_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)))
238 {
239 print_proxy_address (sockaddr);
240 g_object_unref (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 _proxy_enumerate_cb,
253 loop);
254 g_main_loop_run (loop);
255 g_main_loop_unref (loop);
256 }
257 }
258
259 static void
use_enumerator(gboolean synchronous)260 use_enumerator (gboolean synchronous)
261 {
262 GSocketAddressEnumerator *enumerator;
263
264 enumerator = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
265 "uri", info,
266 NULL);
267
268 printf ("Proxies for URI '%s' are:\n", info);
269 run_with_enumerator (synchronous, enumerator);
270
271 g_object_unref (enumerator);
272 }
273
274 static void
use_inet_address(gboolean synchronous)275 use_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 (info, ":", 2);
284
285 if (ip_and_port[0])
286 {
287 addr = g_inet_address_new_from_string (ip_and_port[0]);
288 if (ip_and_port [1])
289 port = strtoul (ip_and_port [1], NULL, 10);
290 }
291
292 g_strfreev (ip_and_port);
293
294 if (addr == NULL || port <= 0 || port >= 65535)
295 {
296 fprintf (stderr, "Bad 'ip:port' parameter '%s'\n", info);
297 if (addr)
298 g_object_unref (addr);
299 return_value = 1;
300 return;
301 }
302
303 sockaddr = g_inet_socket_address_new (addr, port);
304 g_object_unref (addr);
305
306 enumerator =
307 g_socket_connectable_proxy_enumerate (G_SOCKET_CONNECTABLE (sockaddr));
308 g_object_unref (sockaddr);
309
310 printf ("Proxies for ip and port '%s' are:\n", info);
311 run_with_enumerator (synchronous, enumerator);
312
313 g_object_unref (enumerator);
314 }
315
316 #ifdef G_OS_UNIX
317 static void
use_unix_address(gboolean synchronous)318 use_unix_address (gboolean synchronous)
319 {
320 GSocketAddressEnumerator *enumerator;
321 GSocketAddress *sockaddr;
322
323 sockaddr = g_unix_socket_address_new_with_type (info, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT);
324
325 if (sockaddr == NULL)
326 {
327 fprintf (stderr, "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 (sockaddr);
335
336 printf ("Proxies for path '%s' are:\n", info);
337 run_with_enumerator (synchronous, enumerator);
338
339 g_object_unref (enumerator);
340 }
341 #endif
342
343 static void
use_proxy_address(gboolean synchronous)344 use_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 (info, ":", 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, "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 (split_info[0]);
371 port = strtoul (split_info [1], NULL, 10);
372 protocol = g_strdup (split_info[2]);
373 dest_host = g_strdup (split_info[3]);
374 dest_port = strtoul (split_info[4], NULL, 10);
375
376 if (split_info[5])
377 {
378 username = g_strdup (split_info[5]);
379 if (split_info[6])
380 password = g_strdup (split_info[6]);
381 }
382
383 g_strfreev (split_info);
384
385 sockaddr = g_proxy_address_new (addr, port,
386 protocol, dest_host, dest_port,
387 username, password);
388
389 g_object_unref (addr);
390 g_free (protocol);
391 g_free (dest_host);
392 g_free (username);
393 g_free (password);
394
395 enumerator =
396 g_socket_connectable_proxy_enumerate (G_SOCKET_CONNECTABLE (sockaddr));
397 g_object_unref (sockaddr);
398
399 printf ("Proxies for ip and port '%s' are:\n", info);
400 run_with_enumerator (synchronous, enumerator);
401
402 g_object_unref (enumerator);
403 }
404
405 static void
use_network_address(gboolean synchronous)406 use_network_address (gboolean synchronous)
407 {
408 GError *error = NULL;
409 GSocketAddressEnumerator *enumerator;
410 GSocketConnectable *connectable;
411
412 connectable = g_network_address_parse (info, -1, &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 (connectable);
422
423 printf ("Proxies for hostname and port '%s' are:\n", info);
424 run_with_enumerator (synchronous, enumerator);
425
426 g_object_unref (enumerator);
427 }
428
429 static void
use_network_uri(gboolean synchronous)430 use_network_uri (gboolean synchronous)
431 {
432 GError *error = NULL;
433 GSocketAddressEnumerator *enumerator;
434 GSocketConnectable *connectable;
435
436 connectable = g_network_address_parse_uri (info, 0, &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 (connectable);
446
447 printf ("Proxies for URI '%s' are:\n", info);
448 run_with_enumerator (synchronous, enumerator);
449
450 g_object_unref (enumerator);
451 }
452
453 static void
use_network_service(gboolean synchronous)454 use_network_service (gboolean synchronous)
455 {
456 GSocketAddressEnumerator *enumerator;
457 GSocketConnectable *connectable = NULL;
458 gchar **split;
459
460 split = g_strsplit (info, "/", 3);
461
462 if (split[0] && split[1] && split[2])
463 connectable = g_network_service_new (split[0], split[1], split[2]);
464
465 g_strfreev (split);
466
467 if (connectable == NULL)
468 {
469 fprintf (stderr, "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 (connectable);
476
477 printf ("Proxies for hostname and port '%s' are:\n", info);
478 run_with_enumerator (synchronous, enumerator);
479
480 g_object_unref (enumerator);
481 }
482
483 static void
_socket_connect_cb(GObject * object,GAsyncResult * result,gpointer user_data)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);
496 if (connection)
497 {
498 GSocketAddress *proxy_addr;
499 proxy_addr = g_socket_connection_get_remote_address (connection, NULL);
500 print_proxy_address (proxy_addr);
501 }
502 else
503 {
504 print_and_free_error (error);
505 }
506
507 g_main_loop_quit (loop);
508 }
509
510 static void
use_socket_client(gboolean synchronous)511 use_socket_client (gboolean synchronous)
512 {
513 GError *error = NULL;
514 GSocketClient *client;
515
516 client = g_socket_client_new ();
517
518 printf ("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 info,
527 0,
528 cancellable,
529 &error);
530
531 if (connection)
532 {
533 proxy_addr = g_socket_connection_get_remote_address (connection, NULL);
534 print_proxy_address (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 info,
547 0,
548 cancellable,
549 _socket_connect_cb,
550 loop);
551
552 g_main_loop_run (loop);
553 g_main_loop_unref (loop);
554 }
555
556 g_object_unref (client);
557 }
558
559 typedef 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
574 gint
main(gint argc,gchar ** argv)575 main (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 (argv[1], "-s"))
584 synchronous = TRUE;
585 else if (!strcmp (argv[1], "-c"))
586 cancel = TRUE;
587 else if (!strcmp (argv[1], "-e"))
588 type = USE_ENUMERATOR;
589 else if (!strcmp (argv[1], "-inet"))
590 type = USE_INET_SOCKET_ADDRESS;
591 #ifdef G_OS_UNIX
592 else if (!strcmp (argv[1], "-unix"))
593 type = USE_UNIX_SOCKET_ADDRESS;
594 #endif
595 else if (!strcmp (argv[1], "-proxyaddr"))
596 type = USE_PROXY_ADDRESS;
597 else if (!strcmp (argv[1], "-netaddr"))
598 type = USE_NETWORK_ADDRESS;
599 else if (!strcmp (argv[1], "-neturi"))
600 type = USE_NETWORK_URI;
601 else if (!strcmp (argv[1], "-netsrv"))
602 type = USE_NETWORK_SERVICE;
603 else if (!strcmp (argv[1], "-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