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