gio: Replace g_clear_object() with if()…g_object_unref()
[platform/upstream/glib.git] / gio / gdbusserver.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28
29 #include "giotypes.h"
30 #include "gioerror.h"
31 #include "gdbusaddress.h"
32 #include "gdbusutils.h"
33 #include "gdbusconnection.h"
34 #include "gdbusserver.h"
35 #include "gioenumtypes.h"
36 #include "gdbusprivate.h"
37 #include "gdbusauthobserver.h"
38 #include "ginitable.h"
39 #include "gsocketservice.h"
40 #include "gthreadedsocketservice.h"
41 #include "gresolver.h"
42 #include "glib/gstdio.h"
43 #include "ginetaddress.h"
44 #include "ginetsocketaddress.h"
45 #include "ginputstream.h"
46 #include "giostream.h"
47
48 #ifdef G_OS_UNIX
49 #include <unistd.h>
50 #endif
51 #ifdef G_OS_WIN32
52 #include <io.h>
53 #endif
54
55 #ifdef G_OS_UNIX
56 #include "gunixsocketaddress.h"
57 #endif
58
59 #include "glibintl.h"
60
61 /**
62  * SECTION:gdbusserver
63  * @short_description: Helper for accepting connections
64  * @include: gio/gio.h
65  *
66  * #GDBusServer is a helper for listening to and accepting D-Bus
67  * connections. This can be used to create a new D-Bus server, allowing two
68  * peers to use the D-Bus protocol for their own specialized communication.
69  * A server instance provided in this way will not perform message routing or
70  * implement the org.freedesktop.DBus interface.
71  *
72  * To just export an object on a well-known name on a message bus, such as the
73  * session or system bus, you should instead use g_bus_own_name().
74  *
75  * <example id="gdbus-peer-to-peer"><title>D-Bus peer-to-peer example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-peer.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
76  */
77
78 /**
79  * GDBusServer:
80  *
81  * The #GDBusServer structure contains only private data and
82  * should only be accessed using the provided API.
83  *
84  * Since: 2.26
85  */
86 struct _GDBusServer
87 {
88   /*< private >*/
89   GObject parent_instance;
90
91   GDBusServerFlags flags;
92   gchar *address;
93   gchar *guid;
94
95   guchar *nonce;
96   gchar *nonce_file;
97
98   gchar *client_address;
99
100   GSocketListener *listener;
101   gboolean is_using_listener;
102   gulong run_signal_handler_id;
103
104   /* The result of g_main_context_ref_thread_default() when the object
105    * was created (the GObject _init() function) - this is used for delivery
106    * of the :new-connection GObject signal.
107    */
108   GMainContext *main_context_at_construction;
109
110   gboolean active;
111
112   GDBusAuthObserver *authentication_observer;
113 };
114
115 typedef struct _GDBusServerClass GDBusServerClass;
116
117 /**
118  * GDBusServerClass:
119  * @new_connection: Signal class handler for the #GDBusServer::new-connection signal.
120  *
121  * Class structure for #GDBusServer.
122  *
123  * Since: 2.26
124  */
125 struct _GDBusServerClass
126 {
127   /*< private >*/
128   GObjectClass parent_class;
129
130   /*< public >*/
131   /* Signals */
132   gboolean (*new_connection) (GDBusServer      *server,
133                               GDBusConnection  *connection);
134 };
135
136 enum
137 {
138   PROP_0,
139   PROP_ADDRESS,
140   PROP_CLIENT_ADDRESS,
141   PROP_FLAGS,
142   PROP_GUID,
143   PROP_ACTIVE,
144   PROP_AUTHENTICATION_OBSERVER,
145 };
146
147 enum
148 {
149   NEW_CONNECTION_SIGNAL,
150   LAST_SIGNAL,
151 };
152
153 static guint _signals[LAST_SIGNAL] = {0};
154
155 static void initable_iface_init       (GInitableIface *initable_iface);
156
157 G_DEFINE_TYPE_WITH_CODE (GDBusServer, g_dbus_server, G_TYPE_OBJECT,
158                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
159                          );
160
161 static void
162 g_dbus_server_finalize (GObject *object)
163 {
164   GDBusServer *server = G_DBUS_SERVER (object);
165
166   if (server->authentication_observer != NULL)
167     g_object_unref (server->authentication_observer);
168
169   if (server->run_signal_handler_id > 0)
170     g_signal_handler_disconnect (server->listener, server->run_signal_handler_id);
171
172   if (server->listener != NULL)
173     g_object_unref (server->listener);
174
175   g_free (server->address);
176   g_free (server->guid);
177   g_free (server->client_address);
178   if (server->nonce != NULL)
179     {
180       memset (server->nonce, '\0', 16);
181       g_free (server->nonce);
182     }
183   /* we could unlink the nonce file but I don't
184    * think it's really worth the effort/risk
185    */
186   g_free (server->nonce_file);
187
188   g_main_context_unref (server->main_context_at_construction);
189
190   G_OBJECT_CLASS (g_dbus_server_parent_class)->finalize (object);
191 }
192
193 static void
194 g_dbus_server_get_property (GObject    *object,
195                             guint       prop_id,
196                             GValue     *value,
197                             GParamSpec *pspec)
198 {
199   GDBusServer *server = G_DBUS_SERVER (object);
200
201   switch (prop_id)
202     {
203     case PROP_FLAGS:
204       g_value_set_flags (value, server->flags);
205       break;
206
207     case PROP_GUID:
208       g_value_set_string (value, server->guid);
209       break;
210
211     case PROP_ADDRESS:
212       g_value_set_string (value, server->address);
213       break;
214
215     case PROP_CLIENT_ADDRESS:
216       g_value_set_string (value, server->client_address);
217       break;
218
219     case PROP_ACTIVE:
220       g_value_set_boolean (value, server->active);
221       break;
222
223     case PROP_AUTHENTICATION_OBSERVER:
224       g_value_set_object (value, server->authentication_observer);
225       break;
226
227     default:
228       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
229       break;
230     }
231 }
232
233 static void
234 g_dbus_server_set_property (GObject      *object,
235                             guint         prop_id,
236                             const GValue *value,
237                             GParamSpec   *pspec)
238 {
239   GDBusServer *server = G_DBUS_SERVER (object);
240
241   switch (prop_id)
242     {
243     case PROP_FLAGS:
244       server->flags = g_value_get_flags (value);
245       break;
246
247     case PROP_GUID:
248       server->guid = g_value_dup_string (value);
249       break;
250
251     case PROP_ADDRESS:
252       server->address = g_value_dup_string (value);
253       break;
254
255     case PROP_AUTHENTICATION_OBSERVER:
256       server->authentication_observer = g_value_dup_object (value);
257       break;
258
259     default:
260       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
261       break;
262     }
263 }
264
265 static void
266 g_dbus_server_class_init (GDBusServerClass *klass)
267 {
268   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
269
270   gobject_class->finalize     = g_dbus_server_finalize;
271   gobject_class->set_property = g_dbus_server_set_property;
272   gobject_class->get_property = g_dbus_server_get_property;
273
274   /**
275    * GDBusServer:flags:
276    *
277    * Flags from the #GDBusServerFlags enumeration.
278    *
279    * Since: 2.26
280    */
281   g_object_class_install_property (gobject_class,
282                                    PROP_FLAGS,
283                                    g_param_spec_flags ("flags",
284                                                        P_("Flags"),
285                                                        P_("Flags for the server"),
286                                                        G_TYPE_DBUS_SERVER_FLAGS,
287                                                        G_DBUS_SERVER_FLAGS_NONE,
288                                                        G_PARAM_READABLE |
289                                                        G_PARAM_WRITABLE |
290                                                        G_PARAM_CONSTRUCT_ONLY |
291                                                        G_PARAM_STATIC_NAME |
292                                                        G_PARAM_STATIC_BLURB |
293                                                        G_PARAM_STATIC_NICK));
294
295   /**
296    * GDBusServer:guid:
297    *
298    * The guid of the server.
299    *
300    * Since: 2.26
301    */
302   g_object_class_install_property (gobject_class,
303                                    PROP_GUID,
304                                    g_param_spec_string ("guid",
305                                                         P_("GUID"),
306                                                         P_("The guid of the server"),
307                                                         NULL,
308                                                         G_PARAM_READABLE |
309                                                         G_PARAM_WRITABLE |
310                                                         G_PARAM_CONSTRUCT_ONLY |
311                                                         G_PARAM_STATIC_NAME |
312                                                         G_PARAM_STATIC_BLURB |
313                                                         G_PARAM_STATIC_NICK));
314
315   /**
316    * GDBusServer:address:
317    *
318    * The D-Bus address to listen on.
319    *
320    * Since: 2.26
321    */
322   g_object_class_install_property (gobject_class,
323                                    PROP_ADDRESS,
324                                    g_param_spec_string ("address",
325                                                         P_("Address"),
326                                                         P_("The address to listen on"),
327                                                         NULL,
328                                                         G_PARAM_READABLE |
329                                                         G_PARAM_WRITABLE |
330                                                         G_PARAM_CONSTRUCT_ONLY |
331                                                         G_PARAM_STATIC_NAME |
332                                                         G_PARAM_STATIC_BLURB |
333                                                         G_PARAM_STATIC_NICK));
334
335   /**
336    * GDBusServer:client-address:
337    *
338    * The D-Bus address that clients can use.
339    *
340    * Since: 2.26
341    */
342   g_object_class_install_property (gobject_class,
343                                    PROP_CLIENT_ADDRESS,
344                                    g_param_spec_string ("client-address",
345                                                         P_("Client Address"),
346                                                         P_("The address clients can use"),
347                                                         NULL,
348                                                         G_PARAM_READABLE |
349                                                         G_PARAM_STATIC_NAME |
350                                                         G_PARAM_STATIC_BLURB |
351                                                         G_PARAM_STATIC_NICK));
352
353   /**
354    * GDBusServer:active:
355    *
356    * Whether the server is currently active.
357    *
358    * Since: 2.26
359    */
360   g_object_class_install_property (gobject_class,
361                                    PROP_ACTIVE,
362                                    g_param_spec_boolean ("active",
363                                                          P_("Active"),
364                                                          P_("Whether the server is currently active"),
365                                                          FALSE,
366                                                          G_PARAM_READABLE |
367                                                          G_PARAM_STATIC_NAME |
368                                                          G_PARAM_STATIC_BLURB |
369                                                          G_PARAM_STATIC_NICK));
370
371   /**
372    * GDBusServer:authentication-observer:
373    *
374    * A #GDBusAuthObserver object to assist in the authentication process or %NULL.
375    *
376    * Since: 2.26
377    */
378   g_object_class_install_property (gobject_class,
379                                    PROP_AUTHENTICATION_OBSERVER,
380                                    g_param_spec_object ("authentication-observer",
381                                                         P_("Authentication Observer"),
382                                                         P_("Object used to assist in the authentication process"),
383                                                         G_TYPE_DBUS_AUTH_OBSERVER,
384                                                         G_PARAM_READABLE |
385                                                         G_PARAM_WRITABLE |
386                                                         G_PARAM_CONSTRUCT_ONLY |
387                                                         G_PARAM_STATIC_NAME |
388                                                         G_PARAM_STATIC_BLURB |
389                                                         G_PARAM_STATIC_NICK));
390
391   /**
392    * GDBusServer::new-connection:
393    * @server: The #GDBusServer emitting the signal.
394    * @connection: A #GDBusConnection for the new connection.
395    *
396    * Emitted when a new authenticated connection has been made. Use
397    * g_dbus_connection_get_peer_credentials() to figure out what
398    * identity (if any), was authenticated.
399    *
400    * If you want to accept the connection, take a reference to the
401    * @connection object and return %TRUE. When you are done with the
402    * connection call g_dbus_connection_close() and give up your
403    * reference. Note that the other peer may disconnect at any time -
404    * a typical thing to do when accepting a connection is to listen to
405    * the #GDBusConnection::closed signal.
406    *
407    * If #GDBusServer:flags contains %G_DBUS_SERVER_FLAGS_RUN_IN_THREAD
408    * then the signal is emitted in a new thread dedicated to the
409    * connection. Otherwise the signal is emitted in the <link
410    * linkend="g-main-context-push-thread-default">thread-default main
411    * loop</link> of the thread that @server was constructed in.
412    *
413    * You are guaranteed that signal handlers for this signal runs
414    * before incoming messages on @connection are processed. This means
415    * that it's suitable to call g_dbus_connection_register_object() or
416    * similar from the signal handler.
417    *
418    * Returns: %TRUE to claim @connection, %FALSE to let other handlers
419    * run.
420    *
421    * Since: 2.26
422    */
423   _signals[NEW_CONNECTION_SIGNAL] = g_signal_new ("new-connection",
424                                                   G_TYPE_DBUS_SERVER,
425                                                   G_SIGNAL_RUN_LAST,
426                                                   G_STRUCT_OFFSET (GDBusServerClass, new_connection),
427                                                   g_signal_accumulator_true_handled,
428                                                   NULL, /* accu_data */
429                                                   NULL,
430                                                   G_TYPE_BOOLEAN,
431                                                   1,
432                                                   G_TYPE_DBUS_CONNECTION);
433 }
434
435 static void
436 g_dbus_server_init (GDBusServer *server)
437 {
438   server->main_context_at_construction = g_main_context_ref_thread_default ();
439 }
440
441 static gboolean
442 on_run (GSocketService    *service,
443         GSocketConnection *socket_connection,
444         GObject           *source_object,
445         gpointer           user_data);
446
447 /**
448  * g_dbus_server_new_sync:
449  * @address: A D-Bus address.
450  * @flags: Flags from the #GDBusServerFlags enumeration.
451  * @guid: A D-Bus GUID.
452  * @observer: (allow-none): A #GDBusAuthObserver or %NULL.
453  * @cancellable: (allow-none): A #GCancellable or %NULL.
454  * @error: Return location for server or %NULL.
455  *
456  * Creates a new D-Bus server that listens on the first address in
457  * @address that works.
458  *
459  * Once constructed, you can use g_dbus_server_get_client_address() to
460  * get a D-Bus address string that clients can use to connect.
461  *
462  * Connect to the #GDBusServer::new-connection signal to handle
463  * incoming connections.
464  *
465  * The returned #GDBusServer isn't active - you have to start it with
466  * g_dbus_server_start().
467  *
468  * See <xref linkend="gdbus-peer-to-peer"/> for how #GDBusServer can
469  * be used.
470  *
471  * This is a synchronous failable constructor. See
472  * g_dbus_server_new() for the asynchronous version.
473  *
474  * Returns: A #GDBusServer or %NULL if @error is set. Free with
475  * g_object_unref().
476  *
477  * Since: 2.26
478  */
479 GDBusServer *
480 g_dbus_server_new_sync (const gchar        *address,
481                         GDBusServerFlags    flags,
482                         const gchar        *guid,
483                         GDBusAuthObserver  *observer,
484                         GCancellable       *cancellable,
485                         GError            **error)
486 {
487   GDBusServer *server;
488
489   g_return_val_if_fail (address != NULL, NULL);
490   g_return_val_if_fail (g_dbus_is_guid (guid), NULL);
491   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
492
493   server = g_initable_new (G_TYPE_DBUS_SERVER,
494                            cancellable,
495                            error,
496                            "address", address,
497                            "flags", flags,
498                            "guid", guid,
499                            "authentication-observer", observer,
500                            NULL);
501
502   return server;
503 }
504
505 /**
506  * g_dbus_server_get_client_address:
507  * @server: A #GDBusServer.
508  *
509  * Gets a D-Bus address string that can be used by clients to connect
510  * to @server.
511  *
512  * Returns: A D-Bus address string. Do not free, the string is owned
513  * by @server.
514  *
515  * Since: 2.26
516  */
517 const gchar *
518 g_dbus_server_get_client_address (GDBusServer *server)
519 {
520   g_return_val_if_fail (G_IS_DBUS_SERVER (server), NULL);
521   return server->client_address;
522 }
523
524 /**
525  * g_dbus_server_get_guid:
526  * @server: A #GDBusServer.
527  *
528  * Gets the GUID for @server.
529  *
530  * Returns: A D-Bus GUID. Do not free this string, it is owned by @server.
531  *
532  * Since: 2.26
533  */
534 const gchar *
535 g_dbus_server_get_guid (GDBusServer *server)
536 {
537   g_return_val_if_fail (G_IS_DBUS_SERVER (server), NULL);
538   return server->guid;
539 }
540
541 /**
542  * g_dbus_server_get_flags:
543  * @server: A #GDBusServer.
544  *
545  * Gets the flags for @server.
546  *
547  * Returns: A set of flags from the #GDBusServerFlags enumeration.
548  *
549  * Since: 2.26
550  */
551 GDBusServerFlags
552 g_dbus_server_get_flags (GDBusServer *server)
553 {
554   g_return_val_if_fail (G_IS_DBUS_SERVER (server), G_DBUS_SERVER_FLAGS_NONE);
555   return server->flags;
556 }
557
558 /**
559  * g_dbus_server_is_active:
560  * @server: A #GDBusServer.
561  *
562  * Gets whether @server is active.
563  *
564  * Returns: %TRUE if server is active, %FALSE otherwise.
565  *
566  * Since: 2.26
567  */
568 gboolean
569 g_dbus_server_is_active (GDBusServer *server)
570 {
571   g_return_val_if_fail (G_IS_DBUS_SERVER (server), G_DBUS_SERVER_FLAGS_NONE);
572   return server->active;
573 }
574
575 /**
576  * g_dbus_server_start:
577  * @server: A #GDBusServer.
578  *
579  * Starts @server.
580  *
581  * Since: 2.26
582  */
583 void
584 g_dbus_server_start (GDBusServer *server)
585 {
586   g_return_if_fail (G_IS_DBUS_SERVER (server));
587   if (server->active)
588     return;
589   /* Right now we don't have any transport not using the listener... */
590   g_assert (server->is_using_listener);
591   g_socket_service_start (G_SOCKET_SERVICE (server->listener));
592   server->active = TRUE;
593   g_object_notify (G_OBJECT (server), "active");
594 }
595
596 /**
597  * g_dbus_server_stop:
598  * @server: A #GDBusServer.
599  *
600  * Stops @server.
601  *
602  * Since: 2.26
603  */
604 void
605 g_dbus_server_stop (GDBusServer *server)
606 {
607   g_return_if_fail (G_IS_DBUS_SERVER (server));
608   if (!server->active)
609     return;
610   /* Right now we don't have any transport not using the listener... */
611   g_assert (server->is_using_listener);
612   g_assert (server->run_signal_handler_id > 0);
613   g_signal_handler_disconnect (server->listener, server->run_signal_handler_id);
614   server->run_signal_handler_id = 0;
615   g_socket_service_stop (G_SOCKET_SERVICE (server->listener));
616   server->active = FALSE;
617   g_object_notify (G_OBJECT (server), "active");
618 }
619
620 /* ---------------------------------------------------------------------------------------------------- */
621
622 #ifdef G_OS_UNIX
623
624 static gint
625 random_ascii (void)
626 {
627   gint ret;
628   ret = g_random_int_range (0, 60);
629   if (ret < 25)
630     ret += 'A';
631   else if (ret < 50)
632     ret += 'a' - 25;
633   else
634     ret += '0' - 50;
635   return ret;
636 }
637
638 /* note that address_entry has already been validated => exactly one of path, tmpdir or abstract keys are set */
639 static gboolean
640 try_unix (GDBusServer  *server,
641           const gchar  *address_entry,
642           GHashTable   *key_value_pairs,
643           GError      **error)
644 {
645   gboolean ret;
646   const gchar *path;
647   const gchar *tmpdir;
648   const gchar *abstract;
649   GSocketAddress *address;
650
651   ret = FALSE;
652   address = NULL;
653
654   path = g_hash_table_lookup (key_value_pairs, "path");
655   tmpdir = g_hash_table_lookup (key_value_pairs, "tmpdir");
656   abstract = g_hash_table_lookup (key_value_pairs, "abstract");
657
658   if (path != NULL)
659     {
660       address = g_unix_socket_address_new (path);
661     }
662   else if (tmpdir != NULL)
663     {
664       gint n;
665       GString *s;
666       GError *local_error;
667
668     retry:
669       s = g_string_new (tmpdir);
670       g_string_append (s, "/dbus-");
671       for (n = 0; n < 8; n++)
672         g_string_append_c (s, random_ascii ());
673
674       /* prefer abstract namespace if available */
675       if (g_unix_socket_address_abstract_names_supported ())
676         address = g_unix_socket_address_new_with_type (s->str,
677                                                        -1,
678                                                        G_UNIX_SOCKET_ADDRESS_ABSTRACT);
679       else
680         address = g_unix_socket_address_new (s->str);
681       g_string_free (s, TRUE);
682
683       local_error = NULL;
684       if (!g_socket_listener_add_address (server->listener,
685                                           address,
686                                           G_SOCKET_TYPE_STREAM,
687                                           G_SOCKET_PROTOCOL_DEFAULT,
688                                           NULL, /* source_object */
689                                           NULL, /* effective_address */
690                                           &local_error))
691         {
692           if (local_error->domain == G_IO_ERROR && local_error->code == G_IO_ERROR_ADDRESS_IN_USE)
693             {
694               g_error_free (local_error);
695               goto retry;
696             }
697           g_propagate_error (error, local_error);
698           goto out;
699         }
700       ret = TRUE;
701       goto out;
702     }
703   else if (abstract != NULL)
704     {
705       if (!g_unix_socket_address_abstract_names_supported ())
706         {
707           g_set_error_literal (error,
708                                G_IO_ERROR,
709                                G_IO_ERROR_NOT_SUPPORTED,
710                                _("Abstract name space not supported"));
711           goto out;
712         }
713       address = g_unix_socket_address_new_with_type (abstract,
714                                                      -1,
715                                                      G_UNIX_SOCKET_ADDRESS_ABSTRACT);
716     }
717   else
718     {
719       g_assert_not_reached ();
720     }
721
722   if (!g_socket_listener_add_address (server->listener,
723                                       address,
724                                       G_SOCKET_TYPE_STREAM,
725                                       G_SOCKET_PROTOCOL_DEFAULT,
726                                       NULL, /* source_object */
727                                       NULL, /* effective_address */
728                                       error))
729     goto out;
730
731   ret = TRUE;
732
733  out:
734
735   if (address != NULL)
736     {
737       /* Fill out client_address if the connection attempt worked */
738       if (ret)
739         {
740           server->is_using_listener = TRUE;
741
742           switch (g_unix_socket_address_get_address_type (G_UNIX_SOCKET_ADDRESS (address)))
743             {
744             case G_UNIX_SOCKET_ADDRESS_ABSTRACT:
745               server->client_address = g_strdup_printf ("unix:abstract=%s",
746                                                         g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (address)));
747               break;
748
749             case G_UNIX_SOCKET_ADDRESS_PATH:
750               server->client_address = g_strdup_printf ("unix:path=%s",
751                                                         g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (address)));
752               break;
753
754             default:
755               g_assert_not_reached ();
756               break;
757             }
758         }
759       g_object_unref (address);
760     }
761   return ret;
762 }
763 #endif
764
765 /* ---------------------------------------------------------------------------------------------------- */
766
767 /* note that address_entry has already been validated =>
768  *  both host and port (guaranteed to be a number in [0, 65535]) are set (family is optional)
769  */
770 static gboolean
771 try_tcp (GDBusServer  *server,
772          const gchar  *address_entry,
773          GHashTable   *key_value_pairs,
774          gboolean      do_nonce,
775          GError      **error)
776 {
777   gboolean ret;
778   const gchar *host;
779   const gchar *port;
780   gint port_num;
781   GResolver *resolver;
782   GList *resolved_addresses;
783   GList *l;
784
785   ret = FALSE;
786   resolver = NULL;
787   resolved_addresses = NULL;
788
789   host = g_hash_table_lookup (key_value_pairs, "host");
790   port = g_hash_table_lookup (key_value_pairs, "port");
791   /* family = g_hash_table_lookup (key_value_pairs, "family"); */
792   if (g_hash_table_lookup (key_value_pairs, "noncefile") != NULL)
793     {
794       g_set_error_literal (error,
795                            G_IO_ERROR,
796                            G_IO_ERROR_INVALID_ARGUMENT,
797                            _("Cannot specify nonce file when creating a server"));
798       goto out;
799     }
800
801   if (host == NULL)
802     host = "localhost";
803   if (port == NULL)
804     port = "0";
805   port_num = strtol (port, NULL, 10);
806
807   resolver = g_resolver_get_default ();
808   resolved_addresses = g_resolver_lookup_by_name (resolver,
809                                                   host,
810                                                   NULL,
811                                                   error);
812   if (resolved_addresses == NULL)
813     goto out;
814
815   /* TODO: handle family */
816   for (l = resolved_addresses; l != NULL; l = l->next)
817     {
818       GInetAddress *address = G_INET_ADDRESS (l->data);
819       GSocketAddress *socket_address;
820       GSocketAddress *effective_address;
821
822       socket_address = g_inet_socket_address_new (address, port_num);
823       if (!g_socket_listener_add_address (server->listener,
824                                           socket_address,
825                                           G_SOCKET_TYPE_STREAM,
826                                           G_SOCKET_PROTOCOL_TCP,
827                                           NULL, /* GObject *source_object */
828                                           &effective_address,
829                                           error))
830         {
831           g_object_unref (socket_address);
832           goto out;
833         }
834       if (port_num == 0)
835         /* make sure we allocate the same port number for other listeners */
836         port_num = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (effective_address));
837
838       g_object_unref (effective_address);
839       g_object_unref (socket_address);
840     }
841
842   if (do_nonce)
843     {
844       gint fd;
845       guint n;
846       gsize bytes_written;
847       gsize bytes_remaining;
848       char *file_escaped;
849
850       server->nonce = g_new0 (guchar, 16);
851       for (n = 0; n < 16; n++)
852         server->nonce[n] = g_random_int_range (0, 256);
853       fd = g_file_open_tmp ("gdbus-nonce-file-XXXXXX",
854                             &server->nonce_file,
855                             error);
856       if (fd == -1)
857         {
858           g_socket_listener_close (server->listener);
859           goto out;
860         }
861     again:
862       bytes_written = 0;
863       bytes_remaining = 16;
864       while (bytes_remaining > 0)
865         {
866           gssize ret;
867           ret = write (fd, server->nonce + bytes_written, bytes_remaining);
868           if (ret == -1)
869             {
870               if (errno == EINTR)
871                 goto again;
872               g_set_error (error,
873                            G_IO_ERROR,
874                            g_io_error_from_errno (errno),
875                            _("Error writing nonce file at '%s': %s"),
876                            server->nonce_file,
877                            strerror (errno));
878               goto out;
879             }
880           bytes_written += ret;
881           bytes_remaining -= ret;
882         }
883       if (!g_close (fd, error))
884         goto out;
885       file_escaped = g_uri_escape_string (server->nonce_file, "/\\", FALSE);
886       server->client_address = g_strdup_printf ("nonce-tcp:host=%s,port=%d,noncefile=%s",
887                                                 host,
888                                                 port_num,
889                                                 file_escaped);
890       g_free (file_escaped);
891     }
892   else
893     {
894       server->client_address = g_strdup_printf ("tcp:host=%s,port=%d", host, port_num);
895     }
896   server->is_using_listener = TRUE;
897   ret = TRUE;
898
899  out:
900   g_list_free_full (resolved_addresses, g_object_unref);
901   if (resolver)
902     g_object_unref (resolver);
903   return ret;
904 }
905
906 /* ---------------------------------------------------------------------------------------------------- */
907
908 typedef struct
909 {
910   GDBusServer *server;
911   GDBusConnection *connection;
912 } EmitIdleData;
913
914 static void
915 emit_idle_data_free (EmitIdleData *data)
916 {
917   g_object_unref (data->server);
918   g_object_unref (data->connection);
919   g_free (data);
920 }
921
922 static gboolean
923 emit_new_connection_in_idle (gpointer user_data)
924 {
925   EmitIdleData *data = user_data;
926   gboolean claimed;
927
928   claimed = FALSE;
929   g_signal_emit (data->server,
930                  _signals[NEW_CONNECTION_SIGNAL],
931                  0,
932                  data->connection,
933                  &claimed);
934
935   if (claimed)
936     g_dbus_connection_start_message_processing (data->connection);
937   g_object_unref (data->connection);
938
939   return FALSE;
940 }
941
942 /* Called in new thread */
943 static gboolean
944 on_run (GSocketService    *service,
945         GSocketConnection *socket_connection,
946         GObject           *source_object,
947         gpointer           user_data)
948 {
949   GDBusServer *server = G_DBUS_SERVER (user_data);
950   GDBusConnection *connection;
951   GDBusConnectionFlags connection_flags;
952
953   if (server->nonce != NULL)
954     {
955       gchar buf[16];
956       gsize bytes_read;
957
958       if (!g_input_stream_read_all (g_io_stream_get_input_stream (G_IO_STREAM (socket_connection)),
959                                     buf,
960                                     16,
961                                     &bytes_read,
962                                     NULL,  /* GCancellable */
963                                     NULL)) /* GError */
964         goto out;
965
966       if (bytes_read != 16)
967         goto out;
968
969       if (memcmp (buf, server->nonce, 16) != 0)
970         goto out;
971     }
972
973   connection_flags =
974     G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
975     G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING;
976   if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS)
977     connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
978
979   connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
980                                            server->guid,
981                                            connection_flags,
982                                            server->authentication_observer,
983                                            NULL,  /* GCancellable */
984                                            NULL); /* GError */
985   if (connection == NULL)
986       goto out;
987
988   if (server->flags & G_DBUS_SERVER_FLAGS_RUN_IN_THREAD)
989     {
990       gboolean claimed;
991
992       claimed = FALSE;
993       g_signal_emit (server,
994                      _signals[NEW_CONNECTION_SIGNAL],
995                      0,
996                      connection,
997                      &claimed);
998       if (claimed)
999         g_dbus_connection_start_message_processing (connection);
1000       g_object_unref (connection);
1001     }
1002   else
1003     {
1004       GSource *idle_source;
1005       EmitIdleData *data;
1006
1007       data = g_new0 (EmitIdleData, 1);
1008       data->server = g_object_ref (server);
1009       data->connection = g_object_ref (connection);
1010
1011       idle_source = g_idle_source_new ();
1012       g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
1013       g_source_set_callback (idle_source,
1014                              emit_new_connection_in_idle,
1015                              data,
1016                              (GDestroyNotify) emit_idle_data_free);
1017       g_source_attach (idle_source, server->main_context_at_construction);
1018       g_source_unref (idle_source);
1019     }
1020
1021  out:
1022   return TRUE;
1023 }
1024
1025 static gboolean
1026 initable_init (GInitable     *initable,
1027                GCancellable  *cancellable,
1028                GError       **error)
1029 {
1030   GDBusServer *server = G_DBUS_SERVER (initable);
1031   gboolean ret;
1032   guint n;
1033   gchar **addr_array;
1034   GError *last_error;
1035
1036   ret = FALSE;
1037   addr_array = NULL;
1038   last_error = NULL;
1039
1040   if (!g_dbus_is_guid (server->guid))
1041     {
1042       g_set_error (&last_error,
1043                    G_IO_ERROR,
1044                    G_IO_ERROR_INVALID_ARGUMENT,
1045                    _("The string '%s' is not a valid D-Bus GUID"),
1046                    server->guid);
1047       goto out;
1048     }
1049
1050   server->listener = G_SOCKET_LISTENER (g_threaded_socket_service_new (-1));
1051
1052   addr_array = g_strsplit (server->address, ";", 0);
1053   last_error = NULL;
1054   for (n = 0; addr_array != NULL && addr_array[n] != NULL; n++)
1055     {
1056       const gchar *address_entry = addr_array[n];
1057       GHashTable *key_value_pairs;
1058       gchar *transport_name;
1059       GError *this_error;
1060
1061       this_error = NULL;
1062       if (g_dbus_is_supported_address (address_entry,
1063                                        &this_error) &&
1064           _g_dbus_address_parse_entry (address_entry,
1065                                        &transport_name,
1066                                        &key_value_pairs,
1067                                        &this_error))
1068         {
1069
1070           if (FALSE)
1071             {
1072             }
1073 #ifdef G_OS_UNIX
1074           else if (g_strcmp0 (transport_name, "unix") == 0)
1075             ret = try_unix (server, address_entry, key_value_pairs, &this_error);
1076 #endif
1077           else if (g_strcmp0 (transport_name, "tcp") == 0)
1078             ret = try_tcp (server, address_entry, key_value_pairs, FALSE, &this_error);
1079           else if (g_strcmp0 (transport_name, "nonce-tcp") == 0)
1080             ret = try_tcp (server, address_entry, key_value_pairs, TRUE, &this_error);
1081           else
1082             g_set_error (&this_error,
1083                          G_IO_ERROR,
1084                          G_IO_ERROR_INVALID_ARGUMENT,
1085                          _("Cannot listen on unsupported transport '%s'"),
1086                          transport_name);
1087
1088           g_free (transport_name);
1089           if (key_value_pairs != NULL)
1090             g_hash_table_unref (key_value_pairs);
1091
1092           if (ret)
1093             {
1094               g_assert (this_error == NULL);
1095               goto out;
1096             }
1097         }
1098
1099       if (this_error != NULL)
1100         {
1101           if (last_error != NULL)
1102             g_error_free (last_error);
1103           last_error = this_error;
1104         }
1105     }
1106
1107  out:
1108
1109   g_strfreev (addr_array);
1110
1111   if (ret)
1112     {
1113       if (last_error != NULL)
1114         g_error_free (last_error);
1115
1116       /* Right now we don't have any transport not using the listener... */
1117       g_assert (server->is_using_listener);
1118       server->run_signal_handler_id = g_signal_connect (G_SOCKET_SERVICE (server->listener),
1119                                                         "run",
1120                                                         G_CALLBACK (on_run),
1121                                                         server);
1122     }
1123   else
1124     {
1125       g_assert (last_error != NULL);
1126       g_propagate_error (error, last_error);
1127     }
1128   return ret;
1129 }
1130
1131
1132 static void
1133 initable_iface_init (GInitableIface *initable_iface)
1134 {
1135   initable_iface->init = initable_init;
1136 }
1137
1138 /* ---------------------------------------------------------------------------------------------------- */