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