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