1/* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
4 * © 2008 codethink
5 * Copyright © 2009 Red Hat, Inc
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * Authors: Christian Kellner <gicmo@gnome.org>
21 * Samuel Cormier-Iijima <sciyoshi@gmail.com>
22 * Ryan Lortie <desrt@desrt.ca>
23 * Alexander Larsson <alexl@redhat.com>
24 */
25
26#include "config.h"
27
28#include "gsocketconnection.h"
29
30#include "gsocketoutputstream.h"
31#include "gsocketinputstream.h"
32#include "gioprivate.h"
33#include <gio/giostream.h>
34#include <gio/gtask.h>
35#include "gunixconnection.h"
36#include "gtcpconnection.h"
37#include "glibintl.h"
38
39
40/**
41 * SECTION:gsocketconnection
42 * @short_description: A socket connection
43 * @include: gio/gio.h
44 * @see_also: #GIOStream, #GSocketClient, #GSocketListener
45 *
46 * #GSocketConnection is a #GIOStream for a connected socket. They
47 * can be created either by #GSocketClient when connecting to a host,
48 * or by #GSocketListener when accepting a new client.
49 *
50 * The type of the #GSocketConnection object returned from these calls
51 * depends on the type of the underlying socket that is in use. For
52 * instance, for a TCP/IP connection it will be a #GTcpConnection.
53 *
54 * Choosing what type of object to construct is done with the socket
55 * connection factory, and it is possible for 3rd parties to register
56 * custom socket connection types for specific combination of socket
57 * family/type/protocol using g_socket_connection_factory_register_type().
58 *
59 * To close a #GSocketConnection, use g_io_stream_close(). Closing both
60 * substreams of the #GIOStream separately will not close the underlying
61 * #GSocket.
62 *
63 * Since: 2.22
64 */
65
66enum
67{
68 PROP_NONE,
69 PROP_SOCKET,
70};
71
72struct _GSocketConnectionPrivate
73{
74 GSocket *socket;
75 GInputStream *input_stream;
76 GOutputStream *output_stream;
77
78 GSocketAddress *cached_remote_address;
79
80 gboolean in_dispose;
81};
82
83static gboolean g_socket_connection_close (GIOStream *stream,
84 GCancellable *cancellable,
85 GError **error);
86static void g_socket_connection_close_async (GIOStream *stream,
87 int io_priority,
88 GCancellable *cancellable,
89 GAsyncReadyCallback callback,
90 gpointer user_data);
91static gboolean g_socket_connection_close_finish (GIOStream *stream,
92 GAsyncResult *result,
93 GError **error);
94
95G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
96
97static GInputStream *
98g_socket_connection_get_input_stream (GIOStream *io_stream)
99{
100 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
101
102 if (connection->priv->input_stream == NULL)
103 connection->priv->input_stream = (GInputStream *)
104 _g_socket_input_stream_new (socket: connection->priv->socket);
105
106 return connection->priv->input_stream;
107}
108
109static GOutputStream *
110g_socket_connection_get_output_stream (GIOStream *io_stream)
111{
112 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
113
114 if (connection->priv->output_stream == NULL)
115 connection->priv->output_stream = (GOutputStream *)
116 _g_socket_output_stream_new (socket: connection->priv->socket);
117
118 return connection->priv->output_stream;
119}
120
121/**
122 * g_socket_connection_is_connected:
123 * @connection: a #GSocketConnection
124 *
125 * Checks if @connection is connected. This is equivalent to calling
126 * g_socket_is_connected() on @connection's underlying #GSocket.
127 *
128 * Returns: whether @connection is connected
129 *
130 * Since: 2.32
131 */
132gboolean
133g_socket_connection_is_connected (GSocketConnection *connection)
134{
135 return g_socket_is_connected (socket: connection->priv->socket);
136}
137
138/**
139 * g_socket_connection_connect:
140 * @connection: a #GSocketConnection
141 * @address: a #GSocketAddress specifying the remote address.
142 * @cancellable: (nullable): a %GCancellable or %NULL
143 * @error: #GError for error reporting, or %NULL to ignore.
144 *
145 * Connect @connection to the specified remote address.
146 *
147 * Returns: %TRUE if the connection succeeded, %FALSE on error
148 *
149 * Since: 2.32
150 */
151gboolean
152g_socket_connection_connect (GSocketConnection *connection,
153 GSocketAddress *address,
154 GCancellable *cancellable,
155 GError **error)
156{
157 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
158 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
159
160 return g_socket_connect (socket: connection->priv->socket, address,
161 cancellable, error);
162}
163
164static gboolean g_socket_connection_connect_callback (GSocket *socket,
165 GIOCondition condition,
166 gpointer user_data);
167
168/**
169 * g_socket_connection_connect_async:
170 * @connection: a #GSocketConnection
171 * @address: a #GSocketAddress specifying the remote address.
172 * @cancellable: (nullable): a %GCancellable or %NULL
173 * @callback: (scope async): a #GAsyncReadyCallback
174 * @user_data: (closure): user data for the callback
175 *
176 * Asynchronously connect @connection to the specified remote address.
177 *
178 * This clears the #GSocket:blocking flag on @connection's underlying
179 * socket if it is currently set.
180 *
181 * Use g_socket_connection_connect_finish() to retrieve the result.
182 *
183 * Since: 2.32
184 */
185void
186g_socket_connection_connect_async (GSocketConnection *connection,
187 GSocketAddress *address,
188 GCancellable *cancellable,
189 GAsyncReadyCallback callback,
190 gpointer user_data)
191{
192 GTask *task;
193 GError *tmp_error = NULL;
194
195 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
196 g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
197
198 task = g_task_new (source_object: connection, cancellable, callback, callback_data: user_data);
199 g_task_set_source_tag (task, g_socket_connection_connect_async);
200
201 g_socket_set_blocking (socket: connection->priv->socket, FALSE);
202
203 if (g_socket_connect (socket: connection->priv->socket, address,
204 cancellable, error: &tmp_error))
205 {
206 g_task_return_boolean (task, TRUE);
207 g_object_unref (object: task);
208 }
209 else if (g_error_matches (error: tmp_error, G_IO_ERROR, code: G_IO_ERROR_PENDING))
210 {
211 GSource *source;
212
213 g_error_free (error: tmp_error);
214 source = g_socket_create_source (socket: connection->priv->socket,
215 condition: G_IO_OUT, cancellable);
216 g_task_attach_source (task, source,
217 callback: (GSourceFunc) g_socket_connection_connect_callback);
218 g_source_unref (source);
219 }
220 else
221 {
222 g_task_return_error (task, error: tmp_error);
223 g_object_unref (object: task);
224 }
225}
226
227static gboolean
228g_socket_connection_connect_callback (GSocket *socket,
229 GIOCondition condition,
230 gpointer user_data)
231{
232 GTask *task = user_data;
233 GSocketConnection *connection = g_task_get_source_object (task);
234 GError *error = NULL;
235
236 if (g_socket_check_connect_result (socket: connection->priv->socket, error: &error))
237 g_task_return_boolean (task, TRUE);
238 else
239 g_task_return_error (task, error);
240
241 g_object_unref (object: task);
242 return FALSE;
243}
244
245/**
246 * g_socket_connection_connect_finish:
247 * @connection: a #GSocketConnection
248 * @result: the #GAsyncResult
249 * @error: #GError for error reporting, or %NULL to ignore.
250 *
251 * Gets the result of a g_socket_connection_connect_async() call.
252 *
253 * Returns: %TRUE if the connection succeeded, %FALSE on error
254 *
255 * Since: 2.32
256 */
257gboolean
258g_socket_connection_connect_finish (GSocketConnection *connection,
259 GAsyncResult *result,
260 GError **error)
261{
262 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
263 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
264
265 return g_task_propagate_boolean (G_TASK (result), error);
266}
267
268/**
269 * g_socket_connection_get_socket:
270 * @connection: a #GSocketConnection
271 *
272 * Gets the underlying #GSocket object of the connection.
273 * This can be useful if you want to do something unusual on it
274 * not supported by the #GSocketConnection APIs.
275 *
276 * Returns: (transfer none): a #GSocket or %NULL on error.
277 *
278 * Since: 2.22
279 */
280GSocket *
281g_socket_connection_get_socket (GSocketConnection *connection)
282{
283 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
284
285 return connection->priv->socket;
286}
287
288/**
289 * g_socket_connection_get_local_address:
290 * @connection: a #GSocketConnection
291 * @error: #GError for error reporting, or %NULL to ignore.
292 *
293 * Try to get the local address of a socket connection.
294 *
295 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
296 * Free the returned object with g_object_unref().
297 *
298 * Since: 2.22
299 */
300GSocketAddress *
301g_socket_connection_get_local_address (GSocketConnection *connection,
302 GError **error)
303{
304 return g_socket_get_local_address (socket: connection->priv->socket, error);
305}
306
307/**
308 * g_socket_connection_get_remote_address:
309 * @connection: a #GSocketConnection
310 * @error: #GError for error reporting, or %NULL to ignore.
311 *
312 * Try to get the remote address of a socket connection.
313 *
314 * Since GLib 2.40, when used with g_socket_client_connect() or
315 * g_socket_client_connect_async(), during emission of
316 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
317 * address that will be used for the connection. This allows
318 * applications to print e.g. "Connecting to example.com
319 * (10.42.77.3)...".
320 *
321 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
322 * Free the returned object with g_object_unref().
323 *
324 * Since: 2.22
325 */
326GSocketAddress *
327g_socket_connection_get_remote_address (GSocketConnection *connection,
328 GError **error)
329{
330 if (!g_socket_is_connected (socket: connection->priv->socket))
331 {
332 return connection->priv->cached_remote_address ?
333 g_object_ref (connection->priv->cached_remote_address) : NULL;
334 }
335 return g_socket_get_remote_address (socket: connection->priv->socket, error);
336}
337
338/* Private API allowing applications to retrieve the resolved address
339 * now, before we start connecting.
340 *
341 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
342 */
343void
344g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
345 GSocketAddress *address)
346{
347 g_clear_object (&connection->priv->cached_remote_address);
348 connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
349}
350
351static void
352g_socket_connection_get_property (GObject *object,
353 guint prop_id,
354 GValue *value,
355 GParamSpec *pspec)
356{
357 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
358
359 switch (prop_id)
360 {
361 case PROP_SOCKET:
362 g_value_set_object (value, v_object: connection->priv->socket);
363 break;
364
365 default:
366 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
367 }
368}
369
370static void
371g_socket_connection_set_property (GObject *object,
372 guint prop_id,
373 const GValue *value,
374 GParamSpec *pspec)
375{
376 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
377
378 switch (prop_id)
379 {
380 case PROP_SOCKET:
381 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
382 break;
383
384 default:
385 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386 }
387}
388
389static void
390g_socket_connection_constructed (GObject *object)
391{
392#ifndef G_DISABLE_ASSERT
393 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
394#endif
395
396 g_assert (connection->priv->socket != NULL);
397}
398
399static void
400g_socket_connection_dispose (GObject *object)
401{
402 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
403
404 connection->priv->in_dispose = TRUE;
405
406 g_clear_object (&connection->priv->cached_remote_address);
407
408 G_OBJECT_CLASS (g_socket_connection_parent_class)
409 ->dispose (object);
410
411 connection->priv->in_dispose = FALSE;
412}
413
414static void
415g_socket_connection_finalize (GObject *object)
416{
417 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
418
419 if (connection->priv->input_stream)
420 g_object_unref (object: connection->priv->input_stream);
421
422 if (connection->priv->output_stream)
423 g_object_unref (object: connection->priv->output_stream);
424
425 g_object_unref (object: connection->priv->socket);
426
427 G_OBJECT_CLASS (g_socket_connection_parent_class)
428 ->finalize (object);
429}
430
431static void
432g_socket_connection_class_init (GSocketConnectionClass *klass)
433{
434 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
435 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
436
437 gobject_class->set_property = g_socket_connection_set_property;
438 gobject_class->get_property = g_socket_connection_get_property;
439 gobject_class->constructed = g_socket_connection_constructed;
440 gobject_class->finalize = g_socket_connection_finalize;
441 gobject_class->dispose = g_socket_connection_dispose;
442
443 stream_class->get_input_stream = g_socket_connection_get_input_stream;
444 stream_class->get_output_stream = g_socket_connection_get_output_stream;
445 stream_class->close_fn = g_socket_connection_close;
446 stream_class->close_async = g_socket_connection_close_async;
447 stream_class->close_finish = g_socket_connection_close_finish;
448
449 g_object_class_install_property (oclass: gobject_class,
450 property_id: PROP_SOCKET,
451 pspec: g_param_spec_object (name: "socket",
452 P_("Socket"),
453 P_("The underlying GSocket"),
454 G_TYPE_SOCKET,
455 flags: G_PARAM_CONSTRUCT_ONLY |
456 G_PARAM_READWRITE |
457 G_PARAM_STATIC_STRINGS));
458}
459
460static void
461g_socket_connection_init (GSocketConnection *connection)
462{
463 connection->priv = g_socket_connection_get_instance_private (self: connection);
464}
465
466static gboolean
467g_socket_connection_close (GIOStream *stream,
468 GCancellable *cancellable,
469 GError **error)
470{
471 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
472
473 if (connection->priv->output_stream)
474 g_output_stream_close (stream: connection->priv->output_stream,
475 cancellable, NULL);
476 if (connection->priv->input_stream)
477 g_input_stream_close (stream: connection->priv->input_stream,
478 cancellable, NULL);
479
480 /* Don't close the underlying socket if this is being called
481 * as part of dispose(); when destroying the GSocketConnection,
482 * we only want to close the socket if we're holding the last
483 * reference on it, and in that case it will close itself when
484 * we unref it in finalize().
485 */
486 if (connection->priv->in_dispose)
487 return TRUE;
488
489 return g_socket_close (socket: connection->priv->socket, error);
490}
491
492
493static void
494g_socket_connection_close_async (GIOStream *stream,
495 int io_priority,
496 GCancellable *cancellable,
497 GAsyncReadyCallback callback,
498 gpointer user_data)
499{
500 GTask *task;
501 GIOStreamClass *class;
502 GError *error;
503
504 class = G_IO_STREAM_GET_CLASS (stream);
505
506 task = g_task_new (source_object: stream, cancellable, callback, callback_data: user_data);
507 g_task_set_source_tag (task, g_socket_connection_close_async);
508
509 /* socket close is not blocked, just do it! */
510 error = NULL;
511 if (class->close_fn &&
512 !class->close_fn (stream, cancellable, &error))
513 g_task_return_error (task, error);
514 else
515 g_task_return_boolean (task, TRUE);
516
517 g_object_unref (object: task);
518}
519
520static gboolean
521g_socket_connection_close_finish (GIOStream *stream,
522 GAsyncResult *result,
523 GError **error)
524{
525 return g_task_propagate_boolean (G_TASK (result), error);
526}
527
528typedef struct {
529 GSocketFamily socket_family;
530 GSocketType socket_type;
531 int protocol;
532 GType implementation;
533} ConnectionFactory;
534
535static guint
536connection_factory_hash (gconstpointer key)
537{
538 const ConnectionFactory *factory = key;
539 guint h;
540
541 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
542 /* This is likely to be small, so spread over whole
543 hash space to get some distribution */
544 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
545
546 return h;
547}
548
549static gboolean
550connection_factory_equal (gconstpointer _a,
551 gconstpointer _b)
552{
553 const ConnectionFactory *a = _a;
554 const ConnectionFactory *b = _b;
555
556 if (a->socket_family != b->socket_family)
557 return FALSE;
558
559 if (a->socket_type != b->socket_type)
560 return FALSE;
561
562 if (a->protocol != b->protocol)
563 return FALSE;
564
565 return TRUE;
566}
567
568static GHashTable *connection_factories = NULL;
569G_LOCK_DEFINE_STATIC(connection_factories);
570
571/**
572 * g_socket_connection_factory_register_type:
573 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
574 * @family: a #GSocketFamily
575 * @type: a #GSocketType
576 * @protocol: a protocol id
577 *
578 * Looks up the #GType to be used when creating socket connections on
579 * sockets with the specified @family, @type and @protocol.
580 *
581 * If no type is registered, the #GSocketConnection base type is returned.
582 *
583 * Since: 2.22
584 */
585void
586g_socket_connection_factory_register_type (GType g_type,
587 GSocketFamily family,
588 GSocketType type,
589 gint protocol)
590{
591 ConnectionFactory *factory;
592
593 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
594
595 G_LOCK (connection_factories);
596
597 if (connection_factories == NULL)
598 connection_factories = g_hash_table_new_full (hash_func: connection_factory_hash,
599 key_equal_func: connection_factory_equal,
600 key_destroy_func: (GDestroyNotify)g_free,
601 NULL);
602
603 factory = g_new0 (ConnectionFactory, 1);
604 factory->socket_family = family;
605 factory->socket_type = type;
606 factory->protocol = protocol;
607 factory->implementation = g_type;
608
609 g_hash_table_insert (hash_table: connection_factories,
610 key: factory, value: factory);
611
612 G_UNLOCK (connection_factories);
613}
614
615static void
616init_builtin_types (void)
617{
618#ifndef G_OS_WIN32
619 g_type_ensure (G_TYPE_UNIX_CONNECTION);
620#endif
621 g_type_ensure (G_TYPE_TCP_CONNECTION);
622}
623
624/**
625 * g_socket_connection_factory_lookup_type:
626 * @family: a #GSocketFamily
627 * @type: a #GSocketType
628 * @protocol_id: a protocol id
629 *
630 * Looks up the #GType to be used when creating socket connections on
631 * sockets with the specified @family, @type and @protocol_id.
632 *
633 * If no type is registered, the #GSocketConnection base type is returned.
634 *
635 * Returns: a #GType
636 *
637 * Since: 2.22
638 */
639GType
640g_socket_connection_factory_lookup_type (GSocketFamily family,
641 GSocketType type,
642 gint protocol_id)
643{
644 ConnectionFactory *factory, key;
645 GType g_type;
646
647 init_builtin_types ();
648
649 G_LOCK (connection_factories);
650
651 g_type = G_TYPE_SOCKET_CONNECTION;
652
653 if (connection_factories)
654 {
655 key.socket_family = family;
656 key.socket_type = type;
657 key.protocol = protocol_id;
658
659 factory = g_hash_table_lookup (hash_table: connection_factories, key: &key);
660 if (factory)
661 g_type = factory->implementation;
662 }
663
664 G_UNLOCK (connection_factories);
665
666 return g_type;
667}
668
669/**
670 * g_socket_connection_factory_create_connection:
671 * @socket: a #GSocket
672 *
673 * Creates a #GSocketConnection subclass of the right type for
674 * @socket.
675 *
676 * Returns: (transfer full): a #GSocketConnection
677 *
678 * Since: 2.22
679 */
680GSocketConnection *
681g_socket_connection_factory_create_connection (GSocket *socket)
682{
683 GType type;
684
685 type = g_socket_connection_factory_lookup_type (family: g_socket_get_family (socket),
686 type: g_socket_get_socket_type (socket),
687 protocol_id: g_socket_get_protocol (socket));
688 return g_object_new (object_type: type, first_property_name: "socket", socket, NULL);
689}
690

source code of gtk/subprojects/glib/gio/gsocketconnection.c