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