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