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