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().
59 * To close a #GSocketConnection, use g_io_stream_close(). Closing both
60 * substreams of the #GIOStream separately will not close the underlying
72 struct _GSocketConnectionPrivate
75 GInputStream
*input_stream
;
76 GOutputStream
*output_stream
;
78 GSocketAddress
*cached_remote_address
;
83 static gboolean
g_socket_connection_close (GIOStream
*stream
,
84 GCancellable
*cancellable
,
86 static void g_socket_connection_close_async (GIOStream
*stream
,
88 GCancellable
*cancellable
,
89 GAsyncReadyCallback callback
,
91 static gboolean
g_socket_connection_close_finish (GIOStream
*stream
,
95 G_DEFINE_TYPE_WITH_PRIVATE (GSocketConnection
, g_socket_connection
, G_TYPE_IO_STREAM
)
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
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: (allow-none): 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
152 g_socket_connection_connect (GSocketConnection
*connection
,
153 GSocketAddress
*address
,
154 GCancellable
*cancellable
,
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
,
164 static gboolean
g_socket_connection_connect_callback (GSocket
*socket
,
165 GIOCondition condition
,
169 * g_socket_connection_connect_async:
170 * @connection: a #GSocketConnection
171 * @address: a #GSocketAddress specifying the remote address.
172 * @cancellable: (allow-none): 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.
186 g_socket_connection_connect_async (GSocketConnection
*connection
,
187 GSocketAddress
*address
,
188 GCancellable
*cancellable
,
189 GAsyncReadyCallback callback
,
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
);
200 g_socket_set_blocking (connection
->priv
->socket
, FALSE
);
202 if (g_socket_connect (connection
->priv
->socket
, address
,
203 cancellable
, &tmp_error
))
205 g_task_return_boolean (task
, TRUE
);
206 g_object_unref (task
);
208 else if (g_error_matches (tmp_error
, G_IO_ERROR
, G_IO_ERROR_PENDING
))
212 g_error_free (tmp_error
);
213 source
= g_socket_create_source (connection
->priv
->socket
,
214 G_IO_OUT
, cancellable
);
215 g_task_attach_source (task
, source
,
216 (GSourceFunc
) g_socket_connection_connect_callback
);
217 g_source_unref (source
);
221 g_task_return_error (task
, tmp_error
);
222 g_object_unref (task
);
227 g_socket_connection_connect_callback (GSocket
*socket
,
228 GIOCondition condition
,
231 GTask
*task
= user_data
;
232 GSocketConnection
*connection
= g_task_get_source_object (task
);
233 GError
*error
= NULL
;
235 if (g_socket_check_connect_result (connection
->priv
->socket
, &error
))
236 g_task_return_boolean (task
, TRUE
);
238 g_task_return_error (task
, error
);
240 g_object_unref (task
);
245 * g_socket_connection_connect_finish:
246 * @connection: a #GSocketConnection
247 * @result: the #GAsyncResult
248 * @error: #GError for error reporting, or %NULL to ignore.
250 * Gets the result of a g_socket_connection_connect_async() call.
252 * Returns: %TRUE if the connection succeeded, %FALSE on error
257 g_socket_connection_connect_finish (GSocketConnection
*connection
,
258 GAsyncResult
*result
,
261 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection
), FALSE
);
262 g_return_val_if_fail (g_task_is_valid (result
, connection
), FALSE
);
264 return g_task_propagate_boolean (G_TASK (result
), error
);
268 * g_socket_connection_get_socket:
269 * @connection: a #GSocketConnection
271 * Gets the underlying #GSocket object of the connection.
272 * This can be useful if you want to do something unusual on it
273 * not supported by the #GSocketConnection APIs.
275 * Returns: (transfer none): a #GSocketAddress or %NULL on error.
280 g_socket_connection_get_socket (GSocketConnection
*connection
)
282 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection
), NULL
);
284 return connection
->priv
->socket
;
288 * g_socket_connection_get_local_address:
289 * @connection: a #GSocketConnection
290 * @error: #GError for error reporting, or %NULL to ignore.
292 * Try to get the local address of a socket connection.
294 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
295 * Free the returned object with g_object_unref().
300 g_socket_connection_get_local_address (GSocketConnection
*connection
,
303 return g_socket_get_local_address (connection
->priv
->socket
, error
);
307 * g_socket_connection_get_remote_address:
308 * @connection: a #GSocketConnection
309 * @error: #GError for error reporting, or %NULL to ignore.
311 * Try to get the remote address of a socket connection.
313 * Since GLib 2.40, when used with g_socket_client_connect() or
314 * g_socket_client_connect_async(), during emission of
315 * %G_SOCKET_CLIENT_CONNECTING, this function will return the remote
316 * address that will be used for the connection. This allows
317 * applications to print e.g. "Connecting to example.com
320 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
321 * Free the returned object with g_object_unref().
326 g_socket_connection_get_remote_address (GSocketConnection
*connection
,
329 if (!g_socket_is_connected (connection
->priv
->socket
))
331 return connection
->priv
->cached_remote_address
?
332 g_object_ref (connection
->priv
->cached_remote_address
) : NULL
;
334 return g_socket_get_remote_address (connection
->priv
->socket
, error
);
337 /* Private API allowing applications to retrieve the resolved address
338 * now, before we start connecting.
340 * https://bugzilla.gnome.org/show_bug.cgi?id=712547
343 g_socket_connection_set_cached_remote_address (GSocketConnection
*connection
,
344 GSocketAddress
*address
)
346 g_clear_object (&connection
->priv
->cached_remote_address
);
347 connection
->priv
->cached_remote_address
= address
? g_object_ref (address
) : NULL
;
351 g_socket_connection_get_property (GObject
*object
,
356 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
361 g_value_set_object (value
, connection
->priv
->socket
);
365 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
370 g_socket_connection_set_property (GObject
*object
,
375 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
380 connection
->priv
->socket
= G_SOCKET (g_value_dup_object (value
));
384 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
389 g_socket_connection_constructed (GObject
*object
)
391 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
393 g_assert (connection
->priv
->socket
!= NULL
);
397 g_socket_connection_dispose (GObject
*object
)
399 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
401 connection
->priv
->in_dispose
= TRUE
;
403 g_clear_object (&connection
->priv
->cached_remote_address
);
405 G_OBJECT_CLASS (g_socket_connection_parent_class
)
408 connection
->priv
->in_dispose
= FALSE
;
412 g_socket_connection_finalize (GObject
*object
)
414 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
416 if (connection
->priv
->input_stream
)
417 g_object_unref (connection
->priv
->input_stream
);
419 if (connection
->priv
->output_stream
)
420 g_object_unref (connection
->priv
->output_stream
);
422 g_object_unref (connection
->priv
->socket
);
424 G_OBJECT_CLASS (g_socket_connection_parent_class
)
429 g_socket_connection_class_init (GSocketConnectionClass
*klass
)
431 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
432 GIOStreamClass
*stream_class
= G_IO_STREAM_CLASS (klass
);
434 gobject_class
->set_property
= g_socket_connection_set_property
;
435 gobject_class
->get_property
= g_socket_connection_get_property
;
436 gobject_class
->constructed
= g_socket_connection_constructed
;
437 gobject_class
->finalize
= g_socket_connection_finalize
;
438 gobject_class
->dispose
= g_socket_connection_dispose
;
440 stream_class
->get_input_stream
= g_socket_connection_get_input_stream
;
441 stream_class
->get_output_stream
= g_socket_connection_get_output_stream
;
442 stream_class
->close_fn
= g_socket_connection_close
;
443 stream_class
->close_async
= g_socket_connection_close_async
;
444 stream_class
->close_finish
= g_socket_connection_close_finish
;
446 g_object_class_install_property (gobject_class
,
448 g_param_spec_object ("socket",
450 P_("The underlying GSocket"),
452 G_PARAM_CONSTRUCT_ONLY
|
454 G_PARAM_STATIC_STRINGS
));
458 g_socket_connection_init (GSocketConnection
*connection
)
460 connection
->priv
= g_socket_connection_get_instance_private (connection
);
464 g_socket_connection_close (GIOStream
*stream
,
465 GCancellable
*cancellable
,
468 GSocketConnection
*connection
= G_SOCKET_CONNECTION (stream
);
470 if (connection
->priv
->output_stream
)
471 g_output_stream_close (connection
->priv
->output_stream
,
473 if (connection
->priv
->input_stream
)
474 g_input_stream_close (connection
->priv
->input_stream
,
477 /* Don't close the underlying socket if this is being called
478 * as part of dispose(); when destroying the GSocketConnection,
479 * we only want to close the socket if we're holding the last
480 * reference on it, and in that case it will close itself when
481 * we unref it in finalize().
483 if (connection
->priv
->in_dispose
)
486 return g_socket_close (connection
->priv
->socket
, error
);
491 g_socket_connection_close_async (GIOStream
*stream
,
493 GCancellable
*cancellable
,
494 GAsyncReadyCallback callback
,
498 GIOStreamClass
*class;
501 class = G_IO_STREAM_GET_CLASS (stream
);
503 task
= g_task_new (stream
, cancellable
, callback
, user_data
);
505 /* socket close is not blocked, just do it! */
507 if (class->close_fn
&&
508 !class->close_fn (stream
, cancellable
, &error
))
509 g_task_return_error (task
, error
);
511 g_task_return_boolean (task
, TRUE
);
513 g_object_unref (task
);
517 g_socket_connection_close_finish (GIOStream
*stream
,
518 GAsyncResult
*result
,
521 return g_task_propagate_boolean (G_TASK (result
), error
);
525 GSocketFamily socket_family
;
526 GSocketType socket_type
;
528 GType implementation
;
532 connection_factory_hash (gconstpointer key
)
534 const ConnectionFactory
*factory
= key
;
537 h
= factory
->socket_family
^ (factory
->socket_type
<< 4) ^ (factory
->protocol
<< 8);
538 /* This is likely to be small, so spread over whole
539 hash space to get some distribution */
540 h
= h
^ (h
<< 8) ^ (h
<< 16) ^ (h
<< 24);
546 connection_factory_equal (gconstpointer _a
,
549 const ConnectionFactory
*a
= _a
;
550 const ConnectionFactory
*b
= _b
;
552 if (a
->socket_family
!= b
->socket_family
)
555 if (a
->socket_type
!= b
->socket_type
)
558 if (a
->protocol
!= b
->protocol
)
564 static GHashTable
*connection_factories
= NULL
;
565 G_LOCK_DEFINE_STATIC(connection_factories
);
568 * g_socket_connection_factory_register_type:
569 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
570 * @family: a #GSocketFamily
571 * @type: a #GSocketType
572 * @protocol: a protocol id
574 * Looks up the #GType to be used when creating socket connections on
575 * sockets with the specified @family, @type and @protocol.
577 * If no type is registered, the #GSocketConnection base type is returned.
582 g_socket_connection_factory_register_type (GType g_type
,
583 GSocketFamily family
,
587 ConnectionFactory
*factory
;
589 g_return_if_fail (g_type_is_a (g_type
, G_TYPE_SOCKET_CONNECTION
));
591 G_LOCK (connection_factories
);
593 if (connection_factories
== NULL
)
594 connection_factories
= g_hash_table_new_full (connection_factory_hash
,
595 connection_factory_equal
,
596 (GDestroyNotify
)g_free
,
599 factory
= g_new0 (ConnectionFactory
, 1);
600 factory
->socket_family
= family
;
601 factory
->socket_type
= type
;
602 factory
->protocol
= protocol
;
603 factory
->implementation
= g_type
;
605 g_hash_table_insert (connection_factories
,
608 G_UNLOCK (connection_factories
);
612 init_builtin_types (void)
615 g_type_ensure (G_TYPE_UNIX_CONNECTION
);
617 g_type_ensure (G_TYPE_TCP_CONNECTION
);
621 * g_socket_connection_factory_lookup_type:
622 * @family: a #GSocketFamily
623 * @type: a #GSocketType
624 * @protocol_id: a protocol id
626 * Looks up the #GType to be used when creating socket connections on
627 * sockets with the specified @family, @type and @protocol_id.
629 * If no type is registered, the #GSocketConnection base type is returned.
636 g_socket_connection_factory_lookup_type (GSocketFamily family
,
640 ConnectionFactory
*factory
, key
;
643 init_builtin_types ();
645 G_LOCK (connection_factories
);
647 g_type
= G_TYPE_SOCKET_CONNECTION
;
649 if (connection_factories
)
651 key
.socket_family
= family
;
652 key
.socket_type
= type
;
653 key
.protocol
= protocol_id
;
655 factory
= g_hash_table_lookup (connection_factories
, &key
);
657 g_type
= factory
->implementation
;
660 G_UNLOCK (connection_factories
);
666 * g_socket_connection_factory_create_connection:
667 * @socket: a #GSocket
669 * Creates a #GSocketConnection subclass of the right type for
672 * Returns: (transfer full): a #GSocketConnection
677 g_socket_connection_factory_create_connection (GSocket
*socket
)
681 type
= g_socket_connection_factory_lookup_type (g_socket_get_family (socket
),
682 g_socket_get_socket_type (socket
),
683 g_socket_get_protocol (socket
));
684 return g_object_new (type
, "socket", socket
, NULL
);