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