Add support for abstract unix socket addresses
[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 depends
53  * on the type of the underlying socket that is in use. For instance, for a
54  * TCP/IP connection it will be a #GTcpConnection.
55  *
56  * Chosing what type of object to construct is done with the socket connection
57  * factory, and it is possible for 3rd parties to register custom socket connection
58  * types for specific combination of socket family/type/protocol using
59  * 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
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: 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: a #GSocketAddress or %NULL on error.
144  *
145  * Since: 2.22
146  **/
147 GSocketAddress *
148 g_socket_connection_get_local_address (GSocketConnection  *connection,
149                                        GError  **error)
150 {
151   return g_socket_get_local_address (connection->priv->socket, error);
152 }
153
154 /**
155  * g_socket_connection_get_remote_address:
156  * @connection: a #GSocketConnection.
157  * @error: #GError for error reporting, or %NULL to ignore.
158  *
159  * Try to get the remove address of a socket connection.
160  *
161  * Returns: a #GSocketAddress or %NULL on error.
162  *
163  * Since: 2.22
164  **/
165 GSocketAddress *
166 g_socket_connection_get_remote_address (GSocketConnection  *connection,
167                                         GError  **error)
168 {
169   return g_socket_get_remote_address (connection->priv->socket, error);
170 }
171
172 static void
173 g_socket_connection_get_property (GObject *object, guint prop_id,
174                                   GValue *value, GParamSpec *pspec)
175 {
176   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
177
178   switch (prop_id)
179     {
180      case PROP_SOCKET:
181       g_value_set_object (value, connection->priv->socket);
182       break;
183
184      default:
185       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
186     }
187 }
188
189 static void
190 g_socket_connection_set_property (GObject *object, guint prop_id,
191                                   const GValue *value, GParamSpec *pspec)
192 {
193   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
194
195   switch (prop_id)
196     {
197      case PROP_SOCKET:
198       connection->priv->socket = G_SOCKET (g_value_dup_object (value));
199       break;
200
201      default:
202       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
203     }
204 }
205
206 static void
207 g_socket_connection_constructed (GObject *object)
208 {
209   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
210
211   g_assert (connection->priv->socket != NULL);
212 }
213
214 static void
215 g_socket_connection_finalize (GObject *object)
216 {
217   GSocketConnection *connection = G_SOCKET_CONNECTION (object);
218
219   if (connection->priv->input_stream)
220     g_object_unref (connection->priv->input_stream);
221
222   if (connection->priv->output_stream)
223     g_object_unref (connection->priv->output_stream);
224
225   g_object_unref (connection->priv->socket);
226
227   G_OBJECT_CLASS (g_socket_connection_parent_class)
228     ->finalize (object);
229 }
230
231 static void
232 g_socket_connection_class_init (GSocketConnectionClass *klass)
233 {
234   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
235   GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
236
237   g_type_class_add_private (klass, sizeof (GSocketConnectionPrivate));
238
239   gobject_class->set_property = g_socket_connection_set_property;
240   gobject_class->get_property = g_socket_connection_get_property;
241   gobject_class->constructed = g_socket_connection_constructed;
242   gobject_class->finalize = g_socket_connection_finalize;
243
244   stream_class->get_input_stream = g_socket_connection_get_input_stream;
245   stream_class->get_output_stream = g_socket_connection_get_output_stream;
246   stream_class->close_fn = g_socket_connection_close;
247   stream_class->close_async = g_socket_connection_close_async;
248   stream_class->close_finish = g_socket_connection_close_finish;
249
250   g_object_class_install_property (gobject_class, PROP_SOCKET,
251     g_param_spec_object ("socket",
252                          P_("Socket"),
253                          P_("The underlying GSocket"),
254                          G_TYPE_SOCKET, G_PARAM_CONSTRUCT_ONLY |
255                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
256 }
257
258 static void
259 g_socket_connection_init (GSocketConnection *connection)
260 {
261   connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
262                                                   G_TYPE_SOCKET_CONNECTION,
263                                                   GSocketConnectionPrivate);
264 }
265
266 static gboolean
267 g_socket_connection_close (GIOStream            *stream,
268                            GCancellable         *cancellable,
269                            GError              **error)
270 {
271   GSocketConnection *connection = G_SOCKET_CONNECTION (stream);
272
273   if (connection->priv->output_stream)
274     g_output_stream_close (connection->priv->output_stream,
275                            cancellable, NULL);
276   if (connection->priv->input_stream)
277     g_input_stream_close (connection->priv->input_stream,
278                           cancellable, NULL);
279
280   return g_socket_close (connection->priv->socket, error);
281 }
282
283
284 static void
285 g_socket_connection_close_async (GIOStream        *stream,
286                                  int               io_priority,
287                                  GCancellable     *cancellable,
288                                  GAsyncReadyCallback callback,
289                                  gpointer          user_data)
290 {
291   GSimpleAsyncResult *res;
292   GError *error;
293
294   /* socket close is not blocked, just do it! */
295   error = NULL;
296   if (!g_io_stream_close (stream, cancellable, &error))
297     {
298       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
299                                             callback, user_data,
300                                             error);
301       g_error_free (error);
302       return;
303     }
304
305   res = g_simple_async_result_new (G_OBJECT (stream),
306                                    callback,
307                                    user_data,
308                                    g_socket_connection_close_async);
309   g_simple_async_result_complete_in_idle (res);
310   g_object_unref (res);
311 }
312
313 static gboolean
314 g_socket_connection_close_finish (GIOStream  *stream,
315                                   GAsyncResult  *result,
316                                   GError       **error)
317 {
318   return TRUE;
319 }
320
321 typedef struct {
322   GSocketFamily socket_family;
323   GSocketType socket_type;
324   int protocol;
325   GType implementation;
326 } ConnectionFactory;
327
328 static guint
329 connection_factory_hash (gconstpointer key)
330 {
331   const ConnectionFactory *factory = key;
332   guint h;
333
334   h = factory->socket_family ^ (factory->socket_type << 4) ^ (factory->protocol << 8);
335   /* This is likely to be small, so spread over whole
336      hash space to get some distribution */
337   h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
338
339   return h;
340 }
341
342 static gboolean
343 connection_factory_equal (gconstpointer _a,
344                           gconstpointer _b)
345 {
346   const ConnectionFactory *a = _a;
347   const ConnectionFactory *b = _b;
348
349   if (a->socket_family != b->socket_family)
350     return FALSE;
351
352   if (a->socket_type != b->socket_type)
353     return FALSE;
354
355   if (a->protocol != b->protocol)
356     return FALSE;
357
358   return TRUE;
359 }
360
361 static GHashTable *connection_factories = NULL;
362 G_LOCK_DEFINE_STATIC(connection_factories);
363
364 /**
365  * g_socket_connection_factory_register_type:
366  * @g_type: a #GType, inheriting from G_SOCKET_CONNECTION
367  * @family: a #GSocketFamily.
368  * @type: a #GSocketType
369  * @protocol: a protocol id
370  *
371  * Looks up the #GType to be used when creating socket connections on
372  * sockets with the specified @family,@type and @protocol.
373  *
374  * If no type is registered, the #GSocketConnection base type is returned.
375  *
376  * Since: 2.22
377  **/
378 void
379 g_socket_connection_factory_register_type (GType g_type,
380                                            GSocketFamily family,
381                                            GSocketType type,
382                                            gint protocol)
383 {
384   ConnectionFactory *factory;
385
386   g_return_if_fail (g_type_is_a (g_type, G_TYPE_SOCKET_CONNECTION));
387
388   G_LOCK (connection_factories);
389
390   if (connection_factories == NULL)
391     connection_factories = g_hash_table_new_full (connection_factory_hash,
392                                                   connection_factory_equal,
393                                                   (GDestroyNotify)g_free,
394                                                   NULL);
395
396   factory = g_new0 (ConnectionFactory, 1);
397   factory->socket_family = family;
398   factory->socket_type = type;
399   factory->protocol = protocol;
400   factory->implementation = g_type;
401
402   g_hash_table_insert (connection_factories,
403                        factory, factory);
404
405   G_UNLOCK (connection_factories);
406 }
407
408 static void
409 init_builtin_types (void)
410 {
411   volatile GType a_type;
412 #ifndef G_OS_WIN32
413   a_type = g_unix_connection_get_type ();
414 #endif
415   a_type = g_tcp_connection_get_type ();
416 }
417
418 /**
419  * g_socket_connection_factory_lookup_type:
420  * @family: a #GSocketFamily.
421  * @type: a #GSocketType
422  * @protocol_id: a protocol id
423  *
424  * Looks up the #GType to be used when creating socket connections on
425  * sockets with the specified @family,@type and @protocol_id.
426  *
427  * If no type is registered, the #GSocketConnection base type is returned.
428  *
429  * Returns: a #GType
430  * Since: 2.22
431  **/
432 GType
433 g_socket_connection_factory_lookup_type (GSocketFamily family,
434                                          GSocketType type,
435                                          gint protocol_id)
436 {
437   ConnectionFactory *factory, key;
438   GType g_type;
439
440   init_builtin_types ();
441
442   G_LOCK (connection_factories);
443
444   g_type = G_TYPE_SOCKET_CONNECTION;
445
446   if (connection_factories)
447     {
448       key.socket_family = family;
449       key.socket_type = type;
450       key.protocol = protocol_id;
451
452       factory = g_hash_table_lookup (connection_factories, &key);
453       if (factory)
454         g_type = factory->implementation;
455     }
456
457   G_UNLOCK (connection_factories);
458
459   return g_type;
460 }
461
462 /**
463  * g_socket_connection_factory_create_connection:
464  * @socket: a #GSocket.
465  *
466  * Creates a #GSocketConnection subclass of the right type for
467  * @socket.
468  *
469  * Returns: a #GSocketConnection
470  *
471  * Since: 2.22
472  **/
473 GSocketConnection *
474 g_socket_connection_factory_create_connection (GSocket *socket)
475 {
476   GType type;
477
478   type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
479                                                   g_socket_get_socket_type (socket),
480                                                   g_socket_get_protocol_id (socket));
481   return g_object_new (type, "socket", socket, NULL);
482 }
483
484 #define __G_SOCKET_CONNECTION_C__
485 #include "gioaliasdef.c"