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"
43 * SECTION:gsocketconnection
44 * @short_description: A socket connection
46 * @see_also: #GIOStream, #GSocketClient, #GSocketListener
48 * #GSocketConnection is a #GIOStream for a connected socket. They
49 * can be created either by #GSocketClient when connecting to a host,
50 * or by #GSocketListener when accepting a new client.
52 * The type of the #GSocketConnection object returned from these calls
53 * depends on the type of the underlying socket that is in use. For
54 * instance, for a TCP/IP connection it will be a #GTcpConnection.
56 * Choosing what type of object to construct is done with the socket
57 * connection factory, and it is possible for 3rd parties to register
58 * custom socket connection types for specific combination of socket
59 * family/type/protocol using g_socket_connection_factory_register_type().
61 * To close a #GSocketConnection, use g_io_stream_close(). Closing both
62 * substreams of the #GIOStream separately will not close the underlying
74 struct _GSocketConnectionPrivate
77 GInputStream *input_stream;
78 GOutputStream *output_stream;
80 GSocketAddress *cached_remote_address;
85 static gboolean g_socket_connection_close (GIOStream *stream,
86 GCancellable *cancellable,
88 static void g_socket_connection_close_async (GIOStream *stream,
90 GCancellable *cancellable,
91 GAsyncReadyCallback callback,
93 static gboolean g_socket_connection_close_finish (GIOStream *stream,
97 G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
100 g_socket_connection_get_input_stream (GIOStream *io_stream)
102 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
104 if (connection->priv->input_stream == NULL)
105 connection->priv->input_stream = (GInputStream *)
106 _g_socket_input_stream_new (connection->priv->socket);
108 return connection->priv->input_stream;
111 static GOutputStream *
112 g_socket_connection_get_output_stream (GIOStream *io_stream)
114 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
116 if (connection->priv->output_stream == NULL)
117 connection->priv->output_stream = (GOutputStream *)
118 _g_socket_output_stream_new (connection->priv->socket);
120 return connection->priv->output_stream;
124 * g_socket_connection_is_connected:
125 * @connection: a #GSocketConnection
127 * Checks if @connection is connected. This is equivalent to calling
128 * g_socket_is_connected() on @connection's underlying #GSocket.
130 * Returns: whether @connection is connected
135 g_socket_connection_is_connected (GSocketConnection *connection)
137 return g_socket_is_connected (connection->priv->socket);
141 * g_socket_connection_connect:
142 * @connection: a #GSocketConnection
143 * @address: a #GSocketAddress specifying the remote address.
144 * @cancellable: (nullable): a %GCancellable or %NULL
145 * @error: #GError for error reporting, or %NULL to ignore.
147 * Connect @connection to the specified remote address.
149 * Returns: %TRUE if the connection succeeded, %FALSE on error
154 g_socket_connection_connect (GSocketConnection *connection,
155 GSocketAddress *address,
156 GCancellable *cancellable,
159 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
160 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
162 return g_socket_connect (connection->priv->socket, address,
166 static gboolean g_socket_connection_connect_callback (GSocket *socket,
167 GIOCondition condition,
171 * g_socket_connection_connect_async:
172 * @connection: a #GSocketConnection
173 * @address: a #GSocketAddress specifying the remote address.
174 * @cancellable: (nullable): a %GCancellable or %NULL
175 * @callback: (scope async): a #GAsyncReadyCallback
176 * @user_data: user data for the callback
178 * Asynchronously connect @connection to the specified remote address.
180 * This clears the #GSocket:blocking flag on @connection's underlying
181 * socket if it is currently set.
183 * Use g_socket_connection_connect_finish() to retrieve the result.
188 g_socket_connection_connect_async (GSocketConnection *connection,
189 GSocketAddress *address,
190 GCancellable *cancellable,
191 GAsyncReadyCallback callback,
195 GError *tmp_error = NULL;
197 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
198 g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
200 task = g_task_new (connection, cancellable, callback, user_data);
201 g_task_set_source_tag (task, g_socket_connection_connect_async);
203 g_socket_set_blocking (connection->priv->socket, FALSE);
205 if (g_socket_connect (connection->priv->socket, address,
206 cancellable, &tmp_error))
208 g_task_return_boolean (task, TRUE);
209 g_object_unref (task);
211 else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
215 g_error_free (tmp_error);
216 source = g_socket_create_source (connection->priv->socket,
217 G_IO_OUT, cancellable);
218 g_task_attach_source (task, source,
219 (GSourceFunc) g_socket_connection_connect_callback);
220 g_source_unref (source);
224 g_task_return_error (task, tmp_error);
225 g_object_unref (task);
230 g_socket_connection_connect_callback (GSocket *socket,
231 GIOCondition condition,
234 GTask *task = user_data;
235 GSocketConnection *connection = g_task_get_source_object (task);
236 GError *error = NULL;
238 if (g_socket_check_connect_result (connection->priv->socket, &error))
239 g_task_return_boolean (task, TRUE);
241 g_task_return_error (task, error);
243 g_object_unref (task);
248 * g_socket_connection_connect_finish:
249 * @connection: a #GSocketConnection
250 * @result: the #GAsyncResult
251 * @error: #GError for error reporting, or %NULL to ignore.
253 * Gets the result of a g_socket_connection_connect_async() call.
255 * Returns: %TRUE if the connection succeeded, %FALSE on error
260 g_socket_connection_connect_finish (GSocketConnection *connection,
261 GAsyncResult *result,
264 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
265 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
267 return g_task_propagate_boolean (G_TASK (result), error);
271 * g_socket_connection_get_socket:
272 * @connection: a #GSocketConnection
274 * Gets the underlying #GSocket object of the connection.
275 * This can be useful if you want to do something unusual on it
276 * not supported by the #GSocketConnection APIs.
278 * Returns: (transfer none): a #GSocket or %NULL on error.
283 g_socket_connection_get_socket (GSocketConnection *connection)
285 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
287 return connection->priv->socket;
291 * g_socket_connection_get_local_address:
292 * @connection: a #GSocketConnection
293 * @error: #GError for error reporting, or %NULL to ignore.
295 * Try to get the local address of a socket connection.
297 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
298 * Free the returned object with g_object_unref().
303 g_socket_connection_get_local_address (GSocketConnection *connection,
306 return g_socket_get_local_address (connection->priv->socket, error);
310 * g_socket_connection_get_remote_address:
311 * @connection: a #GSocketConnection
312 * @error: #GError for error reporting, or %NULL to ignore.
314 * Try to get the remote address of a socket connection.
316 * Since GLib 2.40, when used with g_socket_client_connect() or
317 * g_socket_client_connect_async(), during emission of
318 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
319 * address that will be used for the connection. This allows
320 * applications to print e.g. "Connecting to example.com
323 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
324 * Free the returned object with g_object_unref().
329 g_socket_connection_get_remote_address (GSocketConnection *connection,
332 if (!g_socket_is_connected (connection->priv->socket))
334 return connection->priv->cached_remote_address ?
335 g_object_ref (connection->priv->cached_remote_address) : NULL;
337 return g_socket_get_remote_address (connection->priv->socket, error);
340 /* Private API allowing applications to retrieve the resolved address
341 * now, before we start connecting.
343 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
346 g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
347 GSocketAddress *address)
349 g_clear_object (&connection->priv->cached_remote_address);
350 connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
354 g_socket_connection_get_property (GObject *object,
359 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
364 g_value_set_object (value, connection->priv->socket);
368 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
373 g_socket_connection_set_property (GObject *object,
378 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
383 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
387 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
392 g_socket_connection_constructed (GObject *object)
394 #ifndef G_DISABLE_ASSERT
395 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
398 g_assert (connection->priv->socket != NULL);
402 g_socket_connection_dispose (GObject *object)
404 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
406 connection->priv->in_dispose = TRUE;
408 g_clear_object (&connection->priv->cached_remote_address);
410 G_OBJECT_CLASS (g_socket_connection_parent_class)
413 connection->priv->in_dispose = FALSE;
417 g_socket_connection_finalize (GObject *object)
419 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
421 if (connection->priv->input_stream)
422 g_object_unref (connection->priv->input_stream);
424 if (connection->priv->output_stream)
425 g_object_unref (connection->priv->output_stream);
427 g_object_unref (connection->priv->socket);
429 G_OBJECT_CLASS (g_socket_connection_parent_class)
434 g_socket_connection_class_init (GSocketConnectionClass *klass)
436 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
437 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
439 gobject_class->set_property = g_socket_connection_set_property;
440 gobject_class->get_property = g_socket_connection_get_property;
441 gobject_class->constructed = g_socket_connection_constructed;
442 gobject_class->finalize = g_socket_connection_finalize;
443 gobject_class->dispose = g_socket_connection_dispose;
445 stream_class->get_input_stream = g_socket_connection_get_input_stream;
446 stream_class->get_output_stream = g_socket_connection_get_output_stream;
447 stream_class->close_fn = g_socket_connection_close;
448 stream_class->close_async = g_socket_connection_close_async;
449 stream_class->close_finish = g_socket_connection_close_finish;
451 g_object_class_install_property (gobject_class,
453 g_param_spec_object ("socket",
455 P_("The underlying GSocket"),
457 G_PARAM_CONSTRUCT_ONLY |
459 G_PARAM_STATIC_STRINGS));
463 g_socket_connection_init (GSocketConnection *connection)
465 connection->priv = g_socket_connection_get_instance_private (connection);
469 g_socket_connection_close (GIOStream *stream,
470 GCancellable *cancellable,
473 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
475 if (connection->priv->output_stream)
476 g_output_stream_close (connection->priv->output_stream,
478 if (connection->priv->input_stream)
479 g_input_stream_close (connection->priv->input_stream,
482 /* Don't close the underlying socket if this is being called
483 * as part of dispose(); when destroying the GSocketConnection,
484 * we only want to close the socket if we're holding the last
485 * reference on it, and in that case it will close itself when
486 * we unref it in finalize().
488 if (connection->priv->in_dispose)
491 return g_socket_close (connection->priv->socket, error);
496 g_socket_connection_close_async (GIOStream *stream,
498 GCancellable *cancellable,
499 GAsyncReadyCallback callback,
503 GIOStreamClass *class;
506 class = G_IO_STREAM_GET_CLASS (stream);
508 task = g_task_new (stream, cancellable, callback, user_data);
509 g_task_set_source_tag (task, g_socket_connection_close_async);
511 /* socket close is not blocked, just do it! */
513 if (class->close_fn &&
514 !class->close_fn (stream, cancellable, &error))
515 g_task_return_error (task, error);
517 g_task_return_boolean (task, TRUE);
519 g_object_unref (task);
523 g_socket_connection_close_finish (GIOStream *stream,
524 GAsyncResult *result,
527 return g_task_propagate_boolean (G_TASK (result), error);
531 GSocketFamily socket_family;
532 GSocketType socket_type;
534 GType implementation;
538 connection_factory_hash (gconstpointer key)
540 const ConnectionFactory *factory = key;
543 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
544 /* This is likely to be small, so spread over whole
545 hash space to get some distribution */
546 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
552 connection_factory_equal (gconstpointer _a,
555 const ConnectionFactory *a = _a;
556 const ConnectionFactory *b = _b;
558 if (a->socket_family != b->socket_family)
561 if (a->socket_type != b->socket_type)
564 if (a->protocol != b->protocol)
570 static GHashTable *connection_factories = NULL;
571 G_LOCK_DEFINE_STATIC(connection_factories);
574 * g_socket_connection_factory_register_type:
575 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
576 * @family: a #GSocketFamily
577 * @type: a #GSocketType
578 * @protocol: a protocol id
580 * Looks up the #GType to be used when creating socket connections on
581 * sockets with the specified @family, @type and @protocol.
583 * If no type is registered, the #GSocketConnection base type is returned.
588 g_socket_connection_factory_register_type (GType g_type,
589 GSocketFamily family,
593 ConnectionFactory *factory;
595 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
597 G_LOCK (connection_factories);
599 if (connection_factories == NULL)
600 connection_factories = g_hash_table_new_full (connection_factory_hash,
601 connection_factory_equal,
602 (GDestroyNotify)g_free,
605 factory = g_new0 (ConnectionFactory, 1);
606 factory->socket_family = family;
607 factory->socket_type = type;
608 factory->protocol = protocol;
609 factory->implementation = g_type;
611 g_hash_table_insert (connection_factories,
614 G_UNLOCK (connection_factories);
618 init_builtin_types (void)
620 g_type_ensure (G_TYPE_UNIX_CONNECTION);
621 g_type_ensure (G_TYPE_TCP_CONNECTION);
625 * g_socket_connection_factory_lookup_type:
626 * @family: a #GSocketFamily
627 * @type: a #GSocketType
628 * @protocol_id: a protocol id
630 * Looks up the #GType to be used when creating socket connections on
631 * sockets with the specified @family, @type and @protocol_id.
633 * If no type is registered, the #GSocketConnection base type is returned.
640 g_socket_connection_factory_lookup_type (GSocketFamily family,
644 ConnectionFactory *factory, key;
647 init_builtin_types ();
649 G_LOCK (connection_factories);
651 g_type = G_TYPE_SOCKET_CONNECTION;
653 if (connection_factories)
655 key.socket_family = family;
656 key.socket_type = type;
657 key.protocol = protocol_id;
659 factory = g_hash_table_lookup (connection_factories, &key);
661 g_type = factory->implementation;
664 G_UNLOCK (connection_factories);
670 * g_socket_connection_factory_create_connection:
671 * @socket: a #GSocket
673 * Creates a #GSocketConnection subclass of the right type for
676 * Returns: (transfer full): a #GSocketConnection
681 g_socket_connection_factory_create_connection (GSocket *socket)
685 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
686 g_socket_get_socket_type (socket),
687 g_socket_get_protocol (socket));
688 return g_object_new (type, "socket", socket, NULL);