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