glib/tests: Fix non-debug build of slice test
[glib.git] / gio / gsocketconnection.c
blob6127a84c9bdb7f93c51778b9b8c910cd1be4c645
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 "gioprivate.h"
35 #include <gio/giostream.h>
36 #include <gio/gtask.h>
37 #include "gunixconnection.h"
38 #include "gtcpconnection.h"
39 #include "glibintl.h"
42 /**
43 * SECTION:gsocketconnection
44 * @short_description: A socket connection
45 * @include: gio/gio.h
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 * Since: 2.22
64 enum
66 PROP_NONE,
67 PROP_SOCKET,
70 struct _GSocketConnectionPrivate
72 GSocket *socket;
73 GInputStream *input_stream;
74 GOutputStream *output_stream;
76 GSocketAddress *cached_remote_address;
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 G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
95 static GInputStream *
96 g_socket_connection_get_input_stream (GIOStream *io_stream)
98 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
100 if (connection->priv->input_stream == NULL)
101 connection->priv->input_stream = (GInputStream *)
102 _g_socket_input_stream_new (connection->priv->socket);
104 return connection->priv->input_stream;
107 static GOutputStream *
108 g_socket_connection_get_output_stream (GIOStream *io_stream)
110 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
112 if (connection->priv->output_stream == NULL)
113 connection->priv->output_stream = (GOutputStream *)
114 _g_socket_output_stream_new (connection->priv->socket);
116 return connection->priv->output_stream;
120 * g_socket_connection_is_connected:
121 * @connection: a #GSocketConnection
123 * Checks if @connection is connected. This is equivalent to calling
124 * g_socket_is_connected() on @connection's underlying #GSocket.
126 * Returns: whether @connection is connected
128 * Since: 2.32
130 gboolean
131 g_socket_connection_is_connected (GSocketConnection *connection)
133 return g_socket_is_connected (connection->priv->socket);
137 * g_socket_connection_connect:
138 * @connection: a #GSocketConnection
139 * @address: a #GSocketAddress specifying the remote address.
140 * @cancellable: (allow-none): a %GCancellable or %NULL
141 * @error: #GError for error reporting, or %NULL to ignore.
143 * Connect @connection to the specified remote address.
145 * Returns: %TRUE if the connection succeeded, %FALSE on error
147 * Since: 2.32
149 gboolean
150 g_socket_connection_connect (GSocketConnection *connection,
151 GSocketAddress *address,
152 GCancellable *cancellable,
153 GError **error)
155 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
156 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
158 return g_socket_connect (connection->priv->socket, address,
159 cancellable, error);
162 static gboolean g_socket_connection_connect_callback (GSocket *socket,
163 GIOCondition condition,
164 gpointer user_data);
167 * g_socket_connection_connect_async:
168 * @connection: a #GSocketConnection
169 * @address: a #GSocketAddress specifying the remote address.
170 * @cancellable: (allow-none): a %GCancellable or %NULL
171 * @callback: (scope async): a #GAsyncReadyCallback
172 * @user_data: (closure): user data for the callback
174 * Asynchronously connect @connection to the specified remote address.
176 * This clears the #GSocket:blocking flag on @connection's underlying
177 * socket if it is currently set.
179 * Use g_socket_connection_connect_finish() to retrieve the result.
181 * Since: 2.32
183 void
184 g_socket_connection_connect_async (GSocketConnection *connection,
185 GSocketAddress *address,
186 GCancellable *cancellable,
187 GAsyncReadyCallback callback,
188 gpointer user_data)
190 GTask *task;
191 GError *tmp_error = NULL;
193 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
194 g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
196 task = g_task_new (connection, cancellable, callback, user_data);
198 g_socket_set_blocking (connection->priv->socket, FALSE);
200 if (g_socket_connect (connection->priv->socket, address,
201 cancellable, &tmp_error))
203 g_task_return_boolean (task, TRUE);
204 g_object_unref (task);
206 else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
208 GSource *source;
210 g_error_free (tmp_error);
211 source = g_socket_create_source (connection->priv->socket,
212 G_IO_OUT, cancellable);
213 g_task_attach_source (task, source,
214 (GSourceFunc) g_socket_connection_connect_callback);
215 g_source_unref (source);
217 else
219 g_task_return_error (task, tmp_error);
220 g_object_unref (task);
224 static gboolean
225 g_socket_connection_connect_callback (GSocket *socket,
226 GIOCondition condition,
227 gpointer user_data)
229 GTask *task = user_data;
230 GSocketConnection *connection = g_task_get_source_object (task);
231 GError *error = NULL;
233 if (g_socket_check_connect_result (connection->priv->socket, &error))
234 g_task_return_boolean (task, TRUE);
235 else
236 g_task_return_error (task, error);
238 g_object_unref (task);
239 return FALSE;
243 * g_socket_connection_connect_finish:
244 * @connection: a #GSocketConnection
245 * @result: the #GAsyncResult
246 * @error: #GError for error reporting, or %NULL to ignore.
248 * Gets the result of a g_socket_connection_connect_async() call.
250 * Returns: %TRUE if the connection succeeded, %FALSE on error
252 * Since: 2.32
254 gboolean
255 g_socket_connection_connect_finish (GSocketConnection *connection,
256 GAsyncResult *result,
257 GError **error)
259 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
260 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
262 return g_task_propagate_boolean (G_TASK (result), error);
266 * g_socket_connection_get_socket:
267 * @connection: a #GSocketConnection
269 * Gets the underlying #GSocket object of the connection.
270 * This can be useful if you want to do something unusual on it
271 * not supported by the #GSocketConnection APIs.
273 * Returns: (transfer none): a #GSocketAddress or %NULL on error.
275 * Since: 2.22
277 GSocket *
278 g_socket_connection_get_socket (GSocketConnection *connection)
280 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
282 return connection->priv->socket;
286 * g_socket_connection_get_local_address:
287 * @connection: a #GSocketConnection
288 * @error: #GError for error reporting, or %NULL to ignore.
290 * Try to get the local address of a socket connection.
292 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
293 * Free the returned object with g_object_unref().
295 * Since: 2.22
297 GSocketAddress *
298 g_socket_connection_get_local_address (GSocketConnection *connection,
299 GError **error)
301 return g_socket_get_local_address (connection->priv->socket, error);
305 * g_socket_connection_get_remote_address:
306 * @connection: a #GSocketConnection
307 * @error: #GError for error reporting, or %NULL to ignore.
309 * Try to get the remote address of a socket connection.
311 * Since GLib 2.40, when used with g_socket_client_connect() or
312 * g_socket_client_connect_async(), during emission of
313 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
314 * address that will be used for the connection. This allows
315 * applications to print e.g. "Connecting to example.com
316 * (10.42.77.3)...".
318 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
319 * Free the returned object with g_object_unref().
321 * Since: 2.22
323 GSocketAddress *
324 g_socket_connection_get_remote_address (GSocketConnection *connection,
325 GError **error)
327 if (!g_socket_is_connected (connection->priv->socket))
329 return connection->priv->cached_remote_address ?
330 g_object_ref (connection->priv->cached_remote_address) : NULL;
332 return g_socket_get_remote_address (connection->priv->socket, error);
335 /* Private API allowing applications to retrieve the resolved address
336 * now, before we start connecting.
338 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
340 void
341 g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
342 GSocketAddress *address)
344 g_clear_object (&connection->priv->cached_remote_address);
345 connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
348 static void
349 g_socket_connection_get_property (GObject *object,
350 guint prop_id,
351 GValue *value,
352 GParamSpec *pspec)
354 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
356 switch (prop_id)
358 case PROP_SOCKET:
359 g_value_set_object (value, connection->priv->socket);
360 break;
362 default:
363 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
367 static void
368 g_socket_connection_set_property (GObject *object,
369 guint prop_id,
370 const GValue *value,
371 GParamSpec *pspec)
373 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
375 switch (prop_id)
377 case PROP_SOCKET:
378 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
379 break;
381 default:
382 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386 static void
387 g_socket_connection_constructed (GObject *object)
389 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
391 g_assert (connection->priv->socket != NULL);
394 static void
395 g_socket_connection_dispose (GObject *object)
397 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
399 connection->priv->in_dispose = TRUE;
401 g_clear_object (&connection->priv->cached_remote_address);
403 G_OBJECT_CLASS (g_socket_connection_parent_class)
404 ->dispose (object);
406 connection->priv->in_dispose = FALSE;
409 static void
410 g_socket_connection_finalize (GObject *object)
412 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
414 if (connection->priv->input_stream)
415 g_object_unref (connection->priv->input_stream);
417 if (connection->priv->output_stream)
418 g_object_unref (connection->priv->output_stream);
420 g_object_unref (connection->priv->socket);
422 G_OBJECT_CLASS (g_socket_connection_parent_class)
423 ->finalize (object);
426 static void
427 g_socket_connection_class_init (GSocketConnectionClass *klass)
429 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
430 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
432 gobject_class->set_property = g_socket_connection_set_property;
433 gobject_class->get_property = g_socket_connection_get_property;
434 gobject_class->constructed = g_socket_connection_constructed;
435 gobject_class->finalize = g_socket_connection_finalize;
436 gobject_class->dispose = g_socket_connection_dispose;
438 stream_class->get_input_stream = g_socket_connection_get_input_stream;
439 stream_class->get_output_stream = g_socket_connection_get_output_stream;
440 stream_class->close_fn = g_socket_connection_close;
441 stream_class->close_async = g_socket_connection_close_async;
442 stream_class->close_finish = g_socket_connection_close_finish;
444 g_object_class_install_property (gobject_class,
445 PROP_SOCKET,
446 g_param_spec_object ("socket",
447 P_("Socket"),
448 P_("The underlying GSocket"),
449 G_TYPE_SOCKET,
450 G_PARAM_CONSTRUCT_ONLY |
451 G_PARAM_READWRITE |
452 G_PARAM_STATIC_STRINGS));
455 static void
456 g_socket_connection_init (GSocketConnection *connection)
458 connection->priv = g_socket_connection_get_instance_private (connection);
461 static gboolean
462 g_socket_connection_close (GIOStream *stream,
463 GCancellable *cancellable,
464 GError **error)
466 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
468 if (connection->priv->output_stream)
469 g_output_stream_close (connection->priv->output_stream,
470 cancellable, NULL);
471 if (connection->priv->input_stream)
472 g_input_stream_close (connection->priv->input_stream,
473 cancellable, NULL);
475 /* Don't close the underlying socket if this is being called
476 * as part of dispose(); when destroying the GSocketConnection,
477 * we only want to close the socket if we're holding the last
478 * reference on it, and in that case it will close itself when
479 * we unref it in finalize().
481 if (connection->priv->in_dispose)
482 return TRUE;
484 return g_socket_close (connection->priv->socket, error);
488 static void
489 g_socket_connection_close_async (GIOStream *stream,
490 int io_priority,
491 GCancellable *cancellable,
492 GAsyncReadyCallback callback,
493 gpointer user_data)
495 GTask *task;
496 GIOStreamClass *class;
497 GError *error;
499 class = G_IO_STREAM_GET_CLASS (stream);
501 task = g_task_new (stream, cancellable, callback, user_data);
503 /* socket close is not blocked, just do it! */
504 error = NULL;
505 if (class->close_fn &&
506 !class->close_fn (stream, cancellable, &error))
507 g_task_return_error (task, error);
508 else
509 g_task_return_boolean (task, TRUE);
511 g_object_unref (task);
514 static gboolean
515 g_socket_connection_close_finish (GIOStream *stream,
516 GAsyncResult *result,
517 GError **error)
519 return g_task_propagate_boolean (G_TASK (result), error);
522 typedef struct {
523 GSocketFamily socket_family;
524 GSocketType socket_type;
525 int protocol;
526 GType implementation;
527 } ConnectionFactory;
529 static guint
530 connection_factory_hash (gconstpointer key)
532 const ConnectionFactory *factory = key;
533 guint h;
535 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
536 /* This is likely to be small, so spread over whole
537 hash space to get some distribution */
538 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
540 return h;
543 static gboolean
544 connection_factory_equal (gconstpointer _a,
545 gconstpointer _b)
547 const ConnectionFactory *a = _a;
548 const ConnectionFactory *b = _b;
550 if (a->socket_family != b->socket_family)
551 return FALSE;
553 if (a->socket_type != b->socket_type)
554 return FALSE;
556 if (a->protocol != b->protocol)
557 return FALSE;
559 return TRUE;
562 static GHashTable *connection_factories = NULL;
563 G_LOCK_DEFINE_STATIC(connection_factories);
566 * g_socket_connection_factory_register_type:
567 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
568 * @family: a #GSocketFamily
569 * @type: a #GSocketType
570 * @protocol: a protocol id
572 * Looks up the #GType to be used when creating socket connections on
573 * sockets with the specified @family, @type and @protocol.
575 * If no type is registered, the #GSocketConnection base type is returned.
577 * Since: 2.22
579 void
580 g_socket_connection_factory_register_type (GType g_type,
581 GSocketFamily family,
582 GSocketType type,
583 gint protocol)
585 ConnectionFactory *factory;
587 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
589 G_LOCK (connection_factories);
591 if (connection_factories == NULL)
592 connection_factories = g_hash_table_new_full (connection_factory_hash,
593 connection_factory_equal,
594 (GDestroyNotify)g_free,
595 NULL);
597 factory = g_new0 (ConnectionFactory, 1);
598 factory->socket_family = family;
599 factory->socket_type = type;
600 factory->protocol = protocol;
601 factory->implementation = g_type;
603 g_hash_table_insert (connection_factories,
604 factory, factory);
606 G_UNLOCK (connection_factories);
609 static void
610 init_builtin_types (void)
612 #ifndef G_OS_WIN32
613 g_type_ensure (G_TYPE_UNIX_CONNECTION);
614 #endif
615 g_type_ensure (G_TYPE_TCP_CONNECTION);
619 * g_socket_connection_factory_lookup_type:
620 * @family: a #GSocketFamily
621 * @type: a #GSocketType
622 * @protocol_id: a protocol id
624 * Looks up the #GType to be used when creating socket connections on
625 * sockets with the specified @family, @type and @protocol_id.
627 * If no type is registered, the #GSocketConnection base type is returned.
629 * Returns: a #GType
631 * Since: 2.22
633 GType
634 g_socket_connection_factory_lookup_type (GSocketFamily family,
635 GSocketType type,
636 gint protocol_id)
638 ConnectionFactory *factory, key;
639 GType g_type;
641 init_builtin_types ();
643 G_LOCK (connection_factories);
645 g_type = G_TYPE_SOCKET_CONNECTION;
647 if (connection_factories)
649 key.socket_family = family;
650 key.socket_type = type;
651 key.protocol = protocol_id;
653 factory = g_hash_table_lookup (connection_factories, &key);
654 if (factory)
655 g_type = factory->implementation;
658 G_UNLOCK (connection_factories);
660 return g_type;
664 * g_socket_connection_factory_create_connection:
665 * @socket: a #GSocket
667 * Creates a #GSocketConnection subclass of the right type for
668 * @socket.
670 * Returns: (transfer full): a #GSocketConnection
672 * Since: 2.22
674 GSocketConnection *
675 g_socket_connection_factory_create_connection (GSocket *socket)
677 GType type;
679 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
680 g_socket_get_socket_type (socket),
681 g_socket_get_protocol (socket));
682 return g_object_new (type, "socket", socket, NULL);