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