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