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