Add some more test about gdbus_error apis
[glib.git] / gio / gsocketconnection.c
blobc68465d950de63b7e932de22930eb4078ca413e4
1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
4 * © 2008 codethink
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>
28 #include "config.h"
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"
38 #include "glibintl.h"
41 /**
42 * SECTION:gsocketconnection
43 * @short_description: A socket connection
44 * @include: gio/gio.h
45 * @see_also: #GIOStream, #GSocketClient, #GSocketListener
47 * #GSocketConnection is a #GIOStream for a connected socket. They
48 * can be created either by #GSocketClient when connecting to a host,
49 * or by #GSocketListener when accepting a new client.
51 * The type of the #GSocketConnection object returned from these calls
52 * depends on the type of the underlying socket that is in use. For
53 * instance, for a TCP/IP connection it will be a #GTcpConnection.
55 * Chosing what type of object to construct is done with the socket
56 * connection factory, and it is possible for 3rd parties to register
57 * custom socket connection types for specific combination of socket
58 * family/type/protocol using g_socket_connection_factory_register_type().
60 * Since: 2.22
63 G_DEFINE_TYPE (GSocketConnection,
64 g_socket_connection, G_TYPE_IO_STREAM);
66 enum
68 PROP_NONE,
69 PROP_SOCKET,
72 struct _GSocketConnectionPrivate
74 GSocket *socket;
75 GInputStream *input_stream;
76 GOutputStream *output_stream;
78 gboolean in_dispose;
81 static gboolean g_socket_connection_close (GIOStream *stream,
82 GCancellable *cancellable,
83 GError **error);
84 static void g_socket_connection_close_async (GIOStream *stream,
85 int io_priority,
86 GCancellable *cancellable,
87 GAsyncReadyCallback callback,
88 gpointer user_data);
89 static gboolean g_socket_connection_close_finish (GIOStream *stream,
90 GAsyncResult *result,
91 GError **error);
93 static GInputStream *
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_get_socket:
119 * @connection: a #GSocketConnection
121 * Gets the underlying #GSocket object of the connection.
122 * This can be useful if you want to do something unusual on it
123 * not supported by the #GSocketConnection APIs.
125 * Returns: (transfer none): a #GSocketAddress or %NULL on error.
127 * Since: 2.22
129 GSocket *
130 g_socket_connection_get_socket (GSocketConnection *connection)
132 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
134 return connection->priv->socket;
138 * g_socket_connection_get_local_address:
139 * @connection: a #GSocketConnection
140 * @error: #GError for error reporting, or %NULL to ignore.
142 * Try to get the local address of a socket connection.
144 * Returns: a #GSocketAddress or %NULL on error.
145 * Free the returned object with g_object_unref().
147 * Since: 2.22
149 GSocketAddress *
150 g_socket_connection_get_local_address (GSocketConnection *connection,
151 GError **error)
153 return g_socket_get_local_address (connection->priv->socket, error);
157 * g_socket_connection_get_remote_address:
158 * @connection: a #GSocketConnection
159 * @error: #GError for error reporting, or %NULL to ignore.
161 * Try to get the remote address of a socket connection.
163 * Returns: a #GSocketAddress or %NULL on error.
164 * Free the returned object with g_object_unref().
166 * Since: 2.22
168 GSocketAddress *
169 g_socket_connection_get_remote_address (GSocketConnection *connection,
170 GError **error)
172 return g_socket_get_remote_address (connection->priv->socket, error);
175 static void
176 g_socket_connection_get_property (GObject *object,
177 guint prop_id,
178 GValue *value,
179 GParamSpec *pspec)
181 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
183 switch (prop_id)
185 case PROP_SOCKET:
186 g_value_set_object (value, connection->priv->socket);
187 break;
189 default:
190 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
194 static void
195 g_socket_connection_set_property (GObject *object,
196 guint prop_id,
197 const GValue *value,
198 GParamSpec *pspec)
200 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
202 switch (prop_id)
204 case PROP_SOCKET:
205 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
206 break;
208 default:
209 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
213 static void
214 g_socket_connection_constructed (GObject *object)
216 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
218 g_assert (connection->priv->socket != NULL);
221 static void
222 g_socket_connection_dispose (GObject *object)
224 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
226 connection->priv->in_dispose = TRUE;
228 G_OBJECT_CLASS (g_socket_connection_parent_class)
229 ->dispose (object);
231 connection->priv->in_dispose = FALSE;
234 static void
235 g_socket_connection_finalize (GObject *object)
237 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
239 if (connection->priv->input_stream)
240 g_object_unref (connection->priv->input_stream);
242 if (connection->priv->output_stream)
243 g_object_unref (connection->priv->output_stream);
245 g_object_unref (connection->priv->socket);
247 G_OBJECT_CLASS (g_socket_connection_parent_class)
248 ->finalize (object);
251 static void
252 g_socket_connection_class_init (GSocketConnectionClass *klass)
254 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
255 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
257 g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
259 gobject_class->set_property = g_socket_connection_set_property;
260 gobject_class->get_property = g_socket_connection_get_property;
261 gobject_class->constructed = g_socket_connection_constructed;
262 gobject_class->finalize = g_socket_connection_finalize;
263 gobject_class->dispose = g_socket_connection_dispose;
265 stream_class->get_input_stream = g_socket_connection_get_input_stream;
266 stream_class->get_output_stream = g_socket_connection_get_output_stream;
267 stream_class->close_fn = g_socket_connection_close;
268 stream_class->close_async = g_socket_connection_close_async;
269 stream_class->close_finish = g_socket_connection_close_finish;
271 g_object_class_install_property (gobject_class,
272 PROP_SOCKET,
273 g_param_spec_object ("socket",
274 P_("Socket"),
275 P_("The underlying GSocket"),
276 G_TYPE_SOCKET,
277 G_PARAM_CONSTRUCT_ONLY |
278 G_PARAM_READWRITE |
279 G_PARAM_STATIC_STRINGS));
282 static void
283 g_socket_connection_init (GSocketConnection *connection)
285 connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
286 G_TYPE_SOCKET_CONNECTION,
287 GSocketConnectionPrivate);
290 static gboolean
291 g_socket_connection_close (GIOStream *stream,
292 GCancellable *cancellable,
293 GError **error)
295 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
297 if (connection->priv->output_stream)
298 g_output_stream_close (connection->priv->output_stream,
299 cancellable, NULL);
300 if (connection->priv->input_stream)
301 g_input_stream_close (connection->priv->input_stream,
302 cancellable, NULL);
304 /* Don't close the underlying socket if this is being called
305 * as part of dispose(); when destroying the GSocketConnection,
306 * we only want to close the socket if we're holding the last
307 * reference on it, and in that case it will close itself when
308 * we unref it in finalize().
310 if (connection->priv->in_dispose)
311 return TRUE;
313 return g_socket_close (connection->priv->socket, error);
317 static void
318 g_socket_connection_close_async (GIOStream *stream,
319 int io_priority,
320 GCancellable *cancellable,
321 GAsyncReadyCallback callback,
322 gpointer user_data)
324 GSimpleAsyncResult *res;
325 GIOStreamClass *class;
326 GError *error;
328 class = G_IO_STREAM_GET_CLASS (stream);
330 /* socket close is not blocked, just do it! */
331 error = NULL;
332 if (class->close_fn &&
333 !class->close_fn (stream, cancellable, &error))
335 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
336 callback, user_data,
337 error);
338 g_error_free (error);
339 return;
342 res = g_simple_async_result_new (G_OBJECT (stream),
343 callback,
344 user_data,
345 g_socket_connection_close_async);
346 g_simple_async_result_complete_in_idle (res);
347 g_object_unref (res);
350 static gboolean
351 g_socket_connection_close_finish (GIOStream *stream,
352 GAsyncResult *result,
353 GError **error)
355 return TRUE;
358 typedef struct {
359 GSocketFamily socket_family;
360 GSocketType socket_type;
361 int protocol;
362 GType implementation;
363 } ConnectionFactory;
365 static guint
366 connection_factory_hash (gconstpointer key)
368 const ConnectionFactory *factory = key;
369 guint h;
371 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
372 /* This is likely to be small, so spread over whole
373 hash space to get some distribution */
374 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
376 return h;
379 static gboolean
380 connection_factory_equal (gconstpointer _a,
381 gconstpointer _b)
383 const ConnectionFactory *a = _a;
384 const ConnectionFactory *b = _b;
386 if (a->socket_family != b->socket_family)
387 return FALSE;
389 if (a->socket_type != b->socket_type)
390 return FALSE;
392 if (a->protocol != b->protocol)
393 return FALSE;
395 return TRUE;
398 static GHashTable *connection_factories = NULL;
399 G_LOCK_DEFINE_STATIC(connection_factories);
402 * g_socket_connection_factory_register_type:
403 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
404 * @family: a #GSocketFamily
405 * @type: a #GSocketType
406 * @protocol: a protocol id
408 * Looks up the #GType to be used when creating socket connections on
409 * sockets with the specified @family,@type and @protocol.
411 * If no type is registered, the #GSocketConnection base type is returned.
413 * Since: 2.22
415 void
416 g_socket_connection_factory_register_type (GType g_type,
417 GSocketFamily family,
418 GSocketType type,
419 gint protocol)
421 ConnectionFactory *factory;
423 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
425 G_LOCK (connection_factories);
427 if (connection_factories == NULL)
428 connection_factories = g_hash_table_new_full (connection_factory_hash,
429 connection_factory_equal,
430 (GDestroyNotify)g_free,
431 NULL);
433 factory = g_new0 (ConnectionFactory, 1);
434 factory->socket_family = family;
435 factory->socket_type = type;
436 factory->protocol = protocol;
437 factory->implementation = g_type;
439 g_hash_table_insert (connection_factories,
440 factory, factory);
442 G_UNLOCK (connection_factories);
445 static void
446 init_builtin_types (void)
448 volatile GType a_type;
449 #ifndef G_OS_WIN32
450 a_type = g_unix_connection_get_type ();
451 #endif
452 a_type = g_tcp_connection_get_type ();
456 * g_socket_connection_factory_lookup_type:
457 * @family: a #GSocketFamily
458 * @type: a #GSocketType
459 * @protocol_id: a protocol id
461 * Looks up the #GType to be used when creating socket connections on
462 * sockets with the specified @family,@type and @protocol_id.
464 * If no type is registered, the #GSocketConnection base type is returned.
466 * Returns: a #GType
468 * Since: 2.22
470 GType
471 g_socket_connection_factory_lookup_type (GSocketFamily family,
472 GSocketType type,
473 gint protocol_id)
475 ConnectionFactory *factory, key;
476 GType g_type;
478 init_builtin_types ();
480 G_LOCK (connection_factories);
482 g_type = G_TYPE_SOCKET_CONNECTION;
484 if (connection_factories)
486 key.socket_family = family;
487 key.socket_type = type;
488 key.protocol = protocol_id;
490 factory = g_hash_table_lookup (connection_factories, &key);
491 if (factory)
492 g_type = factory->implementation;
495 G_UNLOCK (connection_factories);
497 return g_type;
501 * g_socket_connection_factory_create_connection:
502 * @socket: a #GSocket
504 * Creates a #GSocketConnection subclass of the right type for
505 * @socket.
507 * Returns: a #GSocketConnection
509 * Since: 2.22
511 GSocketConnection *
512 g_socket_connection_factory_create_connection (GSocket *socket)
514 GType type;
516 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
517 g_socket_get_socket_type (socket),
518 g_socket_get_protocol (socket));
519 return g_object_new (type, "socket", socket, NULL);