GSettings: deprecate 'schema' property
[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  * 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().
59  *
60  * Since: 2.22
61  */
62
63 G_DEFINE_TYPE (GSocketConnection, g_socket_connection, G_TYPE_IO_STREAM);
64
65 enum
66 {
67   PROP_NONE,
68   PROP_SOCKET,
69 };
70
71 struct _GSocketConnectionPrivate
72 {
73   GSocket       *socket;
74   GInputStream  *input_stream;
75   GOutputStream *output_stream;
76
77   gboolean       in_dispose;
78 };
79
80 static gboolean g_socket_connection_close         (GIOStream            *stream,
81                                                    GCancellable         *cancellable,
82                                                    GError              **error);
83 static void     g_socket_connection_close_async   (GIOStream            *stream,
84                                                    int                   io_priority,
85                                                    GCancellable         *cancellable,
86                                                    GAsyncReadyCallback   callback,
87                                                    gpointer              user_data);
88 static gboolean g_socket_connection_close_finish  (GIOStream            *stream,
89                                                    GAsyncResult         *result,
90                                                    GError              **error);
91
92 static GInputStream *
93 g_socket_connection_get_input_stream (GIOStream *io_stream)
94 {
95   GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
96
97   if (connection->priv->input_stream == NULL)
98     connection->priv->input_stream = (GInputStream *)
99       _g_socket_input_stream_new (connection->priv->socket);
100
101   return connection->priv->input_stream;
102 }
103
104 static GOutputStream *
105 g_socket_connection_get_output_stream (GIOStream *io_stream)
106 {
107   GSocketConnection *connection = G_SOCKET_CONNECTION (io_stream);
108
109   if (connection->priv->output_stream == NULL)
110     connection->priv->output_stream = (GOutputStream *)
111       _g_socket_output_stream_new (connection->priv->socket);
112
113   return connection->priv->output_stream;
114 }
115
116 /**
117  * g_socket_connection_get_socket:
118  * @connection: a #GSocketConnection
119  *
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.
123  *
124  * Returns: (transfer none): a #GSocketAddress or %NULL on error.
125  *
126  * Since: 2.22
127  */
128 GSocket *
129 g_socket_connection_get_socket (GSocketConnection *connection)
130 {
131   g_return_val_if_fail (G_IS_SOCKET_CONNECTION (connection), NULL);
132
133   return connection->priv->socket;
134 }
135
136 /**
137  * g_socket_connection_get_local_address:
138  * @connection: a #GSocketConnection
139  * @error: #GError for error reporting, or %NULL to ignore.
140  *
141  * Try to get the local address of a socket connection.
142  *
143  * Returns: (transfer full): a #GSocketAddress or %NULL on error.
144  *     Free the returned object with g_object_unref().
145  *
146  * Since: 2.22
147  */
148 GSocketAddress *
149 g_socket_connection_get_local_address (GSocketConnection  *connection,
150                                        GError            **error)
151 {
152   return g_socket_get_local_address (connection->priv->socket, error);
153 }
154
155 /**
156  * g_socket_connection_get_remote_address:
157  * @connection: a #GSocketConnection
158  * @error: #GError for error reporting, or %NULL to ignore.
159  *
160  * Try to get the remote address of a socket connection.
161  *
162  * Returns: (transfer full): a #GSocketAddress or %NULL on error.
163  *     Free the returned object with g_object_unref().
164  *
165  * Since: 2.22
166  */
167 GSocketAddress *
168 g_socket_connection_get_remote_address (GSocketConnection  *connection,
169                                         GError            **error)
170 {
171   return g_socket_get_remote_address (connection->priv->socket, error);
172 }
173
174 static void
175 g_socket_connection_get_property (GObject    *object,
176                                   guint       prop_id,
177                                   GValue     *value,
178                                   GParamSpec *pspec)
179 {
180   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
181
182   switch (prop_id)
183     {
184      case PROP_SOCKET:
185       g_value_set_object (value, connection->priv->socket);
186       break;
187
188      default:
189       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
190     }
191 }
192
193 static void
194 g_socket_connection_set_property (GObject      *object,
195                                   guint         prop_id,
196                                   const GValue *value,
197                                   GParamSpec   *pspec)
198 {
199   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
200
201   switch (prop_id)
202     {
203      case PROP_SOCKET:
204       connection->priv->socket = G_SOCKET (g_value_dup_object (value));
205       break;
206
207      default:
208       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209     }
210 }
211
212 static void
213 g_socket_connection_constructed (GObject *object)
214 {
215   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
216
217   g_assert (connection->priv->socket != NULL);
218 }
219
220 static void
221 g_socket_connection_dispose (GObject *object)
222 {
223   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
224
225   connection->priv->in_dispose = TRUE;
226
227   G_OBJECT_CLASS (g_socket_connection_parent_class)
228     ->dispose (object);
229
230   connection->priv->in_dispose = FALSE;
231 }
232
233 static void
234 g_socket_connection_finalize (GObject *object)
235 {
236   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
237
238   if (connection->priv->input_stream)
239     g_object_unref (connection->priv->input_stream);
240
241   if (connection->priv->output_stream)
242     g_object_unref (connection->priv->output_stream);
243
244   g_object_unref (connection->priv->socket);
245
246   G_OBJECT_CLASS (g_socket_connection_parent_class)
247     ->finalize (object);
248 }
249
250 static void
251 g_socket_connection_class_init (GSocketConnectionClass *klass)
252 {
253   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
254   GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
255
256   g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
257
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;
263
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;
269
270   g_object_class_install_property (gobject_class,
271                                    PROP_SOCKET,
272                                    g_param_spec_object ("socket",
273                                                         P_("Socket"),
274                                                         P_("The underlying GSocket"),
275                                                         G_TYPE_SOCKET,
276                                                         G_PARAM_CONSTRUCT_ONLY |
277                                                         G_PARAM_READWRITE |
278                                                         G_PARAM_STATIC_STRINGS));
279 }
280
281 static void
282 g_socket_connection_init (GSocketConnection *connection)
283 {
284   connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
285                                                   G_TYPE_SOCKET_CONNECTION,
286                                                   GSocketConnectionPrivate);
287 }
288
289 static gboolean
290 g_socket_connection_close (GIOStream     *stream,
291                            GCancellable  *cancellable,
292                            GError       **error)
293 {
294   GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
295
296   if (connection->priv->output_stream)
297     g_output_stream_close (connection->priv->output_stream,
298                            cancellable, NULL);
299   if (connection->priv->input_stream)
300     g_input_stream_close (connection->priv->input_stream,
301                           cancellable, NULL);
302
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().
308    */
309   if (connection->priv->in_dispose)
310     return TRUE;
311
312   return g_socket_close (connection->priv->socket, error);
313 }
314
315
316 static void
317 g_socket_connection_close_async (GIOStream           *stream,
318                                  int                  io_priority,
319                                  GCancellable        *cancellable,
320                                  GAsyncReadyCallback  callback,
321                                  gpointer             user_data)
322 {
323   GSimpleAsyncResult *res;
324   GIOStreamClass *class;
325   GError *error;
326
327   class = G_IO_STREAM_GET_CLASS (stream);
328
329   /* socket close is not blocked, just do it! */
330   error = NULL;
331   if (class->close_fn &&
332       !class->close_fn (stream, cancellable, &error))
333     {
334       g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream),
335                                             callback, user_data,
336                                             error);
337       return;
338     }
339
340   res = g_simple_async_result_new (G_OBJECT (stream),
341                                    callback,
342                                    user_data,
343                                    g_socket_connection_close_async);
344   g_simple_async_result_complete_in_idle (res);
345   g_object_unref (res);
346 }
347
348 static gboolean
349 g_socket_connection_close_finish (GIOStream     *stream,
350                                   GAsyncResult  *result,
351                                   GError       **error)
352 {
353   return TRUE;
354 }
355
356 typedef struct {
357   GSocketFamily socket_family;
358   GSocketType socket_type;
359   int protocol;
360   GType implementation;
361 } ConnectionFactory;
362
363 static guint
364 connection_factory_hash (gconstpointer key)
365 {
366   const ConnectionFactory *factory = key;
367   guint h;
368
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);
373
374   return h;
375 }
376
377 static gboolean
378 connection_factory_equal (gconstpointer _a,
379                           gconstpointer _b)
380 {
381   const ConnectionFactory *a = _a;
382   const ConnectionFactory *b = _b;
383
384   if (a->socket_family != b->socket_family)
385     return FALSE;
386
387   if (a->socket_type != b->socket_type)
388     return FALSE;
389
390   if (a->protocol != b->protocol)
391     return FALSE;
392
393   return TRUE;
394 }
395
396 static GHashTable *connection_factories = NULL;
397 G_LOCK_DEFINE_STATIC(connection_factories);
398
399 /**
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
405  *
406  * Looks up the #GType to be used when creating socket connections on
407  * sockets with the specified @family, @type and @protocol.
408  *
409  * If no type is registered, the #GSocketConnection base type is returned.
410  *
411  * Since: 2.22
412  */
413 void
414 g_socket_connection_factory_register_type (GType         g_type,
415                                            GSocketFamily family,
416                                            GSocketType   type,
417                                            gint          protocol)
418 {
419   ConnectionFactory *factory;
420
421   g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
422
423   G_LOCK (connection_factories);
424
425   if (connection_factories == NULL)
426     connection_factories = g_hash_table_new_full (connection_factory_hash,
427                                                   connection_factory_equal,
428                                                   (GDestroyNotify)g_free,
429                                                   NULL);
430
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;
436
437   g_hash_table_insert (connection_factories,
438                        factory, factory);
439
440   G_UNLOCK (connection_factories);
441 }
442
443 static void
444 init_builtin_types (void)
445 {
446   volatile GType a_type;
447 #ifndef G_OS_WIN32
448   a_type = g_unix_connection_get_type ();
449 #endif
450   a_type = g_tcp_connection_get_type ();
451   (a_type); /* To avoid -Wunused-but-set-variable */
452 }
453
454 /**
455  * g_socket_connection_factory_lookup_type:
456  * @family: a #GSocketFamily
457  * @type: a #GSocketType
458  * @protocol_id: a protocol id
459  *
460  * Looks up the #GType to be used when creating socket connections on
461  * sockets with the specified @family, @type and @protocol_id.
462  *
463  * If no type is registered, the #GSocketConnection base type is returned.
464  *
465  * Returns: a #GType
466  *
467  * Since: 2.22
468  */
469 GType
470 g_socket_connection_factory_lookup_type (GSocketFamily family,
471                                          GSocketType   type,
472                                          gint          protocol_id)
473 {
474   ConnectionFactory *factory, key;
475   GType g_type;
476
477   init_builtin_types ();
478
479   G_LOCK (connection_factories);
480
481   g_type = G_TYPE_SOCKET_CONNECTION;
482
483   if (connection_factories)
484     {
485       key.socket_family = family;
486       key.socket_type = type;
487       key.protocol = protocol_id;
488
489       factory = g_hash_table_lookup (connection_factories, &key);
490       if (factory)
491         g_type = factory->implementation;
492     }
493
494   G_UNLOCK (connection_factories);
495
496   return g_type;
497 }
498
499 /**
500  * g_socket_connection_factory_create_connection:
501  * @socket: a #GSocket
502  *
503  * Creates a #GSocketConnection subclass of the right type for
504  * @socket.
505  *
506  * Returns: (transfer full): a #GSocketConnection
507  *
508  * Since: 2.22
509  */
510 GSocketConnection *
511 g_socket_connection_factory_create_connection (GSocket *socket)
512 {
513   GType type;
514
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);
519 }