Add some more cases to the app-id unit tests
[glib.git] / gio / gsocketconnection.c
blob63d974dde44f386ddc8d83b28ed6623a15ab861f
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, 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>
26 #include "config.h"
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"
37 #include "glibintl.h"
40 /**
41 * SECTION:gsocketconnection
42 * @short_description: A socket connection
43 * @include: gio/gio.h
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().
59 * To close a #GSocketConnection, use g_io_stream_close(). Closing both
60 * substreams of the #GIOStream separately will not close the underlying
61 * #GSocket.
63 * Since: 2.22
66 enum
68 PROP_NONE,
69 PROP_SOCKET,
72 struct _GSocketConnectionPrivate
74 GSocket *socket;
75 GInputStream *input_stream;
76 GOutputStream *output_stream;
78 GSocketAddress *cached_remote_address;
80 gboolean in_dispose;
83 static gboolean g_socket_connection_close (GIOStream *stream,
84 GCancellable *cancellable,
85 GError **error);
86 static void g_socket_connection_close_async (GIOStream *stream,
87 int io_priority,
88 GCancellable *cancellable,
89 GAsyncReadyCallback callback,
90 gpointer user_data);
91 static gboolean g_socket_connection_close_finish (GIOStream *stream,
92 GAsyncResult *result,
93 GError **error);
95 G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM)
97 static GInputStream *
98 g_socket_connection_get_input_stream (GIOStream *io_stream)
100 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
102 if (connection->priv->input_stream == NULL)
103 connection->priv->input_stream = (GInputStream *)
104 _g_socket_input_stream_new (connection->priv->socket);
106 return connection->priv->input_stream;
109 static GOutputStream *
110 g_socket_connection_get_output_stream (GIOStream *io_stream)
112 GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
114 if (connection->priv->output_stream == NULL)
115 connection->priv->output_stream = (GOutputStream *)
116 _g_socket_output_stream_new (connection->priv->socket);
118 return connection->priv->output_stream;
122 * g_socket_connection_is_connected:
123 * @connection: a #GSocketConnection
125 * Checks if @connection is connected. This is equivalent to calling
126 * g_socket_is_connected() on @connection's underlying #GSocket.
128 * Returns: whether @connection is connected
130 * Since: 2.32
132 gboolean
133 g_socket_connection_is_connected (GSocketConnection *connection)
135 return g_socket_is_connected (connection->priv->socket);
139 * g_socket_connection_connect:
140 * @connection: a #GSocketConnection
141 * @address: a #GSocketAddress specifying the remote address.
142 * @cancellable: (nullable): a %GCancellable or %NULL
143 * @error: #GError for error reporting, or %NULL to ignore.
145 * Connect @connection to the specified remote address.
147 * Returns: %TRUE if the connection succeeded, %FALSE on error
149 * Since: 2.32
151 gboolean
152 g_socket_connection_connect (GSocketConnection *connection,
153 GSocketAddress *address,
154 GCancellable *cancellable,
155 GError **error)
157 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
158 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address), FALSE);
160 return g_socket_connect (connection->priv->socket, address,
161 cancellable, error);
164 static gboolean g_socket_connection_connect_callback (GSocket *socket,
165 GIOCondition condition,
166 gpointer user_data);
169 * g_socket_connection_connect_async:
170 * @connection: a #GSocketConnection
171 * @address: a #GSocketAddress specifying the remote address.
172 * @cancellable: (nullable): a %GCancellable or %NULL
173 * @callback: (scope async): a #GAsyncReadyCallback
174 * @user_data: (closure): user data for the callback
176 * Asynchronously connect @connection to the specified remote address.
178 * This clears the #GSocket:blocking flag on @connection's underlying
179 * socket if it is currently set.
181 * Use g_socket_connection_connect_finish() to retrieve the result.
183 * Since: 2.32
185 void
186 g_socket_connection_connect_async (GSocketConnection *connection,
187 GSocketAddress *address,
188 GCancellable *cancellable,
189 GAsyncReadyCallback callback,
190 gpointer user_data)
192 GTask *task;
193 GError *tmp_error = NULL;
195 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection));
196 g_return_if_fail (G_IS_SOCKET_ADDRESS (address));
198 task = g_task_new (connection, cancellable, callback, user_data);
199 g_task_set_source_tag (task, g_socket_connection_connect_async);
201 g_socket_set_blocking (connection->priv->socket, FALSE);
203 if (g_socket_connect (connection->priv->socket, address,
204 cancellable, &tmp_error))
206 g_task_return_boolean (task, TRUE);
207 g_object_unref (task);
209 else if (g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_PENDING))
211 GSource *source;
213 g_error_free (tmp_error);
214 source = g_socket_create_source (connection->priv->socket,
215 G_IO_OUT, cancellable);
216 g_task_attach_source (task, source,
217 (GSourceFunc) g_socket_connection_connect_callback);
218 g_source_unref (source);
220 else
222 g_task_return_error (task, tmp_error);
223 g_object_unref (task);
227 static gboolean
228 g_socket_connection_connect_callback (GSocket *socket,
229 GIOCondition condition,
230 gpointer user_data)
232 GTask *task = user_data;
233 GSocketConnection *connection = g_task_get_source_object (task);
234 GError *error = NULL;
236 if (g_socket_check_connect_result (connection->priv->socket, &error))
237 g_task_return_boolean (task, TRUE);
238 else
239 g_task_return_error (task, error);
241 g_object_unref (task);
242 return FALSE;
246 * g_socket_connection_connect_finish:
247 * @connection: a #GSocketConnection
248 * @result: the #GAsyncResult
249 * @error: #GError for error reporting, or %NULL to ignore.
251 * Gets the result of a g_socket_connection_connect_async() call.
253 * Returns: %TRUE if the connection succeeded, %FALSE on error
255 * Since: 2.32
257 gboolean
258 g_socket_connection_connect_finish (GSocketConnection *connection,
259 GAsyncResult *result,
260 GError **error)
262 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), FALSE);
263 g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
265 return g_task_propagate_boolean (G_TASK (result), error);
269 * g_socket_connection_get_socket:
270 * @connection: a #GSocketConnection
272 * Gets the underlying #GSocket object of the connection.
273 * This can be useful if you want to do something unusual on it
274 * not supported by the #GSocketConnection APIs.
276 * Returns: (transfer none): a #GSocket or %NULL on error.
278 * Since: 2.22
280 GSocket *
281 g_socket_connection_get_socket (GSocketConnection *connection)
283 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
285 return connection->priv->socket;
289 * g_socket_connection_get_local_address:
290 * @connection: a #GSocketConnection
291 * @error: #GError for error reporting, or %NULL to ignore.
293 * Try to get the local address of a socket connection.
295 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
296 * Free the returned object with g_object_unref().
298 * Since: 2.22
300 GSocketAddress *
301 g_socket_connection_get_local_address (GSocketConnection *connection,
302 GError **error)
304 return g_socket_get_local_address (connection->priv->socket, error);
308 * g_socket_connection_get_remote_address:
309 * @connection: a #GSocketConnection
310 * @error: #GError for error reporting, or %NULL to ignore.
312 * Try to get the remote address of a socket connection.
314 * Since GLib 2.40, when used with g_socket_client_connect() or
315 * g_socket_client_connect_async(), during emission of
316 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
317 * address that will be used for the connection. This allows
318 * applications to print e.g. "Connecting to example.com
319 * (10.42.77.3)...".
321 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
322 * Free the returned object with g_object_unref().
324 * Since: 2.22
326 GSocketAddress *
327 g_socket_connection_get_remote_address (GSocketConnection *connection,
328 GError **error)
330 if (!g_socket_is_connected (connection->priv->socket))
332 return connection->priv->cached_remote_address ?
333 g_object_ref (connection->priv->cached_remote_address) : NULL;
335 return g_socket_get_remote_address (connection->priv->socket, error);
338 /* Private API allowing applications to retrieve the resolved address
339 * now, before we start connecting.
341 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
343 void
344 g_socket_connection_set_cached_remote_address (GSocketConnection *connection,
345 GSocketAddress *address)
347 g_clear_object (&connection->priv->cached_remote_address);
348 connection->priv->cached_remote_address = address ? g_object_ref (address) : NULL;
351 static void
352 g_socket_connection_get_property (GObject *object,
353 guint prop_id,
354 GValue *value,
355 GParamSpec *pspec)
357 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
359 switch (prop_id)
361 case PROP_SOCKET:
362 g_value_set_object (value, connection->priv->socket);
363 break;
365 default:
366 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
370 static void
371 g_socket_connection_set_property (GObject *object,
372 guint prop_id,
373 const GValue *value,
374 GParamSpec *pspec)
376 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
378 switch (prop_id)
380 case PROP_SOCKET:
381 connection->priv->socket = G_SOCKET (g_value_dup_object (value));
382 break;
384 default:
385 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
389 static void
390 g_socket_connection_constructed (GObject *object)
392 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
394 g_assert (connection->priv->socket != NULL);
397 static void
398 g_socket_connection_dispose (GObject *object)
400 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
402 connection->priv->in_dispose = TRUE;
404 g_clear_object (&connection->priv->cached_remote_address);
406 G_OBJECT_CLASS (g_socket_connection_parent_class)
407 ->dispose (object);
409 connection->priv->in_dispose = FALSE;
412 static void
413 g_socket_connection_finalize (GObject *object)
415 GSocketConnection *connection = G_SOCKET_CONNECTION (object);
417 if (connection->priv->input_stream)
418 g_object_unref (connection->priv->input_stream);
420 if (connection->priv->output_stream)
421 g_object_unref (connection->priv->output_stream);
423 g_object_unref (connection->priv->socket);
425 G_OBJECT_CLASS (g_socket_connection_parent_class)
426 ->finalize (object);
429 static void
430 g_socket_connection_class_init (GSocketConnectionClass *klass)
432 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
433 GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
435 gobject_class->set_property = g_socket_connection_set_property;
436 gobject_class->get_property = g_socket_connection_get_property;
437 gobject_class->constructed = g_socket_connection_constructed;
438 gobject_class->finalize = g_socket_connection_finalize;
439 gobject_class->dispose = g_socket_connection_dispose;
441 stream_class->get_input_stream = g_socket_connection_get_input_stream;
442 stream_class->get_output_stream = g_socket_connection_get_output_stream;
443 stream_class->close_fn = g_socket_connection_close;
444 stream_class->close_async = g_socket_connection_close_async;
445 stream_class->close_finish = g_socket_connection_close_finish;
447 g_object_class_install_property (gobject_class,
448 PROP_SOCKET,
449 g_param_spec_object ("socket",
450 P_("Socket"),
451 P_("The underlying GSocket"),
452 G_TYPE_SOCKET,
453 G_PARAM_CONSTRUCT_ONLY |
454 G_PARAM_READWRITE |
455 G_PARAM_STATIC_STRINGS));
458 static void
459 g_socket_connection_init (GSocketConnection *connection)
461 connection->priv = g_socket_connection_get_instance_private (connection);
464 static gboolean
465 g_socket_connection_close (GIOStream *stream,
466 GCancellable *cancellable,
467 GError **error)
469 GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
471 if (connection->priv->output_stream)
472 g_output_stream_close (connection->priv->output_stream,
473 cancellable, NULL);
474 if (connection->priv->input_stream)
475 g_input_stream_close (connection->priv->input_stream,
476 cancellable, NULL);
478 /* Don't close the underlying socket if this is being called
479 * as part of dispose(); when destroying the GSocketConnection,
480 * we only want to close the socket if we're holding the last
481 * reference on it, and in that case it will close itself when
482 * we unref it in finalize().
484 if (connection->priv->in_dispose)
485 return TRUE;
487 return g_socket_close (connection->priv->socket, error);
491 static void
492 g_socket_connection_close_async (GIOStream *stream,
493 int io_priority,
494 GCancellable *cancellable,
495 GAsyncReadyCallback callback,
496 gpointer user_data)
498 GTask *task;
499 GIOStreamClass *class;
500 GError *error;
502 class = G_IO_STREAM_GET_CLASS (stream);
504 task = g_task_new (stream, cancellable, callback, user_data);
505 g_task_set_source_tag (task, g_socket_connection_close_async);
507 /* socket close is not blocked, just do it! */
508 error = NULL;
509 if (class->close_fn &&
510 !class->close_fn (stream, cancellable, &error))
511 g_task_return_error (task, error);
512 else
513 g_task_return_boolean (task, TRUE);
515 g_object_unref (task);
518 static gboolean
519 g_socket_connection_close_finish (GIOStream *stream,
520 GAsyncResult *result,
521 GError **error)
523 return g_task_propagate_boolean (G_TASK (result), error);
526 typedef struct {
527 GSocketFamily socket_family;
528 GSocketType socket_type;
529 int protocol;
530 GType implementation;
531 } ConnectionFactory;
533 static guint
534 connection_factory_hash (gconstpointer key)
536 const ConnectionFactory *factory = key;
537 guint h;
539 h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
540 /* This is likely to be small, so spread over whole
541 hash space to get some distribution */
542 h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
544 return h;
547 static gboolean
548 connection_factory_equal (gconstpointer _a,
549 gconstpointer _b)
551 const ConnectionFactory *a = _a;
552 const ConnectionFactory *b = _b;
554 if (a->socket_family != b->socket_family)
555 return FALSE;
557 if (a->socket_type != b->socket_type)
558 return FALSE;
560 if (a->protocol != b->protocol)
561 return FALSE;
563 return TRUE;
566 static GHashTable *connection_factories = NULL;
567 G_LOCK_DEFINE_STATIC(connection_factories);
570 * g_socket_connection_factory_register_type:
571 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
572 * @family: a #GSocketFamily
573 * @type: a #GSocketType
574 * @protocol: a protocol id
576 * Looks up the #GType to be used when creating socket connections on
577 * sockets with the specified @family, @type and @protocol.
579 * If no type is registered, the #GSocketConnection base type is returned.
581 * Since: 2.22
583 void
584 g_socket_connection_factory_register_type (GType g_type,
585 GSocketFamily family,
586 GSocketType type,
587 gint protocol)
589 ConnectionFactory *factory;
591 g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
593 G_LOCK (connection_factories);
595 if (connection_factories == NULL)
596 connection_factories = g_hash_table_new_full (connection_factory_hash,
597 connection_factory_equal,
598 (GDestroyNotify)g_free,
599 NULL);
601 factory = g_new0 (ConnectionFactory, 1);
602 factory->socket_family = family;
603 factory->socket_type = type;
604 factory->protocol = protocol;
605 factory->implementation = g_type;
607 g_hash_table_insert (connection_factories,
608 factory, factory);
610 G_UNLOCK (connection_factories);
613 static void
614 init_builtin_types (void)
616 #ifndef G_OS_WIN32
617 g_type_ensure (G_TYPE_UNIX_CONNECTION);
618 #endif
619 g_type_ensure (G_TYPE_TCP_CONNECTION);
623 * g_socket_connection_factory_lookup_type:
624 * @family: a #GSocketFamily
625 * @type: a #GSocketType
626 * @protocol_id: a protocol id
628 * Looks up the #GType to be used when creating socket connections on
629 * sockets with the specified @family, @type and @protocol_id.
631 * If no type is registered, the #GSocketConnection base type is returned.
633 * Returns: a #GType
635 * Since: 2.22
637 GType
638 g_socket_connection_factory_lookup_type (GSocketFamily family,
639 GSocketType type,
640 gint protocol_id)
642 ConnectionFactory *factory, key;
643 GType g_type;
645 init_builtin_types ();
647 G_LOCK (connection_factories);
649 g_type = G_TYPE_SOCKET_CONNECTION;
651 if (connection_factories)
653 key.socket_family = family;
654 key.socket_type = type;
655 key.protocol = protocol_id;
657 factory = g_hash_table_lookup (connection_factories, &key);
658 if (factory)
659 g_type = factory->implementation;
662 G_UNLOCK (connection_factories);
664 return g_type;
668 * g_socket_connection_factory_create_connection:
669 * @socket: a #GSocket
671 * Creates a #GSocketConnection subclass of the right type for
672 * @socket.
674 * Returns: (transfer full): a #GSocketConnection
676 * Since: 2.22
678 GSocketConnection *
679 g_socket_connection_factory_create_connection (GSocket *socket)
681 GType type;
683 type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
684 g_socket_get_socket_type (socket),
685 g_socket_get_protocol (socket));
686 return g_object_new (type, "socket", socket, NULL);