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"
42 * SECTION:gsocketconnection
43 * @short_description: A socket connection
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 * Choosing 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().
63 G_DEFINE_TYPE (GSocketConnection
, g_socket_connection
, G_TYPE_IO_STREAM
);
71 struct _GSocketConnectionPrivate
74 GInputStream
*input_stream
;
75 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_is_connected:
118 * @connection: a #GSocketConnection
120 * Checks if @connection is connected. This is equivalent to calling
121 * g_socket_is_connected() on @connection's underlying #GSocket.
123 * Returns: whether @connection is connected
128 g_socket_connection_is_connected (GSocketConnection
*connection
)
130 return g_socket_is_connected (connection
->priv
->socket
);
134 * g_socket_connection_connect:
135 * @connection: a #GSocketConnection
136 * @address: a #GSocketAddress specifying the remote address.
137 * @cancellable: (allow-none): a %GCancellable or %NULL
138 * @error: #GError for error reporting, or %NULL to ignore.
140 * Connect @connection to the specified remote address.
142 * Returns: %TRUE if the connection succeeded, %FALSE on error
147 g_socket_connection_connect (GSocketConnection
*connection
,
148 GSocketAddress
*address
,
149 GCancellable
*cancellable
,
152 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection
), FALSE
);
153 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (address
), FALSE
);
155 return g_socket_connect (connection
->priv
->socket
, address
,
159 static gboolean
g_socket_connection_connect_callback (GSocket
*socket
,
160 GIOCondition condition
,
164 * g_socket_connection_connect_async:
165 * @connection: a #GSocketConnection
166 * @address: a #GSocketAddress specifying the remote address.
167 * @cancellable: (allow-none): a %GCancellable or %NULL
168 * @callback: (scope async): a #GAsyncReadyCallback
169 * @user_data: (closure): user data for the callback
171 * Asynchronously connect @connection to the specified remote address.
173 * This clears the #GSocket:blocking flag on @connection's underlying
174 * socket if it is currently set.
176 * Use g_socket_connection_connect_finish() to retrieve the result.
181 g_socket_connection_connect_async (GSocketConnection
*connection
,
182 GSocketAddress
*address
,
183 GCancellable
*cancellable
,
184 GAsyncReadyCallback callback
,
187 GSimpleAsyncResult
*simple
;
188 GError
*tmp_error
= NULL
;
190 g_return_if_fail (G_IS_SOCKET_CONNECTION (connection
));
191 g_return_if_fail (G_IS_SOCKET_ADDRESS (address
));
193 simple
= g_simple_async_result_new (G_OBJECT (connection
),
195 g_socket_connection_connect_async
);
197 g_socket_set_blocking (connection
->priv
->socket
, FALSE
);
199 if (g_socket_connect (connection
->priv
->socket
, address
,
200 cancellable
, &tmp_error
))
202 g_simple_async_result_set_op_res_gboolean (simple
, TRUE
);
203 g_simple_async_result_complete_in_idle (simple
);
205 else if (g_error_matches (tmp_error
, G_IO_ERROR
, G_IO_ERROR_PENDING
))
209 g_error_free (tmp_error
);
210 source
= g_socket_create_source (connection
->priv
->socket
,
211 G_IO_OUT
, cancellable
);
212 g_source_set_callback (source
,
213 (GSourceFunc
) g_socket_connection_connect_callback
,
215 g_source_attach (source
, g_main_context_get_thread_default ());
216 g_source_unref (source
);
220 g_simple_async_result_take_error (simple
, tmp_error
);
221 g_simple_async_result_complete_in_idle (simple
);
226 g_socket_connection_connect_callback (GSocket
*socket
,
227 GIOCondition condition
,
230 GSimpleAsyncResult
*simple
= user_data
;
231 GSocketConnection
*connection
;
232 GError
*error
= NULL
;
234 connection
= G_SOCKET_CONNECTION (g_async_result_get_source_object (G_ASYNC_RESULT (simple
)));
235 g_object_unref (connection
);
237 if (g_socket_check_connect_result (connection
->priv
->socket
, &error
))
238 g_simple_async_result_set_op_res_gboolean (simple
, TRUE
);
240 g_simple_async_result_take_error (simple
, error
);
242 g_simple_async_result_complete (simple
);
243 g_object_unref (simple
);
248 * g_socket_connection_connect_finish:
249 * @connection: a #GSocketConnection
250 * @result: the #GAsyncResult
251 * @error: #GError for error reporting, or %NULL to ignore.
253 * Gets the result of a g_socket_connection_connect_async() call.
255 * Returns: %TRUE if the connection succeeded, %FALSE on error
260 g_socket_connection_connect_finish (GSocketConnection
*connection
,
261 GAsyncResult
*result
,
264 GSimpleAsyncResult
*simple
;
266 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection
), FALSE
);
267 g_return_val_if_fail (g_simple_async_result_is_valid (result
, G_OBJECT (connection
), g_socket_connection_connect_async
), FALSE
);
269 simple
= G_SIMPLE_ASYNC_RESULT (result
);
270 if (g_simple_async_result_propagate_error (simple
, error
))
276 * g_socket_connection_get_socket:
277 * @connection: a #GSocketConnection
279 * Gets the underlying #GSocket object of the connection.
280 * This can be useful if you want to do something unusual on it
281 * not supported by the #GSocketConnection APIs.
283 * Returns: (transfer none): a #GSocketAddress or %NULL on error.
288 g_socket_connection_get_socket (GSocketConnection
*connection
)
290 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection
), NULL
);
292 return connection
->priv
->socket
;
296 * g_socket_connection_get_local_address:
297 * @connection: a #GSocketConnection
298 * @error: #GError for error reporting, or %NULL to ignore.
300 * Try to get the local address of a socket connection.
302 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
303 * Free the returned object with g_object_unref().
308 g_socket_connection_get_local_address (GSocketConnection
*connection
,
311 return g_socket_get_local_address (connection
->priv
->socket
, error
);
315 * g_socket_connection_get_remote_address:
316 * @connection: a #GSocketConnection
317 * @error: #GError for error reporting, or %NULL to ignore.
319 * Try to get the remote address of a socket connection.
321 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
322 * Free the returned object with g_object_unref().
327 g_socket_connection_get_remote_address (GSocketConnection
*connection
,
330 return g_socket_get_remote_address (connection
->priv
->socket
, error
);
334 g_socket_connection_get_property (GObject
*object
,
339 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
344 g_value_set_object (value
, connection
->priv
->socket
);
348 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
353 g_socket_connection_set_property (GObject
*object
,
358 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
363 connection
->priv
->socket
= G_SOCKET (g_value_dup_object (value
));
367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
372 g_socket_connection_constructed (GObject
*object
)
374 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
376 g_assert (connection
->priv
->socket
!= NULL
);
380 g_socket_connection_dispose (GObject
*object
)
382 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
384 connection
->priv
->in_dispose
= TRUE
;
386 G_OBJECT_CLASS (g_socket_connection_parent_class
)
389 connection
->priv
->in_dispose
= FALSE
;
393 g_socket_connection_finalize (GObject
*object
)
395 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
397 if (connection
->priv
->input_stream
)
398 g_object_unref (connection
->priv
->input_stream
);
400 if (connection
->priv
->output_stream
)
401 g_object_unref (connection
->priv
->output_stream
);
403 g_object_unref (connection
->priv
->socket
);
405 G_OBJECT_CLASS (g_socket_connection_parent_class
)
410 g_socket_connection_class_init (GSocketConnectionClass
*klass
)
412 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
413 GIOStreamClass
*stream_class
= G_IO_STREAM_CLASS (klass
);
415 g_type_class_add_private (klass
, sizeof (GSocketConnectionPrivate
));
417 gobject_class
->set_property
= g_socket_connection_set_property
;
418 gobject_class
->get_property
= g_socket_connection_get_property
;
419 gobject_class
->constructed
= g_socket_connection_constructed
;
420 gobject_class
->finalize
= g_socket_connection_finalize
;
421 gobject_class
->dispose
= g_socket_connection_dispose
;
423 stream_class
->get_input_stream
= g_socket_connection_get_input_stream
;
424 stream_class
->get_output_stream
= g_socket_connection_get_output_stream
;
425 stream_class
->close_fn
= g_socket_connection_close
;
426 stream_class
->close_async
= g_socket_connection_close_async
;
427 stream_class
->close_finish
= g_socket_connection_close_finish
;
429 g_object_class_install_property (gobject_class
,
431 g_param_spec_object ("socket",
433 P_("The underlying GSocket"),
435 G_PARAM_CONSTRUCT_ONLY
|
437 G_PARAM_STATIC_STRINGS
));
441 g_socket_connection_init (GSocketConnection
*connection
)
443 connection
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (connection
,
444 G_TYPE_SOCKET_CONNECTION
,
445 GSocketConnectionPrivate
);
449 g_socket_connection_close (GIOStream
*stream
,
450 GCancellable
*cancellable
,
453 GSocketConnection
*connection
= G_SOCKET_CONNECTION (stream
);
455 if (connection
->priv
->output_stream
)
456 g_output_stream_close (connection
->priv
->output_stream
,
458 if (connection
->priv
->input_stream
)
459 g_input_stream_close (connection
->priv
->input_stream
,
462 /* Don't close the underlying socket if this is being called
463 * as part of dispose(); when destroying the GSocketConnection,
464 * we only want to close the socket if we're holding the last
465 * reference on it, and in that case it will close itself when
466 * we unref it in finalize().
468 if (connection
->priv
->in_dispose
)
471 return g_socket_close (connection
->priv
->socket
, error
);
476 g_socket_connection_close_async (GIOStream
*stream
,
478 GCancellable
*cancellable
,
479 GAsyncReadyCallback callback
,
482 GSimpleAsyncResult
*res
;
483 GIOStreamClass
*class;
486 class = G_IO_STREAM_GET_CLASS (stream
);
488 /* socket close is not blocked, just do it! */
490 if (class->close_fn
&&
491 !class->close_fn (stream
, cancellable
, &error
))
493 g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream
),
499 res
= g_simple_async_result_new (G_OBJECT (stream
),
502 g_socket_connection_close_async
);
503 g_simple_async_result_complete_in_idle (res
);
504 g_object_unref (res
);
508 g_socket_connection_close_finish (GIOStream
*stream
,
509 GAsyncResult
*result
,
516 GSocketFamily socket_family
;
517 GSocketType socket_type
;
519 GType implementation
;
523 connection_factory_hash (gconstpointer key
)
525 const ConnectionFactory
*factory
= key
;
528 h
= factory
->socket_family
^ (factory
->socket_type
<< 4) ^ (factory
->protocol
<< 8);
529 /* This is likely to be small, so spread over whole
530 hash space to get some distribution */
531 h
= h
^ (h
<< 8) ^ (h
<< 16) ^ (h
<< 24);
537 connection_factory_equal (gconstpointer _a
,
540 const ConnectionFactory
*a
= _a
;
541 const ConnectionFactory
*b
= _b
;
543 if (a
->socket_family
!= b
->socket_family
)
546 if (a
->socket_type
!= b
->socket_type
)
549 if (a
->protocol
!= b
->protocol
)
555 static GHashTable
*connection_factories
= NULL
;
556 G_LOCK_DEFINE_STATIC(connection_factories
);
559 * g_socket_connection_factory_register_type:
560 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
561 * @family: a #GSocketFamily
562 * @type: a #GSocketType
563 * @protocol: a protocol id
565 * Looks up the #GType to be used when creating socket connections on
566 * sockets with the specified @family, @type and @protocol.
568 * If no type is registered, the #GSocketConnection base type is returned.
573 g_socket_connection_factory_register_type (GType g_type
,
574 GSocketFamily family
,
578 ConnectionFactory
*factory
;
580 g_return_if_fail (g_type_is_a (g_type
, G_TYPE_SOCKET_CONNECTION
));
582 G_LOCK (connection_factories
);
584 if (connection_factories
== NULL
)
585 connection_factories
= g_hash_table_new_full (connection_factory_hash
,
586 connection_factory_equal
,
587 (GDestroyNotify
)g_free
,
590 factory
= g_new0 (ConnectionFactory
, 1);
591 factory
->socket_family
= family
;
592 factory
->socket_type
= type
;
593 factory
->protocol
= protocol
;
594 factory
->implementation
= g_type
;
596 g_hash_table_insert (connection_factories
,
599 G_UNLOCK (connection_factories
);
603 init_builtin_types (void)
605 volatile GType a_type
;
607 a_type
= g_unix_connection_get_type ();
609 a_type
= g_tcp_connection_get_type ();
610 (a_type
); /* To avoid -Wunused-but-set-variable */
614 * g_socket_connection_factory_lookup_type:
615 * @family: a #GSocketFamily
616 * @type: a #GSocketType
617 * @protocol_id: a protocol id
619 * Looks up the #GType to be used when creating socket connections on
620 * sockets with the specified @family, @type and @protocol_id.
622 * If no type is registered, the #GSocketConnection base type is returned.
629 g_socket_connection_factory_lookup_type (GSocketFamily family
,
633 ConnectionFactory
*factory
, key
;
636 init_builtin_types ();
638 G_LOCK (connection_factories
);
640 g_type
= G_TYPE_SOCKET_CONNECTION
;
642 if (connection_factories
)
644 key
.socket_family
= family
;
645 key
.socket_type
= type
;
646 key
.protocol
= protocol_id
;
648 factory
= g_hash_table_lookup (connection_factories
, &key
);
650 g_type
= factory
->implementation
;
653 G_UNLOCK (connection_factories
);
659 * g_socket_connection_factory_create_connection:
660 * @socket: a #GSocket
662 * Creates a #GSocketConnection subclass of the right type for
665 * Returns: (transfer full): a #GSocketConnection
670 g_socket_connection_factory_create_connection (GSocket
*socket
)
674 type
= g_socket_connection_factory_lookup_type (g_socket_get_family (socket
),
675 g_socket_get_socket_type (socket
),
676 g_socket_get_protocol (socket
));
677 return g_object_new (type
, "socket", socket
, NULL
);