nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GLib testing framework examples and tests |
2 | * |
||
3 | * Copyright 2012 Red Hat, Inc. |
||
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, see <http://www.gnu.org/licenses/>. |
||
17 | */ |
||
18 | |||
19 | #include <string.h> |
||
20 | |||
21 | #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_34 |
||
22 | #include <gio/gio.h> |
||
23 | |||
24 | /* Overview: |
||
25 | * |
||
26 | * We have an echo server, two proxy servers, two GProxy |
||
27 | * implementations, and two GProxyResolver implementations. |
||
28 | * |
||
29 | * The echo server runs at @server.server_addr (on |
||
30 | * @server.server_port). |
||
31 | * |
||
32 | * The two proxy servers, A and B, run on @proxy_a.port and |
||
33 | * @proxy_b.port, with @proxy_a.uri and @proxy_b.uri pointing to them. |
||
34 | * The "negotiation" with the two proxies is just sending the single |
||
35 | * letter "a" or "b" and receiving it back in uppercase; the proxy |
||
36 | * then connects to @server_addr. |
||
37 | * |
||
38 | * Proxy A supports "alpha://" URIs, and does not support hostname |
||
39 | * resolution, and Proxy B supports "beta://" URIs, and does support |
||
40 | * hostname resolution (but it just ignores the hostname and always |
||
41 | * connects to @server_addr anyway). |
||
42 | * |
||
43 | * The default GProxyResolver (GTestProxyResolver) looks at its URI |
||
44 | * and returns [ "direct://" ] for "simple://" URIs, and [ |
||
45 | * proxy_a.uri, proxy_b.uri ] for other URIs. The other GProxyResolver |
||
46 | * (GTestAltProxyResolver) always returns [ proxy_a.uri ]. |
||
47 | */ |
||
48 | |||
49 | typedef struct { |
||
50 | gchar *proxy_command; |
||
51 | gchar *supported_protocol; |
||
52 | |||
53 | GSocket *server; |
||
54 | GThread *thread; |
||
55 | GCancellable *cancellable; |
||
56 | gchar *uri; |
||
57 | gushort port; |
||
58 | |||
59 | GSocket *client_sock, *server_sock; |
||
60 | GMainLoop *loop; |
||
61 | |||
62 | GError *last_error; |
||
63 | } ProxyData; |
||
64 | |||
65 | static ProxyData proxy_a, proxy_b; |
||
66 | |||
67 | typedef struct { |
||
68 | GSocket *server; |
||
69 | GThread *server_thread; |
||
70 | GCancellable *cancellable; |
||
71 | GSocketAddress *server_addr; |
||
72 | gushort server_port; |
||
73 | } ServerData; |
||
74 | |||
75 | static ServerData server; |
||
76 | |||
77 | static gchar **last_proxies; |
||
78 | |||
79 | static GSocketClient *client; |
||
80 | |||
81 | |||
82 | /**************************************/ |
||
83 | /* Test GProxyResolver implementation */ |
||
84 | /**************************************/ |
||
85 | |||
86 | typedef struct { |
||
87 | GObject parent_instance; |
||
88 | } GTestProxyResolver; |
||
89 | |||
90 | typedef struct { |
||
91 | GObjectClass parent_class; |
||
92 | } GTestProxyResolverClass; |
||
93 | |||
94 | static void g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface); |
||
95 | |||
96 | static GType _g_test_proxy_resolver_get_type (void); |
||
97 | #define g_test_proxy_resolver_get_type _g_test_proxy_resolver_get_type |
||
98 | G_DEFINE_TYPE_WITH_CODE (GTestProxyResolver, g_test_proxy_resolver, G_TYPE_OBJECT, |
||
99 | G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER, |
||
100 | g_test_proxy_resolver_iface_init) |
||
101 | g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME, |
||
102 | g_define_type_id, |
||
103 | "test", |
||
104 | 0)) |
||
105 | |||
106 | static void |
||
107 | g_test_proxy_resolver_init (GTestProxyResolver *resolver) |
||
108 | { |
||
109 | } |
||
110 | |||
111 | static gboolean |
||
112 | g_test_proxy_resolver_is_supported (GProxyResolver *resolver) |
||
113 | { |
||
114 | return TRUE; |
||
115 | } |
||
116 | |||
117 | static gchar ** |
||
118 | g_test_proxy_resolver_lookup (GProxyResolver *resolver, |
||
119 | const gchar *uri, |
||
120 | GCancellable *cancellable, |
||
121 | GError **error) |
||
122 | { |
||
123 | gchar **proxies; |
||
124 | |||
125 | g_assert (last_proxies == NULL); |
||
126 | |||
127 | if (g_cancellable_set_error_if_cancelled (cancellable, error)) |
||
128 | return NULL; |
||
129 | |||
130 | proxies = g_new (gchar *, 3); |
||
131 | |||
132 | if (!strncmp (uri, "simple://", 4)) |
||
133 | { |
||
134 | proxies[0] = g_strdup ("direct://"); |
||
135 | proxies[1] = NULL; |
||
136 | } |
||
137 | else |
||
138 | { |
||
139 | /* Proxy A can only deal with "alpha://" URIs, not |
||
140 | * "beta://", but we always return both URIs |
||
141 | * anyway so we can test error handling when the first |
||
142 | * fails. |
||
143 | */ |
||
144 | proxies[0] = g_strdup (proxy_a.uri); |
||
145 | proxies[1] = g_strdup (proxy_b.uri); |
||
146 | proxies[2] = NULL; |
||
147 | } |
||
148 | |||
149 | last_proxies = g_strdupv (proxies); |
||
150 | |||
151 | return proxies; |
||
152 | } |
||
153 | |||
154 | static void |
||
155 | g_test_proxy_resolver_lookup_async (GProxyResolver *resolver, |
||
156 | const gchar *uri, |
||
157 | GCancellable *cancellable, |
||
158 | GAsyncReadyCallback callback, |
||
159 | gpointer user_data) |
||
160 | { |
||
161 | GError *error = NULL; |
||
162 | GTask *task; |
||
163 | gchar **proxies; |
||
164 | |||
165 | proxies = g_proxy_resolver_lookup (resolver, uri, cancellable, &error); |
||
166 | |||
167 | task = g_task_new (resolver, NULL, callback, user_data); |
||
168 | if (proxies == NULL) |
||
169 | g_task_return_error (task, error); |
||
170 | else |
||
171 | g_task_return_pointer (task, proxies, (GDestroyNotify) g_strfreev); |
||
172 | |||
173 | g_object_unref (task); |
||
174 | } |
||
175 | |||
176 | static gchar ** |
||
177 | g_test_proxy_resolver_lookup_finish (GProxyResolver *resolver, |
||
178 | GAsyncResult *result, |
||
179 | GError **error) |
||
180 | { |
||
181 | return g_task_propagate_pointer (G_TASK (result), error); |
||
182 | } |
||
183 | |||
184 | static void |
||
185 | g_test_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class) |
||
186 | { |
||
187 | } |
||
188 | |||
189 | static void |
||
190 | g_test_proxy_resolver_iface_init (GProxyResolverInterface *iface) |
||
191 | { |
||
192 | iface->is_supported = g_test_proxy_resolver_is_supported; |
||
193 | iface->lookup = g_test_proxy_resolver_lookup; |
||
194 | iface->lookup_async = g_test_proxy_resolver_lookup_async; |
||
195 | iface->lookup_finish = g_test_proxy_resolver_lookup_finish; |
||
196 | } |
||
197 | |||
198 | /****************************/ |
||
199 | /* Alternate GProxyResolver */ |
||
200 | /****************************/ |
||
201 | |||
202 | typedef GTestProxyResolver GTestAltProxyResolver; |
||
203 | typedef GTestProxyResolverClass GTestAltProxyResolverClass; |
||
204 | |||
205 | static void g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface); |
||
206 | |||
207 | static GType _g_test_alt_proxy_resolver_get_type (void); |
||
208 | #define g_test_alt_proxy_resolver_get_type _g_test_alt_proxy_resolver_get_type |
||
209 | G_DEFINE_TYPE_WITH_CODE (GTestAltProxyResolver, g_test_alt_proxy_resolver, g_test_proxy_resolver_get_type (), |
||
210 | G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER, |
||
211 | g_test_alt_proxy_resolver_iface_init); |
||
212 | ) |
||
213 | |||
214 | static void |
||
215 | g_test_alt_proxy_resolver_init (GTestProxyResolver *resolver) |
||
216 | { |
||
217 | } |
||
218 | |||
219 | static gchar ** |
||
220 | g_test_alt_proxy_resolver_lookup (GProxyResolver *resolver, |
||
221 | const gchar *uri, |
||
222 | GCancellable *cancellable, |
||
223 | GError **error) |
||
224 | { |
||
225 | gchar **proxies; |
||
226 | |||
227 | proxies = g_new (gchar *, 2); |
||
228 | |||
229 | proxies[0] = g_strdup (proxy_a.uri); |
||
230 | proxies[1] = NULL; |
||
231 | |||
232 | last_proxies = g_strdupv (proxies); |
||
233 | |||
234 | return proxies; |
||
235 | } |
||
236 | |||
237 | static void |
||
238 | g_test_alt_proxy_resolver_class_init (GTestProxyResolverClass *resolver_class) |
||
239 | { |
||
240 | } |
||
241 | |||
242 | static void |
||
243 | g_test_alt_proxy_resolver_iface_init (GProxyResolverInterface *iface) |
||
244 | { |
||
245 | iface->lookup = g_test_alt_proxy_resolver_lookup; |
||
246 | } |
||
247 | |||
248 | |||
249 | /****************************************/ |
||
250 | /* Test proxy implementation base class */ |
||
251 | /****************************************/ |
||
252 | |||
253 | typedef struct { |
||
254 | GObject parent; |
||
255 | |||
256 | ProxyData *proxy_data; |
||
257 | } GProxyBase; |
||
258 | |||
259 | typedef struct { |
||
260 | GObjectClass parent_class; |
||
261 | } GProxyBaseClass; |
||
262 | |||
263 | static GType _g_proxy_base_get_type (void); |
||
264 | #define g_proxy_base_get_type _g_proxy_base_get_type |
||
265 | G_DEFINE_ABSTRACT_TYPE (GProxyBase, g_proxy_base, G_TYPE_OBJECT) |
||
266 | |||
267 | static void |
||
268 | g_proxy_base_init (GProxyBase *proxy) |
||
269 | { |
||
270 | } |
||
271 | |||
272 | static GIOStream * |
||
273 | g_proxy_base_connect (GProxy *proxy, |
||
274 | GIOStream *io_stream, |
||
275 | GProxyAddress *proxy_address, |
||
276 | GCancellable *cancellable, |
||
277 | GError **error) |
||
278 | { |
||
279 | ProxyData *data = ((GProxyBase *) proxy)->proxy_data; |
||
280 | const gchar *protocol; |
||
281 | GOutputStream *ostream; |
||
282 | GInputStream *istream; |
||
283 | gchar response; |
||
284 | |||
285 | g_assert_no_error (data->last_error); |
||
286 | |||
287 | protocol = g_proxy_address_get_destination_protocol (proxy_address); |
||
288 | if (strcmp (protocol, data->supported_protocol) != 0) |
||
289 | { |
||
290 | g_set_error_literal (&data->last_error, |
||
291 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
||
292 | "Unsupported protocol"); |
||
293 | goto fail; |
||
294 | } |
||
295 | |||
296 | ostream = g_io_stream_get_output_stream (io_stream); |
||
297 | if (g_output_stream_write (ostream, data->proxy_command, 1, cancellable, |
||
298 | &data->last_error) != 1) |
||
299 | goto fail; |
||
300 | |||
301 | istream = g_io_stream_get_input_stream (io_stream); |
||
302 | if (g_input_stream_read (istream, &response, 1, cancellable, |
||
303 | &data->last_error) != 1) |
||
304 | goto fail; |
||
305 | |||
306 | if (response != g_ascii_toupper (*data->proxy_command)) |
||
307 | { |
||
308 | g_set_error_literal (&data->last_error, |
||
309 | G_IO_ERROR, G_IO_ERROR_FAILED, |
||
310 | "Failed"); |
||
311 | goto fail; |
||
312 | } |
||
313 | |||
314 | return g_object_ref (io_stream); |
||
315 | |||
316 | fail: |
||
317 | g_propagate_error (error, g_error_copy (data->last_error)); |
||
318 | return NULL; |
||
319 | } |
||
320 | |||
321 | static void |
||
322 | g_proxy_base_connect_async (GProxy *proxy, |
||
323 | GIOStream *io_stream, |
||
324 | GProxyAddress *proxy_address, |
||
325 | GCancellable *cancellable, |
||
326 | GAsyncReadyCallback callback, |
||
327 | gpointer user_data) |
||
328 | { |
||
329 | GError *error = NULL; |
||
330 | GTask *task; |
||
331 | GIOStream *proxy_io_stream; |
||
332 | |||
333 | task = g_task_new (proxy, NULL, callback, user_data); |
||
334 | |||
335 | proxy_io_stream = g_proxy_connect (proxy, io_stream, proxy_address, |
||
336 | cancellable, &error); |
||
337 | if (proxy_io_stream) |
||
338 | g_task_return_pointer (task, proxy_io_stream, g_object_unref); |
||
339 | else |
||
340 | g_task_return_error (task, error); |
||
341 | g_object_unref (task); |
||
342 | } |
||
343 | |||
344 | static GIOStream * |
||
345 | g_proxy_base_connect_finish (GProxy *proxy, |
||
346 | GAsyncResult *result, |
||
347 | GError **error) |
||
348 | { |
||
349 | return g_task_propagate_pointer (G_TASK (result), error); |
||
350 | } |
||
351 | |||
352 | static void |
||
353 | g_proxy_base_class_init (GProxyBaseClass *class) |
||
354 | { |
||
355 | } |
||
356 | |||
357 | |||
358 | /********************************************/ |
||
359 | /* Test proxy implementation #1 ("Proxy A") */ |
||
360 | /********************************************/ |
||
361 | |||
362 | typedef GProxyBase GProxyA; |
||
363 | typedef GProxyBaseClass GProxyAClass; |
||
364 | |||
365 | static void g_proxy_a_iface_init (GProxyInterface *proxy_iface); |
||
366 | |||
367 | static GType _g_proxy_a_get_type (void); |
||
368 | #define g_proxy_a_get_type _g_proxy_a_get_type |
||
369 | G_DEFINE_TYPE_WITH_CODE (GProxyA, g_proxy_a, g_proxy_base_get_type (), |
||
370 | G_IMPLEMENT_INTERFACE (G_TYPE_PROXY, |
||
371 | g_proxy_a_iface_init) |
||
372 | g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME, |
||
373 | g_define_type_id, |
||
374 | "proxy-a", |
||
375 | 0)) |
||
376 | |||
377 | static void |
||
378 | g_proxy_a_init (GProxyA *proxy) |
||
379 | { |
||
380 | ((GProxyBase *) proxy)->proxy_data = &proxy_a; |
||
381 | } |
||
382 | |||
383 | static gboolean |
||
384 | g_proxy_a_supports_hostname (GProxy *proxy) |
||
385 | { |
||
386 | return FALSE; |
||
387 | } |
||
388 | |||
389 | static void |
||
390 | g_proxy_a_class_init (GProxyAClass *class) |
||
391 | { |
||
392 | } |
||
393 | |||
394 | static void |
||
395 | g_proxy_a_iface_init (GProxyInterface *proxy_iface) |
||
396 | { |
||
397 | proxy_iface->connect = g_proxy_base_connect; |
||
398 | proxy_iface->connect_async = g_proxy_base_connect_async; |
||
399 | proxy_iface->connect_finish = g_proxy_base_connect_finish; |
||
400 | proxy_iface->supports_hostname = g_proxy_a_supports_hostname; |
||
401 | } |
||
402 | |||
403 | /********************************************/ |
||
404 | /* Test proxy implementation #2 ("Proxy B") */ |
||
405 | /********************************************/ |
||
406 | |||
407 | typedef GProxyBase GProxyB; |
||
408 | typedef GProxyBaseClass GProxyBClass; |
||
409 | |||
410 | static void g_proxy_b_iface_init (GProxyInterface *proxy_iface); |
||
411 | |||
412 | static GType _g_proxy_b_get_type (void); |
||
413 | #define g_proxy_b_get_type _g_proxy_b_get_type |
||
414 | G_DEFINE_TYPE_WITH_CODE (GProxyB, g_proxy_b, g_proxy_base_get_type (), |
||
415 | G_IMPLEMENT_INTERFACE (G_TYPE_PROXY, |
||
416 | g_proxy_b_iface_init) |
||
417 | g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME, |
||
418 | g_define_type_id, |
||
419 | "proxy-b", |
||
420 | 0)) |
||
421 | |||
422 | static void |
||
423 | g_proxy_b_init (GProxyB *proxy) |
||
424 | { |
||
425 | ((GProxyBase *) proxy)->proxy_data = &proxy_b; |
||
426 | } |
||
427 | |||
428 | static gboolean |
||
429 | g_proxy_b_supports_hostname (GProxy *proxy) |
||
430 | { |
||
431 | return TRUE; |
||
432 | } |
||
433 | |||
434 | static void |
||
435 | g_proxy_b_class_init (GProxyBClass *class) |
||
436 | { |
||
437 | } |
||
438 | |||
439 | static void |
||
440 | g_proxy_b_iface_init (GProxyInterface *proxy_iface) |
||
441 | { |
||
442 | proxy_iface->connect = g_proxy_base_connect; |
||
443 | proxy_iface->connect_async = g_proxy_base_connect_async; |
||
444 | proxy_iface->connect_finish = g_proxy_base_connect_finish; |
||
445 | proxy_iface->supports_hostname = g_proxy_b_supports_hostname; |
||
446 | } |
||
447 | |||
448 | |||
449 | /***********************************/ |
||
450 | /* The proxy server implementation */ |
||
451 | /***********************************/ |
||
452 | |||
453 | static gboolean |
||
454 | proxy_bytes (GSocket *socket, |
||
455 | GIOCondition condition, |
||
456 | gpointer user_data) |
||
457 | { |
||
458 | ProxyData *proxy = user_data; |
||
459 | gssize nread, nwrote, total; |
||
460 | gchar buffer[8]; |
||
461 | GSocket *out_socket; |
||
462 | GError *error = NULL; |
||
463 | |||
464 | nread = g_socket_receive_with_blocking (socket, buffer, sizeof (buffer), |
||
465 | TRUE, NULL, &error); |
||
466 | if (nread == -1) |
||
467 | { |
||
468 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED); |
||
469 | return FALSE; |
||
470 | } |
||
471 | else |
||
472 | g_assert_no_error (error); |
||
473 | |||
474 | if (nread == 0) |
||
475 | { |
||
476 | g_main_loop_quit (proxy->loop); |
||
477 | return FALSE; |
||
478 | } |
||
479 | |||
480 | if (socket == proxy->client_sock) |
||
481 | out_socket = proxy->server_sock; |
||
482 | else |
||
483 | out_socket = proxy->client_sock; |
||
484 | |||
485 | for (total = 0; total < nread; total += nwrote) |
||
486 | { |
||
487 | nwrote = g_socket_send_with_blocking (out_socket, |
||
488 | buffer + total, nread - total, |
||
489 | TRUE, NULL, &error); |
||
490 | g_assert_no_error (error); |
||
491 | } |
||
492 | |||
493 | return TRUE; |
||
494 | } |
||
495 | |||
496 | static gpointer |
||
497 | proxy_thread (gpointer user_data) |
||
498 | { |
||
499 | ProxyData *proxy = user_data; |
||
500 | GError *error = NULL; |
||
501 | gssize nread, nwrote; |
||
502 | gchar command[2] = { 0, 0 }; |
||
503 | GMainContext *context; |
||
504 | GSource *read_source, *write_source; |
||
505 | |||
506 | context = g_main_context_new (); |
||
507 | proxy->loop = g_main_loop_new (context, FALSE); |
||
508 | |||
509 | while (TRUE) |
||
510 | { |
||
511 | proxy->client_sock = g_socket_accept (proxy->server, proxy->cancellable, &error); |
||
512 | if (!proxy->client_sock) |
||
513 | { |
||
514 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); |
||
515 | g_error_free (error); |
||
516 | break; |
||
517 | } |
||
518 | else |
||
519 | g_assert_no_error (error); |
||
520 | |||
521 | nread = g_socket_receive (proxy->client_sock, command, 1, NULL, &error); |
||
522 | g_assert_no_error (error); |
||
523 | |||
524 | if (nread == 0) |
||
525 | { |
||
526 | g_clear_object (&proxy->client_sock); |
||
527 | continue; |
||
528 | } |
||
529 | |||
530 | g_assert_cmpint (nread, ==, 1); |
||
531 | g_assert_cmpstr (command, ==, proxy->proxy_command); |
||
532 | |||
533 | *command = g_ascii_toupper (*command); |
||
534 | nwrote = g_socket_send (proxy->client_sock, command, 1, NULL, &error); |
||
535 | g_assert_no_error (error); |
||
536 | g_assert_cmpint (nwrote, ==, 1); |
||
537 | |||
538 | proxy->server_sock = g_socket_new (G_SOCKET_FAMILY_IPV4, |
||
539 | G_SOCKET_TYPE_STREAM, |
||
540 | G_SOCKET_PROTOCOL_DEFAULT, |
||
541 | &error); |
||
542 | g_assert_no_error (error); |
||
543 | g_socket_connect (proxy->server_sock, server.server_addr, NULL, &error); |
||
544 | g_assert_no_error (error); |
||
545 | |||
546 | read_source = g_socket_create_source (proxy->client_sock, G_IO_IN, NULL); |
||
547 | g_source_set_callback (read_source, (GSourceFunc)proxy_bytes, proxy, NULL); |
||
548 | g_source_attach (read_source, context); |
||
549 | |||
550 | write_source = g_socket_create_source (proxy->server_sock, G_IO_IN, NULL); |
||
551 | g_source_set_callback (write_source, (GSourceFunc)proxy_bytes, proxy, NULL); |
||
552 | g_source_attach (write_source, context); |
||
553 | |||
554 | g_main_loop_run (proxy->loop); |
||
555 | |||
556 | g_socket_close (proxy->client_sock, &error); |
||
557 | g_assert_no_error (error); |
||
558 | g_clear_object (&proxy->client_sock); |
||
559 | |||
560 | g_socket_close (proxy->server_sock, &error); |
||
561 | g_assert_no_error (error); |
||
562 | g_clear_object (&proxy->server_sock); |
||
563 | |||
564 | g_source_destroy (read_source); |
||
565 | g_source_unref (read_source); |
||
566 | g_source_destroy (write_source); |
||
567 | g_source_unref (write_source); |
||
568 | } |
||
569 | |||
570 | g_main_loop_unref (proxy->loop); |
||
571 | g_main_context_unref (context); |
||
572 | |||
573 | g_object_unref (proxy->server); |
||
574 | g_object_unref (proxy->cancellable); |
||
575 | |||
576 | g_free (proxy->proxy_command); |
||
577 | g_free (proxy->supported_protocol); |
||
578 | g_free (proxy->uri); |
||
579 | |||
580 | return NULL; |
||
581 | } |
||
582 | |||
583 | static void |
||
584 | create_proxy (ProxyData *proxy, |
||
585 | gchar proxy_protocol, |
||
586 | const gchar *destination_protocol, |
||
587 | GCancellable *cancellable) |
||
588 | { |
||
589 | GError *error = NULL; |
||
590 | GSocketAddress *addr; |
||
591 | GInetAddress *iaddr; |
||
592 | |||
593 | proxy->proxy_command = g_strdup_printf ("%c", proxy_protocol); |
||
594 | proxy->supported_protocol = g_strdup (destination_protocol); |
||
595 | proxy->cancellable = g_object_ref (cancellable); |
||
596 | |||
597 | proxy->server = g_socket_new (G_SOCKET_FAMILY_IPV4, |
||
598 | G_SOCKET_TYPE_STREAM, |
||
599 | G_SOCKET_PROTOCOL_DEFAULT, |
||
600 | &error); |
||
601 | g_assert_no_error (error); |
||
602 | |||
603 | iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4); |
||
604 | addr = g_inet_socket_address_new (iaddr, 0); |
||
605 | g_object_unref (iaddr); |
||
606 | |||
607 | g_socket_bind (proxy->server, addr, TRUE, &error); |
||
608 | g_assert_no_error (error); |
||
609 | g_object_unref (addr); |
||
610 | |||
611 | addr = g_socket_get_local_address (proxy->server, &error); |
||
612 | proxy->port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); |
||
613 | proxy->uri = g_strdup_printf ("proxy-%c://127.0.0.1:%u", |
||
614 | g_ascii_tolower (proxy_protocol), |
||
615 | proxy->port); |
||
616 | g_object_unref (addr); |
||
617 | |||
618 | g_socket_listen (proxy->server, &error); |
||
619 | g_assert_no_error (error); |
||
620 | |||
621 | proxy->thread = g_thread_new ("proxy", proxy_thread, proxy); |
||
622 | } |
||
623 | |||
624 | |||
625 | |||
626 | /**************************/ |
||
627 | /* The actual echo server */ |
||
628 | /**************************/ |
||
629 | |||
630 | static gpointer |
||
631 | echo_server_thread (gpointer user_data) |
||
632 | { |
||
633 | ServerData *data = user_data; |
||
634 | GSocket *sock; |
||
635 | GError *error = NULL; |
||
636 | gssize nread, nwrote; |
||
637 | gchar buf[128]; |
||
638 | |||
639 | while (TRUE) |
||
640 | { |
||
641 | sock = g_socket_accept (data->server, data->cancellable, &error); |
||
642 | if (!sock) |
||
643 | { |
||
644 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); |
||
645 | g_error_free (error); |
||
646 | break; |
||
647 | } |
||
648 | else |
||
649 | g_assert_no_error (error); |
||
650 | |||
651 | while (TRUE) |
||
652 | { |
||
653 | nread = g_socket_receive (sock, buf, sizeof (buf), NULL, &error); |
||
654 | g_assert_no_error (error); |
||
655 | g_assert_cmpint (nread, >=, 0); |
||
656 | |||
657 | if (nread == 0) |
||
658 | break; |
||
659 | |||
660 | nwrote = g_socket_send (sock, buf, nread, NULL, &error); |
||
661 | g_assert_no_error (error); |
||
662 | g_assert_cmpint (nwrote, ==, nread); |
||
663 | } |
||
664 | |||
665 | g_socket_close (sock, &error); |
||
666 | g_assert_no_error (error); |
||
667 | g_object_unref (sock); |
||
668 | } |
||
669 | |||
670 | g_object_unref (data->server); |
||
671 | g_object_unref (data->server_addr); |
||
672 | g_object_unref (data->cancellable); |
||
673 | |||
674 | return NULL; |
||
675 | } |
||
676 | |||
677 | static void |
||
678 | create_server (ServerData *data, GCancellable *cancellable) |
||
679 | { |
||
680 | GError *error = NULL; |
||
681 | GSocketAddress *addr; |
||
682 | GInetAddress *iaddr; |
||
683 | |||
684 | data->cancellable = g_object_ref (cancellable); |
||
685 | |||
686 | data->server = g_socket_new (G_SOCKET_FAMILY_IPV4, |
||
687 | G_SOCKET_TYPE_STREAM, |
||
688 | G_SOCKET_PROTOCOL_DEFAULT, |
||
689 | &error); |
||
690 | g_assert_no_error (error); |
||
691 | |||
692 | g_socket_set_blocking (data->server, TRUE); |
||
693 | iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4); |
||
694 | addr = g_inet_socket_address_new (iaddr, 0); |
||
695 | g_object_unref (iaddr); |
||
696 | |||
697 | g_socket_bind (data->server, addr, TRUE, &error); |
||
698 | g_assert_no_error (error); |
||
699 | g_object_unref (addr); |
||
700 | |||
701 | data->server_addr = g_socket_get_local_address (data->server, &error); |
||
702 | g_assert_no_error (error); |
||
703 | |||
704 | data->server_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (data->server_addr)); |
||
705 | |||
706 | g_socket_listen (data->server, &error); |
||
707 | g_assert_no_error (error); |
||
708 | |||
709 | data->server_thread = g_thread_new ("server", echo_server_thread, data); |
||
710 | } |
||
711 | |||
712 | |||
713 | /******************************************************************/ |
||
714 | /* Now a GResolver implementation, so the can't-resolve test will */ |
||
715 | /* pass even if you have an evil DNS-faking ISP. */ |
||
716 | /******************************************************************/ |
||
717 | |||
718 | typedef GResolver GFakeResolver; |
||
719 | typedef GResolverClass GFakeResolverClass; |
||
720 | |||
721 | static GType g_fake_resolver_get_type (void); |
||
722 | G_DEFINE_TYPE (GFakeResolver, g_fake_resolver, G_TYPE_RESOLVER) |
||
723 | |||
724 | static void |
||
725 | g_fake_resolver_init (GFakeResolver *gtr) |
||
726 | { |
||
727 | } |
||
728 | |||
729 | static GList * |
||
730 | g_fake_resolver_lookup_by_name (GResolver *resolver, |
||
731 | const gchar *hostname, |
||
732 | GCancellable *cancellable, |
||
733 | GError **error) |
||
734 | { |
||
735 | if (!strcmp (hostname, "example.com")) |
||
736 | return g_list_prepend (NULL, g_inet_address_new_from_string ("127.0.0.1")); |
||
737 | else |
||
738 | { |
||
739 | /* Anything else is expected to fail. */ |
||
740 | g_set_error (error, |
||
741 | G_RESOLVER_ERROR, |
||
742 | G_RESOLVER_ERROR_NOT_FOUND, |
||
743 | "Not found"); |
||
744 | return NULL; |
||
745 | } |
||
746 | } |
||
747 | |||
748 | static void |
||
749 | g_fake_resolver_lookup_by_name_async (GResolver *resolver, |
||
750 | const gchar *hostname, |
||
751 | GCancellable *cancellable, |
||
752 | GAsyncReadyCallback callback, |
||
753 | gpointer user_data) |
||
754 | { |
||
755 | GTask *task; |
||
756 | |||
757 | task = g_task_new (resolver, cancellable, callback, user_data); |
||
758 | |||
759 | if (!strcmp (hostname, "example.com")) |
||
760 | { |
||
761 | GList *result; |
||
762 | |||
763 | result = g_list_prepend (NULL, g_inet_address_new_from_string ("127.0.0.1")); |
||
764 | g_task_return_pointer (task, result, (GDestroyNotify) g_resolver_free_addresses); |
||
765 | } |
||
766 | else |
||
767 | { |
||
768 | g_task_return_new_error (task, |
||
769 | G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, |
||
770 | "Not found"); |
||
771 | } |
||
772 | g_object_unref (task); |
||
773 | } |
||
774 | |||
775 | static GList * |
||
776 | g_fake_resolver_lookup_by_name_finish (GResolver *resolver, |
||
777 | GAsyncResult *result, |
||
778 | GError **error) |
||
779 | { |
||
780 | return g_task_propagate_pointer (G_TASK (result), error); |
||
781 | } |
||
782 | |||
783 | static void |
||
784 | g_fake_resolver_class_init (GFakeResolverClass *fake_class) |
||
785 | { |
||
786 | GResolverClass *resolver_class = G_RESOLVER_CLASS (fake_class); |
||
787 | |||
788 | resolver_class->lookup_by_name = g_fake_resolver_lookup_by_name; |
||
789 | resolver_class->lookup_by_name_async = g_fake_resolver_lookup_by_name_async; |
||
790 | resolver_class->lookup_by_name_finish = g_fake_resolver_lookup_by_name_finish; |
||
791 | } |
||
792 | |||
793 | |||
794 | |||
795 | /****************************************/ |
||
796 | /* We made it! Now for the actual test! */ |
||
797 | /****************************************/ |
||
798 | |||
799 | static void |
||
800 | setup_test (gpointer fixture, |
||
801 | gconstpointer user_data) |
||
802 | { |
||
803 | } |
||
804 | |||
805 | static void |
||
806 | teardown_test (gpointer fixture, |
||
807 | gconstpointer user_data) |
||
808 | { |
||
809 | if (last_proxies) |
||
810 | { |
||
811 | g_strfreev (last_proxies); |
||
812 | last_proxies = NULL; |
||
813 | } |
||
814 | g_clear_error (&proxy_a.last_error); |
||
815 | g_clear_error (&proxy_b.last_error); |
||
816 | } |
||
817 | |||
818 | |||
819 | static const gchar *testbuf = "0123456789abcdef"; |
||
820 | |||
821 | static void |
||
822 | do_echo_test (GSocketConnection *conn) |
||
823 | { |
||
824 | GIOStream *iostream = G_IO_STREAM (conn); |
||
825 | GInputStream *istream = g_io_stream_get_input_stream (iostream); |
||
826 | GOutputStream *ostream = g_io_stream_get_output_stream (iostream); |
||
827 | gssize nread, total; |
||
828 | gsize nwrote; |
||
829 | gchar buf[128]; |
||
830 | GError *error = NULL; |
||
831 | |||
832 | g_output_stream_write_all (ostream, testbuf, strlen (testbuf), |
||
833 | &nwrote, NULL, &error); |
||
834 | g_assert_no_error (error); |
||
835 | g_assert_cmpint (nwrote, ==, strlen (testbuf)); |
||
836 | |||
837 | for (total = 0; total < nwrote; total += nread) |
||
838 | { |
||
839 | nread = g_input_stream_read (istream, |
||
840 | buf + total, sizeof (buf) - total, |
||
841 | NULL, &error); |
||
842 | g_assert_no_error (error); |
||
843 | g_assert_cmpint (nread, >, 0); |
||
844 | } |
||
845 | |||
846 | buf[total] = '\0'; |
||
847 | g_assert_cmpstr (buf, ==, testbuf); |
||
848 | } |
||
849 | |||
850 | static void |
||
851 | async_got_conn (GObject *source, |
||
852 | GAsyncResult *result, |
||
853 | gpointer user_data) |
||
854 | { |
||
855 | GSocketConnection **conn = user_data; |
||
856 | GError *error = NULL; |
||
857 | |||
858 | *conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (source), |
||
859 | result, &error); |
||
860 | g_assert_no_error (error); |
||
861 | } |
||
862 | |||
863 | static void |
||
864 | async_got_error (GObject *source, |
||
865 | GAsyncResult *result, |
||
866 | gpointer user_data) |
||
867 | { |
||
868 | GError **error = user_data; |
||
869 | |||
870 | g_assert (error != NULL && *error == NULL); |
||
871 | g_socket_client_connect_finish (G_SOCKET_CLIENT (source), |
||
872 | result, error); |
||
873 | g_assert (*error != NULL); |
||
874 | } |
||
875 | |||
876 | |||
877 | static void |
||
878 | assert_direct (GSocketConnection *conn) |
||
879 | { |
||
880 | GSocketAddress *addr; |
||
881 | GError *error = NULL; |
||
882 | |||
883 | g_assert_cmpint (g_strv_length (last_proxies), ==, 1); |
||
884 | g_assert_cmpstr (last_proxies[0], ==, "direct://"); |
||
885 | g_assert_no_error (proxy_a.last_error); |
||
886 | g_assert_no_error (proxy_b.last_error); |
||
887 | |||
888 | addr = g_socket_connection_get_remote_address (conn, &error); |
||
889 | g_assert_no_error (error); |
||
890 | g_assert (addr != NULL && !G_IS_PROXY_ADDRESS (addr)); |
||
891 | g_object_unref (addr); |
||
892 | |||
893 | addr = g_socket_connection_get_local_address (conn, &error); |
||
894 | g_assert_no_error (error); |
||
895 | g_object_unref (addr); |
||
896 | |||
897 | g_assert (g_socket_connection_is_connected (conn)); |
||
898 | } |
||
899 | |||
900 | static void |
||
901 | test_direct_sync (gpointer fixture, |
||
902 | gconstpointer user_data) |
||
903 | { |
||
904 | GSocketConnection *conn; |
||
905 | gchar *uri; |
||
906 | GError *error = NULL; |
||
907 | |||
908 | /* The simple:// URI should not require any proxy. */ |
||
909 | |||
910 | uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port); |
||
911 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
912 | g_free (uri); |
||
913 | g_assert_no_error (error); |
||
914 | |||
915 | assert_direct (conn); |
||
916 | do_echo_test (conn); |
||
917 | g_object_unref (conn); |
||
918 | } |
||
919 | |||
920 | static void |
||
921 | test_direct_async (gpointer fixture, |
||
922 | gconstpointer user_data) |
||
923 | { |
||
924 | GSocketConnection *conn; |
||
925 | gchar *uri; |
||
926 | |||
927 | /* The simple:// URI should not require any proxy. */ |
||
928 | uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port); |
||
929 | conn = NULL; |
||
930 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
931 | async_got_conn, &conn); |
||
932 | g_free (uri); |
||
933 | while (conn == NULL) |
||
934 | g_main_context_iteration (NULL, TRUE); |
||
935 | |||
936 | assert_direct (conn); |
||
937 | do_echo_test (conn); |
||
938 | g_object_unref (conn); |
||
939 | } |
||
940 | |||
941 | static void |
||
942 | assert_single (GSocketConnection *conn) |
||
943 | { |
||
944 | GSocketAddress *addr; |
||
945 | const gchar *proxy_uri; |
||
946 | gushort proxy_port; |
||
947 | GError *error = NULL; |
||
948 | |||
949 | g_assert_cmpint (g_strv_length (last_proxies), ==, 2); |
||
950 | g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri); |
||
951 | g_assert_cmpstr (last_proxies[1], ==, proxy_b.uri); |
||
952 | g_assert_no_error (proxy_a.last_error); |
||
953 | g_assert_no_error (proxy_b.last_error); |
||
954 | |||
955 | addr = g_socket_connection_get_remote_address (conn, &error); |
||
956 | g_assert_no_error (error); |
||
957 | g_assert (G_IS_PROXY_ADDRESS (addr)); |
||
958 | proxy_uri = g_proxy_address_get_uri (G_PROXY_ADDRESS (addr)); |
||
959 | g_assert_cmpstr (proxy_uri, ==, proxy_a.uri); |
||
960 | proxy_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); |
||
961 | g_assert_cmpint (proxy_port, ==, proxy_a.port); |
||
962 | |||
963 | g_object_unref (addr); |
||
964 | } |
||
965 | |||
966 | static void |
||
967 | test_single_sync (gpointer fixture, |
||
968 | gconstpointer user_data) |
||
969 | { |
||
970 | GSocketConnection *conn; |
||
971 | GError *error = NULL; |
||
972 | gchar *uri; |
||
973 | |||
974 | /* The alpha:// URI should be proxied via Proxy A */ |
||
975 | uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port); |
||
976 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
977 | g_free (uri); |
||
978 | g_assert_no_error (error); |
||
979 | |||
980 | assert_single (conn); |
||
981 | |||
982 | do_echo_test (conn); |
||
983 | g_object_unref (conn); |
||
984 | } |
||
985 | |||
986 | static void |
||
987 | test_single_async (gpointer fixture, |
||
988 | gconstpointer user_data) |
||
989 | { |
||
990 | GSocketConnection *conn; |
||
991 | gchar *uri; |
||
992 | |||
993 | /* The alpha:// URI should be proxied via Proxy A */ |
||
994 | uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port); |
||
995 | conn = NULL; |
||
996 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
997 | async_got_conn, &conn); |
||
998 | g_free (uri); |
||
999 | while (conn == NULL) |
||
1000 | g_main_context_iteration (NULL, TRUE); |
||
1001 | |||
1002 | assert_single (conn); |
||
1003 | do_echo_test (conn); |
||
1004 | g_object_unref (conn); |
||
1005 | } |
||
1006 | |||
1007 | static void |
||
1008 | assert_multiple (GSocketConnection *conn) |
||
1009 | { |
||
1010 | GSocketAddress *addr; |
||
1011 | const gchar *proxy_uri; |
||
1012 | gushort proxy_port; |
||
1013 | GError *error = NULL; |
||
1014 | |||
1015 | g_assert_cmpint (g_strv_length (last_proxies), ==, 2); |
||
1016 | g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri); |
||
1017 | g_assert_cmpstr (last_proxies[1], ==, proxy_b.uri); |
||
1018 | g_assert_error (proxy_a.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1019 | g_assert_no_error (proxy_b.last_error); |
||
1020 | |||
1021 | addr = g_socket_connection_get_remote_address (conn, &error); |
||
1022 | g_assert_no_error (error); |
||
1023 | g_assert (G_IS_PROXY_ADDRESS (addr)); |
||
1024 | proxy_uri = g_proxy_address_get_uri (G_PROXY_ADDRESS (addr)); |
||
1025 | g_assert_cmpstr (proxy_uri, ==, proxy_b.uri); |
||
1026 | proxy_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); |
||
1027 | g_assert_cmpint (proxy_port, ==, proxy_b.port); |
||
1028 | |||
1029 | g_object_unref (addr); |
||
1030 | } |
||
1031 | |||
1032 | static void |
||
1033 | test_multiple_sync (gpointer fixture, |
||
1034 | gconstpointer user_data) |
||
1035 | { |
||
1036 | GSocketConnection *conn; |
||
1037 | GError *error = NULL; |
||
1038 | gchar *uri; |
||
1039 | |||
1040 | /* The beta:// URI should be proxied via Proxy B, after failing |
||
1041 | * via Proxy A. |
||
1042 | */ |
||
1043 | uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port); |
||
1044 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1045 | g_free (uri); |
||
1046 | g_assert_no_error (error); |
||
1047 | |||
1048 | assert_multiple (conn); |
||
1049 | do_echo_test (conn); |
||
1050 | g_object_unref (conn); |
||
1051 | } |
||
1052 | |||
1053 | static void |
||
1054 | test_multiple_async (gpointer fixture, |
||
1055 | gconstpointer user_data) |
||
1056 | { |
||
1057 | GSocketConnection *conn; |
||
1058 | gchar *uri; |
||
1059 | |||
1060 | /* The beta:// URI should be proxied via Proxy B, after failing |
||
1061 | * via Proxy A. |
||
1062 | */ |
||
1063 | uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port); |
||
1064 | conn = NULL; |
||
1065 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1066 | async_got_conn, &conn); |
||
1067 | g_free (uri); |
||
1068 | while (conn == NULL) |
||
1069 | g_main_context_iteration (NULL, TRUE); |
||
1070 | |||
1071 | assert_multiple (conn); |
||
1072 | do_echo_test (conn); |
||
1073 | g_object_unref (conn); |
||
1074 | } |
||
1075 | |||
1076 | static void |
||
1077 | test_dns (gpointer fixture, |
||
1078 | gconstpointer user_data) |
||
1079 | { |
||
1080 | GSocketConnection *conn; |
||
1081 | GError *error = NULL; |
||
1082 | gchar *uri; |
||
1083 | |||
1084 | /* The simple:// and alpha:// URIs should fail with a DNS error, |
||
1085 | * but the beta:// URI should succeed, because we pass it to |
||
1086 | * Proxy B without trying to resolve it first |
||
1087 | */ |
||
1088 | |||
1089 | /* simple */ |
||
1090 | uri = g_strdup_printf ("simple://no-such-host.xx:%u", server.server_port); |
||
1091 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1092 | g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND); |
||
1093 | g_clear_error (&error); |
||
1094 | |||
1095 | g_assert_no_error (proxy_a.last_error); |
||
1096 | g_assert_no_error (proxy_b.last_error); |
||
1097 | teardown_test (NULL, NULL); |
||
1098 | |||
1099 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1100 | async_got_error, &error); |
||
1101 | while (error == NULL) |
||
1102 | g_main_context_iteration (NULL, TRUE); |
||
1103 | g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND); |
||
1104 | g_clear_error (&error); |
||
1105 | g_free (uri); |
||
1106 | |||
1107 | g_assert_no_error (proxy_a.last_error); |
||
1108 | g_assert_no_error (proxy_b.last_error); |
||
1109 | teardown_test (NULL, NULL); |
||
1110 | |||
1111 | /* alpha */ |
||
1112 | uri = g_strdup_printf ("alpha://no-such-host.xx:%u", server.server_port); |
||
1113 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1114 | /* Since Proxy A fails, @client will try Proxy B too, which won't |
||
1115 | * load an alpha:// URI. |
||
1116 | */ |
||
1117 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1118 | g_clear_error (&error); |
||
1119 | |||
1120 | g_assert_no_error (proxy_a.last_error); |
||
1121 | g_assert_error (proxy_b.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1122 | teardown_test (NULL, NULL); |
||
1123 | |||
1124 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1125 | async_got_error, &error); |
||
1126 | while (error == NULL) |
||
1127 | g_main_context_iteration (NULL, TRUE); |
||
1128 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1129 | g_clear_error (&error); |
||
1130 | g_free (uri); |
||
1131 | |||
1132 | g_assert_no_error (proxy_a.last_error); |
||
1133 | g_assert_error (proxy_b.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1134 | teardown_test (NULL, NULL); |
||
1135 | |||
1136 | /* beta */ |
||
1137 | uri = g_strdup_printf ("beta://no-such-host.xx:%u", server.server_port); |
||
1138 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1139 | g_assert_no_error (error); |
||
1140 | |||
1141 | g_assert_no_error (proxy_a.last_error); |
||
1142 | g_assert_no_error (proxy_b.last_error); |
||
1143 | |||
1144 | do_echo_test (conn); |
||
1145 | g_clear_object (&conn); |
||
1146 | teardown_test (NULL, NULL); |
||
1147 | |||
1148 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1149 | async_got_conn, &conn); |
||
1150 | while (conn == NULL) |
||
1151 | g_main_context_iteration (NULL, TRUE); |
||
1152 | g_free (uri); |
||
1153 | |||
1154 | g_assert_no_error (proxy_a.last_error); |
||
1155 | g_assert_no_error (proxy_b.last_error); |
||
1156 | |||
1157 | do_echo_test (conn); |
||
1158 | g_clear_object (&conn); |
||
1159 | teardown_test (NULL, NULL); |
||
1160 | } |
||
1161 | |||
1162 | static void |
||
1163 | assert_override (GSocketConnection *conn) |
||
1164 | { |
||
1165 | g_assert_cmpint (g_strv_length (last_proxies), ==, 1); |
||
1166 | g_assert_cmpstr (last_proxies[0], ==, proxy_a.uri); |
||
1167 | |||
1168 | if (conn) |
||
1169 | g_assert_no_error (proxy_a.last_error); |
||
1170 | else |
||
1171 | g_assert_error (proxy_a.last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1172 | } |
||
1173 | |||
1174 | static void |
||
1175 | test_override (gpointer fixture, |
||
1176 | gconstpointer user_data) |
||
1177 | { |
||
1178 | GProxyResolver *alt_resolver; |
||
1179 | GSocketConnection *conn; |
||
1180 | GError *error = NULL; |
||
1181 | gchar *uri; |
||
1182 | |||
1183 | g_assert (g_socket_client_get_proxy_resolver (client) == g_proxy_resolver_get_default ()); |
||
1184 | alt_resolver = g_object_new (g_test_alt_proxy_resolver_get_type (), NULL); |
||
1185 | g_socket_client_set_proxy_resolver (client, alt_resolver); |
||
1186 | g_assert (g_socket_client_get_proxy_resolver (client) == alt_resolver); |
||
1187 | |||
1188 | /* Alt proxy resolver always returns Proxy A, so alpha:// should |
||
1189 | * succeed, and simple:// and beta:// should fail. |
||
1190 | */ |
||
1191 | |||
1192 | /* simple */ |
||
1193 | uri = g_strdup_printf ("simple://127.0.0.1:%u", server.server_port); |
||
1194 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1195 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1196 | g_clear_error (&error); |
||
1197 | assert_override (conn); |
||
1198 | teardown_test (NULL, NULL); |
||
1199 | |||
1200 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1201 | async_got_error, &error); |
||
1202 | while (error == NULL) |
||
1203 | g_main_context_iteration (NULL, TRUE); |
||
1204 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1205 | g_clear_error (&error); |
||
1206 | assert_override (conn); |
||
1207 | g_free (uri); |
||
1208 | teardown_test (NULL, NULL); |
||
1209 | |||
1210 | /* alpha */ |
||
1211 | uri = g_strdup_printf ("alpha://127.0.0.1:%u", server.server_port); |
||
1212 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1213 | g_assert_no_error (error); |
||
1214 | assert_override (conn); |
||
1215 | do_echo_test (conn); |
||
1216 | g_clear_object (&conn); |
||
1217 | teardown_test (NULL, NULL); |
||
1218 | |||
1219 | conn = NULL; |
||
1220 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1221 | async_got_conn, &conn); |
||
1222 | while (conn == NULL) |
||
1223 | g_main_context_iteration (NULL, TRUE); |
||
1224 | assert_override (conn); |
||
1225 | do_echo_test (conn); |
||
1226 | g_clear_object (&conn); |
||
1227 | g_free (uri); |
||
1228 | teardown_test (NULL, NULL); |
||
1229 | |||
1230 | /* beta */ |
||
1231 | uri = g_strdup_printf ("beta://127.0.0.1:%u", server.server_port); |
||
1232 | conn = g_socket_client_connect_to_uri (client, uri, 0, NULL, &error); |
||
1233 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1234 | g_clear_error (&error); |
||
1235 | assert_override (conn); |
||
1236 | teardown_test (NULL, NULL); |
||
1237 | |||
1238 | g_socket_client_connect_to_uri_async (client, uri, 0, NULL, |
||
1239 | async_got_error, &error); |
||
1240 | while (error == NULL) |
||
1241 | g_main_context_iteration (NULL, TRUE); |
||
1242 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED); |
||
1243 | g_clear_error (&error); |
||
1244 | assert_override (conn); |
||
1245 | g_free (uri); |
||
1246 | teardown_test (NULL, NULL); |
||
1247 | |||
1248 | g_assert (g_socket_client_get_proxy_resolver (client) == alt_resolver); |
||
1249 | g_socket_client_set_proxy_resolver (client, NULL); |
||
1250 | g_assert (g_socket_client_get_proxy_resolver (client) == g_proxy_resolver_get_default ()); |
||
1251 | g_object_unref (alt_resolver); |
||
1252 | } |
||
1253 | |||
1254 | static void |
||
1255 | assert_destination_port (GSocketAddressEnumerator *etor, |
||
1256 | guint16 port) |
||
1257 | { |
||
1258 | GSocketAddress *addr; |
||
1259 | GProxyAddress *paddr; |
||
1260 | GError *error = NULL; |
||
1261 | |||
1262 | while ((addr = g_socket_address_enumerator_next (etor, NULL, &error))) |
||
1263 | { |
||
1264 | g_assert_no_error (error); |
||
1265 | |||
1266 | g_assert (G_IS_PROXY_ADDRESS (addr)); |
||
1267 | paddr = G_PROXY_ADDRESS (addr); |
||
1268 | g_assert_cmpint (g_proxy_address_get_destination_port (paddr), ==, port); |
||
1269 | g_object_unref (addr); |
||
1270 | } |
||
1271 | g_assert_no_error (error); |
||
1272 | } |
||
1273 | |||
1274 | static void |
||
1275 | test_proxy_enumerator_ports (void) |
||
1276 | { |
||
1277 | GSocketAddressEnumerator *etor; |
||
1278 | |||
1279 | etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, |
||
1280 | "uri", "http://example.com/", |
||
1281 | NULL); |
||
1282 | assert_destination_port (etor, 0); |
||
1283 | g_object_unref (etor); |
||
1284 | |||
1285 | /* Have to call this to clear last_proxies so the next call to |
||
1286 | * g_test_proxy_resolver_lookup() won't assert. |
||
1287 | */ |
||
1288 | teardown_test (NULL, NULL); |
||
1289 | |||
1290 | etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, |
||
1291 | "uri", "http://example.com:8080/", |
||
1292 | NULL); |
||
1293 | assert_destination_port (etor, 8080); |
||
1294 | g_object_unref (etor); |
||
1295 | |||
1296 | teardown_test (NULL, NULL); |
||
1297 | |||
1298 | etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, |
||
1299 | "uri", "http://example.com/", |
||
1300 | "default-port", 80, |
||
1301 | NULL); |
||
1302 | assert_destination_port (etor, 80); |
||
1303 | g_object_unref (etor); |
||
1304 | |||
1305 | teardown_test (NULL, NULL); |
||
1306 | |||
1307 | etor = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, |
||
1308 | "uri", "http://example.com:8080/", |
||
1309 | "default-port", 80, |
||
1310 | NULL); |
||
1311 | assert_destination_port (etor, 8080); |
||
1312 | g_object_unref (etor); |
||
1313 | |||
1314 | teardown_test (NULL, NULL); |
||
1315 | } |
||
1316 | |||
1317 | int |
||
1318 | main (int argc, |
||
1319 | char *argv[]) |
||
1320 | { |
||
1321 | GResolver *fake_resolver; |
||
1322 | GCancellable *cancellable; |
||
1323 | gint result; |
||
1324 | |||
1325 | g_test_init (&argc, &argv, NULL); |
||
1326 | |||
1327 | /* Register stuff. The dummy g_proxy_get_default_for_protocol() call |
||
1328 | * is to force _g_io_modules_ensure_extension_points_registered() to |
||
1329 | * get called, so we can then register a proxy resolver extension |
||
1330 | * point. |
||
1331 | */ |
||
1332 | g_proxy_get_default_for_protocol ("foo"); |
||
1333 | g_test_proxy_resolver_get_type (); |
||
1334 | g_proxy_a_get_type (); |
||
1335 | g_proxy_b_get_type (); |
||
1336 | g_setenv ("GIO_USE_PROXY_RESOLVER", "test", TRUE); |
||
1337 | |||
1338 | fake_resolver = g_object_new (g_fake_resolver_get_type (), NULL); |
||
1339 | g_resolver_set_default (fake_resolver); |
||
1340 | |||
1341 | cancellable = g_cancellable_new (); |
||
1342 | create_server (&server, cancellable); |
||
1343 | create_proxy (&proxy_a, 'a', "alpha", cancellable); |
||
1344 | create_proxy (&proxy_b, 'b', "beta", cancellable); |
||
1345 | |||
1346 | client = g_socket_client_new (); |
||
1347 | g_assert_cmpint (g_socket_client_get_enable_proxy (client), ==, TRUE); |
||
1348 | |||
1349 | g_test_add_vtable ("/proxy/direct_sync", 0, NULL, setup_test, test_direct_sync, teardown_test); |
||
1350 | g_test_add_vtable ("/proxy/direct_async", 0, NULL, setup_test, test_direct_async, teardown_test); |
||
1351 | g_test_add_vtable ("/proxy/single_sync", 0, NULL, setup_test, test_single_sync, teardown_test); |
||
1352 | g_test_add_vtable ("/proxy/single_async", 0, NULL, setup_test, test_single_async, teardown_test); |
||
1353 | g_test_add_vtable ("/proxy/multiple_sync", 0, NULL, setup_test, test_multiple_sync, teardown_test); |
||
1354 | g_test_add_vtable ("/proxy/multiple_async", 0, NULL, setup_test, test_multiple_async, teardown_test); |
||
1355 | g_test_add_vtable ("/proxy/dns", 0, NULL, setup_test, test_dns, teardown_test); |
||
1356 | g_test_add_vtable ("/proxy/override", 0, NULL, setup_test, test_override, teardown_test); |
||
1357 | g_test_add_func ("/proxy/enumerator-ports", test_proxy_enumerator_ports); |
||
1358 | |||
1359 | result = g_test_run(); |
||
1360 | |||
1361 | g_object_unref (client); |
||
1362 | |||
1363 | g_cancellable_cancel (cancellable); |
||
1364 | g_thread_join (proxy_a.thread); |
||
1365 | g_thread_join (proxy_b.thread); |
||
1366 | g_thread_join (server.server_thread); |
||
1367 | |||
1368 | g_object_unref (cancellable); |
||
1369 | |||
1370 | return result; |
||
1371 | } |
||
1372 |