nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GIO - GLib Input, Output and Streaming Library |
2 | * |
||
3 | * Copyright © 2008, 2009 codethink |
||
4 | * Copyright © 2009 Red Hat, Inc |
||
5 | * |
||
6 | * This library is free software; you can redistribute it and/or |
||
7 | * modify it under the terms of the GNU Lesser General Public |
||
8 | * License as published by the Free Software Foundation; either |
||
9 | * version 2 of the License, or (at your option) any later version. |
||
10 | * |
||
11 | * This library is distributed in the hope that it will be useful, |
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
14 | * Lesser General Public License for more details. |
||
15 | * |
||
16 | * You should have received a copy of the GNU Lesser General |
||
17 | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
||
18 | * |
||
19 | * Authors: Ryan Lortie <desrt@desrt.ca> |
||
20 | * Alexander Larsson <alexl@redhat.com> |
||
21 | */ |
||
22 | |||
23 | #include "config.h" |
||
24 | #include "gsocketclient.h" |
||
25 | |||
26 | #include <stdlib.h> |
||
27 | #include <string.h> |
||
28 | |||
29 | #include <gio/gioenumtypes.h> |
||
30 | #include <gio/gsocketaddressenumerator.h> |
||
31 | #include <gio/gsocketconnectable.h> |
||
32 | #include <gio/gsocketconnection.h> |
||
33 | #include <gio/gioprivate.h> |
||
34 | #include <gio/gproxyaddressenumerator.h> |
||
35 | #include <gio/gproxyaddress.h> |
||
36 | #include <gio/gtask.h> |
||
37 | #include <gio/gcancellable.h> |
||
38 | #include <gio/gioerror.h> |
||
39 | #include <gio/gsocket.h> |
||
40 | #include <gio/gnetworkaddress.h> |
||
41 | #include <gio/gnetworkservice.h> |
||
42 | #include <gio/gproxy.h> |
||
43 | #include <gio/gproxyresolver.h> |
||
44 | #include <gio/gsocketaddress.h> |
||
45 | #include <gio/gtcpconnection.h> |
||
46 | #include <gio/gtcpwrapperconnection.h> |
||
47 | #include <gio/gtlscertificate.h> |
||
48 | #include <gio/gtlsclientconnection.h> |
||
49 | #include <gio/ginetaddress.h> |
||
50 | #include "glibintl.h" |
||
51 | |||
52 | |||
53 | /** |
||
54 | * SECTION:gsocketclient |
||
55 | * @short_description: Helper for connecting to a network service |
||
56 | * @include: gio/gio.h |
||
57 | * @see_also: #GSocketConnection, #GSocketListener |
||
58 | * |
||
59 | * #GSocketClient is a lightweight high-level utility class for connecting to |
||
60 | * a network host using a connection oriented socket type. |
||
61 | * |
||
62 | * You create a #GSocketClient object, set any options you want, and then |
||
63 | * call a sync or async connect operation, which returns a #GSocketConnection |
||
64 | * subclass on success. |
||
65 | * |
||
66 | * The type of the #GSocketConnection object returned depends on the type of |
||
67 | * the underlying socket that is in use. For instance, for a TCP/IP connection |
||
68 | * it will be a #GTcpConnection. |
||
69 | * |
||
70 | * As #GSocketClient is a lightweight object, you don't need to cache it. You |
||
71 | * can just create a new one any time you need one. |
||
72 | * |
||
73 | * Since: 2.22 |
||
74 | */ |
||
75 | |||
76 | |||
77 | enum |
||
78 | { |
||
79 | EVENT, |
||
80 | LAST_SIGNAL |
||
81 | }; |
||
82 | |||
83 | static guint signals[LAST_SIGNAL] = { 0 }; |
||
84 | |||
85 | enum |
||
86 | { |
||
87 | PROP_NONE, |
||
88 | PROP_FAMILY, |
||
89 | PROP_TYPE, |
||
90 | PROP_PROTOCOL, |
||
91 | PROP_LOCAL_ADDRESS, |
||
92 | PROP_TIMEOUT, |
||
93 | PROP_ENABLE_PROXY, |
||
94 | PROP_TLS, |
||
95 | PROP_TLS_VALIDATION_FLAGS, |
||
96 | PROP_PROXY_RESOLVER |
||
97 | }; |
||
98 | |||
99 | struct _GSocketClientPrivate |
||
100 | { |
||
101 | GSocketFamily family; |
||
102 | GSocketType type; |
||
103 | GSocketProtocol protocol; |
||
104 | GSocketAddress *local_address; |
||
105 | guint timeout; |
||
106 | gboolean enable_proxy; |
||
107 | GHashTable *app_proxies; |
||
108 | gboolean tls; |
||
109 | GTlsCertificateFlags tls_validation_flags; |
||
110 | GProxyResolver *proxy_resolver; |
||
111 | }; |
||
112 | |||
113 | G_DEFINE_TYPE_WITH_PRIVATE (GSocketClient, g_socket_client, G_TYPE_OBJECT) |
||
114 | |||
115 | static GSocket * |
||
116 | create_socket (GSocketClient *client, |
||
117 | GSocketAddress *dest_address, |
||
118 | GError **error) |
||
119 | { |
||
120 | GSocketFamily family; |
||
121 | GSocket *socket; |
||
122 | |||
123 | family = client->priv->family; |
||
124 | if (family == G_SOCKET_FAMILY_INVALID && |
||
125 | client->priv->local_address != NULL) |
||
126 | family = g_socket_address_get_family (client->priv->local_address); |
||
127 | if (family == G_SOCKET_FAMILY_INVALID) |
||
128 | family = g_socket_address_get_family (dest_address); |
||
129 | |||
130 | socket = g_socket_new (family, |
||
131 | client->priv->type, |
||
132 | client->priv->protocol, |
||
133 | error); |
||
134 | if (socket == NULL) |
||
135 | return NULL; |
||
136 | |||
137 | if (client->priv->local_address) |
||
138 | { |
||
139 | if (!g_socket_bind (socket, |
||
140 | client->priv->local_address, |
||
141 | FALSE, |
||
142 | error)) |
||
143 | { |
||
144 | g_object_unref (socket); |
||
145 | return NULL; |
||
146 | } |
||
147 | } |
||
148 | |||
149 | if (client->priv->timeout) |
||
150 | g_socket_set_timeout (socket, client->priv->timeout); |
||
151 | |||
152 | return socket; |
||
153 | } |
||
154 | |||
155 | static gboolean |
||
156 | can_use_proxy (GSocketClient *client) |
||
157 | { |
||
158 | GSocketClientPrivate *priv = client->priv; |
||
159 | |||
160 | return priv->enable_proxy |
||
161 | && priv->type == G_SOCKET_TYPE_STREAM; |
||
162 | } |
||
163 | |||
164 | static void |
||
165 | clarify_connect_error (GError *error, |
||
166 | GSocketConnectable *connectable, |
||
167 | GSocketAddress *address) |
||
168 | { |
||
169 | const char *name; |
||
170 | char *tmp_name = NULL; |
||
171 | |||
172 | if (G_IS_PROXY_ADDRESS (address)) |
||
173 | { |
||
174 | name = tmp_name = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address))); |
||
175 | |||
176 | g_prefix_error (&error, _("Could not connect to proxy server %s: "), name); |
||
177 | } |
||
178 | else |
||
179 | { |
||
180 | if (G_IS_NETWORK_ADDRESS (connectable)) |
||
181 | name = g_network_address_get_hostname (G_NETWORK_ADDRESS (connectable)); |
||
182 | else if (G_IS_NETWORK_SERVICE (connectable)) |
||
183 | name = g_network_service_get_domain (G_NETWORK_SERVICE (connectable)); |
||
184 | else if (G_IS_INET_SOCKET_ADDRESS (connectable)) |
||
185 | name = tmp_name = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (connectable))); |
||
186 | else |
||
187 | name = NULL; |
||
188 | |||
189 | if (name) |
||
190 | g_prefix_error (&error, _("Could not connect to %s: "), name); |
||
191 | else |
||
192 | g_prefix_error (&error, _("Could not connect: ")); |
||
193 | } |
||
194 | |||
195 | g_free (tmp_name); |
||
196 | } |
||
197 | |||
198 | static void |
||
199 | g_socket_client_init (GSocketClient *client) |
||
200 | { |
||
201 | client->priv = g_socket_client_get_instance_private (client); |
||
202 | client->priv->type = G_SOCKET_TYPE_STREAM; |
||
203 | client->priv->app_proxies = g_hash_table_new_full (g_str_hash, |
||
204 | g_str_equal, |
||
205 | g_free, |
||
206 | NULL); |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * g_socket_client_new: |
||
211 | * |
||
212 | * Creates a new #GSocketClient with the default options. |
||
213 | * |
||
214 | * Returns: a #GSocketClient. |
||
215 | * Free the returned object with g_object_unref(). |
||
216 | * |
||
217 | * Since: 2.22 |
||
218 | */ |
||
219 | GSocketClient * |
||
220 | g_socket_client_new (void) |
||
221 | { |
||
222 | return g_object_new (G_TYPE_SOCKET_CLIENT, NULL); |
||
223 | } |
||
224 | |||
225 | static void |
||
226 | g_socket_client_finalize (GObject *object) |
||
227 | { |
||
228 | GSocketClient *client = G_SOCKET_CLIENT (object); |
||
229 | |||
230 | g_clear_object (&client->priv->local_address); |
||
231 | g_clear_object (&client->priv->proxy_resolver); |
||
232 | |||
233 | G_OBJECT_CLASS (g_socket_client_parent_class)->finalize (object); |
||
234 | |||
235 | g_hash_table_unref (client->priv->app_proxies); |
||
236 | } |
||
237 | |||
238 | static void |
||
239 | g_socket_client_get_property (GObject *object, |
||
240 | guint prop_id, |
||
241 | GValue *value, |
||
242 | GParamSpec *pspec) |
||
243 | { |
||
244 | GSocketClient *client = G_SOCKET_CLIENT (object); |
||
245 | |||
246 | switch (prop_id) |
||
247 | { |
||
248 | case PROP_FAMILY: |
||
249 | g_value_set_enum (value, client->priv->family); |
||
250 | break; |
||
251 | |||
252 | case PROP_TYPE: |
||
253 | g_value_set_enum (value, client->priv->type); |
||
254 | break; |
||
255 | |||
256 | case PROP_PROTOCOL: |
||
257 | g_value_set_enum (value, client->priv->protocol); |
||
258 | break; |
||
259 | |||
260 | case PROP_LOCAL_ADDRESS: |
||
261 | g_value_set_object (value, client->priv->local_address); |
||
262 | break; |
||
263 | |||
264 | case PROP_TIMEOUT: |
||
265 | g_value_set_uint (value, client->priv->timeout); |
||
266 | break; |
||
267 | |||
268 | case PROP_ENABLE_PROXY: |
||
269 | g_value_set_boolean (value, client->priv->enable_proxy); |
||
270 | break; |
||
271 | |||
272 | case PROP_TLS: |
||
273 | g_value_set_boolean (value, g_socket_client_get_tls (client)); |
||
274 | break; |
||
275 | |||
276 | case PROP_TLS_VALIDATION_FLAGS: |
||
277 | g_value_set_flags (value, g_socket_client_get_tls_validation_flags (client)); |
||
278 | break; |
||
279 | |||
280 | case PROP_PROXY_RESOLVER: |
||
281 | g_value_set_object (value, g_socket_client_get_proxy_resolver (client)); |
||
282 | break; |
||
283 | |||
284 | default: |
||
285 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
||
286 | } |
||
287 | } |
||
288 | |||
289 | static void |
||
290 | g_socket_client_set_property (GObject *object, |
||
291 | guint prop_id, |
||
292 | const GValue *value, |
||
293 | GParamSpec *pspec) |
||
294 | { |
||
295 | GSocketClient *client = G_SOCKET_CLIENT (object); |
||
296 | |||
297 | switch (prop_id) |
||
298 | { |
||
299 | case PROP_FAMILY: |
||
300 | g_socket_client_set_family (client, g_value_get_enum (value)); |
||
301 | break; |
||
302 | |||
303 | case PROP_TYPE: |
||
304 | g_socket_client_set_socket_type (client, g_value_get_enum (value)); |
||
305 | break; |
||
306 | |||
307 | case PROP_PROTOCOL: |
||
308 | g_socket_client_set_protocol (client, g_value_get_enum (value)); |
||
309 | break; |
||
310 | |||
311 | case PROP_LOCAL_ADDRESS: |
||
312 | g_socket_client_set_local_address (client, g_value_get_object (value)); |
||
313 | break; |
||
314 | |||
315 | case PROP_TIMEOUT: |
||
316 | g_socket_client_set_timeout (client, g_value_get_uint (value)); |
||
317 | break; |
||
318 | |||
319 | case PROP_ENABLE_PROXY: |
||
320 | g_socket_client_set_enable_proxy (client, g_value_get_boolean (value)); |
||
321 | break; |
||
322 | |||
323 | case PROP_TLS: |
||
324 | g_socket_client_set_tls (client, g_value_get_boolean (value)); |
||
325 | break; |
||
326 | |||
327 | case PROP_TLS_VALIDATION_FLAGS: |
||
328 | g_socket_client_set_tls_validation_flags (client, g_value_get_flags (value)); |
||
329 | break; |
||
330 | |||
331 | case PROP_PROXY_RESOLVER: |
||
332 | g_socket_client_set_proxy_resolver (client, g_value_get_object (value)); |
||
333 | break; |
||
334 | |||
335 | default: |
||
336 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
||
337 | } |
||
338 | } |
||
339 | |||
340 | /** |
||
341 | * g_socket_client_get_family: |
||
342 | * @client: a #GSocketClient. |
||
343 | * |
||
344 | * Gets the socket family of the socket client. |
||
345 | * |
||
346 | * See g_socket_client_set_family() for details. |
||
347 | * |
||
348 | * Returns: a #GSocketFamily |
||
349 | * |
||
350 | * Since: 2.22 |
||
351 | */ |
||
352 | GSocketFamily |
||
353 | g_socket_client_get_family (GSocketClient *client) |
||
354 | { |
||
355 | return client->priv->family; |
||
356 | } |
||
357 | |||
358 | /** |
||
359 | * g_socket_client_set_family: |
||
360 | * @client: a #GSocketClient. |
||
361 | * @family: a #GSocketFamily |
||
362 | * |
||
363 | * Sets the socket family of the socket client. |
||
364 | * If this is set to something other than %G_SOCKET_FAMILY_INVALID |
||
365 | * then the sockets created by this object will be of the specified |
||
366 | * family. |
||
367 | * |
||
368 | * This might be useful for instance if you want to force the local |
||
369 | * connection to be an ipv4 socket, even though the address might |
||
370 | * be an ipv6 mapped to ipv4 address. |
||
371 | * |
||
372 | * Since: 2.22 |
||
373 | */ |
||
374 | void |
||
375 | g_socket_client_set_family (GSocketClient *client, |
||
376 | GSocketFamily family) |
||
377 | { |
||
378 | if (client->priv->family == family) |
||
379 | return; |
||
380 | |||
381 | client->priv->family = family; |
||
382 | g_object_notify (G_OBJECT (client), "family"); |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * g_socket_client_get_socket_type: |
||
387 | * @client: a #GSocketClient. |
||
388 | * |
||
389 | * Gets the socket type of the socket client. |
||
390 | * |
||
391 | * See g_socket_client_set_socket_type() for details. |
||
392 | * |
||
393 | * Returns: a #GSocketFamily |
||
394 | * |
||
395 | * Since: 2.22 |
||
396 | */ |
||
397 | GSocketType |
||
398 | g_socket_client_get_socket_type (GSocketClient *client) |
||
399 | { |
||
400 | return client->priv->type; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * g_socket_client_set_socket_type: |
||
405 | * @client: a #GSocketClient. |
||
406 | * @type: a #GSocketType |
||
407 | * |
||
408 | * Sets the socket type of the socket client. |
||
409 | * The sockets created by this object will be of the specified |
||
410 | * type. |
||
411 | * |
||
412 | * It doesn't make sense to specify a type of %G_SOCKET_TYPE_DATAGRAM, |
||
413 | * as GSocketClient is used for connection oriented services. |
||
414 | * |
||
415 | * Since: 2.22 |
||
416 | */ |
||
417 | void |
||
418 | g_socket_client_set_socket_type (GSocketClient *client, |
||
419 | GSocketType type) |
||
420 | { |
||
421 | if (client->priv->type == type) |
||
422 | return; |
||
423 | |||
424 | client->priv->type = type; |
||
425 | g_object_notify (G_OBJECT (client), "type"); |
||
426 | } |
||
427 | |||
428 | /** |
||
429 | * g_socket_client_get_protocol: |
||
430 | * @client: a #GSocketClient |
||
431 | * |
||
432 | * Gets the protocol name type of the socket client. |
||
433 | * |
||
434 | * See g_socket_client_set_protocol() for details. |
||
435 | * |
||
436 | * Returns: a #GSocketProtocol |
||
437 | * |
||
438 | * Since: 2.22 |
||
439 | */ |
||
440 | GSocketProtocol |
||
441 | g_socket_client_get_protocol (GSocketClient *client) |
||
442 | { |
||
443 | return client->priv->protocol; |
||
444 | } |
||
445 | |||
446 | /** |
||
447 | * g_socket_client_set_protocol: |
||
448 | * @client: a #GSocketClient. |
||
449 | * @protocol: a #GSocketProtocol |
||
450 | * |
||
451 | * Sets the protocol of the socket client. |
||
452 | * The sockets created by this object will use of the specified |
||
453 | * protocol. |
||
454 | * |
||
455 | * If @protocol is %0 that means to use the default |
||
456 | * protocol for the socket family and type. |
||
457 | * |
||
458 | * Since: 2.22 |
||
459 | */ |
||
460 | void |
||
461 | g_socket_client_set_protocol (GSocketClient *client, |
||
462 | GSocketProtocol protocol) |
||
463 | { |
||
464 | if (client->priv->protocol == protocol) |
||
465 | return; |
||
466 | |||
467 | client->priv->protocol = protocol; |
||
468 | g_object_notify (G_OBJECT (client), "protocol"); |
||
469 | } |
||
470 | |||
471 | /** |
||
472 | * g_socket_client_get_local_address: |
||
473 | * @client: a #GSocketClient. |
||
474 | * |
||
475 | * Gets the local address of the socket client. |
||
476 | * |
||
477 | * See g_socket_client_set_local_address() for details. |
||
478 | * |
||
479 | * Returns: (transfer none): a #GSocketAddress or %NULL. Do not free. |
||
480 | * |
||
481 | * Since: 2.22 |
||
482 | */ |
||
483 | GSocketAddress * |
||
484 | g_socket_client_get_local_address (GSocketClient *client) |
||
485 | { |
||
486 | return client->priv->local_address; |
||
487 | } |
||
488 | |||
489 | /** |
||
490 | * g_socket_client_set_local_address: |
||
491 | * @client: a #GSocketClient. |
||
492 | * @address: (allow-none): a #GSocketAddress, or %NULL |
||
493 | * |
||
494 | * Sets the local address of the socket client. |
||
495 | * The sockets created by this object will bound to the |
||
496 | * specified address (if not %NULL) before connecting. |
||
497 | * |
||
498 | * This is useful if you want to ensure that the local |
||
499 | * side of the connection is on a specific port, or on |
||
500 | * a specific interface. |
||
501 | * |
||
502 | * Since: 2.22 |
||
503 | */ |
||
504 | void |
||
505 | g_socket_client_set_local_address (GSocketClient *client, |
||
506 | GSocketAddress *address) |
||
507 | { |
||
508 | if (address) |
||
509 | g_object_ref (address); |
||
510 | |||
511 | if (client->priv->local_address) |
||
512 | { |
||
513 | g_object_unref (client->priv->local_address); |
||
514 | } |
||
515 | client->priv->local_address = address; |
||
516 | g_object_notify (G_OBJECT (client), "local-address"); |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * g_socket_client_get_timeout: |
||
521 | * @client: a #GSocketClient |
||
522 | * |
||
523 | * Gets the I/O timeout time for sockets created by @client. |
||
524 | * |
||
525 | * See g_socket_client_set_timeout() for details. |
||
526 | * |
||
527 | * Returns: the timeout in seconds |
||
528 | * |
||
529 | * Since: 2.26 |
||
530 | */ |
||
531 | guint |
||
532 | g_socket_client_get_timeout (GSocketClient *client) |
||
533 | { |
||
534 | return client->priv->timeout; |
||
535 | } |
||
536 | |||
537 | |||
538 | /** |
||
539 | * g_socket_client_set_timeout: |
||
540 | * @client: a #GSocketClient. |
||
541 | * @timeout: the timeout |
||
542 | * |
||
543 | * Sets the I/O timeout for sockets created by @client. @timeout is a |
||
544 | * time in seconds, or 0 for no timeout (the default). |
||
545 | * |
||
546 | * The timeout value affects the initial connection attempt as well, |
||
547 | * so setting this may cause calls to g_socket_client_connect(), etc, |
||
548 | * to fail with %G_IO_ERROR_TIMED_OUT. |
||
549 | * |
||
550 | * Since: 2.26 |
||
551 | */ |
||
552 | void |
||
553 | g_socket_client_set_timeout (GSocketClient *client, |
||
554 | guint timeout) |
||
555 | { |
||
556 | if (client->priv->timeout == timeout) |
||
557 | return; |
||
558 | |||
559 | client->priv->timeout = timeout; |
||
560 | g_object_notify (G_OBJECT (client), "timeout"); |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * g_socket_client_get_enable_proxy: |
||
565 | * @client: a #GSocketClient. |
||
566 | * |
||
567 | * Gets the proxy enable state; see g_socket_client_set_enable_proxy() |
||
568 | * |
||
569 | * Returns: whether proxying is enabled |
||
570 | * |
||
571 | * Since: 2.26 |
||
572 | */ |
||
573 | gboolean |
||
574 | g_socket_client_get_enable_proxy (GSocketClient *client) |
||
575 | { |
||
576 | return client->priv->enable_proxy; |
||
577 | } |
||
578 | |||
579 | /** |
||
580 | * g_socket_client_set_enable_proxy: |
||
581 | * @client: a #GSocketClient. |
||
582 | * @enable: whether to enable proxies |
||
583 | * |
||
584 | * Sets whether or not @client attempts to make connections via a |
||
585 | * proxy server. When enabled (the default), #GSocketClient will use a |
||
586 | * #GProxyResolver to determine if a proxy protocol such as SOCKS is |
||
587 | * needed, and automatically do the necessary proxy negotiation. |
||
588 | * |
||
589 | * See also g_socket_client_set_proxy_resolver(). |
||
590 | * |
||
591 | * Since: 2.26 |
||
592 | */ |
||
593 | void |
||
594 | g_socket_client_set_enable_proxy (GSocketClient *client, |
||
595 | gboolean enable) |
||
596 | { |
||
597 | enable = !!enable; |
||
598 | if (client->priv->enable_proxy == enable) |
||
599 | return; |
||
600 | |||
601 | client->priv->enable_proxy = enable; |
||
602 | g_object_notify (G_OBJECT (client), "enable-proxy"); |
||
603 | } |
||
604 | |||
605 | /** |
||
606 | * g_socket_client_get_tls: |
||
607 | * @client: a #GSocketClient. |
||
608 | * |
||
609 | * Gets whether @client creates TLS connections. See |
||
610 | * g_socket_client_set_tls() for details. |
||
611 | * |
||
612 | * Returns: whether @client uses TLS |
||
613 | * |
||
614 | * Since: 2.28 |
||
615 | */ |
||
616 | gboolean |
||
617 | g_socket_client_get_tls (GSocketClient *client) |
||
618 | { |
||
619 | return client->priv->tls; |
||
620 | } |
||
621 | |||
622 | /** |
||
623 | * g_socket_client_set_tls: |
||
624 | * @client: a #GSocketClient. |
||
625 | * @tls: whether to use TLS |
||
626 | * |
||
627 | * Sets whether @client creates TLS (aka SSL) connections. If @tls is |
||
628 | * %TRUE, @client will wrap its connections in a #GTlsClientConnection |
||
629 | * and perform a TLS handshake when connecting. |
||
630 | * |
||
631 | * Note that since #GSocketClient must return a #GSocketConnection, |
||
632 | * but #GTlsClientConnection is not a #GSocketConnection, this |
||
633 | * actually wraps the resulting #GTlsClientConnection in a |
||
634 | * #GTcpWrapperConnection when returning it. You can use |
||
635 | * g_tcp_wrapper_connection_get_base_io_stream() on the return value |
||
636 | * to extract the #GTlsClientConnection. |
||
637 | * |
||
638 | * If you need to modify the behavior of the TLS handshake (eg, by |
||
639 | * setting a client-side certificate to use, or connecting to the |
||
640 | * #GTlsConnection::accept-certificate signal), you can connect to |
||
641 | * @client's #GSocketClient::event signal and wait for it to be |
||
642 | * emitted with %G_SOCKET_CLIENT_TLS_HANDSHAKING, which will give you |
||
643 | * a chance to see the #GTlsClientConnection before the handshake |
||
644 | * starts. |
||
645 | * |
||
646 | * Since: 2.28 |
||
647 | */ |
||
648 | void |
||
649 | g_socket_client_set_tls (GSocketClient *client, |
||
650 | gboolean tls) |
||
651 | { |
||
652 | tls = !!tls; |
||
653 | if (tls == client->priv->tls) |
||
654 | return; |
||
655 | |||
656 | client->priv->tls = tls; |
||
657 | g_object_notify (G_OBJECT (client), "tls"); |
||
658 | } |
||
659 | |||
660 | /** |
||
661 | * g_socket_client_get_tls_validation_flags: |
||
662 | * @client: a #GSocketClient. |
||
663 | * |
||
664 | * Gets the TLS validation flags used creating TLS connections via |
||
665 | * @client. |
||
666 | * |
||
667 | * Returns: the TLS validation flags |
||
668 | * |
||
669 | * Since: 2.28 |
||
670 | */ |
||
671 | GTlsCertificateFlags |
||
672 | g_socket_client_get_tls_validation_flags (GSocketClient *client) |
||
673 | { |
||
674 | return client->priv->tls_validation_flags; |
||
675 | } |
||
676 | |||
677 | /** |
||
678 | * g_socket_client_set_tls_validation_flags: |
||
679 | * @client: a #GSocketClient. |
||
680 | * @flags: the validation flags |
||
681 | * |
||
682 | * Sets the TLS validation flags used when creating TLS connections |
||
683 | * via @client. The default value is %G_TLS_CERTIFICATE_VALIDATE_ALL. |
||
684 | * |
||
685 | * Since: 2.28 |
||
686 | */ |
||
687 | void |
||
688 | g_socket_client_set_tls_validation_flags (GSocketClient *client, |
||
689 | GTlsCertificateFlags flags) |
||
690 | { |
||
691 | if (client->priv->tls_validation_flags != flags) |
||
692 | { |
||
693 | client->priv->tls_validation_flags = flags; |
||
694 | g_object_notify (G_OBJECT (client), "tls-validation-flags"); |
||
695 | } |
||
696 | } |
||
697 | |||
698 | /** |
||
699 | * g_socket_client_get_proxy_resolver: |
||
700 | * @client: a #GSocketClient. |
||
701 | * |
||
702 | * Gets the #GProxyResolver being used by @client. Normally, this will |
||
703 | * be the resolver returned by g_proxy_resolver_get_default(), but you |
||
704 | * can override it with g_socket_client_set_proxy_resolver(). |
||
705 | * |
||
706 | * Returns: (transfer none): The #GProxyResolver being used by |
||
707 | * @client. |
||
708 | * |
||
709 | * Since: 2.36 |
||
710 | */ |
||
711 | GProxyResolver * |
||
712 | g_socket_client_get_proxy_resolver (GSocketClient *client) |
||
713 | { |
||
714 | if (client->priv->proxy_resolver) |
||
715 | return client->priv->proxy_resolver; |
||
716 | else |
||
717 | return g_proxy_resolver_get_default (); |
||
718 | } |
||
719 | |||
720 | /** |
||
721 | * g_socket_client_set_proxy_resolver: |
||
722 | * @client: a #GSocketClient. |
||
723 | * @proxy_resolver: (allow-none): a #GProxyResolver, or %NULL for the |
||
724 | * default. |
||
725 | * |
||
726 | * Overrides the #GProxyResolver used by @client. You can call this if |
||
727 | * you want to use specific proxies, rather than using the system |
||
728 | * default proxy settings. |
||
729 | * |
||
730 | * Note that whether or not the proxy resolver is actually used |
||
731 | * depends on the setting of #GSocketClient:enable-proxy, which is not |
||
732 | * changed by this function (but which is %TRUE by default) |
||
733 | * |
||
734 | * Since: 2.36 |
||
735 | */ |
||
736 | void |
||
737 | g_socket_client_set_proxy_resolver (GSocketClient *client, |
||
738 | GProxyResolver *proxy_resolver) |
||
739 | { |
||
740 | /* We have to be careful to avoid calling |
||
741 | * g_proxy_resolver_get_default() until we're sure we need it, |
||
742 | * because trying to load the default proxy resolver module will |
||
743 | * break some test programs that aren't expecting it (eg, |
||
744 | * tests/gsettings). |
||
745 | */ |
||
746 | |||
747 | if (client->priv->proxy_resolver) |
||
748 | g_object_unref (client->priv->proxy_resolver); |
||
749 | |||
750 | client->priv->proxy_resolver = proxy_resolver; |
||
751 | |||
752 | if (client->priv->proxy_resolver) |
||
753 | g_object_ref (client->priv->proxy_resolver); |
||
754 | } |
||
755 | |||
756 | static void |
||
757 | g_socket_client_class_init (GSocketClientClass *class) |
||
758 | { |
||
759 | GObjectClass *gobject_class = G_OBJECT_CLASS (class); |
||
760 | |||
761 | gobject_class->finalize = g_socket_client_finalize; |
||
762 | gobject_class->set_property = g_socket_client_set_property; |
||
763 | gobject_class->get_property = g_socket_client_get_property; |
||
764 | |||
765 | /** |
||
766 | * GSocketClient::event: |
||
767 | * @client: the #GSocketClient |
||
768 | * @event: the event that is occurring |
||
769 | * @connectable: the #GSocketConnectable that @event is occurring on |
||
770 | * @connection: (nullable): the current representation of the connection |
||
771 | * |
||
772 | * Emitted when @client's activity on @connectable changes state. |
||
773 | * Among other things, this can be used to provide progress |
||
774 | * information about a network connection in the UI. The meanings of |
||
775 | * the different @event values are as follows: |
||
776 | * |
||
777 | * - %G_SOCKET_CLIENT_RESOLVING: @client is about to look up @connectable |
||
778 | * in DNS. @connection will be %NULL. |
||
779 | * |
||
780 | * - %G_SOCKET_CLIENT_RESOLVED: @client has successfully resolved |
||
781 | * @connectable in DNS. @connection will be %NULL. |
||
782 | * |
||
783 | * - %G_SOCKET_CLIENT_CONNECTING: @client is about to make a connection |
||
784 | * to a remote host; either a proxy server or the destination server |
||
785 | * itself. @connection is the #GSocketConnection, which is not yet |
||
786 | * connected. Since GLib 2.40, you can access the remote |
||
787 | * address via g_socket_connection_get_remote_address(). |
||
788 | * |
||
789 | * - %G_SOCKET_CLIENT_CONNECTED: @client has successfully connected |
||
790 | * to a remote host. @connection is the connected #GSocketConnection. |
||
791 | * |
||
792 | * - %G_SOCKET_CLIENT_PROXY_NEGOTIATING: @client is about to negotiate |
||
793 | * with a proxy to get it to connect to @connectable. @connection is |
||
794 | * the #GSocketConnection to the proxy server. |
||
795 | * |
||
796 | * - %G_SOCKET_CLIENT_PROXY_NEGOTIATED: @client has negotiated a |
||
797 | * connection to @connectable through a proxy server. @connection is |
||
798 | * the stream returned from g_proxy_connect(), which may or may not |
||
799 | * be a #GSocketConnection. |
||
800 | * |
||
801 | * - %G_SOCKET_CLIENT_TLS_HANDSHAKING: @client is about to begin a TLS |
||
802 | * handshake. @connection is a #GTlsClientConnection. |
||
803 | * |
||
804 | * - %G_SOCKET_CLIENT_TLS_HANDSHAKED: @client has successfully completed |
||
805 | * the TLS handshake. @connection is a #GTlsClientConnection. |
||
806 | * |
||
807 | * - %G_SOCKET_CLIENT_COMPLETE: @client has either successfully connected |
||
808 | * to @connectable (in which case @connection is the #GSocketConnection |
||
809 | * that it will be returning to the caller) or has failed (in which |
||
810 | * case @connection is %NULL and the client is about to return an error). |
||
811 | * |
||
812 | * Each event except %G_SOCKET_CLIENT_COMPLETE may be emitted |
||
813 | * multiple times (or not at all) for a given connectable (in |
||
814 | * particular, if @client ends up attempting to connect to more than |
||
815 | * one address). However, if @client emits the #GSocketClient::event |
||
816 | * signal at all for a given connectable, that it will always emit |
||
817 | * it with %G_SOCKET_CLIENT_COMPLETE when it is done. |
||
818 | * |
||
819 | * Note that there may be additional #GSocketClientEvent values in |
||
820 | * the future; unrecognized @event values should be ignored. |
||
821 | * |
||
822 | * Since: 2.32 |
||
823 | */ |
||
824 | signals[EVENT] = |
||
825 | g_signal_new (I_("event"), |
||
826 | G_TYPE_FROM_CLASS (gobject_class), |
||
827 | G_SIGNAL_RUN_LAST, |
||
828 | G_STRUCT_OFFSET (GSocketClientClass, event), |
||
829 | NULL, NULL, |
||
830 | NULL, |
||
831 | G_TYPE_NONE, 3, |
||
832 | G_TYPE_SOCKET_CLIENT_EVENT, |
||
833 | G_TYPE_SOCKET_CONNECTABLE, |
||
834 | G_TYPE_IO_STREAM); |
||
835 | |||
836 | g_object_class_install_property (gobject_class, PROP_FAMILY, |
||
837 | g_param_spec_enum ("family", |
||
838 | P_("Socket family"), |
||
839 | P_("The sockets address family to use for socket construction"), |
||
840 | G_TYPE_SOCKET_FAMILY, |
||
841 | G_SOCKET_FAMILY_INVALID, |
||
842 | G_PARAM_CONSTRUCT | |
||
843 | G_PARAM_READWRITE | |
||
844 | G_PARAM_STATIC_STRINGS)); |
||
845 | |||
846 | g_object_class_install_property (gobject_class, PROP_TYPE, |
||
847 | g_param_spec_enum ("type", |
||
848 | P_("Socket type"), |
||
849 | P_("The sockets type to use for socket construction"), |
||
850 | G_TYPE_SOCKET_TYPE, |
||
851 | G_SOCKET_TYPE_STREAM, |
||
852 | G_PARAM_CONSTRUCT | |
||
853 | G_PARAM_READWRITE | |
||
854 | G_PARAM_STATIC_STRINGS)); |
||
855 | |||
856 | g_object_class_install_property (gobject_class, PROP_PROTOCOL, |
||
857 | g_param_spec_enum ("protocol", |
||
858 | P_("Socket protocol"), |
||
859 | P_("The protocol to use for socket construction, or 0 for default"), |
||
860 | G_TYPE_SOCKET_PROTOCOL, |
||
861 | G_SOCKET_PROTOCOL_DEFAULT, |
||
862 | G_PARAM_CONSTRUCT | |
||
863 | G_PARAM_READWRITE | |
||
864 | G_PARAM_STATIC_STRINGS)); |
||
865 | |||
866 | g_object_class_install_property (gobject_class, PROP_LOCAL_ADDRESS, |
||
867 | g_param_spec_object ("local-address", |
||
868 | P_("Local address"), |
||
869 | P_("The local address constructed sockets will be bound to"), |
||
870 | G_TYPE_SOCKET_ADDRESS, |
||
871 | G_PARAM_CONSTRUCT | |
||
872 | G_PARAM_READWRITE | |
||
873 | G_PARAM_STATIC_STRINGS)); |
||
874 | |||
875 | g_object_class_install_property (gobject_class, PROP_TIMEOUT, |
||
876 | g_param_spec_uint ("timeout", |
||
877 | P_("Socket timeout"), |
||
878 | P_("The I/O timeout for sockets, or 0 for none"), |
||
879 | 0, G_MAXUINT, 0, |
||
880 | G_PARAM_CONSTRUCT | |
||
881 | G_PARAM_READWRITE | |
||
882 | G_PARAM_STATIC_STRINGS)); |
||
883 | |||
884 | g_object_class_install_property (gobject_class, PROP_ENABLE_PROXY, |
||
885 | g_param_spec_boolean ("enable-proxy", |
||
886 | P_("Enable proxy"), |
||
887 | P_("Enable proxy support"), |
||
888 | TRUE, |
||
889 | G_PARAM_CONSTRUCT | |
||
890 | G_PARAM_READWRITE | |
||
891 | G_PARAM_STATIC_STRINGS)); |
||
892 | |||
893 | g_object_class_install_property (gobject_class, PROP_TLS, |
||
894 | g_param_spec_boolean ("tls", |
||
895 | P_("TLS"), |
||
896 | P_("Whether to create TLS connections"), |
||
897 | FALSE, |
||
898 | G_PARAM_CONSTRUCT | |
||
899 | G_PARAM_READWRITE | |
||
900 | G_PARAM_STATIC_STRINGS)); |
||
901 | g_object_class_install_property (gobject_class, PROP_TLS_VALIDATION_FLAGS, |
||
902 | g_param_spec_flags ("tls-validation-flags", |
||
903 | P_("TLS validation flags"), |
||
904 | P_("TLS validation flags to use"), |
||
905 | G_TYPE_TLS_CERTIFICATE_FLAGS, |
||
906 | G_TLS_CERTIFICATE_VALIDATE_ALL, |
||
907 | G_PARAM_CONSTRUCT | |
||
908 | G_PARAM_READWRITE | |
||
909 | G_PARAM_STATIC_STRINGS)); |
||
910 | |||
911 | /** |
||
912 | * GSocketClient:proxy-resolver: |
||
913 | * |
||
914 | * The proxy resolver to use |
||
915 | * |
||
916 | * Since: 2.36 |
||
917 | */ |
||
918 | g_object_class_install_property (gobject_class, PROP_PROXY_RESOLVER, |
||
919 | g_param_spec_object ("proxy-resolver", |
||
920 | P_("Proxy resolver"), |
||
921 | P_("The proxy resolver to use"), |
||
922 | G_TYPE_PROXY_RESOLVER, |
||
923 | G_PARAM_CONSTRUCT | |
||
924 | G_PARAM_READWRITE | |
||
925 | G_PARAM_STATIC_STRINGS)); |
||
926 | } |
||
927 | |||
928 | static void |
||
929 | g_socket_client_emit_event (GSocketClient *client, |
||
930 | GSocketClientEvent event, |
||
931 | GSocketConnectable *connectable, |
||
932 | GIOStream *connection) |
||
933 | { |
||
934 | g_signal_emit (client, signals[EVENT], 0, |
||
935 | event, connectable, connection); |
||
936 | } |
||
937 | |||
938 | /** |
||
939 | * g_socket_client_connect: |
||
940 | * @client: a #GSocketClient. |
||
941 | * @connectable: a #GSocketConnectable specifying the remote address. |
||
942 | * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. |
||
943 | * @error: #GError for error reporting, or %NULL to ignore. |
||
944 | * |
||
945 | * Tries to resolve the @connectable and make a network connection to it. |
||
946 | * |
||
947 | * Upon a successful connection, a new #GSocketConnection is constructed |
||
948 | * and returned. The caller owns this new object and must drop their |
||
949 | * reference to it when finished with it. |
||
950 | * |
||
951 | * The type of the #GSocketConnection object returned depends on the type of |
||
952 | * the underlying socket that is used. For instance, for a TCP/IP connection |
||
953 | * it will be a #GTcpConnection. |
||
954 | * |
||
955 | * The socket created will be the same family as the address that the |
||
956 | * @connectable resolves to, unless family is set with g_socket_client_set_family() |
||
957 | * or indirectly via g_socket_client_set_local_address(). The socket type |
||
958 | * defaults to %G_SOCKET_TYPE_STREAM but can be set with |
||
959 | * g_socket_client_set_socket_type(). |
||
960 | * |
||
961 | * If a local address is specified with g_socket_client_set_local_address() the |
||
962 | * socket will be bound to this address before connecting. |
||
963 | * |
||
964 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
965 | * |
||
966 | * Since: 2.22 |
||
967 | */ |
||
968 | GSocketConnection * |
||
969 | g_socket_client_connect (GSocketClient *client, |
||
970 | GSocketConnectable *connectable, |
||
971 | GCancellable *cancellable, |
||
972 | GError **error) |
||
973 | { |
||
974 | GIOStream *connection = NULL; |
||
975 | GSocketAddressEnumerator *enumerator = NULL; |
||
976 | GError *last_error, *tmp_error; |
||
977 | |||
978 | last_error = NULL; |
||
979 | |||
980 | if (can_use_proxy (client)) |
||
981 | { |
||
982 | enumerator = g_socket_connectable_proxy_enumerate (connectable); |
||
983 | if (client->priv->proxy_resolver && |
||
984 | G_IS_PROXY_ADDRESS_ENUMERATOR (enumerator)) |
||
985 | { |
||
986 | g_object_set (G_OBJECT (enumerator), |
||
987 | "proxy-resolver", client->priv->proxy_resolver, |
||
988 | NULL); |
||
989 | } |
||
990 | } |
||
991 | else |
||
992 | enumerator = g_socket_connectable_enumerate (connectable); |
||
993 | |||
994 | while (connection == NULL) |
||
995 | { |
||
996 | GSocketAddress *address = NULL; |
||
997 | gboolean application_proxy = FALSE; |
||
998 | GSocket *socket; |
||
999 | gboolean using_proxy; |
||
1000 | |||
1001 | if (g_cancellable_is_cancelled (cancellable)) |
||
1002 | { |
||
1003 | g_clear_error (error); |
||
1004 | g_cancellable_set_error_if_cancelled (cancellable, error); |
||
1005 | break; |
||
1006 | } |
||
1007 | |||
1008 | tmp_error = NULL; |
||
1009 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVING, |
||
1010 | connectable, NULL); |
||
1011 | address = g_socket_address_enumerator_next (enumerator, cancellable, |
||
1012 | &tmp_error); |
||
1013 | |||
1014 | if (address == NULL) |
||
1015 | { |
||
1016 | if (tmp_error) |
||
1017 | { |
||
1018 | g_clear_error (&last_error); |
||
1019 | g_propagate_error (error, tmp_error); |
||
1020 | } |
||
1021 | else if (last_error) |
||
1022 | { |
||
1023 | g_propagate_error (error, last_error); |
||
1024 | } |
||
1025 | else |
||
1026 | g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, |
||
1027 | _("Unknown error on connect")); |
||
1028 | break; |
||
1029 | } |
||
1030 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_RESOLVED, |
||
1031 | connectable, NULL); |
||
1032 | |||
1033 | using_proxy = (G_IS_PROXY_ADDRESS (address) && |
||
1034 | client->priv->enable_proxy); |
||
1035 | |||
1036 | /* clear error from previous attempt */ |
||
1037 | g_clear_error (&last_error); |
||
1038 | |||
1039 | socket = create_socket (client, address, &last_error); |
||
1040 | if (socket == NULL) |
||
1041 | { |
||
1042 | g_object_unref (address); |
||
1043 | continue; |
||
1044 | } |
||
1045 | |||
1046 | connection = (GIOStream *)g_socket_connection_factory_create_connection (socket); |
||
1047 | g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, address); |
||
1048 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTING, connectable, connection); |
||
1049 | |||
1050 | if (g_socket_connection_connect (G_SOCKET_CONNECTION (connection), |
||
1051 | address, cancellable, &last_error)) |
||
1052 | { |
||
1053 | g_socket_connection_set_cached_remote_address ((GSocketConnection*)connection, NULL); |
||
1054 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_CONNECTED, connectable, connection); |
||
1055 | } |
||
1056 | else |
||
1057 | { |
||
1058 | clarify_connect_error (last_error, connectable, address); |
||
1059 | g_object_unref (connection); |
||
1060 | connection = NULL; |
||
1061 | } |
||
1062 | |||
1063 | if (connection && using_proxy) |
||
1064 | { |
||
1065 | GProxyAddress *proxy_addr = G_PROXY_ADDRESS (address); |
||
1066 | const gchar *protocol; |
||
1067 | GProxy *proxy; |
||
1068 | |||
1069 | protocol = g_proxy_address_get_protocol (proxy_addr); |
||
1070 | |||
1071 | /* The connection should not be anything else then TCP Connection, |
||
1072 | * but let's put a safety guard in case |
||
1073 | */ |
||
1074 | if (!G_IS_TCP_CONNECTION (connection)) |
||
1075 | { |
||
1076 | g_critical ("Trying to proxy over non-TCP connection, this is " |
||
1077 | "most likely a bug in GLib IO library."); |
||
1078 | |||
1079 | g_set_error_literal (&last_error, |
||
1080 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
||
1081 | _("Proxying over a non-TCP connection is not supported.")); |
||
1082 | |||
1083 | g_object_unref (connection); |
||
1084 | connection = NULL; |
||
1085 | } |
||
1086 | else if (g_hash_table_contains (client->priv->app_proxies, protocol)) |
||
1087 | { |
||
1088 | application_proxy = TRUE; |
||
1089 | } |
||
1090 | else if ((proxy = g_proxy_get_default_for_protocol (protocol))) |
||
1091 | { |
||
1092 | GIOStream *proxy_connection; |
||
1093 | |||
1094 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, connectable, connection); |
||
1095 | proxy_connection = g_proxy_connect (proxy, |
||
1096 | connection, |
||
1097 | proxy_addr, |
||
1098 | cancellable, |
||
1099 | &last_error); |
||
1100 | g_object_unref (connection); |
||
1101 | connection = proxy_connection; |
||
1102 | g_object_unref (proxy); |
||
1103 | |||
1104 | if (connection) |
||
1105 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, connectable, connection); |
||
1106 | } |
||
1107 | else |
||
1108 | { |
||
1109 | g_set_error (&last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
||
1110 | _("Proxy protocol '%s' is not supported."), |
||
1111 | protocol); |
||
1112 | g_object_unref (connection); |
||
1113 | connection = NULL; |
||
1114 | } |
||
1115 | } |
||
1116 | |||
1117 | if (!application_proxy && connection && client->priv->tls) |
||
1118 | { |
||
1119 | GIOStream *tlsconn; |
||
1120 | |||
1121 | tlsconn = g_tls_client_connection_new (connection, connectable, &last_error); |
||
1122 | g_object_unref (connection); |
||
1123 | connection = tlsconn; |
||
1124 | |||
1125 | if (tlsconn) |
||
1126 | { |
||
1127 | g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn), |
||
1128 | client->priv->tls_validation_flags); |
||
1129 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKING, connectable, connection); |
||
1130 | if (g_tls_connection_handshake (G_TLS_CONNECTION (tlsconn), |
||
1131 | cancellable, &last_error)) |
||
1132 | { |
||
1133 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_TLS_HANDSHAKED, connectable, connection); |
||
1134 | } |
||
1135 | else |
||
1136 | { |
||
1137 | g_object_unref (tlsconn); |
||
1138 | connection = NULL; |
||
1139 | } |
||
1140 | } |
||
1141 | } |
||
1142 | |||
1143 | if (connection && !G_IS_SOCKET_CONNECTION (connection)) |
||
1144 | { |
||
1145 | GSocketConnection *wrapper_connection; |
||
1146 | |||
1147 | wrapper_connection = g_tcp_wrapper_connection_new (connection, socket); |
||
1148 | g_object_unref (connection); |
||
1149 | connection = (GIOStream *)wrapper_connection; |
||
1150 | } |
||
1151 | |||
1152 | g_object_unref (socket); |
||
1153 | g_object_unref (address); |
||
1154 | } |
||
1155 | g_object_unref (enumerator); |
||
1156 | |||
1157 | g_socket_client_emit_event (client, G_SOCKET_CLIENT_COMPLETE, connectable, connection); |
||
1158 | return G_SOCKET_CONNECTION (connection); |
||
1159 | } |
||
1160 | |||
1161 | /** |
||
1162 | * g_socket_client_connect_to_host: |
||
1163 | * @client: a #GSocketClient |
||
1164 | * @host_and_port: the name and optionally port of the host to connect to |
||
1165 | * @default_port: the default port to connect to |
||
1166 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1167 | * @error: a pointer to a #GError, or %NULL |
||
1168 | * |
||
1169 | * This is a helper function for g_socket_client_connect(). |
||
1170 | * |
||
1171 | * Attempts to create a TCP connection to the named host. |
||
1172 | * |
||
1173 | * @host_and_port may be in any of a number of recognized formats; an IPv6 |
||
1174 | * address, an IPv4 address, or a domain name (in which case a DNS |
||
1175 | * lookup is performed). Quoting with [] is supported for all address |
||
1176 | * types. A port override may be specified in the usual way with a |
||
1177 | * colon. Ports may be given as decimal numbers or symbolic names (in |
||
1178 | * which case an /etc/services lookup is performed). |
||
1179 | * |
||
1180 | * If no port override is given in @host_and_port then @default_port will be |
||
1181 | * used as the port number to connect to. |
||
1182 | * |
||
1183 | * In general, @host_and_port is expected to be provided by the user (allowing |
||
1184 | * them to give the hostname, and a port override if necessary) and |
||
1185 | * @default_port is expected to be provided by the application. |
||
1186 | * |
||
1187 | * In the case that an IP address is given, a single connection |
||
1188 | * attempt is made. In the case that a name is given, multiple |
||
1189 | * connection attempts may be made, in turn and according to the |
||
1190 | * number of address records in DNS, until a connection succeeds. |
||
1191 | * |
||
1192 | * Upon a successful connection, a new #GSocketConnection is constructed |
||
1193 | * and returned. The caller owns this new object and must drop their |
||
1194 | * reference to it when finished with it. |
||
1195 | * |
||
1196 | * In the event of any failure (DNS error, service not found, no hosts |
||
1197 | * connectable) %NULL is returned and @error (if non-%NULL) is set |
||
1198 | * accordingly. |
||
1199 | * |
||
1200 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
1201 | * |
||
1202 | * Since: 2.22 |
||
1203 | */ |
||
1204 | GSocketConnection * |
||
1205 | g_socket_client_connect_to_host (GSocketClient *client, |
||
1206 | const gchar *host_and_port, |
||
1207 | guint16 default_port, |
||
1208 | GCancellable *cancellable, |
||
1209 | GError **error) |
||
1210 | { |
||
1211 | GSocketConnectable *connectable; |
||
1212 | GSocketConnection *connection; |
||
1213 | |||
1214 | connectable = g_network_address_parse (host_and_port, default_port, error); |
||
1215 | if (connectable == NULL) |
||
1216 | return NULL; |
||
1217 | |||
1218 | connection = g_socket_client_connect (client, connectable, |
||
1219 | cancellable, error); |
||
1220 | g_object_unref (connectable); |
||
1221 | |||
1222 | return connection; |
||
1223 | } |
||
1224 | |||
1225 | /** |
||
1226 | * g_socket_client_connect_to_service: |
||
1227 | * @client: a #GSocketConnection |
||
1228 | * @domain: a domain name |
||
1229 | * @service: the name of the service to connect to |
||
1230 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1231 | * @error: a pointer to a #GError, or %NULL |
||
1232 | * |
||
1233 | * Attempts to create a TCP connection to a service. |
||
1234 | * |
||
1235 | * This call looks up the SRV record for @service at @domain for the |
||
1236 | * "tcp" protocol. It then attempts to connect, in turn, to each of |
||
1237 | * the hosts providing the service until either a connection succeeds |
||
1238 | * or there are no hosts remaining. |
||
1239 | * |
||
1240 | * Upon a successful connection, a new #GSocketConnection is constructed |
||
1241 | * and returned. The caller owns this new object and must drop their |
||
1242 | * reference to it when finished with it. |
||
1243 | * |
||
1244 | * In the event of any failure (DNS error, service not found, no hosts |
||
1245 | * connectable) %NULL is returned and @error (if non-%NULL) is set |
||
1246 | * accordingly. |
||
1247 | * |
||
1248 | * Returns: (transfer full): a #GSocketConnection if successful, or %NULL on error |
||
1249 | */ |
||
1250 | GSocketConnection * |
||
1251 | g_socket_client_connect_to_service (GSocketClient *client, |
||
1252 | const gchar *domain, |
||
1253 | const gchar *service, |
||
1254 | GCancellable *cancellable, |
||
1255 | GError **error) |
||
1256 | { |
||
1257 | GSocketConnectable *connectable; |
||
1258 | GSocketConnection *connection; |
||
1259 | |||
1260 | connectable = g_network_service_new (service, "tcp", domain); |
||
1261 | connection = g_socket_client_connect (client, connectable, |
||
1262 | cancellable, error); |
||
1263 | g_object_unref (connectable); |
||
1264 | |||
1265 | return connection; |
||
1266 | } |
||
1267 | |||
1268 | /** |
||
1269 | * g_socket_client_connect_to_uri: |
||
1270 | * @client: a #GSocketClient |
||
1271 | * @uri: A network URI |
||
1272 | * @default_port: the default port to connect to |
||
1273 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1274 | * @error: a pointer to a #GError, or %NULL |
||
1275 | * |
||
1276 | * This is a helper function for g_socket_client_connect(). |
||
1277 | * |
||
1278 | * Attempts to create a TCP connection with a network URI. |
||
1279 | * |
||
1280 | * @uri may be any valid URI containing an "authority" (hostname/port) |
||
1281 | * component. If a port is not specified in the URI, @default_port |
||
1282 | * will be used. TLS will be negotiated if #GSocketClient:tls is %TRUE. |
||
1283 | * (#GSocketClient does not know to automatically assume TLS for |
||
1284 | * certain URI schemes.) |
||
1285 | * |
||
1286 | * Using this rather than g_socket_client_connect() or |
||
1287 | * g_socket_client_connect_to_host() allows #GSocketClient to |
||
1288 | * determine when to use application-specific proxy protocols. |
||
1289 | * |
||
1290 | * Upon a successful connection, a new #GSocketConnection is constructed |
||
1291 | * and returned. The caller owns this new object and must drop their |
||
1292 | * reference to it when finished with it. |
||
1293 | * |
||
1294 | * In the event of any failure (DNS error, service not found, no hosts |
||
1295 | * connectable) %NULL is returned and @error (if non-%NULL) is set |
||
1296 | * accordingly. |
||
1297 | * |
||
1298 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
1299 | * |
||
1300 | * Since: 2.26 |
||
1301 | */ |
||
1302 | GSocketConnection * |
||
1303 | g_socket_client_connect_to_uri (GSocketClient *client, |
||
1304 | const gchar *uri, |
||
1305 | guint16 default_port, |
||
1306 | GCancellable *cancellable, |
||
1307 | GError **error) |
||
1308 | { |
||
1309 | GSocketConnectable *connectable; |
||
1310 | GSocketConnection *connection; |
||
1311 | |||
1312 | connectable = g_network_address_parse_uri (uri, default_port, error); |
||
1313 | if (connectable == NULL) |
||
1314 | return NULL; |
||
1315 | |||
1316 | connection = g_socket_client_connect (client, connectable, |
||
1317 | cancellable, error); |
||
1318 | g_object_unref (connectable); |
||
1319 | |||
1320 | return connection; |
||
1321 | } |
||
1322 | |||
1323 | typedef struct |
||
1324 | { |
||
1325 | GTask *task; |
||
1326 | GSocketClient *client; |
||
1327 | |||
1328 | GSocketConnectable *connectable; |
||
1329 | GSocketAddressEnumerator *enumerator; |
||
1330 | GProxyAddress *proxy_addr; |
||
1331 | GSocketAddress *current_addr; |
||
1332 | GSocket *current_socket; |
||
1333 | GIOStream *connection; |
||
1334 | |||
1335 | GError *last_error; |
||
1336 | } GSocketClientAsyncConnectData; |
||
1337 | |||
1338 | static void |
||
1339 | g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data) |
||
1340 | { |
||
1341 | g_clear_object (&data->connectable); |
||
1342 | g_clear_object (&data->enumerator); |
||
1343 | g_clear_object (&data->proxy_addr); |
||
1344 | g_clear_object (&data->current_addr); |
||
1345 | g_clear_object (&data->current_socket); |
||
1346 | g_clear_object (&data->connection); |
||
1347 | |||
1348 | g_clear_error (&data->last_error); |
||
1349 | |||
1350 | g_slice_free (GSocketClientAsyncConnectData, data); |
||
1351 | } |
||
1352 | |||
1353 | static void |
||
1354 | g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data) |
||
1355 | { |
||
1356 | g_assert (data->connection); |
||
1357 | |||
1358 | if (!G_IS_SOCKET_CONNECTION (data->connection)) |
||
1359 | { |
||
1360 | GSocketConnection *wrapper_connection; |
||
1361 | |||
1362 | wrapper_connection = g_tcp_wrapper_connection_new (data->connection, |
||
1363 | data->current_socket); |
||
1364 | g_object_unref (data->connection); |
||
1365 | data->connection = (GIOStream *)wrapper_connection; |
||
1366 | } |
||
1367 | |||
1368 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, data->connection); |
||
1369 | g_task_return_pointer (data->task, data->connection, g_object_unref); |
||
1370 | data->connection = NULL; |
||
1371 | g_object_unref (data->task); |
||
1372 | } |
||
1373 | |||
1374 | |||
1375 | static void |
||
1376 | g_socket_client_enumerator_callback (GObject *object, |
||
1377 | GAsyncResult *result, |
||
1378 | gpointer user_data); |
||
1379 | |||
1380 | static void |
||
1381 | set_last_error (GSocketClientAsyncConnectData *data, |
||
1382 | GError *error) |
||
1383 | { |
||
1384 | g_clear_error (&data->last_error); |
||
1385 | data->last_error = error; |
||
1386 | } |
||
1387 | |||
1388 | static void |
||
1389 | enumerator_next_async (GSocketClientAsyncConnectData *data) |
||
1390 | { |
||
1391 | /* We need to cleanup the state */ |
||
1392 | g_clear_object (&data->current_socket); |
||
1393 | g_clear_object (&data->current_addr); |
||
1394 | g_clear_object (&data->proxy_addr); |
||
1395 | g_clear_object (&data->connection); |
||
1396 | |||
1397 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL); |
||
1398 | g_socket_address_enumerator_next_async (data->enumerator, |
||
1399 | g_task_get_cancellable (data->task), |
||
1400 | g_socket_client_enumerator_callback, |
||
1401 | data); |
||
1402 | } |
||
1403 | |||
1404 | static void |
||
1405 | g_socket_client_tls_handshake_callback (GObject *object, |
||
1406 | GAsyncResult *result, |
||
1407 | gpointer user_data) |
||
1408 | { |
||
1409 | GSocketClientAsyncConnectData *data = user_data; |
||
1410 | |||
1411 | if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object), |
||
1412 | result, |
||
1413 | &data->last_error)) |
||
1414 | { |
||
1415 | g_object_unref (data->connection); |
||
1416 | data->connection = G_IO_STREAM (object); |
||
1417 | |||
1418 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, data->connection); |
||
1419 | g_socket_client_async_connect_complete (data); |
||
1420 | } |
||
1421 | else |
||
1422 | { |
||
1423 | g_object_unref (object); |
||
1424 | enumerator_next_async (data); |
||
1425 | } |
||
1426 | } |
||
1427 | |||
1428 | static void |
||
1429 | g_socket_client_tls_handshake (GSocketClientAsyncConnectData *data) |
||
1430 | { |
||
1431 | GIOStream *tlsconn; |
||
1432 | |||
1433 | if (!data->client->priv->tls) |
||
1434 | { |
||
1435 | g_socket_client_async_connect_complete (data); |
||
1436 | return; |
||
1437 | } |
||
1438 | |||
1439 | tlsconn = g_tls_client_connection_new (data->connection, |
||
1440 | data->connectable, |
||
1441 | &data->last_error); |
||
1442 | if (tlsconn) |
||
1443 | { |
||
1444 | g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (tlsconn), |
||
1445 | data->client->priv->tls_validation_flags); |
||
1446 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKING, data->connectable, G_IO_STREAM (tlsconn)); |
||
1447 | g_tls_connection_handshake_async (G_TLS_CONNECTION (tlsconn), |
||
1448 | G_PRIORITY_DEFAULT, |
||
1449 | g_task_get_cancellable (data->task), |
||
1450 | g_socket_client_tls_handshake_callback, |
||
1451 | data); |
||
1452 | } |
||
1453 | else |
||
1454 | { |
||
1455 | enumerator_next_async (data); |
||
1456 | } |
||
1457 | } |
||
1458 | |||
1459 | static void |
||
1460 | g_socket_client_proxy_connect_callback (GObject *object, |
||
1461 | GAsyncResult *result, |
||
1462 | gpointer user_data) |
||
1463 | { |
||
1464 | GSocketClientAsyncConnectData *data = user_data; |
||
1465 | |||
1466 | g_object_unref (data->connection); |
||
1467 | data->connection = g_proxy_connect_finish (G_PROXY (object), |
||
1468 | result, |
||
1469 | &data->last_error); |
||
1470 | if (data->connection) |
||
1471 | { |
||
1472 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, data->connection); |
||
1473 | } |
||
1474 | else |
||
1475 | { |
||
1476 | enumerator_next_async (data); |
||
1477 | return; |
||
1478 | } |
||
1479 | |||
1480 | g_socket_client_tls_handshake (data); |
||
1481 | } |
||
1482 | |||
1483 | static void |
||
1484 | g_socket_client_connected_callback (GObject *source, |
||
1485 | GAsyncResult *result, |
||
1486 | gpointer user_data) |
||
1487 | { |
||
1488 | GSocketClientAsyncConnectData *data = user_data; |
||
1489 | GError *error = NULL; |
||
1490 | GProxy *proxy; |
||
1491 | const gchar *protocol; |
||
1492 | |||
1493 | if (g_task_return_error_if_cancelled (data->task)) |
||
1494 | { |
||
1495 | g_object_unref (data->task); |
||
1496 | return; |
||
1497 | } |
||
1498 | |||
1499 | if (!g_socket_connection_connect_finish (G_SOCKET_CONNECTION (source), |
||
1500 | result, &error)) |
||
1501 | { |
||
1502 | clarify_connect_error (error, data->connectable, |
||
1503 | data->current_addr); |
||
1504 | set_last_error (data, error); |
||
1505 | |||
1506 | /* try next one */ |
||
1507 | enumerator_next_async (data); |
||
1508 | return; |
||
1509 | } |
||
1510 | |||
1511 | g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, NULL); |
||
1512 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, data->connection); |
||
1513 | |||
1514 | /* wrong, but backward compatible */ |
||
1515 | g_socket_set_blocking (data->current_socket, TRUE); |
||
1516 | |||
1517 | if (!data->proxy_addr) |
||
1518 | { |
||
1519 | g_socket_client_tls_handshake (data); |
||
1520 | return; |
||
1521 | } |
||
1522 | |||
1523 | protocol = g_proxy_address_get_protocol (data->proxy_addr); |
||
1524 | |||
1525 | /* The connection should not be anything other than TCP, |
||
1526 | * but let's put a safety guard in case |
||
1527 | */ |
||
1528 | if (!G_IS_TCP_CONNECTION (data->connection)) |
||
1529 | { |
||
1530 | g_critical ("Trying to proxy over non-TCP connection, this is " |
||
1531 | "most likely a bug in GLib IO library."); |
||
1532 | |||
1533 | g_set_error_literal (&data->last_error, |
||
1534 | G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
||
1535 | _("Proxying over a non-TCP connection is not supported.")); |
||
1536 | |||
1537 | enumerator_next_async (data); |
||
1538 | } |
||
1539 | else if (g_hash_table_contains (data->client->priv->app_proxies, protocol)) |
||
1540 | { |
||
1541 | /* Simply complete the connection, we don't want to do TLS handshake |
||
1542 | * as the application proxy handling may need proxy handshake first */ |
||
1543 | g_socket_client_async_connect_complete (data); |
||
1544 | } |
||
1545 | else if ((proxy = g_proxy_get_default_for_protocol (protocol))) |
||
1546 | { |
||
1547 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, data->connection); |
||
1548 | g_proxy_connect_async (proxy, |
||
1549 | data->connection, |
||
1550 | data->proxy_addr, |
||
1551 | g_task_get_cancellable (data->task), |
||
1552 | g_socket_client_proxy_connect_callback, |
||
1553 | data); |
||
1554 | g_object_unref (proxy); |
||
1555 | } |
||
1556 | else |
||
1557 | { |
||
1558 | g_clear_error (&data->last_error); |
||
1559 | |||
1560 | g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
||
1561 | _("Proxy protocol '%s' is not supported."), |
||
1562 | protocol); |
||
1563 | |||
1564 | enumerator_next_async (data); |
||
1565 | } |
||
1566 | } |
||
1567 | |||
1568 | static void |
||
1569 | g_socket_client_enumerator_callback (GObject *object, |
||
1570 | GAsyncResult *result, |
||
1571 | gpointer user_data) |
||
1572 | { |
||
1573 | GSocketClientAsyncConnectData *data = user_data; |
||
1574 | GSocketAddress *address = NULL; |
||
1575 | GSocket *socket; |
||
1576 | GError *error = NULL; |
||
1577 | |||
1578 | if (g_task_return_error_if_cancelled (data->task)) |
||
1579 | { |
||
1580 | g_object_unref (data->task); |
||
1581 | return; |
||
1582 | } |
||
1583 | |||
1584 | address = g_socket_address_enumerator_next_finish (data->enumerator, |
||
1585 | result, &error); |
||
1586 | if (address == NULL) |
||
1587 | { |
||
1588 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL); |
||
1589 | if (!error) |
||
1590 | { |
||
1591 | if (data->last_error) |
||
1592 | { |
||
1593 | error = data->last_error; |
||
1594 | data->last_error = NULL; |
||
1595 | } |
||
1596 | else |
||
1597 | { |
||
1598 | g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, |
||
1599 | _("Unknown error on connect")); |
||
1600 | } |
||
1601 | } |
||
1602 | g_task_return_error (data->task, error); |
||
1603 | g_object_unref (data->task); |
||
1604 | return; |
||
1605 | } |
||
1606 | |||
1607 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED, |
||
1608 | data->connectable, NULL); |
||
1609 | |||
1610 | if (G_IS_PROXY_ADDRESS (address) && |
||
1611 | data->client->priv->enable_proxy) |
||
1612 | data->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address)); |
||
1613 | |||
1614 | g_clear_error (&data->last_error); |
||
1615 | |||
1616 | socket = create_socket (data->client, address, &data->last_error); |
||
1617 | if (socket == NULL) |
||
1618 | { |
||
1619 | g_object_unref (address); |
||
1620 | enumerator_next_async (data); |
||
1621 | return; |
||
1622 | } |
||
1623 | |||
1624 | data->current_socket = socket; |
||
1625 | data->current_addr = address; |
||
1626 | data->connection = (GIOStream *) g_socket_connection_factory_create_connection (socket); |
||
1627 | |||
1628 | g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, address); |
||
1629 | g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, data->connection); |
||
1630 | g_socket_connection_connect_async (G_SOCKET_CONNECTION (data->connection), |
||
1631 | address, |
||
1632 | g_task_get_cancellable (data->task), |
||
1633 | g_socket_client_connected_callback, data); |
||
1634 | } |
||
1635 | |||
1636 | /** |
||
1637 | * g_socket_client_connect_async: |
||
1638 | * @client: a #GSocketClient |
||
1639 | * @connectable: a #GSocketConnectable specifying the remote address. |
||
1640 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1641 | * @callback: (scope async): a #GAsyncReadyCallback |
||
1642 | * @user_data: (closure): user data for the callback |
||
1643 | * |
||
1644 | * This is the asynchronous version of g_socket_client_connect(). |
||
1645 | * |
||
1646 | * When the operation is finished @callback will be |
||
1647 | * called. You can then call g_socket_client_connect_finish() to get |
||
1648 | * the result of the operation. |
||
1649 | * |
||
1650 | * Since: 2.22 |
||
1651 | */ |
||
1652 | void |
||
1653 | g_socket_client_connect_async (GSocketClient *client, |
||
1654 | GSocketConnectable *connectable, |
||
1655 | GCancellable *cancellable, |
||
1656 | GAsyncReadyCallback callback, |
||
1657 | gpointer user_data) |
||
1658 | { |
||
1659 | GSocketClientAsyncConnectData *data; |
||
1660 | |||
1661 | g_return_if_fail (G_IS_SOCKET_CLIENT (client)); |
||
1662 | |||
1663 | data = g_slice_new0 (GSocketClientAsyncConnectData); |
||
1664 | data->client = client; |
||
1665 | data->connectable = g_object_ref (connectable); |
||
1666 | |||
1667 | if (can_use_proxy (client)) |
||
1668 | { |
||
1669 | data->enumerator = g_socket_connectable_proxy_enumerate (connectable); |
||
1670 | if (client->priv->proxy_resolver && |
||
1671 | G_IS_PROXY_ADDRESS_ENUMERATOR (data->enumerator)) |
||
1672 | { |
||
1673 | g_object_set (G_OBJECT (data->enumerator), |
||
1674 | "proxy-resolver", client->priv->proxy_resolver, |
||
1675 | NULL); |
||
1676 | } |
||
1677 | } |
||
1678 | else |
||
1679 | data->enumerator = g_socket_connectable_enumerate (connectable); |
||
1680 | |||
1681 | data->task = g_task_new (client, cancellable, callback, user_data); |
||
1682 | g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free); |
||
1683 | |||
1684 | enumerator_next_async (data); |
||
1685 | } |
||
1686 | |||
1687 | /** |
||
1688 | * g_socket_client_connect_to_host_async: |
||
1689 | * @client: a #GSocketClient |
||
1690 | * @host_and_port: the name and optionally the port of the host to connect to |
||
1691 | * @default_port: the default port to connect to |
||
1692 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1693 | * @callback: (scope async): a #GAsyncReadyCallback |
||
1694 | * @user_data: (closure): user data for the callback |
||
1695 | * |
||
1696 | * This is the asynchronous version of g_socket_client_connect_to_host(). |
||
1697 | * |
||
1698 | * When the operation is finished @callback will be |
||
1699 | * called. You can then call g_socket_client_connect_to_host_finish() to get |
||
1700 | * the result of the operation. |
||
1701 | * |
||
1702 | * Since: 2.22 |
||
1703 | */ |
||
1704 | void |
||
1705 | g_socket_client_connect_to_host_async (GSocketClient *client, |
||
1706 | const gchar *host_and_port, |
||
1707 | guint16 default_port, |
||
1708 | GCancellable *cancellable, |
||
1709 | GAsyncReadyCallback callback, |
||
1710 | gpointer user_data) |
||
1711 | { |
||
1712 | GSocketConnectable *connectable; |
||
1713 | GError *error; |
||
1714 | |||
1715 | error = NULL; |
||
1716 | connectable = g_network_address_parse (host_and_port, default_port, |
||
1717 | &error); |
||
1718 | if (connectable == NULL) |
||
1719 | { |
||
1720 | g_task_report_error (client, callback, user_data, |
||
1721 | g_socket_client_connect_to_host_async, |
||
1722 | error); |
||
1723 | } |
||
1724 | else |
||
1725 | { |
||
1726 | g_socket_client_connect_async (client, |
||
1727 | connectable, cancellable, |
||
1728 | callback, user_data); |
||
1729 | g_object_unref (connectable); |
||
1730 | } |
||
1731 | } |
||
1732 | |||
1733 | /** |
||
1734 | * g_socket_client_connect_to_service_async: |
||
1735 | * @client: a #GSocketClient |
||
1736 | * @domain: a domain name |
||
1737 | * @service: the name of the service to connect to |
||
1738 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1739 | * @callback: (scope async): a #GAsyncReadyCallback |
||
1740 | * @user_data: (closure): user data for the callback |
||
1741 | * |
||
1742 | * This is the asynchronous version of |
||
1743 | * g_socket_client_connect_to_service(). |
||
1744 | * |
||
1745 | * Since: 2.22 |
||
1746 | */ |
||
1747 | void |
||
1748 | g_socket_client_connect_to_service_async (GSocketClient *client, |
||
1749 | const gchar *domain, |
||
1750 | const gchar *service, |
||
1751 | GCancellable *cancellable, |
||
1752 | GAsyncReadyCallback callback, |
||
1753 | gpointer user_data) |
||
1754 | { |
||
1755 | GSocketConnectable *connectable; |
||
1756 | |||
1757 | connectable = g_network_service_new (service, "tcp", domain); |
||
1758 | g_socket_client_connect_async (client, |
||
1759 | connectable, cancellable, |
||
1760 | callback, user_data); |
||
1761 | g_object_unref (connectable); |
||
1762 | } |
||
1763 | |||
1764 | /** |
||
1765 | * g_socket_client_connect_to_uri_async: |
||
1766 | * @client: a #GSocketClient |
||
1767 | * @uri: a network uri |
||
1768 | * @default_port: the default port to connect to |
||
1769 | * @cancellable: (allow-none): a #GCancellable, or %NULL |
||
1770 | * @callback: (scope async): a #GAsyncReadyCallback |
||
1771 | * @user_data: (closure): user data for the callback |
||
1772 | * |
||
1773 | * This is the asynchronous version of g_socket_client_connect_to_uri(). |
||
1774 | * |
||
1775 | * When the operation is finished @callback will be |
||
1776 | * called. You can then call g_socket_client_connect_to_uri_finish() to get |
||
1777 | * the result of the operation. |
||
1778 | * |
||
1779 | * Since: 2.26 |
||
1780 | */ |
||
1781 | void |
||
1782 | g_socket_client_connect_to_uri_async (GSocketClient *client, |
||
1783 | const gchar *uri, |
||
1784 | guint16 default_port, |
||
1785 | GCancellable *cancellable, |
||
1786 | GAsyncReadyCallback callback, |
||
1787 | gpointer user_data) |
||
1788 | { |
||
1789 | GSocketConnectable *connectable; |
||
1790 | GError *error; |
||
1791 | |||
1792 | error = NULL; |
||
1793 | connectable = g_network_address_parse_uri (uri, default_port, &error); |
||
1794 | if (connectable == NULL) |
||
1795 | { |
||
1796 | g_task_report_error (client, callback, user_data, |
||
1797 | g_socket_client_connect_to_uri_async, |
||
1798 | error); |
||
1799 | } |
||
1800 | else |
||
1801 | { |
||
1802 | g_socket_client_connect_async (client, |
||
1803 | connectable, cancellable, |
||
1804 | callback, user_data); |
||
1805 | g_object_unref (connectable); |
||
1806 | } |
||
1807 | } |
||
1808 | |||
1809 | |||
1810 | /** |
||
1811 | * g_socket_client_connect_finish: |
||
1812 | * @client: a #GSocketClient. |
||
1813 | * @result: a #GAsyncResult. |
||
1814 | * @error: a #GError location to store the error occurring, or %NULL to |
||
1815 | * ignore. |
||
1816 | * |
||
1817 | * Finishes an async connect operation. See g_socket_client_connect_async() |
||
1818 | * |
||
1819 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
1820 | * |
||
1821 | * Since: 2.22 |
||
1822 | */ |
||
1823 | GSocketConnection * |
||
1824 | g_socket_client_connect_finish (GSocketClient *client, |
||
1825 | GAsyncResult *result, |
||
1826 | GError **error) |
||
1827 | { |
||
1828 | g_return_val_if_fail (g_task_is_valid (result, client), NULL); |
||
1829 | |||
1830 | return g_task_propagate_pointer (G_TASK (result), error); |
||
1831 | } |
||
1832 | |||
1833 | /** |
||
1834 | * g_socket_client_connect_to_host_finish: |
||
1835 | * @client: a #GSocketClient. |
||
1836 | * @result: a #GAsyncResult. |
||
1837 | * @error: a #GError location to store the error occurring, or %NULL to |
||
1838 | * ignore. |
||
1839 | * |
||
1840 | * Finishes an async connect operation. See g_socket_client_connect_to_host_async() |
||
1841 | * |
||
1842 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
1843 | * |
||
1844 | * Since: 2.22 |
||
1845 | */ |
||
1846 | GSocketConnection * |
||
1847 | g_socket_client_connect_to_host_finish (GSocketClient *client, |
||
1848 | GAsyncResult *result, |
||
1849 | GError **error) |
||
1850 | { |
||
1851 | return g_socket_client_connect_finish (client, result, error); |
||
1852 | } |
||
1853 | |||
1854 | /** |
||
1855 | * g_socket_client_connect_to_service_finish: |
||
1856 | * @client: a #GSocketClient. |
||
1857 | * @result: a #GAsyncResult. |
||
1858 | * @error: a #GError location to store the error occurring, or %NULL to |
||
1859 | * ignore. |
||
1860 | * |
||
1861 | * Finishes an async connect operation. See g_socket_client_connect_to_service_async() |
||
1862 | * |
||
1863 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
1864 | * |
||
1865 | * Since: 2.22 |
||
1866 | */ |
||
1867 | GSocketConnection * |
||
1868 | g_socket_client_connect_to_service_finish (GSocketClient *client, |
||
1869 | GAsyncResult *result, |
||
1870 | GError **error) |
||
1871 | { |
||
1872 | return g_socket_client_connect_finish (client, result, error); |
||
1873 | } |
||
1874 | |||
1875 | /** |
||
1876 | * g_socket_client_connect_to_uri_finish: |
||
1877 | * @client: a #GSocketClient. |
||
1878 | * @result: a #GAsyncResult. |
||
1879 | * @error: a #GError location to store the error occurring, or %NULL to |
||
1880 | * ignore. |
||
1881 | * |
||
1882 | * Finishes an async connect operation. See g_socket_client_connect_to_uri_async() |
||
1883 | * |
||
1884 | * Returns: (transfer full): a #GSocketConnection on success, %NULL on error. |
||
1885 | * |
||
1886 | * Since: 2.26 |
||
1887 | */ |
||
1888 | GSocketConnection * |
||
1889 | g_socket_client_connect_to_uri_finish (GSocketClient *client, |
||
1890 | GAsyncResult *result, |
||
1891 | GError **error) |
||
1892 | { |
||
1893 | return g_socket_client_connect_finish (client, result, error); |
||
1894 | } |
||
1895 | |||
1896 | /** |
||
1897 | * g_socket_client_add_application_proxy: |
||
1898 | * @client: a #GSocketClient |
||
1899 | * @protocol: The proxy protocol |
||
1900 | * |
||
1901 | * Enable proxy protocols to be handled by the application. When the |
||
1902 | * indicated proxy protocol is returned by the #GProxyResolver, |
||
1903 | * #GSocketClient will consider this protocol as supported but will |
||
1904 | * not try to find a #GProxy instance to handle handshaking. The |
||
1905 | * application must check for this case by calling |
||
1906 | * g_socket_connection_get_remote_address() on the returned |
||
1907 | * #GSocketConnection, and seeing if it's a #GProxyAddress of the |
||
1908 | * appropriate type, to determine whether or not it needs to handle |
||
1909 | * the proxy handshaking itself. |
||
1910 | * |
||
1911 | * This should be used for proxy protocols that are dialects of |
||
1912 | * another protocol such as HTTP proxy. It also allows cohabitation of |
||
1913 | * proxy protocols that are reused between protocols. A good example |
||
1914 | * is HTTP. It can be used to proxy HTTP, FTP and Gopher and can also |
||
1915 | * be use as generic socket proxy through the HTTP CONNECT method. |
||
1916 | * |
||
1917 | * When the proxy is detected as being an application proxy, TLS handshake |
||
1918 | * will be skipped. This is required to let the application do the proxy |
||
1919 | * specific handshake. |
||
1920 | */ |
||
1921 | void |
||
1922 | g_socket_client_add_application_proxy (GSocketClient *client, |
||
1923 | const gchar *protocol) |
||
1924 | { |
||
1925 | g_hash_table_add (client->priv->app_proxies, g_strdup (protocol)); |
||
1926 | } |