Docs: Big entity cleanup
[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 <literal>raise(SIGTERM)</literal>) if the connection
964    * is closed by the remote peer.
965    *
966    * Note that #GDBusConnection objects returned by g_bus_get_finish() and
967    * 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 <link
1230  * linkend="g-main-context-push-thread-default">thread-default main
1231  * loop</link> 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 <link
1434  * linkend="g-main-context-push-thread-default">thread-default main
1435  * loop</link> 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 <link
1439  * linkend="g-main-context-push-thread-default">thread-default main
1440  * loop</link> 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 <xref linkend="gdbus-server"/> and <xref
1735  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1736  * low-level API to send and receive 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 will be invoked
2054  * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
2055  * of the thread you are calling this method from. You can then call
2056  * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
2057  * See g_dbus_connection_send_message_with_reply_sync() for the synchronous version.
2058  *
2059  * Note that @message must be unlocked, unless @flags contain the
2060  * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
2061  *
2062  * See <xref linkend="gdbus-server"/> and <xref
2063  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
2064  * low-level API to send and receive UNIX file descriptors.
2065  *
2066  * Since: 2.26
2067  */
2068 void
2069 g_dbus_connection_send_message_with_reply (GDBusConnection       *connection,
2070                                            GDBusMessage          *message,
2071                                            GDBusSendMessageFlags  flags,
2072                                            gint                   timeout_msec,
2073                                            volatile guint32      *out_serial,
2074                                            GCancellable          *cancellable,
2075                                            GAsyncReadyCallback    callback,
2076                                            gpointer               user_data)
2077 {
2078   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2079   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2080   g_return_if_fail ((flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL) || !g_dbus_message_get_locked (message));
2081   g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
2082
2083   CONNECTION_LOCK (connection);
2084   g_dbus_connection_send_message_with_reply_unlocked (connection,
2085                                                       message,
2086                                                       flags,
2087                                                       timeout_msec,
2088                                                       out_serial,
2089                                                       cancellable,
2090                                                       callback,
2091                                                       user_data);
2092   CONNECTION_UNLOCK (connection);
2093 }
2094
2095 /**
2096  * g_dbus_connection_send_message_with_reply_finish:
2097  * @connection: a #GDBusConnection
2098  * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to
2099  *     g_dbus_connection_send_message_with_reply()
2100  * @error: teturn location for error or %NULL
2101  *
2102  * Finishes an operation started with g_dbus_connection_send_message_with_reply().
2103  *
2104  * Note that @error is only set if a local in-process error
2105  * occurred. That is to say that the returned #GDBusMessage object may
2106  * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
2107  * g_dbus_message_to_gerror() to transcode this to a #GError.
2108  *
2109  * See <xref linkend="gdbus-server"/> and <xref
2110  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
2111  * low-level API to send and receive UNIX file descriptors.
2112  *
2113  * Returns: (transfer full): a locked #GDBusMessage or %NULL if @error is set
2114  *
2115  * Since: 2.26
2116  */
2117 GDBusMessage *
2118 g_dbus_connection_send_message_with_reply_finish (GDBusConnection  *connection,
2119                                                   GAsyncResult     *res,
2120                                                   GError          **error)
2121 {
2122   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
2123   GDBusMessage *reply;
2124
2125   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2126   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2127
2128   reply = NULL;
2129
2130   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_send_message_with_reply);
2131
2132   if (g_simple_async_result_propagate_error (simple, error))
2133     goto out;
2134
2135   reply = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
2136
2137  out:
2138   return reply;
2139 }
2140
2141 /* ---------------------------------------------------------------------------------------------------- */
2142
2143 typedef struct
2144 {
2145   GAsyncResult *res;
2146   GMainContext *context;
2147   GMainLoop *loop;
2148 } SendMessageSyncData;
2149
2150 /* Called from a user thread, lock is not held */
2151 static void
2152 send_message_with_reply_sync_cb (GDBusConnection *connection,
2153                                  GAsyncResult    *res,
2154                                  gpointer         user_data)
2155 {
2156   SendMessageSyncData *data = user_data;
2157   data->res = g_object_ref (res);
2158   g_main_loop_quit (data->loop);
2159 }
2160
2161 /**
2162  * g_dbus_connection_send_message_with_reply_sync:
2163  * @connection: a #GDBusConnection
2164  * @message: a #GDBusMessage
2165  * @flags: flags affecting how the message is sent.
2166  * @timeout_msec: the timeout in milliseconds, -1 to use the default
2167  *     timeout or %G_MAXINT for no timeout
2168  * @out_serial: (out) (allow-none): return location for serial number
2169  *     assigned to @message when sending it or %NULL
2170  * @cancellable: (allow-none): a #GCancellable or %NULL
2171  * @error: return location for error or %NULL
2172  *
2173  * Synchronously sends @message to the peer represented by @connection
2174  * and blocks the calling thread until a reply is received or the
2175  * timeout is reached. See g_dbus_connection_send_message_with_reply()
2176  * for the asynchronous version of this method.
2177  *
2178  * Unless @flags contain the
2179  * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
2180  * will be assigned by @connection and set on @message via
2181  * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
2182  * serial number used will be written to this location prior to
2183  * submitting the message to the underlying transport.
2184  *
2185  * If @connection is closed then the operation will fail with
2186  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
2187  * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
2188  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
2189  *
2190  * Note that @error is only set if a local in-process error
2191  * occurred. That is to say that the returned #GDBusMessage object may
2192  * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
2193  * g_dbus_message_to_gerror() to transcode this to a #GError.
2194  *
2195  * See <xref linkend="gdbus-server"/> and <xref
2196  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
2197  * low-level API to send and receive UNIX file descriptors.
2198  *
2199  * Note that @message must be unlocked, unless @flags contain the
2200  * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
2201  *
2202  * Returns: (transfer full): a locked #GDBusMessage that is the reply
2203  *     to @message or %NULL if @error is set
2204  *
2205  * Since: 2.26
2206  */
2207 GDBusMessage *
2208 g_dbus_connection_send_message_with_reply_sync (GDBusConnection        *connection,
2209                                                 GDBusMessage           *message,
2210                                                 GDBusSendMessageFlags   flags,
2211                                                 gint                    timeout_msec,
2212                                                 volatile guint32       *out_serial,
2213                                                 GCancellable           *cancellable,
2214                                                 GError                **error)
2215 {
2216   SendMessageSyncData *data;
2217   GDBusMessage *reply;
2218
2219   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2220   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2221   g_return_val_if_fail ((flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL) || !g_dbus_message_get_locked (message), NULL);
2222   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
2223   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2224
2225   data = g_new0 (SendMessageSyncData, 1);
2226   data->context = g_main_context_new ();
2227   data->loop = g_main_loop_new (data->context, FALSE);
2228
2229   g_main_context_push_thread_default (data->context);
2230
2231   g_dbus_connection_send_message_with_reply (connection,
2232                                              message,
2233                                              flags,
2234                                              timeout_msec,
2235                                              out_serial,
2236                                              cancellable,
2237                                              (GAsyncReadyCallback) send_message_with_reply_sync_cb,
2238                                              data);
2239   g_main_loop_run (data->loop);
2240   reply = g_dbus_connection_send_message_with_reply_finish (connection,
2241                                                             data->res,
2242                                                             error);
2243
2244   g_main_context_pop_thread_default (data->context);
2245
2246   g_main_context_unref (data->context);
2247   g_main_loop_unref (data->loop);
2248   g_object_unref (data->res);
2249   g_free (data);
2250
2251   return reply;
2252 }
2253
2254 /* ---------------------------------------------------------------------------------------------------- */
2255
2256 typedef struct
2257 {
2258   GDBusMessageFilterFunction func;
2259   gpointer user_data;
2260 } FilterCallback;
2261
2262 typedef struct
2263 {
2264   guint                       id;
2265   GDBusMessageFilterFunction  filter_function;
2266   gpointer                    user_data;
2267   GDestroyNotify              user_data_free_func;
2268 } FilterData;
2269
2270 /* Called in GDBusWorker's thread - we must not block - with no lock held */
2271 static void
2272 on_worker_message_received (GDBusWorker  *worker,
2273                             GDBusMessage *message,
2274                             gpointer      user_data)
2275 {
2276   GDBusConnection *connection;
2277   FilterCallback *filters;
2278   guint num_filters;
2279   guint n;
2280   gboolean alive;
2281
2282   G_LOCK (message_bus_lock);
2283   alive = (g_hash_table_lookup (alive_connections, user_data) != NULL);
2284   if (!alive)
2285     {
2286       G_UNLOCK (message_bus_lock);
2287       return;
2288     }
2289   connection = G_DBUS_CONNECTION (user_data);
2290   g_object_ref (connection);
2291   G_UNLOCK (message_bus_lock);
2292
2293   //g_debug ("in on_worker_message_received");
2294
2295   g_object_ref (message);
2296   g_dbus_message_lock (message);
2297
2298   //g_debug ("boo ref_count = %d %p %p", G_OBJECT (connection)->ref_count, connection, connection->worker);
2299
2300   /* First collect the set of callback functions */
2301   CONNECTION_LOCK (connection);
2302   num_filters = connection->filters->len;
2303   filters = g_new0 (FilterCallback, num_filters);
2304   for (n = 0; n < num_filters; n++)
2305     {
2306       FilterData *data = connection->filters->pdata[n];
2307       filters[n].func = data->filter_function;
2308       filters[n].user_data = data->user_data;
2309     }
2310   CONNECTION_UNLOCK (connection);
2311
2312   /* then call the filters in order (without holding the lock) */
2313   for (n = 0; n < num_filters; n++)
2314     {
2315       message = filters[n].func (connection,
2316                                  message,
2317                                  TRUE,
2318                                  filters[n].user_data);
2319       if (message == NULL)
2320         break;
2321       g_dbus_message_lock (message);
2322     }
2323
2324   /* Standard dispatch unless the filter ate the message - no need to
2325    * do anything if the message was altered
2326    */
2327   if (message != NULL)
2328     {
2329       GDBusMessageType message_type;
2330
2331       message_type = g_dbus_message_get_message_type (message);
2332       if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN || message_type == G_DBUS_MESSAGE_TYPE_ERROR)
2333         {
2334           guint32 reply_serial;
2335           SendMessageData *send_message_data;
2336
2337           reply_serial = g_dbus_message_get_reply_serial (message);
2338           CONNECTION_LOCK (connection);
2339           send_message_data = g_hash_table_lookup (connection->map_method_serial_to_send_message_data,
2340                                                    GUINT_TO_POINTER (reply_serial));
2341           if (send_message_data != NULL)
2342             {
2343               //g_debug ("delivering reply/error for serial %d for %p", reply_serial, connection);
2344               send_message_data_deliver_reply_unlocked (send_message_data, message);
2345             }
2346           else
2347             {
2348               //g_debug ("message reply/error for serial %d but no SendMessageData found for %p", reply_serial, connection);
2349             }
2350           CONNECTION_UNLOCK (connection);
2351         }
2352       else if (message_type == G_DBUS_MESSAGE_TYPE_SIGNAL)
2353         {
2354           CONNECTION_LOCK (connection);
2355           distribute_signals (connection, message);
2356           CONNECTION_UNLOCK (connection);
2357         }
2358       else if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
2359         {
2360           CONNECTION_LOCK (connection);
2361           distribute_method_call (connection, message);
2362           CONNECTION_UNLOCK (connection);
2363         }
2364     }
2365
2366   if (message != NULL)
2367     g_object_unref (message);
2368   g_object_unref (connection);
2369   g_free (filters);
2370 }
2371
2372 /* Called in GDBusWorker's thread, lock is not held */
2373 static GDBusMessage *
2374 on_worker_message_about_to_be_sent (GDBusWorker  *worker,
2375                                     GDBusMessage *message,
2376                                     gpointer      user_data)
2377 {
2378   GDBusConnection *connection;
2379   FilterCallback *filters;
2380   guint num_filters;
2381   guint n;
2382   gboolean alive;
2383
2384   G_LOCK (message_bus_lock);
2385   alive = (g_hash_table_lookup (alive_connections, user_data) != NULL);
2386   if (!alive)
2387     {
2388       G_UNLOCK (message_bus_lock);
2389       return message;
2390     }
2391   connection = G_DBUS_CONNECTION (user_data);
2392   g_object_ref (connection);
2393   G_UNLOCK (message_bus_lock);
2394
2395   //g_debug ("in on_worker_message_about_to_be_sent");
2396
2397   /* First collect the set of callback functions */
2398   CONNECTION_LOCK (connection);
2399   num_filters = connection->filters->len;
2400   filters = g_new0 (FilterCallback, num_filters);
2401   for (n = 0; n < num_filters; n++)
2402     {
2403       FilterData *data = connection->filters->pdata[n];
2404       filters[n].func = data->filter_function;
2405       filters[n].user_data = data->user_data;
2406     }
2407   CONNECTION_UNLOCK (connection);
2408
2409   /* then call the filters in order (without holding the lock) */
2410   for (n = 0; n < num_filters; n++)
2411     {
2412       g_dbus_message_lock (message);
2413       message = filters[n].func (connection,
2414                                  message,
2415                                  FALSE,
2416                                  filters[n].user_data);
2417       if (message == NULL)
2418         break;
2419     }
2420
2421   g_object_unref (connection);
2422   g_free (filters);
2423
2424   return message;
2425 }
2426
2427 /* called with connection lock held, in GDBusWorker thread */
2428 static gboolean
2429 cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
2430 {
2431   SendMessageData *data = value;
2432
2433   if (data->delivered)
2434     return FALSE;
2435
2436   g_simple_async_result_set_error (data->simple,
2437                                    G_IO_ERROR,
2438                                    G_IO_ERROR_CLOSED,
2439                                    _("The connection is closed"));
2440
2441   /* Ask send_message_with_reply_deliver not to remove the element from the
2442    * hash table - we're in the middle of a foreach; that would be unsafe.
2443    * Instead, return TRUE from this function so that it gets removed safely.
2444    */
2445   send_message_with_reply_deliver (data, FALSE);
2446   return TRUE;
2447 }
2448
2449 /* Called in GDBusWorker's thread - we must not block - without lock held */
2450 static void
2451 on_worker_closed (GDBusWorker *worker,
2452                   gboolean     remote_peer_vanished,
2453                   GError      *error,
2454                   gpointer     user_data)
2455 {
2456   GDBusConnection *connection;
2457   gboolean alive;
2458   guint old_atomic_flags;
2459
2460   G_LOCK (message_bus_lock);
2461   alive = (g_hash_table_lookup (alive_connections, user_data) != NULL);
2462   if (!alive)
2463     {
2464       G_UNLOCK (message_bus_lock);
2465       return;
2466     }
2467   connection = G_DBUS_CONNECTION (user_data);
2468   g_object_ref (connection);
2469   G_UNLOCK (message_bus_lock);
2470
2471   //g_debug ("in on_worker_closed: %s", error->message);
2472
2473   CONNECTION_LOCK (connection);
2474   /* Even though this is atomic, we do it inside the lock to avoid breaking
2475    * assumptions in remove_match_rule(). We'd need the lock in a moment
2476    * anyway, so, no loss.
2477    */
2478   old_atomic_flags = g_atomic_int_or (&connection->atomic_flags, FLAG_CLOSED);
2479
2480   if (!(old_atomic_flags & FLAG_CLOSED))
2481     {
2482       g_hash_table_foreach_remove (connection->map_method_serial_to_send_message_data, cancel_method_on_close, NULL);
2483       schedule_closed_unlocked (connection, remote_peer_vanished, error);
2484     }
2485   CONNECTION_UNLOCK (connection);
2486
2487   g_object_unref (connection);
2488 }
2489
2490 /* ---------------------------------------------------------------------------------------------------- */
2491
2492 /* Determines the biggest set of capabilities we can support on this
2493  * connection.
2494  *
2495  * Called with the init_lock held.
2496  */
2497 static GDBusCapabilityFlags
2498 get_offered_capabilities_max (GDBusConnection *connection)
2499 {
2500       GDBusCapabilityFlags ret;
2501       ret = G_DBUS_CAPABILITY_FLAGS_NONE;
2502 #ifdef G_OS_UNIX
2503       if (G_IS_UNIX_CONNECTION (connection->stream))
2504         ret |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
2505 #endif
2506       return ret;
2507 }
2508
2509 /* Called in a user thread, lock is not held */
2510 static gboolean
2511 initable_init (GInitable     *initable,
2512                GCancellable  *cancellable,
2513                GError       **error)
2514 {
2515   GDBusConnection *connection = G_DBUS_CONNECTION (initable);
2516   gboolean ret;
2517
2518   /* This method needs to be idempotent to work with the singleton
2519    * pattern. See the docs for g_initable_init(). We implement this by
2520    * locking.
2521    *
2522    * Unfortunately we can't use the main lock since the on_worker_*()
2523    * callbacks above needs the lock during initialization (for message
2524    * bus connections we do a synchronous Hello() call on the bus).
2525    */
2526   g_mutex_lock (&connection->init_lock);
2527
2528   ret = FALSE;
2529
2530   /* Make this a no-op if we're already initialized (successfully or
2531    * unsuccessfully)
2532    */
2533   if ((g_atomic_int_get (&connection->atomic_flags) & FLAG_INITIALIZED))
2534     {
2535       ret = (connection->initialization_error == NULL);
2536       goto out;
2537     }
2538
2539   /* Because of init_lock, we can't get here twice in different threads */
2540   g_assert (connection->initialization_error == NULL);
2541
2542   /* The user can pass multiple (but mutally exclusive) construct
2543    * properties:
2544    *
2545    *  - stream (of type GIOStream)
2546    *  - address (of type gchar*)
2547    *
2548    * At the end of the day we end up with a non-NULL GIOStream
2549    * object in connection->stream.
2550    */
2551   if (connection->address != NULL)
2552     {
2553       g_assert (connection->stream == NULL);
2554
2555       if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
2556           (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS))
2557         {
2558           g_set_error_literal (&connection->initialization_error,
2559                                G_IO_ERROR,
2560                                G_IO_ERROR_INVALID_ARGUMENT,
2561                                _("Unsupported flags encountered when constructing a client-side connection"));
2562           goto out;
2563         }
2564
2565       connection->stream = g_dbus_address_get_stream_sync (connection->address,
2566                                                            NULL, /* TODO: out_guid */
2567                                                            cancellable,
2568                                                            &connection->initialization_error);
2569       if (connection->stream == NULL)
2570         goto out;
2571     }
2572   else if (connection->stream != NULL)
2573     {
2574       /* nothing to do */
2575     }
2576   else
2577     {
2578       g_assert_not_reached ();
2579     }
2580
2581   /* Authenticate the connection */
2582   if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
2583     {
2584       g_assert (!(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT));
2585       g_assert (connection->guid != NULL);
2586       connection->auth = _g_dbus_auth_new (connection->stream);
2587       if (!_g_dbus_auth_run_server (connection->auth,
2588                                     connection->authentication_observer,
2589                                     connection->guid,
2590                                     (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS),
2591                                     get_offered_capabilities_max (connection),
2592                                     &connection->capabilities,
2593                                     &connection->credentials,
2594                                     cancellable,
2595                                     &connection->initialization_error))
2596         goto out;
2597     }
2598   else if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT)
2599     {
2600       g_assert (!(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER));
2601       g_assert (connection->guid == NULL);
2602       connection->auth = _g_dbus_auth_new (connection->stream);
2603       connection->guid = _g_dbus_auth_run_client (connection->auth,
2604                                                   connection->authentication_observer,
2605                                                   get_offered_capabilities_max (connection),
2606                                                   &connection->capabilities,
2607                                                   cancellable,
2608                                                   &connection->initialization_error);
2609       if (connection->guid == NULL)
2610         goto out;
2611     }
2612
2613   if (connection->authentication_observer != NULL)
2614     {
2615       g_object_unref (connection->authentication_observer);
2616       connection->authentication_observer = NULL;
2617     }
2618
2619   //g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
2620
2621   //g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
2622
2623 #ifdef G_OS_UNIX
2624   /* We want all IO operations to be non-blocking since they happen in
2625    * the worker thread which is shared by _all_ connections.
2626    */
2627   if (G_IS_SOCKET_CONNECTION (connection->stream))
2628     {
2629       g_socket_set_blocking (g_socket_connection_get_socket (G_SOCKET_CONNECTION (connection->stream)), FALSE);
2630     }
2631 #endif
2632
2633   G_LOCK (message_bus_lock);
2634   if (alive_connections == NULL)
2635     alive_connections = g_hash_table_new (g_direct_hash, g_direct_equal);
2636   g_hash_table_insert (alive_connections, connection, connection);
2637   G_UNLOCK (message_bus_lock);
2638
2639   connection->worker = _g_dbus_worker_new (connection->stream,
2640                                            connection->capabilities,
2641                                            ((connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) != 0),
2642                                            on_worker_message_received,
2643                                            on_worker_message_about_to_be_sent,
2644                                            on_worker_closed,
2645                                            connection);
2646
2647   /* if a bus connection, call org.freedesktop.DBus.Hello - this is how we're getting a name */
2648   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2649     {
2650       GVariant *hello_result;
2651
2652       /* we could lift this restriction by adding code in gdbusprivate.c */
2653       if (connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING)
2654         {
2655           g_set_error_literal (&connection->initialization_error,
2656                                G_IO_ERROR,
2657                                G_IO_ERROR_FAILED,
2658                                "Cannot use DELAY_MESSAGE_PROCESSING with MESSAGE_BUS_CONNECTION");
2659           goto out;
2660         }
2661
2662       hello_result = g_dbus_connection_call_sync (connection,
2663                                                   "org.freedesktop.DBus", /* name */
2664                                                   "/org/freedesktop/DBus", /* path */
2665                                                   "org.freedesktop.DBus", /* interface */
2666                                                   "Hello",
2667                                                   NULL, /* parameters */
2668                                                   G_VARIANT_TYPE ("(s)"),
2669                                                   CALL_FLAGS_INITIALIZING,
2670                                                   -1,
2671                                                   NULL, /* TODO: cancellable */
2672                                                   &connection->initialization_error);
2673       if (hello_result == NULL)
2674         goto out;
2675
2676       g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
2677       g_variant_unref (hello_result);
2678       //g_debug ("unique name is '%s'", connection->bus_unique_name);
2679     }
2680
2681   ret = TRUE;
2682  out:
2683   if (!ret)
2684     {
2685       g_assert (connection->initialization_error != NULL);
2686       g_propagate_error (error, g_error_copy (connection->initialization_error));
2687     }
2688
2689   g_atomic_int_or (&connection->atomic_flags, FLAG_INITIALIZED);
2690   g_mutex_unlock (&connection->init_lock);
2691
2692   return ret;
2693 }
2694
2695 static void
2696 initable_iface_init (GInitableIface *initable_iface)
2697 {
2698   initable_iface->init = initable_init;
2699 }
2700
2701 /* ---------------------------------------------------------------------------------------------------- */
2702
2703 static void
2704 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
2705 {
2706   /* Use default */
2707 }
2708
2709 /* ---------------------------------------------------------------------------------------------------- */
2710
2711 /**
2712  * g_dbus_connection_new:
2713  * @stream: a #GIOStream
2714  * @guid: (allow-none): the GUID to use if a authenticating as a server or %NULL
2715  * @flags: flags describing how to make the connection
2716  * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2717  * @cancellable: (allow-none): a #GCancellable or %NULL
2718  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2719  * @user_data: the data to pass to @callback
2720  *
2721  * Asynchronously sets up a D-Bus connection for exchanging D-Bus messages
2722  * with the end represented by @stream.
2723  *
2724  * If @stream is a #GSocketConnection, then the corresponding #GSocket
2725  * will be put into non-blocking mode.
2726  *
2727  * The D-Bus connection will interact with @stream from a worker thread.
2728  * As a result, the caller should not interact with @stream after this
2729  * method has been called, except by calling g_object_unref() on it.
2730  *
2731  * If @observer is not %NULL it may be used to control the
2732  * authentication process.
2733  *
2734  * When the operation is finished, @callback will be invoked. You can
2735  * then call g_dbus_connection_new_finish() to get the result of the
2736  * operation.
2737  *
2738  * This is a asynchronous failable constructor. See
2739  * g_dbus_connection_new_sync() for the synchronous
2740  * version.
2741  *
2742  * Since: 2.26
2743  */
2744 void
2745 g_dbus_connection_new (GIOStream            *stream,
2746                        const gchar          *guid,
2747                        GDBusConnectionFlags  flags,
2748                        GDBusAuthObserver    *observer,
2749                        GCancellable         *cancellable,
2750                        GAsyncReadyCallback   callback,
2751                        gpointer              user_data)
2752 {
2753   g_return_if_fail (G_IS_IO_STREAM (stream));
2754   g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2755                               G_PRIORITY_DEFAULT,
2756                               cancellable,
2757                               callback,
2758                               user_data,
2759                               "stream", stream,
2760                               "guid", guid,
2761                               "flags", flags,
2762                               "authentication-observer", observer,
2763                               NULL);
2764 }
2765
2766 /**
2767  * g_dbus_connection_new_finish:
2768  * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback
2769  *     passed to g_dbus_connection_new().
2770  * @error: return location for error or %NULL
2771  *
2772  * Finishes an operation started with g_dbus_connection_new().
2773  *
2774  * Returns: a #GDBusConnection or %NULL if @error is set. Free
2775  *     with g_object_unref().
2776  *
2777  * Since: 2.26
2778  */
2779 GDBusConnection *
2780 g_dbus_connection_new_finish (GAsyncResult  *res,
2781                               GError       **error)
2782 {
2783   GObject *object;
2784   GObject *source_object;
2785
2786   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2787   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2788
2789   source_object = g_async_result_get_source_object (res);
2790   g_assert (source_object != NULL);
2791   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2792                                         res,
2793                                         error);
2794   g_object_unref (source_object);
2795   if (object != NULL)
2796     return G_DBUS_CONNECTION (object);
2797   else
2798     return NULL;
2799 }
2800
2801 /**
2802  * g_dbus_connection_new_sync:
2803  * @stream: a #GIOStream
2804  * @guid: (allow-none): the GUID to use if a authenticating as a server or %NULL
2805  * @flags: flags describing how to make the connection
2806  * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2807  * @cancellable: (allow-none): a #GCancellable or %NULL
2808  * @error: return location for error or %NULL
2809  *
2810  * Synchronously sets up a D-Bus connection for exchanging D-Bus messages
2811  * with the end represented by @stream.
2812  *
2813  * If @stream is a #GSocketConnection, then the corresponding #GSocket
2814  * will be put into non-blocking mode.
2815  *
2816  * The D-Bus connection will interact with @stream from a worker thread.
2817  * As a result, the caller should not interact with @stream after this
2818  * method has been called, except by calling g_object_unref() on it.
2819  *
2820  * If @observer is not %NULL it may be used to control the
2821  * authentication process.
2822  *
2823  * This is a synchronous failable constructor. See
2824  * g_dbus_connection_new() for the asynchronous version.
2825  *
2826  * Returns: a #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2827  *
2828  * Since: 2.26
2829  */
2830 GDBusConnection *
2831 g_dbus_connection_new_sync (GIOStream             *stream,
2832                             const gchar           *guid,
2833                             GDBusConnectionFlags   flags,
2834                             GDBusAuthObserver     *observer,
2835                             GCancellable          *cancellable,
2836                             GError               **error)
2837 {
2838   g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL);
2839   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2840   return g_initable_new (G_TYPE_DBUS_CONNECTION,
2841                          cancellable,
2842                          error,
2843                          "stream", stream,
2844                          "guid", guid,
2845                          "flags", flags,
2846                          "authentication-observer", observer,
2847                          NULL);
2848 }
2849
2850 /* ---------------------------------------------------------------------------------------------------- */
2851
2852 /**
2853  * g_dbus_connection_new_for_address:
2854  * @address: a D-Bus address
2855  * @flags: flags describing how to make the connection
2856  * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2857  * @cancellable: (allow-none): a #GCancellable or %NULL
2858  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2859  * @user_data: the data to pass to @callback
2860  *
2861  * Asynchronously connects and sets up a D-Bus client connection for
2862  * exchanging D-Bus messages with an endpoint specified by @address
2863  * which must be in the D-Bus address format.
2864  *
2865  * This constructor can only be used to initiate client-side
2866  * connections - use g_dbus_connection_new() if you need to act as the
2867  * server. In particular, @flags cannot contain the
2868  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2869  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2870  *
2871  * When the operation is finished, @callback will be invoked. You can
2872  * then call g_dbus_connection_new_finish() to get the result of the
2873  * operation.
2874  *
2875  * If @observer is not %NULL it may be used to control the
2876  * authentication process.
2877  *
2878  * This is a asynchronous failable constructor. See
2879  * g_dbus_connection_new_for_address_sync() for the synchronous
2880  * version.
2881  *
2882  * Since: 2.26
2883  */
2884 void
2885 g_dbus_connection_new_for_address (const gchar          *address,
2886                                    GDBusConnectionFlags  flags,
2887                                    GDBusAuthObserver    *observer,
2888                                    GCancellable         *cancellable,
2889                                    GAsyncReadyCallback   callback,
2890                                    gpointer              user_data)
2891 {
2892   g_return_if_fail (address != NULL);
2893   g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2894                               G_PRIORITY_DEFAULT,
2895                               cancellable,
2896                               callback,
2897                               user_data,
2898                               "address", address,
2899                               "flags", flags,
2900                               "authentication-observer", observer,
2901                               NULL);
2902 }
2903
2904 /**
2905  * g_dbus_connection_new_for_address_finish:
2906  * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
2907  *     to g_dbus_connection_new()
2908  * @error: return location for error or %NULL
2909  *
2910  * Finishes an operation started with g_dbus_connection_new_for_address().
2911  *
2912  * Returns: a #GDBusConnection or %NULL if @error is set. Free with
2913  *     g_object_unref().
2914  *
2915  * Since: 2.26
2916  */
2917 GDBusConnection *
2918 g_dbus_connection_new_for_address_finish (GAsyncResult  *res,
2919                                           GError       **error)
2920 {
2921   GObject *object;
2922   GObject *source_object;
2923
2924   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2925   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2926
2927   source_object = g_async_result_get_source_object (res);
2928   g_assert (source_object != NULL);
2929   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2930                                         res,
2931                                         error);
2932   g_object_unref (source_object);
2933   if (object != NULL)
2934     return G_DBUS_CONNECTION (object);
2935   else
2936     return NULL;
2937 }
2938
2939 /**
2940  * g_dbus_connection_new_for_address_sync:
2941  * @address: a D-Bus address
2942  * @flags: flags describing how to make the connection
2943  * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2944  * @cancellable: (allow-none): a #GCancellable or %NULL
2945  * @error: return location for error or %NULL
2946  *
2947  * Synchronously connects and sets up a D-Bus client connection for
2948  * exchanging D-Bus messages with an endpoint specified by @address
2949  * which must be in the D-Bus address format.
2950  *
2951  * This constructor can only be used to initiate client-side
2952  * connections - use g_dbus_connection_new_sync() if you need to act
2953  * as the server. In particular, @flags cannot contain the
2954  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2955  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2956  *
2957  * This is a synchronous failable constructor. See
2958  * g_dbus_connection_new_for_address() for the asynchronous version.
2959  *
2960  * If @observer is not %NULL it may be used to control the
2961  * authentication process.
2962  *
2963  * Returns: a #GDBusConnection or %NULL if @error is set. Free with
2964  *     g_object_unref().
2965  *
2966  * Since: 2.26
2967  */
2968 GDBusConnection *
2969 g_dbus_connection_new_for_address_sync (const gchar           *address,
2970                                         GDBusConnectionFlags   flags,
2971                                         GDBusAuthObserver     *observer,
2972                                         GCancellable          *cancellable,
2973                                         GError               **error)
2974 {
2975   g_return_val_if_fail (address != NULL, NULL);
2976   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2977   return g_initable_new (G_TYPE_DBUS_CONNECTION,
2978                          cancellable,
2979                          error,
2980                          "address", address,
2981                          "flags", flags,
2982                          "authentication-observer", observer,
2983                          NULL);
2984 }
2985
2986 /* ---------------------------------------------------------------------------------------------------- */
2987
2988 /**
2989  * g_dbus_connection_set_exit_on_close:
2990  * @connection: a #GDBusConnection
2991  * @exit_on_close: whether the process should be terminated
2992  *     when @connection is closed by the remote peer
2993  *
2994  * Sets whether the process should be terminated when @connection is
2995  * closed by the remote peer. See #GDBusConnection:exit-on-close for
2996  * more details.
2997  *
2998  * Note that this function should be used with care. Most modern UNIX
2999  * desktops tie the notion of a user session the session bus, and expect
3000  * all of a users applications to quit when their bus connection goes away.
3001  * If you are setting @exit_on_close to %FALSE for the shared session
3002  * bus connection, you should make sure that your application exits
3003  * when the user session ends.
3004  *
3005  * Since: 2.26
3006  */
3007 void
3008 g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
3009                                      gboolean         exit_on_close)
3010 {
3011   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
3012
3013   if (exit_on_close)
3014     g_atomic_int_or (&connection->atomic_flags, FLAG_EXIT_ON_CLOSE);
3015   else
3016     g_atomic_int_and (&connection->atomic_flags, ~FLAG_EXIT_ON_CLOSE);
3017
3018 }
3019
3020 /**
3021  * g_dbus_connection_get_exit_on_close:
3022  * @connection: a #GDBusConnection
3023  *
3024  * Gets whether the process is terminated when @connection is
3025  * closed by the remote peer. See
3026  * #GDBusConnection:exit-on-close for more details.
3027  *
3028  * Returns: whether the process is terminated when @connection is
3029  *     closed by the remote peer
3030  *
3031  * Since: 2.26
3032  */
3033 gboolean
3034 g_dbus_connection_get_exit_on_close (GDBusConnection *connection)
3035 {
3036   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
3037
3038   if (g_atomic_int_get (&connection->atomic_flags) & FLAG_EXIT_ON_CLOSE)
3039     return TRUE;
3040   else
3041     return FALSE;
3042 }
3043
3044 /**
3045  * g_dbus_connection_get_guid:
3046  * @connection: a #GDBusConnection
3047  *
3048  * The GUID of the peer performing the role of server when
3049  * authenticating. See #GDBusConnection:guid for more details.
3050  *
3051  * Returns: The GUID. Do not free this string, it is owned by
3052  *     @connection.
3053  *
3054  * Since: 2.26
3055  */
3056 const gchar *
3057 g_dbus_connection_get_guid (GDBusConnection *connection)
3058 {
3059   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
3060   return connection->guid;
3061 }
3062
3063 /**
3064  * g_dbus_connection_get_unique_name:
3065  * @connection: a #GDBusConnection
3066  *
3067  * Gets the unique name of @connection as assigned by the message
3068  * bus. This can also be used to figure out if @connection is a
3069  * message bus connection.
3070  *
3071  * Returns: the unique name or %NULL if @connection is not a message
3072  *     bus connection. Do not free this string, it is owned by
3073  *     @connection.
3074  *
3075  * Since: 2.26
3076  */
3077 const gchar *
3078 g_dbus_connection_get_unique_name (GDBusConnection *connection)
3079 {
3080   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
3081
3082   /* do not use g_return_val_if_fail(), we want the memory barrier */
3083   if (!check_initialized (connection))
3084     return NULL;
3085
3086   return connection->bus_unique_name;
3087 }
3088
3089 /**
3090  * g_dbus_connection_get_peer_credentials:
3091  * @connection: a #GDBusConnection
3092  *
3093  * Gets the credentials of the authenticated peer. This will always
3094  * return %NULL unless @connection acted as a server
3095  * (e.g. %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER was passed)
3096  * when set up and the client passed credentials as part of the
3097  * authentication process.
3098  *
3099  * In a message bus setup, the message bus is always the server and
3100  * each application is a client. So this method will always return
3101  * %NULL for message bus clients.
3102  *
3103  * Returns: (transfer none): a #GCredentials or %NULL if not available.
3104  *     Do not free this object, it is owned by @connection.
3105  *
3106  * Since: 2.26
3107  */
3108 GCredentials *
3109 g_dbus_connection_get_peer_credentials (GDBusConnection *connection)
3110 {
3111   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
3112
3113   /* do not use g_return_val_if_fail(), we want the memory barrier */
3114   if (!check_initialized (connection))
3115     return NULL;
3116
3117   return connection->credentials;
3118 }
3119
3120 /* ---------------------------------------------------------------------------------------------------- */
3121
3122 static guint _global_filter_id = 1;
3123
3124 /**
3125  * g_dbus_connection_add_filter:
3126  * @connection: a #GDBusConnection
3127  * @filter_function: a filter function
3128  * @user_data: user data to pass to @filter_function
3129  * @user_data_free_func: function to free @user_data with when filter
3130  *     is removed or %NULL
3131  *
3132  * Adds a message filter. Filters are handlers that are run on all
3133  * incoming and outgoing messages, prior to standard dispatch. Filters
3134  * are run in the order that they were added.  The same handler can be
3135  * added as a filter more than once, in which case it will be run more
3136  * than once.  Filters added during a filter callback won't be run on
3137  * the message being processed. Filter functions are allowed to modify
3138  * and even drop messages.
3139  *
3140  * Note that filters are run in a dedicated message handling thread so
3141  * they can't block and, generally, can't do anything but signal a
3142  * worker thread. Also note that filters are rarely needed - use API
3143  * such as g_dbus_connection_send_message_with_reply(),
3144  * g_dbus_connection_signal_subscribe() or g_dbus_connection_call() instead.
3145  *
3146  * If a filter consumes an incoming message the message is not
3147  * dispatched anywhere else - not even the standard dispatch machinery
3148  * (that API such as g_dbus_connection_signal_subscribe() and
3149  * g_dbus_connection_send_message_with_reply() relies on) will see the
3150  * message. Similary, if a filter consumes an outgoing message, the
3151  * message will not be sent to the other peer.
3152  *
3153  * Returns: a filter identifier that can be used with
3154  *     g_dbus_connection_remove_filter()
3155  *
3156  * Since: 2.26
3157  */
3158 guint
3159 g_dbus_connection_add_filter (GDBusConnection            *connection,
3160                               GDBusMessageFilterFunction  filter_function,
3161                               gpointer                    user_data,
3162                               GDestroyNotify              user_data_free_func)
3163 {
3164   FilterData *data;
3165
3166   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
3167   g_return_val_if_fail (filter_function != NULL, 0);
3168   g_return_val_if_fail (check_initialized (connection), 0);
3169
3170   CONNECTION_LOCK (connection);
3171   data = g_new0 (FilterData, 1);
3172   data->id = _global_filter_id++; /* TODO: overflow etc. */
3173   data->filter_function = filter_function;
3174   data->user_data = user_data;
3175   data->user_data_free_func = user_data_free_func;
3176   g_ptr_array_add (connection->filters, data);
3177   CONNECTION_UNLOCK (connection);
3178
3179   return data->id;
3180 }
3181
3182 /* only called from finalize(), removes all filters */
3183 static void
3184 purge_all_filters (GDBusConnection *connection)
3185 {
3186   guint n;
3187   for (n = 0; n < connection->filters->len; n++)
3188     {
3189       FilterData *data = connection->filters->pdata[n];
3190       if (data->user_data_free_func != NULL)
3191         data->user_data_free_func (data->user_data);
3192       g_free (data);
3193     }
3194 }
3195
3196 /**
3197  * g_dbus_connection_remove_filter:
3198  * @connection: a #GDBusConnection
3199  * @filter_id: an identifier obtained from g_dbus_connection_add_filter()
3200  *
3201  * Removes a filter.
3202  *
3203  * Since: 2.26
3204  */
3205 void
3206 g_dbus_connection_remove_filter (GDBusConnection *connection,
3207                                  guint            filter_id)
3208 {
3209   guint n;
3210   FilterData *to_destroy;
3211
3212   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
3213   g_return_if_fail (check_initialized (connection));
3214
3215   CONNECTION_LOCK (connection);
3216   to_destroy = NULL;
3217   for (n = 0; n < connection->filters->len; n++)
3218     {
3219       FilterData *data = connection->filters->pdata[n];
3220       if (data->id == filter_id)
3221         {
3222           g_ptr_array_remove_index (connection->filters, n);
3223           to_destroy = data;
3224           break;
3225         }
3226     }
3227   CONNECTION_UNLOCK (connection);
3228
3229   /* do free without holding lock */
3230   if (to_destroy != NULL)
3231     {
3232       if (to_destroy->user_data_free_func != NULL)
3233         to_destroy->user_data_free_func (to_destroy->user_data);
3234       g_free (to_destroy);
3235     }
3236   else
3237     {
3238       g_warning ("g_dbus_connection_remove_filter: No filter found for filter_id %d", filter_id);
3239     }
3240 }
3241
3242 /* ---------------------------------------------------------------------------------------------------- */
3243
3244 typedef struct
3245 {
3246   gchar *rule;
3247   gchar *sender;
3248   gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */
3249   gchar *interface_name;
3250   gchar *member;
3251   gchar *object_path;
3252   gchar *arg0;
3253   GDBusSignalFlags flags;
3254   GArray *subscribers;
3255 } SignalData;
3256
3257 typedef struct
3258 {
3259   GDBusSignalCallback callback;
3260   gpointer user_data;
3261   GDestroyNotify user_data_free_func;
3262   guint id;
3263   GMainContext *context;
3264 } SignalSubscriber;
3265
3266 static void
3267 signal_data_free (SignalData *signal_data)
3268 {
3269   g_free (signal_data->rule);
3270   g_free (signal_data->sender);
3271   g_free (signal_data->sender_unique_name);
3272   g_free (signal_data->interface_name);
3273   g_free (signal_data->member);
3274   g_free (signal_data->object_path);
3275   g_free (signal_data->arg0);
3276   g_array_free (signal_data->subscribers, TRUE);
3277   g_free (signal_data);
3278 }
3279
3280 static gchar *
3281 args_to_rule (const gchar      *sender,
3282               const gchar      *interface_name,
3283               const gchar      *member,
3284               const gchar      *object_path,
3285               const gchar      *arg0,
3286               GDBusSignalFlags  flags)
3287 {
3288   GString *rule;
3289
3290   rule = g_string_new ("type='signal'");
3291   if (flags & G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE)
3292     g_string_prepend_c (rule, '-');
3293   if (sender != NULL)
3294     g_string_append_printf (rule, ",sender='%s'", sender);
3295   if (interface_name != NULL)
3296     g_string_append_printf (rule, ",interface='%s'", interface_name);
3297   if (member != NULL)
3298     g_string_append_printf (rule, ",member='%s'", member);
3299   if (object_path != NULL)
3300     g_string_append_printf (rule, ",path='%s'", object_path);
3301
3302   if (arg0 != NULL)
3303     {
3304       if (flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH)
3305         g_string_append_printf (rule, ",arg0path='%s'", arg0);
3306       else if (flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE)
3307         g_string_append_printf (rule, ",arg0namespace='%s'", arg0);
3308       else
3309         g_string_append_printf (rule, ",arg0='%s'", arg0);
3310     }
3311
3312   return g_string_free (rule, FALSE);
3313 }
3314
3315 static guint _global_subscriber_id = 1;
3316 static guint _global_registration_id = 1;
3317 static guint _global_subtree_registration_id = 1;
3318
3319 /* ---------------------------------------------------------------------------------------------------- */
3320
3321 /* Called in a user thread, lock is held */
3322 static void
3323 add_match_rule (GDBusConnection *connection,
3324                 const gchar     *match_rule)
3325 {
3326   GError *error;
3327   GDBusMessage *message;
3328
3329   if (match_rule[0] == '-')
3330     return;
3331
3332   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
3333                                             "/org/freedesktop/DBus", /* path */
3334                                             "org.freedesktop.DBus", /* interface */
3335                                             "AddMatch");
3336   g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
3337   error = NULL;
3338   if (!g_dbus_connection_send_message_unlocked (connection,
3339                                                 message,
3340                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
3341                                                 NULL,
3342                                                 &error))
3343     {
3344       g_critical ("Error while sending AddMatch() message: %s", error->message);
3345       g_error_free (error);
3346     }
3347   g_object_unref (message);
3348 }
3349
3350 /* ---------------------------------------------------------------------------------------------------- */
3351
3352 /* Called in a user thread, lock is held */
3353 static void
3354 remove_match_rule (GDBusConnection *connection,
3355                    const gchar     *match_rule)
3356 {
3357   GError *error;
3358   GDBusMessage *message;
3359
3360   if (match_rule[0] == '-')
3361     return;
3362
3363   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
3364                                             "/org/freedesktop/DBus", /* path */
3365                                             "org.freedesktop.DBus", /* interface */
3366                                             "RemoveMatch");
3367   g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
3368
3369   error = NULL;
3370   if (!g_dbus_connection_send_message_unlocked (connection,
3371                                                 message,
3372                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
3373                                                 NULL,
3374                                                 &error))
3375     {
3376       /* If we could get G_IO_ERROR_CLOSED here, it wouldn't be reasonable to
3377        * critical; but we're holding the lock, and our caller checked whether
3378        * we were already closed, so we can't get that error.
3379        */
3380       g_critical ("Error while sending RemoveMatch() message: %s", error->message);
3381       g_error_free (error);
3382     }
3383   g_object_unref (message);
3384 }
3385
3386 /* ---------------------------------------------------------------------------------------------------- */
3387
3388 static gboolean
3389 is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
3390 {
3391   return g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 &&
3392          g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
3393          g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
3394          (g_strcmp0 (signal_data->member, "NameLost") == 0 ||
3395           g_strcmp0 (signal_data->member, "NameAcquired") == 0);
3396 }
3397
3398 /* ---------------------------------------------------------------------------------------------------- */
3399
3400 /**
3401  * g_dbus_connection_signal_subscribe:
3402  * @connection: a #GDBusConnection
3403  * @sender: (allow-none): sender name to match on (unique or well-known name)
3404  *     or %NULL to listen from all senders
3405  * @interface_name: (allow-none): D-Bus interface name to match on or %NULL to
3406  *     match on all interfaces
3407  * @member: (allow-none): D-Bus signal name to match on or %NULL to match on
3408  *     all signals
3409  * @object_path: (allow-none): object path to match on or %NULL to match on
3410  *     all object paths
3411  * @arg0: (allow-none): contents of first string argument to match on or %NULL
3412  *     to match on all kinds of arguments
3413  * @flags: flags describing how to subscribe to the signal (currently unused)
3414  * @callback: callback to invoke when there is a signal matching the requested data
3415  * @user_data: user data to pass to @callback
3416  * @user_data_free_func: (allow-none): function to free @user_data with when
3417  *     subscription is removed or %NULL
3418  *
3419  * Subscribes to signals on @connection and invokes @callback with a
3420  * whenever the signal is received. Note that @callback will be invoked
3421  * in the <link
3422  * linkend="g-main-context-push-thread-default">thread-default main
3423  * loop</link> 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
5095  * happen in the <link linkend="g-main-context-push-thread-default">thread-default main
5096  * loop</link> of the thread you are calling this method from.
5097  *
5098  * Note that all #GVariant values passed to functions in @vtable will match
5099  * the signature given in @interface_info - if a remote caller passes
5100  * incorrect values, the <literal>org.freedesktop.DBus.Error.InvalidArgs</literal>
5101  * is returned to the remote caller.
5102  *
5103  * Additionally, if the remote caller attempts to invoke methods or
5104  * access properties not mentioned in @interface_info the
5105  * <literal>org.freedesktop.DBus.Error.UnknownMethod</literal> resp.
5106  * <literal>org.freedesktop.DBus.Error.InvalidArgs</literal> errors
5107  * are returned to the caller.
5108  *
5109  * It is considered a programming error if the
5110  * #GDBusInterfaceGetPropertyFunc function in @vtable returns a
5111  * #GVariant of incorrect type.
5112  *
5113  * If an existing callback is already registered at @object_path and
5114  * @interface_name, then @error is set to #G_IO_ERROR_EXISTS.
5115  *
5116  * GDBus automatically implements the standard D-Bus interfaces
5117  * org.freedesktop.DBus.Properties, org.freedesktop.DBus.Introspectable
5118  * and org.freedesktop.Peer, so you don't have to implement those for the
5119  * objects you export. You can implement org.freedesktop.DBus.Properties
5120  * yourself, e.g. to handle getting and setting of properties asynchronously.
5121  *
5122  * Note that the reference count on @interface_info will be
5123  * incremented by 1 (unless allocated statically, e.g. if the
5124  * reference count is -1, see g_dbus_interface_info_ref()) for as long
5125  * as the object is exported. Also note that @vtable will be copied.
5126  *
5127  * See <xref linkend="gdbus-server"/> for an example of how to use this method.
5128  *
5129  * Returns: 0 if @error is set, otherwise a registration id (never 0)
5130  *     that can be used with g_dbus_connection_unregister_object()
5131  *
5132  * Since: 2.26
5133  */
5134 guint
5135 g_dbus_connection_register_object (GDBusConnection             *connection,
5136                                    const gchar                 *object_path,
5137                                    GDBusInterfaceInfo          *interface_info,
5138                                    const GDBusInterfaceVTable  *vtable,
5139                                    gpointer                     user_data,
5140                                    GDestroyNotify               user_data_free_func,
5141                                    GError                     **error)
5142 {
5143   ExportedObject *eo;
5144   ExportedInterface *ei;
5145   guint ret;
5146
5147   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
5148   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
5149   g_return_val_if_fail (interface_info != NULL, 0);
5150   g_return_val_if_fail (g_dbus_is_interface_name (interface_info->name), 0);
5151   g_return_val_if_fail (error == NULL || *error == NULL, 0);
5152   g_return_val_if_fail (check_initialized (connection), 0);
5153
5154   ret = 0;
5155
5156   CONNECTION_LOCK (connection);
5157
5158   eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path);
5159   if (eo == NULL)
5160     {
5161       eo = g_new0 (ExportedObject, 1);
5162       eo->object_path = g_strdup (object_path);
5163       eo->connection = connection;
5164       eo->map_if_name_to_ei = g_hash_table_new_full (g_str_hash,
5165                                                      g_str_equal,
5166                                                      NULL,
5167                                                      (GDestroyNotify) exported_interface_free);
5168       g_hash_table_insert (connection->map_object_path_to_eo, eo->object_path, eo);
5169     }
5170
5171   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_info->name);
5172   if (ei != NULL)
5173     {
5174       g_set_error (error,
5175                    G_IO_ERROR,
5176                    G_IO_ERROR_EXISTS,
5177                    _("An object is already exported for the interface %s at %s"),
5178                    interface_info->name,
5179                    object_path);
5180       goto out;
5181     }
5182
5183   ei = g_new0 (ExportedInterface, 1);
5184   ei->id = _global_registration_id++; /* TODO: overflow etc. */
5185   ei->eo = eo;
5186   ei->user_data = user_data;
5187   ei->user_data_free_func = user_data_free_func;
5188   ei->vtable = _g_dbus_interface_vtable_copy (vtable);
5189   ei->interface_info = g_dbus_interface_info_ref (interface_info);
5190   g_dbus_interface_info_cache_build (ei->interface_info);
5191   ei->interface_name = g_strdup (interface_info->name);
5192   ei->context = g_main_context_ref_thread_default ();
5193
5194   g_hash_table_insert (eo->map_if_name_to_ei,
5195                        (gpointer) ei->interface_name,
5196                        ei);
5197   g_hash_table_insert (connection->map_id_to_ei,
5198                        GUINT_TO_POINTER (ei->id),
5199                        ei);
5200
5201   ret = ei->id;
5202
5203  out:
5204   CONNECTION_UNLOCK (connection);
5205
5206   return ret;
5207 }
5208
5209 /**
5210  * g_dbus_connection_unregister_object:
5211  * @connection: a #GDBusConnection
5212  * @registration_id: a registration id obtained from
5213  *     g_dbus_connection_register_object()
5214  *
5215  * Unregisters an object.
5216  *
5217  * Returns: %TRUE if the object was unregistered, %FALSE otherwise
5218  *
5219  * Since: 2.26
5220  */
5221 gboolean
5222 g_dbus_connection_unregister_object (GDBusConnection *connection,
5223                                      guint            registration_id)
5224 {
5225   ExportedInterface *ei;
5226   ExportedObject *eo;
5227   gboolean ret;
5228
5229   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
5230   g_return_val_if_fail (check_initialized (connection), FALSE);
5231
5232   ret = FALSE;
5233
5234   CONNECTION_LOCK (connection);
5235
5236   ei = g_hash_table_lookup (connection->map_id_to_ei,
5237                             GUINT_TO_POINTER (registration_id));
5238   if (ei == NULL)
5239     goto out;
5240
5241   eo = ei->eo;
5242
5243   g_warn_if_fail (g_hash_table_remove (connection->map_id_to_ei, GUINT_TO_POINTER (ei->id)));
5244   g_warn_if_fail (g_hash_table_remove (eo->map_if_name_to_ei, ei->interface_name));
5245   /* unregister object path if we have no more exported interfaces */
5246   if (g_hash_table_size (eo->map_if_name_to_ei) == 0)
5247     g_warn_if_fail (g_hash_table_remove (connection->map_object_path_to_eo,
5248                                          eo->object_path));
5249
5250   ret = TRUE;
5251
5252  out:
5253   CONNECTION_UNLOCK (connection);
5254
5255   return ret;
5256 }
5257
5258 /* ---------------------------------------------------------------------------------------------------- */
5259
5260 /**
5261  * g_dbus_connection_emit_signal:
5262  * @connection: a #GDBusConnection
5263  * @destination_bus_name: (allow-none): the unique bus name for the destination
5264  *     for the signal or %NULL to emit to all listeners
5265  * @object_path: path of remote object
5266  * @interface_name: D-Bus interface to emit a signal on
5267  * @signal_name: the name of the signal to emit
5268  * @parameters: (allow-none): a #GVariant tuple with parameters for the signal
5269  *              or %NULL if not passing parameters
5270  * @error: Return location for error or %NULL
5271  *
5272  * Emits a signal.
5273  *
5274  * If the parameters GVariant is floating, it is consumed.
5275  *
5276  * This can only fail if @parameters is not compatible with the D-Bus protocol.
5277  *
5278  * Returns: %TRUE unless @error is set
5279  *
5280  * Since: 2.26
5281  */
5282 gboolean
5283 g_dbus_connection_emit_signal (GDBusConnection  *connection,
5284                                const gchar      *destination_bus_name,
5285                                const gchar      *object_path,
5286                                const gchar      *interface_name,
5287                                const gchar      *signal_name,
5288                                GVariant         *parameters,
5289                                GError          **error)
5290 {
5291   GDBusMessage *message;
5292   gboolean ret;
5293
5294   message = NULL;
5295   ret = FALSE;
5296
5297   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
5298   g_return_val_if_fail (destination_bus_name == NULL || g_dbus_is_name (destination_bus_name), FALSE);
5299   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), FALSE);
5300   g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), FALSE);
5301   g_return_val_if_fail (signal_name != NULL && g_dbus_is_member_name (signal_name), FALSE);
5302   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), FALSE);
5303   g_return_val_if_fail (check_initialized (connection), FALSE);
5304
5305   if (G_UNLIKELY (_g_dbus_debug_emission ()))
5306     {
5307       _g_dbus_debug_print_lock ();
5308       g_print ("========================================================================\n"
5309                "GDBus-debug:Emission:\n"
5310                " >>>> SIGNAL EMISSION %s.%s()\n"
5311                "      on object %s\n"
5312                "      destination %s\n",
5313                interface_name, signal_name,
5314                object_path,
5315                destination_bus_name != NULL ? destination_bus_name : "(none)");
5316       _g_dbus_debug_print_unlock ();
5317     }
5318
5319   message = g_dbus_message_new_signal (object_path,
5320                                        interface_name,
5321                                        signal_name);
5322
5323   if (destination_bus_name != NULL)
5324     g_dbus_message_set_header (message,
5325                                G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION,
5326                                g_variant_new_string (destination_bus_name));
5327
5328   if (parameters != NULL)
5329     g_dbus_message_set_body (message, parameters);
5330
5331   ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, error);
5332   g_object_unref (message);
5333
5334   return ret;
5335 }
5336
5337 static void
5338 add_call_flags (GDBusMessage           *message,
5339                          GDBusCallFlags  flags)
5340 {
5341   if (flags & G_DBUS_CALL_FLAGS_NO_AUTO_START)
5342     g_dbus_message_set_flags (message, G_DBUS_MESSAGE_FLAGS_NO_AUTO_START);
5343 }
5344
5345 static GVariant *
5346 decode_method_reply (GDBusMessage        *reply,
5347                      const gchar         *method_name,
5348                      const GVariantType  *reply_type,
5349                      GUnixFDList        **out_fd_list,
5350                      GError             **error)
5351 {
5352   GVariant *result;
5353
5354   result = NULL;
5355   switch (g_dbus_message_get_message_type (reply))
5356     {
5357     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
5358       result = g_dbus_message_get_body (reply);
5359       if (result == NULL)
5360         {
5361           result = g_variant_new ("()");
5362           g_variant_ref_sink (result);
5363         }
5364       else
5365         {
5366           g_variant_ref (result);
5367         }
5368
5369       if (!g_variant_is_of_type (result, reply_type))
5370         {
5371           gchar *type_string = g_variant_type_dup_string (reply_type);
5372
5373           g_set_error (error,
5374                        G_IO_ERROR,
5375                        G_IO_ERROR_INVALID_ARGUMENT,
5376                        _("Method '%s' returned type '%s', but expected '%s'"),
5377                        method_name, g_variant_get_type_string (result), type_string);
5378
5379           g_variant_unref (result);
5380           g_free (type_string);
5381           result = NULL;
5382         }
5383
5384 #ifdef G_OS_UNIX
5385       if (result != NULL)
5386         {
5387           if (out_fd_list != NULL)
5388             {
5389               *out_fd_list = g_dbus_message_get_unix_fd_list (reply);
5390               if (*out_fd_list != NULL)
5391                 g_object_ref (*out_fd_list);
5392             }
5393         }
5394 #endif
5395       break;
5396
5397     case G_DBUS_MESSAGE_TYPE_ERROR:
5398       g_dbus_message_to_gerror (reply, error);
5399       break;
5400
5401     default:
5402       g_assert_not_reached ();
5403       break;
5404     }
5405
5406   return result;
5407 }
5408
5409
5410 typedef struct
5411 {
5412   GSimpleAsyncResult *simple;
5413   GVariantType *reply_type;
5414   gchar *method_name; /* for error message */
5415   guint32 serial;
5416
5417   GVariant *value;
5418   GUnixFDList *fd_list;
5419 } CallState;
5420
5421 static void
5422 call_state_free (CallState *state)
5423 {
5424   g_variant_type_free (state->reply_type);
5425   g_free (state->method_name);
5426
5427   if (state->value != NULL)
5428     g_variant_unref (state->value);
5429   if (state->fd_list != NULL)
5430     g_object_unref (state->fd_list);
5431   g_slice_free (CallState, state);
5432 }
5433
5434 /* called in any thread, with the connection's lock not held */
5435 static void
5436 g_dbus_connection_call_done (GObject      *source,
5437                              GAsyncResult *result,
5438                              gpointer      user_data)
5439 {
5440   GSimpleAsyncResult *simple;
5441   GDBusConnection *connection = G_DBUS_CONNECTION (source);
5442   CallState *state = user_data;
5443   GError *error;
5444   GDBusMessage *reply;
5445
5446   error = NULL;
5447   reply = g_dbus_connection_send_message_with_reply_finish (connection,
5448                                                             result,
5449                                                             &error);
5450
5451   if (G_UNLIKELY (_g_dbus_debug_call ()))
5452     {
5453       _g_dbus_debug_print_lock ();
5454       g_print ("========================================================================\n"
5455                "GDBus-debug:Call:\n"
5456                " <<<< ASYNC COMPLETE %s() (serial %d)\n"
5457                "      ",
5458                state->method_name,
5459                state->serial);
5460       if (reply != NULL)
5461         {
5462           g_print ("SUCCESS\n");
5463         }
5464       else
5465         {
5466           g_print ("FAILED: %s\n",
5467                    error->message);
5468         }
5469       _g_dbus_debug_print_unlock ();
5470     }
5471
5472   if (reply != NULL)
5473     state->value = decode_method_reply (reply, state->method_name, state->reply_type, &state->fd_list, &error);
5474
5475   simple = state->simple; /* why? because state is freed before we unref simple.. */
5476   if (error != NULL)
5477     {
5478       g_simple_async_result_take_error (state->simple, error);
5479       g_simple_async_result_complete (state->simple);
5480       call_state_free (state);
5481     }
5482   else
5483     {
5484       g_simple_async_result_set_op_res_gpointer (state->simple, state, (GDestroyNotify) call_state_free);
5485       g_simple_async_result_complete (state->simple);
5486     }
5487   g_clear_object (&reply);
5488   g_object_unref (simple);
5489 }
5490
5491 /* called in any thread, with the connection's lock not held */
5492 static void
5493 g_dbus_connection_call_internal (GDBusConnection        *connection,
5494                                  const gchar            *bus_name,
5495                                  const gchar            *object_path,
5496                                  const gchar            *interface_name,
5497                                  const gchar            *method_name,
5498                                  GVariant               *parameters,
5499                                  const GVariantType     *reply_type,
5500                                  GDBusCallFlags          flags,
5501                                  gint                    timeout_msec,
5502                                  GUnixFDList            *fd_list,
5503                                  GCancellable           *cancellable,
5504                                  GAsyncReadyCallback     callback,
5505                                  gpointer                user_data)
5506 {
5507   GDBusMessage *message;
5508   guint32 serial;
5509
5510   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
5511   g_return_if_fail (bus_name == NULL || g_dbus_is_name (bus_name));
5512   g_return_if_fail (object_path != NULL && g_variant_is_object_path (object_path));
5513   g_return_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name));
5514   g_return_if_fail (method_name != NULL && g_dbus_is_member_name (method_name));
5515   g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
5516   g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
5517   g_return_if_fail (check_initialized (connection));
5518 #ifdef G_OS_UNIX
5519   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
5520 #else
5521   g_return_if_fail (fd_list == NULL);
5522 #endif
5523
5524   message = g_dbus_message_new_method_call (bus_name,
5525                                             object_path,
5526                                             interface_name,
5527                                             method_name);
5528   add_call_flags (message, flags);
5529   if (parameters != NULL)
5530     g_dbus_message_set_body (message, parameters);
5531
5532 #ifdef G_OS_UNIX
5533   if (fd_list != NULL)
5534     g_dbus_message_set_unix_fd_list (message, fd_list);
5535 #endif
5536
5537   /* If the user has no callback then we can just send the message with
5538    * the G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set and skip all
5539    * the logic for processing the reply.  If the service sends the reply
5540    * anyway then it will just be ignored.
5541    */
5542   if (callback != NULL)
5543     {
5544       CallState *state;
5545
5546       state = g_slice_new0 (CallState);
5547       state->simple = g_simple_async_result_new (G_OBJECT (connection),
5548                                                  callback, user_data,
5549                                                  g_dbus_connection_call_internal);
5550       g_simple_async_result_set_check_cancellable (state->simple, cancellable);
5551       state->method_name = g_strjoin (".", interface_name, method_name, NULL);
5552
5553       if (reply_type == NULL)
5554         reply_type = G_VARIANT_TYPE_ANY;
5555
5556       state->reply_type = g_variant_type_copy (reply_type);
5557
5558       g_dbus_connection_send_message_with_reply (connection,
5559                                                  message,
5560                                                  G_DBUS_SEND_MESSAGE_FLAGS_NONE,
5561                                                  timeout_msec,
5562                                                  &state->serial,
5563                                                  cancellable,
5564                                                  g_dbus_connection_call_done,
5565                                                  state);
5566       serial = state->serial;
5567     }
5568   else
5569     {
5570       GDBusMessageFlags flags;
5571
5572       flags = g_dbus_message_get_flags (message);
5573       flags |= G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
5574       g_dbus_message_set_flags (message, flags);
5575
5576       g_dbus_connection_send_message (connection,
5577                                       message,
5578                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
5579                                       &serial, NULL);
5580     }
5581
5582   if (G_UNLIKELY (_g_dbus_debug_call ()))
5583     {
5584       _g_dbus_debug_print_lock ();
5585       g_print ("========================================================================\n"
5586                "GDBus-debug:Call:\n"
5587                " >>>> ASYNC %s.%s()\n"
5588                "      on object %s\n"
5589                "      owned by name %s (serial %d)\n",
5590                interface_name,
5591                method_name,
5592                object_path,
5593                bus_name != NULL ? bus_name : "(none)",
5594                serial);
5595       _g_dbus_debug_print_unlock ();
5596     }
5597
5598   if (message != NULL)
5599     g_object_unref (message);
5600 }
5601
5602 /* called in any thread, with the connection's lock not held */
5603 static GVariant *
5604 g_dbus_connection_call_finish_internal (GDBusConnection  *connection,
5605                                         GUnixFDList     **out_fd_list,
5606                                         GAsyncResult     *res,
5607                                         GError          **error)
5608 {
5609   GSimpleAsyncResult *simple;
5610   CallState *state;
5611
5612   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
5613   g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (connection),
5614                                                         g_dbus_connection_call_internal), NULL);
5615   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
5616
5617   simple = G_SIMPLE_ASYNC_RESULT (res);
5618
5619   if (g_simple_async_result_propagate_error (simple, error))
5620     return NULL;
5621
5622   state = g_simple_async_result_get_op_res_gpointer (simple);
5623   if (out_fd_list != NULL)
5624     *out_fd_list = state->fd_list != NULL ? g_object_ref (state->fd_list) : NULL;
5625   return g_variant_ref (state->value);
5626 }
5627
5628 /* called in any user thread, with the connection's lock not held */
5629 static GVariant *
5630 g_dbus_connection_call_sync_internal (GDBusConnection         *connection,
5631                                       const gchar             *bus_name,
5632                                       const gchar             *object_path,
5633                                       const gchar             *interface_name,
5634                                       const gchar             *method_name,
5635                                       GVariant                *parameters,
5636                                       const GVariantType      *reply_type,
5637                                       GDBusCallFlags           flags,
5638                                       gint                     timeout_msec,
5639                                       GUnixFDList             *fd_list,
5640                                       GUnixFDList            **out_fd_list,
5641                                       GCancellable            *cancellable,
5642                                       GError                 **error)
5643 {
5644   GDBusMessage *message;
5645   GDBusMessage *reply;
5646   GVariant *result;
5647   GError *local_error;
5648   GDBusSendMessageFlags send_flags;
5649
5650   message = NULL;
5651   reply = NULL;
5652   result = NULL;
5653
5654   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
5655   g_return_val_if_fail (bus_name == NULL || g_dbus_is_name (bus_name), NULL);
5656   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), NULL);
5657   g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), NULL);
5658   g_return_val_if_fail (method_name != NULL && g_dbus_is_member_name (method_name), NULL);
5659   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
5660   g_return_val_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
5661 #ifdef G_OS_UNIX
5662   g_return_val_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list), NULL);
5663 #else
5664   g_return_val_if_fail (fd_list == NULL, NULL);
5665 #endif
5666   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
5667
5668   if (!(flags & CALL_FLAGS_INITIALIZING))
5669     g_return_val_if_fail (check_initialized (connection), FALSE);
5670
5671   if (reply_type == NULL)
5672     reply_type = G_VARIANT_TYPE_ANY;
5673
5674   message = g_dbus_message_new_method_call (bus_name,
5675                                             object_path,
5676                                             interface_name,
5677                                             method_name);
5678   add_call_flags (message, flags);
5679   if (parameters != NULL)
5680     g_dbus_message_set_body (message, parameters);
5681
5682 #ifdef G_OS_UNIX
5683   if (fd_list != NULL)
5684     g_dbus_message_set_unix_fd_list (message, fd_list);
5685 #endif
5686
5687   if (G_UNLIKELY (_g_dbus_debug_call ()))
5688     {
5689       _g_dbus_debug_print_lock ();
5690       g_print ("========================================================================\n"
5691                "GDBus-debug:Call:\n"
5692                " >>>> SYNC %s.%s()\n"
5693                "      on object %s\n"
5694                "      owned by name %s\n",
5695                interface_name,
5696                method_name,
5697                object_path,
5698                bus_name != NULL ? bus_name : "(none)");
5699       _g_dbus_debug_print_unlock ();
5700     }
5701
5702   local_error = NULL;
5703
5704   send_flags = G_DBUS_SEND_MESSAGE_FLAGS_NONE;
5705
5706   /* translate from one flavour of flags to another... */
5707   if (flags & CALL_FLAGS_INITIALIZING)
5708     send_flags |= SEND_MESSAGE_FLAGS_INITIALIZING;
5709
5710   reply = g_dbus_connection_send_message_with_reply_sync (connection,
5711                                                           message,
5712                                                           send_flags,
5713                                                           timeout_msec,
5714                                                           NULL, /* volatile guint32 *out_serial */
5715                                                           cancellable,
5716                                                           &local_error);
5717
5718   if (G_UNLIKELY (_g_dbus_debug_call ()))
5719     {
5720       _g_dbus_debug_print_lock ();
5721       g_print ("========================================================================\n"
5722                "GDBus-debug:Call:\n"
5723                " <<<< SYNC COMPLETE %s.%s()\n"
5724                "      ",
5725                interface_name,
5726                method_name);
5727       if (reply != NULL)
5728         {
5729           g_print ("SUCCESS\n");
5730         }
5731       else
5732         {
5733           g_print ("FAILED: %s\n",
5734                    local_error->message);
5735         }
5736       _g_dbus_debug_print_unlock ();
5737     }
5738
5739   if (reply == NULL)
5740     {
5741       if (error != NULL)
5742         *error = local_error;
5743       else
5744         g_error_free (local_error);
5745       goto out;
5746     }
5747
5748   result = decode_method_reply (reply, method_name, reply_type, out_fd_list, error);
5749
5750  out:
5751   if (message != NULL)
5752     g_object_unref (message);
5753   if (reply != NULL)
5754     g_object_unref (reply);
5755
5756   return result;
5757 }
5758
5759 /* ---------------------------------------------------------------------------------------------------- */
5760
5761 /**
5762  * g_dbus_connection_call:
5763  * @connection: a #GDBusConnection
5764  * @bus_name: (allow-none): a unique or well-known bus name or %NULL if
5765  *     @connection is not a message bus connection
5766  * @object_path: path of remote object
5767  * @interface_name: D-Bus interface to invoke method on
5768  * @method_name: the name of the method to invoke
5769  * @parameters: (allow-none): a #GVariant tuple with parameters for the method
5770  *     or %NULL if not passing parameters
5771  * @reply_type: (allow-none): the expected type of the reply, or %NULL
5772  * @flags: flags from the #GDBusCallFlags enumeration
5773  * @timeout_msec: the timeout in milliseconds, -1 to use the default
5774  *     timeout or %G_MAXINT for no timeout
5775  * @cancellable: (allow-none): a #GCancellable or %NULL
5776  * @callback: (allow-none): a #GAsyncReadyCallback to call when the request
5777  *     is satisfied or %NULL if you don't care about the result of the
5778  *     method invocation
5779  * @user_data: the data to pass to @callback
5780  *
5781  * Asynchronously invokes the @method_name method on the
5782  * @interface_name D-Bus interface on the remote object at
5783  * @object_path owned by @bus_name.
5784  *
5785  * If @connection is closed then the operation will fail with
5786  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
5787  * fail with %G_IO_ERROR_CANCELLED. If @parameters contains a value
5788  * not compatible with the D-Bus protocol, the operation fails with
5789  * %G_IO_ERROR_INVALID_ARGUMENT.
5790  *
5791  * If @reply_type is non-%NULL then the reply will be checked for having this type and an
5792  * error will be raised if it does not match.  Said another way, if you give a @reply_type
5793  * then any non-%NULL return value will be of this type.
5794  *
5795  * If the @parameters #GVariant is floating, it is consumed. This allows
5796  * convenient 'inline' use of g_variant_new(), e.g.:
5797  * |[
5798  *  g_dbus_connection_call (connection,
5799  *                          "org.freedesktop.StringThings",
5800  *                          "/org/freedesktop/StringThings",
5801  *                          "org.freedesktop.StringThings",
5802  *                          "TwoStrings",
5803  *                          g_variant_new ("(ss)",
5804  *                                         "Thing One",
5805  *                                         "Thing Two"),
5806  *                          NULL,
5807  *                          G_DBUS_CALL_FLAGS_NONE,
5808  *                          -1,
5809  *                          NULL,
5810  *                          (GAsyncReadyCallback) two_strings_done,
5811  *                          NULL);
5812  * ]|
5813  *
5814  * This is an asynchronous method. When the operation is finished, @callback will be invoked
5815  * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
5816  * of the thread you are calling this method from. You can then call
5817  * g_dbus_connection_call_finish() to get the result of the operation.
5818  * See g_dbus_connection_call_sync() for the synchronous version of this
5819  * function.
5820  *
5821  * If @callback is %NULL then the D-Bus method call message will be sent with
5822  * the %G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set.
5823  *
5824  * Since: 2.26
5825  */
5826 void
5827 g_dbus_connection_call (GDBusConnection     *connection,
5828                         const gchar         *bus_name,
5829                         const gchar         *object_path,
5830                         const gchar         *interface_name,
5831                         const gchar         *method_name,
5832                         GVariant            *parameters,
5833                         const GVariantType  *reply_type,
5834                         GDBusCallFlags       flags,
5835                         gint                 timeout_msec,
5836                         GCancellable        *cancellable,
5837                         GAsyncReadyCallback  callback,
5838                         gpointer             user_data)
5839 {
5840   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);
5841 }
5842
5843 /**
5844  * g_dbus_connection_call_finish:
5845  * @connection: a #GDBusConnection
5846  * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_call()
5847  * @error: return location for error or %NULL
5848  *
5849  * Finishes an operation started with g_dbus_connection_call().
5850  *
5851  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
5852  *     return values. Free with g_variant_unref().
5853  *
5854  * Since: 2.26
5855  */
5856 GVariant *
5857 g_dbus_connection_call_finish (GDBusConnection  *connection,
5858                                GAsyncResult     *res,
5859                                GError          **error)
5860 {
5861   return g_dbus_connection_call_finish_internal (connection, NULL, res, error);
5862 }
5863
5864 /**
5865  * g_dbus_connection_call_sync:
5866  * @connection: a #GDBusConnection
5867  * @bus_name: (allow-none): a unique or well-known bus name or %NULL if
5868  *     @connection is not a message bus connection
5869  * @object_path: path of remote object
5870  * @interface_name: D-Bus interface to invoke method on
5871  * @method_name: the name of the method to invoke
5872  * @parameters: (allow-none): a #GVariant tuple with parameters for the method
5873  *     or %NULL if not passing parameters
5874  * @reply_type: (allow-none): the expected type of the reply, or %NULL
5875  * @flags: flags from the #GDBusCallFlags enumeration
5876  * @timeout_msec: the timeout in milliseconds, -1 to use the default
5877  *     timeout or %G_MAXINT for no timeout
5878  * @cancellable: (allow-none): a #GCancellable or %NULL
5879  * @error: return location for error or %NULL
5880  *
5881  * Synchronously invokes the @method_name method on the
5882  * @interface_name D-Bus interface on the remote object at
5883  * @object_path owned by @bus_name.
5884  *
5885  * If @connection is closed then the operation will fail with
5886  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the
5887  * operation will fail with %G_IO_ERROR_CANCELLED. If @parameters
5888  * contains a value not compatible with the D-Bus protocol, the operation
5889  * fails with %G_IO_ERROR_INVALID_ARGUMENT.
5890
5891  * If @reply_type is non-%NULL then the reply will be checked for having
5892  * this type and an error will be raised if it does not match.  Said
5893  * another way, if you give a @reply_type then any non-%NULL return
5894  * value will be of this type.
5895  *
5896  * If the @parameters #GVariant is floating, it is consumed.
5897  * This allows convenient 'inline' use of g_variant_new(), e.g.:
5898  * |[
5899  *  g_dbus_connection_call_sync (connection,
5900  *                               "org.freedesktop.StringThings",
5901  *                               "/org/freedesktop/StringThings",
5902  *                               "org.freedesktop.StringThings",
5903  *                               "TwoStrings",
5904  *                               g_variant_new ("(ss)",
5905  *                                              "Thing One",
5906  *                                              "Thing Two"),
5907  *                               NULL,
5908  *                               G_DBUS_CALL_FLAGS_NONE,
5909  *                               -1,
5910  *                               NULL,
5911  *                               &error);
5912  * ]|
5913  *
5914  * The calling thread is blocked until a reply is received. See
5915  * g_dbus_connection_call() for the asynchronous version of
5916  * this method.
5917  *
5918  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
5919  *     return values. Free with g_variant_unref().
5920  *
5921  * Since: 2.26
5922  */
5923 GVariant *
5924 g_dbus_connection_call_sync (GDBusConnection     *connection,
5925                              const gchar         *bus_name,
5926                              const gchar         *object_path,
5927                              const gchar         *interface_name,
5928                              const gchar         *method_name,
5929                              GVariant            *parameters,
5930                              const GVariantType  *reply_type,
5931                              GDBusCallFlags       flags,
5932                              gint                 timeout_msec,
5933                              GCancellable        *cancellable,
5934                              GError             **error)
5935 {
5936   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);
5937 }
5938
5939 /* ---------------------------------------------------------------------------------------------------- */
5940
5941 #ifdef G_OS_UNIX
5942
5943 /**
5944  * g_dbus_connection_call_with_unix_fd_list:
5945  * @connection: a #GDBusConnection
5946  * @bus_name: (allow-none): a unique or well-known bus name or %NULL if
5947  *     @connection is not a message bus connection
5948  * @object_path: path of remote object
5949  * @interface_name: D-Bus interface to invoke method on
5950  * @method_name: the name of the method to invoke
5951  * @parameters: (allow-none): a #GVariant tuple with parameters for the method
5952  *     or %NULL if not passing parameters
5953  * @reply_type: (allow-none): the expected type of the reply, or %NULL
5954  * @flags: flags from the #GDBusCallFlags enumeration
5955  * @timeout_msec: the timeout in milliseconds, -1 to use the default
5956  *     timeout or %G_MAXINT for no timeout
5957  * @fd_list: (allow-none): a #GUnixFDList or %NULL
5958  * @cancellable: (allow-none): a #GCancellable or %NULL
5959  * @callback: (allow-none): a #GAsyncReadyCallback to call when the request is
5960  *     satisfied or %NULL if you don't * care about the result of the
5961  *     method invocation
5962  * @user_data: The data to pass to @callback.
5963  *
5964  * Like g_dbus_connection_call() but also takes a #GUnixFDList object.
5965  *
5966  * This method is only available on UNIX.
5967  *
5968  * Since: 2.30
5969  */
5970 void
5971 g_dbus_connection_call_with_unix_fd_list (GDBusConnection     *connection,
5972                                           const gchar         *bus_name,
5973                                           const gchar         *object_path,
5974                                           const gchar         *interface_name,
5975                                           const gchar         *method_name,
5976                                           GVariant            *parameters,
5977                                           const GVariantType  *reply_type,
5978                                           GDBusCallFlags       flags,
5979                                           gint                 timeout_msec,
5980                                           GUnixFDList         *fd_list,
5981                                           GCancellable        *cancellable,
5982                                           GAsyncReadyCallback  callback,
5983                                           gpointer             user_data)
5984 {
5985   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);
5986 }
5987
5988 /**
5989  * g_dbus_connection_call_with_unix_fd_list_finish:
5990  * @connection: a #GDBusConnection
5991  * @out_fd_list: (out) (allow-none): return location for a #GUnixFDList or %NULL
5992  * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to
5993  *     g_dbus_connection_call_with_unix_fd_list()
5994  * @error: return location for error or %NULL
5995  *
5996  * Finishes an operation started with g_dbus_connection_call_with_unix_fd_list().
5997  *
5998  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
5999  *     return values. Free with g_variant_unref().
6000  *
6001  * Since: 2.30
6002  */
6003 GVariant *
6004 g_dbus_connection_call_with_unix_fd_list_finish (GDBusConnection  *connection,
6005                                                  GUnixFDList     **out_fd_list,
6006                                                  GAsyncResult     *res,
6007                                                  GError          **error)
6008 {
6009   return g_dbus_connection_call_finish_internal (connection, out_fd_list, res, error);
6010 }
6011
6012 /**
6013  * g_dbus_connection_call_with_unix_fd_list_sync:
6014  * @connection: a #GDBusConnection
6015  * @bus_name: (allow-none): a unique or well-known bus name or %NULL
6016  *     if @connection is not a message bus connection
6017  * @object_path: path of remote object
6018  * @interface_name: D-Bus interface to invoke method on
6019  * @method_name: the name of the method to invoke
6020  * @parameters: (allow-none): a #GVariant tuple with parameters for
6021  *     the method or %NULL if not passing parameters
6022  * @reply_type: (allow-none): the expected type of the reply, or %NULL
6023  * @flags: flags from the #GDBusCallFlags enumeration
6024  * @timeout_msec: the timeout in milliseconds, -1 to use the default
6025  *     timeout or %G_MAXINT for no timeout
6026  * @fd_list: (allow-none): a #GUnixFDList or %NULL
6027  * @out_fd_list: (out) (allow-none): return location for a #GUnixFDList or %NULL
6028  * @cancellable: (allow-none): a #GCancellable or %NULL
6029  * @error: return location for error or %NULL
6030  *
6031  * Like g_dbus_connection_call_sync() but also takes and returns #GUnixFDList objects.
6032  *
6033  * This method is only available on UNIX.
6034  *
6035  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
6036  *     return values. Free with g_variant_unref().
6037  *
6038  * Since: 2.30
6039  */
6040 GVariant *
6041 g_dbus_connection_call_with_unix_fd_list_sync (GDBusConnection     *connection,
6042                                                const gchar         *bus_name,
6043                                                const gchar         *object_path,
6044                                                const gchar         *interface_name,
6045                                                const gchar         *method_name,
6046                                                GVariant            *parameters,
6047                                                const GVariantType  *reply_type,
6048                                                GDBusCallFlags       flags,
6049                                                gint                 timeout_msec,
6050                                                GUnixFDList         *fd_list,
6051                                                GUnixFDList        **out_fd_list,
6052                                                GCancellable        *cancellable,
6053                                                GError             **error)
6054 {
6055   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);
6056 }
6057
6058 #endif /* G_OS_UNIX */
6059
6060 /* ---------------------------------------------------------------------------------------------------- */
6061
6062 struct ExportedSubtree
6063 {
6064   guint                     id;
6065   gchar                    *object_path;
6066   GDBusConnection          *connection;
6067   GDBusSubtreeVTable       *vtable;
6068   GDBusSubtreeFlags         flags;
6069
6070   GMainContext             *context;
6071   gpointer                  user_data;
6072   GDestroyNotify            user_data_free_func;
6073 };
6074
6075 static void
6076 exported_subtree_free (ExportedSubtree *es)
6077 {
6078   call_destroy_notify (es->context,
6079                        es->user_data_free_func,
6080                        es->user_data);
6081
6082   g_main_context_unref (es->context);
6083
6084   _g_dbus_subtree_vtable_free (es->vtable);
6085   g_free (es->object_path);
6086   g_free (es);
6087 }
6088
6089 /* called without lock held in the thread where the caller registered
6090  * the subtree
6091  */
6092 static gboolean
6093 handle_subtree_introspect (GDBusConnection *connection,
6094                            ExportedSubtree *es,
6095                            GDBusMessage    *message)
6096 {
6097   GString *s;
6098   gboolean handled;
6099   GDBusMessage *reply;
6100   gchar **children;
6101   gboolean is_root;
6102   const gchar *sender;
6103   const gchar *requested_object_path;
6104   const gchar *requested_node;
6105   GDBusInterfaceInfo **interfaces;
6106   guint n;
6107   gchar **subnode_paths;
6108   gboolean has_properties_interface;
6109   gboolean has_introspectable_interface;
6110
6111   handled = FALSE;
6112
6113   requested_object_path = g_dbus_message_get_path (message);
6114   sender = g_dbus_message_get_sender (message);
6115   is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
6116
6117   s = g_string_new (NULL);
6118   introspect_append_header (s);
6119
6120   /* Strictly we don't need the children in dynamic mode, but we avoid the
6121    * conditionals to preserve code clarity
6122    */
6123   children = es->vtable->enumerate (es->connection,
6124                                     sender,
6125                                     es->object_path,
6126                                     es->user_data);
6127
6128   if (!is_root)
6129     {
6130       requested_node = strrchr (requested_object_path, '/') + 1;
6131
6132       /* Assert existence of object if we are not dynamic */
6133       if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
6134           !_g_strv_has_string ((const gchar * const *) children, requested_node))
6135         goto out;
6136     }
6137   else
6138     {
6139       requested_node = NULL;
6140     }
6141
6142   interfaces = es->vtable->introspect (es->connection,
6143                                        sender,
6144                                        es->object_path,
6145                                        requested_node,
6146                                        es->user_data);
6147   if (interfaces != NULL)
6148     {
6149       has_properties_interface = FALSE;
6150       has_introspectable_interface = FALSE;
6151
6152       for (n = 0; interfaces[n] != NULL; n++)
6153         {
6154           if (strcmp (interfaces[n]->name, "org.freedesktop.DBus.Properties") == 0)
6155             has_properties_interface = TRUE;
6156           else if (strcmp (interfaces[n]->name, "org.freedesktop.DBus.Introspectable") == 0)
6157             has_introspectable_interface = TRUE;
6158         }
6159       if (!has_properties_interface)
6160         g_string_append (s, introspect_properties_interface);
6161       if (!has_introspectable_interface)
6162         g_string_append (s, introspect_introspectable_interface);
6163
6164       for (n = 0; interfaces[n] != NULL; n++)
6165         {
6166           g_dbus_interface_info_generate_xml (interfaces[n], 2, s);
6167           g_dbus_interface_info_unref (interfaces[n]);
6168         }
6169       g_free (interfaces);
6170     }
6171
6172   /* then include <node> entries from the Subtree for the root */
6173   if (is_root)
6174     {
6175       for (n = 0; children != NULL && children[n] != NULL; n++)
6176         g_string_append_printf (s, "  <node name=\"%s\"/>\n", children[n]);
6177     }
6178
6179   /* finally include nodes registered below us */
6180   subnode_paths = g_dbus_connection_list_registered (es->connection, requested_object_path);
6181   for (n = 0; subnode_paths != NULL && subnode_paths[n] != NULL; n++)
6182     g_string_append_printf (s, "  <node name=\"%s\"/>\n", subnode_paths[n]);
6183   g_strfreev (subnode_paths);
6184
6185   g_string_append (s, "</node>\n");
6186
6187   reply = g_dbus_message_new_method_reply (message);
6188   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
6189   g_dbus_connection_send_message (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6190   g_object_unref (reply);
6191
6192   handled = TRUE;
6193
6194  out:
6195   g_string_free (s, TRUE);
6196   g_strfreev (children);
6197   return handled;
6198 }
6199
6200 /* called without lock held in the thread where the caller registered
6201  * the subtree
6202  */
6203 static gboolean
6204 handle_subtree_method_invocation (GDBusConnection *connection,
6205                                   ExportedSubtree *es,
6206                                   GDBusMessage    *message)
6207 {
6208   gboolean handled;
6209   const gchar *sender;
6210   const gchar *interface_name;
6211   const gchar *member;
6212   const gchar *signature;
6213   const gchar *requested_object_path;
6214   const gchar *requested_node;
6215   gboolean is_root;
6216   GDBusInterfaceInfo *interface_info;
6217   const GDBusInterfaceVTable *interface_vtable;
6218   gpointer interface_user_data;
6219   guint n;
6220   GDBusInterfaceInfo **interfaces;
6221   gboolean is_property_get;
6222   gboolean is_property_set;
6223   gboolean is_property_get_all;
6224
6225   handled = FALSE;
6226   interfaces = NULL;
6227
6228   requested_object_path = g_dbus_message_get_path (message);
6229   sender = g_dbus_message_get_sender (message);
6230   interface_name = g_dbus_message_get_interface (message);
6231   member = g_dbus_message_get_member (message);
6232   signature = g_dbus_message_get_signature (message);
6233   is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
6234
6235   is_property_get = FALSE;
6236   is_property_set = FALSE;
6237   is_property_get_all = FALSE;
6238   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0)
6239     {
6240       if (g_strcmp0 (member, "Get") == 0 && g_strcmp0 (signature, "ss") == 0)
6241         is_property_get = TRUE;
6242       else if (g_strcmp0 (member, "Set") == 0 && g_strcmp0 (signature, "ssv") == 0)
6243         is_property_set = TRUE;
6244       else if (g_strcmp0 (member, "GetAll") == 0 && g_strcmp0 (signature, "s") == 0)
6245         is_property_get_all = TRUE;
6246     }
6247
6248   if (!is_root)
6249     {
6250       requested_node = strrchr (requested_object_path, '/') + 1;
6251
6252       if (~es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES)
6253         {
6254           /* We don't want to dispatch to unenumerated
6255            * nodes, so ensure that the child exists.
6256            */
6257           gchar **children;
6258           gboolean exists;
6259
6260           children = es->vtable->enumerate (es->connection,
6261                                             sender,
6262                                             es->object_path,
6263                                             es->user_data);
6264
6265           exists = _g_strv_has_string ((const gchar * const *) children, requested_node);
6266           g_strfreev (children);
6267
6268           if (!exists)
6269             goto out;
6270         }
6271     }
6272   else
6273     {
6274       requested_node = NULL;
6275     }
6276
6277   /* get introspection data for the node */
6278   interfaces = es->vtable->introspect (es->connection,
6279                                        sender,
6280                                        requested_object_path,
6281                                        requested_node,
6282                                        es->user_data);
6283
6284   if (interfaces == NULL)
6285     goto out;
6286
6287   interface_info = NULL;
6288   for (n = 0; interfaces[n] != NULL; n++)
6289     {
6290       if (g_strcmp0 (interfaces[n]->name, interface_name) == 0)
6291         interface_info = interfaces[n];
6292     }
6293
6294   /* dispatch the call if the user wants to handle it */
6295   if (interface_info != NULL)
6296     {
6297       /* figure out where to dispatch the method call */
6298       interface_user_data = NULL;
6299       interface_vtable = es->vtable->dispatch (es->connection,
6300                                                sender,
6301                                                es->object_path,
6302                                                interface_name,
6303                                                requested_node,
6304                                                &interface_user_data,
6305                                                es->user_data);
6306       if (interface_vtable == NULL)
6307         goto out;
6308
6309       CONNECTION_LOCK (connection);
6310       handled = validate_and_maybe_schedule_method_call (es->connection,
6311                                                          message,
6312                                                          0,
6313                                                          es->id,
6314                                                          interface_info,
6315                                                          interface_vtable,
6316                                                          es->context,
6317                                                          interface_user_data);
6318       CONNECTION_UNLOCK (connection);
6319     }
6320   /* handle org.freedesktop.DBus.Properties interface if not explicitly handled */
6321   else if (is_property_get || is_property_set || is_property_get_all)
6322     {
6323       if (is_property_get)
6324         g_variant_get (g_dbus_message_get_body (message), "(&s&s)", &interface_name, NULL);
6325       else if (is_property_set)
6326         g_variant_get (g_dbus_message_get_body (message), "(&s&sv)", &interface_name, NULL, NULL);
6327       else if (is_property_get_all)
6328         g_variant_get (g_dbus_message_get_body (message), "(&s)", &interface_name, NULL, NULL);
6329       else
6330         g_assert_not_reached ();
6331
6332       /* see if the object supports this interface at all */
6333       for (n = 0; interfaces[n] != NULL; n++)
6334         {
6335           if (g_strcmp0 (interfaces[n]->name, interface_name) == 0)
6336             interface_info = interfaces[n];
6337         }
6338
6339       /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the user-code
6340        * claims it won't support the interface
6341        */
6342       if (interface_info == NULL)
6343         {
6344           GDBusMessage *reply;
6345           reply = g_dbus_message_new_method_error (message,
6346                                                    "org.freedesktop.DBus.Error.InvalidArgs",
6347                                                    _("No such interface '%s'"),
6348                                                    interface_name);
6349           g_dbus_connection_send_message (es->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6350           g_object_unref (reply);
6351           handled = TRUE;
6352           goto out;
6353         }
6354
6355       /* figure out where to dispatch the property get/set/getall calls */
6356       interface_user_data = NULL;
6357       interface_vtable = es->vtable->dispatch (es->connection,
6358                                                sender,
6359                                                es->object_path,
6360                                                interface_name,
6361                                                requested_node,
6362                                                &interface_user_data,
6363                                                es->user_data);
6364       if (interface_vtable == NULL)
6365         {
6366           g_warning ("The subtree introspection function indicates that '%s' "
6367                      "is a valid interface name, but calling the dispatch "
6368                      "function on that interface gave us NULL", interface_name);
6369           goto out;
6370         }
6371
6372       if (is_property_get || is_property_set)
6373         {
6374           CONNECTION_LOCK (connection);
6375           handled = validate_and_maybe_schedule_property_getset (es->connection,
6376                                                                  message,
6377                                                                  0,
6378                                                                  es->id,
6379                                                                  is_property_get,
6380                                                                  interface_info,
6381                                                                  interface_vtable,
6382                                                                  es->context,
6383                                                                  interface_user_data);
6384           CONNECTION_UNLOCK (connection);
6385         }
6386       else if (is_property_get_all)
6387         {
6388           CONNECTION_LOCK (connection);
6389           handled = validate_and_maybe_schedule_property_get_all (es->connection,
6390                                                                   message,
6391                                                                   0,
6392                                                                   es->id,
6393                                                                   interface_info,
6394                                                                   interface_vtable,
6395                                                                   es->context,
6396                                                                   interface_user_data);
6397           CONNECTION_UNLOCK (connection);
6398         }
6399     }
6400
6401  out:
6402   if (interfaces != NULL)
6403     {
6404       for (n = 0; interfaces[n] != NULL; n++)
6405         g_dbus_interface_info_unref (interfaces[n]);
6406       g_free (interfaces);
6407     }
6408
6409   return handled;
6410 }
6411
6412 typedef struct
6413 {
6414   GDBusMessage *message;
6415   ExportedSubtree *es;
6416 } SubtreeDeferredData;
6417
6418 static void
6419 subtree_deferred_data_free (SubtreeDeferredData *data)
6420 {
6421   g_object_unref (data->message);
6422   g_free (data);
6423 }
6424
6425 /* called without lock held in the thread where the caller registered the subtree */
6426 static gboolean
6427 process_subtree_vtable_message_in_idle_cb (gpointer _data)
6428 {
6429   SubtreeDeferredData *data = _data;
6430   gboolean handled;
6431
6432   handled = FALSE;
6433
6434   if (g_strcmp0 (g_dbus_message_get_interface (data->message), "org.freedesktop.DBus.Introspectable") == 0 &&
6435       g_strcmp0 (g_dbus_message_get_member (data->message), "Introspect") == 0 &&
6436       g_strcmp0 (g_dbus_message_get_signature (data->message), "") == 0)
6437     handled = handle_subtree_introspect (data->es->connection,
6438                                          data->es,
6439                                          data->message);
6440   else
6441     handled = handle_subtree_method_invocation (data->es->connection,
6442                                                 data->es,
6443                                                 data->message);
6444
6445   if (!handled)
6446     {
6447       CONNECTION_LOCK (data->es->connection);
6448       handled = handle_generic_unlocked (data->es->connection, data->message);
6449       CONNECTION_UNLOCK (data->es->connection);
6450     }
6451
6452   /* if we couldn't handle the request, just bail with the UnknownMethod error */
6453   if (!handled)
6454     {
6455       GDBusMessage *reply;
6456       reply = g_dbus_message_new_method_error (data->message,
6457                                                "org.freedesktop.DBus.Error.UnknownMethod",
6458                                                _("Method '%s' on interface '%s' with signature '%s' does not exist"),
6459                                                g_dbus_message_get_member (data->message),
6460                                                g_dbus_message_get_interface (data->message),
6461                                                g_dbus_message_get_signature (data->message));
6462       g_dbus_connection_send_message (data->es->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6463       g_object_unref (reply);
6464     }
6465
6466   return FALSE;
6467 }
6468
6469 /* called in GDBusWorker thread with connection's lock held */
6470 static gboolean
6471 subtree_message_func (GDBusConnection *connection,
6472                       ExportedSubtree *es,
6473                       GDBusMessage    *message)
6474 {
6475   GSource *idle_source;
6476   SubtreeDeferredData *data;
6477
6478   data = g_new0 (SubtreeDeferredData, 1);
6479   data->message = g_object_ref (message);
6480   data->es = es;
6481
6482   /* defer this call to an idle handler in the right thread */
6483   idle_source = g_idle_source_new ();
6484   g_source_set_priority (idle_source, G_PRIORITY_HIGH);
6485   g_source_set_callback (idle_source,
6486                          process_subtree_vtable_message_in_idle_cb,
6487                          data,
6488                          (GDestroyNotify) subtree_deferred_data_free);
6489   g_source_attach (idle_source, es->context);
6490   g_source_unref (idle_source);
6491
6492   /* since we own the entire subtree, handlers for objects not in the subtree have been
6493    * tried already by libdbus-1 - so we just need to ensure that we're always going
6494    * to reply to the message
6495    */
6496   return TRUE;
6497 }
6498
6499 /**
6500  * g_dbus_connection_register_subtree:
6501  * @connection: a #GDBusConnection
6502  * @object_path: the object path to register the subtree at
6503  * @vtable: a #GDBusSubtreeVTable to enumerate, introspect and
6504  *     dispatch nodes in the subtree
6505  * @flags: flags used to fine tune the behavior of the subtree
6506  * @user_data: data to pass to functions in @vtable
6507  * @user_data_free_func: function to call when the subtree is unregistered
6508  * @error: return location for error or %NULL
6509  *
6510  * Registers a whole subtree of <quote>dynamic</quote> objects.
6511  *
6512  * The @enumerate and @introspection functions in @vtable are used to
6513  * convey, to remote callers, what nodes exist in the subtree rooted
6514  * by @object_path.
6515  *
6516  * When handling remote calls into any node in the subtree, first the
6517  * @enumerate function is used to check if the node exists. If the node exists
6518  * or the #G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag is set
6519  * the @introspection function is used to check if the node supports the
6520  * requested method. If so, the @dispatch function is used to determine
6521  * where to dispatch the call. The collected #GDBusInterfaceVTable and
6522  * #gpointer will be used to call into the interface vtable for processing
6523  * the request.
6524  *
6525  * All calls into user-provided code will be invoked in the <link
6526  * linkend="g-main-context-push-thread-default">thread-default main
6527  * loop</link> of the thread you are calling this method from.
6528  *
6529  * If an existing subtree is already registered at @object_path or
6530  * then @error is set to #G_IO_ERROR_EXISTS.
6531  *
6532  * Note that it is valid to register regular objects (using
6533  * g_dbus_connection_register_object()) in a subtree registered with
6534  * g_dbus_connection_register_subtree() - if so, the subtree handler
6535  * is tried as the last resort. One way to think about a subtree
6536  * handler is to consider it a <quote>fallback handler</quote>
6537  * for object paths not registered via g_dbus_connection_register_object()
6538  * or other bindings.
6539  *
6540  * Note that @vtable will be copied so you cannot change it after
6541  * registration.
6542  *
6543  * See <xref linkend="gdbus-subtree-server"/> for an example of how to use this method.
6544  *
6545  * Returns: 0 if @error is set, otherwise a subtree registration id (never 0)
6546  * that can be used with g_dbus_connection_unregister_subtree() .
6547  *
6548  * Since: 2.26
6549  */
6550 guint
6551 g_dbus_connection_register_subtree (GDBusConnection           *connection,
6552                                     const gchar               *object_path,
6553                                     const GDBusSubtreeVTable  *vtable,
6554                                     GDBusSubtreeFlags          flags,
6555                                     gpointer                   user_data,
6556                                     GDestroyNotify             user_data_free_func,
6557                                     GError                   **error)
6558 {
6559   guint ret;
6560   ExportedSubtree *es;
6561
6562   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
6563   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
6564   g_return_val_if_fail (vtable != NULL, 0);
6565   g_return_val_if_fail (error == NULL || *error == NULL, 0);
6566   g_return_val_if_fail (check_initialized (connection), 0);
6567
6568   ret = 0;
6569
6570   CONNECTION_LOCK (connection);
6571
6572   es = g_hash_table_lookup (connection->map_object_path_to_es, object_path);
6573   if (es != NULL)
6574     {
6575       g_set_error (error,
6576                    G_IO_ERROR,
6577                    G_IO_ERROR_EXISTS,
6578                    _("A subtree is already exported for %s"),
6579                    object_path);
6580       goto out;
6581     }
6582
6583   es = g_new0 (ExportedSubtree, 1);
6584   es->object_path = g_strdup (object_path);
6585   es->connection = connection;
6586
6587   es->vtable = _g_dbus_subtree_vtable_copy (vtable);
6588   es->flags = flags;
6589   es->id = _global_subtree_registration_id++; /* TODO: overflow etc. */
6590   es->user_data = user_data;
6591   es->user_data_free_func = user_data_free_func;
6592   es->context = g_main_context_ref_thread_default ();
6593
6594   g_hash_table_insert (connection->map_object_path_to_es, es->object_path, es);
6595   g_hash_table_insert (connection->map_id_to_es,
6596                        GUINT_TO_POINTER (es->id),
6597                        es);
6598
6599   ret = es->id;
6600
6601  out:
6602   CONNECTION_UNLOCK (connection);
6603
6604   return ret;
6605 }
6606
6607 /* ---------------------------------------------------------------------------------------------------- */
6608
6609 /**
6610  * g_dbus_connection_unregister_subtree:
6611  * @connection: a #GDBusConnection
6612  * @registration_id: a subtree registration id obtained from
6613  *     g_dbus_connection_register_subtree()
6614  *
6615  * Unregisters a subtree.
6616  *
6617  * Returns: %TRUE if the subtree was unregistered, %FALSE otherwise
6618  *
6619  * Since: 2.26
6620  */
6621 gboolean
6622 g_dbus_connection_unregister_subtree (GDBusConnection *connection,
6623                                       guint            registration_id)
6624 {
6625   ExportedSubtree *es;
6626   gboolean ret;
6627
6628   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
6629   g_return_val_if_fail (check_initialized (connection), FALSE);
6630
6631   ret = FALSE;
6632
6633   CONNECTION_LOCK (connection);
6634
6635   es = g_hash_table_lookup (connection->map_id_to_es,
6636                             GUINT_TO_POINTER (registration_id));
6637   if (es == NULL)
6638     goto out;
6639
6640   g_warn_if_fail (g_hash_table_remove (connection->map_id_to_es, GUINT_TO_POINTER (es->id)));
6641   g_warn_if_fail (g_hash_table_remove (connection->map_object_path_to_es, es->object_path));
6642
6643   ret = TRUE;
6644
6645  out:
6646   CONNECTION_UNLOCK (connection);
6647
6648   return ret;
6649 }
6650
6651 /* ---------------------------------------------------------------------------------------------------- */
6652
6653 /* may be called in any thread, with connection's lock held */
6654 static void
6655 handle_generic_ping_unlocked (GDBusConnection *connection,
6656                               const gchar     *object_path,
6657                               GDBusMessage    *message)
6658 {
6659   GDBusMessage *reply;
6660   reply = g_dbus_message_new_method_reply (message);
6661   g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6662   g_object_unref (reply);
6663 }
6664
6665 /* may be called in any thread, with connection's lock held */
6666 static void
6667 handle_generic_get_machine_id_unlocked (GDBusConnection *connection,
6668                                         const gchar     *object_path,
6669                                         GDBusMessage    *message)
6670 {
6671   GDBusMessage *reply;
6672
6673   reply = NULL;
6674   if (connection->machine_id == NULL)
6675     {
6676       GError *error;
6677
6678       error = NULL;
6679       connection->machine_id = _g_dbus_get_machine_id (&error);
6680       if (connection->machine_id == NULL)
6681         {
6682           reply = g_dbus_message_new_method_error_literal (message,
6683                                                            "org.freedesktop.DBus.Error.Failed",
6684                                                            error->message);
6685           g_error_free (error);
6686         }
6687     }
6688
6689   if (reply == NULL)
6690     {
6691       reply = g_dbus_message_new_method_reply (message);
6692       g_dbus_message_set_body (reply, g_variant_new ("(s)", connection->machine_id));
6693     }
6694   g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6695   g_object_unref (reply);
6696 }
6697
6698 /* may be called in any thread, with connection's lock held */
6699 static void
6700 handle_generic_introspect_unlocked (GDBusConnection *connection,
6701                                     const gchar     *object_path,
6702                                     GDBusMessage    *message)
6703 {
6704   guint n;
6705   GString *s;
6706   gchar **registered;
6707   GDBusMessage *reply;
6708
6709   /* first the header */
6710   s = g_string_new (NULL);
6711   introspect_append_header (s);
6712
6713   registered = g_dbus_connection_list_registered_unlocked (connection, object_path);
6714   for (n = 0; registered != NULL && registered[n] != NULL; n++)
6715       g_string_append_printf (s, "  <node name=\"%s\"/>\n", registered[n]);
6716   g_strfreev (registered);
6717   g_string_append (s, "</node>\n");
6718
6719   reply = g_dbus_message_new_method_reply (message);
6720   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
6721   g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6722   g_object_unref (reply);
6723   g_string_free (s, TRUE);
6724 }
6725
6726 /* may be called in any thread, with connection's lock held */
6727 static gboolean
6728 handle_generic_unlocked (GDBusConnection *connection,
6729                          GDBusMessage    *message)
6730 {
6731   gboolean handled;
6732   const gchar *interface_name;
6733   const gchar *member;
6734   const gchar *signature;
6735   const gchar *path;
6736
6737   CONNECTION_ENSURE_LOCK (connection);
6738
6739   handled = FALSE;
6740
6741   interface_name = g_dbus_message_get_interface (message);
6742   member = g_dbus_message_get_member (message);
6743   signature = g_dbus_message_get_signature (message);
6744   path = g_dbus_message_get_path (message);
6745
6746   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
6747       g_strcmp0 (member, "Introspect") == 0 &&
6748       g_strcmp0 (signature, "") == 0)
6749     {
6750       handle_generic_introspect_unlocked (connection, path, message);
6751       handled = TRUE;
6752     }
6753   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
6754            g_strcmp0 (member, "Ping") == 0 &&
6755            g_strcmp0 (signature, "") == 0)
6756     {
6757       handle_generic_ping_unlocked (connection, path, message);
6758       handled = TRUE;
6759     }
6760   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
6761            g_strcmp0 (member, "GetMachineId") == 0 &&
6762            g_strcmp0 (signature, "") == 0)
6763     {
6764       handle_generic_get_machine_id_unlocked (connection, path, message);
6765       handled = TRUE;
6766     }
6767
6768   return handled;
6769 }
6770
6771 /* ---------------------------------------------------------------------------------------------------- */
6772
6773 /* called in GDBusWorker thread with connection's lock held */
6774 static void
6775 distribute_method_call (GDBusConnection *connection,
6776                         GDBusMessage    *message)
6777 {
6778   GDBusMessage *reply;
6779   ExportedObject *eo;
6780   ExportedSubtree *es;
6781   const gchar *object_path;
6782   const gchar *interface_name;
6783   const gchar *member;
6784   const gchar *path;
6785   gchar *subtree_path;
6786   gchar *needle;
6787
6788   g_assert (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL);
6789
6790   interface_name = g_dbus_message_get_interface (message);
6791   member = g_dbus_message_get_member (message);
6792   path = g_dbus_message_get_path (message);
6793   subtree_path = g_strdup (path);
6794   needle = strrchr (subtree_path, '/');
6795   if (needle != NULL && needle != subtree_path)
6796     {
6797       *needle = '\0';
6798     }
6799   else
6800     {
6801       g_free (subtree_path);
6802       subtree_path = NULL;
6803     }
6804
6805
6806   if (G_UNLIKELY (_g_dbus_debug_incoming ()))
6807     {
6808       _g_dbus_debug_print_lock ();
6809       g_print ("========================================================================\n"
6810                "GDBus-debug:Incoming:\n"
6811                " <<<< METHOD INVOCATION %s.%s()\n"
6812                "      on object %s\n"
6813                "      invoked by name %s\n"
6814                "      serial %d\n",
6815                interface_name, member,
6816                path,
6817                g_dbus_message_get_sender (message) != NULL ? g_dbus_message_get_sender (message) : "(none)",
6818                g_dbus_message_get_serial (message));
6819       _g_dbus_debug_print_unlock ();
6820     }
6821
6822   object_path = g_dbus_message_get_path (message);
6823   g_assert (object_path != NULL);
6824
6825   eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path);
6826   if (eo != NULL)
6827     {
6828       if (obj_message_func (connection, eo, message))
6829         goto out;
6830     }
6831
6832   es = g_hash_table_lookup (connection->map_object_path_to_es, object_path);
6833   if (es != NULL)
6834     {
6835       if (subtree_message_func (connection, es, message))
6836         goto out;
6837     }
6838
6839   if (subtree_path != NULL)
6840     {
6841       es = g_hash_table_lookup (connection->map_object_path_to_es, subtree_path);
6842       if (es != NULL)
6843         {
6844           if (subtree_message_func (connection, es, message))
6845             goto out;
6846         }
6847     }
6848
6849   if (handle_generic_unlocked (connection, message))
6850     goto out;
6851
6852   /* if we end up here, the message has not been not handled - so return an error saying this */
6853   reply = g_dbus_message_new_method_error (message,
6854                                            "org.freedesktop.DBus.Error.UnknownMethod",
6855                                            _("No such interface '%s' on object at path %s"),
6856                                            interface_name,
6857                                            object_path);
6858   g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6859   g_object_unref (reply);
6860
6861  out:
6862   g_free (subtree_path);
6863 }
6864
6865 /* ---------------------------------------------------------------------------------------------------- */
6866
6867 /* Called in any user thread, with the message_bus_lock held. */
6868 static GWeakRef *
6869 message_bus_get_singleton (GBusType   bus_type,
6870                            GError   **error)
6871 {
6872   GWeakRef *ret;
6873   const gchar *starter_bus;
6874
6875   ret = NULL;
6876
6877   switch (bus_type)
6878     {
6879     case G_BUS_TYPE_SESSION:
6880       ret = &the_session_bus;
6881       break;
6882
6883     case G_BUS_TYPE_SYSTEM:
6884       ret = &the_system_bus;
6885       break;
6886
6887     case G_BUS_TYPE_STARTER:
6888       starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE");
6889       if (g_strcmp0 (starter_bus, "session") == 0)
6890         {
6891           ret = message_bus_get_singleton (G_BUS_TYPE_SESSION, error);
6892           goto out;
6893         }
6894       else if (g_strcmp0 (starter_bus, "system") == 0)
6895         {
6896           ret = message_bus_get_singleton (G_BUS_TYPE_SYSTEM, error);
6897           goto out;
6898         }
6899       else
6900         {
6901           if (starter_bus != NULL)
6902             {
6903               g_set_error (error,
6904                            G_IO_ERROR,
6905                            G_IO_ERROR_INVALID_ARGUMENT,
6906                            _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable"
6907                              " - unknown value '%s'"),
6908                            starter_bus);
6909             }
6910           else
6911             {
6912               g_set_error_literal (error,
6913                                    G_IO_ERROR,
6914                                    G_IO_ERROR_INVALID_ARGUMENT,
6915                                    _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment "
6916                                      "variable is not set"));
6917             }
6918         }
6919       break;
6920
6921     default:
6922       g_assert_not_reached ();
6923       break;
6924     }
6925
6926  out:
6927   return ret;
6928 }
6929
6930 /* Called in any user thread, without holding locks. */
6931 static GDBusConnection *
6932 get_uninitialized_connection (GBusType       bus_type,
6933                               GCancellable  *cancellable,
6934                               GError       **error)
6935 {
6936   GWeakRef *singleton;
6937   GDBusConnection *ret;
6938
6939   ret = NULL;
6940
6941   G_LOCK (message_bus_lock);
6942   singleton = message_bus_get_singleton (bus_type, error);
6943   if (singleton == NULL)
6944     goto out;
6945
6946   ret = g_weak_ref_get (singleton);
6947
6948   if (ret == NULL)
6949     {
6950       gchar *address;
6951       address = g_dbus_address_get_for_bus_sync (bus_type, cancellable, error);
6952       if (address == NULL)
6953         goto out;
6954       ret = g_object_new (G_TYPE_DBUS_CONNECTION,
6955                           "address", address,
6956                           "flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
6957                                    G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
6958                           "exit-on-close", TRUE,
6959                           NULL);
6960
6961       g_weak_ref_set (singleton, ret);
6962       g_free (address);
6963     }
6964
6965   g_assert (ret != NULL);
6966
6967  out:
6968   G_UNLOCK (message_bus_lock);
6969   return ret;
6970 }
6971
6972 /* May be called from any thread. Must not hold message_bus_lock. */
6973 GDBusConnection *
6974 _g_bus_get_singleton_if_exists (GBusType bus_type)
6975 {
6976   GWeakRef *singleton;
6977   GDBusConnection *ret = NULL;
6978
6979   G_LOCK (message_bus_lock);
6980   singleton = message_bus_get_singleton (bus_type, NULL);
6981   if (singleton == NULL)
6982     goto out;
6983
6984   ret = g_weak_ref_get (singleton);
6985
6986  out:
6987   G_UNLOCK (message_bus_lock);
6988   return ret;
6989 }
6990
6991 /**
6992  * g_bus_get_sync:
6993  * @bus_type: a #GBusType
6994  * @cancellable: (allow-none): a #GCancellable or %NULL
6995  * @error: return location for error or %NULL
6996  *
6997  * Synchronously connects to the message bus specified by @bus_type.
6998  * Note that the returned object may shared with other callers,
6999  * e.g. if two separate parts of a process calls this function with
7000  * the same @bus_type, they will share the same object.
7001  *
7002  * This is a synchronous failable function. See g_bus_get() and
7003  * g_bus_get_finish() for the asynchronous version.
7004  *
7005  * The returned object is a singleton, that is, shared with other
7006  * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
7007  * event that you need a private message bus connection, use
7008  * g_dbus_address_get_for_bus_sync() and
7009  * g_dbus_connection_new_for_address().
7010  *
7011  * Note that the returned #GDBusConnection object will (usually) have
7012  * the #GDBusConnection:exit-on-close property set to %TRUE.
7013  *
7014  * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
7015  *     Free with g_object_unref().
7016  *
7017  * Since: 2.26
7018  */
7019 GDBusConnection *
7020 g_bus_get_sync (GBusType       bus_type,
7021                 GCancellable  *cancellable,
7022                 GError       **error)
7023 {
7024   GDBusConnection *connection;
7025
7026   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
7027
7028   connection = get_uninitialized_connection (bus_type, cancellable, error);
7029   if (connection == NULL)
7030     goto out;
7031
7032   if (!g_initable_init (G_INITABLE (connection), cancellable, error))
7033     {
7034       g_object_unref (connection);
7035       connection = NULL;
7036     }
7037
7038  out:
7039   return connection;
7040 }
7041
7042 static void
7043 bus_get_async_initable_cb (GObject      *source_object,
7044                            GAsyncResult *res,
7045                            gpointer      user_data)
7046 {
7047   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
7048   GError *error;
7049
7050   error = NULL;
7051   if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
7052                                      res,
7053                                      &error))
7054     {
7055       g_assert (error != NULL);
7056       g_simple_async_result_take_error (simple, error);
7057       g_object_unref (source_object);
7058     }
7059   else
7060     {
7061       g_simple_async_result_set_op_res_gpointer (simple,
7062                                                  source_object,
7063                                                  g_object_unref);
7064     }
7065   g_simple_async_result_complete_in_idle (simple);
7066   g_object_unref (simple);
7067 }
7068
7069 /**
7070  * g_bus_get:
7071  * @bus_type: a #GBusType
7072  * @cancellable: (allow-none): a #GCancellable or %NULL
7073  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
7074  * @user_data: the data to pass to @callback
7075  *
7076  * Asynchronously connects to the message bus specified by @bus_type.
7077  *
7078  * When the operation is finished, @callback will be invoked. You can
7079  * then call g_bus_get_finish() to get the result of the operation.
7080  *
7081  * This is a asynchronous failable function. See g_bus_get_sync() for
7082  * the synchronous version.
7083  *
7084  * Since: 2.26
7085  */
7086 void
7087 g_bus_get (GBusType             bus_type,
7088            GCancellable        *cancellable,
7089            GAsyncReadyCallback  callback,
7090            gpointer             user_data)
7091 {
7092   GDBusConnection *connection;
7093   GSimpleAsyncResult *simple;
7094   GError *error;
7095
7096   simple = g_simple_async_result_new (NULL,
7097                                       callback,
7098                                       user_data,
7099                                       g_bus_get);
7100   g_simple_async_result_set_check_cancellable (simple, cancellable);
7101
7102   error = NULL;
7103   connection = get_uninitialized_connection (bus_type, cancellable, &error);
7104   if (connection == NULL)
7105     {
7106       g_assert (error != NULL);
7107       g_simple_async_result_take_error (simple, error);
7108       g_simple_async_result_complete_in_idle (simple);
7109       g_object_unref (simple);
7110     }
7111   else
7112     {
7113       g_async_initable_init_async (G_ASYNC_INITABLE (connection),
7114                                    G_PRIORITY_DEFAULT,
7115                                    cancellable,
7116                                    bus_get_async_initable_cb,
7117                                    simple);
7118     }
7119 }
7120
7121 /**
7122  * g_bus_get_finish:
7123  * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
7124  *     to g_bus_get()
7125  * @error: return location for error or %NULL
7126  *
7127  * Finishes an operation started with g_bus_get().
7128  *
7129  * The returned object is a singleton, that is, shared with other
7130  * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
7131  * event that you need a private message bus connection, use
7132  * g_dbus_address_get_for_bus_sync() and
7133  * g_dbus_connection_new_for_address().
7134  *
7135  * Note that the returned #GDBusConnection object will (usually) have
7136  * the #GDBusConnection:exit-on-close property set to %TRUE.
7137  *
7138  * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
7139  *     Free with g_object_unref().
7140  *
7141  * Since: 2.26
7142  */
7143 GDBusConnection *
7144 g_bus_get_finish (GAsyncResult  *res,
7145                   GError       **error)
7146 {
7147   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
7148   GObject *object;
7149   GDBusConnection *ret;
7150
7151   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
7152
7153   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_bus_get);
7154
7155   ret = NULL;
7156
7157   if (g_simple_async_result_propagate_error (simple, error))
7158     goto out;
7159
7160   object = g_simple_async_result_get_op_res_gpointer (simple);
7161   g_assert (object != NULL);
7162   ret = g_object_ref (G_DBUS_CONNECTION (object));
7163
7164  out:
7165   return ret;
7166 }
7167
7168 /* ---------------------------------------------------------------------------------------------------- */