1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
5 * Copyright © 2009 Red Hat, Inc
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 of the License, or (at your option) any later version.
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.
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/>.
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>
28 #include "gsocketconnection.h"
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"
41 * SECTION:gsocketconnection
42 * @short_description: A socket connection
44 * @see_also: #GIOStream, #GSocketClient, #GSocketListener
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.
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.
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().
68 struct _GSocketConnectionPrivate
71 GInputStream *input_stream;
72 GOutputStream *output_stream;
74 GSocketAddress *cached_remote_address;
79 static gboolean g_socket_connection_close (GIOStream *stream,
80 GCancellable *cancellable,
82 static void g_socket_connection_close_async (GIOStream *stream,
84 GCancellable *cancellable,
85 GAsyncReadyCallback callback,
87 static gboolean g_socket_connection_close_finish (GIOStream *stream,
91 G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
94 g_socket_connection_get_input_stream (GIOStream *io_stream)
96 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
98 if (connection->priv->input_stream == NULL)
99 connection->priv->input_stream = (GInputStream *)
100 _g_socket_input_stream_new (connection->priv->socket);
102 return connection->priv->input_stream;
105 static GOutputStream *
106 g_socket_connection_get_output_stream (GIOStream *io_stream)
108 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
110 if (connection->priv->output_stream == NULL)
111 connection->priv->output_stream = (GOutputStream *)
112 _g_socket_output_stream_new (connection->priv->socket);
114 return connection->priv->output_stream;
118 * g_socket_connection_is_connected:
119 * @connection: a #GSocketConnection
121 * Checks if @connection is connected. This is equivalent to calling
122 * g_socket_is_connected() on @connection's underlying #GSocket.
124 * Returns: whether @connection is connected
129 g_socket_connection_is_connected (GSocketConnection *connection)
131 return g_socket_is_connected (connection->priv->socket);
135 * g_socket_connection_connect:
136 * @connection: a #GSocketConnection
137 * @address: a #GSocketAddress specifying the remote address.
138 * @cancellable: (allow-none): a %GCancellable or %NULL
139 * @error: #GError for error reporting, or %NULL to ignore.
141 * Connect @connection to the specified remote address.
143 * Returns: %TRUE if the connection succeeded, %FALSE on error
148 g_socket_connection_connect (GSocketConnection *connection,
149 GSocketAddress *address,
150 GCancellable *cancellable,
153 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
154 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
156 return g_socket_connect (connection->priv->socket, address,
160 static gboolean g_socket_connection_connect_callback (GSocket *socket,
161 GIOCondition condition,
165 * g_socket_connection_connect_async:
166 * @connection: a #GSocketConnection
167 * @address: a #GSocketAddress specifying the remote address.
168 * @cancellable: (allow-none): a %GCancellable or %NULL
169 * @callback: (scope async): a #GAsyncReadyCallback
170 * @user_data: (closure): user data for the callback
172 * Asynchronously connect @connection to the specified remote address.
174 * This clears the #GSocket:blocking flag on @connection's underlying
175 * socket if it is currently set.
177 * Use g_socket_connection_connect_finish() to retrieve the result.
182 g_socket_connection_connect_async (GSocketConnection *connection,
183 GSocketAddress *address,
184 GCancellable *cancellable,
185 GAsyncReadyCallback callback,
189 GError *tmp_error = NULL;
191 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
192 g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
194 task = g_task_new (connection, cancellable, callback, user_data);
196 g_socket_set_blocking (connection->priv->socket, FALSE);
198 if (g_socket_connect (connection->priv->socket, address,
199 cancellable, &tmp_error))
201 g_task_return_boolean (task, TRUE);
202 g_object_unref (task);
204 else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
208 g_error_free (tmp_error);
209 source = g_socket_create_source (connection->priv->socket,
210 G_IO_OUT, cancellable);
211 g_task_attach_source (task, source,
212 (GSourceFunc) g_socket_connection_connect_callback);
213 g_source_unref (source);
217 g_task_return_error (task, tmp_error);
218 g_object_unref (task);
223 g_socket_connection_connect_callback (GSocket *socket,
224 GIOCondition condition,
227 GTask *task = user_data;
228 GSocketConnection *connection = g_task_get_source_object (task);
229 GError *error = NULL;
231 if (g_socket_check_connect_result (connection->priv->socket, &error))
232 g_task_return_boolean (task, TRUE);
234 g_task_return_error (task, error);
236 g_object_unref (task);
241 * g_socket_connection_connect_finish:
242 * @connection: a #GSocketConnection
243 * @result: the #GAsyncResult
244 * @error: #GError for error reporting, or %NULL to ignore.
246 * Gets the result of a g_socket_connection_connect_async() call.
248 * Returns: %TRUE if the connection succeeded, %FALSE on error
253 g_socket_connection_connect_finish (GSocketConnection *connection,
254 GAsyncResult *result,
257 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
258 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
260 return g_task_propagate_boolean (G_TASK (result), error);
264 * g_socket_connection_get_socket:
265 * @connection: a #GSocketConnection
267 * Gets the underlying #GSocket object of the connection.
268 * This can be useful if you want to do something unusual on it
269 * not supported by the #GSocketConnection APIs.
271 * Returns: (transfer none): a #GSocketAddress or %NULL on error.
276 g_socket_connection_get_socket (GSocketConnection *connection)
278 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
280 return connection->priv->socket;
284 * g_socket_connection_get_local_address:
285 * @connection: a #GSocketConnection
286 * @error: #GError for error reporting, or %NULL to ignore.
288 * Try to get the local address of a socket connection.
290 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
291 * Free the returned object with g_object_unref().
296 g_socket_connection_get_local_address (GSocketConnection *connection,
299 return g_socket_get_local_address (connection->priv->socket, error);
303 * g_socket_connection_get_remote_address:
304 * @connection: a #GSocketConnection
305 * @error: #GError for error reporting, or %NULL to ignore.
307 * Try to get the remote address of a socket connection.
309 * Since GLib 2.40, when used with g_socket_client_connect() or
310 * g_socket_client_connect_async(), during emission of
311 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
312 * address that will be used for the connection. This allows
313 * applications to print e.g. "Connecting to example.com
316 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
317 * Free the returned object with g_object_unref().
322 g_socket_connection_get_remote_address (GSocketConnection *connection,
325 if (!g_socket_is_connected (connection->priv->socket))
327 return connection->priv->cached_remote_address ?
328 g_object_ref (connection->priv->cached_remote_address) : NULL;
330 return g_socket_get_remote_address (connection->priv->socket, error);
333 /* Private API allowing applications to retrieve the resolved address
334 * now, before we start connecting.
336 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
339 g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
340 GSocketAddress *address)
342 g_clear_object (&connection->priv->cached_remote_address);
343 connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
347 g_socket_connection_get_property (GObject *object,
352 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
357 g_value_set_object (value, connection->priv->socket);
361 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
366 g_socket_connection_set_property (GObject *object,
371 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
376 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
380 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
385 g_socket_connection_constructed (GObject *object)
387 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
389 g_assert (connection->priv->socket != NULL);
393 g_socket_connection_dispose (GObject *object)
395 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
397 connection->priv->in_dispose = TRUE;
399 g_clear_object (&connection->priv->cached_remote_address);
401 G_OBJECT_CLASS (g_socket_connection_parent_class)
404 connection->priv->in_dispose = FALSE;
408 g_socket_connection_finalize (GObject *object)
410 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
412 if (connection->priv->input_stream)
413 g_object_unref (connection->priv->input_stream);
415 if (connection->priv->output_stream)
416 g_object_unref (connection->priv->output_stream);
418 g_object_unref (connection->priv->socket);
420 G_OBJECT_CLASS (g_socket_connection_parent_class)
425 g_socket_connection_class_init (GSocketConnectionClass *klass)
427 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
428 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
430 gobject_class->set_property = g_socket_connection_set_property;
431 gobject_class->get_property = g_socket_connection_get_property;
432 gobject_class->constructed = g_socket_connection_constructed;
433 gobject_class->finalize = g_socket_connection_finalize;
434 gobject_class->dispose = g_socket_connection_dispose;
436 stream_class->get_input_stream = g_socket_connection_get_input_stream;
437 stream_class->get_output_stream = g_socket_connection_get_output_stream;
438 stream_class->close_fn = g_socket_connection_close;
439 stream_class->close_async = g_socket_connection_close_async;
440 stream_class->close_finish = g_socket_connection_close_finish;
442 g_object_class_install_property (gobject_class,
444 g_param_spec_object ("socket",
446 P_("The underlying GSocket"),
448 G_PARAM_CONSTRUCT_ONLY |
450 G_PARAM_STATIC_STRINGS));
454 g_socket_connection_init (GSocketConnection *connection)
456 connection->priv = g_socket_connection_get_instance_private (connection);
460 g_socket_connection_close (GIOStream *stream,
461 GCancellable *cancellable,
464 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
466 if (connection->priv->output_stream)
467 g_output_stream_close (connection->priv->output_stream,
469 if (connection->priv->input_stream)
470 g_input_stream_close (connection->priv->input_stream,
473 /* Don't close the underlying socket if this is being called
474 * as part of dispose(); when destroying the GSocketConnection,
475 * we only want to close the socket if we're holding the last
476 * reference on it, and in that case it will close itself when
477 * we unref it in finalize().
479 if (connection->priv->in_dispose)
482 return g_socket_close (connection->priv->socket, error);
487 g_socket_connection_close_async (GIOStream *stream,
489 GCancellable *cancellable,
490 GAsyncReadyCallback callback,
494 GIOStreamClass *class;
497 class = G_IO_STREAM_GET_CLASS (stream);
499 task = g_task_new (stream, cancellable, callback, user_data);
501 /* socket close is not blocked, just do it! */
503 if (class->close_fn &&
504 !class->close_fn (stream, cancellable, &error))
505 g_task_return_error (task, error);
507 g_task_return_boolean (task, TRUE);
509 g_object_unref (task);
513 g_socket_connection_close_finish (GIOStream *stream,
514 GAsyncResult *result,
517 return g_task_propagate_boolean (G_TASK (result), error);
521 GSocketFamily socket_family;
522 GSocketType socket_type;
524 GType implementation;
528 connection_factory_hash (gconstpointer key)
530 const ConnectionFactory *factory = key;
533 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
534 /* This is likely to be small, so spread over whole
535 hash space to get some distribution */
536 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
542 connection_factory_equal (gconstpointer _a,
545 const ConnectionFactory *a = _a;
546 const ConnectionFactory *b = _b;
548 if (a->socket_family != b->socket_family)
551 if (a->socket_type != b->socket_type)
554 if (a->protocol != b->protocol)
560 static GHashTable *connection_factories = NULL;
561 G_LOCK_DEFINE_STATIC(connection_factories);
564 * g_socket_connection_factory_register_type:
565 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
566 * @family: a #GSocketFamily
567 * @type: a #GSocketType
568 * @protocol: a protocol id
570 * Looks up the #GType to be used when creating socket connections on
571 * sockets with the specified @family, @type and @protocol.
573 * If no type is registered, the #GSocketConnection base type is returned.
578 g_socket_connection_factory_register_type (GType g_type,
579 GSocketFamily family,
583 ConnectionFactory *factory;
585 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
587 G_LOCK (connection_factories);
589 if (connection_factories == NULL)
590 connection_factories = g_hash_table_new_full (connection_factory_hash,
591 connection_factory_equal,
592 (GDestroyNotify)g_free,
595 factory = g_new0 (ConnectionFactory, 1);
596 factory->socket_family = family;
597 factory->socket_type = type;
598 factory->protocol = protocol;
599 factory->implementation = g_type;
601 g_hash_table_insert (connection_factories,
604 G_UNLOCK (connection_factories);
608 init_builtin_types (void)
611 g_type_ensure (G_TYPE_UNIX_CONNECTION);
613 g_type_ensure (G_TYPE_TCP_CONNECTION);
617 * g_socket_connection_factory_lookup_type:
618 * @family: a #GSocketFamily
619 * @type: a #GSocketType
620 * @protocol_id: a protocol id
622 * Looks up the #GType to be used when creating socket connections on
623 * sockets with the specified @family, @type and @protocol_id.
625 * If no type is registered, the #GSocketConnection base type is returned.
632 g_socket_connection_factory_lookup_type (GSocketFamily family,
636 ConnectionFactory *factory, key;
639 init_builtin_types ();
641 G_LOCK (connection_factories);
643 g_type = G_TYPE_SOCKET_CONNECTION;
645 if (connection_factories)
647 key.socket_family = family;
648 key.socket_type = type;
649 key.protocol = protocol_id;
651 factory = g_hash_table_lookup (connection_factories, &key);
653 g_type = factory->implementation;
656 G_UNLOCK (connection_factories);
662 * g_socket_connection_factory_create_connection:
663 * @socket: a #GSocket
665 * Creates a #GSocketConnection subclass of the right type for
668 * Returns: (transfer full): a #GSocketConnection
673 g_socket_connection_factory_create_connection (GSocket *socket)
677 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
678 g_socket_get_socket_type (socket),
679 g_socket_get_protocol (socket));
680 return g_object_new (type, "socket", socket, NULL);