GDBus: Hide instance structures for classes we don't want to be subclassed
[platform/upstream/glib.git] / gio / gdbusconnection.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 /*
24  * TODO for GDBus:
25  *
26  * - Validate all data (e.g. UTF-8) and check all the required D-Bus headers
27  *   are present and forbidden ones aren't
28  *   - When writing: g_dbus_message_to_blob()
29  *   - When reading: g_dbus_message_new_from_blob()
30  *
31  * - would be nice to expose GDBusAuthMechanism and an extension point
32  *
33  * - Need to rewrite GDBusAuth and rework GDBusAuthMechanism. In particular
34  *   the mechanism VFuncs need to be able to set an error.
35  *
36  * - Need to document other mechanisms/sources for determining the D-Bus
37  *   address of a well-known bus.
38  *
39  *   - e.g. on Win32 we need code like from here
40  *
41  *     http://cgit.freedesktop.org/~david/gdbus-standalone/tree/gdbus/gdbusaddress.c#n900
42  *
43  *     that was never copied over here because it originally was copy-paste
44  *     from the GPLv2 / AFL 2.1 libdbus sources.
45  *
46  *   - on OS X we need to look in launchd for the address
47  *
48  *     https://bugs.freedesktop.org/show_bug.cgi?id=14259
49  *
50  *   - on X11 we need to look in a X11 property on the X server
51  *     - (we can also just use dbus-launch(1) from the D-Bus
52  *        distribution)
53  *
54  *   - (ideally) this requires D-Bus spec work because none of
55  *     this has never really been specced out properly (excect
56  *     the X11 bits)
57  *
58  * - Related to the above, we also need to be able to launch a message bus
59  *   instance.... Since we don't want to write our own bus daemon we should
60  *   launch dbus-daemon(1) (thus: Win32 and OS X need to bundle it)
61  *
62  * - probably want a G_DBUS_NONCE_TCP_TMPDIR environment variable
63  *   to specify where the nonce is stored. This will allow people to use
64  *   G_DBUS_NONCE_TCP_TMPDIR=/mnt/secure.company.server/dbus-nonce-dir
65  *   to easily acheive secure RPC via nonce-tcp.
66  *
67  * - need to expose an extension point for resolving D-Bus address and
68  *   turning them into GIOStream objects. This will allow us to implement
69  *   e.g. X11 D-Bus transports without dlopen()'ing or linking against
70  *   libX11 from libgio.
71  *   - see g_dbus_address_connect() in gdbusaddress.c
72  *
73  * - would be cute to use kernel-specific APIs to resolve fds for
74  *   debug output when using G_DBUS_DEBUG=message, e.g. in addition to
75  *
76  *     fd 21: dev=8:1,mode=0100644,ino=1171231,uid=0,gid=0,rdev=0:0,size=234,atime=1273070640,mtime=1267126160,ctime=1267126160
77  *
78  *   maybe we can show more information about what fd 21 really is.
79  *   Ryan suggests looking in /proc/self/fd for clues / symlinks!
80  *   Initial experiments on Linux 2.6 suggests that the symlink looks
81  *   like this:
82  *
83  *    3 -> /proc/18068/fd
84  *
85  *   e.g. not of much use.
86  *
87  *  - GDBus High-Level docs
88  *    - Proxy: properties, signals...
89  *    - Connection: IOStream based, ::close, connection setup steps
90  *                  mainloop integration, threading
91  *    - Differences from libdbus (extend "Migrating from")
92  *      - the message handling thread
93  *      - Using GVariant instead of GValue
94  *    - Explain why the high-level API is a good thing and what
95  *      kind of pitfalls it avoids
96  *      - Export objects before claiming names
97  *    - Talk about auto-starting services (cf. GBusNameWatcherFlags)
98  */
99
100 #include "config.h"
101
102 #include <stdlib.h>
103 #include <string.h>
104 #include <sys/types.h>
105 #ifdef HAVE_UNISTD_H
106 #include <unistd.h>
107 #endif
108
109 #include "gdbusauth.h"
110 #include "gdbusutils.h"
111 #include "gdbusaddress.h"
112 #include "gdbusmessage.h"
113 #include "gdbusconnection.h"
114 #include "gdbuserror.h"
115 #include "gioenumtypes.h"
116 #include "gdbusintrospection.h"
117 #include "gdbusmethodinvocation.h"
118 #include "gdbusprivate.h"
119 #include "gdbusauthobserver.h"
120 #include "gio-marshal.h"
121 #include "ginitable.h"
122 #include "gasyncinitable.h"
123 #include "giostream.h"
124 #include "gasyncresult.h"
125 #include "gsimpleasyncresult.h"
126
127 #ifdef G_OS_UNIX
128 #include "gunixconnection.h"
129 #include "gunixfdmessage.h"
130 #endif
131
132 #include "glibintl.h"
133 #include "gioalias.h"
134
135 /**
136  * SECTION:gdbusconnection
137  * @short_description: D-Bus Connections
138  * @include: gio/gio.h
139  *
140  * The #GDBusConnection type is used for D-Bus connections to remote
141  * peers such as a message buses. It is a low-level API that offers a
142  * lot of flexibility. For instance, it lets you establish a connection
143  * over any transport that can by represented as an #GIOStream.
144  *
145  * This class is rarely used directly in D-Bus clients. If you are writing
146  * an D-Bus client, it is often easier to use the g_bus_own_name(),
147  * g_bus_watch_name() or g_dbus_proxy_new_for_bus() APIs.
148  *
149  * <example id="gdbus-server"><title>D-Bus server example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
150  *
151  * <example id="gdbus-subtree-server"><title>D-Bus subtree example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-subtree.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
152  *
153  * <example id="gdbus-unix-fd-client"><title>D-Bus UNIX File Descriptor example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-unix-fd-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
154  *
155  * <example id="gdbus-export"><title>Exporting a GObject</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-export.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
156  */
157
158 /* ---------------------------------------------------------------------------------------------------- */
159
160 typedef struct _GDBusConnectionClass GDBusConnectionClass;
161
162 /**
163  * GDBusConnectionClass:
164  * @closed: Signal class handler for the #GDBusConnection::closed signal.
165  *
166  * Class structure for #GDBusConnection.
167  *
168  * Since: 2.26
169  */
170 struct _GDBusConnectionClass
171 {
172   /*< private >*/
173   GObjectClass parent_class;
174
175   /*< public >*/
176   /* Signals */
177   void (*closed) (GDBusConnection *connection,
178                   gboolean         remote_peer_vanished,
179                   GError          *error);
180 };
181
182 G_LOCK_DEFINE_STATIC (message_bus_lock);
183
184 static GDBusConnection *the_session_bus = NULL;
185 static GDBusConnection *the_system_bus = NULL;
186
187 /* ---------------------------------------------------------------------------------------------------- */
188
189 static gboolean
190 _g_strv_has_string (const gchar* const *haystack,
191                     const gchar        *needle)
192 {
193   guint n;
194
195   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
196     {
197       if (g_strcmp0 (haystack[n], needle) == 0)
198         return TRUE;
199     }
200   return FALSE;
201 }
202
203 /* ---------------------------------------------------------------------------------------------------- */
204
205 #ifdef G_OS_WIN32
206 #define CONNECTION_ENSURE_LOCK(obj) do { ; } while (FALSE)
207 #else
208 // TODO: for some reason this doesn't work on Windows
209 #define CONNECTION_ENSURE_LOCK(obj) do {                                \
210     if (G_UNLIKELY (g_mutex_trylock((obj)->lock)))                      \
211       {                                                                 \
212         g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
213                              "CONNECTION_ENSURE_LOCK: GDBusConnection object lock is not locked"); \
214       }                                                                 \
215   } while (FALSE)
216 #endif
217
218 #define CONNECTION_LOCK(obj) do {                                       \
219     g_mutex_lock ((obj)->lock);                                         \
220   } while (FALSE)
221
222 #define CONNECTION_UNLOCK(obj) do {                                     \
223     g_mutex_unlock ((obj)->lock);                                       \
224   } while (FALSE)
225
226 /**
227  * GDBusConnection:
228  *
229  * The #GDBusConnection structure contains only private data and
230  * should only be accessed using the provided API.
231  *
232  * Since: 2.26
233  */
234 struct _GDBusConnection
235 {
236   /*< private >*/
237   GObject parent_instance;
238
239   /* ------------------------------------------------------------------------ */
240   /* -- General object state ------------------------------------------------ */
241   /* ------------------------------------------------------------------------ */
242
243   /* object-wide lock */
244   GMutex *lock;
245
246   /* A lock used in the init() method of the GInitable interface - see comments
247    * in initable_init() for why a separate lock is needed
248    */
249   GMutex *init_lock;
250
251   /* Set (by loading the contents of /var/lib/dbus/machine-id) the first time
252    * someone calls org.freedesktop.DBus.GetMachineId()
253    */
254   gchar *machine_id;
255
256   /* The underlying stream used for communication */
257   GIOStream *stream;
258
259   /* The object used for authentication (if any) */
260   GDBusAuth *auth;
261
262   /* Set to TRUE if the connection has been closed */
263   gboolean closed;
264
265   /* Last serial used */
266   guint32 last_serial;
267
268   /* The object used to send/receive message */
269   GDBusWorker *worker;
270
271   /* If connected to a message bus, this contains the unique name assigned to
272    * us by the bus (e.g. ":1.42")
273    */
274   gchar *bus_unique_name;
275
276   /* The GUID returned by the other side if we authenticed as a client or
277    * the GUID to use if authenticating as a server
278    */
279   gchar *guid;
280
281   /* set to TRUE exactly when initable_init() has finished running */
282   gboolean is_initialized;
283
284   /* If the connection could not be established during initable_init(), this GError will set */
285   GError *initialization_error;
286
287   /* The result of g_main_context_get_thread_default() when the object
288    * was created (the GObject _init() function) - this is used for delivery
289    * of the :closed GObject signal.
290    */
291   GMainContext *main_context_at_construction;
292
293   /* construct properties */
294   gchar *address;
295   GDBusConnectionFlags flags;
296
297   /* Map used for managing method replies */
298   GHashTable *map_method_serial_to_send_message_data;  /* guint32 -> SendMessageData* */
299
300   /* Maps used for managing signal subscription */
301   GHashTable *map_rule_to_signal_data;                      /* match rule (gchar*)    -> SignalData */
302   GHashTable *map_id_to_signal_data;                        /* id (guint)             -> SignalData */
303   GHashTable *map_sender_unique_name_to_signal_data_array;  /* unique sender (gchar*) -> GPtrArray* of SignalData */
304
305   /* Maps used for managing exported objects and subtrees */
306   GHashTable *map_object_path_to_eo;  /* gchar* -> ExportedObject* */
307   GHashTable *map_id_to_ei;           /* guint  -> ExportedInterface* */
308   GHashTable *map_object_path_to_es;  /* gchar* -> ExportedSubtree* */
309   GHashTable *map_id_to_es;           /* guint  -> ExportedSubtree* */
310
311   /* Structure used for message filters */
312   GPtrArray *filters;
313
314   /* Whether to exit on close */
315   gboolean exit_on_close;
316
317   /* Capabilities negotiated during authentication */
318   GDBusCapabilityFlags capabilities;
319
320   GDBusAuthObserver *authentication_observer;
321   GCredentials *crendentials;
322 };
323
324 typedef struct ExportedObject ExportedObject;
325 static void exported_object_free (ExportedObject *eo);
326
327 typedef struct ExportedSubtree ExportedSubtree;
328 static void exported_subtree_free (ExportedSubtree *es);
329
330 enum
331 {
332   CLOSED_SIGNAL,
333   LAST_SIGNAL,
334 };
335
336 enum
337 {
338   PROP_0,
339   PROP_STREAM,
340   PROP_ADDRESS,
341   PROP_FLAGS,
342   PROP_GUID,
343   PROP_UNIQUE_NAME,
344   PROP_CLOSED,
345   PROP_EXIT_ON_CLOSE,
346   PROP_CAPABILITY_FLAGS,
347   PROP_AUTHENTICATION_OBSERVER,
348 };
349
350 static void distribute_signals (GDBusConnection  *connection,
351                                 GDBusMessage     *message);
352
353 static void distribute_method_call (GDBusConnection  *connection,
354                                     GDBusMessage     *message);
355
356 static gboolean handle_generic_unlocked (GDBusConnection *connection,
357                                          GDBusMessage    *message);
358
359
360 static void purge_all_signal_subscriptions (GDBusConnection *connection);
361 static void purge_all_filters (GDBusConnection *connection);
362
363 #define _G_ENSURE_LOCK(name) do {                                       \
364     if (G_UNLIKELY (G_TRYLOCK(name)))                                   \
365       {                                                                 \
366         g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
367                              "_G_ENSURE_LOCK: Lock `" #name "' is not locked"); \
368       }                                                                 \
369   } while (FALSE)                                                       \
370
371 static guint signals[LAST_SIGNAL] = { 0 };
372
373 static void initable_iface_init       (GInitableIface      *initable_iface);
374 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
375
376 G_DEFINE_TYPE_WITH_CODE (GDBusConnection, g_dbus_connection, G_TYPE_OBJECT,
377                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
378                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
379                          );
380
381 static void
382 g_dbus_connection_dispose (GObject *object)
383 {
384   GDBusConnection *connection = G_DBUS_CONNECTION (object);
385
386   G_LOCK (message_bus_lock);
387   //g_debug ("disposing %p", connection);
388   if (connection == the_session_bus)
389     {
390       the_session_bus = NULL;
391     }
392   else if (connection == the_system_bus)
393     {
394       the_system_bus = NULL;
395     }
396   if (connection->worker != NULL)
397     {
398       _g_dbus_worker_stop (connection->worker);
399       connection->worker = NULL;
400     }
401   G_UNLOCK (message_bus_lock);
402
403   if (G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose != NULL)
404     G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose (object);
405 }
406
407 static void
408 g_dbus_connection_finalize (GObject *object)
409 {
410   GDBusConnection *connection = G_DBUS_CONNECTION (object);
411
412   if (connection->authentication_observer != NULL)
413     g_object_unref (connection->authentication_observer);
414
415   if (connection->auth != NULL)
416     g_object_unref (connection->auth);
417
418   //g_debug ("finalizing %p", connection);
419   if (connection->stream != NULL)
420     {
421       /* We don't really care if closing the stream succeeds or not */
422       g_io_stream_close_async (connection->stream,
423                                G_PRIORITY_DEFAULT,
424                                NULL,  /* GCancellable */
425                                NULL,  /* GAsyncReadyCallback */
426                                NULL); /* userdata */
427       g_object_unref (connection->stream);
428       connection->stream = NULL;
429     }
430
431   g_free (connection->address);
432
433   g_free (connection->guid);
434   g_free (connection->bus_unique_name);
435
436   if (connection->initialization_error != NULL)
437     g_error_free (connection->initialization_error);
438
439   g_hash_table_unref (connection->map_method_serial_to_send_message_data);
440
441   purge_all_signal_subscriptions (connection);
442   g_hash_table_unref (connection->map_rule_to_signal_data);
443   g_hash_table_unref (connection->map_id_to_signal_data);
444   g_hash_table_unref (connection->map_sender_unique_name_to_signal_data_array);
445
446   g_hash_table_unref (connection->map_id_to_ei);
447   g_hash_table_unref (connection->map_object_path_to_eo);
448   g_hash_table_unref (connection->map_id_to_es);
449   g_hash_table_unref (connection->map_object_path_to_es);
450
451   purge_all_filters (connection);
452   g_ptr_array_unref (connection->filters);
453
454   if (connection->main_context_at_construction != NULL)
455     g_main_context_unref (connection->main_context_at_construction);
456
457   g_free (connection->machine_id);
458
459   g_mutex_free (connection->init_lock);
460   g_mutex_free (connection->lock);
461
462   G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize (object);
463 }
464
465 static void
466 g_dbus_connection_get_property (GObject    *object,
467                                 guint       prop_id,
468                                 GValue     *value,
469                                 GParamSpec *pspec)
470 {
471   GDBusConnection *connection = G_DBUS_CONNECTION (object);
472
473   switch (prop_id)
474     {
475     case PROP_STREAM:
476       g_value_set_object (value, g_dbus_connection_get_stream (connection));
477       break;
478
479     case PROP_GUID:
480       g_value_set_string (value, g_dbus_connection_get_guid (connection));
481       break;
482
483     case PROP_UNIQUE_NAME:
484       g_value_set_string (value, g_dbus_connection_get_unique_name (connection));
485       break;
486
487     case PROP_CLOSED:
488       g_value_set_boolean (value, g_dbus_connection_is_closed (connection));
489       break;
490
491     case PROP_EXIT_ON_CLOSE:
492       g_value_set_boolean (value, g_dbus_connection_get_exit_on_close (connection));
493       break;
494
495     case PROP_CAPABILITY_FLAGS:
496       g_value_set_flags (value, g_dbus_connection_get_capabilities (connection));
497       break;
498
499     default:
500       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
501       break;
502     }
503 }
504
505 static void
506 g_dbus_connection_set_property (GObject      *object,
507                                 guint         prop_id,
508                                 const GValue *value,
509                                 GParamSpec   *pspec)
510 {
511   GDBusConnection *connection = G_DBUS_CONNECTION (object);
512
513   switch (prop_id)
514     {
515     case PROP_STREAM:
516       connection->stream = g_value_dup_object (value);
517       break;
518
519     case PROP_GUID:
520       connection->guid = g_value_dup_string (value);
521       break;
522
523     case PROP_ADDRESS:
524       connection->address = g_value_dup_string (value);
525       break;
526
527     case PROP_FLAGS:
528       connection->flags = g_value_get_flags (value);
529       break;
530
531     case PROP_EXIT_ON_CLOSE:
532       g_dbus_connection_set_exit_on_close (connection, g_value_get_boolean (value));
533       break;
534
535     case PROP_AUTHENTICATION_OBSERVER:
536       connection->authentication_observer = g_value_dup_object (value);
537       break;
538
539     default:
540       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
541       break;
542     }
543 }
544
545 static void
546 g_dbus_connection_real_closed (GDBusConnection *connection,
547                                gboolean         remote_peer_vanished,
548                                GError          *error)
549 {
550   if (remote_peer_vanished && connection->exit_on_close)
551     {
552       g_print ("%s: Remote peer vanished. Exiting.\n", G_STRFUNC);
553       raise (SIGTERM);
554     }
555 }
556
557 static void
558 g_dbus_connection_class_init (GDBusConnectionClass *klass)
559 {
560   GObjectClass *gobject_class;
561
562   gobject_class = G_OBJECT_CLASS (klass);
563
564   gobject_class->finalize     = g_dbus_connection_finalize;
565   gobject_class->dispose      = g_dbus_connection_dispose;
566   gobject_class->set_property = g_dbus_connection_set_property;
567   gobject_class->get_property = g_dbus_connection_get_property;
568
569   klass->closed = g_dbus_connection_real_closed;
570
571   /**
572    * GDBusConnection:stream:
573    *
574    * The underlying #GIOStream used for I/O.
575    *
576    * Since: 2.26
577    */
578   g_object_class_install_property (gobject_class,
579                                    PROP_STREAM,
580                                    g_param_spec_object ("stream",
581                                                         P_("IO Stream"),
582                                                         P_("The underlying streams used for I/O"),
583                                                         G_TYPE_IO_STREAM,
584                                                         G_PARAM_READABLE |
585                                                         G_PARAM_WRITABLE |
586                                                         G_PARAM_CONSTRUCT_ONLY |
587                                                         G_PARAM_STATIC_NAME |
588                                                         G_PARAM_STATIC_BLURB |
589                                                         G_PARAM_STATIC_NICK));
590
591   /**
592    * GDBusConnection:address:
593    *
594    * A D-Bus address specifying potential endpoints that can be used
595    * when establishing the connection.
596    *
597    * Since: 2.26
598    */
599   g_object_class_install_property (gobject_class,
600                                    PROP_ADDRESS,
601                                    g_param_spec_string ("address",
602                                                         P_("Address"),
603                                                         P_("D-Bus address specifying potential socket endpoints"),
604                                                         NULL,
605                                                         G_PARAM_WRITABLE |
606                                                         G_PARAM_CONSTRUCT_ONLY |
607                                                         G_PARAM_STATIC_NAME |
608                                                         G_PARAM_STATIC_BLURB |
609                                                         G_PARAM_STATIC_NICK));
610
611   /**
612    * GDBusConnection:flags:
613    *
614    * Flags from the #GDBusConnectionFlags enumeration.
615    *
616    * Since: 2.26
617    */
618   g_object_class_install_property (gobject_class,
619                                    PROP_FLAGS,
620                                    g_param_spec_flags ("flags",
621                                                        P_("Flags"),
622                                                        P_("Flags"),
623                                                        G_TYPE_DBUS_CONNECTION_FLAGS,
624                                                        G_DBUS_CONNECTION_FLAGS_NONE,
625                                                        G_PARAM_WRITABLE |
626                                                        G_PARAM_CONSTRUCT_ONLY |
627                                                        G_PARAM_STATIC_NAME |
628                                                        G_PARAM_STATIC_BLURB |
629                                                        G_PARAM_STATIC_NICK));
630
631   /**
632    * GDBusConnection:guid:
633    *
634    * The GUID of the peer performing the role of server when
635    * authenticating.
636    *
637    * If you are constructing a #GDBusConnection and pass
638    * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER in the
639    * #GDBusConnection:flags property then you MUST also set this
640    * property to a valid guid.
641    *
642    * If you are constructing a #GDBusConnection and pass
643    * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT in the
644    * #GDBusConnection:flags property you will be able to read the GUID
645    * of the other peer here after the connection has been successfully
646    * initialized.
647    *
648    * Since: 2.26
649    */
650   g_object_class_install_property (gobject_class,
651                                    PROP_GUID,
652                                    g_param_spec_string ("guid",
653                                                         P_("GUID"),
654                                                         P_("GUID of the server peer"),
655                                                         NULL,
656                                                         G_PARAM_READABLE |
657                                                         G_PARAM_WRITABLE |
658                                                         G_PARAM_CONSTRUCT_ONLY |
659                                                         G_PARAM_STATIC_NAME |
660                                                         G_PARAM_STATIC_BLURB |
661                                                         G_PARAM_STATIC_NICK));
662
663   /**
664    * GDBusConnection:unique-name:
665    *
666    * The unique name as assigned by the message bus or %NULL if the
667    * connection is not open or not a message bus connection.
668    *
669    * Since: 2.26
670    */
671   g_object_class_install_property (gobject_class,
672                                    PROP_UNIQUE_NAME,
673                                    g_param_spec_string ("unique-name",
674                                                         P_("unique-name"),
675                                                         P_("Unique name of bus connection"),
676                                                         NULL,
677                                                         G_PARAM_READABLE |
678                                                         G_PARAM_STATIC_NAME |
679                                                         G_PARAM_STATIC_BLURB |
680                                                         G_PARAM_STATIC_NICK));
681
682   /**
683    * GDBusConnection:closed:
684    *
685    * A boolean specifying whether the connection has been closed.
686    *
687    * Since: 2.26
688    */
689   g_object_class_install_property (gobject_class,
690                                    PROP_CLOSED,
691                                    g_param_spec_boolean ("closed",
692                                                          P_("Closed"),
693                                                          P_("Whether the connection is closed"),
694                                                          FALSE,
695                                                          G_PARAM_READABLE |
696                                                          G_PARAM_STATIC_NAME |
697                                                          G_PARAM_STATIC_BLURB |
698                                                          G_PARAM_STATIC_NICK));
699
700   /**
701    * GDBusConnection:exit-on-close:
702    *
703    * A boolean specifying whether the process will be terminated (by
704    * calling <literal>raise(SIGTERM)</literal>) if the connection
705    * is closed by the remote peer.
706    *
707    * Since: 2.26
708    */
709   g_object_class_install_property (gobject_class,
710                                    PROP_EXIT_ON_CLOSE,
711                                    g_param_spec_boolean ("exit-on-close",
712                                                          P_("Exit on close"),
713                                                          P_("Whether the process is terminated when the connection is closed"),
714                                                          FALSE,
715                                                          G_PARAM_READABLE |
716                                                          G_PARAM_WRITABLE |
717                                                          G_PARAM_STATIC_NAME |
718                                                          G_PARAM_STATIC_BLURB |
719                                                          G_PARAM_STATIC_NICK));
720
721   /**
722    * GDBusConnection:capabilities:
723    *
724    * Flags from the #GDBusCapabilityFlags enumeration
725    * representing connection features negotiated with the other peer.
726    *
727    * Since: 2.26
728    */
729   g_object_class_install_property (gobject_class,
730                                    PROP_CAPABILITY_FLAGS,
731                                    g_param_spec_flags ("capabilities",
732                                                        P_("Capabilities"),
733                                                        P_("Capabilities"),
734                                                        G_TYPE_DBUS_CAPABILITY_FLAGS,
735                                                        G_DBUS_CAPABILITY_FLAGS_NONE,
736                                                        G_PARAM_READABLE |
737                                                        G_PARAM_STATIC_NAME |
738                                                        G_PARAM_STATIC_BLURB |
739                                                        G_PARAM_STATIC_NICK));
740
741   /**
742    * GDBusConnection:authentication-observer:
743    *
744    * A #GDBusAuthObserver object to assist in the authentication process or %NULL.
745    *
746    * Since: 2.26
747    */
748   g_object_class_install_property (gobject_class,
749                                    PROP_AUTHENTICATION_OBSERVER,
750                                    g_param_spec_object ("authentication-observer",
751                                                         P_("Authentication Observer"),
752                                                         P_("Object used to assist in the authentication process"),
753                                                         G_TYPE_DBUS_AUTH_OBSERVER,
754                                                         G_PARAM_WRITABLE |
755                                                         G_PARAM_CONSTRUCT_ONLY |
756                                                         G_PARAM_STATIC_NAME |
757                                                         G_PARAM_STATIC_BLURB |
758                                                         G_PARAM_STATIC_NICK));
759
760   /**
761    * GDBusConnection::closed:
762    * @connection: The #GDBusConnection emitting the signal.
763    * @remote_peer_vanished: %TRUE if @connection is closed because the
764    * remote peer closed its end of the connection.
765    * @error: A #GError with more details about the event or %NULL.
766    *
767    * Emitted when the connection is closed.
768    *
769    * The cause of this event can be
770    * <itemizedlist>
771    * <listitem><para>
772    *    If g_dbus_connection_close() is called. In this case
773    *    @remote_peer_vanished is set to %FALSE and @error is %NULL.
774    * </para></listitem>
775    * <listitem><para>
776    *    If the remote peer closes the connection. In this case
777    *    @remote_peer_vanished is set to %TRUE and @error is set.
778    * </para></listitem>
779    * <listitem><para>
780    *    If the remote peer sends invalid or malformed data. In this
781    *    case @remote_peer_vanished is set to %FALSE and @error
782    *    is set.
783    * </para></listitem>
784    * </itemizedlist>
785    *
786    * Upon receiving this signal, you should give up your reference to
787    * @connection. You are guaranteed that this signal is emitted only
788    * once.
789    *
790    * Since: 2.26
791    */
792   signals[CLOSED_SIGNAL] = g_signal_new ("closed",
793                                          G_TYPE_DBUS_CONNECTION,
794                                          G_SIGNAL_RUN_LAST,
795                                          G_STRUCT_OFFSET (GDBusConnectionClass, closed),
796                                          NULL,
797                                          NULL,
798                                          _gio_marshal_VOID__BOOLEAN_BOXED,
799                                          G_TYPE_NONE,
800                                          2,
801                                          G_TYPE_BOOLEAN,
802                                          G_TYPE_ERROR);
803 }
804
805 static void
806 g_dbus_connection_init (GDBusConnection *connection)
807 {
808   connection->lock = g_mutex_new ();
809   connection->init_lock = g_mutex_new ();
810
811   connection->map_method_serial_to_send_message_data = g_hash_table_new (g_direct_hash, g_direct_equal);
812
813   connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash,
814                                                           g_str_equal);
815   connection->map_id_to_signal_data = g_hash_table_new (g_direct_hash,
816                                                         g_direct_equal);
817   connection->map_sender_unique_name_to_signal_data_array = g_hash_table_new_full (g_str_hash,
818                                                                                    g_str_equal,
819                                                                                    g_free,
820                                                                                    NULL);
821
822   connection->map_object_path_to_eo = g_hash_table_new_full (g_str_hash,
823                                                              g_str_equal,
824                                                              NULL,
825                                                              (GDestroyNotify) exported_object_free);
826
827   connection->map_id_to_ei = g_hash_table_new (g_direct_hash,
828                                                g_direct_equal);
829
830   connection->map_object_path_to_es = g_hash_table_new_full (g_str_hash,
831                                                              g_str_equal,
832                                                              NULL,
833                                                              (GDestroyNotify) exported_subtree_free);
834
835   connection->map_id_to_es = g_hash_table_new (g_direct_hash,
836                                                g_direct_equal);
837
838   connection->main_context_at_construction = g_main_context_get_thread_default ();
839   if (connection->main_context_at_construction != NULL)
840     g_main_context_ref (connection->main_context_at_construction);
841
842   connection->filters = g_ptr_array_new ();
843 }
844
845 /**
846  * g_dbus_connection_get_stream:
847  * @connection: a #GDBusConnection
848  *
849  * Gets the underlying stream used for IO.
850  *
851  * Returns: the stream used for IO
852  *
853  * Since: 2.26
854  */
855 GIOStream *
856 g_dbus_connection_get_stream (GDBusConnection *connection)
857 {
858   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
859   return connection->stream;
860 }
861
862 /**
863  * g_dbus_connection_start_message_processing:
864  * @connection: A #GDBusConnection.
865  *
866  * If @connection was created with
867  * %G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, this method
868  * starts processing messages. Does nothing on if @connection wasn't
869  * created with this flag or if the method has already been called.
870  *
871  * Since: 2.26
872  */
873 void
874 g_dbus_connection_start_message_processing (GDBusConnection *connection)
875 {
876   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
877   _g_dbus_worker_unfreeze (connection->worker);
878 }
879
880 /**
881  * g_dbus_connection_is_closed:
882  * @connection: A #GDBusConnection.
883  *
884  * Gets whether @connection is closed.
885  *
886  * Returns: %TRUE if the connection is closed, %FALSE otherwise.
887  *
888  * Since: 2.26
889  */
890 gboolean
891 g_dbus_connection_is_closed (GDBusConnection *connection)
892 {
893   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
894   return connection->closed;
895 }
896
897 /**
898  * g_dbus_connection_get_capabilities:
899  * @connection: A #GDBusConnection.
900  *
901  * Gets the capabilities negotiated with the remote peer
902  *
903  * Returns: Zero or more flags from the #GDBusCapabilityFlags enumeration.
904  *
905  * Since: 2.26
906  */
907 GDBusCapabilityFlags
908 g_dbus_connection_get_capabilities (GDBusConnection *connection)
909 {
910   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_DBUS_CAPABILITY_FLAGS_NONE);
911   return connection->capabilities;
912 }
913
914 /* ---------------------------------------------------------------------------------------------------- */
915
916 static void
917 flush_in_thread_func (GSimpleAsyncResult *res,
918                       GObject            *object,
919                       GCancellable       *cancellable)
920 {
921   GError *error;
922
923   error = NULL;
924   if (!g_dbus_connection_flush_sync (G_DBUS_CONNECTION (object),
925                                      cancellable,
926                                      &error))
927     {
928       g_simple_async_result_set_from_error (res, error);
929       g_error_free (error);
930     }
931 }
932
933 /**
934  * g_dbus_connection_flush:
935  * @connection: A #GDBusConnection.
936  * @cancellable: A #GCancellable or %NULL.
937  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
938  * care about the result.
939  * @user_data: The data to pass to @callback.
940  *
941  * Asynchronously flushes @connection, that is, writes all queued
942  * outgoing message to the transport and then flushes the transport
943  * (using g_output_stream_flush_async()). This is useful in programs
944  * that wants to emit a D-Bus signal and then exit
945  * immediately. Without flushing the connection, there is no guarantee
946  * that the message has been sent to the networking buffers in the OS
947  * kernel.
948  *
949  * This is an asynchronous method. When the operation is finished,
950  * @callback will be invoked in the <link
951  * linkend="g-main-context-push-thread-default">thread-default main
952  * loop</link> of the thread you are calling this method from. You can
953  * then call g_dbus_connection_flush_finish() to get the result of the
954  * operation.  See g_dbus_connection_flush_sync() for the synchronous
955  * version.
956  *
957  * Since: 2.26
958  */
959 void
960 g_dbus_connection_flush (GDBusConnection     *connection,
961                          GCancellable        *cancellable,
962                          GAsyncReadyCallback  callback,
963                          gpointer             user_data)
964 {
965   GSimpleAsyncResult *simple;
966
967   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
968
969   simple = g_simple_async_result_new (NULL,
970                                       callback,
971                                       user_data,
972                                       g_dbus_connection_flush);
973   g_simple_async_result_run_in_thread (simple,
974                                        flush_in_thread_func,
975                                        G_PRIORITY_DEFAULT,
976                                        cancellable);
977   g_object_unref (simple);
978 }
979
980 /**
981  * g_dbus_connection_flush_finish:
982  * @connection: A #GDBusConnection.
983  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_flush().
984  * @error: Return location for error or %NULL.
985  *
986  * Finishes an operation started with g_dbus_connection_flush().
987  *
988  * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
989  *
990  * Since: 2.26
991  */
992 gboolean
993 g_dbus_connection_flush_finish (GDBusConnection  *connection,
994                                 GAsyncResult     *res,
995                                 GError          **error)
996 {
997   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
998   gboolean ret;
999
1000   ret = FALSE;
1001
1002   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1003   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
1004   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1005
1006   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_flush);
1007
1008   if (g_simple_async_result_propagate_error (simple, error))
1009     goto out;
1010
1011   ret = TRUE;
1012
1013  out:
1014   return ret;
1015 }
1016
1017 /**
1018  * g_dbus_connection_flush_sync:
1019  * @connection: A #GDBusConnection.
1020  * @cancellable: A #GCancellable or %NULL.
1021  * @error: Return location for error or %NULL.
1022  *
1023  * Synchronously flushes @connection. The calling thread is blocked
1024  * until this is done. See g_dbus_connection_flush() for the
1025  * asynchronous version of this method and more details about what it
1026  * does.
1027  *
1028  * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
1029  *
1030  * Since: 2.26
1031  */
1032 gboolean
1033 g_dbus_connection_flush_sync (GDBusConnection  *connection,
1034                               GCancellable     *cancellable,
1035                               GError          **error)
1036 {
1037   gboolean ret;
1038
1039   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1040
1041   ret = FALSE;
1042
1043   if (connection->closed)
1044     {
1045       g_set_error_literal (error,
1046                            G_IO_ERROR,
1047                            G_IO_ERROR_CLOSED,
1048                            _("The connection is closed"));
1049       goto out;
1050     }
1051
1052   ret = _g_dbus_worker_flush_sync (connection->worker,
1053                                    cancellable,
1054                                    error);
1055
1056  out:
1057   return ret;
1058 }
1059
1060 /* ---------------------------------------------------------------------------------------------------- */
1061
1062 typedef struct
1063 {
1064   GDBusConnection *connection;
1065   GError *error;
1066   gboolean remote_peer_vanished;
1067 } EmitClosedData;
1068
1069 static void
1070 emit_closed_data_free (EmitClosedData *data)
1071 {
1072   g_object_unref (data->connection);
1073   if (data->error != NULL)
1074     g_error_free (data->error);
1075   g_free (data);
1076 }
1077
1078 static gboolean
1079 emit_closed_in_idle (gpointer user_data)
1080 {
1081   EmitClosedData *data = user_data;
1082   gboolean result;
1083
1084   g_object_notify (G_OBJECT (data->connection), "closed");
1085   g_signal_emit (data->connection,
1086                  signals[CLOSED_SIGNAL],
1087                  0,
1088                  data->remote_peer_vanished,
1089                  data->error,
1090                  &result);
1091   return FALSE;
1092 }
1093
1094 /* Can be called from any thread, must hold lock */
1095 static void
1096 set_closed_unlocked (GDBusConnection *connection,
1097                      gboolean         remote_peer_vanished,
1098                      GError          *error)
1099 {
1100   GSource *idle_source;
1101   EmitClosedData *data;
1102
1103   CONNECTION_ENSURE_LOCK (connection);
1104
1105   g_assert (!connection->closed);
1106
1107   connection->closed = TRUE;
1108
1109   data = g_new0 (EmitClosedData, 1);
1110   data->connection = g_object_ref (connection);
1111   data->remote_peer_vanished = remote_peer_vanished;
1112   data->error = error != NULL ? g_error_copy (error) : NULL;
1113
1114   idle_source = g_idle_source_new ();
1115   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
1116   g_source_set_callback (idle_source,
1117                          emit_closed_in_idle,
1118                          data,
1119                          (GDestroyNotify) emit_closed_data_free);
1120   g_source_attach (idle_source, connection->main_context_at_construction);
1121   g_source_unref (idle_source);
1122 }
1123
1124 /* ---------------------------------------------------------------------------------------------------- */
1125
1126 /**
1127  * g_dbus_connection_close:
1128  * @connection: A #GDBusConnection.
1129  *
1130  * Closes @connection. Note that this never causes the process to
1131  * exit (this might only happen if the other end of a shared message
1132  * bus connection disconnects, see #GDBusConnection:exit-on-close).
1133  *
1134  * Once the stream is closed, all operations will return
1135  * %G_IO_ERROR_CLOSED.
1136  *
1137  * Note that closing a connection will not automatically flush the
1138  * connection so queued messages may be lost. Use
1139  * g_dbus_connection_flush() if you need such guarantees.
1140  *
1141  * If @connection is already closed, this method does nothing.
1142  *
1143  * Since: 2.26
1144  */
1145 void
1146 g_dbus_connection_close (GDBusConnection *connection)
1147 {
1148   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1149
1150   CONNECTION_LOCK (connection);
1151   if (!connection->closed)
1152     {
1153       GError *error = NULL;
1154
1155       /* TODO: do this async */
1156       //g_debug ("closing connection %p's stream %p", connection, connection->stream);
1157       if (!g_io_stream_close (connection->stream, NULL, &error))
1158         {
1159           g_warning ("Error closing stream: %s", error->message);
1160           g_error_free (error);
1161         }
1162
1163       set_closed_unlocked (connection, FALSE, NULL);
1164     }
1165   CONNECTION_UNLOCK (connection);
1166 }
1167
1168 /* ---------------------------------------------------------------------------------------------------- */
1169
1170 static gboolean
1171 g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
1172                                          GDBusMessage      *message,
1173                                          volatile guint32  *out_serial,
1174                                          GError           **error)
1175 {
1176   guchar *blob;
1177   gsize blob_size;
1178   guint32 serial_to_use;
1179   gboolean ret;
1180
1181   CONNECTION_ENSURE_LOCK (connection);
1182
1183   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1184   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1185
1186   /* TODO: check all necessary headers are present */
1187
1188   ret = FALSE;
1189   blob = NULL;
1190
1191   if (out_serial != NULL)
1192     *out_serial = 0;
1193
1194   if (connection->closed)
1195     {
1196       g_set_error_literal (error,
1197                            G_IO_ERROR,
1198                            G_IO_ERROR_CLOSED,
1199                            _("The connection is closed"));
1200       goto out;
1201     }
1202
1203   blob = g_dbus_message_to_blob (message,
1204                                  &blob_size,
1205                                  connection->capabilities,
1206                                  error);
1207   if (blob == NULL)
1208     goto out;
1209
1210   serial_to_use = g_dbus_message_get_serial (message);
1211   if (serial_to_use == 0)
1212     {
1213       serial_to_use = ++connection->last_serial; /* TODO: handle overflow */
1214     }
1215
1216   switch (blob[0])
1217     {
1218     case 'l':
1219       ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
1220       break;
1221     case 'B':
1222       ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
1223       break;
1224     default:
1225       g_assert_not_reached ();
1226       break;
1227     }
1228
1229 #if 0
1230   g_printerr ("Writing message of %" G_GSIZE_FORMAT " bytes (serial %d) on %p:\n",
1231               blob_size, serial_to_use, connection);
1232   g_printerr ("----\n");
1233   hexdump (blob, blob_size);
1234   g_printerr ("----\n");
1235 #endif
1236
1237   /* TODO: use connection->auth to encode the blob */
1238
1239   if (out_serial != NULL)
1240     *out_serial = serial_to_use;
1241
1242   g_dbus_message_set_serial (message, serial_to_use);
1243
1244   _g_dbus_worker_send_message (connection->worker,
1245                                message,
1246                                (gchar*) blob,
1247                                blob_size);
1248   blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
1249
1250   ret = TRUE;
1251
1252  out:
1253   g_free (blob);
1254
1255   return ret;
1256 }
1257
1258 /**
1259  * g_dbus_connection_send_message:
1260  * @connection: A #GDBusConnection.
1261  * @message: A #GDBusMessage
1262  * @out_serial: Return location for serial number assigned to @message when sending it or %NULL.
1263  * @error: Return location for error or %NULL.
1264  *
1265  * Asynchronously sends @message to the peer represented by @connection.
1266  *
1267  * If g_dbus_message_get_serial() returns non-zero for @message, then
1268  * that value is used for the message serial number. Otherwise a
1269  * serial number will be assigned by @connection and set on @message
1270  * via g_dbus_message_set_serial(). If @out_serial is not %NULL, then
1271  * the serial number used will be written to this location prior to
1272  * submitting the message to the underlying transport.
1273  *
1274  * If @connection is closed then the operation will fail with
1275  * %G_IO_ERROR_CLOSED. If @message is not well-formed,
1276  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1277  *
1278  * See <xref linkend="gdbus-server"/> and <xref
1279  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1280  * low-level API to send and receive UNIX file descriptors.
1281  *
1282  * Returns: %TRUE if the message was well-formed and queued for
1283  * transmission, %FALSE if @error is set.
1284  *
1285  * Since: 2.26
1286  */
1287 gboolean
1288 g_dbus_connection_send_message (GDBusConnection   *connection,
1289                                 GDBusMessage      *message,
1290                                 volatile guint32  *out_serial,
1291                                 GError           **error)
1292 {
1293   gboolean ret;
1294
1295   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1296   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1297   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1298
1299   CONNECTION_LOCK (connection);
1300   ret = g_dbus_connection_send_message_unlocked (connection, message, out_serial, error);
1301   CONNECTION_UNLOCK (connection);
1302   return ret;
1303 }
1304
1305 /* ---------------------------------------------------------------------------------------------------- */
1306
1307 typedef struct
1308 {
1309   volatile gint ref_count;
1310   GDBusConnection *connection;
1311   guint32 serial;
1312   GSimpleAsyncResult *simple;
1313
1314   GMainContext *main_context;
1315
1316   GCancellable *cancellable;
1317
1318   gulong cancellable_handler_id;
1319
1320   GSource *timeout_source;
1321
1322   gboolean delivered;
1323 } SendMessageData;
1324
1325 static SendMessageData *
1326 send_message_data_ref (SendMessageData *data)
1327 {
1328   g_atomic_int_inc (&data->ref_count);
1329   return data;
1330 }
1331
1332 static void
1333 send_message_data_unref (SendMessageData *data)
1334 {
1335   if (g_atomic_int_dec_and_test (&data->ref_count))
1336     {
1337       g_assert (data->timeout_source == NULL);
1338       g_assert (data->simple == NULL);
1339       g_assert (data->cancellable_handler_id == 0);
1340       g_object_unref (data->connection);
1341       if (data->cancellable != NULL)
1342         g_object_unref (data->cancellable);
1343       if (data->main_context != NULL)
1344         g_main_context_unref (data->main_context);
1345       g_free (data);
1346     }
1347 }
1348
1349 /* ---------------------------------------------------------------------------------------------------- */
1350
1351 /* can be called from any thread with lock held - caller must have prepared GSimpleAsyncResult already */
1352 static void
1353 send_message_with_reply_deliver (SendMessageData *data)
1354 {
1355   CONNECTION_ENSURE_LOCK (data->connection);
1356
1357   g_assert (!data->delivered);
1358
1359   data->delivered = TRUE;
1360
1361   g_simple_async_result_complete_in_idle (data->simple);
1362   g_object_unref (data->simple);
1363   data->simple = NULL;
1364
1365   if (data->timeout_source != NULL)
1366     {
1367       g_source_destroy (data->timeout_source);
1368       data->timeout_source = NULL;
1369     }
1370   if (data->cancellable_handler_id > 0)
1371     {
1372       g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
1373       data->cancellable_handler_id = 0;
1374     }
1375
1376   g_warn_if_fail (g_hash_table_remove (data->connection->map_method_serial_to_send_message_data,
1377                                        GUINT_TO_POINTER (data->serial)));
1378
1379   send_message_data_unref (data);
1380 }
1381
1382 /* ---------------------------------------------------------------------------------------------------- */
1383
1384 /* must hold lock */
1385 static void
1386 send_message_data_deliver_reply_unlocked (SendMessageData *data,
1387                                           GDBusMessage    *reply)
1388 {
1389   if (data->delivered)
1390     goto out;
1391
1392   g_simple_async_result_set_op_res_gpointer (data->simple,
1393                                              g_object_ref (reply),
1394                                              g_object_unref);
1395
1396   send_message_with_reply_deliver (data);
1397
1398  out:
1399   ;
1400 }
1401
1402 /* ---------------------------------------------------------------------------------------------------- */
1403
1404 static gboolean
1405 send_message_with_reply_cancelled_idle_cb (gpointer user_data)
1406 {
1407   SendMessageData *data = user_data;
1408
1409   CONNECTION_LOCK (data->connection);
1410   if (data->delivered)
1411     goto out;
1412
1413   g_simple_async_result_set_error (data->simple,
1414                                    G_IO_ERROR,
1415                                    G_IO_ERROR_CANCELLED,
1416                                    _("Operation was cancelled"));
1417
1418   send_message_with_reply_deliver (data);
1419
1420  out:
1421   CONNECTION_UNLOCK (data->connection);
1422   return FALSE;
1423 }
1424
1425 /* Can be called from any thread with or without lock held */
1426 static void
1427 send_message_with_reply_cancelled_cb (GCancellable *cancellable,
1428                                       gpointer      user_data)
1429 {
1430   SendMessageData *data = user_data;
1431   GSource *idle_source;
1432
1433   /* postpone cancellation to idle handler since we may be called directly
1434    * via g_cancellable_connect() (e.g. holding lock)
1435    */
1436   idle_source = g_idle_source_new ();
1437   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
1438   g_source_set_callback (idle_source,
1439                          send_message_with_reply_cancelled_idle_cb,
1440                          send_message_data_ref (data),
1441                          (GDestroyNotify) send_message_data_unref);
1442   g_source_attach (idle_source, data->main_context);
1443   g_source_unref (idle_source);
1444 }
1445
1446 /* ---------------------------------------------------------------------------------------------------- */
1447
1448 static gboolean
1449 send_message_with_reply_timeout_cb (gpointer user_data)
1450 {
1451   SendMessageData *data = user_data;
1452
1453   CONNECTION_LOCK (data->connection);
1454   if (data->delivered)
1455     goto out;
1456
1457   g_simple_async_result_set_error (data->simple,
1458                                    G_IO_ERROR,
1459                                    G_IO_ERROR_TIMED_OUT,
1460                                    _("Timeout was reached"));
1461
1462   send_message_with_reply_deliver (data);
1463
1464  out:
1465   CONNECTION_UNLOCK (data->connection);
1466
1467   return FALSE;
1468 }
1469
1470 /* ---------------------------------------------------------------------------------------------------- */
1471
1472 static void
1473 g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connection,
1474                                                     GDBusMessage        *message,
1475                                                     gint                 timeout_msec,
1476                                                     volatile guint32    *out_serial,
1477                                                     GCancellable        *cancellable,
1478                                                     GAsyncReadyCallback  callback,
1479                                                     gpointer             user_data)
1480 {
1481   GSimpleAsyncResult *simple;
1482   SendMessageData *data;
1483   GError *error;
1484   volatile guint32 serial;
1485
1486   data = NULL;
1487
1488   if (out_serial == NULL)
1489     out_serial = &serial;
1490
1491   if (timeout_msec == -1)
1492     timeout_msec = 25 * 1000;
1493
1494   simple = g_simple_async_result_new (G_OBJECT (connection),
1495                                       callback,
1496                                       user_data,
1497                                       g_dbus_connection_send_message_with_reply);
1498
1499   if (g_cancellable_is_cancelled (cancellable))
1500     {
1501       g_simple_async_result_set_error (simple,
1502                                        G_IO_ERROR,
1503                                        G_IO_ERROR_CANCELLED,
1504                                        _("Operation was cancelled"));
1505       g_simple_async_result_complete_in_idle (simple);
1506       g_object_unref (simple);
1507       goto out;
1508     }
1509
1510   if (connection->closed)
1511     {
1512       g_simple_async_result_set_error (simple,
1513                                        G_IO_ERROR,
1514                                        G_IO_ERROR_CLOSED,
1515                                        _("The connection is closed"));
1516       g_simple_async_result_complete_in_idle (simple);
1517       g_object_unref (simple);
1518       goto out;
1519     }
1520
1521   error = NULL;
1522   if (!g_dbus_connection_send_message_unlocked (connection, message, out_serial, &error))
1523     {
1524       g_simple_async_result_set_from_error (simple, error);
1525       g_simple_async_result_complete_in_idle (simple);
1526       g_object_unref (simple);
1527       goto out;
1528     }
1529
1530   data = g_new0 (SendMessageData, 1);
1531   data->ref_count = 1;
1532   data->connection = g_object_ref (connection);
1533   data->simple = simple;
1534   data->serial = *out_serial;
1535   data->main_context = g_main_context_get_thread_default ();
1536   if (data->main_context != NULL)
1537     g_main_context_ref (data->main_context);
1538
1539   if (cancellable != NULL)
1540     {
1541       data->cancellable = g_object_ref (cancellable);
1542       data->cancellable_handler_id = g_cancellable_connect (cancellable,
1543                                                             G_CALLBACK (send_message_with_reply_cancelled_cb),
1544                                                             send_message_data_ref (data),
1545                                                             (GDestroyNotify) send_message_data_unref);
1546       g_object_set_data_full (G_OBJECT (simple),
1547                               "cancellable",
1548                               g_object_ref (cancellable),
1549                               (GDestroyNotify) g_object_unref);
1550     }
1551
1552   data->timeout_source = g_timeout_source_new (timeout_msec);
1553   g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
1554   g_source_set_callback (data->timeout_source,
1555                          send_message_with_reply_timeout_cb,
1556                          send_message_data_ref (data),
1557                          (GDestroyNotify) send_message_data_unref);
1558   g_source_attach (data->timeout_source, data->main_context);
1559   g_source_unref (data->timeout_source);
1560
1561   g_hash_table_insert (connection->map_method_serial_to_send_message_data,
1562                        GUINT_TO_POINTER (*out_serial),
1563                        data);
1564
1565  out:
1566   ;
1567 }
1568
1569 /**
1570  * g_dbus_connection_send_message_with_reply:
1571  * @connection: A #GDBusConnection.
1572  * @message: A #GDBusMessage.
1573  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
1574  * @out_serial: Return location for serial number assigned to @message when sending it or %NULL.
1575  * @cancellable: A #GCancellable or %NULL.
1576  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
1577  * care about the result.
1578  * @user_data: The data to pass to @callback.
1579  *
1580  * Asynchronously sends @message to the peer represented by @connection.
1581  *
1582  * If g_dbus_message_get_serial() returns non-zero for @message, then
1583  * that value is used for the message serial number. Otherwise a
1584  * serial number will be assigned by @connection and set on @message
1585  * via g_dbus_message_set_serial(). If @out_serial is not %NULL, then
1586  * the serial number used will be written to this location prior to
1587  * submitting the message to the underlying transport.
1588  *
1589  * If @connection is closed then the operation will fail with
1590  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
1591  * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
1592  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1593  *
1594  * This is an asynchronous method. When the operation is finished, @callback will be invoked
1595  * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
1596  * of the thread you are calling this method from. You can then call
1597  * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
1598  * See g_dbus_connection_send_message_with_reply_sync() for the synchronous version.
1599  *
1600  * See <xref linkend="gdbus-server"/> and <xref
1601  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1602  * low-level API to send and receive UNIX file descriptors.
1603  *
1604  * Since: 2.26
1605  */
1606 void
1607 g_dbus_connection_send_message_with_reply (GDBusConnection     *connection,
1608                                            GDBusMessage        *message,
1609                                            gint                 timeout_msec,
1610                                            volatile guint32    *out_serial,
1611                                            GCancellable        *cancellable,
1612                                            GAsyncReadyCallback  callback,
1613                                            gpointer             user_data)
1614 {
1615   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1616   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1617   g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
1618
1619   CONNECTION_LOCK (connection);
1620   g_dbus_connection_send_message_with_reply_unlocked (connection,
1621                                                       message,
1622                                                       timeout_msec,
1623                                                       out_serial,
1624                                                       cancellable,
1625                                                       callback,
1626                                                       user_data);
1627   CONNECTION_UNLOCK (connection);
1628 }
1629
1630 /**
1631  * g_dbus_connection_send_message_with_reply_finish:
1632  * @connection: a #GDBusConnection
1633  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_send_message_with_reply().
1634  * @error: Return location for error or %NULL.
1635  *
1636  * Finishes an operation started with g_dbus_connection_send_message_with_reply().
1637  *
1638  * Note that @error is only set if a local in-process error
1639  * occured. That is to say that the returned #GDBusMessage object may
1640  * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
1641  * g_dbus_message_to_gerror() to transcode this to a #GError.
1642  *
1643  * See <xref linkend="gdbus-server"/> and <xref
1644  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1645  * low-level API to send and receive UNIX file descriptors.
1646  *
1647  * Returns: A #GDBusMessage or %NULL if @error is set.
1648  *
1649  * Since: 2.26
1650  */
1651 GDBusMessage *
1652 g_dbus_connection_send_message_with_reply_finish (GDBusConnection  *connection,
1653                                                   GAsyncResult     *res,
1654                                                   GError          **error)
1655 {
1656   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1657   GDBusMessage *reply;
1658   GCancellable *cancellable;
1659
1660   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1661   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1662
1663   reply = NULL;
1664
1665   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_send_message_with_reply);
1666
1667   if (g_simple_async_result_propagate_error (simple, error))
1668     goto out;
1669
1670   reply = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
1671   cancellable = g_object_get_data (G_OBJECT (simple), "cancellable");
1672   if (cancellable != NULL && g_cancellable_is_cancelled (cancellable))
1673     {
1674       g_object_unref (reply);
1675       reply = NULL;
1676       g_set_error_literal (error,
1677                            G_IO_ERROR,
1678                            G_IO_ERROR_CANCELLED,
1679                            _("Operation was cancelled"));
1680     }
1681  out:
1682   return reply;
1683 }
1684
1685 /* ---------------------------------------------------------------------------------------------------- */
1686
1687 typedef struct
1688 {
1689   GAsyncResult *res;
1690   GMainContext *context;
1691   GMainLoop *loop;
1692 } SendMessageSyncData;
1693
1694 static void
1695 send_message_with_reply_sync_cb (GDBusConnection *connection,
1696                                  GAsyncResult    *res,
1697                                  gpointer         user_data)
1698 {
1699   SendMessageSyncData *data = user_data;
1700   data->res = g_object_ref (res);
1701   g_main_loop_quit (data->loop);
1702 }
1703
1704 /**
1705  * g_dbus_connection_send_message_with_reply_sync:
1706  * @connection: A #GDBusConnection.
1707  * @message: A #GDBusMessage.
1708  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
1709  * @out_serial: Return location for serial number assigned to @message when sending it or %NULL.
1710  * @cancellable: A #GCancellable or %NULL.
1711  * @error: Return location for error or %NULL.
1712  *
1713  * Synchronously sends @message to the peer represented by @connection
1714  * and blocks the calling thread until a reply is received or the
1715  * timeout is reached. See g_dbus_connection_send_message_with_reply()
1716  * for the asynchronous version of this method.
1717  *
1718  * If g_dbus_message_get_serial() returns non-zero for @message, then
1719  * that value is used for the message serial number. Otherwise a
1720  * serial number will be assigned by @connection and set on @message
1721  * via g_dbus_message_set_serial(). If @out_serial is not %NULL, then
1722  * the serial number used will be written to this location prior to
1723  * submitting the message to the underlying transport.
1724  *
1725  * If @connection is closed then the operation will fail with
1726  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
1727  * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
1728  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1729  *
1730  * Note that @error is only set if a local in-process error
1731  * occured. That is to say that the returned #GDBusMessage object may
1732  * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
1733  * g_dbus_message_to_gerror() to transcode this to a #GError.
1734  *
1735  * See <xref linkend="gdbus-server"/> and <xref
1736  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1737  * low-level API to send and receive UNIX file descriptors.
1738  *
1739  * Returns: A #GDBusMessage that is the reply to @message or %NULL if @error is set.
1740  *
1741  * Since: 2.26
1742  */
1743 GDBusMessage *
1744 g_dbus_connection_send_message_with_reply_sync (GDBusConnection   *connection,
1745                                                 GDBusMessage      *message,
1746                                                 gint               timeout_msec,
1747                                                 volatile guint32  *out_serial,
1748                                                 GCancellable      *cancellable,
1749                                                 GError           **error)
1750 {
1751   SendMessageSyncData *data;
1752   GDBusMessage *reply;
1753
1754   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1755   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1756   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
1757   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1758
1759   data = g_new0 (SendMessageSyncData, 1);
1760   data->context = g_main_context_new ();
1761   data->loop = g_main_loop_new (data->context, FALSE);
1762
1763   g_main_context_push_thread_default (data->context);
1764
1765   g_dbus_connection_send_message_with_reply (connection,
1766                                              message,
1767                                              timeout_msec,
1768                                              out_serial,
1769                                              cancellable,
1770                                              (GAsyncReadyCallback) send_message_with_reply_sync_cb,
1771                                              data);
1772   g_main_loop_run (data->loop);
1773   reply = g_dbus_connection_send_message_with_reply_finish (connection,
1774                                                             data->res,
1775                                                             error);
1776
1777   g_main_context_pop_thread_default (data->context);
1778
1779   g_main_context_unref (data->context);
1780   g_main_loop_unref (data->loop);
1781   g_object_unref (data->res);
1782   g_free (data);
1783
1784   return reply;
1785 }
1786
1787 /* ---------------------------------------------------------------------------------------------------- */
1788
1789 typedef struct
1790 {
1791   GDBusMessageFilterFunction func;
1792   gpointer user_data;
1793 } FilterCallback;
1794
1795 typedef struct
1796 {
1797   guint                       id;
1798   GDBusMessageFilterFunction  filter_function;
1799   gpointer                    user_data;
1800   GDestroyNotify              user_data_free_func;
1801 } FilterData;
1802
1803 /* Called in worker's thread - we must not block */
1804 static void
1805 on_worker_message_received (GDBusWorker  *worker,
1806                             GDBusMessage *message,
1807                             gpointer      user_data)
1808 {
1809   GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
1810   FilterCallback *filters;
1811   gboolean consumed_by_filter;
1812   guint num_filters;
1813   guint n;
1814
1815   //g_debug ("in on_worker_message_received");
1816
1817   g_object_ref (connection);
1818
1819   /* First collect the set of callback functions */
1820   CONNECTION_LOCK (connection);
1821   num_filters = connection->filters->len;
1822   filters = g_new0 (FilterCallback, num_filters);
1823   for (n = 0; n < num_filters; n++)
1824     {
1825       FilterData *data = connection->filters->pdata[n];
1826       filters[n].func = data->filter_function;
1827       filters[n].user_data = data->user_data;
1828     }
1829   CONNECTION_UNLOCK (connection);
1830
1831   /* the call the filters in order (without holding the lock) */
1832   consumed_by_filter = FALSE;
1833   for (n = 0; n < num_filters; n++)
1834     {
1835       consumed_by_filter = filters[n].func (connection,
1836                                             message,
1837                                             TRUE,
1838                                             filters[n].user_data);
1839       if (consumed_by_filter)
1840         break;
1841     }
1842
1843   /* Standard dispatch unless the filter ate the message */
1844   if (!consumed_by_filter)
1845     {
1846       GDBusMessageType message_type;
1847
1848       message_type = g_dbus_message_get_message_type (message);
1849       if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN || message_type == G_DBUS_MESSAGE_TYPE_ERROR)
1850         {
1851           guint32 reply_serial;
1852           SendMessageData *send_message_data;
1853
1854           reply_serial = g_dbus_message_get_reply_serial (message);
1855           CONNECTION_LOCK (connection);
1856           send_message_data = g_hash_table_lookup (connection->map_method_serial_to_send_message_data,
1857                                                    GUINT_TO_POINTER (reply_serial));
1858           if (send_message_data != NULL)
1859             {
1860               //g_debug ("delivering reply/error for serial %d for %p", reply_serial, connection);
1861               send_message_data_deliver_reply_unlocked (send_message_data, message);
1862             }
1863           else
1864             {
1865               //g_debug ("message reply/error for serial %d but no SendMessageData found for %p", reply_serial, connection);
1866             }
1867           CONNECTION_UNLOCK (connection);
1868         }
1869       else if (message_type == G_DBUS_MESSAGE_TYPE_SIGNAL)
1870         {
1871           CONNECTION_LOCK (connection);
1872           distribute_signals (connection, message);
1873           CONNECTION_UNLOCK (connection);
1874         }
1875       else if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
1876         {
1877           CONNECTION_LOCK (connection);
1878           distribute_method_call (connection, message);
1879           CONNECTION_UNLOCK (connection);
1880         }
1881     }
1882
1883   g_object_unref (connection);
1884   g_free (filters);
1885 }
1886
1887 /* Called in worker's thread */
1888 static gboolean
1889 on_worker_message_about_to_be_sent (GDBusWorker  *worker,
1890                                     GDBusMessage *message,
1891                                     gpointer      user_data)
1892 {
1893   GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
1894   FilterCallback *filters;
1895   gboolean consumed_by_filter;
1896   guint num_filters;
1897   guint n;
1898
1899   //g_debug ("in on_worker_message_about_to_be_sent");
1900
1901   g_object_ref (connection);
1902
1903   /* First collect the set of callback functions */
1904   CONNECTION_LOCK (connection);
1905   num_filters = connection->filters->len;
1906   filters = g_new0 (FilterCallback, num_filters);
1907   for (n = 0; n < num_filters; n++)
1908     {
1909       FilterData *data = connection->filters->pdata[n];
1910       filters[n].func = data->filter_function;
1911       filters[n].user_data = data->user_data;
1912     }
1913   CONNECTION_UNLOCK (connection);
1914
1915   /* the call the filters in order (without holding the lock) */
1916   consumed_by_filter = FALSE;
1917   for (n = 0; n < num_filters; n++)
1918     {
1919       consumed_by_filter = filters[n].func (connection,
1920                                             message,
1921                                             FALSE,
1922                                             filters[n].user_data);
1923       if (consumed_by_filter)
1924         break;
1925     }
1926
1927   g_object_unref (connection);
1928   g_free (filters);
1929
1930   return consumed_by_filter;
1931 }
1932
1933 /* Called in worker's thread - we must not block */
1934 static void
1935 on_worker_closed (GDBusWorker *worker,
1936                   gboolean     remote_peer_vanished,
1937                   GError      *error,
1938                   gpointer     user_data)
1939 {
1940   GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
1941
1942   //g_debug ("in on_worker_closed: %s", error->message);
1943
1944   CONNECTION_LOCK (connection);
1945   if (!connection->closed)
1946     set_closed_unlocked (connection, remote_peer_vanished, error);
1947   CONNECTION_UNLOCK (connection);
1948 }
1949
1950 /* ---------------------------------------------------------------------------------------------------- */
1951
1952 /* Determines the biggest set of capabilities we can support on this connection */
1953 static GDBusCapabilityFlags
1954 get_offered_capabilities_max (GDBusConnection *connection)
1955 {
1956       GDBusCapabilityFlags ret;
1957       ret = G_DBUS_CAPABILITY_FLAGS_NONE;
1958 #ifdef G_OS_UNIX
1959       if (G_IS_UNIX_CONNECTION (connection->stream))
1960         ret |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
1961 #endif
1962       return ret;
1963 }
1964
1965 static gboolean
1966 initable_init (GInitable     *initable,
1967                GCancellable  *cancellable,
1968                GError       **error)
1969 {
1970   GDBusConnection *connection = G_DBUS_CONNECTION (initable);
1971   gboolean ret;
1972
1973   /* This method needs to be idempotent to work with the singleton
1974    * pattern. See the docs for g_initable_init(). We implement this by
1975    * locking.
1976    *
1977    * Unfortunately we can't use the main lock since the on_worker_*()
1978    * callbacks above needs the lock during initialization (for message
1979    * bus connections we do a synchronous Hello() call on the bus).
1980    */
1981   g_mutex_lock (connection->init_lock);
1982
1983   ret = FALSE;
1984
1985   if (connection->is_initialized)
1986     {
1987       if (connection->stream != NULL)
1988         ret = TRUE;
1989       else
1990         g_assert (connection->initialization_error != NULL);
1991       goto out;
1992     }
1993   g_assert (connection->initialization_error == NULL);
1994
1995   /* The user can pass multiple (but mutally exclusive) construct
1996    * properties:
1997    *
1998    *  - stream (of type GIOStream)
1999    *  - address (of type gchar*)
2000    *
2001    * At the end of the day we end up with a non-NULL GIOStream
2002    * object in connection->stream.
2003    */
2004   if (connection->address != NULL)
2005     {
2006       g_assert (connection->stream == NULL);
2007
2008       if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
2009           (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS))
2010         {
2011           g_set_error_literal (error,
2012                                G_IO_ERROR,
2013                                G_IO_ERROR_INVALID_ARGUMENT,
2014                                _("Unsupported flags encountered when constructing a client-side connection"));
2015           goto out;
2016         }
2017
2018       connection->stream = g_dbus_address_get_stream_sync (connection->address,
2019                                                            NULL, /* TODO: out_guid */
2020                                                            cancellable,
2021                                                            &connection->initialization_error);
2022       if (connection->stream == NULL)
2023         goto out;
2024     }
2025   else if (connection->stream != NULL)
2026     {
2027       /* nothing to do */
2028     }
2029   else
2030     {
2031       g_assert_not_reached ();
2032     }
2033
2034   /* Authenticate the connection */
2035   if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
2036     {
2037       g_assert (!(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT));
2038       g_assert (connection->guid != NULL);
2039       connection->auth = _g_dbus_auth_new (connection->stream);
2040       if (!_g_dbus_auth_run_server (connection->auth,
2041                                     connection->authentication_observer,
2042                                     connection->guid,
2043                                     (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS),
2044                                     get_offered_capabilities_max (connection),
2045                                     &connection->capabilities,
2046                                     &connection->crendentials,
2047                                     cancellable,
2048                                     &connection->initialization_error))
2049         goto out;
2050     }
2051   else if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT)
2052     {
2053       g_assert (!(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER));
2054       g_assert (connection->guid == NULL);
2055       connection->auth = _g_dbus_auth_new (connection->stream);
2056       connection->guid = _g_dbus_auth_run_client (connection->auth,
2057                                                   get_offered_capabilities_max (connection),
2058                                                   &connection->capabilities,
2059                                                   cancellable,
2060                                                   &connection->initialization_error);
2061       if (connection->guid == NULL)
2062         goto out;
2063     }
2064
2065   if (connection->authentication_observer != NULL)
2066     {
2067       g_object_unref (connection->authentication_observer);
2068       connection->authentication_observer = NULL;
2069     }
2070
2071   //g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
2072
2073   //g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
2074
2075 #ifdef G_OS_UNIX
2076   /* Hack used until
2077    *
2078    *  https://bugzilla.gnome.org/show_bug.cgi?id=616458
2079    *
2080    * has been resolved
2081    */
2082   if (G_IS_SOCKET_CONNECTION (connection->stream))
2083     {
2084       g_socket_set_blocking (g_socket_connection_get_socket (G_SOCKET_CONNECTION (connection->stream)), FALSE);
2085     }
2086 #endif
2087
2088   connection->worker = _g_dbus_worker_new (connection->stream,
2089                                            connection->capabilities,
2090                                            (connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING),
2091                                            on_worker_message_received,
2092                                            on_worker_message_about_to_be_sent,
2093                                            on_worker_closed,
2094                                            connection);
2095
2096   /* if a bus connection, call org.freedesktop.DBus.Hello - this is how we're getting a name */
2097   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2098     {
2099       GVariant *hello_result;
2100
2101       /* we could lift this restriction by adding code in gdbusprivate.c */
2102       if (connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING)
2103         {
2104           g_set_error_literal (&connection->initialization_error,
2105                                G_IO_ERROR,
2106                                G_IO_ERROR_FAILED,
2107                                "Cannot use DELAY_MESSAGE_PROCESSING with MESSAGE_BUS_CONNECTION");
2108           goto out;
2109         }
2110
2111       hello_result = g_dbus_connection_call_sync (connection,
2112                                                   "org.freedesktop.DBus", /* name */
2113                                                   "/org/freedesktop/DBus", /* path */
2114                                                   "org.freedesktop.DBus", /* interface */
2115                                                   "Hello",
2116                                                   NULL, /* parameters */
2117                                                   G_VARIANT_TYPE ("(s)"),
2118                                                   G_DBUS_CALL_FLAGS_NONE,
2119                                                   -1,
2120                                                   NULL, /* TODO: cancellable */
2121                                                   &connection->initialization_error);
2122       if (hello_result == NULL)
2123         goto out;
2124
2125       g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
2126       g_variant_unref (hello_result);
2127       //g_debug ("unique name is `%s'", connection->bus_unique_name);
2128     }
2129
2130   connection->is_initialized = TRUE;
2131
2132   ret = TRUE;
2133  out:
2134   if (!ret)
2135     {
2136       g_assert (connection->initialization_error != NULL);
2137       g_propagate_error (error, g_error_copy (connection->initialization_error));
2138     }
2139
2140   g_mutex_unlock (connection->init_lock);
2141
2142   return ret;
2143 }
2144
2145 static void
2146 initable_iface_init (GInitableIface *initable_iface)
2147 {
2148   initable_iface->init = initable_init;
2149 }
2150
2151 /* ---------------------------------------------------------------------------------------------------- */
2152
2153 static void
2154 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
2155 {
2156   /* Use default */
2157 }
2158
2159 /* ---------------------------------------------------------------------------------------------------- */
2160
2161 /**
2162  * g_dbus_connection_new:
2163  * @stream: A #GIOStream.
2164  * @guid: The GUID to use if a authenticating as a server or %NULL.
2165  * @flags: Flags describing how to make the connection.
2166  * @observer: A #GDBusAuthObserver or %NULL.
2167  * @cancellable: A #GCancellable or %NULL.
2168  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
2169  * @user_data: The data to pass to @callback.
2170  *
2171  * Asynchronously sets up a D-Bus connection for exchanging D-Bus messages
2172  * with the end represented by @stream.
2173  *
2174  * If @observer is not %NULL it may be used to control the
2175  * authentication process.
2176  *
2177  * When the operation is finished, @callback will be invoked. You can
2178  * then call g_dbus_connection_new_finish() to get the result of the
2179  * operation.
2180  *
2181  * This is a asynchronous failable constructor. See
2182  * g_dbus_connection_new_sync() for the synchronous
2183  * version.
2184  *
2185  * Since: 2.26
2186  */
2187 void
2188 g_dbus_connection_new (GIOStream            *stream,
2189                        const gchar          *guid,
2190                        GDBusConnectionFlags  flags,
2191                        GDBusAuthObserver    *observer,
2192                        GCancellable         *cancellable,
2193                        GAsyncReadyCallback   callback,
2194                        gpointer              user_data)
2195 {
2196   g_return_if_fail (G_IS_IO_STREAM (stream));
2197   g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2198                               G_PRIORITY_DEFAULT,
2199                               cancellable,
2200                               callback,
2201                               user_data,
2202                               "stream", stream,
2203                               "guid", guid,
2204                               "flags", flags,
2205                               "authentication-observer", observer,
2206                               NULL);
2207 }
2208
2209 /**
2210  * g_dbus_connection_new_finish:
2211  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_new().
2212  * @error: Return location for error or %NULL.
2213  *
2214  * Finishes an operation started with g_dbus_connection_new().
2215  *
2216  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2217  *
2218  * Since: 2.26
2219  */
2220 GDBusConnection *
2221 g_dbus_connection_new_finish (GAsyncResult  *res,
2222                               GError       **error)
2223 {
2224   GObject *object;
2225   GObject *source_object;
2226
2227   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2228   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2229
2230   source_object = g_async_result_get_source_object (res);
2231   g_assert (source_object != NULL);
2232   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2233                                         res,
2234                                         error);
2235   g_object_unref (source_object);
2236   if (object != NULL)
2237     return G_DBUS_CONNECTION (object);
2238   else
2239     return NULL;
2240 }
2241
2242 /**
2243  * g_dbus_connection_new_sync:
2244  * @stream: A #GIOStream.
2245  * @guid: The GUID to use if a authenticating as a server or %NULL.
2246  * @flags: Flags describing how to make the connection.
2247  * @observer: A #GDBusAuthObserver or %NULL.
2248  * @cancellable: A #GCancellable or %NULL.
2249  * @error: Return location for error or %NULL.
2250  *
2251  * Synchronously sets up a D-Bus connection for exchanging D-Bus messages
2252  * with the end represented by @stream.
2253  *
2254  * If @observer is not %NULL it may be used to control the
2255  * authentication process.
2256  *
2257  * This is a synchronous failable constructor. See
2258  * g_dbus_connection_new() for the asynchronous version.
2259  *
2260  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2261  *
2262  * Since: 2.26
2263  */
2264 GDBusConnection *
2265 g_dbus_connection_new_sync (GIOStream             *stream,
2266                             const gchar           *guid,
2267                             GDBusConnectionFlags   flags,
2268                             GDBusAuthObserver     *observer,
2269                             GCancellable          *cancellable,
2270                             GError               **error)
2271 {
2272   g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL);
2273   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2274   return g_initable_new (G_TYPE_DBUS_CONNECTION,
2275                          cancellable,
2276                          error,
2277                          "stream", stream,
2278                          "guid", guid,
2279                          "flags", flags,
2280                          "authentication-observer", observer,
2281                          NULL);
2282 }
2283
2284 /* ---------------------------------------------------------------------------------------------------- */
2285
2286 /**
2287  * g_dbus_connection_new_for_address:
2288  * @address: A D-Bus address.
2289  * @flags: Flags describing how to make the connection.
2290  * @observer: A #GDBusAuthObserver or %NULL.
2291  * @cancellable: A #GCancellable or %NULL.
2292  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
2293  * @user_data: The data to pass to @callback.
2294  *
2295  * Asynchronously connects and sets up a D-Bus client connection for
2296  * exchanging D-Bus messages with an endpoint specified by @address
2297  * which must be in the D-Bus address format.
2298  *
2299  * This constructor can only be used to initiate client-side
2300  * connections - use g_dbus_connection_new() if you need to act as the
2301  * server. In particular, @flags cannot contain the
2302  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2303  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2304  *
2305  * When the operation is finished, @callback will be invoked. You can
2306  * then call g_dbus_connection_new_finish() to get the result of the
2307  * operation.
2308  *
2309  * If @observer is not %NULL it may be used to control the
2310  * authentication process.
2311  *
2312  * This is a asynchronous failable constructor. See
2313  * g_dbus_connection_new_for_address_sync() for the synchronous
2314  * version.
2315  *
2316  * Since: 2.26
2317  */
2318 void
2319 g_dbus_connection_new_for_address (const gchar          *address,
2320                                    GDBusConnectionFlags  flags,
2321                                    GDBusAuthObserver    *observer,
2322                                    GCancellable         *cancellable,
2323                                    GAsyncReadyCallback   callback,
2324                                    gpointer              user_data)
2325 {
2326   g_return_if_fail (address != NULL);
2327   g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2328                               G_PRIORITY_DEFAULT,
2329                               cancellable,
2330                               callback,
2331                               user_data,
2332                               "address", address,
2333                               "flags", flags,
2334                               "authentication-observer", observer,
2335                               NULL);
2336 }
2337
2338 /**
2339  * g_dbus_connection_new_for_address_finish:
2340  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_new().
2341  * @error: Return location for error or %NULL.
2342  *
2343  * Finishes an operation started with g_dbus_connection_new_for_address().
2344  *
2345  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2346  *
2347  * Since: 2.26
2348  */
2349 GDBusConnection *
2350 g_dbus_connection_new_for_address_finish (GAsyncResult  *res,
2351                                           GError       **error)
2352 {
2353   GObject *object;
2354   GObject *source_object;
2355
2356   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2357   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2358
2359   source_object = g_async_result_get_source_object (res);
2360   g_assert (source_object != NULL);
2361   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2362                                         res,
2363                                         error);
2364   g_object_unref (source_object);
2365   if (object != NULL)
2366     return G_DBUS_CONNECTION (object);
2367   else
2368     return NULL;
2369 }
2370
2371 /**
2372  * g_dbus_connection_new_for_address_sync:
2373  * @address: A D-Bus address.
2374  * @flags: Flags describing how to make the connection.
2375  * @observer: A #GDBusAuthObserver or %NULL.
2376  * @cancellable: A #GCancellable or %NULL.
2377  * @error: Return location for error or %NULL.
2378  *
2379  * Synchronously connects and sets up a D-Bus client connection for
2380  * exchanging D-Bus messages with an endpoint specified by @address
2381  * which must be in the D-Bus address format.
2382  *
2383  * This constructor can only be used to initiate client-side
2384  * connections - use g_dbus_connection_new_sync() if you need to act
2385  * as the server. In particular, @flags cannot contain the
2386  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2387  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2388  *
2389  * This is a synchronous failable constructor. See
2390  * g_dbus_connection_new_for_address() for the asynchronous version.
2391  *
2392  * If @observer is not %NULL it may be used to control the
2393  * authentication process.
2394  *
2395  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2396  *
2397  * Since: 2.26
2398  */
2399 GDBusConnection *
2400 g_dbus_connection_new_for_address_sync (const gchar           *address,
2401                                         GDBusConnectionFlags   flags,
2402                                         GDBusAuthObserver     *observer,
2403                                         GCancellable          *cancellable,
2404                                         GError               **error)
2405 {
2406   g_return_val_if_fail (address != NULL, NULL);
2407   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2408   return g_initable_new (G_TYPE_DBUS_CONNECTION,
2409                          cancellable,
2410                          error,
2411                          "address", address,
2412                          "flags", flags,
2413                          "authentication-observer", observer,
2414                          NULL);
2415 }
2416
2417 /* ---------------------------------------------------------------------------------------------------- */
2418
2419 /**
2420  * g_dbus_connection_set_exit_on_close:
2421  * @connection: A #GDBusConnection.
2422  * @exit_on_close: Whether the process should be terminated
2423  * when @connection is closed by the remote peer.
2424  *
2425  * Sets whether the process should be terminated when @connection is
2426  * closed by the remote peer. See #GDBusConnection:exit-on-close for
2427  * more details.
2428  *
2429  * Since: 2.26
2430  */
2431 void
2432 g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
2433                                      gboolean         exit_on_close)
2434 {
2435   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2436   connection->exit_on_close = exit_on_close;
2437 }
2438
2439 /**
2440  * g_dbus_connection_get_exit_on_close:
2441  * @connection: A #GDBusConnection.
2442  *
2443  * Gets whether the process is terminated when @connection is
2444  * closed by the remote peer. See
2445  * #GDBusConnection:exit-on-close for more details.
2446  *
2447  * Returns: Whether the process is terminated when @connection is
2448  * closed by the remote peer.
2449  *
2450  * Since: 2.26
2451  */
2452 gboolean
2453 g_dbus_connection_get_exit_on_close (GDBusConnection *connection)
2454 {
2455   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
2456   return connection->exit_on_close;
2457 }
2458
2459 /**
2460  * g_dbus_connection_get_guid:
2461  * @connection: A #GDBusConnection.
2462  *
2463  * The GUID of the peer performing the role of server when
2464  * authenticating. See #GDBusConnection:guid for more details.
2465  *
2466  * Returns: The GUID. Do not free this string, it is owned by
2467  * @connection.
2468  *
2469  * Since: 2.26
2470  */
2471 const gchar *
2472 g_dbus_connection_get_guid (GDBusConnection *connection)
2473 {
2474   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2475   return connection->guid;
2476 }
2477
2478 /**
2479  * g_dbus_connection_get_unique_name:
2480  * @connection: A #GDBusConnection.
2481  *
2482  * Gets the unique name of @connection as assigned by the message
2483  * bus. This can also be used to figure out if @connection is a
2484  * message bus connection.
2485  *
2486  * Returns: The unique name or %NULL if @connection is not a message
2487  * bus connection. Do not free this string, it is owned by
2488  * @connection.
2489  *
2490  * Since: 2.26
2491  */
2492 const gchar *
2493 g_dbus_connection_get_unique_name (GDBusConnection *connection)
2494 {
2495   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2496   return connection->bus_unique_name;
2497 }
2498
2499 /**
2500  * g_dbus_connection_get_peer_credentials:
2501  * @connection: A #GDBusConnection.
2502  *
2503  * Gets the credentials of the authenticated peer. This will always
2504  * return %NULL unless @connection acted as a server
2505  * (e.g. %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER was passed)
2506  * when set up and the client passed credentials as part of the
2507  * authentication process.
2508  *
2509  * In a message bus setup, the message bus is always the server and
2510  * each application is a client. So this method will always return
2511  * %NULL for message bus clients.
2512  *
2513  * Returns: A #GCredentials or %NULL if not available. Do not free
2514  * this object, it is owned by @connection.
2515  *
2516  * Since: 2.26
2517  */
2518 GCredentials *
2519 g_dbus_connection_get_peer_credentials (GDBusConnection *connection)
2520 {
2521   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2522   return connection->crendentials;
2523 }
2524
2525 /* ---------------------------------------------------------------------------------------------------- */
2526
2527 static guint _global_filter_id = 1;
2528
2529 /**
2530  * g_dbus_connection_add_filter:
2531  * @connection: A #GDBusConnection.
2532  * @filter_function: A filter function.
2533  * @user_data: User data to pass to @filter_function.
2534  * @user_data_free_func: Function to free @user_data with when filter
2535  * is removed or %NULL.
2536  *
2537  * Adds a message filter. Filters are handlers that are run on all
2538  * incoming and outgoing messages, prior to standard dispatch. Filters
2539  * are run in the order that they were added.  The same handler can be
2540  * added as a filter more than once, in which case it will be run more
2541  * than once.  Filters added during a filter callback won't be run on
2542  * the message being processed.
2543  *
2544  * Note that filters are run in a dedicated message handling thread so
2545  * they can't block and, generally, can't do anything but signal a
2546  * worker thread. Also note that filters are rarely needed - use API
2547  * such as g_dbus_connection_send_message_with_reply(),
2548  * g_dbus_connection_signal_subscribe() or
2549  * g_dbus_connection_call() instead.
2550  *
2551  * If a filter consumes an incoming message (by returning %TRUE), the
2552  * message is not dispatched anywhere else - not even the standard
2553  * dispatch machinery (that API such as
2554  * g_dbus_connection_signal_subscribe() and
2555  * g_dbus_connection_send_message_with_reply() relies on) will see the
2556  * message. Similary, if a filter consumes an outgoing message, the
2557  * message will not be sent to the other peer.
2558  *
2559  * Returns: A filter identifier that can be used with
2560  * g_dbus_connection_remove_filter().
2561  *
2562  * Since: 2.26
2563  */
2564 guint
2565 g_dbus_connection_add_filter (GDBusConnection            *connection,
2566                               GDBusMessageFilterFunction  filter_function,
2567                               gpointer                    user_data,
2568                               GDestroyNotify              user_data_free_func)
2569 {
2570   FilterData *data;
2571
2572   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
2573   g_return_val_if_fail (filter_function != NULL, 0);
2574
2575   CONNECTION_LOCK (connection);
2576   data = g_new0 (FilterData, 1);
2577   data->id = _global_filter_id++; /* TODO: overflow etc. */
2578   data->filter_function = filter_function;
2579   data->user_data = user_data;
2580   data->user_data_free_func = user_data_free_func;
2581   g_ptr_array_add (connection->filters, data);
2582   CONNECTION_UNLOCK (connection);
2583
2584   return data->id;
2585 }
2586
2587 /* only called from finalize(), removes all filters */
2588 static void
2589 purge_all_filters (GDBusConnection *connection)
2590 {
2591   guint n;
2592   for (n = 0; n < connection->filters->len; n++)
2593     {
2594       FilterData *data = connection->filters->pdata[n];
2595       if (data->user_data_free_func != NULL)
2596         data->user_data_free_func (data->user_data);
2597       g_free (data);
2598     }
2599 }
2600
2601 /**
2602  * g_dbus_connection_remove_filter:
2603  * @connection: a #GDBusConnection
2604  * @filter_id: an identifier obtained from g_dbus_connection_add_filter()
2605  *
2606  * Removes a filter.
2607  *
2608  * Since: 2.26
2609  */
2610 void
2611 g_dbus_connection_remove_filter (GDBusConnection *connection,
2612                                  guint            filter_id)
2613 {
2614   guint n;
2615   FilterData *to_destroy;
2616
2617   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2618
2619   CONNECTION_LOCK (connection);
2620   to_destroy = NULL;
2621   for (n = 0; n < connection->filters->len; n++)
2622     {
2623       FilterData *data = connection->filters->pdata[n];
2624       if (data->id == filter_id)
2625         {
2626           g_ptr_array_remove_index (connection->filters, n);
2627           to_destroy = data;
2628           break;
2629         }
2630     }
2631   CONNECTION_UNLOCK (connection);
2632
2633   /* do free without holding lock */
2634   if (to_destroy != NULL)
2635     {
2636       if (to_destroy->user_data_free_func != NULL)
2637         to_destroy->user_data_free_func (to_destroy->user_data);
2638       g_free (to_destroy);
2639     }
2640   else
2641     {
2642       g_warning ("g_dbus_connection_remove_filter: No filter found for filter_id %d", filter_id);
2643     }
2644 }
2645
2646 /* ---------------------------------------------------------------------------------------------------- */
2647
2648 typedef struct
2649 {
2650   gchar *rule;
2651   gchar *sender;
2652   gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */
2653   gchar *interface_name;
2654   gchar *member;
2655   gchar *object_path;
2656   gchar *arg0;
2657   GArray *subscribers;
2658 } SignalData;
2659
2660 typedef struct
2661 {
2662   GDBusSignalCallback callback;
2663   gpointer user_data;
2664   GDestroyNotify user_data_free_func;
2665   guint id;
2666   GMainContext *context;
2667 } SignalSubscriber;
2668
2669 static void
2670 signal_data_free (SignalData *signal_data)
2671 {
2672   g_free (signal_data->rule);
2673   g_free (signal_data->sender);
2674   g_free (signal_data->sender_unique_name);
2675   g_free (signal_data->interface_name);
2676   g_free (signal_data->member);
2677   g_free (signal_data->object_path);
2678   g_free (signal_data->arg0);
2679   g_array_free (signal_data->subscribers, TRUE);
2680   g_free (signal_data);
2681 }
2682
2683 static gchar *
2684 args_to_rule (const gchar *sender,
2685               const gchar *interface_name,
2686               const gchar *member,
2687               const gchar *object_path,
2688               const gchar *arg0)
2689 {
2690   GString *rule;
2691
2692   rule = g_string_new ("type='signal'");
2693   if (sender != NULL)
2694     g_string_append_printf (rule, ",sender='%s'", sender);
2695   if (interface_name != NULL)
2696     g_string_append_printf (rule, ",interface='%s'", interface_name);
2697   if (member != NULL)
2698     g_string_append_printf (rule, ",member='%s'", member);
2699   if (object_path != NULL)
2700     g_string_append_printf (rule, ",path='%s'", object_path);
2701   if (arg0 != NULL)
2702     g_string_append_printf (rule, ",arg0='%s'", arg0);
2703
2704   return g_string_free (rule, FALSE);
2705 }
2706
2707 static guint _global_subscriber_id = 1;
2708 static guint _global_registration_id = 1;
2709 static guint _global_subtree_registration_id = 1;
2710
2711 /* ---------------------------------------------------------------------------------------------------- */
2712
2713 /* must hold lock when calling */
2714 static void
2715 add_match_rule (GDBusConnection *connection,
2716                 const gchar     *match_rule)
2717 {
2718   GError *error;
2719   GDBusMessage *message;
2720
2721   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
2722                                             "/org/freedesktop/DBus", /* path */
2723                                             "org.freedesktop.DBus", /* interface */
2724                                             "AddMatch");
2725   g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
2726   error = NULL;
2727   if (!g_dbus_connection_send_message_unlocked (connection,
2728                                                 message,
2729                                                 NULL,
2730                                                 &error))
2731     {
2732       g_critical ("Error while sending AddMatch() message: %s", error->message);
2733       g_error_free (error);
2734     }
2735   g_object_unref (message);
2736 }
2737
2738 /* ---------------------------------------------------------------------------------------------------- */
2739
2740 /* must hold lock when calling */
2741 static void
2742 remove_match_rule (GDBusConnection *connection,
2743                    const gchar     *match_rule)
2744 {
2745   GError *error;
2746   GDBusMessage *message;
2747
2748   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
2749                                             "/org/freedesktop/DBus", /* path */
2750                                             "org.freedesktop.DBus", /* interface */
2751                                             "RemoveMatch");
2752   g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
2753
2754   error = NULL;
2755   if (!g_dbus_connection_send_message_unlocked (connection,
2756                                                 message,
2757                                                 NULL,
2758                                                 &error))
2759     {
2760       g_critical ("Error while sending RemoveMatch() message: %s", error->message);
2761       g_error_free (error);
2762     }
2763   g_object_unref (message);
2764 }
2765
2766 /* ---------------------------------------------------------------------------------------------------- */
2767
2768 static gboolean
2769 is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
2770 {
2771   return g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 &&
2772          g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
2773          g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
2774          (g_strcmp0 (signal_data->member, "NameLost") == 0 ||
2775           g_strcmp0 (signal_data->member, "NameAcquired") == 0);
2776 }
2777
2778 /* ---------------------------------------------------------------------------------------------------- */
2779
2780 /**
2781  * g_dbus_connection_signal_subscribe:
2782  * @connection: A #GDBusConnection.
2783  * @sender: Sender name to match on (unique or well-known name) or %NULL to listen from all senders.
2784  * @interface_name: D-Bus interface name to match on or %NULL to match on all interfaces.
2785  * @member: D-Bus signal name to match on or %NULL to match on all signals.
2786  * @object_path: Object path to match on or %NULL to match on all object paths.
2787  * @arg0: Contents of first string argument to match on or %NULL to match on all kinds of arguments.
2788  * @callback: Callback to invoke when there is a signal matching the requested data.
2789  * @user_data: User data to pass to @callback.
2790  * @user_data_free_func: Function to free @user_data with when subscription is removed or %NULL.
2791  *
2792  * Subscribes to signals on @connection and invokes @callback with a
2793  * whenever the signal is received. Note that @callback
2794  * will be invoked in the <link
2795  * linkend="g-main-context-push-thread-default">thread-default main
2796  * loop</link> of the thread you are calling this method from.
2797  *
2798  * If @connection is not a message bus connection, @sender must be
2799  * %NULL.
2800  *
2801  * If @sender is a well-known name note that @callback is invoked with
2802  * the unique name for the owner of @sender, not the well-known name
2803  * as one would expect. This is because the message bus rewrites the
2804  * name. As such, to avoid certain race conditions, users should be
2805  * tracking the name owner of the well-known name and use that when
2806  * processing the received signal.
2807  *
2808  * Returns: A subscription identifier that can be used with g_dbus_connection_signal_unsubscribe().
2809  *
2810  * Since: 2.26
2811  */
2812 guint
2813 g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
2814                                     const gchar         *sender,
2815                                     const gchar         *interface_name,
2816                                     const gchar         *member,
2817                                     const gchar         *object_path,
2818                                     const gchar         *arg0,
2819                                     GDBusSignalCallback  callback,
2820                                     gpointer             user_data,
2821                                     GDestroyNotify       user_data_free_func)
2822 {
2823   gchar *rule;
2824   SignalData *signal_data;
2825   SignalSubscriber subscriber;
2826   GPtrArray *signal_data_array;
2827   const gchar *sender_unique_name;
2828
2829   /* Right now we abort if AddMatch() fails since it can only fail with the bus being in
2830    * an OOM condition. We might want to change that but that would involve making
2831    * g_dbus_connection_signal_subscribe() asynchronous and having the call sites
2832    * handle that. And there's really no sensible way of handling this short of retrying
2833    * to add the match rule... and then there's the little thing that, hey, maybe there's
2834    * a reason the bus in an OOM condition.
2835    *
2836    * Doable, but not really sure it's worth it...
2837    */
2838
2839   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
2840   g_return_val_if_fail (sender == NULL || (g_dbus_is_name (sender) && (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)), 0);
2841   g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), 0);
2842   g_return_val_if_fail (member == NULL || g_dbus_is_member_name (member), 0);
2843   g_return_val_if_fail (object_path == NULL || g_variant_is_object_path (object_path), 0);
2844   g_return_val_if_fail (callback != NULL, 0);
2845
2846   CONNECTION_LOCK (connection);
2847
2848   rule = args_to_rule (sender, interface_name, member, object_path, arg0);
2849
2850   if (sender != NULL && (g_dbus_is_unique_name (sender) || g_strcmp0 (sender, "org.freedesktop.DBus") == 0))
2851     sender_unique_name = sender;
2852   else
2853     sender_unique_name = "";
2854
2855   subscriber.callback = callback;
2856   subscriber.user_data = user_data;
2857   subscriber.user_data_free_func = user_data_free_func;
2858   subscriber.id = _global_subscriber_id++; /* TODO: overflow etc. */
2859   subscriber.context = g_main_context_get_thread_default ();
2860   if (subscriber.context != NULL)
2861     g_main_context_ref (subscriber.context);
2862
2863   /* see if we've already have this rule */
2864   signal_data = g_hash_table_lookup (connection->map_rule_to_signal_data, rule);
2865   if (signal_data != NULL)
2866     {
2867       g_array_append_val (signal_data->subscribers, subscriber);
2868       g_free (rule);
2869       goto out;
2870     }
2871
2872   signal_data = g_new0 (SignalData, 1);
2873   signal_data->rule                  = rule;
2874   signal_data->sender                = g_strdup (sender);
2875   signal_data->sender_unique_name    = g_strdup (sender_unique_name);
2876   signal_data->interface_name        = g_strdup (interface_name);
2877   signal_data->member                = g_strdup (member);
2878   signal_data->object_path           = g_strdup (object_path);
2879   signal_data->arg0                  = g_strdup (arg0);
2880   signal_data->subscribers           = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
2881   g_array_append_val (signal_data->subscribers, subscriber);
2882
2883   g_hash_table_insert (connection->map_rule_to_signal_data,
2884                        signal_data->rule,
2885                        signal_data);
2886
2887   /* Add the match rule to the bus...
2888    *
2889    * Avoid adding match rules for NameLost and NameAcquired messages - the bus will
2890    * always send such messages to us.
2891    */
2892   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2893     {
2894       if (!is_signal_data_for_name_lost_or_acquired (signal_data))
2895         add_match_rule (connection, signal_data->rule);
2896     }
2897
2898   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
2899                                            signal_data->sender_unique_name);
2900   if (signal_data_array == NULL)
2901     {
2902       signal_data_array = g_ptr_array_new ();
2903       g_hash_table_insert (connection->map_sender_unique_name_to_signal_data_array,
2904                            g_strdup (signal_data->sender_unique_name),
2905                            signal_data_array);
2906     }
2907   g_ptr_array_add (signal_data_array, signal_data);
2908
2909  out:
2910   g_hash_table_insert (connection->map_id_to_signal_data,
2911                        GUINT_TO_POINTER (subscriber.id),
2912                        signal_data);
2913
2914   CONNECTION_UNLOCK (connection);
2915
2916   return subscriber.id;
2917 }
2918
2919 /* ---------------------------------------------------------------------------------------------------- */
2920
2921 /* must hold lock when calling this */
2922 static void
2923 unsubscribe_id_internal (GDBusConnection *connection,
2924                          guint            subscription_id,
2925                          GArray          *out_removed_subscribers)
2926 {
2927   SignalData *signal_data;
2928   GPtrArray *signal_data_array;
2929   guint n;
2930
2931   signal_data = g_hash_table_lookup (connection->map_id_to_signal_data,
2932                                      GUINT_TO_POINTER (subscription_id));
2933   if (signal_data == NULL)
2934     {
2935       /* Don't warn here, we may have thrown all subscriptions out when the connection was closed */
2936       goto out;
2937     }
2938
2939   for (n = 0; n < signal_data->subscribers->len; n++)
2940     {
2941       SignalSubscriber *subscriber;
2942
2943       subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, n));
2944       if (subscriber->id != subscription_id)
2945         continue;
2946
2947       g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data,
2948                                            GUINT_TO_POINTER (subscription_id)));
2949       g_array_append_val (out_removed_subscribers, *subscriber);
2950       g_array_remove_index (signal_data->subscribers, n);
2951
2952       if (signal_data->subscribers->len == 0)
2953         {
2954           g_warn_if_fail (g_hash_table_remove (connection->map_rule_to_signal_data, signal_data->rule));
2955
2956           signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
2957                                                    signal_data->sender_unique_name);
2958           g_warn_if_fail (signal_data_array != NULL);
2959           g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data));
2960
2961           if (signal_data_array->len == 0)
2962             {
2963               g_warn_if_fail (g_hash_table_remove (connection->map_sender_unique_name_to_signal_data_array,
2964                                                    signal_data->sender_unique_name));
2965             }
2966
2967           /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
2968           if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2969             {
2970               if (!is_signal_data_for_name_lost_or_acquired (signal_data))
2971                 if (!connection->closed)
2972                   remove_match_rule (connection, signal_data->rule);
2973             }
2974           signal_data_free (signal_data);
2975         }
2976
2977       goto out;
2978     }
2979
2980   g_assert_not_reached ();
2981
2982  out:
2983   ;
2984 }
2985
2986 /**
2987  * g_dbus_connection_signal_unsubscribe:
2988  * @connection: A #GDBusConnection.
2989  * @subscription_id: A subscription id obtained from g_dbus_connection_signal_subscribe().
2990  *
2991  * Unsubscribes from signals.
2992  *
2993  * Since: 2.26
2994  */
2995 void
2996 g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
2997                                       guint            subscription_id)
2998 {
2999   GArray *subscribers;
3000   guint n;
3001
3002   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
3003
3004   subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
3005
3006   CONNECTION_LOCK (connection);
3007   unsubscribe_id_internal (connection,
3008                            subscription_id,
3009                            subscribers);
3010   CONNECTION_UNLOCK (connection);
3011
3012   /* invariant */
3013   g_assert (subscribers->len == 0 || subscribers->len == 1);
3014
3015   /* call GDestroyNotify without lock held */
3016   for (n = 0; n < subscribers->len; n++)
3017     {
3018       SignalSubscriber *subscriber;
3019       subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
3020       if (subscriber->user_data_free_func != NULL)
3021         subscriber->user_data_free_func (subscriber->user_data);
3022       if (subscriber->context != NULL)
3023         g_main_context_unref (subscriber->context);
3024     }
3025
3026   g_array_free (subscribers, TRUE);
3027 }
3028
3029 /* ---------------------------------------------------------------------------------------------------- */
3030
3031 typedef struct
3032 {
3033   guint                subscription_id;
3034   GDBusSignalCallback  callback;
3035   gpointer             user_data;
3036   GDBusMessage        *message;
3037   GDBusConnection     *connection;
3038   const gchar         *sender;
3039   const gchar         *path;
3040   const gchar         *interface;
3041   const gchar         *member;
3042 } SignalInstance;
3043
3044 /* called on delivery thread (e.g. where g_dbus_connection_signal_subscribe() was called) with
3045  * no locks held
3046  */
3047 static gboolean
3048 emit_signal_instance_in_idle_cb (gpointer data)
3049 {
3050   SignalInstance *signal_instance = data;
3051   GVariant *parameters;
3052   gboolean has_subscription;
3053
3054   parameters = g_dbus_message_get_body (signal_instance->message);
3055   if (parameters == NULL)
3056     {
3057       parameters = g_variant_new ("()");
3058       g_variant_ref_sink (parameters);
3059     }
3060   else
3061     {
3062       g_variant_ref_sink (parameters);
3063     }
3064
3065 #if 0
3066   g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n",
3067            signal_instance->subscription_id,
3068            signal_instance->sender,
3069            signal_instance->path,
3070            signal_instance->interface,
3071            signal_instance->member,
3072            g_variant_print (parameters, TRUE));
3073 #endif
3074
3075   /* Careful here, don't do the callback if we no longer has the subscription */
3076   CONNECTION_LOCK (signal_instance->connection);
3077   has_subscription = FALSE;
3078   if (g_hash_table_lookup (signal_instance->connection->map_id_to_signal_data,
3079                            GUINT_TO_POINTER (signal_instance->subscription_id)) != NULL)
3080     has_subscription = TRUE;
3081   CONNECTION_UNLOCK (signal_instance->connection);
3082
3083   if (has_subscription)
3084     signal_instance->callback (signal_instance->connection,
3085                                signal_instance->sender,
3086                                signal_instance->path,
3087                                signal_instance->interface,
3088                                signal_instance->member,
3089                                parameters,
3090                                signal_instance->user_data);
3091
3092   if (parameters != NULL)
3093     g_variant_unref (parameters);
3094
3095   return FALSE;
3096 }
3097
3098 static void
3099 signal_instance_free (SignalInstance *signal_instance)
3100 {
3101   g_object_unref (signal_instance->message);
3102   g_object_unref (signal_instance->connection);
3103   g_free (signal_instance);
3104 }
3105
3106 /* called in message handler thread WITH lock held */
3107 static void
3108 schedule_callbacks (GDBusConnection *connection,
3109                     GPtrArray       *signal_data_array,
3110                     GDBusMessage    *message,
3111                     const gchar     *sender)
3112 {
3113   guint n, m;
3114   const gchar *interface;
3115   const gchar *member;
3116   const gchar *path;
3117   const gchar *arg0;
3118
3119   interface = NULL;
3120   member = NULL;
3121   path = NULL;
3122   arg0 = NULL;
3123
3124   interface = g_dbus_message_get_interface (message);
3125   member = g_dbus_message_get_member (message);
3126   path = g_dbus_message_get_path (message);
3127   arg0 = g_dbus_message_get_arg0 (message);
3128
3129 #if 0
3130   g_print ("In schedule_callbacks:\n"
3131            "  sender    = `%s'\n"
3132            "  interface = `%s'\n"
3133            "  member    = `%s'\n"
3134            "  path      = `%s'\n"
3135            "  arg0      = `%s'\n",
3136            sender,
3137            interface,
3138            member,
3139            path,
3140            arg0);
3141 #endif
3142
3143   /* TODO: if this is slow, then we can change signal_data_array into
3144    *       map_object_path_to_signal_data_array or something.
3145    */
3146   for (n = 0; n < signal_data_array->len; n++)
3147     {
3148       SignalData *signal_data = signal_data_array->pdata[n];
3149
3150       if (signal_data->interface_name != NULL && g_strcmp0 (signal_data->interface_name, interface) != 0)
3151         continue;
3152
3153       if (signal_data->member != NULL && g_strcmp0 (signal_data->member, member) != 0)
3154         continue;
3155
3156       if (signal_data->object_path != NULL && g_strcmp0 (signal_data->object_path, path) != 0)
3157         continue;
3158
3159       if (signal_data->arg0 != NULL && g_strcmp0 (signal_data->arg0, arg0) != 0)
3160         continue;
3161
3162       for (m = 0; m < signal_data->subscribers->len; m++)
3163         {
3164           SignalSubscriber *subscriber;
3165           GSource *idle_source;
3166           SignalInstance *signal_instance;
3167
3168           subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, m));
3169
3170           signal_instance = g_new0 (SignalInstance, 1);
3171           signal_instance->subscription_id = subscriber->id;
3172           signal_instance->callback = subscriber->callback;
3173           signal_instance->user_data = subscriber->user_data;
3174           signal_instance->message = g_object_ref (message);
3175           signal_instance->connection = g_object_ref (connection);
3176           signal_instance->sender = sender;
3177           signal_instance->path = path;
3178           signal_instance->interface = interface;
3179           signal_instance->member = member;
3180
3181           idle_source = g_idle_source_new ();
3182           g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3183           g_source_set_callback (idle_source,
3184                                  emit_signal_instance_in_idle_cb,
3185                                  signal_instance,
3186                                  (GDestroyNotify) signal_instance_free);
3187           g_source_attach (idle_source, subscriber->context);
3188           g_source_unref (idle_source);
3189         }
3190     }
3191 }
3192
3193 /* called in message handler thread with lock held */
3194 static void
3195 distribute_signals (GDBusConnection *connection,
3196                     GDBusMessage    *message)
3197 {
3198   GPtrArray *signal_data_array;
3199   const gchar *sender;
3200
3201   sender = g_dbus_message_get_sender (message);
3202
3203   if (G_UNLIKELY (_g_dbus_debug_signal ()))
3204     {
3205       _g_dbus_debug_print_lock ();
3206       g_print ("========================================================================\n"
3207                "GDBus-debug:Signal:\n"
3208                " >>>> SIGNAL %s.%s\n"
3209                "      on object %s\n"
3210                "      sent by name %s\n",
3211                g_dbus_message_get_interface (message),
3212                g_dbus_message_get_member (message),
3213                g_dbus_message_get_path (message),
3214                sender != NULL ? sender : "(none)");
3215       _g_dbus_debug_print_unlock ();
3216     }
3217
3218   /* collect subscribers that match on sender */
3219   if (sender != NULL)
3220     {
3221       signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, sender);
3222       if (signal_data_array != NULL)
3223         schedule_callbacks (connection, signal_data_array, message, sender);
3224     }
3225
3226   /* collect subscribers not matching on sender */
3227   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, "");
3228   if (signal_data_array != NULL)
3229     schedule_callbacks (connection, signal_data_array, message, sender);
3230 }
3231
3232 /* ---------------------------------------------------------------------------------------------------- */
3233
3234 /* only called from finalize(), removes all subscriptions */
3235 static void
3236 purge_all_signal_subscriptions (GDBusConnection *connection)
3237 {
3238   GHashTableIter iter;
3239   gpointer key;
3240   GArray *ids;
3241   GArray *subscribers;
3242   guint n;
3243
3244   ids = g_array_new (FALSE, FALSE, sizeof (guint));
3245   g_hash_table_iter_init (&iter, connection->map_id_to_signal_data);
3246   while (g_hash_table_iter_next (&iter, &key, NULL))
3247     {
3248       guint subscription_id = GPOINTER_TO_UINT (key);
3249       g_array_append_val (ids, subscription_id);
3250     }
3251
3252   subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
3253   for (n = 0; n < ids->len; n++)
3254     {
3255       guint subscription_id = g_array_index (ids, guint, n);
3256       unsubscribe_id_internal (connection,
3257                                subscription_id,
3258                                subscribers);
3259     }
3260   g_array_free (ids, TRUE);
3261
3262   /* call GDestroyNotify without lock held */
3263   for (n = 0; n < subscribers->len; n++)
3264     {
3265       SignalSubscriber *subscriber;
3266       subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
3267       if (subscriber->user_data_free_func != NULL)
3268         subscriber->user_data_free_func (subscriber->user_data);
3269       if (subscriber->context != NULL)
3270         g_main_context_unref (subscriber->context);
3271     }
3272
3273   g_array_free (subscribers, TRUE);
3274 }
3275
3276 /* ---------------------------------------------------------------------------------------------------- */
3277
3278 struct ExportedObject
3279 {
3280   gchar *object_path;
3281   GDBusConnection *connection;
3282
3283   /* maps gchar* -> ExportedInterface* */
3284   GHashTable *map_if_name_to_ei;
3285 };
3286
3287 /* only called with lock held */
3288 static void
3289 exported_object_free (ExportedObject *eo)
3290 {
3291   g_free (eo->object_path);
3292   g_hash_table_unref (eo->map_if_name_to_ei);
3293   g_free (eo);
3294 }
3295
3296 typedef struct
3297 {
3298   ExportedObject *eo;
3299
3300   guint                       id;
3301   gchar                      *interface_name;
3302   const GDBusInterfaceVTable *vtable;
3303   const GDBusInterfaceInfo   *interface_info;
3304
3305   GMainContext               *context;
3306   gpointer                    user_data;
3307   GDestroyNotify              user_data_free_func;
3308 } ExportedInterface;
3309
3310 /* called with lock held */
3311 static void
3312 exported_interface_free (ExportedInterface *ei)
3313 {
3314   g_dbus_interface_info_unref ((GDBusInterfaceInfo *) ei->interface_info);
3315
3316   if (ei->user_data_free_func != NULL)
3317     /* TODO: push to thread-default mainloop */
3318     ei->user_data_free_func (ei->user_data);
3319
3320   if (ei->context != NULL)
3321     g_main_context_unref (ei->context);
3322
3323   g_free (ei->interface_name);
3324   g_free (ei);
3325 }
3326
3327 /* ---------------------------------------------------------------------------------------------------- */
3328
3329 /* Convenience function to check if @registration_id (if not zero) or
3330  * @subtree_registration_id (if not zero) has been unregistered. If
3331  * so, returns %TRUE.
3332  *
3333  * Caller must *not* hold lock.
3334  */
3335 static gboolean
3336 has_object_been_unregistered (GDBusConnection  *connection,
3337                               guint             registration_id,
3338                               guint             subtree_registration_id)
3339 {
3340   gboolean ret;
3341
3342   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
3343
3344   ret = FALSE;
3345
3346   CONNECTION_LOCK (connection);
3347   if (registration_id != 0 && g_hash_table_lookup (connection->map_id_to_ei,
3348                                                    GUINT_TO_POINTER (registration_id)) == NULL)
3349     {
3350       ret = TRUE;
3351     }
3352   else if (subtree_registration_id != 0 && g_hash_table_lookup (connection->map_id_to_es,
3353                                                                 GUINT_TO_POINTER (subtree_registration_id)) == NULL)
3354     {
3355       ret = TRUE;
3356     }
3357   CONNECTION_UNLOCK (connection);
3358
3359   return ret;
3360 }
3361
3362 /* ---------------------------------------------------------------------------------------------------- */
3363
3364 typedef struct
3365 {
3366   GDBusConnection *connection;
3367   GDBusMessage *message;
3368   gpointer user_data;
3369   const gchar *property_name;
3370   const GDBusInterfaceVTable *vtable;
3371   const GDBusInterfaceInfo *interface_info;
3372   const GDBusPropertyInfo *property_info;
3373   guint registration_id;
3374   guint subtree_registration_id;
3375 } PropertyData;
3376
3377 static void
3378 property_data_free (PropertyData *data)
3379 {
3380   g_object_unref (data->connection);
3381   g_object_unref (data->message);
3382   g_free (data);
3383 }
3384
3385 /* called in thread where object was registered - no locks held */
3386 static gboolean
3387 invoke_get_property_in_idle_cb (gpointer _data)
3388 {
3389   PropertyData *data = _data;
3390   GVariant *value;
3391   GError *error;
3392   GDBusMessage *reply;
3393
3394   if (has_object_been_unregistered (data->connection,
3395                                     data->registration_id,
3396                                     data->subtree_registration_id))
3397     {
3398       reply = g_dbus_message_new_method_error (data->message,
3399                                                "org.freedesktop.DBus.Error.UnknownMethod",
3400                                                _("No such interface `org.freedesktop.DBus.Properties' on object at path %s"),
3401                                                g_dbus_message_get_path (data->message));
3402       g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3403       g_object_unref (reply);
3404       goto out;
3405     }
3406
3407   error = NULL;
3408   value = data->vtable->get_property (data->connection,
3409                                       g_dbus_message_get_sender (data->message),
3410                                       g_dbus_message_get_path (data->message),
3411                                       data->interface_info->name,
3412                                       data->property_name,
3413                                       &error,
3414                                       data->user_data);
3415
3416
3417   if (value != NULL)
3418     {
3419       g_assert_no_error (error);
3420
3421       g_variant_ref_sink (value);
3422       reply = g_dbus_message_new_method_reply (data->message);
3423       g_dbus_message_set_body (reply, g_variant_new ("(v)", value));
3424       g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3425       g_variant_unref (value);
3426       g_object_unref (reply);
3427     }
3428   else
3429     {
3430       gchar *dbus_error_name;
3431       g_assert (error != NULL);
3432       dbus_error_name = g_dbus_error_encode_gerror (error);
3433       reply = g_dbus_message_new_method_error_literal (data->message,
3434                                                        dbus_error_name,
3435                                                        error->message);
3436       g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3437       g_free (dbus_error_name);
3438       g_error_free (error);
3439       g_object_unref (reply);
3440     }
3441
3442  out:
3443   return FALSE;
3444 }
3445
3446 /* called in thread where object was registered - no locks held */
3447 static gboolean
3448 invoke_set_property_in_idle_cb (gpointer _data)
3449 {
3450   PropertyData *data = _data;
3451   GError *error;
3452   GDBusMessage *reply;
3453   GVariant *value;
3454
3455   error = NULL;
3456   value = NULL;
3457
3458   g_variant_get (g_dbus_message_get_body (data->message),
3459                  "(ssv)",
3460                  NULL,
3461                  NULL,
3462                  &value);
3463
3464   /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the type
3465    * of the given value is wrong
3466    */
3467   if (g_strcmp0 (g_variant_get_type_string (value), data->property_info->signature) != 0)
3468     {
3469       reply = g_dbus_message_new_method_error (data->message,
3470                                                "org.freedesktop.DBus.Error.InvalidArgs",
3471                                                _("Error setting property `%s': Expected type `%s' but got `%s'"),
3472                                                data->property_info->name,
3473                                                data->property_info->signature,
3474                                                g_variant_get_type_string (value));
3475       goto out;
3476     }
3477
3478   if (!data->vtable->set_property (data->connection,
3479                                    g_dbus_message_get_sender (data->message),
3480                                    g_dbus_message_get_path (data->message),
3481                                    data->interface_info->name,
3482                                    data->property_name,
3483                                    value,
3484                                    &error,
3485                                    data->user_data))
3486     {
3487       gchar *dbus_error_name;
3488       g_assert (error != NULL);
3489       dbus_error_name = g_dbus_error_encode_gerror (error);
3490       reply = g_dbus_message_new_method_error_literal (data->message,
3491                                                        dbus_error_name,
3492                                                        error->message);
3493       g_free (dbus_error_name);
3494       g_error_free (error);
3495     }
3496   else
3497     {
3498       reply = g_dbus_message_new_method_reply (data->message);
3499     }
3500
3501  out:
3502   g_assert (reply != NULL);
3503   g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3504   g_object_unref (reply);
3505
3506   return FALSE;
3507 }
3508
3509 /* called with lock held */
3510 static gboolean
3511 validate_and_maybe_schedule_property_getset (GDBusConnection            *connection,
3512                                              GDBusMessage               *message,
3513                                              guint                       registration_id,
3514                                              guint                       subtree_registration_id,
3515                                              gboolean                    is_get,
3516                                              const GDBusInterfaceInfo   *interface_info,
3517                                              const GDBusInterfaceVTable *vtable,
3518                                              GMainContext               *main_context,
3519                                              gpointer                    user_data)
3520 {
3521   gboolean handled;
3522   const char *interface_name;
3523   const char *property_name;
3524   const GDBusPropertyInfo *property_info;
3525   GSource *idle_source;
3526   PropertyData *property_data;
3527   GDBusMessage *reply;
3528
3529   handled = FALSE;
3530
3531   if (is_get)
3532     g_variant_get (g_dbus_message_get_body (message),
3533                    "(&s&s)",
3534                    &interface_name,
3535                    &property_name);
3536   else
3537     g_variant_get (g_dbus_message_get_body (message),
3538                    "(&s&sv)",
3539                    &interface_name,
3540                    &property_name,
3541                    NULL);
3542
3543
3544   if (is_get)
3545     {
3546       if (vtable == NULL || vtable->get_property == NULL)
3547         goto out;
3548     }
3549   else
3550     {
3551       if (vtable == NULL || vtable->set_property == NULL)
3552         goto out;
3553     }
3554
3555   /* Check that the property exists - if not fail with org.freedesktop.DBus.Error.InvalidArgs
3556    */
3557   property_info = NULL;
3558
3559   /* TODO: the cost of this is O(n) - it might be worth caching the result */
3560   property_info = g_dbus_interface_info_lookup_property (interface_info, property_name);
3561   if (property_info == NULL)
3562     {
3563       reply = g_dbus_message_new_method_error (message,
3564                                                "org.freedesktop.DBus.Error.InvalidArgs",
3565                                                _("No such property `%s'"),
3566                                                property_name);
3567       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3568       g_object_unref (reply);
3569       handled = TRUE;
3570       goto out;
3571     }
3572
3573   if (is_get && !(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE))
3574     {
3575       reply = g_dbus_message_new_method_error (message,
3576                                                "org.freedesktop.DBus.Error.InvalidArgs",
3577                                                _("Property `%s' is not readable"),
3578                                                property_name);
3579       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3580       g_object_unref (reply);
3581       handled = TRUE;
3582       goto out;
3583     }
3584   else if (!is_get && !(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
3585     {
3586       reply = g_dbus_message_new_method_error (message,
3587                                                "org.freedesktop.DBus.Error.InvalidArgs",
3588                                                _("Property `%s' is not writable"),
3589                                                property_name);
3590       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3591       g_object_unref (reply);
3592       handled = TRUE;
3593       goto out;
3594     }
3595
3596   /* ok, got the property info - call user code in an idle handler */
3597   property_data = g_new0 (PropertyData, 1);
3598   property_data->connection = g_object_ref (connection);
3599   property_data->message = g_object_ref (message);
3600   property_data->user_data = user_data;
3601   property_data->property_name = property_name;
3602   property_data->vtable = vtable;
3603   property_data->interface_info = interface_info;
3604   property_data->property_info = property_info;
3605   property_data->registration_id = registration_id;
3606   property_data->subtree_registration_id = subtree_registration_id;
3607
3608   idle_source = g_idle_source_new ();
3609   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3610   g_source_set_callback (idle_source,
3611                          is_get ? invoke_get_property_in_idle_cb : invoke_set_property_in_idle_cb,
3612                          property_data,
3613                          (GDestroyNotify) property_data_free);
3614   g_source_attach (idle_source, main_context);
3615   g_source_unref (idle_source);
3616
3617   handled = TRUE;
3618
3619  out:
3620   return handled;
3621 }
3622
3623 /* called with lock held */
3624 static gboolean
3625 handle_getset_property (GDBusConnection *connection,
3626                         ExportedObject  *eo,
3627                         GDBusMessage    *message,
3628                         gboolean         is_get)
3629 {
3630   ExportedInterface *ei;
3631   gboolean handled;
3632   const char *interface_name;
3633   const char *property_name;
3634
3635   handled = FALSE;
3636
3637   if (is_get)
3638     g_variant_get (g_dbus_message_get_body (message),
3639                    "(&s&s)",
3640                    &interface_name,
3641                    &property_name);
3642   else
3643     g_variant_get (g_dbus_message_get_body (message),
3644                    "(&s&sv)",
3645                    &interface_name,
3646                    &property_name,
3647                    NULL);
3648
3649   /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
3650    * no such interface registered
3651    */
3652   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
3653   if (ei == NULL)
3654     {
3655       GDBusMessage *reply;
3656       reply = g_dbus_message_new_method_error (message,
3657                                                "org.freedesktop.DBus.Error.InvalidArgs",
3658                                                _("No such interface `%s'"),
3659                                                interface_name);
3660       g_dbus_connection_send_message_unlocked (eo->connection, reply, NULL, NULL);
3661       g_object_unref (reply);
3662       handled = TRUE;
3663       goto out;
3664     }
3665
3666   handled = validate_and_maybe_schedule_property_getset (eo->connection,
3667                                                          message,
3668                                                          ei->id,
3669                                                          0,
3670                                                          is_get,
3671                                                          ei->interface_info,
3672                                                          ei->vtable,
3673                                                          ei->context,
3674                                                          ei->user_data);
3675  out:
3676   return handled;
3677 }
3678
3679 /* ---------------------------------------------------------------------------------------------------- */
3680
3681 typedef struct
3682 {
3683   GDBusConnection *connection;
3684   GDBusMessage *message;
3685   gpointer user_data;
3686   const GDBusInterfaceVTable *vtable;
3687   const GDBusInterfaceInfo *interface_info;
3688   guint registration_id;
3689   guint subtree_registration_id;
3690 } PropertyGetAllData;
3691
3692 static void
3693 property_get_all_data_free (PropertyData *data)
3694 {
3695   g_object_unref (data->connection);
3696   g_object_unref (data->message);
3697   g_free (data);
3698 }
3699
3700 /* called in thread where object was registered - no locks held */
3701 static gboolean
3702 invoke_get_all_properties_in_idle_cb (gpointer _data)
3703 {
3704   PropertyGetAllData *data = _data;
3705   GVariantBuilder builder;
3706   GError *error;
3707   GDBusMessage *reply;
3708   guint n;
3709
3710   if (has_object_been_unregistered (data->connection,
3711                                     data->registration_id,
3712                                     data->subtree_registration_id))
3713     {
3714       reply = g_dbus_message_new_method_error (data->message,
3715                                                "org.freedesktop.DBus.Error.UnknownMethod",
3716                                                _("No such interface `org.freedesktop.DBus.Properties' on object at path %s"),
3717                                                g_dbus_message_get_path (data->message));
3718       g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3719       g_object_unref (reply);
3720       goto out;
3721     }
3722
3723   error = NULL;
3724
3725   /* TODO: Right now we never fail this call - we just omit values if
3726    *       a get_property() call is failing.
3727    *
3728    *       We could fail the whole call if just a single get_property() call
3729    *       returns an error. We need clarification in the D-Bus spec about this.
3730    */
3731   g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a{sv})"));
3732   g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
3733   for (n = 0; data->interface_info->properties != NULL && data->interface_info->properties[n] != NULL; n++)
3734     {
3735       const GDBusPropertyInfo *property_info = data->interface_info->properties[n];
3736       GVariant *value;
3737
3738       if (!(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE))
3739         continue;
3740
3741       value = data->vtable->get_property (data->connection,
3742                                           g_dbus_message_get_sender (data->message),
3743                                           g_dbus_message_get_path (data->message),
3744                                           data->interface_info->name,
3745                                           property_info->name,
3746                                           NULL,
3747                                           data->user_data);
3748
3749       if (value == NULL)
3750         continue;
3751
3752       g_variant_builder_add (&builder,
3753                              "{sv}",
3754                              property_info->name,
3755                              value);
3756     }
3757   g_variant_builder_close (&builder);
3758
3759   reply = g_dbus_message_new_method_reply (data->message);
3760   g_dbus_message_set_body (reply, g_variant_builder_end (&builder));
3761   g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3762   g_object_unref (reply);
3763
3764  out:
3765   return FALSE;
3766 }
3767
3768 /* called with lock held */
3769 static gboolean
3770 validate_and_maybe_schedule_property_get_all (GDBusConnection            *connection,
3771                                               GDBusMessage               *message,
3772                                               guint                       registration_id,
3773                                               guint                       subtree_registration_id,
3774                                               const GDBusInterfaceInfo   *interface_info,
3775                                               const GDBusInterfaceVTable *vtable,
3776                                               GMainContext               *main_context,
3777                                               gpointer                    user_data)
3778 {
3779   gboolean handled;
3780   const char *interface_name;
3781   GSource *idle_source;
3782   PropertyGetAllData *property_get_all_data;
3783
3784   handled = FALSE;
3785
3786   g_variant_get (g_dbus_message_get_body (message),
3787                  "(&s)",
3788                  &interface_name);
3789
3790   if (vtable == NULL || vtable->get_property == NULL)
3791     goto out;
3792
3793   /* ok, got the property info - call user in an idle handler */
3794   property_get_all_data = g_new0 (PropertyGetAllData, 1);
3795   property_get_all_data->connection = g_object_ref (connection);
3796   property_get_all_data->message = g_object_ref (message);
3797   property_get_all_data->user_data = user_data;
3798   property_get_all_data->vtable = vtable;
3799   property_get_all_data->interface_info = interface_info;
3800   property_get_all_data->registration_id = registration_id;
3801   property_get_all_data->subtree_registration_id = subtree_registration_id;
3802
3803   idle_source = g_idle_source_new ();
3804   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3805   g_source_set_callback (idle_source,
3806                          invoke_get_all_properties_in_idle_cb,
3807                          property_get_all_data,
3808                          (GDestroyNotify) property_get_all_data_free);
3809   g_source_attach (idle_source, main_context);
3810   g_source_unref (idle_source);
3811
3812   handled = TRUE;
3813
3814  out:
3815   return handled;
3816 }
3817
3818 /* called with lock held */
3819 static gboolean
3820 handle_get_all_properties (GDBusConnection *connection,
3821                            ExportedObject  *eo,
3822                            GDBusMessage    *message)
3823 {
3824   ExportedInterface *ei;
3825   gboolean handled;
3826   const char *interface_name;
3827
3828   handled = FALSE;
3829
3830   g_variant_get (g_dbus_message_get_body (message),
3831                  "(&s)",
3832                  &interface_name);
3833
3834   /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
3835    * no such interface registered
3836    */
3837   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
3838   if (ei == NULL)
3839     {
3840       GDBusMessage *reply;
3841       reply = g_dbus_message_new_method_error (message,
3842                                                "org.freedesktop.DBus.Error.InvalidArgs",
3843                                                _("No such interface"),
3844                                                interface_name);
3845       g_dbus_connection_send_message_unlocked (eo->connection, reply, NULL, NULL);
3846       g_object_unref (reply);
3847       handled = TRUE;
3848       goto out;
3849     }
3850
3851   handled = validate_and_maybe_schedule_property_get_all (eo->connection,
3852                                                           message,
3853                                                           ei->id,
3854                                                           0,
3855                                                           ei->interface_info,
3856                                                           ei->vtable,
3857                                                           ei->context,
3858                                                           ei->user_data);
3859  out:
3860   return handled;
3861 }
3862
3863 /* ---------------------------------------------------------------------------------------------------- */
3864
3865 static const gchar introspect_header[] =
3866   "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
3867   "                      \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
3868   "<!-- GDBus " PACKAGE_VERSION " -->\n"
3869   "<node>\n";
3870
3871 static const gchar introspect_tail[] =
3872   "</node>\n";
3873
3874 static const gchar introspect_standard_interfaces[] =
3875   "  <interface name=\"org.freedesktop.DBus.Properties\">\n"
3876   "    <method name=\"Get\">\n"
3877   "      <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
3878   "      <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
3879   "      <arg type=\"v\" name=\"value\" direction=\"out\"/>\n"
3880   "    </method>\n"
3881   "    <method name=\"GetAll\">\n"
3882   "      <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
3883   "      <arg type=\"a{sv}\" name=\"properties\" direction=\"out\"/>\n"
3884   "    </method>\n"
3885   "    <method name=\"Set\">\n"
3886   "      <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
3887   "      <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
3888   "      <arg type=\"v\" name=\"value\" direction=\"in\"/>\n"
3889   "    </method>\n"
3890   "    <signal name=\"PropertiesChanged\">\n"
3891   "      <arg type=\"s\" name=\"interface_name\"/>\n"
3892   "      <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"
3893   "      <arg type=\"as\" name=\"invalidated_properties\"/>\n"
3894   "    </signal>\n"
3895   "  </interface>\n"
3896   "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
3897   "    <method name=\"Introspect\">\n"
3898   "      <arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
3899   "    </method>\n"
3900   "  </interface>\n"
3901   "  <interface name=\"org.freedesktop.DBus.Peer\">\n"
3902   "    <method name=\"Ping\"/>\n"
3903   "    <method name=\"GetMachineId\">\n"
3904   "      <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n"
3905   "    </method>\n"
3906   "  </interface>\n";
3907
3908 static void
3909 introspect_append_header (GString *s)
3910 {
3911   g_string_append (s, introspect_header);
3912 }
3913
3914 static void
3915 introspect_append_standard_interfaces (GString *s)
3916 {
3917   g_string_append (s, introspect_standard_interfaces);
3918 }
3919
3920 static void
3921 maybe_add_path (const gchar *path, gsize path_len, const gchar *object_path, GHashTable *set)
3922 {
3923   if (g_str_has_prefix (object_path, path) && strlen (object_path) > path_len && object_path[path_len-1] == '/')
3924     {
3925       const gchar *begin;
3926       const gchar *end;
3927       gchar *s;
3928
3929       begin = object_path + path_len;
3930       end = strchr (begin, '/');
3931       if (end != NULL)
3932         s = g_strndup (begin, end - begin);
3933       else
3934         s = g_strdup (begin);
3935
3936       if (g_hash_table_lookup (set, s) == NULL)
3937         g_hash_table_insert (set, s, GUINT_TO_POINTER (1));
3938       else
3939         g_free (s);
3940     }
3941 }
3942
3943 /* TODO: we want a nicer public interface for this */
3944 static gchar **
3945 g_dbus_connection_list_registered_unlocked (GDBusConnection *connection,
3946                                             const gchar     *path)
3947 {
3948   GPtrArray *p;
3949   gchar **ret;
3950   GHashTableIter hash_iter;
3951   const gchar *object_path;
3952   gsize path_len;
3953   GHashTable *set;
3954   GList *keys;
3955   GList *l;
3956
3957   CONNECTION_ENSURE_LOCK (connection);
3958
3959   path_len = strlen (path);
3960   if (path_len > 1)
3961     path_len++;
3962
3963   set = g_hash_table_new (g_str_hash, g_str_equal);
3964
3965   g_hash_table_iter_init (&hash_iter, connection->map_object_path_to_eo);
3966   while (g_hash_table_iter_next (&hash_iter, (gpointer) &object_path, NULL))
3967     maybe_add_path (path, path_len, object_path, set);
3968
3969   g_hash_table_iter_init (&hash_iter, connection->map_object_path_to_es);
3970   while (g_hash_table_iter_next (&hash_iter, (gpointer) &object_path, NULL))
3971     maybe_add_path (path, path_len, object_path, set);
3972
3973   p = g_ptr_array_new ();
3974   keys = g_hash_table_get_keys (set);
3975   for (l = keys; l != NULL; l = l->next)
3976     g_ptr_array_add (p, l->data);
3977   g_hash_table_unref (set);
3978   g_list_free (keys);
3979
3980   g_ptr_array_add (p, NULL);
3981   ret = (gchar **) g_ptr_array_free (p, FALSE);
3982   return ret;
3983 }
3984
3985 static gchar **
3986 g_dbus_connection_list_registered (GDBusConnection *connection,
3987                                    const gchar     *path)
3988 {
3989   gchar **ret;
3990   CONNECTION_LOCK (connection);
3991   ret = g_dbus_connection_list_registered_unlocked (connection, path);
3992   CONNECTION_UNLOCK (connection);
3993   return ret;
3994 }
3995
3996 /* called in message handler thread with lock held */
3997 static gboolean
3998 handle_introspect (GDBusConnection *connection,
3999                    ExportedObject  *eo,
4000                    GDBusMessage    *message)
4001 {
4002   guint n;
4003   GString *s;
4004   GDBusMessage *reply;
4005   GHashTableIter hash_iter;
4006   ExportedInterface *ei;
4007   gchar **registered;
4008
4009   /* first the header with the standard interfaces */
4010   s = g_string_sized_new (sizeof (introspect_header) +
4011                           sizeof (introspect_standard_interfaces) +
4012                           sizeof (introspect_tail));
4013   introspect_append_header (s);
4014   introspect_append_standard_interfaces (s);
4015
4016   /* then include the registered interfaces */
4017   g_hash_table_iter_init (&hash_iter, eo->map_if_name_to_ei);
4018   while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &ei))
4019     g_dbus_interface_info_generate_xml (ei->interface_info, 2, s);
4020
4021   /* finally include nodes registered below us */
4022   registered = g_dbus_connection_list_registered_unlocked (connection, eo->object_path);
4023   for (n = 0; registered != NULL && registered[n] != NULL; n++)
4024     g_string_append_printf (s, "  <node name=\"%s\"/>\n", registered[n]);
4025   g_strfreev (registered);
4026   g_string_append (s, introspect_tail);
4027
4028   reply = g_dbus_message_new_method_reply (message);
4029   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
4030   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
4031   g_object_unref (reply);
4032   g_string_free (s, TRUE);
4033
4034   return TRUE;
4035 }
4036
4037 /* called in thread where object was registered - no locks held */
4038 static gboolean
4039 call_in_idle_cb (gpointer user_data)
4040 {
4041   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
4042   GDBusInterfaceVTable *vtable;
4043   guint registration_id;
4044   guint subtree_registration_id;
4045
4046   vtable = g_object_get_data (G_OBJECT (invocation), "g-dbus-interface-vtable");
4047   g_assert (vtable != NULL && vtable->method_call != NULL);
4048
4049   registration_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (invocation), "g-dbus-registration-id"));
4050   subtree_registration_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (invocation), "g-dbus-subtree-registration-id"));
4051
4052   if (has_object_been_unregistered (g_dbus_method_invocation_get_connection (invocation),
4053                                     registration_id,
4054                                     subtree_registration_id))
4055     {
4056       GDBusMessage *reply;
4057       reply = g_dbus_message_new_method_error (g_dbus_method_invocation_get_message (invocation),
4058                                                "org.freedesktop.DBus.Error.UnknownMethod",
4059                                                _("No such interface `%s' on object at path %s"),
4060                                                g_dbus_method_invocation_get_interface_name (invocation),
4061                                                g_dbus_method_invocation_get_object_path (invocation));
4062       g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, NULL, NULL);
4063       g_object_unref (reply);
4064       goto out;
4065     }
4066
4067   vtable->method_call (g_dbus_method_invocation_get_connection (invocation),
4068                        g_dbus_method_invocation_get_sender (invocation),
4069                        g_dbus_method_invocation_get_object_path (invocation),
4070                        g_dbus_method_invocation_get_interface_name (invocation),
4071                        g_dbus_method_invocation_get_method_name (invocation),
4072                        g_dbus_method_invocation_get_parameters (invocation),
4073                        g_object_ref (invocation),
4074                        g_dbus_method_invocation_get_user_data (invocation));
4075
4076  out:
4077   return FALSE;
4078 }
4079
4080 /* called in message handler thread with lock held */
4081 static gboolean
4082 validate_and_maybe_schedule_method_call (GDBusConnection            *connection,
4083                                          GDBusMessage               *message,
4084                                          guint                       registration_id,
4085                                          guint                       subtree_registration_id,
4086                                          const GDBusInterfaceInfo   *interface_info,
4087                                          const GDBusInterfaceVTable *vtable,
4088                                          GMainContext               *main_context,
4089                                          gpointer                    user_data)
4090 {
4091   GDBusMethodInvocation *invocation;
4092   const GDBusMethodInfo *method_info;
4093   GDBusMessage *reply;
4094   GVariant *parameters;
4095   GSource *idle_source;
4096   gboolean handled;
4097   GVariantType *in_type;
4098
4099   handled = FALSE;
4100
4101   /* TODO: the cost of this is O(n) - it might be worth caching the result */
4102   method_info = g_dbus_interface_info_lookup_method (interface_info, g_dbus_message_get_member (message));
4103
4104   /* if the method doesn't exist, return the org.freedesktop.DBus.Error.UnknownMethod
4105    * error to the caller
4106    */
4107   if (method_info == NULL)
4108     {
4109       reply = g_dbus_message_new_method_error (message,
4110                                                "org.freedesktop.DBus.Error.UnknownMethod",
4111                                                _("No such method `%s'"),
4112                                                g_dbus_message_get_member (message));
4113       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
4114       g_object_unref (reply);
4115       handled = TRUE;
4116       goto out;
4117     }
4118
4119   parameters = g_dbus_message_get_body (message);
4120   if (parameters == NULL)
4121     {
4122       parameters = g_variant_new ("()");
4123       g_variant_ref_sink (parameters);
4124     }
4125   else
4126     {
4127       g_variant_ref (parameters);
4128     }
4129
4130   /* Check that the incoming args are of the right type - if they are not, return
4131    * the org.freedesktop.DBus.Error.InvalidArgs error to the caller
4132    */
4133   in_type = _g_dbus_compute_complete_signature (method_info->in_args);
4134   if (!g_variant_is_of_type (parameters, in_type))
4135     {
4136       gchar *type_string;
4137
4138       type_string = g_variant_type_dup_string (in_type);
4139
4140       reply = g_dbus_message_new_method_error (message,
4141                                                "org.freedesktop.DBus.Error.InvalidArgs",
4142                                                _("Type of message, `%s', does not match expected type `%s'"),
4143                                                g_variant_get_type_string (parameters),
4144                                                type_string);
4145       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
4146       g_variant_type_free (in_type);
4147       g_variant_unref (parameters);
4148       g_object_unref (reply);
4149       g_free (type_string);
4150       handled = TRUE;
4151       goto out;
4152     }
4153   g_variant_type_free (in_type);
4154
4155   /* schedule the call in idle */
4156   invocation = g_dbus_method_invocation_new (g_dbus_message_get_sender (message),
4157                                              g_dbus_message_get_path (message),
4158                                              g_dbus_message_get_interface (message),
4159                                              g_dbus_message_get_member (message),
4160                                              method_info,
4161                                              connection,
4162                                              message,
4163                                              parameters,
4164                                              user_data);
4165   g_variant_unref (parameters);
4166
4167   /* TODO: would be nicer with a real MethodData like we already
4168    * have PropertyData and PropertyGetAllData... */
4169   g_object_set_data (G_OBJECT (invocation), "g-dbus-interface-vtable", (gpointer) vtable);
4170   g_object_set_data (G_OBJECT (invocation), "g-dbus-registration-id", GUINT_TO_POINTER (registration_id));
4171   g_object_set_data (G_OBJECT (invocation), "g-dbus-subtree-registration-id", GUINT_TO_POINTER (subtree_registration_id));
4172
4173   idle_source = g_idle_source_new ();
4174   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
4175   g_source_set_callback (idle_source,
4176                          call_in_idle_cb,
4177                          invocation,
4178                          g_object_unref);
4179   g_source_attach (idle_source, main_context);
4180   g_source_unref (idle_source);
4181
4182   handled = TRUE;
4183
4184  out:
4185   return handled;
4186 }
4187
4188 /* ---------------------------------------------------------------------------------------------------- */
4189
4190 /* called in message handler thread with lock held */
4191 static gboolean
4192 obj_message_func (GDBusConnection *connection,
4193                   ExportedObject  *eo,
4194                   GDBusMessage    *message)
4195 {
4196   const gchar *interface_name;
4197   const gchar *member;
4198   const gchar *signature;
4199   gboolean handled;
4200
4201   handled = FALSE;
4202
4203   interface_name = g_dbus_message_get_interface (message);
4204   member = g_dbus_message_get_member (message);
4205   signature = g_dbus_message_get_signature (message);
4206
4207   /* see if we have an interface for handling this call */
4208   if (interface_name != NULL)
4209     {
4210       ExportedInterface *ei;
4211       ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
4212       if (ei != NULL)
4213         {
4214           /* we do - invoke the handler in idle in the right thread */
4215
4216           /* handle no vtable or handler being present */
4217           if (ei->vtable == NULL || ei->vtable->method_call == NULL)
4218             goto out;
4219
4220           handled = validate_and_maybe_schedule_method_call (connection,
4221                                                              message,
4222                                                              ei->id,
4223                                                              0,
4224                                                              ei->interface_info,
4225                                                              ei->vtable,
4226                                                              ei->context,
4227                                                              ei->user_data);
4228           goto out;
4229         }
4230     }
4231
4232   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
4233       g_strcmp0 (member, "Introspect") == 0 &&
4234       g_strcmp0 (signature, "") == 0)
4235     {
4236       handled = handle_introspect (connection, eo, message);
4237       goto out;
4238     }
4239   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
4240            g_strcmp0 (member, "Get") == 0 &&
4241            g_strcmp0 (signature, "ss") == 0)
4242     {
4243       handled = handle_getset_property (connection, eo, message, TRUE);
4244       goto out;
4245     }
4246   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
4247            g_strcmp0 (member, "Set") == 0 &&
4248            g_strcmp0 (signature, "ssv") == 0)
4249     {
4250       handled = handle_getset_property (connection, eo, message, FALSE);
4251       goto out;
4252     }
4253   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
4254            g_strcmp0 (member, "GetAll") == 0 &&
4255            g_strcmp0 (signature, "s") == 0)
4256     {
4257       handled = handle_get_all_properties (connection, eo, message);
4258       goto out;
4259     }
4260
4261  out:
4262   return handled;
4263 }
4264
4265 /**
4266  * g_dbus_connection_register_object:
4267  * @connection: A #GDBusConnection.
4268  * @object_path: The object path to register at.
4269  * @interface_info: Introspection data for the interface.
4270  * @vtable: A #GDBusInterfaceVTable to call into or %NULL.
4271  * @user_data: Data to pass to functions in @vtable.
4272  * @user_data_free_func: Function to call when the object path is unregistered.
4273  * @error: Return location for error or %NULL.
4274  *
4275  * Registers callbacks for exported objects at @object_path with the
4276  * D-Bus interface that is described in @interface_info.
4277  *
4278  * Calls to functions in @vtable (and @user_data_free_func) will
4279  * happen in the <link linkend="g-main-context-push-thread-default">thread-default main
4280  * loop</link> of the thread you are calling this method from.
4281  *
4282  * Note that all #GVariant values passed to functions in @vtable will match
4283  * the signature given in @interface_info - if a remote caller passes
4284  * incorrect values, the <literal>org.freedesktop.DBus.Error.InvalidArgs</literal>
4285  * is returned to the remote caller.
4286  *
4287  * Additionally, if the remote caller attempts to invoke methods or
4288  * access properties not mentioned in @interface_info the
4289  * <literal>org.freedesktop.DBus.Error.UnknownMethod</literal> resp.
4290  * <literal>org.freedesktop.DBus.Error.InvalidArgs</literal> errors
4291  * are returned to the caller.
4292  *
4293  * It is considered a programming error if the
4294  * #GDBusInterfaceGetPropertyFunc function in @vtable returns a
4295  * #GVariant of incorrect type.
4296  *
4297  * If an existing callback is already registered at @object_path and
4298  * @interface_name, then @error is set to #G_IO_ERROR_EXISTS.
4299  *
4300  * Note that @vtable is not copied, so the struct you pass must exist until
4301  * the path is unregistered. One possibility is to free @vtable at the
4302  * same time as @user_data when @user_data_free_func is called.
4303  *
4304  * GDBus automatically implements the standard D-Bus interfaces
4305  * org.freedesktop.DBus.Properties, org.freedesktop.DBus.Introspectable
4306  * and org.freedesktop.Peer, so you don't have to implement those for
4307  * the objects you export. You <emphasis>can</emphasis> implement
4308  * org.freedesktop.DBus.Properties yourself, e.g. to handle getting
4309  * and setting of properties asynchronously.
4310  *
4311  * See <xref linkend="gdbus-server"/> for an example of how to use this method.
4312  *
4313  * Returns: 0 if @error is set, otherwise a registration id (never 0)
4314  * that can be used with g_dbus_connection_unregister_object() .
4315  *
4316  * Since: 2.26
4317  */
4318 guint
4319 g_dbus_connection_register_object (GDBusConnection            *connection,
4320                                    const gchar                *object_path,
4321                                    const GDBusInterfaceInfo   *interface_info,
4322                                    const GDBusInterfaceVTable *vtable,
4323                                    gpointer                    user_data,
4324                                    GDestroyNotify              user_data_free_func,
4325                                    GError                    **error)
4326 {
4327   ExportedObject *eo;
4328   ExportedInterface *ei;
4329   guint ret;
4330
4331   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
4332   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
4333   g_return_val_if_fail (interface_info != NULL, 0);
4334   g_return_val_if_fail (g_dbus_is_interface_name (interface_info->name), 0);
4335   g_return_val_if_fail (error == NULL || *error == NULL, 0);
4336
4337   ret = 0;
4338
4339   CONNECTION_LOCK (connection);
4340
4341   eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path);
4342   if (eo == NULL)
4343     {
4344       eo = g_new0 (ExportedObject, 1);
4345       eo->object_path = g_strdup (object_path);
4346       eo->connection = connection;
4347       eo->map_if_name_to_ei = g_hash_table_new_full (g_str_hash,
4348                                                      g_str_equal,
4349                                                      NULL,
4350                                                      (GDestroyNotify) exported_interface_free);
4351       g_hash_table_insert (connection->map_object_path_to_eo, eo->object_path, eo);
4352     }
4353
4354   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_info->name);
4355   if (ei != NULL)
4356     {
4357       g_set_error (error,
4358                    G_IO_ERROR,
4359                    G_IO_ERROR_EXISTS,
4360                    _("An object is already exported for the interface %s at %s"),
4361                    interface_info->name,
4362                    object_path);
4363       goto out;
4364     }
4365
4366   ei = g_new0 (ExportedInterface, 1);
4367   ei->id = _global_registration_id++; /* TODO: overflow etc. */
4368   ei->eo = eo;
4369   ei->user_data = user_data;
4370   ei->user_data_free_func = user_data_free_func;
4371   ei->vtable = vtable;
4372   ei->interface_info = g_dbus_interface_info_ref ((GDBusInterfaceInfo *) interface_info);
4373   ei->interface_name = g_strdup (interface_info->name);
4374   ei->context = g_main_context_get_thread_default ();
4375   if (ei->context != NULL)
4376     g_main_context_ref (ei->context);
4377
4378   g_hash_table_insert (eo->map_if_name_to_ei,
4379                        (gpointer) ei->interface_name,
4380                        ei);
4381   g_hash_table_insert (connection->map_id_to_ei,
4382                        GUINT_TO_POINTER (ei->id),
4383                        ei);
4384
4385   ret = ei->id;
4386
4387  out:
4388   CONNECTION_UNLOCK (connection);
4389
4390   return ret;
4391 }
4392
4393 /**
4394  * g_dbus_connection_unregister_object:
4395  * @connection: A #GDBusConnection.
4396  * @registration_id: A registration id obtained from g_dbus_connection_register_object().
4397  *
4398  * Unregisters an object.
4399  *
4400  * Returns: %TRUE if the object was unregistered, %FALSE otherwise.
4401  *
4402  * Since: 2.26
4403  */
4404 gboolean
4405 g_dbus_connection_unregister_object (GDBusConnection *connection,
4406                                      guint            registration_id)
4407 {
4408   ExportedInterface *ei;
4409   ExportedObject *eo;
4410   gboolean ret;
4411
4412   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
4413
4414   ret = FALSE;
4415
4416   CONNECTION_LOCK (connection);
4417
4418   ei = g_hash_table_lookup (connection->map_id_to_ei,
4419                             GUINT_TO_POINTER (registration_id));
4420   if (ei == NULL)
4421     goto out;
4422
4423   eo = ei->eo;
4424
4425   g_warn_if_fail (g_hash_table_remove (connection->map_id_to_ei, GUINT_TO_POINTER (ei->id)));
4426   g_warn_if_fail (g_hash_table_remove (eo->map_if_name_to_ei, ei->interface_name));
4427   /* unregister object path if we have no more exported interfaces */
4428   if (g_hash_table_size (eo->map_if_name_to_ei) == 0)
4429     g_warn_if_fail (g_hash_table_remove (connection->map_object_path_to_eo,
4430                                          eo->object_path));
4431
4432   ret = TRUE;
4433
4434  out:
4435   CONNECTION_UNLOCK (connection);
4436
4437   return ret;
4438 }
4439
4440 /* ---------------------------------------------------------------------------------------------------- */
4441
4442 /**
4443  * g_dbus_connection_emit_signal:
4444  * @connection: A #GDBusConnection.
4445  * @destination_bus_name: The unique bus name for the destination for the signal or %NULL to emit to all listeners.
4446  * @object_path: Path of remote object.
4447  * @interface_name: D-Bus interface to emit a signal on.
4448  * @signal_name: The name of the signal to emit.
4449  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
4450  * @error: Return location for error or %NULL.
4451  *
4452  * Emits a signal.
4453  *
4454  * If the parameters GVariant is floating, it is consumed.
4455  *
4456  * This can only fail if @parameters is not compatible with the D-Bus protocol.
4457  *
4458  * Returns: %TRUE unless @error is set.
4459  *
4460  * Since: 2.26
4461  */
4462 gboolean
4463 g_dbus_connection_emit_signal (GDBusConnection  *connection,
4464                                const gchar      *destination_bus_name,
4465                                const gchar      *object_path,
4466                                const gchar      *interface_name,
4467                                const gchar      *signal_name,
4468                                GVariant         *parameters,
4469                                GError          **error)
4470 {
4471   GDBusMessage *message;
4472   gboolean ret;
4473
4474   message = NULL;
4475   ret = FALSE;
4476
4477   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
4478   g_return_val_if_fail (destination_bus_name == NULL || g_dbus_is_name (destination_bus_name), FALSE);
4479   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), FALSE);
4480   g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), FALSE);
4481   g_return_val_if_fail (signal_name != NULL && g_dbus_is_member_name (signal_name), FALSE);
4482   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), FALSE);
4483
4484   if (G_UNLIKELY (_g_dbus_debug_emission ()))
4485     {
4486       _g_dbus_debug_print_lock ();
4487       g_print ("========================================================================\n"
4488                "GDBus-debug:Emission:\n"
4489                " >>>> SIGNAL EMISSION %s.%s()\n"
4490                "      on object %s\n"
4491                "      destination %s\n",
4492                interface_name, signal_name,
4493                object_path,
4494                destination_bus_name != NULL ? destination_bus_name : "(none)");
4495       _g_dbus_debug_print_unlock ();
4496     }
4497
4498   message = g_dbus_message_new_signal (object_path,
4499                                        interface_name,
4500                                        signal_name);
4501
4502   if (destination_bus_name != NULL)
4503     g_dbus_message_set_header (message,
4504                                G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION,
4505                                g_variant_new_string (destination_bus_name));
4506
4507   if (parameters != NULL)
4508     g_dbus_message_set_body (message, parameters);
4509
4510   ret = g_dbus_connection_send_message (connection, message, NULL, error);
4511   g_object_unref (message);
4512
4513   return ret;
4514 }
4515
4516 static void
4517 add_call_flags (GDBusMessage           *message,
4518                          GDBusCallFlags  flags)
4519 {
4520   if (flags & G_DBUS_CALL_FLAGS_NO_AUTO_START)
4521     g_dbus_message_set_flags (message, G_DBUS_MESSAGE_FLAGS_NO_AUTO_START);
4522 }
4523
4524 static GVariant *
4525 decode_method_reply (GDBusMessage        *reply,
4526                      const gchar         *method_name,
4527                      const GVariantType  *reply_type,
4528                      GError             **error)
4529 {
4530   GVariant *result;
4531
4532   result = NULL;
4533   switch (g_dbus_message_get_message_type (reply))
4534     {
4535     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
4536       result = g_dbus_message_get_body (reply);
4537       if (result == NULL)
4538         {
4539           result = g_variant_new ("()");
4540           g_variant_ref_sink (result);
4541         }
4542       else
4543         {
4544           g_variant_ref (result);
4545         }
4546
4547       if (!g_variant_is_of_type (result, reply_type))
4548         {
4549           gchar *type_string = g_variant_type_dup_string (reply_type);
4550
4551           g_set_error (error,
4552                        G_IO_ERROR,
4553                        G_IO_ERROR_INVALID_ARGUMENT,
4554                        _("Method `%s' returned type `%s', but expected `%s'"),
4555                        method_name, g_variant_get_type_string (result), type_string);
4556
4557           g_variant_unref (result);
4558           g_free (type_string);
4559           result = NULL;
4560         }
4561       break;
4562
4563     case G_DBUS_MESSAGE_TYPE_ERROR:
4564       g_dbus_message_to_gerror (reply, error);
4565       break;
4566
4567     default:
4568       g_assert_not_reached ();
4569       break;
4570     }
4571
4572   return result;
4573 }
4574
4575
4576 typedef struct
4577 {
4578   GSimpleAsyncResult *simple;
4579   GVariantType *reply_type;
4580   gchar *method_name; /* for error message */
4581   guint32 serial;
4582 } CallState;
4583
4584 static void
4585 g_dbus_connection_call_done (GObject      *source,
4586                              GAsyncResult *result,
4587                              gpointer      user_data)
4588 {
4589   GDBusConnection *connection = G_DBUS_CONNECTION (source);
4590   CallState *state = user_data;
4591   GError *error;
4592   GDBusMessage *reply;
4593   GVariant *value;
4594
4595   error = NULL;
4596   reply = g_dbus_connection_send_message_with_reply_finish (connection,
4597                                                             result,
4598                                                             &error);
4599
4600   if (G_UNLIKELY (_g_dbus_debug_call ()))
4601     {
4602       _g_dbus_debug_print_lock ();
4603       g_print ("========================================================================\n"
4604                "GDBus-debug:Call:\n"
4605                " >>>> ASYNC COMPLETE %s() (serial %d)\n"
4606                "      ",
4607                state->method_name,
4608                state->serial);
4609       if (reply != NULL)
4610         {
4611           g_print ("SUCCESS\n");
4612         }
4613       else
4614         {
4615           g_print ("FAILED: %s\n",
4616                    error->message);
4617         }
4618       _g_dbus_debug_print_unlock ();
4619     }
4620
4621
4622   if (reply != NULL)
4623     {
4624       value = decode_method_reply (reply, state->method_name,
4625                                    state->reply_type, &error);
4626       g_object_unref (reply);
4627     }
4628   else
4629     value = NULL;
4630
4631   if (value == NULL)
4632     {
4633       g_simple_async_result_set_from_error (state->simple, error);
4634       g_error_free (error);
4635     }
4636   else
4637     g_simple_async_result_set_op_res_gpointer (state->simple, value,
4638                                                (GDestroyNotify) g_variant_unref);
4639
4640   g_simple_async_result_complete (state->simple);
4641   g_variant_type_free (state->reply_type);
4642   g_object_unref (state->simple);
4643   g_free (state->method_name);
4644
4645   g_slice_free (CallState, state);
4646 }
4647
4648 /**
4649  * g_dbus_connection_call:
4650  * @connection: A #GDBusConnection.
4651  * @bus_name: A unique or well-known bus name or %NULL if @connection is not a message bus connection.
4652  * @object_path: Path of remote object.
4653  * @interface_name: D-Bus interface to invoke method on.
4654  * @method_name: The name of the method to invoke.
4655  * @parameters: A #GVariant tuple with parameters for the method or %NULL if not passing parameters.
4656  * @reply_type: The expected type of the reply, or %NULL.
4657  * @flags: Flags from the #GDBusCallFlags enumeration.
4658  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
4659  * @cancellable: A #GCancellable or %NULL.
4660  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
4661  * care about the result of the method invocation.
4662  * @user_data: The data to pass to @callback.
4663  *
4664  * Asynchronously invokes the @method_name method on the
4665  * @interface_name D-Bus interface on the remote object at
4666  * @object_path owned by @bus_name.
4667  *
4668  * If @connection is closed then the operation will fail with
4669  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
4670  * fail with %G_IO_ERROR_CANCELLED. If @parameters contains a value
4671  * not compatible with the D-Bus protocol, the operation fails with
4672  * %G_IO_ERROR_INVALID_ARGUMENT.
4673  *
4674  * If @reply_type is non-%NULL then the reply will be checked for having this type and an
4675  * error will be raised if it does not match.  Said another way, if you give a @reply_type
4676  * then any non-%NULL return value will be of this type.
4677  *
4678  * If the @parameters #GVariant is floating, it is consumed. This allows
4679  * convenient 'inline' use of g_variant_new(), e.g.:
4680  * |[
4681  *  g_dbus_connection_call (connection,
4682  *                          "org.freedesktop.StringThings",
4683  *                          "/org/freedesktop/StringThings",
4684  *                          "org.freedesktop.StringThings",
4685  *                          "TwoStrings",
4686  *                          g_variant_new ("(ss)",
4687  *                                         "Thing One",
4688  *                                         "Thing Two"),
4689  *                          NULL,
4690  *                          G_DBUS_CALL_FLAGS_NONE,
4691  *                          -1,
4692  *                          NULL,
4693  *                          (GAsyncReadyCallback) two_strings_done,
4694  *                          NULL);
4695  * ]|
4696  *
4697  * This is an asynchronous method. When the operation is finished, @callback will be invoked
4698  * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
4699  * of the thread you are calling this method from. You can then call
4700  * g_dbus_connection_call_finish() to get the result of the operation.
4701  * See g_dbus_connection_call_sync() for the synchronous version of this
4702  * function.
4703  *
4704  * Since: 2.26
4705  */
4706 void
4707 g_dbus_connection_call (GDBusConnection        *connection,
4708                         const gchar            *bus_name,
4709                         const gchar            *object_path,
4710                         const gchar            *interface_name,
4711                         const gchar            *method_name,
4712                         GVariant               *parameters,
4713                         const GVariantType     *reply_type,
4714                         GDBusCallFlags          flags,
4715                         gint                    timeout_msec,
4716                         GCancellable           *cancellable,
4717                         GAsyncReadyCallback     callback,
4718                         gpointer                user_data)
4719 {
4720   GDBusMessage *message;
4721   CallState *state;
4722
4723   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
4724   g_return_if_fail (bus_name == NULL || g_dbus_is_name (bus_name));
4725   g_return_if_fail (object_path != NULL && g_variant_is_object_path (object_path));
4726   g_return_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name));
4727   g_return_if_fail (method_name != NULL && g_dbus_is_member_name (method_name));
4728   g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
4729   g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
4730
4731   state = g_slice_new (CallState);
4732   state->simple = g_simple_async_result_new (G_OBJECT (connection),
4733                                              callback, user_data,
4734                                              g_dbus_connection_call);
4735   state->method_name = g_strjoin (".", interface_name, method_name, NULL);
4736
4737   if (reply_type == NULL)
4738     reply_type = G_VARIANT_TYPE_ANY;
4739
4740   state->reply_type = g_variant_type_copy (reply_type);
4741
4742   message = g_dbus_message_new_method_call (bus_name,
4743                                             object_path,
4744                                             interface_name,
4745                                             method_name);
4746   add_call_flags (message, flags);
4747   if (parameters != NULL)
4748     g_dbus_message_set_body (message, parameters);
4749
4750   g_dbus_connection_send_message_with_reply (connection,
4751                                              message,
4752                                              timeout_msec,
4753                                              &state->serial,
4754                                              cancellable,
4755                                              g_dbus_connection_call_done,
4756                                              state);
4757
4758   if (G_UNLIKELY (_g_dbus_debug_call ()))
4759     {
4760       _g_dbus_debug_print_lock ();
4761       g_print ("========================================================================\n"
4762                "GDBus-debug:Call:\n"
4763                " >>>> ASYNC %s.%s()\n"
4764                "      on object %s\n"
4765                "      owned by name %s (serial %d)\n",
4766                interface_name,
4767                method_name,
4768                object_path,
4769                bus_name != NULL ? bus_name : "(none)",
4770                state->serial);
4771       _g_dbus_debug_print_unlock ();
4772     }
4773
4774   if (message != NULL)
4775     g_object_unref (message);
4776 }
4777
4778 /**
4779  * g_dbus_connection_call_finish:
4780  * @connection: A #GDBusConnection.
4781  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_call().
4782  * @error: Return location for error or %NULL.
4783  *
4784  * Finishes an operation started with g_dbus_connection_call().
4785  *
4786  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
4787  * return values. Free with g_variant_unref().
4788  *
4789  * Since: 2.26
4790  */
4791 GVariant *
4792 g_dbus_connection_call_finish (GDBusConnection  *connection,
4793                                GAsyncResult     *res,
4794                                GError          **error)
4795 {
4796   GSimpleAsyncResult *simple;
4797
4798   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
4799   g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (connection),
4800                                                         g_dbus_connection_call), NULL);
4801   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
4802
4803   simple = G_SIMPLE_ASYNC_RESULT (res);
4804
4805   if (g_simple_async_result_propagate_error (simple, error))
4806     return FALSE;
4807
4808   return g_variant_ref (g_simple_async_result_get_op_res_gpointer (simple));
4809 }
4810
4811 /* ---------------------------------------------------------------------------------------------------- */
4812
4813 /**
4814  * g_dbus_connection_call_sync:
4815  * @connection: A #GDBusConnection.
4816  * @bus_name: A unique or well-known bus name.
4817  * @object_path: Path of remote object.
4818  * @interface_name: D-Bus interface to invoke method on.
4819  * @method_name: The name of the method to invoke.
4820  * @parameters: A #GVariant tuple with parameters for the method or %NULL if not passing parameters.
4821  * @reply_type: The expected type of the reply, or %NULL.
4822  * @flags: Flags from the #GDBusCallFlags enumeration.
4823  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
4824  * @cancellable: A #GCancellable or %NULL.
4825  * @error: Return location for error or %NULL.
4826  *
4827  * Synchronously invokes the @method_name method on the
4828  * @interface_name D-Bus interface on the remote object at
4829  * @object_path owned by @bus_name.
4830  *
4831  * If @connection is closed then the operation will fail with
4832  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the
4833  * operation will fail with %G_IO_ERROR_CANCELLED. If @parameters
4834  * contains a value not compatible with the D-Bus protocol, the operation
4835  * fails with %G_IO_ERROR_INVALID_ARGUMENT.
4836
4837  * If @reply_type is non-%NULL then the reply will be checked for having
4838  * this type and an error will be raised if it does not match.  Said
4839  * another way, if you give a @reply_type then any non-%NULL return
4840  * value will be of this type.
4841  *
4842  * If the @parameters #GVariant is floating, it is consumed.
4843  * This allows convenient 'inline' use of g_variant_new(), e.g.:
4844  * |[
4845  *  g_dbus_connection_call_sync (connection,
4846  *                               "org.freedesktop.StringThings",
4847  *                               "/org/freedesktop/StringThings",
4848  *                               "org.freedesktop.StringThings",
4849  *                               "TwoStrings",
4850  *                               g_variant_new ("(ss)",
4851  *                                              "Thing One",
4852  *                                              "Thing Two"),
4853  *                               NULL,
4854  *                               G_DBUS_CALL_FLAGS_NONE,
4855  *                               -1,
4856  *                               NULL,
4857  *                               &amp;error);
4858  * ]|
4859  *
4860  * The calling thread is blocked until a reply is received. See
4861  * g_dbus_connection_call() for the asynchronous version of
4862  * this method.
4863  *
4864  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
4865  * return values. Free with g_variant_unref().
4866  *
4867  * Since: 2.26
4868  */
4869 GVariant *
4870 g_dbus_connection_call_sync (GDBusConnection         *connection,
4871                              const gchar             *bus_name,
4872                              const gchar             *object_path,
4873                              const gchar             *interface_name,
4874                              const gchar             *method_name,
4875                              GVariant                *parameters,
4876                              const GVariantType      *reply_type,
4877                              GDBusCallFlags           flags,
4878                              gint                     timeout_msec,
4879                              GCancellable            *cancellable,
4880                              GError                 **error)
4881 {
4882   GDBusMessage *message;
4883   GDBusMessage *reply;
4884   GVariant *result;
4885   GError *local_error;
4886
4887   message = NULL;
4888   reply = NULL;
4889   result = NULL;
4890
4891   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
4892   g_return_val_if_fail (bus_name == NULL || g_dbus_is_name (bus_name), NULL);
4893   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), NULL);
4894   g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), NULL);
4895   g_return_val_if_fail (method_name != NULL && g_dbus_is_member_name (method_name), NULL);
4896   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
4897   g_return_val_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
4898
4899   if (reply_type == NULL)
4900     reply_type = G_VARIANT_TYPE_ANY;
4901
4902   message = g_dbus_message_new_method_call (bus_name,
4903                                             object_path,
4904                                             interface_name,
4905                                             method_name);
4906   add_call_flags (message, flags);
4907   if (parameters != NULL)
4908     g_dbus_message_set_body (message, parameters);
4909
4910   if (G_UNLIKELY (_g_dbus_debug_call ()))
4911     {
4912       _g_dbus_debug_print_lock ();
4913       g_print ("========================================================================\n"
4914                "GDBus-debug:Call:\n"
4915                " >>>> SYNC %s.%s()\n"
4916                "      on object %s\n"
4917                "      owned by name %s\n",
4918                interface_name,
4919                method_name,
4920                object_path,
4921                bus_name != NULL ? bus_name : "(none)");
4922       _g_dbus_debug_print_unlock ();
4923     }
4924
4925   local_error = NULL;
4926   reply = g_dbus_connection_send_message_with_reply_sync (connection,
4927                                                           message,
4928                                                           timeout_msec,
4929                                                           NULL, /* volatile guint32 *out_serial */
4930                                                           cancellable,
4931                                                           &local_error);
4932
4933   if (G_UNLIKELY (_g_dbus_debug_call ()))
4934     {
4935       _g_dbus_debug_print_lock ();
4936       g_print ("========================================================================\n"
4937                "GDBus-debug:Call:\n"
4938                " <<<< SYNC COMPLETE %s.%s()\n"
4939                "      ",
4940                interface_name,
4941                method_name);
4942       if (reply != NULL)
4943         {
4944           g_print ("SUCCESS\n");
4945         }
4946       else
4947         {
4948           g_print ("FAILED: %s\n",
4949                    local_error->message);
4950         }
4951       _g_dbus_debug_print_unlock ();
4952     }
4953
4954   if (reply == NULL)
4955     {
4956       if (error != NULL)
4957         *error = local_error;
4958       else
4959         g_error_free (local_error);
4960       goto out;
4961     }
4962
4963   result = decode_method_reply (reply, method_name, reply_type, error);
4964
4965  out:
4966   if (message != NULL)
4967     g_object_unref (message);
4968   if (reply != NULL)
4969     g_object_unref (reply);
4970
4971   return result;
4972 }
4973
4974 /* ---------------------------------------------------------------------------------------------------- */
4975
4976 struct ExportedSubtree
4977 {
4978   guint                     id;
4979   gchar                    *object_path;
4980   GDBusConnection          *connection;
4981   const GDBusSubtreeVTable *vtable;
4982   GDBusSubtreeFlags         flags;
4983
4984   GMainContext             *context;
4985   gpointer                  user_data;
4986   GDestroyNotify            user_data_free_func;
4987 };
4988
4989 static void
4990 exported_subtree_free (ExportedSubtree *es)
4991 {
4992   if (es->user_data_free_func != NULL)
4993     /* TODO: push to thread-default mainloop */
4994     es->user_data_free_func (es->user_data);
4995
4996   if (es->context != NULL)
4997     g_main_context_unref (es->context);
4998
4999   g_free (es->object_path);
5000   g_free (es);
5001 }
5002
5003 /* called without lock held */
5004 static gboolean
5005 handle_subtree_introspect (GDBusConnection *connection,
5006                            ExportedSubtree *es,
5007                            GDBusMessage    *message)
5008 {
5009   GString *s;
5010   gboolean handled;
5011   GDBusMessage *reply;
5012   gchar **children;
5013   gboolean is_root;
5014   const gchar *sender;
5015   const gchar *requested_object_path;
5016   const gchar *requested_node;
5017   GPtrArray *interfaces;
5018   guint n;
5019   gchar **subnode_paths;
5020
5021   handled = FALSE;
5022
5023   requested_object_path = g_dbus_message_get_path (message);
5024   sender = g_dbus_message_get_sender (message);
5025   is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
5026
5027   s = g_string_new (NULL);
5028   introspect_append_header (s);
5029
5030   /* Strictly we don't need the children in dynamic mode, but we avoid the
5031    * conditionals to preserve code clarity
5032    */
5033   children = es->vtable->enumerate (es->connection,
5034                                     sender,
5035                                     es->object_path,
5036                                     es->user_data);
5037
5038   if (!is_root)
5039     {
5040       requested_node = strrchr (requested_object_path, '/') + 1;
5041
5042       /* Assert existence of object if we are not dynamic */
5043       if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
5044           !_g_strv_has_string ((const gchar * const *) children, requested_node))
5045         goto out;
5046     }
5047   else
5048     {
5049       requested_node = "/";
5050     }
5051
5052   interfaces = es->vtable->introspect (es->connection,
5053                                        sender,
5054                                        es->object_path,
5055                                        requested_node,
5056                                        es->user_data);
5057   if (interfaces != NULL)
5058     {
5059       if (interfaces->len > 0)
5060         {
5061           /* we're in business */
5062           introspect_append_standard_interfaces (s);
5063
5064           for (n = 0; n < interfaces->len; n++)
5065             {
5066               const GDBusInterfaceInfo *interface_info = interfaces->pdata[n];
5067               g_dbus_interface_info_generate_xml (interface_info, 2, s);
5068             }
5069         }
5070       g_ptr_array_unref (interfaces);
5071     }
5072
5073   /* then include <node> entries from the Subtree for the root */
5074   if (is_root)
5075     {
5076       for (n = 0; children != NULL && children[n] != NULL; n++)
5077         g_string_append_printf (s, "  <node name=\"%s\"/>\n", children[n]);
5078     }
5079
5080   /* finally include nodes registered below us */
5081   subnode_paths = g_dbus_connection_list_registered (es->connection, requested_object_path);
5082   for (n = 0; subnode_paths != NULL && subnode_paths[n] != NULL; n++)
5083     g_string_append_printf (s, "  <node name=\"%s\"/>\n", subnode_paths[n]);
5084   g_strfreev (subnode_paths);
5085
5086   g_string_append (s, "</node>\n");
5087
5088   reply = g_dbus_message_new_method_reply (message);
5089   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
5090   g_dbus_connection_send_message (connection, reply, NULL, NULL);
5091   g_object_unref (reply);
5092
5093   handled = TRUE;
5094
5095  out:
5096   g_string_free (s, TRUE);
5097   g_strfreev (children);
5098   return handled;
5099 }
5100
5101 /* called without lock held */
5102 static gboolean
5103 handle_subtree_method_invocation (GDBusConnection *connection,
5104                                   ExportedSubtree *es,
5105                                   GDBusMessage    *message)
5106 {
5107   gboolean handled;
5108   const gchar *sender;
5109   const gchar *interface_name;
5110   const gchar *member;
5111   const gchar *signature;
5112   const gchar *requested_object_path;
5113   const gchar *requested_node;
5114   gboolean is_root;
5115   gchar **children;
5116   const GDBusInterfaceInfo *interface_info;
5117   const GDBusInterfaceVTable *interface_vtable;
5118   gpointer interface_user_data;
5119   guint n;
5120   GPtrArray *interfaces;
5121   gboolean is_property_get;
5122   gboolean is_property_set;
5123   gboolean is_property_get_all;
5124
5125   handled = FALSE;
5126   interfaces = NULL;
5127
5128   requested_object_path = g_dbus_message_get_path (message);
5129   sender = g_dbus_message_get_sender (message);
5130   interface_name = g_dbus_message_get_interface (message);
5131   member = g_dbus_message_get_member (message);
5132   signature = g_dbus_message_get_signature (message);
5133   is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
5134
5135   is_property_get = FALSE;
5136   is_property_set = FALSE;
5137   is_property_get_all = FALSE;
5138   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0)
5139     {
5140       if (g_strcmp0 (member, "Get") == 0 && g_strcmp0 (signature, "ss") == 0)
5141         is_property_get = TRUE;
5142       else if (g_strcmp0 (member, "Set") == 0 && g_strcmp0 (signature, "ssv") == 0)
5143         is_property_set = TRUE;
5144       else if (g_strcmp0 (member, "GetAll") == 0 && g_strcmp0 (signature, "s") == 0)
5145         is_property_get_all = TRUE;
5146     }
5147
5148   children = es->vtable->enumerate (es->connection,
5149                                     sender,
5150                                     es->object_path,
5151                                     es->user_data);
5152
5153   if (!is_root)
5154     {
5155       requested_node = strrchr (requested_object_path, '/') + 1;
5156
5157       /* If not dynamic, skip if requested node is not part of children */
5158       if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
5159           !_g_strv_has_string ((const gchar * const *) children, requested_node))
5160         goto out;
5161     }
5162   else
5163     {
5164       requested_node = "/";
5165     }
5166
5167   /* get introspection data for the node */
5168   interfaces = es->vtable->introspect (es->connection,
5169                                        sender,
5170                                        requested_object_path,
5171                                        requested_node,
5172                                        es->user_data);
5173   g_assert (interfaces != NULL);
5174   interface_info = NULL;
5175   for (n = 0; n < interfaces->len; n++)
5176     {
5177       const GDBusInterfaceInfo *id_n = (const GDBusInterfaceInfo *) interfaces->pdata[n];
5178       if (g_strcmp0 (id_n->name, interface_name) == 0)
5179         interface_info = id_n;
5180     }
5181
5182   /* dispatch the call if the user wants to handle it */
5183   if (interface_info != NULL)
5184     {
5185       /* figure out where to dispatch the method call */
5186       interface_user_data = NULL;
5187       interface_vtable = es->vtable->dispatch (es->connection,
5188                                                sender,
5189                                                es->object_path,
5190                                                interface_name,
5191                                                requested_node,
5192                                                &interface_user_data,
5193                                                es->user_data);
5194       if (interface_vtable == NULL)
5195         goto out;
5196
5197       CONNECTION_LOCK (connection);
5198       handled = validate_and_maybe_schedule_method_call (es->connection,
5199                                                          message,
5200                                                          0,
5201                                                          es->id,
5202                                                          interface_info,
5203                                                          interface_vtable,
5204                                                          es->context,
5205                                                          interface_user_data);
5206       CONNECTION_UNLOCK (connection);
5207     }
5208   /* handle org.freedesktop.DBus.Properties interface if not explicitly handled */
5209   else if (is_property_get || is_property_set || is_property_get_all)
5210     {
5211       if (is_property_get)
5212         g_variant_get (g_dbus_message_get_body (message), "(&s&s)", &interface_name, NULL);
5213       else if (is_property_set)
5214         g_variant_get (g_dbus_message_get_body (message), "(&s&sv)", &interface_name, NULL, NULL);
5215       else if (is_property_get_all)
5216         g_variant_get (g_dbus_message_get_body (message), "(&s)", &interface_name, NULL, NULL);
5217       else
5218         g_assert_not_reached ();
5219
5220       /* see if the object supports this interface at all */
5221       for (n = 0; n < interfaces->len; n++)
5222         {
5223           const GDBusInterfaceInfo *id_n = (const GDBusInterfaceInfo *) interfaces->pdata[n];
5224           if (g_strcmp0 (id_n->name, interface_name) == 0)
5225             interface_info = id_n;
5226         }
5227
5228       /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the user-code
5229        * claims it won't support the interface
5230        */
5231       if (interface_info == NULL)
5232         {
5233           GDBusMessage *reply;
5234           reply = g_dbus_message_new_method_error (message,
5235                                                    "org.freedesktop.DBus.Error.InvalidArgs",
5236                                                    _("No such interface `%s'"),
5237                                                    interface_name);
5238           g_dbus_connection_send_message (es->connection, reply, NULL, NULL);
5239           g_object_unref (reply);
5240           handled = TRUE;
5241           goto out;
5242         }
5243
5244       /* figure out where to dispatch the property get/set/getall calls */
5245       interface_user_data = NULL;
5246       interface_vtable = es->vtable->dispatch (es->connection,
5247                                                sender,
5248                                                es->object_path,
5249                                                interface_name,
5250                                                requested_node,
5251                                                &interface_user_data,
5252                                                es->user_data);
5253       if (interface_vtable == NULL)
5254         goto out;
5255
5256       if (is_property_get || is_property_set)
5257         {
5258           CONNECTION_LOCK (connection);
5259           handled = validate_and_maybe_schedule_property_getset (es->connection,
5260                                                                  message,
5261                                                                  0,
5262                                                                  es->id,
5263                                                                  is_property_get,
5264                                                                  interface_info,
5265                                                                  interface_vtable,
5266                                                                  es->context,
5267                                                                  interface_user_data);
5268           CONNECTION_UNLOCK (connection);
5269         }
5270       else if (is_property_get_all)
5271         {
5272           CONNECTION_LOCK (connection);
5273           handled = validate_and_maybe_schedule_property_get_all (es->connection,
5274                                                                   message,
5275                                                                   0,
5276                                                                   es->id,
5277                                                                   interface_info,
5278                                                                   interface_vtable,
5279                                                                   es->context,
5280                                                                   interface_user_data);
5281           CONNECTION_UNLOCK (connection);
5282         }
5283     }
5284
5285  out:
5286   if (interfaces != NULL)
5287     g_ptr_array_unref (interfaces);
5288   g_strfreev (children);
5289   return handled;
5290 }
5291
5292 typedef struct
5293 {
5294   GDBusMessage *message;
5295   ExportedSubtree *es;
5296 } SubtreeDeferredData;
5297
5298 static void
5299 subtree_deferred_data_free (SubtreeDeferredData *data)
5300 {
5301   g_object_unref (data->message);
5302   g_free (data);
5303 }
5304
5305 /* called without lock held in the thread where the caller registered the subtree */
5306 static gboolean
5307 process_subtree_vtable_message_in_idle_cb (gpointer _data)
5308 {
5309   SubtreeDeferredData *data = _data;
5310   gboolean handled;
5311
5312   handled = FALSE;
5313
5314   if (g_strcmp0 (g_dbus_message_get_interface (data->message), "org.freedesktop.DBus.Introspectable") == 0 &&
5315       g_strcmp0 (g_dbus_message_get_member (data->message), "Introspect") == 0 &&
5316       g_strcmp0 (g_dbus_message_get_signature (data->message), "") == 0)
5317     handled = handle_subtree_introspect (data->es->connection,
5318                                          data->es,
5319                                          data->message);
5320   else
5321     handled = handle_subtree_method_invocation (data->es->connection,
5322                                                 data->es,
5323                                                 data->message);
5324
5325   if (!handled)
5326     {
5327       CONNECTION_LOCK (data->es->connection);
5328       handled = handle_generic_unlocked (data->es->connection, data->message);
5329       CONNECTION_UNLOCK (data->es->connection);
5330     }
5331
5332   /* if we couldn't handle the request, just bail with the UnknownMethod error */
5333   if (!handled)
5334     {
5335       GDBusMessage *reply;
5336       reply = g_dbus_message_new_method_error (data->message,
5337                                                "org.freedesktop.DBus.Error.UnknownMethod",
5338                                                _("Method `%s' on interface `%s' with signature `%s' does not exist"),
5339                                                g_dbus_message_get_member (data->message),
5340                                                g_dbus_message_get_interface (data->message),
5341                                                g_dbus_message_get_signature (data->message));
5342       g_dbus_connection_send_message (data->es->connection, reply, NULL, NULL);
5343       g_object_unref (reply);
5344     }
5345
5346   return FALSE;
5347 }
5348
5349 /* called in message handler thread with lock held */
5350 static gboolean
5351 subtree_message_func (GDBusConnection *connection,
5352                       ExportedSubtree *es,
5353                       GDBusMessage    *message)
5354 {
5355   GSource *idle_source;
5356   SubtreeDeferredData *data;
5357
5358   data = g_new0 (SubtreeDeferredData, 1);
5359   data->message = g_object_ref (message);
5360   data->es = es;
5361
5362   /* defer this call to an idle handler in the right thread */
5363   idle_source = g_idle_source_new ();
5364   g_source_set_priority (idle_source, G_PRIORITY_HIGH);
5365   g_source_set_callback (idle_source,
5366                          process_subtree_vtable_message_in_idle_cb,
5367                          data,
5368                          (GDestroyNotify) subtree_deferred_data_free);
5369   g_source_attach (idle_source, es->context);
5370   g_source_unref (idle_source);
5371
5372   /* since we own the entire subtree, handlers for objects not in the subtree have been
5373    * tried already by libdbus-1 - so we just need to ensure that we're always going
5374    * to reply to the message
5375    */
5376   return TRUE;
5377 }
5378
5379 /**
5380  * g_dbus_connection_register_subtree:
5381  * @connection: A #GDBusConnection.
5382  * @object_path: The object path to register the subtree at.
5383  * @vtable: A #GDBusSubtreeVTable to enumerate, introspect and dispatch nodes in the subtree.
5384  * @flags: Flags used to fine tune the behavior of the subtree.
5385  * @user_data: Data to pass to functions in @vtable.
5386  * @user_data_free_func: Function to call when the subtree is unregistered.
5387  * @error: Return location for error or %NULL.
5388  *
5389  * Registers a whole subtree of <quote>dynamic</quote> objects.
5390  *
5391  * The @enumerate and @introspection functions in @vtable are used to
5392  * convey, to remote callers, what nodes exist in the subtree rooted
5393  * by @object_path.
5394  *
5395  * When handling remote calls into any node in the subtree, first the
5396  * @enumerate function is used to check if the node exists. If the node exists
5397  * or the #G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag is set
5398  * the @introspection function is used to check if the node supports the
5399  * requested method. If so, the @dispatch function is used to determine
5400  * where to dispatch the call. The collected #GDBusInterfaceVTable and
5401  * #gpointer will be used to call into the interface vtable for processing
5402  * the request.
5403  *
5404  * All calls into user-provided code will be invoked in the <link
5405  * linkend="g-main-context-push-thread-default">thread-default main
5406  * loop</link> of the thread you are calling this method from.
5407  *
5408  * If an existing subtree is already registered at @object_path or
5409  * then @error is set to #G_IO_ERROR_EXISTS.
5410  *
5411  * Note that it is valid to register regular objects (using
5412  * g_dbus_connection_register_object()) in a subtree registered with
5413  * g_dbus_connection_register_subtree() - if so, the subtree handler
5414  * is tried as the last resort. One way to think about a subtree
5415  * handler is to consider it a <quote>fallback handler</quote>
5416  * for object paths not registered via g_dbus_connection_register_object()
5417  * or other bindings.
5418  *
5419  * See <xref linkend="gdbus-subtree-server"/> for an example of how to use this method.
5420  *
5421  * Returns: 0 if @error is set, otherwise a subtree registration id (never 0)
5422  * that can be used with g_dbus_connection_unregister_subtree() .
5423  *
5424  * Since: 2.26
5425  */
5426 guint
5427 g_dbus_connection_register_subtree (GDBusConnection           *connection,
5428                                     const gchar               *object_path,
5429                                     const GDBusSubtreeVTable  *vtable,
5430                                     GDBusSubtreeFlags          flags,
5431                                     gpointer                   user_data,
5432                                     GDestroyNotify             user_data_free_func,
5433                                     GError                   **error)
5434 {
5435   guint ret;
5436   ExportedSubtree *es;
5437
5438   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
5439   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
5440   g_return_val_if_fail (vtable != NULL, 0);
5441   g_return_val_if_fail (error == NULL || *error == NULL, 0);
5442
5443   ret = 0;
5444
5445   CONNECTION_LOCK (connection);
5446
5447   es = g_hash_table_lookup (connection->map_object_path_to_es, object_path);
5448   if (es != NULL)
5449     {
5450       g_set_error (error,
5451                    G_IO_ERROR,
5452                    G_IO_ERROR_EXISTS,
5453                    _("A subtree is already exported for %s"),
5454                    object_path);
5455       goto out;
5456     }
5457
5458   es = g_new0 (ExportedSubtree, 1);
5459   es->object_path = g_strdup (object_path);
5460   es->connection = connection;
5461
5462   es->vtable = vtable;
5463   es->flags = flags;
5464   es->id = _global_subtree_registration_id++; /* TODO: overflow etc. */
5465   es->user_data = user_data;
5466   es->user_data_free_func = user_data_free_func;
5467   es->context = g_main_context_get_thread_default ();
5468   if (es->context != NULL)
5469     g_main_context_ref (es->context);
5470
5471   g_hash_table_insert (connection->map_object_path_to_es, es->object_path, es);
5472   g_hash_table_insert (connection->map_id_to_es,
5473                        GUINT_TO_POINTER (es->id),
5474                        es);
5475
5476   ret = es->id;
5477
5478  out:
5479   CONNECTION_UNLOCK (connection);
5480
5481   return ret;
5482 }
5483
5484 /* ---------------------------------------------------------------------------------------------------- */
5485
5486 /**
5487  * g_dbus_connection_unregister_subtree:
5488  * @connection: A #GDBusConnection.
5489  * @registration_id: A subtree registration id obtained from g_dbus_connection_register_subtree().
5490  *
5491  * Unregisters a subtree.
5492  *
5493  * Returns: %TRUE if the subtree was unregistered, %FALSE otherwise.
5494  *
5495  * Since: 2.26
5496  */
5497 gboolean
5498 g_dbus_connection_unregister_subtree (GDBusConnection *connection,
5499                                       guint            registration_id)
5500 {
5501   ExportedSubtree *es;
5502   gboolean ret;
5503
5504   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
5505
5506   ret = FALSE;
5507
5508   CONNECTION_LOCK (connection);
5509
5510   es = g_hash_table_lookup (connection->map_id_to_es,
5511                             GUINT_TO_POINTER (registration_id));
5512   if (es == NULL)
5513     goto out;
5514
5515   g_warn_if_fail (g_hash_table_remove (connection->map_id_to_es, GUINT_TO_POINTER (es->id)));
5516   g_warn_if_fail (g_hash_table_remove (connection->map_object_path_to_es, es->object_path));
5517
5518   ret = TRUE;
5519
5520  out:
5521   CONNECTION_UNLOCK (connection);
5522
5523   return ret;
5524 }
5525
5526 /* ---------------------------------------------------------------------------------------------------- */
5527
5528 /* must be called with lock held */
5529 static void
5530 handle_generic_ping_unlocked (GDBusConnection *connection,
5531                               const gchar     *object_path,
5532                               GDBusMessage    *message)
5533 {
5534   GDBusMessage *reply;
5535   reply = g_dbus_message_new_method_reply (message);
5536   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
5537   g_object_unref (reply);
5538 }
5539
5540 /* must be called with lock held */
5541 static void
5542 handle_generic_get_machine_id_unlocked (GDBusConnection *connection,
5543                                         const gchar     *object_path,
5544                                         GDBusMessage    *message)
5545 {
5546   GDBusMessage *reply;
5547
5548   reply = NULL;
5549   if (connection->machine_id == NULL)
5550     {
5551       GError *error;
5552
5553       error = NULL;
5554       connection->machine_id = _g_dbus_get_machine_id (&error);
5555       if (connection->machine_id == NULL)
5556         {
5557           reply = g_dbus_message_new_method_error_literal (message,
5558                                                            "org.freedesktop.DBus.Error.Failed",
5559                                                            error->message);
5560           g_error_free (error);
5561         }
5562     }
5563
5564   if (reply == NULL)
5565     {
5566       reply = g_dbus_message_new_method_reply (message);
5567       g_dbus_message_set_body (reply, g_variant_new ("(s)", connection->machine_id));
5568     }
5569   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
5570   g_object_unref (reply);
5571 }
5572
5573 /* must be called with lock held */
5574 static void
5575 handle_generic_introspect_unlocked (GDBusConnection *connection,
5576                                     const gchar     *object_path,
5577                                     GDBusMessage    *message)
5578 {
5579   guint n;
5580   GString *s;
5581   gchar **registered;
5582   GDBusMessage *reply;
5583
5584   /* first the header */
5585   s = g_string_new (NULL);
5586   introspect_append_header (s);
5587
5588   registered = g_dbus_connection_list_registered_unlocked (connection, object_path);
5589   for (n = 0; registered != NULL && registered[n] != NULL; n++)
5590       g_string_append_printf (s, "  <node name=\"%s\"/>\n", registered[n]);
5591   g_strfreev (registered);
5592   g_string_append (s, "</node>\n");
5593
5594   reply = g_dbus_message_new_method_reply (message);
5595   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
5596   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
5597   g_object_unref (reply);
5598   g_string_free (s, TRUE);
5599 }
5600
5601 /* must be called with lock held */
5602 static gboolean
5603 handle_generic_unlocked (GDBusConnection *connection,
5604                          GDBusMessage    *message)
5605 {
5606   gboolean handled;
5607   const gchar *interface_name;
5608   const gchar *member;
5609   const gchar *signature;
5610   const gchar *path;
5611
5612   CONNECTION_ENSURE_LOCK (connection);
5613
5614   handled = FALSE;
5615
5616   interface_name = g_dbus_message_get_interface (message);
5617   member = g_dbus_message_get_member (message);
5618   signature = g_dbus_message_get_signature (message);
5619   path = g_dbus_message_get_path (message);
5620
5621   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
5622       g_strcmp0 (member, "Introspect") == 0 &&
5623       g_strcmp0 (signature, "") == 0)
5624     {
5625       handle_generic_introspect_unlocked (connection, path, message);
5626       handled = TRUE;
5627     }
5628   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
5629            g_strcmp0 (member, "Ping") == 0 &&
5630            g_strcmp0 (signature, "") == 0)
5631     {
5632       handle_generic_ping_unlocked (connection, path, message);
5633       handled = TRUE;
5634     }
5635   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
5636            g_strcmp0 (member, "GetMachineId") == 0 &&
5637            g_strcmp0 (signature, "") == 0)
5638     {
5639       handle_generic_get_machine_id_unlocked (connection, path, message);
5640       handled = TRUE;
5641     }
5642
5643   return handled;
5644 }
5645
5646 /* ---------------------------------------------------------------------------------------------------- */
5647
5648 /* called in message handler thread with lock held */
5649 static void
5650 distribute_method_call (GDBusConnection *connection,
5651                         GDBusMessage    *message)
5652 {
5653   GDBusMessage *reply;
5654   ExportedObject *eo;
5655   ExportedSubtree *es;
5656   const gchar *object_path;
5657   const gchar *interface_name;
5658   const gchar *member;
5659   const gchar *signature;
5660   const gchar *path;
5661   gchar *subtree_path;
5662   gchar *needle;
5663
5664   g_assert (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL);
5665
5666   interface_name = g_dbus_message_get_interface (message);
5667   member = g_dbus_message_get_member (message);
5668   signature = g_dbus_message_get_signature (message);
5669   path = g_dbus_message_get_path (message);
5670   subtree_path = g_strdup (path);
5671   needle = strrchr (subtree_path, '/');
5672   if (needle != NULL && needle != subtree_path)
5673     {
5674       *needle = '\0';
5675     }
5676   else
5677     {
5678       g_free (subtree_path);
5679       subtree_path = NULL;
5680     }
5681
5682
5683   if (G_UNLIKELY (_g_dbus_debug_incoming ()))
5684     {
5685       _g_dbus_debug_print_lock ();
5686       g_print ("========================================================================\n"
5687                "GDBus-debug:Incoming:\n"
5688                " >>>> METHOD INVOCATION %s.%s()\n"
5689                "      on object %s\n"
5690                "      invoked by name %s\n",
5691                interface_name, member,
5692                path,
5693                g_dbus_message_get_sender (message) != NULL ? g_dbus_message_get_sender (message) : "(none)");
5694       _g_dbus_debug_print_unlock ();
5695     }
5696
5697 #if 0
5698   g_debug ("interface    = `%s'", interface_name);
5699   g_debug ("member       = `%s'", member);
5700   g_debug ("signature    = `%s'", signature);
5701   g_debug ("path         = `%s'", path);
5702   g_debug ("subtree_path = `%s'", subtree_path != NULL ? subtree_path : "N/A");
5703 #endif
5704
5705   object_path = g_dbus_message_get_path (message);
5706   g_assert (object_path != NULL);
5707
5708   eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path);
5709   if (eo != NULL)
5710     {
5711       if (obj_message_func (connection, eo, message))
5712         goto out;
5713     }
5714
5715   es = g_hash_table_lookup (connection->map_object_path_to_es, object_path);
5716   if (es != NULL)
5717     {
5718       if (subtree_message_func (connection, es, message))
5719         goto out;
5720     }
5721
5722   if (subtree_path != NULL)
5723     {
5724       es = g_hash_table_lookup (connection->map_object_path_to_es, subtree_path);
5725       if (es != NULL)
5726         {
5727           if (subtree_message_func (connection, es, message))
5728             goto out;
5729         }
5730     }
5731
5732   if (handle_generic_unlocked (connection, message))
5733     goto out;
5734
5735   /* if we end up here, the message has not been not handled - so return an error saying this */
5736   reply = g_dbus_message_new_method_error (message,
5737                                            "org.freedesktop.DBus.Error.UnknownMethod",
5738                                            _("No such interface `%s' on object at path %s"),
5739                                            interface_name,
5740                                            object_path);
5741   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
5742   g_object_unref (reply);
5743
5744  out:
5745   g_free (subtree_path);
5746 }
5747
5748 /* ---------------------------------------------------------------------------------------------------- */
5749
5750 static GDBusConnection **
5751 message_bus_get_singleton (GBusType   bus_type,
5752                            GError   **error)
5753 {
5754   GDBusConnection **ret;
5755   const gchar *starter_bus;
5756
5757   ret = NULL;
5758
5759   switch (bus_type)
5760     {
5761     case G_BUS_TYPE_SESSION:
5762       ret = &the_session_bus;
5763       break;
5764
5765     case G_BUS_TYPE_SYSTEM:
5766       ret = &the_system_bus;
5767       break;
5768
5769     case G_BUS_TYPE_STARTER:
5770       starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE");
5771       if (g_strcmp0 (starter_bus, "session") == 0)
5772         {
5773           ret = message_bus_get_singleton (G_BUS_TYPE_SESSION, error);
5774           goto out;
5775         }
5776       else if (g_strcmp0 (starter_bus, "system") == 0)
5777         {
5778           ret = message_bus_get_singleton (G_BUS_TYPE_SYSTEM, error);
5779           goto out;
5780         }
5781       else
5782         {
5783           if (starter_bus != NULL)
5784             {
5785               g_set_error (error,
5786                            G_IO_ERROR,
5787                            G_IO_ERROR_INVALID_ARGUMENT,
5788                            _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable"
5789                              " - unknown value `%s'"),
5790                            starter_bus);
5791             }
5792           else
5793             {
5794               g_set_error_literal (error,
5795                                    G_IO_ERROR,
5796                                    G_IO_ERROR_INVALID_ARGUMENT,
5797                                    _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment "
5798                                      "variable is not set"));
5799             }
5800         }
5801       break;
5802
5803     default:
5804       g_assert_not_reached ();
5805       break;
5806     }
5807
5808  out:
5809   return ret;
5810 }
5811
5812 static GDBusConnection *
5813 get_uninitialized_connection (GBusType       bus_type,
5814                               GCancellable  *cancellable,
5815                               GError       **error)
5816 {
5817   GDBusConnection **singleton;
5818   GDBusConnection *ret;
5819
5820   ret = NULL;
5821
5822   G_LOCK (message_bus_lock);
5823   singleton = message_bus_get_singleton (bus_type, error);
5824   if (singleton == NULL)
5825     goto out;
5826
5827   if (*singleton == NULL)
5828     {
5829       gchar *address;
5830       address = g_dbus_address_get_for_bus_sync (bus_type, cancellable, error);
5831       if (address == NULL)
5832         goto out;
5833       ret = *singleton = g_object_new (G_TYPE_DBUS_CONNECTION,
5834                                        "address", address,
5835                                        "flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
5836                                                 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
5837                                        "exit-on-close", TRUE,
5838                                        NULL);
5839       g_free (address);
5840     }
5841   else
5842     {
5843       ret = g_object_ref (*singleton);
5844     }
5845
5846   g_assert (ret != NULL);
5847
5848  out:
5849   G_UNLOCK (message_bus_lock);
5850   return ret;
5851 }
5852
5853 /**
5854  * g_bus_get_sync:
5855  * @bus_type: A #GBusType.
5856  * @cancellable: A #GCancellable or %NULL.
5857  * @error: Return location for error or %NULL.
5858  *
5859  * Synchronously connects to the message bus specified by @bus_type.
5860  * Note that the returned object may shared with other callers,
5861  * e.g. if two separate parts of a process calls this function with
5862  * the same @bus_type, they will share the same object.
5863  *
5864  * This is a synchronous failable function. See g_bus_get() and
5865  * g_bus_get_finish() for the asynchronous version.
5866  *
5867  * The returned object is a singleton, that is, shared with other
5868  * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
5869  * event that you need a private message bus connection, use
5870  * g_dbus_address_get_for_bus_sync() and
5871  * g_dbus_connection_new_for_address().
5872  *
5873  * Note that the returned #GDBusConnection object will (usually) have
5874  * the #GDBusConnection:exit-on-close property set to %TRUE.
5875  *
5876  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
5877  *
5878  * Since: 2.26
5879  */
5880 GDBusConnection *
5881 g_bus_get_sync (GBusType       bus_type,
5882                 GCancellable  *cancellable,
5883                 GError       **error)
5884 {
5885   GDBusConnection *connection;
5886
5887   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
5888
5889   connection = get_uninitialized_connection (bus_type, cancellable, error);
5890   if (connection == NULL)
5891     goto out;
5892
5893   if (!g_initable_init (G_INITABLE (connection), cancellable, error))
5894     {
5895       g_object_unref (connection);
5896       connection = NULL;
5897     }
5898
5899  out:
5900   return connection;
5901 }
5902
5903 static void
5904 bus_get_async_initable_cb (GObject      *source_object,
5905                            GAsyncResult *res,
5906                            gpointer      user_data)
5907 {
5908   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
5909   GError *error;
5910
5911   error = NULL;
5912   if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
5913                                      res,
5914                                      &error))
5915     {
5916       g_assert (error != NULL);
5917       g_simple_async_result_set_from_error (simple, error);
5918       g_error_free (error);
5919       g_object_unref (source_object);
5920     }
5921   else
5922     {
5923       g_simple_async_result_set_op_res_gpointer (simple,
5924                                                  source_object,
5925                                                  g_object_unref);
5926     }
5927   g_simple_async_result_complete_in_idle (simple);
5928   g_object_unref (simple);
5929 }
5930
5931 /**
5932  * g_bus_get:
5933  * @bus_type: A #GBusType.
5934  * @cancellable: A #GCancellable or %NULL.
5935  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
5936  * @user_data: The data to pass to @callback.
5937  *
5938  * Asynchronously connects to the message bus specified by @bus_type.
5939  *
5940  * When the operation is finished, @callback will be invoked. You can
5941  * then call g_bus_get_finish() to get the result of the operation.
5942  *
5943  * This is a asynchronous failable function. See g_bus_get_sync() for
5944  * the synchronous version.
5945  *
5946  * Since: 2.26
5947  */
5948 void
5949 g_bus_get (GBusType             bus_type,
5950            GCancellable        *cancellable,
5951            GAsyncReadyCallback  callback,
5952            gpointer             user_data)
5953 {
5954   GDBusConnection *connection;
5955   GSimpleAsyncResult *simple;
5956   GError *error;
5957
5958   simple = g_simple_async_result_new (NULL,
5959                                       callback,
5960                                       user_data,
5961                                       g_bus_get);
5962
5963   error = NULL;
5964   connection = get_uninitialized_connection (bus_type, cancellable, &error);
5965   if (connection == NULL)
5966     {
5967       g_assert (error != NULL);
5968       g_simple_async_result_set_from_error (simple, error);
5969       g_error_free (error);
5970       g_simple_async_result_complete_in_idle (simple);
5971       g_object_unref (simple);
5972     }
5973   else
5974     {
5975       g_async_initable_init_async (G_ASYNC_INITABLE (connection),
5976                                    G_PRIORITY_DEFAULT,
5977                                    cancellable,
5978                                    bus_get_async_initable_cb,
5979                                    simple);
5980     }
5981 }
5982
5983 /**
5984  * g_bus_get_finish:
5985  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_bus_get().
5986  * @error: Return location for error or %NULL.
5987  *
5988  * Finishes an operation started with g_bus_get().
5989  *
5990  * The returned object is a singleton, that is, shared with other
5991  * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
5992  * event that you need a private message bus connection, use
5993  * g_dbus_address_get_for_bus() and
5994  * g_dbus_connection_new_for_address().
5995  *
5996  * Note that the returned #GDBusConnection object will (usually) have
5997  * the #GDBusConnection:exit-on-close property set to %TRUE.
5998  *
5999  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
6000  *
6001  * Since: 2.26
6002  */
6003 GDBusConnection *
6004 g_bus_get_finish (GAsyncResult  *res,
6005                   GError       **error)
6006 {
6007   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
6008   GObject *object;
6009   GDBusConnection *ret;
6010
6011   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
6012
6013   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_bus_get);
6014
6015   ret = NULL;
6016
6017   if (g_simple_async_result_propagate_error (simple, error))
6018     goto out;
6019
6020   object = g_simple_async_result_get_op_res_gpointer (simple);
6021   g_assert (object != NULL);
6022   ret = g_object_ref (G_DBUS_CONNECTION (object));
6023
6024  out:
6025   return ret;
6026 }
6027
6028 /* ---------------------------------------------------------------------------------------------------- */
6029
6030 #define __G_DBUS_CONNECTION_C__
6031 #include "gioaliasdef.c"