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