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