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