1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
5 * Copyright © 2009 Red Hat, Inc
7 * SPDX-License-Identifier: LGPL-2.1-or-later
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General
20 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 * Authors: Christian Kellner <gicmo@gnome.org>
23 * Samuel Cormier-Iijima <sciyoshi@gmail.com>
24 * Ryan Lortie <desrt@desrt.ca>
25 * Alexander Larsson <alexl@redhat.com>
30 #include "gsocketconnection.h"
32 #include "gsocketoutputstream.h"
33 #include "gsocketinputstream.h"
34 #include "gioprivate.h"
35 #include <gio/giostream.h>
36 #include <gio/gtask.h>
37 #include "gunixconnection.h"
38 #include "gtcpconnection.h"
45 * `GSocketConnection` is a [class@Gio.IOStream] for a connected socket. They
46 * can be created either by [class@Gio.SocketClient] when connecting to a host,
47 * or by [class@Gio.SocketListener] when accepting a new client.
49 * The type of the `GSocketConnection` object returned from these calls
50 * depends on the type of the underlying socket that is in use. For
51 * instance, for a TCP/IP connection it will be a [class@Gio.TcpConnection].
53 * Choosing what type of object to construct is done with the socket
54 * connection factory, and it is possible for third parties to register
55 * custom socket connection types for specific combination of socket
56 * family/type/protocol using [func@Gio.SocketConnection.factory_register_type].
58 * To close a `GSocketConnection`, use [method@Gio.IOStream.close]. Closing both
59 * substreams of the [class@Gio.IOStream] separately will not close the
60 * underlying [class@Gio.Socket].
71 struct _GSocketConnectionPrivate
74 GInputStream *input_stream;
75 GOutputStream *output_stream;
77 GSocketAddress *cached_remote_address;
82 static gboolean g_socket_connection_close (GIOStream *stream,
83 GCancellable *cancellable,
85 static void g_socket_connection_close_async (GIOStream *stream,
87 GCancellable *cancellable,
88 GAsyncReadyCallback callback,
90 static gboolean g_socket_connection_close_finish (GIOStream *stream,
94 G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
97 g_socket_connection_get_input_stream (GIOStream *io_stream)
99 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
101 if (connection->priv->input_stream == NULL)
102 connection->priv->input_stream = (GInputStream *)
103 _g_socket_input_stream_new (connection->priv->socket);
105 return connection->priv->input_stream;
108 static GOutputStream *
109 g_socket_connection_get_output_stream (GIOStream *io_stream)
111 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
113 if (connection->priv->output_stream == NULL)
114 connection->priv->output_stream = (GOutputStream *)
115 _g_socket_output_stream_new (connection->priv->socket);
117 return connection->priv->output_stream;
121 * g_socket_connection_is_connected:
122 * @connection: a #GSocketConnection
124 * Checks if @connection is connected. This is equivalent to calling
125 * g_socket_is_connected() on @connection's underlying #GSocket.
127 * Returns: whether @connection is connected
132 g_socket_connection_is_connected (GSocketConnection *connection)
134 return g_socket_is_connected (connection->priv->socket);
138 * g_socket_connection_connect:
139 * @connection: a #GSocketConnection
140 * @address: a #GSocketAddress specifying the remote address.
141 * @cancellable: (nullable): a %GCancellable or %NULL
142 * @error: #GError for error reporting, or %NULL to ignore.
144 * Connect @connection to the specified remote address.
146 * Returns: %TRUE if the connection succeeded, %FALSE on error
151 g_socket_connection_connect (GSocketConnection *connection,
152 GSocketAddress *address,
153 GCancellable *cancellable,
156 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
157 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
159 return g_socket_connect (connection->priv->socket, address,
163 static gboolean g_socket_connection_connect_callback (GSocket *socket,
164 GIOCondition condition,
168 * g_socket_connection_connect_async:
169 * @connection: a #GSocketConnection
170 * @address: a #GSocketAddress specifying the remote address.
171 * @cancellable: (nullable): a %GCancellable or %NULL
172 * @callback: (scope async): a #GAsyncReadyCallback
173 * @user_data: user data for the callback
175 * Asynchronously connect @connection to the specified remote address.
177 * This clears the #GSocket:blocking flag on @connection's underlying
178 * socket if it is currently set.
180 * If #GSocket:timeout is set, the operation will time out and return
181 * %G_IO_ERROR_TIMED_OUT after that period. Otherwise, it will continue
182 * indefinitely until operating system timeouts (if any) are hit.
184 * Use g_socket_connection_connect_finish() to retrieve the result.
189 g_socket_connection_connect_async (GSocketConnection *connection,
190 GSocketAddress *address,
191 GCancellable *cancellable,
192 GAsyncReadyCallback callback,
196 GError *tmp_error = NULL;
198 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
199 g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
201 task = g_task_new (connection, cancellable, callback, user_data);
202 g_task_set_source_tag (task, g_socket_connection_connect_async);
204 g_socket_set_blocking (connection->priv->socket, FALSE);
206 if (g_socket_connect (connection->priv->socket, address,
207 cancellable, &tmp_error))
209 g_task_return_boolean (task, TRUE);
210 g_object_unref (task);
212 else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
216 g_error_free (tmp_error);
217 source = g_socket_create_source (connection->priv->socket,
218 G_IO_OUT, cancellable);
219 g_task_attach_source (task, source,
220 (GSourceFunc) g_socket_connection_connect_callback);
221 g_source_unref (source);
225 g_task_return_error (task, tmp_error);
226 g_object_unref (task);
231 g_socket_connection_connect_callback (GSocket *socket,
232 GIOCondition condition,
235 GTask *task = user_data;
236 GSocketConnection *connection = g_task_get_source_object (task);
237 GError *error = NULL;
239 if (g_socket_check_connect_result (connection->priv->socket, &error))
240 g_task_return_boolean (task, TRUE);
242 g_task_return_error (task, error);
244 g_object_unref (task);
249 * g_socket_connection_connect_finish:
250 * @connection: a #GSocketConnection
251 * @result: the #GAsyncResult
252 * @error: #GError for error reporting, or %NULL to ignore.
254 * Gets the result of a g_socket_connection_connect_async() call.
256 * Returns: %TRUE if the connection succeeded, %FALSE on error
261 g_socket_connection_connect_finish (GSocketConnection *connection,
262 GAsyncResult *result,
265 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
266 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
268 return g_task_propagate_boolean (G_TASK (result), error);
272 * g_socket_connection_get_socket:
273 * @connection: a #GSocketConnection
275 * Gets the underlying #GSocket object of the connection.
276 * This can be useful if you want to do something unusual on it
277 * not supported by the #GSocketConnection APIs.
279 * Returns: (transfer none): a #GSocket or %NULL on error.
284 g_socket_connection_get_socket (GSocketConnection *connection)
286 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
288 return connection->priv->socket;
292 * g_socket_connection_get_local_address:
293 * @connection: a #GSocketConnection
294 * @error: #GError for error reporting, or %NULL to ignore.
296 * Try to get the local address of a socket connection.
298 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
299 * Free the returned object with g_object_unref().
304 g_socket_connection_get_local_address (GSocketConnection *connection,
307 return g_socket_get_local_address (connection->priv->socket, error);
311 * g_socket_connection_get_remote_address:
312 * @connection: a #GSocketConnection
313 * @error: #GError for error reporting, or %NULL to ignore.
315 * Try to get the remote address of a socket connection.
317 * Since GLib 2.40, when used with g_socket_client_connect() or
318 * g_socket_client_connect_async(), during emission of
319 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
320 * address that will be used for the connection. This allows
321 * applications to print e.g. "Connecting to example.com
324 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
325 * Free the returned object with g_object_unref().
330 g_socket_connection_get_remote_address (GSocketConnection *connection,
333 if (!g_socket_is_connected (connection->priv->socket))
335 return connection->priv->cached_remote_address ?
336 g_object_ref (connection->priv->cached_remote_address) : NULL;
338 return g_socket_get_remote_address (connection->priv->socket, error);
341 /* Private API allowing applications to retrieve the resolved address
342 * now, before we start connecting.
344 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
347 g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
348 GSocketAddress *address)
350 g_clear_object (&connection->priv->cached_remote_address);
351 connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
355 g_socket_connection_get_property (GObject *object,
360 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
365 g_value_set_object (value, connection->priv->socket);
369 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
374 g_socket_connection_set_property (GObject *object,
379 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
384 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
388 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
393 g_socket_connection_constructed (GObject *object)
395 #ifndef G_DISABLE_ASSERT
396 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
399 g_assert (connection->priv->socket != NULL);
403 g_socket_connection_dispose (GObject *object)
405 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
407 connection->priv->in_dispose = TRUE;
409 g_clear_object (&connection->priv->cached_remote_address);
411 G_OBJECT_CLASS (g_socket_connection_parent_class)
414 connection->priv->in_dispose = FALSE;
418 g_socket_connection_finalize (GObject *object)
420 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
422 if (connection->priv->input_stream)
423 g_object_unref (connection->priv->input_stream);
425 if (connection->priv->output_stream)
426 g_object_unref (connection->priv->output_stream);
428 g_object_unref (connection->priv->socket);
430 G_OBJECT_CLASS (g_socket_connection_parent_class)
435 g_socket_connection_class_init (GSocketConnectionClass *klass)
437 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
438 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
440 gobject_class->set_property = g_socket_connection_set_property;
441 gobject_class->get_property = g_socket_connection_get_property;
442 gobject_class->constructed = g_socket_connection_constructed;
443 gobject_class->finalize = g_socket_connection_finalize;
444 gobject_class->dispose = g_socket_connection_dispose;
446 stream_class->get_input_stream = g_socket_connection_get_input_stream;
447 stream_class->get_output_stream = g_socket_connection_get_output_stream;
448 stream_class->close_fn = g_socket_connection_close;
449 stream_class->close_async = g_socket_connection_close_async;
450 stream_class->close_finish = g_socket_connection_close_finish;
453 * GSocketConnection:socket:
455 * The underlying [class@Gio.Socket].
459 g_object_class_install_property (gobject_class,
461 g_param_spec_object ("socket", NULL, NULL,
463 G_PARAM_CONSTRUCT_ONLY |
465 G_PARAM_STATIC_STRINGS));
469 g_socket_connection_init (GSocketConnection *connection)
471 connection->priv = g_socket_connection_get_instance_private (connection);
475 g_socket_connection_close (GIOStream *stream,
476 GCancellable *cancellable,
479 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
481 if (connection->priv->output_stream)
482 g_output_stream_close (connection->priv->output_stream,
484 if (connection->priv->input_stream)
485 g_input_stream_close (connection->priv->input_stream,
488 /* Don't close the underlying socket if this is being called
489 * as part of dispose(); when destroying the GSocketConnection,
490 * we only want to close the socket if we're holding the last
491 * reference on it, and in that case it will close itself when
492 * we unref it in finalize().
494 if (connection->priv->in_dispose)
497 return g_socket_close (connection->priv->socket, error);
502 g_socket_connection_close_async (GIOStream *stream,
504 GCancellable *cancellable,
505 GAsyncReadyCallback callback,
509 GIOStreamClass *class;
512 class = G_IO_STREAM_GET_CLASS (stream);
514 task = g_task_new (stream, cancellable, callback, user_data);
515 g_task_set_source_tag (task, g_socket_connection_close_async);
517 /* socket close is not blocked, just do it! */
519 if (class->close_fn &&
520 !class->close_fn (stream, cancellable, &error))
521 g_task_return_error (task, error);
523 g_task_return_boolean (task, TRUE);
525 g_object_unref (task);
529 g_socket_connection_close_finish (GIOStream *stream,
530 GAsyncResult *result,
533 return g_task_propagate_boolean (G_TASK (result), error);
537 GSocketFamily socket_family;
538 GSocketType socket_type;
540 GType implementation;
544 connection_factory_hash (gconstpointer key)
546 const ConnectionFactory *factory = key;
549 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
550 /* This is likely to be small, so spread over whole
551 hash space to get some distribution */
552 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
558 connection_factory_equal (gconstpointer _a,
561 const ConnectionFactory *a = _a;
562 const ConnectionFactory *b = _b;
564 if (a->socket_family != b->socket_family)
567 if (a->socket_type != b->socket_type)
570 if (a->protocol != b->protocol)
576 static GHashTable *connection_factories = NULL;
577 G_LOCK_DEFINE_STATIC(connection_factories);
580 * g_socket_connection_factory_register_type:
581 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
582 * @family: a #GSocketFamily
583 * @type: a #GSocketType
584 * @protocol: a protocol id
586 * Looks up the #GType to be used when creating socket connections on
587 * sockets with the specified @family, @type and @protocol.
589 * If no type is registered, the #GSocketConnection base type is returned.
594 g_socket_connection_factory_register_type (GType g_type,
595 GSocketFamily family,
599 ConnectionFactory *factory;
601 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
603 G_LOCK (connection_factories);
605 if (connection_factories == NULL)
606 connection_factories = g_hash_table_new_full (connection_factory_hash,
607 connection_factory_equal,
608 (GDestroyNotify)g_free,
611 factory = g_new0 (ConnectionFactory, 1);
612 factory->socket_family = family;
613 factory->socket_type = type;
614 factory->protocol = protocol;
615 factory->implementation = g_type;
617 g_hash_table_insert (connection_factories,
620 G_UNLOCK (connection_factories);
624 init_builtin_types (void)
626 g_type_ensure (G_TYPE_UNIX_CONNECTION);
627 g_type_ensure (G_TYPE_TCP_CONNECTION);
631 * g_socket_connection_factory_lookup_type:
632 * @family: a #GSocketFamily
633 * @type: a #GSocketType
634 * @protocol_id: a protocol id
636 * Looks up the #GType to be used when creating socket connections on
637 * sockets with the specified @family, @type and @protocol_id.
639 * If no type is registered, the #GSocketConnection base type is returned.
646 g_socket_connection_factory_lookup_type (GSocketFamily family,
650 ConnectionFactory *factory, key;
653 init_builtin_types ();
655 G_LOCK (connection_factories);
657 g_type = G_TYPE_SOCKET_CONNECTION;
659 if (connection_factories)
661 key.socket_family = family;
662 key.socket_type = type;
663 key.protocol = protocol_id;
665 factory = g_hash_table_lookup (connection_factories, &key);
667 g_type = factory->implementation;
670 G_UNLOCK (connection_factories);
676 * g_socket_connection_factory_create_connection:
677 * @socket: a #GSocket
679 * Creates a #GSocketConnection subclass of the right type for
682 * Returns: (transfer full): a #GSocketConnection
687 g_socket_connection_factory_create_connection (GSocket *socket)
691 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
692 g_socket_get_socket_type (socket),
693 g_socket_get_protocol (socket));
694 return g_object_new (type, "socket", socket, NULL);