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