gio/: fully remove gioalias hacks
[platform/upstream/glib.git] / gio / gsocketconnection.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima
4  *           © 2008 codethink
5  * Copyright © 2009 Red Hat, Inc
6  *
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.
11  *
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.
16  *
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.
21  *
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>
26  */
27
28 #include "config.h"
29
30 #include "gsocketconnection.h"
31
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"
38 #include "glibintl.h"
39
40
41 /**
42  * SECTION:gsocketconnection
43  * @short_description: A socket connection
44  * @include: gio/gio.h
45  * @see_also: #GIOStream, #GSocketClient, #GSocketListener
46  *
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.
50  *
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.
54  *
55  * Chosing 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().
59  *
60  * Since: 2.22
61  */
62
63 G_DEFINE_TYPE (GSocketConnection,
64                g_socket_connection, G_TYPE_IO_STREAM);
65
66 enum
67 {
68   PROP_NONE,
69   PROP_SOCKET,
70 };
71
72 struct _GSocketConnectionPrivate
73 {
74   GSocket       *socket;
75   GInputStream  *input_stream;
76   GOutputStream *output_stream;
77
78   gboolean       in_dispose;
79 };
80
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);
92
93 static GInputStream *
94 g_socket_connection_get_input_stream (GIOStream *io_stream)
95 {
96   GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
97
98   if (connection->priv->input_stream == NULL)
99     connection->priv->input_stream = (GInputStream *)
100       _g_socket_input_stream_new (connection->priv->socket);
101
102   return connection->priv->input_stream;
103 }
104
105 static GOutputStream *
106 g_socket_connection_get_output_stream (GIOStream *io_stream)
107 {
108   GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
109
110   if (connection->priv->output_stream == NULL)
111     connection->priv->output_stream = (GOutputStream *)
112       _g_socket_output_stream_new (connection->priv->socket);
113
114   return connection->priv->output_stream;
115 }
116
117 /**
118  * g_socket_connection_get_socket:
119  * @connection: a #GSocketConnection
120  *
121  * Gets the underlying #GSocket object of the connection.
122  * This can be useful if you want to do something unusual on it
123  * not supported by the #GSocketConnection APIs.
124  *
125  * Returns: a #GSocketAddress or %NULL on error.
126  *
127  * Since: 2.22
128  */
129 GSocket *
130 g_socket_connection_get_socket (GSocketConnection *connection)
131 {
132   g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
133
134   return connection->priv->socket;
135 }
136
137 /**
138  * g_socket_connection_get_local_address:
139  * @connection: a #GSocketConnection
140  * @error: #GError for error reporting, or %NULL to ignore.
141  *
142  * Try to get the local address of a socket connection.
143  *
144  * Returns: a #GSocketAddress or %NULL on error.
145  *     Free the returned object with g_object_unref().
146  *
147  * Since: 2.22
148  */
149 GSocketAddress *
150 g_socket_connection_get_local_address (GSocketConnection  *connection,
151                                        GError            **error)
152 {
153   return g_socket_get_local_address (connection->priv->socket, error);
154 }
155
156 /**
157  * g_socket_connection_get_remote_address:
158  * @connection: a #GSocketConnection
159  * @error: #GError for error reporting, or %NULL to ignore.
160  *
161  * Try to get the remote address of a socket connection.
162  *
163  * Returns: a #GSocketAddress or %NULL on error.
164  *     Free the returned object with g_object_unref().
165  *
166  * Since: 2.22
167  */
168 GSocketAddress *
169 g_socket_connection_get_remote_address (GSocketConnection  *connection,
170                                         GError            **error)
171 {
172   return g_socket_get_remote_address (connection->priv->socket, error);
173 }
174
175 static void
176 g_socket_connection_get_property (GObject    *object,
177                                   guint       prop_id,
178                                   GValue     *value,
179                                   GParamSpec *pspec)
180 {
181   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
182
183   switch (prop_id)
184     {
185      case PROP_SOCKET:
186       g_value_set_object (value, connection->priv->socket);
187       break;
188
189      default:
190       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191     }
192 }
193
194 static void
195 g_socket_connection_set_property (GObject      *object,
196                                   guint         prop_id,
197                                   const GValue *value,
198                                   GParamSpec   *pspec)
199 {
200   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
201
202   switch (prop_id)
203     {
204      case PROP_SOCKET:
205       connection->priv->socket = G_SOCKET (g_value_dup_object (value));
206       break;
207
208      default:
209       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
210     }
211 }
212
213 static void
214 g_socket_connection_constructed (GObject *object)
215 {
216   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
217
218   g_assert (connection->priv->socket != NULL);
219 }
220
221 static void
222 g_socket_connection_dispose (GObject *object)
223 {
224   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
225
226   connection->priv->in_dispose = TRUE;
227
228   G_OBJECT_CLASS (g_socket_connection_parent_class)
229     ->dispose (object);
230
231   connection->priv->in_dispose = FALSE;
232 }
233
234 static void
235 g_socket_connection_finalize (GObject *object)
236 {
237   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
238
239   if (connection->priv->input_stream)
240     g_object_unref (connection->priv->input_stream);
241
242   if (connection->priv->output_stream)
243     g_object_unref (connection->priv->output_stream);
244
245   g_object_unref (connection->priv->socket);
246
247   G_OBJECT_CLASS (g_socket_connection_parent_class)
248     ->finalize (object);
249 }
250
251 static void
252 g_socket_connection_class_init (GSocketConnectionClass *klass)
253 {
254   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
255   GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
256
257   g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
258
259   gobject_class->set_property = g_socket_connection_set_property;
260   gobject_class->get_property = g_socket_connection_get_property;
261   gobject_class->constructed = g_socket_connection_constructed;
262   gobject_class->finalize = g_socket_connection_finalize;
263   gobject_class->dispose = g_socket_connection_dispose;
264
265   stream_class->get_input_stream = g_socket_connection_get_input_stream;
266   stream_class->get_output_stream = g_socket_connection_get_output_stream;
267   stream_class->close_fn = g_socket_connection_close;
268   stream_class->close_async = g_socket_connection_close_async;
269   stream_class->close_finish = g_socket_connection_close_finish;
270
271   g_object_class_install_property (gobject_class,
272                                    PROP_SOCKET,
273                                    g_param_spec_object ("socket",
274                                                         P_("Socket"),
275                                                         P_("The underlying GSocket"),
276                                                         G_TYPE_SOCKET,
277                                                         G_PARAM_CONSTRUCT_ONLY |
278                                                         G_PARAM_READWRITE |
279                                                         G_PARAM_STATIC_STRINGS));
280 }
281
282 static void
283 g_socket_connection_init (GSocketConnection *connection)
284 {
285   connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
286                                                   G_TYPE_SOCKET_CONNECTION,
287                                                   GSocketConnectionPrivate);
288 }
289
290 static gboolean
291 g_socket_connection_close (GIOStream     *stream,
292                            GCancellable  *cancellable,
293                            GError       **error)
294 {
295   GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
296
297   if (connection->priv->output_stream)
298     g_output_stream_close (connection->priv->output_stream,
299                            cancellable, NULL);
300   if (connection->priv->input_stream)
301     g_input_stream_close (connection->priv->input_stream,
302                           cancellable, NULL);
303
304   /* Don't close the underlying socket if this is being called
305    * as part of dispose(); when destroying the GSocketConnection,
306    * we only want to close the socket if we're holding the last
307    * reference on it, and in that case it will close itself when
308    * we unref it in finalize().
309    */
310   if (connection->priv->in_dispose)
311     return TRUE;
312
313   return g_socket_close (connection->priv->socket, error);
314 }
315
316
317 static void
318 g_socket_connection_close_async (GIOStream           *stream,
319                                  int                  io_priority,
320                                  GCancellable        *cancellable,
321                                  GAsyncReadyCallback  callback,
322                                  gpointer             user_data)
323 {
324   GSimpleAsyncResult *res;
325   GIOStreamClass *class;
326   GError *error;
327
328   class = G_IO_STREAM_GET_CLASS (stream);
329
330   /* socket close is not blocked, just do it! */
331   error = NULL;
332   if (class->close_fn &&
333       !class->close_fn (stream, cancellable, &error))
334     {
335       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
336                                             callback, user_data,
337                                             error);
338       g_error_free (error);
339       return;
340     }
341
342   res = g_simple_async_result_new (G_OBJECT (stream),
343                                    callback,
344                                    user_data,
345                                    g_socket_connection_close_async);
346   g_simple_async_result_complete_in_idle (res);
347   g_object_unref (res);
348 }
349
350 static gboolean
351 g_socket_connection_close_finish (GIOStream     *stream,
352                                   GAsyncResult  *result,
353                                   GError       **error)
354 {
355   return TRUE;
356 }
357
358 typedef struct {
359   GSocketFamily socket_family;
360   GSocketType socket_type;
361   int protocol;
362   GType implementation;
363 } ConnectionFactory;
364
365 static guint
366 connection_factory_hash (gconstpointer key)
367 {
368   const ConnectionFactory *factory = key;
369   guint h;
370
371   h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
372   /* This is likely to be small, so spread over whole
373      hash space to get some distribution */
374   h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
375
376   return h;
377 }
378
379 static gboolean
380 connection_factory_equal (gconstpointer _a,
381                           gconstpointer _b)
382 {
383   const ConnectionFactory *a = _a;
384   const ConnectionFactory *b = _b;
385
386   if (a->socket_family != b->socket_family)
387     return FALSE;
388
389   if (a->socket_type != b->socket_type)
390     return FALSE;
391
392   if (a->protocol != b->protocol)
393     return FALSE;
394
395   return TRUE;
396 }
397
398 static GHashTable *connection_factories = NULL;
399 G_LOCK_DEFINE_STATIC(connection_factories);
400
401 /**
402  * g_socket_connection_factory_register_type:
403  * @g_type: a #GType, inheriting from %G_TYPE_SOCKET_CONNECTION
404  * @family: a #GSocketFamily
405  * @type: a #GSocketType
406  * @protocol: a protocol id
407  *
408  * Looks up the #GType to be used when creating socket connections on
409  * sockets with the specified @family,@type and @protocol.
410  *
411  * If no type is registered, the #GSocketConnection base type is returned.
412  *
413  * Since: 2.22
414  */
415 void
416 g_socket_connection_factory_register_type (GType         g_type,
417                                            GSocketFamily family,
418                                            GSocketType   type,
419                                            gint          protocol)
420 {
421   ConnectionFactory *factory;
422
423   g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
424
425   G_LOCK (connection_factories);
426
427   if (connection_factories == NULL)
428     connection_factories = g_hash_table_new_full (connection_factory_hash,
429                                                   connection_factory_equal,
430                                                   (GDestroyNotify)g_free,
431                                                   NULL);
432
433   factory = g_new0 (ConnectionFactory, 1);
434   factory->socket_family = family;
435   factory->socket_type = type;
436   factory->protocol = protocol;
437   factory->implementation = g_type;
438
439   g_hash_table_insert (connection_factories,
440                        factory, factory);
441
442   G_UNLOCK (connection_factories);
443 }
444
445 static void
446 init_builtin_types (void)
447 {
448   volatile GType a_type;
449 #ifndef G_OS_WIN32
450   a_type = g_unix_connection_get_type ();
451 #endif
452   a_type = g_tcp_connection_get_type ();
453 }
454
455 /**
456  * g_socket_connection_factory_lookup_type:
457  * @family: a #GSocketFamily
458  * @type: a #GSocketType
459  * @protocol_id: a protocol id
460  *
461  * Looks up the #GType to be used when creating socket connections on
462  * sockets with the specified @family,@type and @protocol_id.
463  *
464  * If no type is registered, the #GSocketConnection base type is returned.
465  *
466  * Returns: a #GType
467  *
468  * Since: 2.22
469  */
470 GType
471 g_socket_connection_factory_lookup_type (GSocketFamily family,
472                                          GSocketType   type,
473                                          gint          protocol_id)
474 {
475   ConnectionFactory *factory, key;
476   GType g_type;
477
478   init_builtin_types ();
479
480   G_LOCK (connection_factories);
481
482   g_type = G_TYPE_SOCKET_CONNECTION;
483
484   if (connection_factories)
485     {
486       key.socket_family = family;
487       key.socket_type = type;
488       key.protocol = protocol_id;
489
490       factory = g_hash_table_lookup (connection_factories, &key);
491       if (factory)
492         g_type = factory->implementation;
493     }
494
495   G_UNLOCK (connection_factories);
496
497   return g_type;
498 }
499
500 /**
501  * g_socket_connection_factory_create_connection:
502  * @socket: a #GSocket
503  *
504  * Creates a #GSocketConnection subclass of the right type for
505  * @socket.
506  *
507  * Returns: a #GSocketConnection
508  *
509  * Since: 2.22
510  */
511 GSocketConnection *
512 g_socket_connection_factory_create_connection (GSocket *socket)
513 {
514   GType type;
515
516   type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
517                                                   g_socket_get_socket_type (socket),
518                                                   g_socket_get_protocol (socket));
519   return g_object_new (type, "socket", socket, NULL);
520 }