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_get_socket:
118 * @connection: a #GSocketConnection
120 * Gets the underlying #GSocket object of the connection.
121 * This can be useful if you want to do something unusual on it
122 * not supported by the #GSocketConnection APIs.
124 * Returns: (transfer none): a #GSocketAddress or %NULL on error.
129 g_socket_connection_get_socket (GSocketConnection
*connection
)
131 g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection
), NULL
);
133 return connection
->priv
->socket
;
137 * g_socket_connection_get_local_address:
138 * @connection: a #GSocketConnection
139 * @error: #GError for error reporting, or %NULL to ignore.
141 * Try to get the local address of a socket connection.
143 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
144 * Free the returned object with g_object_unref().
149 g_socket_connection_get_local_address (GSocketConnection
*connection
,
152 return g_socket_get_local_address (connection
->priv
->socket
, error
);
156 * g_socket_connection_get_remote_address:
157 * @connection: a #GSocketConnection
158 * @error: #GError for error reporting, or %NULL to ignore.
160 * Try to get the remote address of a socket connection.
162 * Returns: (transfer full): a #GSocketAddress or %NULL on error.
163 * Free the returned object with g_object_unref().
168 g_socket_connection_get_remote_address (GSocketConnection
*connection
,
171 return g_socket_get_remote_address (connection
->priv
->socket
, error
);
175 g_socket_connection_get_property (GObject
*object
,
180 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
185 g_value_set_object (value
, connection
->priv
->socket
);
189 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
194 g_socket_connection_set_property (GObject
*object
,
199 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
204 connection
->priv
->socket
= G_SOCKET (g_value_dup_object (value
));
208 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
213 g_socket_connection_constructed (GObject
*object
)
215 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
217 g_assert (connection
->priv
->socket
!= NULL
);
221 g_socket_connection_dispose (GObject
*object
)
223 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
225 connection
->priv
->in_dispose
= TRUE
;
227 G_OBJECT_CLASS (g_socket_connection_parent_class
)
230 connection
->priv
->in_dispose
= FALSE
;
234 g_socket_connection_finalize (GObject
*object
)
236 GSocketConnection
*connection
= G_SOCKET_CONNECTION (object
);
238 if (connection
->priv
->input_stream
)
239 g_object_unref (connection
->priv
->input_stream
);
241 if (connection
->priv
->output_stream
)
242 g_object_unref (connection
->priv
->output_stream
);
244 g_object_unref (connection
->priv
->socket
);
246 G_OBJECT_CLASS (g_socket_connection_parent_class
)
251 g_socket_connection_class_init (GSocketConnectionClass
*klass
)
253 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
254 GIOStreamClass
*stream_class
= G_IO_STREAM_CLASS (klass
);
256 g_type_class_add_private (klass
, sizeof (GSocketConnectionPrivate
));
258 gobject_class
->set_property
= g_socket_connection_set_property
;
259 gobject_class
->get_property
= g_socket_connection_get_property
;
260 gobject_class
->constructed
= g_socket_connection_constructed
;
261 gobject_class
->finalize
= g_socket_connection_finalize
;
262 gobject_class
->dispose
= g_socket_connection_dispose
;
264 stream_class
->get_input_stream
= g_socket_connection_get_input_stream
;
265 stream_class
->get_output_stream
= g_socket_connection_get_output_stream
;
266 stream_class
->close_fn
= g_socket_connection_close
;
267 stream_class
->close_async
= g_socket_connection_close_async
;
268 stream_class
->close_finish
= g_socket_connection_close_finish
;
270 g_object_class_install_property (gobject_class
,
272 g_param_spec_object ("socket",
274 P_("The underlying GSocket"),
276 G_PARAM_CONSTRUCT_ONLY
|
278 G_PARAM_STATIC_STRINGS
));
282 g_socket_connection_init (GSocketConnection
*connection
)
284 connection
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (connection
,
285 G_TYPE_SOCKET_CONNECTION
,
286 GSocketConnectionPrivate
);
290 g_socket_connection_close (GIOStream
*stream
,
291 GCancellable
*cancellable
,
294 GSocketConnection
*connection
= G_SOCKET_CONNECTION (stream
);
296 if (connection
->priv
->output_stream
)
297 g_output_stream_close (connection
->priv
->output_stream
,
299 if (connection
->priv
->input_stream
)
300 g_input_stream_close (connection
->priv
->input_stream
,
303 /* Don't close the underlying socket if this is being called
304 * as part of dispose(); when destroying the GSocketConnection,
305 * we only want to close the socket if we're holding the last
306 * reference on it, and in that case it will close itself when
307 * we unref it in finalize().
309 if (connection
->priv
->in_dispose
)
312 return g_socket_close (connection
->priv
->socket
, error
);
317 g_socket_connection_close_async (GIOStream
*stream
,
319 GCancellable
*cancellable
,
320 GAsyncReadyCallback callback
,
323 GSimpleAsyncResult
*res
;
324 GIOStreamClass
*class;
327 class = G_IO_STREAM_GET_CLASS (stream
);
329 /* socket close is not blocked, just do it! */
331 if (class->close_fn
&&
332 !class->close_fn (stream
, cancellable
, &error
))
334 g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream
),
340 res
= g_simple_async_result_new (G_OBJECT (stream
),
343 g_socket_connection_close_async
);
344 g_simple_async_result_complete_in_idle (res
);
345 g_object_unref (res
);
349 g_socket_connection_close_finish (GIOStream
*stream
,
350 GAsyncResult
*result
,
357 GSocketFamily socket_family
;
358 GSocketType socket_type
;
360 GType implementation
;
364 connection_factory_hash (gconstpointer key
)
366 const ConnectionFactory
*factory
= key
;
369 h
= factory
->socket_family
^ (factory
->socket_type
<< 4) ^ (factory
->protocol
<< 8);
370 /* This is likely to be small, so spread over whole
371 hash space to get some distribution */
372 h
= h
^ (h
<< 8) ^ (h
<< 16) ^ (h
<< 24);
378 connection_factory_equal (gconstpointer _a
,
381 const ConnectionFactory
*a
= _a
;
382 const ConnectionFactory
*b
= _b
;
384 if (a
->socket_family
!= b
->socket_family
)
387 if (a
->socket_type
!= b
->socket_type
)
390 if (a
->protocol
!= b
->protocol
)
396 static GHashTable
*connection_factories
= NULL
;
397 G_LOCK_DEFINE_STATIC(connection_factories
);
400 * g_socket_connection_factory_register_type:
401 * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
402 * @family: a #GSocketFamily
403 * @type: a #GSocketType
404 * @protocol: a protocol id
406 * Looks up the #GType to be used when creating socket connections on
407 * sockets with the specified @family, @type and @protocol.
409 * If no type is registered, the #GSocketConnection base type is returned.
414 g_socket_connection_factory_register_type (GType g_type
,
415 GSocketFamily family
,
419 ConnectionFactory
*factory
;
421 g_return_if_fail (g_type_is_a (g_type
, G_TYPE_SOCKET_CONNECTION
));
423 G_LOCK (connection_factories
);
425 if (connection_factories
== NULL
)
426 connection_factories
= g_hash_table_new_full (connection_factory_hash
,
427 connection_factory_equal
,
428 (GDestroyNotify
)g_free
,
431 factory
= g_new0 (ConnectionFactory
, 1);
432 factory
->socket_family
= family
;
433 factory
->socket_type
= type
;
434 factory
->protocol
= protocol
;
435 factory
->implementation
= g_type
;
437 g_hash_table_insert (connection_factories
,
440 G_UNLOCK (connection_factories
);
444 init_builtin_types (void)
446 volatile GType a_type
;
448 a_type
= g_unix_connection_get_type ();
450 a_type
= g_tcp_connection_get_type ();
451 (a_type
); /* To avoid -Wunused-but-set-variable */
455 * g_socket_connection_factory_lookup_type:
456 * @family: a #GSocketFamily
457 * @type: a #GSocketType
458 * @protocol_id: a protocol id
460 * Looks up the #GType to be used when creating socket connections on
461 * sockets with the specified @family, @type and @protocol_id.
463 * If no type is registered, the #GSocketConnection base type is returned.
470 g_socket_connection_factory_lookup_type (GSocketFamily family
,
474 ConnectionFactory
*factory
, key
;
477 init_builtin_types ();
479 G_LOCK (connection_factories
);
481 g_type
= G_TYPE_SOCKET_CONNECTION
;
483 if (connection_factories
)
485 key
.socket_family
= family
;
486 key
.socket_type
= type
;
487 key
.protocol
= protocol_id
;
489 factory
= g_hash_table_lookup (connection_factories
, &key
);
491 g_type
= factory
->implementation
;
494 G_UNLOCK (connection_factories
);
500 * g_socket_connection_factory_create_connection:
501 * @socket: a #GSocket
503 * Creates a #GSocketConnection subclass of the right type for
506 * Returns: (transfer full): a #GSocketConnection
511 g_socket_connection_factory_create_connection (GSocket
*socket
)
515 type
= g_socket_connection_factory_lookup_type (g_socket_get_family (socket
),
516 g_socket_get_socket_type (socket
),
517 g_socket_get_protocol (socket
));
518 return g_object_new (type
, "socket", socket
, NULL
);