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