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