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