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, write to the
19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
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 <gio/giostream.h>
35 #include <gio/gsimpleasyncresult.h>
36 #include "gunixconnection.h"
37 #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 depends
53 * on the type of the underlying socket that is in use. For instance, for a
54 * TCP/IP connection it will be a #GTcpConnection.
56 * Chosing what type of object to construct is done with the socket connection
57 * factory, and it is possible for 3rd parties to register custom socket connection
58 * types for specific combination of socket family/type/protocol using
59 * g_socket_connection_factory_register_type().
64 G_DEFINE_TYPE (GSocketConnection,
65 g_socket_connection, G_TYPE_IO_STREAM);
73 struct _GSocketConnectionPrivate
76 GInputStream *input_stream;
77 GOutputStream *output_stream;
80 static gboolean g_socket_connection_close (GIOStream *stream,
81 GCancellable *cancellable,
83 static void g_socket_connection_close_async (GIOStream *stream,
85 GCancellable *cancellable,
86 GAsyncReadyCallback callback,
88 static gboolean g_socket_connection_close_finish (GIOStream *stream,
93 g_socket_connection_get_input_stream (GIOStream *io_stream)
95 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
97 if (connection->priv->input_stream == NULL)
98 connection->priv->input_stream = (GInputStream *)
99 _g_socket_input_stream_new (connection->priv->socket);
101 return connection->priv->input_stream;
104 static GOutputStream *
105 g_socket_connection_get_output_stream (GIOStream *io_stream)
107 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
109 if (connection->priv->output_stream == NULL)
110 connection->priv->output_stream = (GOutputStream *)
111 _g_socket_output_stream_new (connection->priv->socket);
113 return connection->priv->output_stream;
117 * g_socket_connection_get_socket:
118 * @connection: a #GSocketConnection.
120 * Gets the underlying #GSocket object of the connection.
121 * This can be useful if you want to do something unusual on it
122 * not supported by the #GSocketConnection APIs.
124 * Returns: a #GSocketAddress or %NULL on error.
129 g_socket_connection_get_socket (GSocketConnection *connection)
131 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
133 return connection->priv->socket;
137 * g_socket_connection_get_local_address:
138 * @connection: a #GSocketConnection.
139 * @error: #GError for error reporting, or %NULL to ignore.
141 * Try to get the local address of a socket connection.
143 * Returns: a #GSocketAddress or %NULL on error.
144 * Free the returned object with g_object_unref().
149 g_socket_connection_get_local_address (GSocketConnection *connection,
152 return g_socket_get_local_address (connection->priv->socket, error);
156 * g_socket_connection_get_remote_address:
157 * @connection: a #GSocketConnection.
158 * @error: #GError for error reporting, or %NULL to ignore.
160 * Try to get the remove address of a socket connection.
162 * Returns: a #GSocketAddress or %NULL on error.
163 * Free the returned object with g_object_unref().
168 g_socket_connection_get_remote_address (GSocketConnection *connection,
171 return g_socket_get_remote_address (connection->priv->socket, error);
175 g_socket_connection_get_property (GObject *object, guint prop_id,
176 GValue *value, GParamSpec *pspec)
178 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
183 g_value_set_object (value, connection->priv->socket);
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
192 g_socket_connection_set_property (GObject *object, guint prop_id,
193 const GValue *value, GParamSpec *pspec)
195 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
200 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
204 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209 g_socket_connection_constructed (GObject *object)
211 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
213 g_assert (connection->priv->socket != NULL);
217 g_socket_connection_finalize (GObject *object)
219 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
221 if (connection->priv->input_stream)
222 g_object_unref (connection->priv->input_stream);
224 if (connection->priv->output_stream)
225 g_object_unref (connection->priv->output_stream);
227 g_object_unref (connection->priv->socket);
229 G_OBJECT_CLASS (g_socket_connection_parent_class)
234 g_socket_connection_class_init (GSocketConnectionClass *klass)
236 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
237 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
239 g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
241 gobject_class->set_property = g_socket_connection_set_property;
242 gobject_class->get_property = g_socket_connection_get_property;
243 gobject_class->constructed = g_socket_connection_constructed;
244 gobject_class->finalize = g_socket_connection_finalize;
246 stream_class->get_input_stream = g_socket_connection_get_input_stream;
247 stream_class->get_output_stream = g_socket_connection_get_output_stream;
248 stream_class->close_fn = g_socket_connection_close;
249 stream_class->close_async = g_socket_connection_close_async;
250 stream_class->close_finish = g_socket_connection_close_finish;
252 g_object_class_install_property (gobject_class, PROP_SOCKET,
253 g_param_spec_object ("socket",
255 P_("The underlying GSocket"),
256 G_TYPE_SOCKET, G_PARAM_CONSTRUCT_ONLY |
257 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
261 g_socket_connection_init (GSocketConnection *connection)
263 connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
264 G_TYPE_SOCKET_CONNECTION,
265 GSocketConnectionPrivate);
269 g_socket_connection_close (GIOStream *stream,
270 GCancellable *cancellable,
273 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
275 if (connection->priv->output_stream)
276 g_output_stream_close (connection->priv->output_stream,
278 if (connection->priv->input_stream)
279 g_input_stream_close (connection->priv->input_stream,
282 return g_socket_close (connection->priv->socket, error);
287 g_socket_connection_close_async (GIOStream *stream,
289 GCancellable *cancellable,
290 GAsyncReadyCallback callback,
293 GSimpleAsyncResult *res;
296 /* socket close is not blocked, just do it! */
298 if (!g_io_stream_close (stream, cancellable, &error))
300 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
303 g_error_free (error);
307 res = g_simple_async_result_new (G_OBJECT (stream),
310 g_socket_connection_close_async);
311 g_simple_async_result_complete_in_idle (res);
312 g_object_unref (res);
316 g_socket_connection_close_finish (GIOStream *stream,
317 GAsyncResult *result,
324 GSocketFamily socket_family;
325 GSocketType socket_type;
327 GType implementation;
331 connection_factory_hash (gconstpointer key)
333 const ConnectionFactory *factory = key;
336 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
337 /* This is likely to be small, so spread over whole
338 hash space to get some distribution */
339 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
345 connection_factory_equal (gconstpointer _a,
348 const ConnectionFactory *a = _a;
349 const ConnectionFactory *b = _b;
351 if (a->socket_family != b->socket_family)
354 if (a->socket_type != b->socket_type)
357 if (a->protocol != b->protocol)
363 static GHashTable *connection_factories = NULL;
364 G_LOCK_DEFINE_STATIC(connection_factories);
367 * g_socket_connection_factory_register_type:
368 * @g_type: a #GType, inheriting from G_SOCKET_CONNECTION
369 * @family: a #GSocketFamily.
370 * @type: a #GSocketType
371 * @protocol: a protocol id
373 * Looks up the #GType to be used when creating socket connections on
374 * sockets with the specified @family,@type and @protocol.
376 * If no type is registered, the #GSocketConnection base type is returned.
381 g_socket_connection_factory_register_type (GType g_type,
382 GSocketFamily family,
386 ConnectionFactory *factory;
388 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
390 G_LOCK (connection_factories);
392 if (connection_factories == NULL)
393 connection_factories = g_hash_table_new_full (connection_factory_hash,
394 connection_factory_equal,
395 (GDestroyNotify)g_free,
398 factory = g_new0 (ConnectionFactory, 1);
399 factory->socket_family = family;
400 factory->socket_type = type;
401 factory->protocol = protocol;
402 factory->implementation = g_type;
404 g_hash_table_insert (connection_factories,
407 G_UNLOCK (connection_factories);
411 init_builtin_types (void)
413 volatile GType a_type;
415 a_type = g_unix_connection_get_type ();
417 a_type = g_tcp_connection_get_type ();
421 * g_socket_connection_factory_lookup_type:
422 * @family: a #GSocketFamily.
423 * @type: a #GSocketType
424 * @protocol_id: a protocol id
426 * Looks up the #GType to be used when creating socket connections on
427 * sockets with the specified @family,@type and @protocol_id.
429 * If no type is registered, the #GSocketConnection base type is returned.
435 g_socket_connection_factory_lookup_type (GSocketFamily family,
439 ConnectionFactory *factory, key;
442 init_builtin_types ();
444 G_LOCK (connection_factories);
446 g_type = G_TYPE_SOCKET_CONNECTION;
448 if (connection_factories)
450 key.socket_family = family;
451 key.socket_type = type;
452 key.protocol = protocol_id;
454 factory = g_hash_table_lookup (connection_factories, &key);
456 g_type = factory->implementation;
459 G_UNLOCK (connection_factories);
465 * g_socket_connection_factory_create_connection:
466 * @socket: a #GSocket.
468 * Creates a #GSocketConnection subclass of the right type for
471 * Returns: a #GSocketConnection
476 g_socket_connection_factory_create_connection (GSocket *socket)
480 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
481 g_socket_get_socket_type (socket),
482 g_socket_get_protocol_id (socket));
483 return g_object_new (type, "socket", socket, NULL);
486 #define __G_SOCKET_CONNECTION_C__
487 #include "gioaliasdef.c"