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