Remove properties from GDBusMethodInvocation class
[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  * - Validate all data (e.g. UTF-8) and check all the required D-Bus headers
27  *   are present and forbidden ones aren't
28  *   - When writing: g_dbus_message_to_blob()
29  *   - When reading: g_dbus_message_new_from_blob()
30  *
31  * - would be nice to expose GDBusAuthMechanism and an extension point
32  *
33  * - Need to rewrite GDBusAuth and rework GDBusAuthMechanism. In particular
34  *   the mechanism VFuncs need to be able to set an error.
35  *
36  * - Need to document other mechanisms/sources for determining the D-Bus
37  *   address of a well-known bus.
38  *
39  *   - e.g. on Win32 we need code like from here
40  *
41  *     http://cgit.freedesktop.org/~david/gdbus-standalone/tree/gdbus/gdbusaddress.c#n900
42  *
43  *     that was never copied over here because it originally was copy-paste
44  *     from the GPLv2 / AFL 2.1 libdbus sources.
45  *
46  *   - on OS X we need to look in launchd for the address
47  *
48  *     https://bugs.freedesktop.org/show_bug.cgi?id=14259
49  *
50  *   - on X11 we need to look in a X11 property on the X server
51  *     - (we can also just use dbus-launch(1) from the D-Bus
52  *        distribution)
53  *
54  *   - (ideally) this requires D-Bus spec work because none of
55  *     this has never really been specced out properly (excect
56  *     the X11 bits)
57  *
58  * - Related to the above, we also need to be able to launch a message bus
59  *   instance.... Since we don't want to write our own bus daemon we should
60  *   launch dbus-daemon(1) (thus: Win32 and OS X need to bundle it)
61  *
62  * - probably want a G_DBUS_NONCE_TCP_TMPDIR environment variable
63  *   to specify where the nonce is stored. This will allow people to use
64  *   G_DBUS_NONCE_TCP_TMPDIR=/mnt/secure.company.server/dbus-nonce-dir
65  *   to easily acheive secure RPC via nonce-tcp.
66  *
67  * - need to expose an extension point for resolving D-Bus address and
68  *   turning them into GIOStream objects. This will allow us to implement
69  *   e.g. X11 D-Bus transports without dlopen()'ing or linking against
70  *   libX11 from libgio.
71  *   - see g_dbus_address_connect() in gdbusaddress.c
72  *
73  * - would be cute to use kernel-specific APIs to resolve fds for
74  *   debug output when using G_DBUS_DEBUG=messages, e.g. in addition to
75  *
76  *     fd 21: dev=8:1,mode=0100644,ino=1171231,uid=0,gid=0,rdev=0:0,size=234,atime=1273070640,mtime=1267126160,ctime=1267126160
77  *
78  *   maybe we can show more information about what fd 21 really is.
79  *   Ryan suggests looking in /proc/self/fd for clues / symlinks!
80  *   Initial experiments on Linux 2.6 suggests that the symlink looks
81  *   like this:
82  *
83  *    3 -> /proc/18068/fd
84  *
85  *   e.g. not of much use.
86  *
87  *  - GDBus High-Level docs
88  *    - Proxy: properties, signals...
89  *    - Connection: IOStream based, ::close, connection setup steps
90  *                  mainloop integration, threading
91  *    - Differences from libdbus (extend "Migrating from")
92  *      - the message handling thread
93  *      - Using GVariant instead of GValue
94  *    - Explain why the high-level API is a good thing and what
95  *      kind of pitfalls it avoids
96  *      - Export objects before claiming names
97  *    - Talk about auto-starting services (cf. GBusNameWatcherFlags)
98  *
99  *  - Mention in all API that the GVariant is sunk. Also mention
100  *    when the returned GVariant is floating.
101  *
102  *  - Small example snippet for each method where useful (won't
103  *    have to compile) where it makes sense (e.g. connetion_call()
104  *    and using a floating GVariant).
105  *
106  *  - Consistent timeout handling (25s vs 30s?)
107  *
108  *  - GDBusProxy subclass example
109  *
110  *  - Update GDBusAuthObserver (is_same_user(), s/deny/authorize/)
111  */
112
113 #include "config.h"
114
115 #include <stdlib.h>
116 #include <string.h>
117
118 #include "gdbusauth.h"
119 #include "gdbusutils.h"
120 #include "gdbusaddress.h"
121 #include "gdbusmessage.h"
122 #include "gdbusconnection.h"
123 #include "gdbuserror.h"
124 #include "gioenumtypes.h"
125 #include "gdbusintrospection.h"
126 #include "gdbusmethodinvocation.h"
127 #include "gdbusprivate.h"
128 #include "gdbusauthobserver.h"
129 #include "gio-marshal.h"
130 #include "ginitable.h"
131 #include "gasyncinitable.h"
132 #include "giostream.h"
133 #include "gasyncresult.h"
134 #include "gsimpleasyncresult.h"
135
136 #ifdef G_OS_UNIX
137 #include <gio/gunixconnection.h>
138 #include <gio/gunixfdmessage.h>
139 #include <unistd.h>
140 #include <sys/types.h>
141 #endif
142
143 #include "glibintl.h"
144 #include "gioalias.h"
145
146 /**
147  * SECTION:gdbusconnection
148  * @short_description: D-Bus Connections
149  * @include: gio/gio.h
150  *
151  * The #GDBusConnection type is used for D-Bus connections to remote
152  * peers such as a message buses. It is a low-level API that offers a
153  * lot of flexibility. For instance, it lets you establish a connection
154  * over any transport that can by represented as an #GIOStream.
155  *
156  * This class is rarely used directly in D-Bus clients. If you are writing
157  * an D-Bus client, it is often easier to use the g_bus_own_name(),
158  * g_bus_watch_name() or g_bus_watch_proxy() APIs.
159  *
160  * <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>
161  *
162  * <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>
163  *
164  * <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>
165  */
166
167 /* ---------------------------------------------------------------------------------------------------- */
168
169 G_LOCK_DEFINE_STATIC (message_bus_lock);
170
171 static GDBusConnection *the_session_bus = NULL;
172 static GDBusConnection *the_system_bus = NULL;
173
174 /* ---------------------------------------------------------------------------------------------------- */
175
176 static gboolean
177 _g_strv_has_string (const gchar* const *haystack,
178                     const gchar        *needle)
179 {
180   guint n;
181
182   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
183     {
184       if (g_strcmp0 (haystack[n], needle) == 0)
185         return TRUE;
186     }
187   return FALSE;
188 }
189
190 /* ---------------------------------------------------------------------------------------------------- */
191
192 #ifdef G_OS_WIN32
193 #define CONNECTION_ENSURE_LOCK(obj) do { ; } while (FALSE)
194 #else
195 // TODO: for some reason this doesn't work on Windows
196 #define CONNECTION_ENSURE_LOCK(obj) do {                                \
197     if (G_UNLIKELY (g_mutex_trylock((obj)->priv->lock)))                \
198       {                                                                 \
199         g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
200                              "CONNECTION_ENSURE_LOCK: GDBusConnection object lock is not locked"); \
201       }                                                                 \
202   } while (FALSE)
203 #endif
204
205 #define CONNECTION_LOCK(obj) do {                                       \
206     g_mutex_lock ((obj)->priv->lock);                                   \
207   } while (FALSE)
208
209 #define CONNECTION_UNLOCK(obj) do {                                     \
210     g_mutex_unlock ((obj)->priv->lock);                                 \
211   } while (FALSE)
212
213 struct _GDBusConnectionPrivate
214 {
215   /* ------------------------------------------------------------------------ */
216   /* -- General object state ------------------------------------------------ */
217   /* ------------------------------------------------------------------------ */
218
219   /* object-wide lock */
220   GMutex *lock;
221
222   /* A lock used in the init() method of the GInitable interface - see comments
223    * in initable_init() for why a separate lock is needed
224    */
225   GMutex *init_lock;
226
227   /* Set (by loading the contents of /var/lib/dbus/machine-id) the first time
228    * someone calls org.freedesktop.DBus.GetMachineId()
229    */
230   gchar *machine_id;
231
232   /* The underlying stream used for communication */
233   GIOStream *stream;
234
235   /* The object used for authentication (if any) */
236   GDBusAuth *auth;
237
238   /* Set to TRUE if the connection has been closed */
239   gboolean closed;
240
241   /* Last serial used */
242   guint32 last_serial;
243
244   /* The object used to send/receive message */
245   GDBusWorker *worker;
246
247   /* If connected to a message bus, this contains the unique name assigned to
248    * us by the bus (e.g. ":1.42")
249    */
250   gchar *bus_unique_name;
251
252   /* The GUID returned by the other side if we authenticed as a client or
253    * the GUID to use if authenticating as a server
254    */
255   gchar *guid;
256
257   /* set to TRUE exactly when initable_init() has finished running */
258   gboolean is_initialized;
259
260   /* If the connection could not be established during initable_init(), this GError will set */
261   GError *initialization_error;
262
263   /* The result of g_main_context_get_thread_default() when the object
264    * was created (the GObject _init() function) - this is used for delivery
265    * of the :closed GObject signal.
266    */
267   GMainContext *main_context_at_construction;
268
269   /* construct properties */
270   gchar *address;
271   GDBusConnectionFlags flags;
272
273   /* Map used for managing method replies */
274   GHashTable *map_method_serial_to_send_message_data;  /* guint32 -> SendMessageData* */
275
276   /* Maps used for managing signal subscription */
277   GHashTable *map_rule_to_signal_data;          /* gchar* -> SignalData */
278   GHashTable *map_id_to_signal_data;            /* guint  -> SignalData */
279   GHashTable *map_sender_to_signal_data_array;  /* gchar* -> GPtrArray* of SignalData */
280
281   /* Maps used for managing exported objects and subtrees */
282   GHashTable *map_object_path_to_eo;  /* gchar* -> ExportedObject* */
283   GHashTable *map_id_to_ei;           /* guint  -> ExportedInterface* */
284   GHashTable *map_object_path_to_es;  /* gchar* -> ExportedSubtree* */
285   GHashTable *map_id_to_es;           /* guint  -> ExportedSubtree* */
286
287   /* Structure used for message filters */
288   GPtrArray *filters;
289
290   /* Whether to exit on close */
291   gboolean exit_on_close;
292
293   /* Capabilities negotiated during authentication */
294   GDBusCapabilityFlags capabilities;
295
296   GDBusAuthObserver *authentication_observer;
297   GCredentials *crendentials;
298 };
299
300 typedef struct ExportedObject ExportedObject;
301 static void exported_object_free (ExportedObject *eo);
302
303 typedef struct ExportedSubtree ExportedSubtree;
304 static void exported_subtree_free (ExportedSubtree *es);
305
306 enum
307 {
308   CLOSED_SIGNAL,
309   LAST_SIGNAL,
310 };
311
312 enum
313 {
314   PROP_0,
315   PROP_STREAM,
316   PROP_ADDRESS,
317   PROP_FLAGS,
318   PROP_GUID,
319   PROP_UNIQUE_NAME,
320   PROP_CLOSED,
321   PROP_EXIT_ON_CLOSE,
322   PROP_CAPABILITY_FLAGS,
323   PROP_AUTHENTICATION_OBSERVER,
324 };
325
326 static void distribute_signals (GDBusConnection  *connection,
327                                 GDBusMessage     *message);
328
329 static void distribute_method_call (GDBusConnection  *connection,
330                                     GDBusMessage     *message);
331
332 static gboolean handle_generic_unlocked (GDBusConnection *connection,
333                                          GDBusMessage    *message);
334
335
336 static void purge_all_signal_subscriptions (GDBusConnection *connection);
337 static void purge_all_filters (GDBusConnection *connection);
338
339 #define _G_ENSURE_LOCK(name) do {                                       \
340     if (G_UNLIKELY (G_TRYLOCK(name)))                                   \
341       {                                                                 \
342         g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
343                              "_G_ENSURE_LOCK: Lock `" #name "' is not locked"); \
344       }                                                                 \
345   } while (FALSE)                                                       \
346
347 static guint signals[LAST_SIGNAL] = { 0 };
348
349 static void initable_iface_init       (GInitableIface      *initable_iface);
350 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
351
352 G_DEFINE_TYPE_WITH_CODE (GDBusConnection, g_dbus_connection, G_TYPE_OBJECT,
353                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
354                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
355                          );
356
357 static void
358 g_dbus_connection_dispose (GObject *object)
359 {
360   GDBusConnection *connection = G_DBUS_CONNECTION (object);
361
362   G_LOCK (message_bus_lock);
363   //g_debug ("disposing %p", connection);
364   if (connection == the_session_bus)
365     {
366       the_session_bus = NULL;
367     }
368   else if (connection == the_system_bus)
369     {
370       the_system_bus = NULL;
371     }
372   if (connection->priv->worker != NULL)
373     {
374       _g_dbus_worker_stop (connection->priv->worker);
375       connection->priv->worker = NULL;
376     }
377   G_UNLOCK (message_bus_lock);
378
379   if (G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose != NULL)
380     G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose (object);
381 }
382
383 static void
384 g_dbus_connection_finalize (GObject *object)
385 {
386   GDBusConnection *connection = G_DBUS_CONNECTION (object);
387
388   if (connection->priv->authentication_observer != NULL)
389     g_object_unref (connection->priv->authentication_observer);
390
391   if (connection->priv->auth != NULL)
392     g_object_unref (connection->priv->auth);
393
394   //g_debug ("finalizing %p", connection);
395   if (connection->priv->stream != NULL)
396     {
397       /* We don't really care if closing the stream succeeds or not */
398       g_io_stream_close_async (connection->priv->stream,
399                                G_PRIORITY_DEFAULT,
400                                NULL,  /* GCancellable */
401                                NULL,  /* GAsyncReadyCallback */
402                                NULL); /* userdata */
403       g_object_unref (connection->priv->stream);
404       connection->priv->stream = NULL;
405     }
406
407   g_free (connection->priv->address);
408
409   g_free (connection->priv->guid);
410   g_free (connection->priv->bus_unique_name);
411
412   if (connection->priv->initialization_error != NULL)
413     g_error_free (connection->priv->initialization_error);
414
415   g_hash_table_unref (connection->priv->map_method_serial_to_send_message_data);
416
417   purge_all_signal_subscriptions (connection);
418   g_hash_table_unref (connection->priv->map_rule_to_signal_data);
419   g_hash_table_unref (connection->priv->map_id_to_signal_data);
420   g_hash_table_unref (connection->priv->map_sender_to_signal_data_array);
421
422   g_hash_table_unref (connection->priv->map_id_to_ei);
423   g_hash_table_unref (connection->priv->map_object_path_to_eo);
424   g_hash_table_unref (connection->priv->map_id_to_es);
425   g_hash_table_unref (connection->priv->map_object_path_to_es);
426
427   purge_all_filters (connection);
428   g_ptr_array_unref (connection->priv->filters);
429
430   if (connection->priv->main_context_at_construction != NULL)
431     g_main_context_unref (connection->priv->main_context_at_construction);
432
433   g_free (connection->priv->machine_id);
434
435   g_mutex_free (connection->priv->init_lock);
436   g_mutex_free (connection->priv->lock);
437
438   G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize (object);
439 }
440
441 static void
442 g_dbus_connection_get_property (GObject    *object,
443                                 guint       prop_id,
444                                 GValue     *value,
445                                 GParamSpec *pspec)
446 {
447   GDBusConnection *connection = G_DBUS_CONNECTION (object);
448
449   switch (prop_id)
450     {
451     case PROP_STREAM:
452       g_value_set_object (value, g_dbus_connection_get_stream (connection));
453       break;
454
455     case PROP_GUID:
456       g_value_set_string (value, g_dbus_connection_get_guid (connection));
457       break;
458
459     case PROP_UNIQUE_NAME:
460       g_value_set_string (value, g_dbus_connection_get_unique_name (connection));
461       break;
462
463     case PROP_CLOSED:
464       g_value_set_boolean (value, g_dbus_connection_is_closed (connection));
465       break;
466
467     case PROP_EXIT_ON_CLOSE:
468       g_value_set_boolean (value, g_dbus_connection_get_exit_on_close (connection));
469       break;
470
471     case PROP_CAPABILITY_FLAGS:
472       g_value_set_flags (value, g_dbus_connection_get_capabilities (connection));
473       break;
474
475     default:
476       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
477       break;
478     }
479 }
480
481 static void
482 g_dbus_connection_set_property (GObject      *object,
483                                 guint         prop_id,
484                                 const GValue *value,
485                                 GParamSpec   *pspec)
486 {
487   GDBusConnection *connection = G_DBUS_CONNECTION (object);
488
489   switch (prop_id)
490     {
491     case PROP_STREAM:
492       connection->priv->stream = g_value_dup_object (value);
493       break;
494
495     case PROP_GUID:
496       connection->priv->guid = g_value_dup_string (value);
497       break;
498
499     case PROP_ADDRESS:
500       connection->priv->address = g_value_dup_string (value);
501       break;
502
503     case PROP_FLAGS:
504       connection->priv->flags = g_value_get_flags (value);
505       break;
506
507     case PROP_EXIT_ON_CLOSE:
508       g_dbus_connection_set_exit_on_close (connection, g_value_get_boolean (value));
509       break;
510
511     case PROP_AUTHENTICATION_OBSERVER:
512       connection->priv->authentication_observer = g_value_dup_object (value);
513       break;
514
515     default:
516       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
517       break;
518     }
519 }
520
521 static void
522 g_dbus_connection_real_closed (GDBusConnection *connection,
523                                gboolean         remote_peer_vanished,
524                                GError          *error)
525 {
526   if (remote_peer_vanished && connection->priv->exit_on_close)
527     {
528       g_print ("%s: Remote peer vanished. Exiting.\n", G_STRFUNC);
529       raise (SIGTERM);
530     }
531 }
532
533 static void
534 g_dbus_connection_class_init (GDBusConnectionClass *klass)
535 {
536   GObjectClass *gobject_class;
537
538   g_type_class_add_private (klass, sizeof (GDBusConnectionPrivate));
539
540   gobject_class = G_OBJECT_CLASS (klass);
541
542   gobject_class->finalize     = g_dbus_connection_finalize;
543   gobject_class->dispose      = g_dbus_connection_dispose;
544   gobject_class->set_property = g_dbus_connection_set_property;
545   gobject_class->get_property = g_dbus_connection_get_property;
546
547   klass->closed = g_dbus_connection_real_closed;
548
549   /**
550    * GDBusConnection:stream:
551    *
552    * The underlying #GIOStream used for I/O.
553    *
554    * Since: 2.26
555    */
556   g_object_class_install_property (gobject_class,
557                                    PROP_STREAM,
558                                    g_param_spec_object ("stream",
559                                                         P_("IO Stream"),
560                                                         P_("The underlying streams used for I/O"),
561                                                         G_TYPE_IO_STREAM,
562                                                         G_PARAM_READABLE |
563                                                         G_PARAM_WRITABLE |
564                                                         G_PARAM_CONSTRUCT_ONLY |
565                                                         G_PARAM_STATIC_NAME |
566                                                         G_PARAM_STATIC_BLURB |
567                                                         G_PARAM_STATIC_NICK));
568
569   /**
570    * GDBusConnection:address:
571    *
572    * A D-Bus address specifying potential endpoints that can be used
573    * when establishing the connection.
574    *
575    * Since: 2.26
576    */
577   g_object_class_install_property (gobject_class,
578                                    PROP_ADDRESS,
579                                    g_param_spec_string ("address",
580                                                         P_("Address"),
581                                                         P_("D-Bus address specifying potential socket endpoints"),
582                                                         NULL,
583                                                         G_PARAM_WRITABLE |
584                                                         G_PARAM_CONSTRUCT_ONLY |
585                                                         G_PARAM_STATIC_NAME |
586                                                         G_PARAM_STATIC_BLURB |
587                                                         G_PARAM_STATIC_NICK));
588
589   /**
590    * GDBusConnection:flags:
591    *
592    * Flags from the #GDBusConnectionFlags enumeration.
593    *
594    * Since: 2.26
595    */
596   g_object_class_install_property (gobject_class,
597                                    PROP_FLAGS,
598                                    g_param_spec_flags ("flags",
599                                                        P_("Flags"),
600                                                        P_("Flags"),
601                                                        G_TYPE_DBUS_CONNECTION_FLAGS,
602                                                        G_DBUS_CONNECTION_FLAGS_NONE,
603                                                        G_PARAM_WRITABLE |
604                                                        G_PARAM_CONSTRUCT_ONLY |
605                                                        G_PARAM_STATIC_NAME |
606                                                        G_PARAM_STATIC_BLURB |
607                                                        G_PARAM_STATIC_NICK));
608
609   /**
610    * GDBusConnection:guid:
611    *
612    * The GUID of the peer performing the role of server when
613    * authenticating.
614    *
615    * If you are constructing a #GDBusConnection and pass
616    * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER in the
617    * #GDBusConnection:flags property then you MUST also set this
618    * property to a valid guid.
619    *
620    * If you are constructing a #GDBusConnection and pass
621    * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT in the
622    * #GDBusConnection:flags property you will be able to read the GUID
623    * of the other peer here after the connection has been successfully
624    * initialized.
625    *
626    * Since: 2.26
627    */
628   g_object_class_install_property (gobject_class,
629                                    PROP_GUID,
630                                    g_param_spec_string ("guid",
631                                                         P_("GUID"),
632                                                         P_("GUID of the server peer"),
633                                                         NULL,
634                                                         G_PARAM_READABLE |
635                                                         G_PARAM_WRITABLE |
636                                                         G_PARAM_CONSTRUCT_ONLY |
637                                                         G_PARAM_STATIC_NAME |
638                                                         G_PARAM_STATIC_BLURB |
639                                                         G_PARAM_STATIC_NICK));
640
641   /**
642    * GDBusConnection:unique-name:
643    *
644    * The unique name as assigned by the message bus or %NULL if the
645    * connection is not open or not a message bus connection.
646    *
647    * Since: 2.26
648    */
649   g_object_class_install_property (gobject_class,
650                                    PROP_UNIQUE_NAME,
651                                    g_param_spec_string ("unique-name",
652                                                         P_("unique-name"),
653                                                         P_("Unique name of bus connection"),
654                                                         NULL,
655                                                         G_PARAM_READABLE |
656                                                         G_PARAM_STATIC_NAME |
657                                                         G_PARAM_STATIC_BLURB |
658                                                         G_PARAM_STATIC_NICK));
659
660   /**
661    * GDBusConnection:closed:
662    *
663    * A boolean specifying whether the connection has been closed.
664    *
665    * Since: 2.26
666    */
667   g_object_class_install_property (gobject_class,
668                                    PROP_CLOSED,
669                                    g_param_spec_boolean ("closed",
670                                                          P_("Closed"),
671                                                          P_("Whether the connection is closed"),
672                                                          FALSE,
673                                                          G_PARAM_READABLE |
674                                                          G_PARAM_STATIC_NAME |
675                                                          G_PARAM_STATIC_BLURB |
676                                                          G_PARAM_STATIC_NICK));
677
678   /**
679    * GDBusConnection:exit-on-close:
680    *
681    * A boolean specifying whether the process will be terminated (by
682    * calling <literal>raise(SIGTERM)</literal>) if the connection
683    * is closed by the remote peer.
684    *
685    * Since: 2.26
686    */
687   g_object_class_install_property (gobject_class,
688                                    PROP_EXIT_ON_CLOSE,
689                                    g_param_spec_boolean ("exit-on-close",
690                                                          P_("Exit on close"),
691                                                          P_("Whether the process is terminated when the connection is closed"),
692                                                          FALSE,
693                                                          G_PARAM_READABLE |
694                                                          G_PARAM_WRITABLE |
695                                                          G_PARAM_STATIC_NAME |
696                                                          G_PARAM_STATIC_BLURB |
697                                                          G_PARAM_STATIC_NICK));
698
699   /**
700    * GDBusConnection:capabilities:
701    *
702    * Flags from the #GDBusCapabilityFlags enumeration
703    * representing connection features negotiated with the other peer.
704    *
705    * Since: 2.26
706    */
707   g_object_class_install_property (gobject_class,
708                                    PROP_CAPABILITY_FLAGS,
709                                    g_param_spec_flags ("capabilities",
710                                                        P_("Capabilities"),
711                                                        P_("Capabilities"),
712                                                        G_TYPE_DBUS_CAPABILITY_FLAGS,
713                                                        G_DBUS_CAPABILITY_FLAGS_NONE,
714                                                        G_PARAM_READABLE |
715                                                        G_PARAM_STATIC_NAME |
716                                                        G_PARAM_STATIC_BLURB |
717                                                        G_PARAM_STATIC_NICK));
718
719   /**
720    * GDBusConnection:authentication-observer:
721    *
722    * A #GDBusAuthObserver object to assist in the authentication process or %NULL.
723    *
724    * Since: 2.26
725    */
726   g_object_class_install_property (gobject_class,
727                                    PROP_AUTHENTICATION_OBSERVER,
728                                    g_param_spec_object ("authentication-observer",
729                                                         P_("Authentication Observer"),
730                                                         P_("Object used to assist in the authentication process"),
731                                                         G_TYPE_DBUS_AUTH_OBSERVER,
732                                                         G_PARAM_WRITABLE |
733                                                         G_PARAM_CONSTRUCT_ONLY |
734                                                         G_PARAM_STATIC_NAME |
735                                                         G_PARAM_STATIC_BLURB |
736                                                         G_PARAM_STATIC_NICK));
737
738   /**
739    * GDBusConnection::closed:
740    * @connection: The #GDBusConnection emitting the signal.
741    * @remote_peer_vanished: %TRUE if @connection is closed because the
742    * remote peer closed its end of the connection.
743    * @error: A #GError with more details about the event or %NULL.
744    *
745    * Emitted when the connection is closed.
746    *
747    * The cause of this event can be
748    * <itemizedlist>
749    * <listitem><para>
750    *    If g_dbus_connection_close() is called. In this case
751    *    @remote_peer_vanished is set to %FALSE and @error is %NULL.
752    * </para></listitem>
753    * <listitem><para>
754    *    If the remote peer closes the connection. In this case
755    *    @remote_peer_vanished is set to %TRUE and @error is set.
756    * </para></listitem>
757    * <listitem><para>
758    *    If the remote peer sends invalid or malformed data. In this
759    *    case @remote_peer_vanished is set to %FALSE and @error
760    *    is set.
761    * </para></listitem>
762    * </itemizedlist>
763    *
764    * Upon receiving this signal, you should give up your reference to
765    * @connection. You are guaranteed that this signal is emitted only
766    * once.
767    *
768    * Since: 2.26
769    */
770   signals[CLOSED_SIGNAL] = g_signal_new ("closed",
771                                          G_TYPE_DBUS_CONNECTION,
772                                          G_SIGNAL_RUN_LAST,
773                                          G_STRUCT_OFFSET (GDBusConnectionClass, closed),
774                                          NULL,
775                                          NULL,
776                                          _gio_marshal_VOID__BOOLEAN_BOXED,
777                                          G_TYPE_NONE,
778                                          2,
779                                          G_TYPE_BOOLEAN,
780                                          G_TYPE_ERROR);
781 }
782
783 static void
784 g_dbus_connection_init (GDBusConnection *connection)
785 {
786   connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection, G_TYPE_DBUS_CONNECTION, GDBusConnectionPrivate);
787
788   connection->priv->lock = g_mutex_new ();
789   connection->priv->init_lock = g_mutex_new ();
790
791   connection->priv->map_method_serial_to_send_message_data = g_hash_table_new (g_direct_hash, g_direct_equal);
792
793   connection->priv->map_rule_to_signal_data = g_hash_table_new (g_str_hash,
794                                                                 g_str_equal);
795   connection->priv->map_id_to_signal_data = g_hash_table_new (g_direct_hash,
796                                                               g_direct_equal);
797   connection->priv->map_sender_to_signal_data_array = g_hash_table_new_full (g_str_hash,
798                                                                              g_str_equal,
799                                                                              g_free,
800                                                                              NULL);
801
802   connection->priv->map_object_path_to_eo = g_hash_table_new_full (g_str_hash,
803                                                                    g_str_equal,
804                                                                    NULL,
805                                                                    (GDestroyNotify) exported_object_free);
806
807   connection->priv->map_id_to_ei = g_hash_table_new (g_direct_hash,
808                                                      g_direct_equal);
809
810   connection->priv->map_object_path_to_es = g_hash_table_new_full (g_str_hash,
811                                                                    g_str_equal,
812                                                                    NULL,
813                                                                    (GDestroyNotify) exported_subtree_free);
814
815   connection->priv->map_id_to_es = g_hash_table_new (g_direct_hash,
816                                                      g_direct_equal);
817
818   connection->priv->main_context_at_construction = g_main_context_get_thread_default ();
819   if (connection->priv->main_context_at_construction != NULL)
820     g_main_context_ref (connection->priv->main_context_at_construction);
821
822   connection->priv->filters = g_ptr_array_new ();
823 }
824
825 /**
826  * g_dbus_connection_get_stream:
827  * @connection: a #GDBusConnection
828  *
829  * Gets the underlying stream used for IO.
830  *
831  * Returns: the stream used for IO
832  *
833  * Since: 2.26
834  */
835 GIOStream *
836 g_dbus_connection_get_stream (GDBusConnection *connection)
837 {
838   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
839   return connection->priv->stream;
840 }
841
842
843 /**
844  * g_dbus_connection_is_closed:
845  * @connection: A #GDBusConnection.
846  *
847  * Gets whether @connection is closed.
848  *
849  * Returns: %TRUE if the connection is closed, %FALSE otherwise.
850  *
851  * Since: 2.26
852  */
853 gboolean
854 g_dbus_connection_is_closed (GDBusConnection *connection)
855 {
856   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
857   return connection->priv->closed;
858 }
859
860 /**
861  * g_dbus_connection_get_capabilities:
862  * @connection: A #GDBusConnection.
863  *
864  * Gets the capabilities negotiated with the remote peer
865  *
866  * Returns: Zero or more flags from the #GDBusCapabilityFlags enumeration.
867  *
868  * Since: 2.26
869  */
870 GDBusCapabilityFlags
871 g_dbus_connection_get_capabilities (GDBusConnection *connection)
872 {
873   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_DBUS_CAPABILITY_FLAGS_NONE);
874   return connection->priv->capabilities;
875 }
876
877
878 /* ---------------------------------------------------------------------------------------------------- */
879
880 typedef struct
881 {
882   GDBusConnection *connection;
883   GError *error;
884   gboolean remote_peer_vanished;
885 } EmitClosedData;
886
887 static void
888 emit_closed_data_free (EmitClosedData *data)
889 {
890   g_object_unref (data->connection);
891   if (data->error != NULL)
892     g_error_free (data->error);
893   g_free (data);
894 }
895
896 static gboolean
897 emit_closed_in_idle (gpointer user_data)
898 {
899   EmitClosedData *data = user_data;
900   gboolean result;
901
902   g_object_notify (G_OBJECT (data->connection), "closed");
903   g_signal_emit (data->connection,
904                  signals[CLOSED_SIGNAL],
905                  0,
906                  data->remote_peer_vanished,
907                  data->error,
908                  &result);
909   return FALSE;
910 }
911
912 /* Can be called from any thread, must hold lock */
913 static void
914 set_closed_unlocked (GDBusConnection *connection,
915                      gboolean         remote_peer_vanished,
916                      GError          *error)
917 {
918   GSource *idle_source;
919   EmitClosedData *data;
920
921   CONNECTION_ENSURE_LOCK (connection);
922
923   g_assert (!connection->priv->closed);
924
925   connection->priv->closed = TRUE;
926
927   data = g_new0 (EmitClosedData, 1);
928   data->connection = g_object_ref (connection);
929   data->remote_peer_vanished = remote_peer_vanished;
930   data->error = error != NULL ? g_error_copy (error) : NULL;
931
932   idle_source = g_idle_source_new ();
933   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
934   g_source_set_callback (idle_source,
935                          emit_closed_in_idle,
936                          data,
937                          (GDestroyNotify) emit_closed_data_free);
938   g_source_attach (idle_source, connection->priv->main_context_at_construction);
939   g_source_unref (idle_source);
940 }
941
942 /* ---------------------------------------------------------------------------------------------------- */
943
944 /**
945  * g_dbus_connection_close:
946  * @connection: A #GDBusConnection.
947  *
948  * Closes @connection. Note that this never causes the process to
949  * exit (this might only happen if the other end of a shared message
950  * bus connection disconnects).
951  *
952  * If @connection is already closed, this method does nothing.
953  *
954  * Since: 2.26
955  */
956 void
957 g_dbus_connection_close (GDBusConnection *connection)
958 {
959   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
960
961   CONNECTION_LOCK (connection);
962   if (!connection->priv->closed)
963     {
964       GError *error = NULL;
965
966       /* TODO: do this async */
967       //g_debug ("closing connection %p's stream %p", connection, connection->priv->stream);
968       if (!g_io_stream_close (connection->priv->stream, NULL, &error))
969         {
970           g_warning ("Error closing stream: %s", error->message);
971           g_error_free (error);
972         }
973
974       set_closed_unlocked (connection, FALSE, NULL);
975     }
976   CONNECTION_UNLOCK (connection);
977 }
978
979 /* ---------------------------------------------------------------------------------------------------- */
980
981 static gboolean
982 g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
983                                          GDBusMessage      *message,
984                                          volatile guint32  *out_serial,
985                                          GError           **error)
986 {
987   guchar *blob;
988   gsize blob_size;
989   guint32 serial_to_use;
990   gboolean ret;
991
992   CONNECTION_ENSURE_LOCK (connection);
993
994   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
995   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
996
997   /* TODO: check all necessary headers are present */
998
999   ret = FALSE;
1000   blob = NULL;
1001
1002   if (out_serial != NULL)
1003     *out_serial = 0;
1004
1005   if (connection->priv->closed)
1006     {
1007       g_set_error_literal (error,
1008                            G_IO_ERROR,
1009                            G_IO_ERROR_CLOSED,
1010                            _("The connection is closed"));
1011       goto out;
1012     }
1013
1014   blob = g_dbus_message_to_blob (message,
1015                                  &blob_size,
1016                                  error);
1017   if (blob == NULL)
1018     goto out;
1019
1020   serial_to_use = ++connection->priv->last_serial; /* TODO: handle overflow */
1021
1022   switch (blob[0])
1023     {
1024     case 'l':
1025       ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
1026       break;
1027     case 'B':
1028       ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
1029       break;
1030     default:
1031       g_assert_not_reached ();
1032       break;
1033     }
1034
1035 #if 0
1036   g_printerr ("Writing message of %" G_GSIZE_FORMAT " bytes (serial %d) on %p:\n",
1037               blob_size, serial_to_use, connection);
1038   g_printerr ("----\n");
1039   hexdump (blob, blob_size);
1040   g_printerr ("----\n");
1041 #endif
1042
1043   /* TODO: use connection->priv->auth to encode the blob */
1044
1045   if (out_serial != NULL)
1046     *out_serial = serial_to_use;
1047
1048   g_dbus_message_set_serial (message, serial_to_use);
1049
1050   _g_dbus_worker_send_message (connection->priv->worker,
1051                                message,
1052                                (gchar*) blob,
1053                                blob_size);
1054   blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
1055
1056   ret = TRUE;
1057
1058  out:
1059   g_free (blob);
1060
1061   return ret;
1062 }
1063
1064 /**
1065  * g_dbus_connection_send_message:
1066  * @connection: A #GDBusConnection.
1067  * @message: A #GDBusMessage
1068  * @out_serial: Return location for serial number assigned to @message when sending it or %NULL.
1069  * @error: Return location for error or %NULL.
1070  *
1071  * Asynchronously sends @message to the peer represented by @connection.
1072  *
1073  * If @out_serial is not %NULL, then the serial number assigned to
1074  * @message by @connection will be written to this location prior to
1075  * submitting the message to the underlying transport.
1076  *
1077  * If @connection is closed then the operation will fail with
1078  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
1079  * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
1080  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1081  *
1082  * See <xref linkend="gdbus-server"/> and <xref
1083  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1084  * low-level API to send and receive UNIX file descriptors.
1085  *
1086  * Returns: %TRUE if the message was well-formed and queued for
1087  * transmission, %FALSE if @error is set.
1088  *
1089  * Since: 2.26
1090  */
1091 gboolean
1092 g_dbus_connection_send_message (GDBusConnection   *connection,
1093                                 GDBusMessage      *message,
1094                                 volatile guint32  *out_serial,
1095                                 GError           **error)
1096 {
1097   gboolean ret;
1098
1099   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1100   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1101   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1102
1103   CONNECTION_LOCK (connection);
1104   ret = g_dbus_connection_send_message_unlocked (connection, message, out_serial, error);
1105   CONNECTION_UNLOCK (connection);
1106   return ret;
1107 }
1108
1109 /* ---------------------------------------------------------------------------------------------------- */
1110
1111 typedef struct
1112 {
1113   volatile gint ref_count;
1114   GDBusConnection *connection;
1115   guint32 serial;
1116   GSimpleAsyncResult *simple;
1117
1118   GMainContext *main_context;
1119
1120   GCancellable *cancellable;
1121
1122   gulong cancellable_handler_id;
1123
1124   GSource *timeout_source;
1125
1126   gboolean delivered;
1127 } SendMessageData;
1128
1129 static SendMessageData *
1130 send_message_data_ref (SendMessageData *data)
1131 {
1132   g_atomic_int_inc (&data->ref_count);
1133   return data;
1134 }
1135
1136 static void
1137 send_message_data_unref (SendMessageData *data)
1138 {
1139   if (g_atomic_int_dec_and_test (&data->ref_count))
1140     {
1141       g_assert (data->timeout_source == NULL);
1142       g_assert (data->simple == NULL);
1143       g_assert (data->cancellable_handler_id == 0);
1144       g_object_unref (data->connection);
1145       if (data->cancellable != NULL)
1146         g_object_unref (data->cancellable);
1147       if (data->main_context != NULL)
1148         g_main_context_unref (data->main_context);
1149       g_free (data);
1150     }
1151 }
1152
1153 /* ---------------------------------------------------------------------------------------------------- */
1154
1155 /* can be called from any thread with lock held - caller must have prepared GSimpleAsyncResult already */
1156 static void
1157 send_message_with_reply_deliver (SendMessageData *data)
1158 {
1159   CONNECTION_ENSURE_LOCK (data->connection);
1160
1161   g_assert (!data->delivered);
1162
1163   data->delivered = TRUE;
1164
1165   g_simple_async_result_complete_in_idle (data->simple);
1166   g_object_unref (data->simple);
1167   data->simple = NULL;
1168
1169   if (data->timeout_source != NULL)
1170     {
1171       g_source_destroy (data->timeout_source);
1172       data->timeout_source = NULL;
1173     }
1174   if (data->cancellable_handler_id > 0)
1175     {
1176       g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
1177       data->cancellable_handler_id = 0;
1178     }
1179
1180   g_warn_if_fail (g_hash_table_remove (data->connection->priv->map_method_serial_to_send_message_data,
1181                                        GUINT_TO_POINTER (data->serial)));
1182
1183   send_message_data_unref (data);
1184 }
1185
1186 /* ---------------------------------------------------------------------------------------------------- */
1187
1188 /* must hold lock */
1189 static void
1190 send_message_data_deliver_reply_unlocked (SendMessageData *data,
1191                                           GDBusMessage    *reply)
1192 {
1193   if (data->delivered)
1194     goto out;
1195
1196   g_simple_async_result_set_op_res_gpointer (data->simple,
1197                                              g_object_ref (reply),
1198                                              g_object_unref);
1199
1200   send_message_with_reply_deliver (data);
1201
1202  out:
1203   ;
1204 }
1205
1206 /* ---------------------------------------------------------------------------------------------------- */
1207
1208 static gboolean
1209 send_message_with_reply_cancelled_idle_cb (gpointer user_data)
1210 {
1211   SendMessageData *data = user_data;
1212
1213   CONNECTION_LOCK (data->connection);
1214   if (data->delivered)
1215     goto out;
1216
1217   g_simple_async_result_set_error (data->simple,
1218                                    G_IO_ERROR,
1219                                    G_IO_ERROR_CANCELLED,
1220                                    _("Operation was cancelled"));
1221
1222   send_message_with_reply_deliver (data);
1223
1224  out:
1225   CONNECTION_UNLOCK (data->connection);
1226   return FALSE;
1227 }
1228
1229 /* Can be called from any thread with or without lock held */
1230 static void
1231 send_message_with_reply_cancelled_cb (GCancellable *cancellable,
1232                                       gpointer      user_data)
1233 {
1234   SendMessageData *data = user_data;
1235   GSource *idle_source;
1236
1237   /* postpone cancellation to idle handler since we may be called directly
1238    * via g_cancellable_connect() (e.g. holding lock)
1239    */
1240   idle_source = g_idle_source_new ();
1241   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
1242   g_source_set_callback (idle_source,
1243                          send_message_with_reply_cancelled_idle_cb,
1244                          send_message_data_ref (data),
1245                          (GDestroyNotify) send_message_data_unref);
1246   g_source_attach (idle_source, data->main_context);
1247   g_source_unref (idle_source);
1248 }
1249
1250 /* ---------------------------------------------------------------------------------------------------- */
1251
1252 static gboolean
1253 send_message_with_reply_timeout_cb (gpointer user_data)
1254 {
1255   SendMessageData *data = user_data;
1256
1257   CONNECTION_LOCK (data->connection);
1258   if (data->delivered)
1259     goto out;
1260
1261   g_simple_async_result_set_error (data->simple,
1262                                    G_IO_ERROR,
1263                                    G_IO_ERROR_TIMED_OUT,
1264                                    _("Timeout was reached"));
1265
1266   send_message_with_reply_deliver (data);
1267
1268  out:
1269   CONNECTION_UNLOCK (data->connection);
1270
1271   return FALSE;
1272 }
1273
1274 /* ---------------------------------------------------------------------------------------------------- */
1275
1276 static void
1277 g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connection,
1278                                                     GDBusMessage        *message,
1279                                                     gint                 timeout_msec,
1280                                                     volatile guint32    *out_serial,
1281                                                     GCancellable        *cancellable,
1282                                                     GAsyncReadyCallback  callback,
1283                                                     gpointer             user_data)
1284 {
1285   GSimpleAsyncResult *simple;
1286   SendMessageData *data;
1287   GError *error;
1288   volatile guint32 serial;
1289
1290   data = NULL;
1291
1292   if (out_serial == NULL)
1293     out_serial = &serial;
1294
1295   if (timeout_msec == -1)
1296     timeout_msec = 30 * 1000; /* TODO: check 30 secs is the default timeout */
1297
1298   simple = g_simple_async_result_new (G_OBJECT (connection),
1299                                       callback,
1300                                       user_data,
1301                                       g_dbus_connection_send_message_with_reply);
1302
1303   if (g_cancellable_is_cancelled (cancellable))
1304     {
1305       g_simple_async_result_set_error (simple,
1306                                        G_IO_ERROR,
1307                                        G_IO_ERROR_CANCELLED,
1308                                        _("Operation was cancelled"));
1309       g_simple_async_result_complete_in_idle (simple);
1310       g_object_unref (simple);
1311       goto out;
1312     }
1313
1314   if (connection->priv->closed)
1315     {
1316       g_simple_async_result_set_error (simple,
1317                                        G_IO_ERROR,
1318                                        G_IO_ERROR_CLOSED,
1319                                        _("The connection is closed"));
1320       g_simple_async_result_complete_in_idle (simple);
1321       g_object_unref (simple);
1322       goto out;
1323     }
1324
1325   error = NULL;
1326   if (!g_dbus_connection_send_message_unlocked (connection, message, out_serial, &error))
1327     {
1328       g_simple_async_result_set_from_error (simple, error);
1329       g_simple_async_result_complete_in_idle (simple);
1330       g_object_unref (simple);
1331       goto out;
1332     }
1333
1334   data = g_new0 (SendMessageData, 1);
1335   data->ref_count = 1;
1336   data->connection = g_object_ref (connection);
1337   data->simple = simple;
1338   data->serial = *out_serial;
1339   data->main_context = g_main_context_get_thread_default ();
1340   if (data->main_context != NULL)
1341     g_main_context_ref (data->main_context);
1342
1343   if (cancellable != NULL)
1344     {
1345       data->cancellable = g_object_ref (cancellable);
1346       data->cancellable_handler_id = g_cancellable_connect (cancellable,
1347                                                             G_CALLBACK (send_message_with_reply_cancelled_cb),
1348                                                             send_message_data_ref (data),
1349                                                             (GDestroyNotify) send_message_data_unref);
1350       g_object_set_data_full (G_OBJECT (simple),
1351                               "cancellable",
1352                               g_object_ref (cancellable),
1353                               (GDestroyNotify) g_object_unref);
1354     }
1355
1356   data->timeout_source = g_timeout_source_new (timeout_msec);
1357   g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
1358   g_source_set_callback (data->timeout_source,
1359                          send_message_with_reply_timeout_cb,
1360                          send_message_data_ref (data),
1361                          (GDestroyNotify) send_message_data_unref);
1362   g_source_attach (data->timeout_source, data->main_context);
1363   g_source_unref (data->timeout_source);
1364
1365   g_hash_table_insert (connection->priv->map_method_serial_to_send_message_data,
1366                        GUINT_TO_POINTER (*out_serial),
1367                        data);
1368
1369  out:
1370   ;
1371 }
1372
1373 /**
1374  * g_dbus_connection_send_message_with_reply:
1375  * @connection: A #GDBusConnection.
1376  * @message: A #GDBusMessage.
1377  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
1378  * @out_serial: Return location for serial number assigned to @message when sending it or %NULL.
1379  * @cancellable: A #GCancellable or %NULL.
1380  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
1381  * care about the result.
1382  * @user_data: The data to pass to @callback.
1383  *
1384  * Asynchronously sends @message to the peer represented by @connection.
1385  *
1386  * If @out_serial is not %NULL, then the serial number assigned to
1387  * @message by @connection will be written to this location prior to
1388  * submitting the message to the underlying transport.
1389  *
1390  * If @connection is closed then the operation will fail with
1391  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
1392  * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
1393  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1394  *
1395  * This is an asynchronous method. When the operation is finished, @callback will be invoked
1396  * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
1397  * of the thread you are calling this method from. You can then call
1398  * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
1399  * See g_dbus_connection_send_message_with_reply_sync() for the synchronous version.
1400  *
1401  * See <xref linkend="gdbus-server"/> and <xref
1402  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1403  * low-level API to send and receive UNIX file descriptors.
1404  *
1405  * Since: 2.26
1406  */
1407 void
1408 g_dbus_connection_send_message_with_reply (GDBusConnection     *connection,
1409                                            GDBusMessage        *message,
1410                                            gint                 timeout_msec,
1411                                            volatile guint32    *out_serial,
1412                                            GCancellable        *cancellable,
1413                                            GAsyncReadyCallback  callback,
1414                                            gpointer             user_data)
1415 {
1416   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1417   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1418   g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
1419
1420   CONNECTION_LOCK (connection);
1421   g_dbus_connection_send_message_with_reply_unlocked (connection,
1422                                                       message,
1423                                                       timeout_msec,
1424                                                       out_serial,
1425                                                       cancellable,
1426                                                       callback,
1427                                                       user_data);
1428   CONNECTION_UNLOCK (connection);
1429 }
1430
1431 /**
1432  * g_dbus_connection_send_message_with_reply_finish:
1433  * @connection: a #GDBusConnection
1434  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_send_message_with_reply().
1435  * @error: Return location for error or %NULL.
1436  *
1437  * Finishes an operation started with g_dbus_connection_send_message_with_reply().
1438  *
1439  * Note that @error is only set if a local in-process error
1440  * occured. That is to say that the returned #GDBusMessage object may
1441  * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
1442  * g_dbus_message_to_gerror() to transcode this to a #GError.
1443  *
1444  * See <xref linkend="gdbus-server"/> and <xref
1445  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1446  * low-level API to send and receive UNIX file descriptors.
1447  *
1448  * Returns: A #GDBusMessage or %NULL if @error is set.
1449  *
1450  * Since: 2.26
1451  */
1452 GDBusMessage *
1453 g_dbus_connection_send_message_with_reply_finish (GDBusConnection  *connection,
1454                                                   GAsyncResult     *res,
1455                                                   GError          **error)
1456 {
1457   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1458   GDBusMessage *reply;
1459   GCancellable *cancellable;
1460
1461   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1462   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1463
1464   reply = NULL;
1465
1466   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_send_message_with_reply);
1467
1468   if (g_simple_async_result_propagate_error (simple, error))
1469     goto out;
1470
1471   reply = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
1472   cancellable = g_object_get_data (G_OBJECT (simple), "cancellable");
1473   if (cancellable != NULL && g_cancellable_is_cancelled (cancellable))
1474     {
1475       g_object_unref (reply);
1476       reply = NULL;
1477       g_set_error_literal (error,
1478                            G_IO_ERROR,
1479                            G_IO_ERROR_CANCELLED,
1480                            _("Operation was cancelled"));
1481     }
1482  out:
1483   return reply;
1484 }
1485
1486 /* ---------------------------------------------------------------------------------------------------- */
1487
1488 typedef struct
1489 {
1490   GAsyncResult *res;
1491   GMainContext *context;
1492   GMainLoop *loop;
1493 } SendMessageSyncData;
1494
1495 static void
1496 send_message_with_reply_sync_cb (GDBusConnection *connection,
1497                                  GAsyncResult    *res,
1498                                  gpointer         user_data)
1499 {
1500   SendMessageSyncData *data = user_data;
1501   data->res = g_object_ref (res);
1502   g_main_loop_quit (data->loop);
1503 }
1504
1505 /**
1506  * g_dbus_connection_send_message_with_reply_sync:
1507  * @connection: A #GDBusConnection.
1508  * @message: A #GDBusMessage.
1509  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
1510  * @out_serial: Return location for serial number assigned to @message when sending it or %NULL.
1511  * @cancellable: A #GCancellable or %NULL.
1512  * @error: Return location for error or %NULL.
1513  *
1514  * Synchronously sends @message to the peer represented by @connection
1515  * and blocks the calling thread until a reply is received or the
1516  * timeout is reached. See g_dbus_connection_send_message_with_reply()
1517  * for the asynchronous version of this method.
1518  *
1519  * If @out_serial is not %NULL, then the serial number assigned to
1520  * @message by @connection will be written to this location prior to
1521  * submitting the message to the underlying transport.
1522  *
1523  * If @connection is closed then the operation will fail with
1524  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
1525  * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
1526  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1527  *
1528  * Note that @error is only set if a local in-process error
1529  * occured. That is to say that the returned #GDBusMessage object may
1530  * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
1531  * g_dbus_message_to_gerror() to transcode this to a #GError.
1532  *
1533  * See <xref linkend="gdbus-server"/> and <xref
1534  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
1535  * low-level API to send and receive UNIX file descriptors.
1536  *
1537  * Returns: A #GDBusMessage that is the reply to @message or %NULL if @error is set.
1538  *
1539  * Since: 2.26
1540  */
1541 GDBusMessage *
1542 g_dbus_connection_send_message_with_reply_sync (GDBusConnection   *connection,
1543                                                 GDBusMessage      *message,
1544                                                 gint               timeout_msec,
1545                                                 volatile guint32  *out_serial,
1546                                                 GCancellable      *cancellable,
1547                                                 GError           **error)
1548 {
1549   SendMessageSyncData *data;
1550   GDBusMessage *reply;
1551
1552   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1553   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1554   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
1555   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1556
1557   data = g_new0 (SendMessageSyncData, 1);
1558   data->context = g_main_context_new ();
1559   data->loop = g_main_loop_new (data->context, FALSE);
1560
1561   g_main_context_push_thread_default (data->context);
1562
1563   g_dbus_connection_send_message_with_reply (connection,
1564                                              message,
1565                                              timeout_msec,
1566                                              out_serial,
1567                                              cancellable,
1568                                              (GAsyncReadyCallback) send_message_with_reply_sync_cb,
1569                                              data);
1570   g_main_loop_run (data->loop);
1571   reply = g_dbus_connection_send_message_with_reply_finish (connection,
1572                                                             data->res,
1573                                                             error);
1574
1575   g_main_context_pop_thread_default (data->context);
1576
1577   g_main_context_unref (data->context);
1578   g_main_loop_unref (data->loop);
1579   g_object_unref (data->res);
1580   g_free (data);
1581
1582   return reply;
1583 }
1584
1585 /* ---------------------------------------------------------------------------------------------------- */
1586
1587 typedef struct
1588 {
1589   GDBusMessageFilterFunction func;
1590   gpointer user_data;
1591 } FilterCallback;
1592
1593 typedef struct
1594 {
1595   guint                       id;
1596   GDBusMessageFilterFunction  filter_function;
1597   gpointer                    user_data;
1598   GDestroyNotify              user_data_free_func;
1599 } FilterData;
1600
1601 /* Called in worker's thread - we must not block */
1602 static void
1603 on_worker_message_received (GDBusWorker  *worker,
1604                             GDBusMessage *message,
1605                             gpointer      user_data)
1606 {
1607   GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
1608   FilterCallback *filters;
1609   gboolean consumed_by_filter;
1610   guint num_filters;
1611   guint n;
1612
1613   //g_debug ("in on_worker_message_received");
1614
1615   g_object_ref (connection);
1616
1617   /* First collect the set of callback functions */
1618   CONNECTION_LOCK (connection);
1619   num_filters = connection->priv->filters->len;
1620   filters = g_new0 (FilterCallback, num_filters);
1621   for (n = 0; n < num_filters; n++)
1622     {
1623       FilterData *data = connection->priv->filters->pdata[n];
1624       filters[n].func = data->filter_function;
1625       filters[n].user_data = data->user_data;
1626     }
1627   CONNECTION_UNLOCK (connection);
1628
1629   /* the call the filters in order (without holding the lock) */
1630   consumed_by_filter = FALSE;
1631   for (n = 0; n < num_filters; n++)
1632     {
1633       consumed_by_filter = filters[n].func (connection,
1634                                             message,
1635                                             filters[n].user_data);
1636       if (consumed_by_filter)
1637         break;
1638     }
1639
1640   /* Standard dispatch unless the filter ate the message */
1641   if (!consumed_by_filter)
1642     {
1643       GDBusMessageType message_type;
1644
1645       message_type = g_dbus_message_get_message_type (message);
1646       if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN || message_type == G_DBUS_MESSAGE_TYPE_ERROR)
1647         {
1648           guint32 reply_serial;
1649           SendMessageData *send_message_data;
1650
1651           reply_serial = g_dbus_message_get_reply_serial (message);
1652           CONNECTION_LOCK (connection);
1653           send_message_data = g_hash_table_lookup (connection->priv->map_method_serial_to_send_message_data,
1654                                                    GUINT_TO_POINTER (reply_serial));
1655           if (send_message_data != NULL)
1656             {
1657               //g_debug ("delivering reply/error for serial %d for %p", reply_serial, connection);
1658               send_message_data_deliver_reply_unlocked (send_message_data, message);
1659             }
1660           else
1661             {
1662               //g_debug ("message reply/error for serial %d but no SendMessageData found for %p", reply_serial, connection);
1663             }
1664           CONNECTION_UNLOCK (connection);
1665         }
1666       else if (message_type == G_DBUS_MESSAGE_TYPE_SIGNAL)
1667         {
1668           CONNECTION_LOCK (connection);
1669           distribute_signals (connection, message);
1670           CONNECTION_UNLOCK (connection);
1671         }
1672       else if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
1673         {
1674           CONNECTION_LOCK (connection);
1675           distribute_method_call (connection, message);
1676           CONNECTION_UNLOCK (connection);
1677         }
1678     }
1679
1680   g_object_unref (connection);
1681   g_free (filters);
1682 }
1683
1684 /* Called in worker's thread - we must not block */
1685 static void
1686 on_worker_closed (GDBusWorker *worker,
1687                   gboolean     remote_peer_vanished,
1688                   GError      *error,
1689                   gpointer     user_data)
1690 {
1691   GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
1692
1693   //g_debug ("in on_worker_closed: %s", error->message);
1694
1695   CONNECTION_LOCK (connection);
1696   if (!connection->priv->closed)
1697     set_closed_unlocked (connection, remote_peer_vanished, error);
1698   CONNECTION_UNLOCK (connection);
1699 }
1700
1701 /* ---------------------------------------------------------------------------------------------------- */
1702
1703 /* Determines the biggest set of capabilities we can support on this connection */
1704 static GDBusCapabilityFlags
1705 get_offered_capabilities_max (GDBusConnection *connection)
1706 {
1707       GDBusCapabilityFlags ret;
1708       ret = G_DBUS_CAPABILITY_FLAGS_NONE;
1709 #ifdef G_OS_UNIX
1710       if (G_IS_UNIX_CONNECTION (connection->priv->stream))
1711         ret |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
1712 #endif
1713       return ret;
1714 }
1715
1716 static gboolean
1717 initable_init (GInitable     *initable,
1718                GCancellable  *cancellable,
1719                GError       **error)
1720 {
1721   GDBusConnection *connection = G_DBUS_CONNECTION (initable);
1722   gboolean ret;
1723
1724   /* This method needs to be idempotent to work with the singleton
1725    * pattern. See the docs for g_initable_init(). We implement this by
1726    * locking.
1727    *
1728    * Unfortunately we can't use the main lock since the on_worker_*()
1729    * callbacks above needs the lock during initialization (for message
1730    * bus connections we do a synchronous Hello() call on the bus).
1731    */
1732   g_mutex_lock (connection->priv->init_lock);
1733
1734   ret = FALSE;
1735
1736   if (connection->priv->is_initialized)
1737     {
1738       if (connection->priv->stream != NULL)
1739         ret = TRUE;
1740       else
1741         g_assert (connection->priv->initialization_error != NULL);
1742       goto out;
1743     }
1744   g_assert (connection->priv->initialization_error == NULL);
1745
1746   /* The user can pass multiple (but mutally exclusive) construct
1747    * properties:
1748    *
1749    *  - stream (of type GIOStream)
1750    *  - address (of type gchar*)
1751    *
1752    * At the end of the day we end up with a non-NULL GIOStream
1753    * object in connection->priv->stream.
1754    */
1755   if (connection->priv->address != NULL)
1756     {
1757       g_assert (connection->priv->stream == NULL);
1758
1759       if ((connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
1760           (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS))
1761         {
1762           g_set_error_literal (error,
1763                                G_IO_ERROR,
1764                                G_IO_ERROR_INVALID_ARGUMENT,
1765                                _("Unsupported flags encountered when constructing a client-side connection"));
1766           goto out;
1767         }
1768
1769       connection->priv->stream = g_dbus_address_get_stream_sync (connection->priv->address,
1770                                                                  NULL, /* TODO: out_guid */
1771                                                                  cancellable,
1772                                                                  &connection->priv->initialization_error);
1773       if (connection->priv->stream == NULL)
1774         goto out;
1775     }
1776   else if (connection->priv->stream != NULL)
1777     {
1778       /* nothing to do */
1779     }
1780   else
1781     {
1782       g_assert_not_reached ();
1783     }
1784
1785   /* Authenticate the connection */
1786   if (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
1787     {
1788       g_assert (!(connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT));
1789       g_assert (connection->priv->guid != NULL);
1790       connection->priv->auth = _g_dbus_auth_new (connection->priv->stream);
1791       if (!_g_dbus_auth_run_server (connection->priv->auth,
1792                                     connection->priv->authentication_observer,
1793                                     connection->priv->guid,
1794                                     (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS),
1795                                     get_offered_capabilities_max (connection),
1796                                     &connection->priv->capabilities,
1797                                     &connection->priv->crendentials,
1798                                     cancellable,
1799                                     &connection->priv->initialization_error))
1800         goto out;
1801     }
1802   else if (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT)
1803     {
1804       g_assert (!(connection->priv->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER));
1805       g_assert (connection->priv->guid == NULL);
1806       connection->priv->auth = _g_dbus_auth_new (connection->priv->stream);
1807       connection->priv->guid = _g_dbus_auth_run_client (connection->priv->auth,
1808                                                         get_offered_capabilities_max (connection),
1809                                                         &connection->priv->capabilities,
1810                                                         cancellable,
1811                                                         &connection->priv->initialization_error);
1812       if (connection->priv->guid == NULL)
1813         goto out;
1814     }
1815
1816   if (connection->priv->authentication_observer != NULL)
1817     {
1818       g_object_unref (connection->priv->authentication_observer);
1819       connection->priv->authentication_observer = NULL;
1820     }
1821
1822   //g_output_stream_flush (G_SOCKET_CONNECTION (connection->priv->stream)
1823
1824   //g_debug ("haz unix fd passing powers: %d", connection->priv->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
1825
1826   /* Hack used until
1827    *
1828    *  https://bugzilla.gnome.org/show_bug.cgi?id=616458
1829    *
1830    * has been resolved
1831    */
1832   if (G_IS_SOCKET_CONNECTION (connection->priv->stream))
1833     {
1834       g_socket_set_blocking (g_socket_connection_get_socket (G_SOCKET_CONNECTION (connection->priv->stream)), FALSE);
1835     }
1836
1837   connection->priv->worker = _g_dbus_worker_new (connection->priv->stream,
1838                                                  connection->priv->capabilities,
1839                                                  on_worker_message_received,
1840                                                  on_worker_closed,
1841                                                  connection);
1842
1843   /* if a bus connection, invoke org.freedesktop.DBus.Hello - this is how we're getting a name */
1844   if (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
1845     {
1846       GVariant *hello_result;
1847       const gchar *s;
1848
1849       hello_result = g_dbus_connection_call_sync (connection,
1850                                                   "org.freedesktop.DBus", /* name */
1851                                                   "/org/freedesktop/DBus", /* path */
1852                                                   "org.freedesktop.DBus", /* interface */
1853                                                   "Hello",
1854                                                   NULL, /* parameters */
1855                                                   G_DBUS_CALL_FLAGS_NONE,
1856                                                   -1,
1857                                                   NULL, /* TODO: cancellable */
1858                                                   &connection->priv->initialization_error);
1859       if (hello_result == NULL)
1860         goto out;
1861
1862       g_variant_get (hello_result, "(s)", &s);
1863       connection->priv->bus_unique_name = g_strdup (s);
1864       g_variant_unref (hello_result);
1865       //g_debug ("unique name is `%s'", connection->priv->bus_unique_name);
1866     }
1867
1868   connection->priv->is_initialized = TRUE;
1869
1870   ret = TRUE;
1871  out:
1872   if (!ret)
1873     {
1874       g_assert (connection->priv->initialization_error != NULL);
1875       g_propagate_error (error, g_error_copy (connection->priv->initialization_error));
1876     }
1877
1878   g_mutex_unlock (connection->priv->init_lock);
1879
1880   return ret;
1881 }
1882
1883 static void
1884 initable_iface_init (GInitableIface *initable_iface)
1885 {
1886   initable_iface->init = initable_init;
1887 }
1888
1889 /* ---------------------------------------------------------------------------------------------------- */
1890
1891 static void
1892 async_init_thread (GSimpleAsyncResult *res,
1893                    GObject            *object,
1894                    GCancellable       *cancellable)
1895 {
1896   GError *error = NULL;
1897
1898   if (!g_initable_init (G_INITABLE (object), cancellable, &error))
1899     {
1900       g_simple_async_result_set_from_error (res, error);
1901       g_error_free (error);
1902     }
1903 }
1904
1905 static void
1906 async_initable_init_async (GAsyncInitable      *initable,
1907                            gint                 io_priority,
1908                            GCancellable        *cancellable,
1909                            GAsyncReadyCallback  callback,
1910                            gpointer             user_data)
1911 {
1912   GSimpleAsyncResult *res;
1913
1914   g_return_if_fail (G_IS_INITABLE (initable));
1915
1916   res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data,
1917                                    async_initable_init_async);
1918   g_simple_async_result_run_in_thread (res, async_init_thread,
1919                                        io_priority, cancellable);
1920   g_object_unref (res);
1921 }
1922
1923 static gboolean
1924 async_initable_init_finish (GAsyncInitable  *initable,
1925                             GAsyncResult    *res,
1926                             GError         **error)
1927 {
1928   return TRUE; /* Errors handled by base impl */
1929 }
1930
1931 static void
1932 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
1933 {
1934   /* We basically just want to use GIO's default implementation - though that one is
1935    * unfortunately broken, see #615111. So we copy-paste a fixed-up version.
1936    */
1937   async_initable_iface->init_async = async_initable_init_async;
1938   async_initable_iface->init_finish = async_initable_init_finish;
1939 }
1940
1941 /* ---------------------------------------------------------------------------------------------------- */
1942
1943 /**
1944  * g_dbus_connection_new:
1945  * @stream: A #GIOStream.
1946  * @guid: The GUID to use if a authenticating as a server or %NULL.
1947  * @flags: Flags describing how to make the connection.
1948  * @observer: A #GDBusAuthObserver or %NULL.
1949  * @cancellable: A #GCancellable or %NULL.
1950  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
1951  * @user_data: The data to pass to @callback.
1952  *
1953  * Asynchronously sets up a D-Bus connection for exchanging D-Bus messages
1954  * with the end represented by @stream.
1955  *
1956  * If %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER is set in @flags,
1957  * @observer (if not %NULL) is used to assist in the client
1958  * authentication process.
1959  *
1960  * When the operation is finished, @callback will be invoked. You can
1961  * then call g_dbus_connection_new_finish() to get the result of the
1962  * operation.
1963  *
1964  * This is a asynchronous failable constructor. See
1965  * g_dbus_connection_new_sync() for the synchronous
1966  * version.
1967  *
1968  * Since: 2.26
1969  */
1970 void
1971 g_dbus_connection_new (GIOStream            *stream,
1972                        const gchar          *guid,
1973                        GDBusConnectionFlags  flags,
1974                        GDBusAuthObserver    *observer,
1975                        GCancellable         *cancellable,
1976                        GAsyncReadyCallback   callback,
1977                        gpointer              user_data)
1978 {
1979   g_return_if_fail (G_IS_IO_STREAM (stream));
1980   g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
1981                               G_PRIORITY_DEFAULT,
1982                               cancellable,
1983                               callback,
1984                               user_data,
1985                               "stream", stream,
1986                               "guid", guid,
1987                               "flags", flags,
1988                               "authentication-observer", observer,
1989                               NULL);
1990 }
1991
1992 /**
1993  * g_dbus_connection_new_finish:
1994  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_new().
1995  * @error: Return location for error or %NULL.
1996  *
1997  * Finishes an operation started with g_dbus_connection_new().
1998  *
1999  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2000  *
2001  * Since: 2.26
2002  */
2003 GDBusConnection *
2004 g_dbus_connection_new_finish (GAsyncResult  *res,
2005                               GError       **error)
2006 {
2007   GObject *object;
2008   GObject *source_object;
2009
2010   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2011   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2012
2013   source_object = g_async_result_get_source_object (res);
2014   g_assert (source_object != NULL);
2015   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2016                                         res,
2017                                         error);
2018   g_object_unref (source_object);
2019   if (object != NULL)
2020     return G_DBUS_CONNECTION (object);
2021   else
2022     return NULL;
2023 }
2024
2025 /**
2026  * g_dbus_connection_new_sync:
2027  * @stream: A #GIOStream.
2028  * @guid: The GUID to use if a authenticating as a server or %NULL.
2029  * @flags: Flags describing how to make the connection.
2030  * @observer: A #GDBusAuthObserver or %NULL.
2031  * @cancellable: A #GCancellable or %NULL.
2032  * @error: Return location for error or %NULL.
2033  *
2034  * Synchronously sets up a D-Bus connection for exchanging D-Bus messages
2035  * with the end represented by @stream.
2036  *
2037  * If %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER is set in @flags,
2038  * @observer (if not %NULL) is used to assist in the client
2039  * authentication process.
2040  *
2041  * This is a synchronous failable constructor. See
2042  * g_dbus_connection_new() for the asynchronous version.
2043  *
2044  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2045  *
2046  * Since: 2.26
2047  */
2048 GDBusConnection *
2049 g_dbus_connection_new_sync (GIOStream             *stream,
2050                             const gchar           *guid,
2051                             GDBusConnectionFlags   flags,
2052                             GDBusAuthObserver     *observer,
2053                             GCancellable          *cancellable,
2054                             GError               **error)
2055 {
2056   g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL);
2057   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2058   return g_initable_new (G_TYPE_DBUS_CONNECTION,
2059                          cancellable,
2060                          error,
2061                          "stream", stream,
2062                          "guid", guid,
2063                          "flags", flags,
2064                          "authentication-observer", observer,
2065                          NULL);
2066 }
2067
2068 /* ---------------------------------------------------------------------------------------------------- */
2069
2070 /**
2071  * g_dbus_connection_new_for_address:
2072  * @address: A D-Bus address.
2073  * @flags: Flags describing how to make the connection.
2074  * @cancellable: A #GCancellable or %NULL.
2075  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
2076  * @user_data: The data to pass to @callback.
2077  *
2078  * Asynchronously connects and sets up a D-Bus client connection for
2079  * exchanging D-Bus messages with an endpoint specified by @address
2080  * which must be in the D-Bus address format.
2081  *
2082  * This constructor can only be used to initiate client-side
2083  * connections - use g_dbus_connection_new() if you need to act as the
2084  * server. In particular, @flags cannot contain the
2085  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2086  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2087  *
2088  * When the operation is finished, @callback will be invoked. You can
2089  * then call g_dbus_connection_new_finish() to get the result of the
2090  * operation.
2091  *
2092  * This is a asynchronous failable constructor. See
2093  * g_dbus_connection_new_for_address_sync() for the synchronous
2094  * version.
2095  *
2096  * Since: 2.26
2097  */
2098 void
2099 g_dbus_connection_new_for_address (const gchar          *address,
2100                                    GDBusConnectionFlags  flags,
2101                                    GCancellable         *cancellable,
2102                                    GAsyncReadyCallback   callback,
2103                                    gpointer              user_data)
2104 {
2105   g_return_if_fail (address != NULL);
2106   g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2107                               G_PRIORITY_DEFAULT,
2108                               cancellable,
2109                               callback,
2110                               user_data,
2111                               "address", address,
2112                               "flags", flags,
2113                               NULL);
2114 }
2115
2116 /**
2117  * g_dbus_connection_new_for_address_finish:
2118  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_new().
2119  * @error: Return location for error or %NULL.
2120  *
2121  * Finishes an operation started with g_dbus_connection_new_for_address().
2122  *
2123  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2124  *
2125  * Since: 2.26
2126  */
2127 GDBusConnection *
2128 g_dbus_connection_new_for_address_finish (GAsyncResult  *res,
2129                                           GError       **error)
2130 {
2131   GObject *object;
2132   GObject *source_object;
2133
2134   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2135   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2136
2137   source_object = g_async_result_get_source_object (res);
2138   g_assert (source_object != NULL);
2139   object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2140                                         res,
2141                                         error);
2142   g_object_unref (source_object);
2143   if (object != NULL)
2144     return G_DBUS_CONNECTION (object);
2145   else
2146     return NULL;
2147 }
2148
2149 /**
2150  * g_dbus_connection_new_for_address_sync:
2151  * @address: A D-Bus address.
2152  * @flags: Flags describing how to make the connection.
2153  * @cancellable: A #GCancellable or %NULL.
2154  * @error: Return location for error or %NULL.
2155  *
2156  * Synchronously connects and sets up a D-Bus client connection for
2157  * exchanging D-Bus messages with an endpoint specified by @address
2158  * which must be in the D-Bus address format.
2159  *
2160  * This constructor can only be used to initiate client-side
2161  * connections - use g_dbus_connection_new_sync() if you need to act
2162  * as the server. In particular, @flags cannot contain the
2163  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2164  * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2165  *
2166  * This is a synchronous failable constructor. See
2167  * g_dbus_connection_new_for_address() for the asynchronous version.
2168  *
2169  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2170  *
2171  * Since: 2.26
2172  */
2173 GDBusConnection *
2174 g_dbus_connection_new_for_address_sync (const gchar           *address,
2175                                         GDBusConnectionFlags   flags,
2176                                         GCancellable          *cancellable,
2177                                         GError               **error)
2178 {
2179   g_return_val_if_fail (address != NULL, NULL);
2180   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2181   return g_initable_new (G_TYPE_DBUS_CONNECTION,
2182                          cancellable,
2183                          error,
2184                          "address", address,
2185                          "flags", flags,
2186                          NULL);
2187 }
2188
2189 /* ---------------------------------------------------------------------------------------------------- */
2190
2191 /**
2192  * g_dbus_connection_set_exit_on_close:
2193  * @connection: A #GDBusConnection.
2194  * @exit_on_close: Whether the process should be terminated
2195  * when @connection is closed by the remote peer.
2196  *
2197  * Sets whether the process should be terminated when @connection is
2198  * closed by the remote peer. See #GDBusConnection:exit-on-close for
2199  * more details.
2200  *
2201  * Since: 2.26
2202  */
2203 void
2204 g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
2205                                      gboolean         exit_on_close)
2206 {
2207   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2208   connection->priv->exit_on_close = exit_on_close;
2209 }
2210
2211 /**
2212  * g_dbus_connection_get_exit_on_close:
2213  * @connection: A #GDBusConnection.
2214  *
2215  * Gets whether the process is terminated when @connection is
2216  * closed by the remote peer. See
2217  * #GDBusConnection:exit-on-close for more details.
2218  *
2219  * Returns: Whether the process is terminated when @connection is
2220  * closed by the remote peer.
2221  *
2222  * Since: 2.26
2223  */
2224 gboolean
2225 g_dbus_connection_get_exit_on_close (GDBusConnection *connection)
2226 {
2227   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
2228   return connection->priv->exit_on_close;
2229 }
2230
2231 /**
2232  * g_dbus_connection_get_guid:
2233  * @connection: A #GDBusConnection.
2234  *
2235  * The GUID of the peer performing the role of server when
2236  * authenticating. See #GDBusConnection:guid for more details.
2237  *
2238  * Returns: The GUID. Do not free this string, it is owned by
2239  * @connection.
2240  *
2241  * Since: 2.26
2242  */
2243 const gchar *
2244 g_dbus_connection_get_guid (GDBusConnection *connection)
2245 {
2246   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2247   return connection->priv->guid;
2248 }
2249
2250 /**
2251  * g_dbus_connection_get_unique_name:
2252  * @connection: A #GDBusConnection.
2253  *
2254  * Gets the unique name of @connection as assigned by the message
2255  * bus. This can also be used to figure out if @connection is a
2256  * message bus connection.
2257  *
2258  * Returns: The unique name or %NULL if @connection is not a message
2259  * bus connection. Do not free this string, it is owned by
2260  * @connection.
2261  *
2262  * Since: 2.26
2263  */
2264 const gchar *
2265 g_dbus_connection_get_unique_name (GDBusConnection *connection)
2266 {
2267   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2268   return connection->priv->bus_unique_name;
2269 }
2270
2271 /**
2272  * g_dbus_connection_get_peer_credentials:
2273  * @connection: A #GDBusConnection.
2274  *
2275  * Gets the credentials of the authenticated peer. This will always
2276  * return %NULL unless @connection acted as a server
2277  * (e.g. %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER was passed)
2278  * when set up and the client passed credentials as part of the
2279  * authentication process.
2280  *
2281  * In a message bus setup, the message bus is always the server and
2282  * each application is a client. So this method will always return
2283  * %NULL for message bus clients.
2284  *
2285  * Returns: A #GCredentials or %NULL if not available. Do not free
2286  * this object, it is owned by @connection.
2287  *
2288  * Since: 2.26
2289  */
2290 GCredentials *
2291 g_dbus_connection_get_peer_credentials (GDBusConnection *connection)
2292 {
2293   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2294   return connection->priv->crendentials;
2295 }
2296
2297 /* ---------------------------------------------------------------------------------------------------- */
2298
2299 static guint _global_filter_id = 1;
2300
2301 /**
2302  * g_dbus_connection_add_filter:
2303  * @connection: A #GDBusConnection.
2304  * @filter_function: A filter function.
2305  * @user_data: User data to pass to @filter_function.
2306  * @user_data_free_func: Function to free @user_data with when filter
2307  * is removed or %NULL.
2308  *
2309  * Adds a message filter. Filters are handlers that are run on all
2310  * incoming messages, prior to standard dispatch. Filters are run in
2311  * the order that they were added.  The same handler can be added as a
2312  * filter more than once, in which case it will be run more than once.
2313  * Filters added during a filter callback won't be run on the message
2314  * being processed.
2315  *
2316  * Note that filters are run in a dedicated message handling thread so
2317  * they can't block and, generally, can't do anything but signal a
2318  * worker thread. Also note that filters are rarely needed - use API
2319  * such as g_dbus_connection_send_message_with_reply(),
2320  * g_dbus_connection_signal_subscribe() or
2321  * g_dbus_connection_call() instead.
2322  *
2323  * Returns: A filter identifier that can be used with
2324  * g_dbus_connection_remove_filter().
2325  *
2326  * Since: 2.26
2327  */
2328 guint
2329 g_dbus_connection_add_filter (GDBusConnection            *connection,
2330                               GDBusMessageFilterFunction  filter_function,
2331                               gpointer                    user_data,
2332                               GDestroyNotify              user_data_free_func)
2333 {
2334   FilterData *data;
2335
2336   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
2337   g_return_val_if_fail (filter_function != NULL, 0);
2338
2339   CONNECTION_LOCK (connection);
2340   data = g_new0 (FilterData, 1);
2341   data->id = _global_filter_id++; /* TODO: overflow etc. */
2342   data->filter_function = filter_function;
2343   data->user_data = user_data;
2344   data->user_data_free_func = user_data_free_func;
2345   g_ptr_array_add (connection->priv->filters, data);
2346   CONNECTION_UNLOCK (connection);
2347
2348   return data->id;
2349 }
2350
2351 /* only called from finalize(), removes all filters */
2352 static void
2353 purge_all_filters (GDBusConnection *connection)
2354 {
2355   guint n;
2356   for (n = 0; n < connection->priv->filters->len; n++)
2357     {
2358       FilterData *data = connection->priv->filters->pdata[n];
2359       if (data->user_data_free_func != NULL)
2360         data->user_data_free_func (data->user_data);
2361       g_free (data);
2362     }
2363 }
2364
2365 /**
2366  * g_dbus_connection_remove_filter:
2367  * @connection: a #GDBusConnection
2368  * @filer_id: an identifier obtained from g_dbus_connection_add_filter()
2369  *
2370  * Removes a filter.
2371  *
2372  * Since: 2.26
2373  */
2374 void
2375 g_dbus_connection_remove_filter (GDBusConnection *connection,
2376                                  guint            filter_id)
2377 {
2378   guint n;
2379   FilterData *to_destroy;
2380
2381   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2382
2383   CONNECTION_LOCK (connection);
2384   to_destroy = NULL;
2385   for (n = 0; n < connection->priv->filters->len; n++)
2386     {
2387       FilterData *data = connection->priv->filters->pdata[n];
2388       if (data->id == filter_id)
2389         {
2390           g_ptr_array_remove_index (connection->priv->filters, n);
2391           to_destroy = data;
2392           break;
2393         }
2394     }
2395   CONNECTION_UNLOCK (connection);
2396
2397   /* do free without holding lock */
2398   if (to_destroy != NULL)
2399     {
2400       if (to_destroy->user_data_free_func != NULL)
2401         to_destroy->user_data_free_func (to_destroy->user_data);
2402       g_free (to_destroy);
2403     }
2404   else
2405     {
2406       g_warning ("g_dbus_connection_remove_filter: No filter found for filter_id %d", filter_id);
2407     }
2408 }
2409
2410 /* ---------------------------------------------------------------------------------------------------- */
2411
2412 typedef struct
2413 {
2414   gchar *rule;
2415   gchar *sender;
2416   gchar *interface_name;
2417   gchar *member;
2418   gchar *object_path;
2419   gchar *arg0;
2420   GArray *subscribers;
2421 } SignalData;
2422
2423 typedef struct
2424 {
2425   GDBusSignalCallback callback;
2426   gpointer user_data;
2427   GDestroyNotify user_data_free_func;
2428   guint id;
2429   GMainContext *context;
2430 } SignalSubscriber;
2431
2432 static void
2433 signal_data_free (SignalData *data)
2434 {
2435   g_free (data->rule);
2436   g_free (data->sender);
2437   g_free (data->interface_name);
2438   g_free (data->member);
2439   g_free (data->object_path);
2440   g_free (data->arg0);
2441   g_array_free (data->subscribers, TRUE);
2442   g_free (data);
2443 }
2444
2445 static gchar *
2446 args_to_rule (const gchar *sender,
2447               const gchar *interface_name,
2448               const gchar *member,
2449               const gchar *object_path,
2450               const gchar *arg0)
2451 {
2452   GString *rule;
2453
2454   rule = g_string_new ("type='signal'");
2455   if (sender != NULL)
2456     g_string_append_printf (rule, ",sender='%s'", sender);
2457   if (interface_name != NULL)
2458     g_string_append_printf (rule, ",interface='%s'", interface_name);
2459   if (member != NULL)
2460     g_string_append_printf (rule, ",member='%s'", member);
2461   if (object_path != NULL)
2462     g_string_append_printf (rule, ",path='%s'", object_path);
2463   if (arg0 != NULL)
2464     g_string_append_printf (rule, ",arg0='%s'", arg0);
2465
2466   return g_string_free (rule, FALSE);
2467 }
2468
2469 static guint _global_subscriber_id = 1;
2470 static guint _global_registration_id = 1;
2471 static guint _global_subtree_registration_id = 1;
2472
2473 /* ---------------------------------------------------------------------------------------------------- */
2474
2475 /* must hold lock when calling */
2476 static void
2477 add_match_rule (GDBusConnection *connection,
2478                 const gchar     *match_rule)
2479 {
2480   GError *error;
2481   GDBusMessage *message;
2482
2483   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
2484                                             "/org/freedesktop/DBus", /* path */
2485                                             "org.freedesktop.DBus", /* interface */
2486                                             "AddMatch");
2487   g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
2488
2489   error = NULL;
2490   if (!g_dbus_connection_send_message_unlocked (connection,
2491                                                 message,
2492                                                 NULL,
2493                                                 &error))
2494     {
2495       g_critical ("Error while sending AddMatch() message: %s", error->message);
2496       g_error_free (error);
2497     }
2498   g_object_unref (message);
2499 }
2500
2501 /* ---------------------------------------------------------------------------------------------------- */
2502
2503 /* must hold lock when calling */
2504 static void
2505 remove_match_rule (GDBusConnection *connection,
2506                    const gchar     *match_rule)
2507 {
2508   GError *error;
2509   GDBusMessage *message;
2510
2511   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
2512                                             "/org/freedesktop/DBus", /* path */
2513                                             "org.freedesktop.DBus", /* interface */
2514                                             "RemoveMatch");
2515   g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
2516
2517   error = NULL;
2518   if (!g_dbus_connection_send_message_unlocked (connection,
2519                                                 message,
2520                                                 NULL,
2521                                                 &error))
2522     {
2523       g_critical ("Error while sending RemoveMatch() message: %s", error->message);
2524       g_error_free (error);
2525     }
2526   g_object_unref (message);
2527 }
2528
2529 /* ---------------------------------------------------------------------------------------------------- */
2530
2531 static gboolean
2532 is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
2533 {
2534   return g_strcmp0 (signal_data->sender, "org.freedesktop.DBus") == 0 &&
2535          g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
2536          g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
2537          (g_strcmp0 (signal_data->member, "NameLost") == 0 ||
2538           g_strcmp0 (signal_data->member, "NameAcquired") == 0);
2539 }
2540
2541 /* ---------------------------------------------------------------------------------------------------- */
2542
2543 /**
2544  * g_dbus_connection_signal_subscribe:
2545  * @connection: A #GDBusConnection.
2546  * @sender: Sender name to match on. Must be either <literal>org.freedesktop.DBus</literal> (for listening to signals from the message bus daemon) or a unique name or %NULL to listen from all senders.
2547  * @interface_name: D-Bus interface name to match on or %NULL to match on all interfaces.
2548  * @member: D-Bus signal name to match on or %NULL to match on all signals.
2549  * @object_path: Object path to match on or %NULL to match on all object paths.
2550  * @arg0: Contents of first string argument to match on or %NULL to match on all kinds of arguments.
2551  * @callback: Callback to invoke when there is a signal matching the requested data.
2552  * @user_data: User data to pass to @callback.
2553  * @user_data_free_func: Function to free @user_data with when subscription is removed or %NULL.
2554  *
2555  * Subscribes to signals on @connection and invokes @callback with a
2556  * whenever the signal is received. Note that @callback
2557  * will be invoked in the <link
2558  * linkend="g-main-context-push-thread-default">thread-default main
2559  * loop</link> of the thread you are calling this method from.
2560  *
2561  * It is considered a programming error to use this function if @connection is closed.
2562  *
2563  * Note that if @sender is not <literal>org.freedesktop.DBus</literal> (for listening to signals from the
2564  * message bus daemon), then it needs to be a unique bus name or %NULL (for listening to signals from any
2565  * name) - you cannot pass a name like <literal>com.example.MyApp</literal>.
2566  * Use e.g. g_bus_watch_name() to find the unique name for the owner of the name you are interested in. Also note
2567  * that this function does not remove a subscription if @sender vanishes from the bus. You have to manually
2568  * call g_dbus_connection_signal_unsubscribe() to remove a subscription.
2569  *
2570  * Returns: A subscription identifier that can be used with g_dbus_connection_signal_unsubscribe().
2571  *
2572  * Since: 2.26
2573  */
2574 guint
2575 g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
2576                                     const gchar         *sender,
2577                                     const gchar         *interface_name,
2578                                     const gchar         *member,
2579                                     const gchar         *object_path,
2580                                     const gchar         *arg0,
2581                                     GDBusSignalCallback  callback,
2582                                     gpointer             user_data,
2583                                     GDestroyNotify       user_data_free_func)
2584 {
2585   gchar *rule;
2586   SignalData *signal_data;
2587   SignalSubscriber subscriber;
2588   GPtrArray *signal_data_array;
2589
2590   /* Right now we abort if AddMatch() fails since it can only fail with the bus being in
2591    * an OOM condition. We might want to change that but that would involve making
2592    * g_dbus_connection_signal_subscribe() asynchronous and having the call sites
2593    * handle that. And there's really no sensible way of handling this short of retrying
2594    * to add the match rule... and then there's the little thing that, hey, maybe there's
2595    * a reason the bus in an OOM condition.
2596    *
2597    * Doable, but not really sure it's worth it...
2598    */
2599
2600   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
2601   g_return_val_if_fail (!g_dbus_connection_is_closed (connection), 0);
2602   g_return_val_if_fail (sender == NULL || ((strcmp (sender, "org.freedesktop.DBus") == 0 || sender[0] == ':') &&
2603                                            (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)), 0);
2604   g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), 0);
2605   g_return_val_if_fail (member == NULL || g_dbus_is_member_name (member), 0);
2606   g_return_val_if_fail (object_path == NULL || g_variant_is_object_path (object_path), 0);
2607   g_return_val_if_fail (callback != NULL, 0);
2608
2609   CONNECTION_LOCK (connection);
2610
2611   rule = args_to_rule (sender, interface_name, member, object_path, arg0);
2612
2613   if (sender == NULL)
2614     sender = "";
2615
2616   subscriber.callback = callback;
2617   subscriber.user_data = user_data;
2618   subscriber.user_data_free_func = user_data_free_func;
2619   subscriber.id = _global_subscriber_id++; /* TODO: overflow etc. */
2620   subscriber.context = g_main_context_get_thread_default ();
2621   if (subscriber.context != NULL)
2622     g_main_context_ref (subscriber.context);
2623
2624   /* see if we've already have this rule */
2625   signal_data = g_hash_table_lookup (connection->priv->map_rule_to_signal_data, rule);
2626   if (signal_data != NULL)
2627     {
2628       g_array_append_val (signal_data->subscribers, subscriber);
2629       g_free (rule);
2630       goto out;
2631     }
2632
2633   signal_data = g_new0 (SignalData, 1);
2634   signal_data->rule           = rule;
2635   signal_data->sender         = g_strdup (sender);
2636   signal_data->interface_name = g_strdup (interface_name);
2637   signal_data->member         = g_strdup (member);
2638   signal_data->object_path    = g_strdup (object_path);
2639   signal_data->arg0           = g_strdup (arg0);
2640   signal_data->subscribers    = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
2641   g_array_append_val (signal_data->subscribers, subscriber);
2642
2643   g_hash_table_insert (connection->priv->map_rule_to_signal_data,
2644                        signal_data->rule,
2645                        signal_data);
2646
2647   /* Add the match rule to the bus...
2648    *
2649    * Avoid adding match rules for NameLost and NameAcquired messages - the bus will
2650    * always send such messages to us.
2651    */
2652   if (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2653     {
2654       if (!is_signal_data_for_name_lost_or_acquired (signal_data))
2655         add_match_rule (connection, signal_data->rule);
2656     }
2657
2658  out:
2659   g_hash_table_insert (connection->priv->map_id_to_signal_data,
2660                        GUINT_TO_POINTER (subscriber.id),
2661                        signal_data);
2662
2663   signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array,
2664                                            signal_data->sender);
2665   if (signal_data_array == NULL)
2666     {
2667       signal_data_array = g_ptr_array_new ();
2668       g_hash_table_insert (connection->priv->map_sender_to_signal_data_array,
2669                            g_strdup (signal_data->sender),
2670                            signal_data_array);
2671     }
2672   g_ptr_array_add (signal_data_array, signal_data);
2673
2674   CONNECTION_UNLOCK (connection);
2675
2676   return subscriber.id;
2677 }
2678
2679 /* ---------------------------------------------------------------------------------------------------- */
2680
2681 /* must hold lock when calling this */
2682 static void
2683 unsubscribe_id_internal (GDBusConnection *connection,
2684                          guint            subscription_id,
2685                          GArray          *out_removed_subscribers)
2686 {
2687   SignalData *signal_data;
2688   GPtrArray *signal_data_array;
2689   guint n;
2690
2691   signal_data = g_hash_table_lookup (connection->priv->map_id_to_signal_data,
2692                                      GUINT_TO_POINTER (subscription_id));
2693   if (signal_data == NULL)
2694     {
2695       /* Don't warn here, we may have thrown all subscriptions out when the connection was closed */
2696       goto out;
2697     }
2698
2699   for (n = 0; n < signal_data->subscribers->len; n++)
2700     {
2701       SignalSubscriber *subscriber;
2702
2703       subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, n));
2704       if (subscriber->id != subscription_id)
2705         continue;
2706
2707       g_warn_if_fail (g_hash_table_remove (connection->priv->map_id_to_signal_data,
2708                                            GUINT_TO_POINTER (subscription_id)));
2709       g_array_append_val (out_removed_subscribers, *subscriber);
2710       g_array_remove_index (signal_data->subscribers, n);
2711
2712       if (signal_data->subscribers->len == 0)
2713         g_warn_if_fail (g_hash_table_remove (connection->priv->map_rule_to_signal_data, signal_data->rule));
2714
2715       signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array,
2716                                                signal_data->sender);
2717       g_warn_if_fail (signal_data_array != NULL);
2718       g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data));
2719
2720       if (signal_data_array->len == 0)
2721         {
2722           g_warn_if_fail (g_hash_table_remove (connection->priv->map_sender_to_signal_data_array, signal_data->sender));
2723
2724           /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
2725           if (connection->priv->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2726             {
2727               if (!is_signal_data_for_name_lost_or_acquired (signal_data))
2728                 remove_match_rule (connection, signal_data->rule);
2729             }
2730
2731           signal_data_free (signal_data);
2732         }
2733
2734       goto out;
2735     }
2736
2737   g_assert_not_reached ();
2738
2739  out:
2740   ;
2741 }
2742
2743 /**
2744  * g_dbus_connection_signal_unsubscribe:
2745  * @connection: A #GDBusConnection.
2746  * @subscription_id: A subscription id obtained from g_dbus_connection_signal_subscribe().
2747  *
2748  * Unsubscribes from signals.
2749  *
2750  * Since: 2.26
2751  */
2752 void
2753 g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
2754                                       guint            subscription_id)
2755 {
2756   GArray *subscribers;
2757   guint n;
2758
2759   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2760
2761   subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
2762
2763   CONNECTION_LOCK (connection);
2764   unsubscribe_id_internal (connection,
2765                            subscription_id,
2766                            subscribers);
2767   CONNECTION_UNLOCK (connection);
2768
2769   /* invariant */
2770   g_assert (subscribers->len == 0 || subscribers->len == 1);
2771
2772   /* call GDestroyNotify without lock held */
2773   for (n = 0; n < subscribers->len; n++)
2774     {
2775       SignalSubscriber *subscriber;
2776       subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
2777       if (subscriber->user_data_free_func != NULL)
2778         subscriber->user_data_free_func (subscriber->user_data);
2779       if (subscriber->context != NULL)
2780         g_main_context_unref (subscriber->context);
2781     }
2782
2783   g_array_free (subscribers, TRUE);
2784 }
2785
2786 /* ---------------------------------------------------------------------------------------------------- */
2787
2788 typedef struct
2789 {
2790   guint                subscription_id;
2791   GDBusSignalCallback  callback;
2792   gpointer             user_data;
2793   GDBusMessage        *message;
2794   GDBusConnection     *connection;
2795   const gchar         *sender;
2796   const gchar         *path;
2797   const gchar         *interface;
2798   const gchar         *member;
2799 } SignalInstance;
2800
2801 /* called on delivery thread (e.g. where g_dbus_connection_signal_subscribe() was called) with
2802  * no locks held
2803  */
2804 static gboolean
2805 emit_signal_instance_in_idle_cb (gpointer data)
2806 {
2807   SignalInstance *signal_instance = data;
2808   GVariant *parameters;
2809   gboolean has_subscription;
2810
2811   parameters = g_dbus_message_get_body (signal_instance->message);
2812   if (parameters == NULL)
2813     {
2814       parameters = g_variant_new ("()");
2815       g_variant_ref_sink (parameters);
2816     }
2817   else
2818     {
2819       g_variant_ref_sink (parameters);
2820     }
2821
2822 #if 0
2823   g_debug ("in emit_signal_instance_in_idle_cb (sender=%s path=%s interface=%s member=%s params=%s)",
2824            signal_instance->sender,
2825            signal_instance->path,
2826            signal_instance->interface,
2827            signal_instance->member,
2828            g_variant_print (parameters, TRUE));
2829 #endif
2830
2831   /* Careful here, don't do the callback if we no longer has the subscription */
2832   CONNECTION_LOCK (signal_instance->connection);
2833   has_subscription = FALSE;
2834   if (g_hash_table_lookup (signal_instance->connection->priv->map_id_to_signal_data,
2835                            GUINT_TO_POINTER (signal_instance->subscription_id)) != NULL)
2836     has_subscription = TRUE;
2837   CONNECTION_UNLOCK (signal_instance->connection);
2838
2839   if (has_subscription)
2840     signal_instance->callback (signal_instance->connection,
2841                                signal_instance->sender,
2842                                signal_instance->path,
2843                                signal_instance->interface,
2844                                signal_instance->member,
2845                                parameters,
2846                                signal_instance->user_data);
2847
2848   if (parameters != NULL)
2849     g_variant_unref (parameters);
2850
2851   return FALSE;
2852 }
2853
2854 static void
2855 signal_instance_free (SignalInstance *signal_instance)
2856 {
2857   g_object_unref (signal_instance->message);
2858   g_object_unref (signal_instance->connection);
2859   g_free (signal_instance);
2860 }
2861
2862 /* called in message handler thread WITH lock held */
2863 static void
2864 schedule_callbacks (GDBusConnection *connection,
2865                     GPtrArray       *signal_data_array,
2866                     GDBusMessage    *message,
2867                     const gchar     *sender)
2868 {
2869   guint n, m;
2870   const gchar *interface;
2871   const gchar *member;
2872   const gchar *path;
2873   const gchar *arg0;
2874
2875   interface = NULL;
2876   member = NULL;
2877   path = NULL;
2878   arg0 = NULL;
2879
2880   interface = g_dbus_message_get_interface (message);
2881   member = g_dbus_message_get_member (message);
2882   path = g_dbus_message_get_path (message);
2883   arg0 = g_dbus_message_get_arg0 (message);
2884
2885 #if 0
2886   g_debug ("sender    = `%s'", sender);
2887   g_debug ("interface = `%s'", interface);
2888   g_debug ("member    = `%s'", member);
2889   g_debug ("path      = `%s'", path);
2890   g_debug ("arg0      = `%s'", arg0);
2891 #endif
2892
2893   /* TODO: if this is slow, then we can change signal_data_array into
2894    *       map_object_path_to_signal_data_array or something.
2895    */
2896   for (n = 0; n < signal_data_array->len; n++)
2897     {
2898       SignalData *signal_data = signal_data_array->pdata[n];
2899
2900       if (signal_data->interface_name != NULL && g_strcmp0 (signal_data->interface_name, interface) != 0)
2901         continue;
2902
2903       if (signal_data->member != NULL && g_strcmp0 (signal_data->member, member) != 0)
2904         continue;
2905
2906       if (signal_data->object_path != NULL && g_strcmp0 (signal_data->object_path, path) != 0)
2907         continue;
2908
2909       if (signal_data->arg0 != NULL && g_strcmp0 (signal_data->arg0, arg0) != 0)
2910         continue;
2911
2912       for (m = 0; m < signal_data->subscribers->len; m++)
2913         {
2914           SignalSubscriber *subscriber;
2915           GSource *idle_source;
2916           SignalInstance *signal_instance;
2917
2918           subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, m));
2919
2920           signal_instance = g_new0 (SignalInstance, 1);
2921           signal_instance->subscription_id = subscriber->id;
2922           signal_instance->callback = subscriber->callback;
2923           signal_instance->user_data = subscriber->user_data;
2924           signal_instance->message = g_object_ref (message);
2925           signal_instance->connection = g_object_ref (connection);
2926           signal_instance->sender = sender;
2927           signal_instance->path = path;
2928           signal_instance->interface = interface;
2929           signal_instance->member = member;
2930
2931           idle_source = g_idle_source_new ();
2932           g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
2933           g_source_set_callback (idle_source,
2934                                  emit_signal_instance_in_idle_cb,
2935                                  signal_instance,
2936                                  (GDestroyNotify) signal_instance_free);
2937           g_source_attach (idle_source, subscriber->context);
2938           g_source_unref (idle_source);
2939         }
2940     }
2941 }
2942
2943 /* called in message handler thread with lock held */
2944 static void
2945 distribute_signals (GDBusConnection *connection,
2946                     GDBusMessage    *message)
2947 {
2948   GPtrArray *signal_data_array;
2949   const gchar *sender;
2950
2951   sender = g_dbus_message_get_sender (message);
2952
2953   /* collect subscribers that match on sender */
2954   if (sender != NULL)
2955     {
2956       signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array, sender);
2957       if (signal_data_array != NULL)
2958         schedule_callbacks (connection, signal_data_array, message, sender);
2959     }
2960
2961   /* collect subscribers not matching on sender */
2962   signal_data_array = g_hash_table_lookup (connection->priv->map_sender_to_signal_data_array, "");
2963   if (signal_data_array != NULL)
2964     schedule_callbacks (connection, signal_data_array, message, sender);
2965 }
2966
2967 /* ---------------------------------------------------------------------------------------------------- */
2968
2969 /* only called from finalize(), removes all subscriptions */
2970 static void
2971 purge_all_signal_subscriptions (GDBusConnection *connection)
2972 {
2973   GHashTableIter iter;
2974   gpointer key;
2975   GArray *ids;
2976   GArray *subscribers;
2977   guint n;
2978
2979   ids = g_array_new (FALSE, FALSE, sizeof (guint));
2980   g_hash_table_iter_init (&iter, connection->priv->map_id_to_signal_data);
2981   while (g_hash_table_iter_next (&iter, &key, NULL))
2982     {
2983       guint subscription_id = GPOINTER_TO_UINT (key);
2984       g_array_append_val (ids, subscription_id);
2985     }
2986
2987   subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
2988   for (n = 0; n < ids->len; n++)
2989     {
2990       guint subscription_id = g_array_index (ids, guint, n);
2991       unsubscribe_id_internal (connection,
2992                                subscription_id,
2993                                subscribers);
2994     }
2995   g_array_free (ids, TRUE);
2996
2997   /* call GDestroyNotify without lock held */
2998   for (n = 0; n < subscribers->len; n++)
2999     {
3000       SignalSubscriber *subscriber;
3001       subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
3002       if (subscriber->user_data_free_func != NULL)
3003         subscriber->user_data_free_func (subscriber->user_data);
3004       if (subscriber->context != NULL)
3005         g_main_context_unref (subscriber->context);
3006     }
3007
3008   g_array_free (subscribers, TRUE);
3009 }
3010
3011 /* ---------------------------------------------------------------------------------------------------- */
3012
3013 struct ExportedObject
3014 {
3015   gchar *object_path;
3016   GDBusConnection *connection;
3017
3018   /* maps gchar* -> ExportedInterface* */
3019   GHashTable *map_if_name_to_ei;
3020 };
3021
3022 /* only called with lock held */
3023 static void
3024 exported_object_free (ExportedObject *eo)
3025 {
3026   g_free (eo->object_path);
3027   g_hash_table_unref (eo->map_if_name_to_ei);
3028   g_free (eo);
3029 }
3030
3031 typedef struct
3032 {
3033   ExportedObject *eo;
3034
3035   guint                       id;
3036   gchar                      *interface_name;
3037   const GDBusInterfaceVTable *vtable;
3038   const GDBusInterfaceInfo   *introspection_data;
3039
3040   GMainContext               *context;
3041   gpointer                    user_data;
3042   GDestroyNotify              user_data_free_func;
3043 } ExportedInterface;
3044
3045 /* called with lock held */
3046 static void
3047 exported_interface_free (ExportedInterface *ei)
3048 {
3049   if (ei->user_data_free_func != NULL)
3050     /* TODO: push to thread-default mainloop */
3051     ei->user_data_free_func (ei->user_data);
3052
3053   if (ei->context != NULL)
3054     g_main_context_unref (ei->context);
3055
3056   g_free (ei->interface_name);
3057   g_free (ei);
3058 }
3059
3060 /* ---------------------------------------------------------------------------------------------------- */
3061
3062 typedef struct
3063 {
3064   GDBusConnection *connection;
3065   GDBusMessage *message;
3066   gpointer user_data;
3067   const char *property_name;
3068   const GDBusInterfaceVTable *vtable;
3069   const GDBusInterfaceInfo *interface_info;
3070   const GDBusPropertyInfo *property_info;
3071 } PropertyData;
3072
3073 static void
3074 property_data_free (PropertyData *data)
3075 {
3076   g_object_unref (data->connection);
3077   g_object_unref (data->message);
3078   g_free (data);
3079 }
3080
3081 /* called in thread where object was registered - no locks held */
3082 static gboolean
3083 invoke_get_property_in_idle_cb (gpointer _data)
3084 {
3085   PropertyData *data = _data;
3086   GVariant *value;
3087   GError *error;
3088   GDBusMessage *reply;
3089
3090   error = NULL;
3091   value = data->vtable->get_property (data->connection,
3092                                       g_dbus_message_get_sender (data->message),
3093                                       g_dbus_message_get_path (data->message),
3094                                       data->interface_info->name,
3095                                       data->property_name,
3096                                       &error,
3097                                       data->user_data);
3098
3099
3100   if (value != NULL)
3101     {
3102       g_assert_no_error (error);
3103
3104       g_variant_ref_sink (value);
3105       reply = g_dbus_message_new_method_reply (data->message);
3106       g_dbus_message_set_body (reply, g_variant_new ("(v)", value));
3107       g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3108       g_variant_unref (value);
3109       g_object_unref (reply);
3110     }
3111   else
3112     {
3113       gchar *dbus_error_name;
3114
3115       g_assert (error != NULL);
3116
3117       dbus_error_name = g_dbus_error_encode_gerror (error);
3118       reply = g_dbus_message_new_method_error_literal (data->message,
3119                                                        dbus_error_name,
3120                                                        error->message);
3121       g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3122       g_free (dbus_error_name);
3123       g_error_free (error);
3124       g_object_unref (reply);
3125     }
3126
3127   return FALSE;
3128 }
3129
3130 /* called in thread where object was registered - no locks held */
3131 static gboolean
3132 invoke_set_property_in_idle_cb (gpointer _data)
3133 {
3134   PropertyData *data = _data;
3135   GError *error;
3136   GDBusMessage *reply;
3137   GVariant *value;
3138
3139   error = NULL;
3140   value = NULL;
3141
3142   g_variant_get (g_dbus_message_get_body (data->message),
3143                  "(ssv)",
3144                  NULL,
3145                  NULL,
3146                  &value);
3147
3148   /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the type
3149    * of the given value is wrong
3150    */
3151   if (g_strcmp0 (g_variant_get_type_string (value), data->property_info->signature) != 0)
3152     {
3153       reply = g_dbus_message_new_method_error (data->message,
3154                                                "org.freedesktop.DBus.Error.InvalidArgs",
3155                                                _("Error setting property `%s': Expected type `%s' but got `%s'"),
3156                                                data->property_info->name,
3157                                                data->property_info->signature,
3158                                                g_variant_get_type_string (value));
3159       goto out;
3160     }
3161
3162   if (!data->vtable->set_property (data->connection,
3163                                    g_dbus_message_get_sender (data->message),
3164                                    g_dbus_message_get_path (data->message),
3165                                    data->interface_info->name,
3166                                    data->property_name,
3167                                    value,
3168                                    &error,
3169                                    data->user_data))
3170     {
3171       gchar *dbus_error_name;
3172       g_assert (error != NULL);
3173       dbus_error_name = g_dbus_error_encode_gerror (error);
3174       reply = g_dbus_message_new_method_error_literal (data->message,
3175                                                        dbus_error_name,
3176                                                        error->message);
3177       g_free (dbus_error_name);
3178       g_error_free (error);
3179     }
3180   else
3181     {
3182       reply = g_dbus_message_new_method_reply (data->message);
3183     }
3184
3185  out:
3186   g_assert (reply != NULL);
3187   g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3188   g_object_unref (reply);
3189
3190   return FALSE;
3191 }
3192
3193 /* called with lock held */
3194 static gboolean
3195 validate_and_maybe_schedule_property_getset (GDBusConnection            *connection,
3196                                              GDBusMessage               *message,
3197                                              gboolean                    is_get,
3198                                              const GDBusInterfaceInfo   *introspection_data,
3199                                              const GDBusInterfaceVTable *vtable,
3200                                              GMainContext               *main_context,
3201                                              gpointer                    user_data)
3202 {
3203   gboolean handled;
3204   const char *interface_name;
3205   const char *property_name;
3206   const GDBusPropertyInfo *property_info;
3207   GSource *idle_source;
3208   PropertyData *property_data;
3209   GDBusMessage *reply;
3210
3211   handled = FALSE;
3212
3213   if (is_get)
3214     g_variant_get (g_dbus_message_get_body (message),
3215                    "(ss)",
3216                    &interface_name,
3217                    &property_name);
3218   else
3219     g_variant_get (g_dbus_message_get_body (message),
3220                    "(ssv)",
3221                    &interface_name,
3222                    &property_name,
3223                    NULL);
3224
3225
3226   if (is_get)
3227     {
3228       if (vtable == NULL || vtable->get_property == NULL)
3229         goto out;
3230     }
3231   else
3232     {
3233       if (vtable == NULL || vtable->set_property == NULL)
3234         goto out;
3235     }
3236
3237   /* Check that the property exists - if not fail with org.freedesktop.DBus.Error.InvalidArgs
3238    */
3239   property_info = NULL;
3240
3241   /* TODO: the cost of this is O(n) - it might be worth caching the result */
3242   property_info = g_dbus_interface_info_lookup_property (introspection_data, property_name);
3243   if (property_info == NULL)
3244     {
3245       reply = g_dbus_message_new_method_error (message,
3246                                                "org.freedesktop.DBus.Error.InvalidArgs",
3247                                                _("No such property `%s'"),
3248                                                property_name);
3249       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3250       g_object_unref (reply);
3251       handled = TRUE;
3252       goto out;
3253     }
3254
3255   if (is_get && !(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE))
3256     {
3257       reply = g_dbus_message_new_method_error (message,
3258                                                "org.freedesktop.DBus.Error.InvalidArgs",
3259                                                _("Property `%s' is not readable"),
3260                                                property_name);
3261       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3262       g_object_unref (reply);
3263       handled = TRUE;
3264       goto out;
3265     }
3266   else if (!is_get && !(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
3267     {
3268       reply = g_dbus_message_new_method_error (message,
3269                                                "org.freedesktop.DBus.Error.InvalidArgs",
3270                                                _("Property `%s' is not writable"),
3271                                                property_name);
3272       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3273       g_object_unref (reply);
3274       handled = TRUE;
3275       goto out;
3276     }
3277
3278   /* ok, got the property info - call user code in an idle handler */
3279   property_data = g_new0 (PropertyData, 1);
3280   property_data->connection = g_object_ref (connection);
3281   property_data->message = g_object_ref (message);
3282   property_data->user_data = user_data;
3283   property_data->property_name = property_name;
3284   property_data->vtable = vtable;
3285   property_data->interface_info = introspection_data;
3286   property_data->property_info = property_info;
3287
3288   idle_source = g_idle_source_new ();
3289   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3290   g_source_set_callback (idle_source,
3291                          is_get ? invoke_get_property_in_idle_cb : invoke_set_property_in_idle_cb,
3292                          property_data,
3293                          (GDestroyNotify) property_data_free);
3294   g_source_attach (idle_source, main_context);
3295   g_source_unref (idle_source);
3296
3297   handled = TRUE;
3298
3299  out:
3300   return handled;
3301 }
3302
3303 /* called with lock held */
3304 static gboolean
3305 handle_getset_property (GDBusConnection *connection,
3306                         ExportedObject  *eo,
3307                         GDBusMessage    *message,
3308                         gboolean         is_get)
3309 {
3310   ExportedInterface *ei;
3311   gboolean handled;
3312   const char *interface_name;
3313   const char *property_name;
3314
3315   handled = FALSE;
3316
3317   if (is_get)
3318     g_variant_get (g_dbus_message_get_body (message),
3319                    "(ss)",
3320                    &interface_name,
3321                    &property_name);
3322   else
3323     g_variant_get (g_dbus_message_get_body (message),
3324                    "(ssv)",
3325                    &interface_name,
3326                    &property_name,
3327                    NULL);
3328
3329   /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
3330    * no such interface registered
3331    */
3332   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
3333   if (ei == NULL)
3334     {
3335       GDBusMessage *reply;
3336       reply = g_dbus_message_new_method_error (message,
3337                                                "org.freedesktop.DBus.Error.InvalidArgs",
3338                                                _("No such interface `%s'"),
3339                                                interface_name);
3340       g_dbus_connection_send_message_unlocked (eo->connection, reply, NULL, NULL);
3341       g_object_unref (reply);
3342       handled = TRUE;
3343       goto out;
3344     }
3345
3346   handled = validate_and_maybe_schedule_property_getset (eo->connection,
3347                                                          message,
3348                                                          is_get,
3349                                                          ei->introspection_data,
3350                                                          ei->vtable,
3351                                                          ei->context,
3352                                                          ei->user_data);
3353  out:
3354   return handled;
3355 }
3356
3357 /* ---------------------------------------------------------------------------------------------------- */
3358
3359 typedef struct
3360 {
3361   GDBusConnection *connection;
3362   GDBusMessage *message;
3363   gpointer user_data;
3364   const GDBusInterfaceVTable *vtable;
3365   const GDBusInterfaceInfo *interface_info;
3366 } PropertyGetAllData;
3367
3368 static void
3369 property_get_all_data_free (PropertyData *data)
3370 {
3371   g_object_unref (data->connection);
3372   g_object_unref (data->message);
3373   g_free (data);
3374 }
3375
3376 /* called in thread where object was registered - no locks held */
3377 static gboolean
3378 invoke_get_all_properties_in_idle_cb (gpointer _data)
3379 {
3380   PropertyGetAllData *data = _data;
3381   GVariantBuilder *builder;
3382   GVariant *packed;
3383   GVariant *result;
3384   GError *error;
3385   GDBusMessage *reply;
3386   guint n;
3387
3388   error = NULL;
3389
3390   /* TODO: Right now we never fail this call - we just omit values if
3391    *       a get_property() call is failing.
3392    *
3393    *       We could fail the whole call if just a single get_property() call
3394    *       returns an error. We need clarification in the D-Bus spec about this.
3395    */
3396   builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3397   for (n = 0; data->interface_info->properties != NULL && data->interface_info->properties[n] != NULL; n++)
3398     {
3399       const GDBusPropertyInfo *property_info = data->interface_info->properties[n];
3400       GVariant *value;
3401
3402       if (!(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE))
3403         continue;
3404
3405       value = data->vtable->get_property (data->connection,
3406                                           g_dbus_message_get_sender (data->message),
3407                                           g_dbus_message_get_path (data->message),
3408                                           data->interface_info->name,
3409                                           property_info->name,
3410                                           NULL,
3411                                           data->user_data);
3412
3413       if (value == NULL)
3414         continue;
3415
3416       g_variant_ref_sink (value);
3417       g_variant_builder_add (builder,
3418                              "{sv}",
3419                              property_info->name,
3420                              value);
3421       g_variant_unref (value);
3422     }
3423   result = g_variant_builder_end (builder);
3424
3425   builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
3426   g_variant_builder_add_value (builder, result); /* steals result since result is floating */
3427   packed = g_variant_builder_end (builder);
3428
3429   reply = g_dbus_message_new_method_reply (data->message);
3430   g_dbus_message_set_body (reply, packed);
3431   g_dbus_connection_send_message (data->connection, reply, NULL, NULL);
3432   g_object_unref (reply);
3433
3434   return FALSE;
3435 }
3436
3437 /* called with lock held */
3438 static gboolean
3439 validate_and_maybe_schedule_property_get_all (GDBusConnection            *connection,
3440                                               GDBusMessage               *message,
3441                                               const GDBusInterfaceInfo   *introspection_data,
3442                                               const GDBusInterfaceVTable *vtable,
3443                                               GMainContext               *main_context,
3444                                               gpointer                    user_data)
3445 {
3446   gboolean handled;
3447   const char *interface_name;
3448   GSource *idle_source;
3449   PropertyGetAllData *property_get_all_data;
3450
3451   handled = FALSE;
3452
3453   g_variant_get (g_dbus_message_get_body (message),
3454                  "(s)",
3455                  &interface_name);
3456
3457   if (vtable == NULL || vtable->get_property == NULL)
3458     goto out;
3459
3460   /* ok, got the property info - call user in an idle handler */
3461   property_get_all_data = g_new0 (PropertyGetAllData, 1);
3462   property_get_all_data->connection = g_object_ref (connection);
3463   property_get_all_data->message = g_object_ref (message);
3464   property_get_all_data->user_data = user_data;
3465   property_get_all_data->vtable = vtable;
3466   property_get_all_data->interface_info = introspection_data;
3467
3468   idle_source = g_idle_source_new ();
3469   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3470   g_source_set_callback (idle_source,
3471                          invoke_get_all_properties_in_idle_cb,
3472                          property_get_all_data,
3473                          (GDestroyNotify) property_get_all_data_free);
3474   g_source_attach (idle_source, main_context);
3475   g_source_unref (idle_source);
3476
3477   handled = TRUE;
3478
3479  out:
3480   return handled;
3481 }
3482
3483 /* called with lock held */
3484 static gboolean
3485 handle_get_all_properties (GDBusConnection *connection,
3486                            ExportedObject  *eo,
3487                            GDBusMessage    *message)
3488 {
3489   ExportedInterface *ei;
3490   gboolean handled;
3491   const char *interface_name;
3492
3493   handled = FALSE;
3494
3495   g_variant_get (g_dbus_message_get_body (message),
3496                  "(s)",
3497                  &interface_name);
3498
3499   /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
3500    * no such interface registered
3501    */
3502   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
3503   if (ei == NULL)
3504     {
3505       GDBusMessage *reply;
3506       reply = g_dbus_message_new_method_error (message,
3507                                                "org.freedesktop.DBus.Error.InvalidArgs",
3508                                                _("No such interface"),
3509                                                interface_name);
3510       g_dbus_connection_send_message_unlocked (eo->connection, reply, NULL, NULL);
3511       g_object_unref (reply);
3512       handled = TRUE;
3513       goto out;
3514     }
3515
3516   handled = validate_and_maybe_schedule_property_get_all (eo->connection,
3517                                                           message,
3518                                                           ei->introspection_data,
3519                                                           ei->vtable,
3520                                                           ei->context,
3521                                                           ei->user_data);
3522  out:
3523   return handled;
3524 }
3525
3526 /* ---------------------------------------------------------------------------------------------------- */
3527
3528 static const gchar introspect_header[] =
3529   "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
3530   "                      \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
3531   "<!-- GDBus " PACKAGE_VERSION " -->\n"
3532   "<node>\n";
3533
3534 static const gchar introspect_tail[] =
3535   "</node>\n";
3536
3537 static const gchar introspect_standard_interfaces[] =
3538   "  <interface name=\"org.freedesktop.DBus.Properties\">\n"
3539   "    <method name=\"Get\">\n"
3540   "      <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
3541   "      <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
3542   "      <arg type=\"v\" name=\"value\" direction=\"out\"/>\n"
3543   "    </method>\n"
3544   "    <method name=\"GetAll\">\n"
3545   "      <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
3546   "      <arg type=\"a{sv}\" name=\"properties\" direction=\"out\"/>\n"
3547   "    </method>\n"
3548   "    <method name=\"Set\">\n"
3549   "      <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
3550   "      <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
3551   "      <arg type=\"v\" name=\"value\" direction=\"in\"/>\n"
3552   "    </method>\n"
3553   "    <signal name=\"PropertiesChanged\">\n"
3554   "      <arg type=\"s\" name=\"interface_name\"/>\n"
3555   "      <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"
3556   "    </signal>\n"
3557   "  </interface>\n"
3558   "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
3559   "    <method name=\"Introspect\">\n"
3560   "      <arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
3561   "    </method>\n"
3562   "  </interface>\n"
3563   "  <interface name=\"org.freedesktop.DBus.Peer\">\n"
3564   "    <method name=\"Ping\"/>\n"
3565   "    <method name=\"GetMachineId\">\n"
3566   "      <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n"
3567   "    </method>\n"
3568   "  </interface>\n";
3569
3570 static void
3571 introspect_append_header (GString *s)
3572 {
3573   g_string_append (s, introspect_header);
3574 }
3575
3576 static void
3577 introspect_append_standard_interfaces (GString *s)
3578 {
3579   g_string_append (s, introspect_standard_interfaces);
3580 }
3581
3582 static void
3583 maybe_add_path (const gchar *path, gsize path_len, const gchar *object_path, GHashTable *set)
3584 {
3585   if (g_str_has_prefix (object_path, path) && strlen (object_path) >= path_len)
3586     {
3587       const gchar *begin;
3588       const gchar *end;
3589       gchar *s;
3590
3591       begin = object_path + path_len;
3592       end = strchr (begin, '/');
3593
3594       if (end != NULL)
3595         s = g_strndup (begin, end - begin);
3596       else
3597         s = g_strdup (begin);
3598
3599       if (g_hash_table_lookup (set, s) == NULL)
3600         g_hash_table_insert (set, s, GUINT_TO_POINTER (1));
3601       else
3602         g_free (s);
3603     }
3604 }
3605
3606 /* TODO: we want a nicer public interface for this */
3607 static gchar **
3608 g_dbus_connection_list_registered_unlocked (GDBusConnection *connection,
3609                                             const gchar     *path)
3610 {
3611   GPtrArray *p;
3612   gchar **ret;
3613   GHashTableIter hash_iter;
3614   const gchar *object_path;
3615   gsize path_len;
3616   GHashTable *set;
3617   GList *keys;
3618   GList *l;
3619
3620   CONNECTION_ENSURE_LOCK (connection);
3621
3622   path_len = strlen (path);
3623   if (path_len > 1)
3624     path_len++;
3625
3626   set = g_hash_table_new (g_str_hash, g_str_equal);
3627
3628   g_hash_table_iter_init (&hash_iter, connection->priv->map_object_path_to_eo);
3629   while (g_hash_table_iter_next (&hash_iter, (gpointer) &object_path, NULL))
3630     maybe_add_path (path, path_len, object_path, set);
3631
3632   g_hash_table_iter_init (&hash_iter, connection->priv->map_object_path_to_es);
3633   while (g_hash_table_iter_next (&hash_iter, (gpointer) &object_path, NULL))
3634     maybe_add_path (path, path_len, object_path, set);
3635
3636   p = g_ptr_array_new ();
3637   keys = g_hash_table_get_keys (set);
3638   for (l = keys; l != NULL; l = l->next)
3639     g_ptr_array_add (p, l->data);
3640   g_hash_table_unref (set);
3641   g_list_free (keys);
3642
3643   g_ptr_array_add (p, NULL);
3644   ret = (gchar **) g_ptr_array_free (p, FALSE);
3645   return ret;
3646 }
3647
3648 static gchar **
3649 g_dbus_connection_list_registered (GDBusConnection *connection,
3650                                    const gchar     *path)
3651 {
3652   gchar **ret;
3653   CONNECTION_LOCK (connection);
3654   ret = g_dbus_connection_list_registered_unlocked (connection, path);
3655   CONNECTION_UNLOCK (connection);
3656   return ret;
3657 }
3658
3659 /* called in message handler thread with lock held */
3660 static gboolean
3661 handle_introspect (GDBusConnection *connection,
3662                    ExportedObject  *eo,
3663                    GDBusMessage    *message)
3664 {
3665   guint n;
3666   GString *s;
3667   GDBusMessage *reply;
3668   GHashTableIter hash_iter;
3669   ExportedInterface *ei;
3670   gchar **registered;
3671
3672   /* first the header with the standard interfaces */
3673   s = g_string_sized_new (sizeof (introspect_header) +
3674                           sizeof (introspect_standard_interfaces) +
3675                           sizeof (introspect_tail));
3676   introspect_append_header (s);
3677   introspect_append_standard_interfaces (s);
3678
3679   /* then include the registered interfaces */
3680   g_hash_table_iter_init (&hash_iter, eo->map_if_name_to_ei);
3681   while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &ei))
3682     g_dbus_interface_info_generate_xml (ei->introspection_data, 2, s);
3683
3684   /* finally include nodes registered below us */
3685   registered = g_dbus_connection_list_registered_unlocked (connection, eo->object_path);
3686   for (n = 0; registered != NULL && registered[n] != NULL; n++)
3687     g_string_append_printf (s, "  <node name=\"%s\"/>\n", registered[n]);
3688   g_strfreev (registered);
3689   g_string_append (s, introspect_tail);
3690
3691   reply = g_dbus_message_new_method_reply (message);
3692   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
3693   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3694   g_object_unref (reply);
3695   g_string_free (s, TRUE);
3696
3697   return TRUE;
3698 }
3699
3700 /* called in thread where object was registered - no locks held */
3701 static gboolean
3702 call_in_idle_cb (gpointer user_data)
3703 {
3704   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
3705   GDBusInterfaceVTable *vtable;
3706
3707   vtable = g_object_get_data (G_OBJECT (invocation), "g-dbus-interface-vtable");
3708   g_assert (vtable != NULL && vtable->method_call != NULL);
3709
3710   vtable->method_call (g_dbus_method_invocation_get_connection (invocation),
3711                        g_dbus_method_invocation_get_sender (invocation),
3712                        g_dbus_method_invocation_get_object_path (invocation),
3713                        g_dbus_method_invocation_get_interface_name (invocation),
3714                        g_dbus_method_invocation_get_method_name (invocation),
3715                        g_dbus_method_invocation_get_parameters (invocation),
3716                        g_object_ref (invocation),
3717                        g_dbus_method_invocation_get_user_data (invocation));
3718
3719   return FALSE;
3720 }
3721
3722 /* called in message handler thread with lock held */
3723 static gboolean
3724 validate_and_maybe_schedule_method_call (GDBusConnection            *connection,
3725                                          GDBusMessage               *message,
3726                                          const GDBusInterfaceInfo   *introspection_data,
3727                                          const GDBusInterfaceVTable *vtable,
3728                                          GMainContext               *main_context,
3729                                          gpointer                    user_data)
3730 {
3731   GDBusMethodInvocation *invocation;
3732   const GDBusMethodInfo *method_info;
3733   GDBusMessage *reply;
3734   GVariant *parameters;
3735   GSource *idle_source;
3736   gboolean handled;
3737   gchar *in_signature;
3738
3739   handled = FALSE;
3740
3741   /* TODO: the cost of this is O(n) - it might be worth caching the result */
3742   method_info = g_dbus_interface_info_lookup_method (introspection_data, g_dbus_message_get_member (message));
3743
3744   /* if the method doesn't exist, return the org.freedesktop.DBus.Error.UnknownMethod
3745    * error to the caller
3746    */
3747   if (method_info == NULL)
3748     {
3749       reply = g_dbus_message_new_method_error (message,
3750                                                "org.freedesktop.DBus.Error.UnknownMethod",
3751                                                _("No such method `%s'"),
3752                                                g_dbus_message_get_member (message));
3753       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3754       g_object_unref (reply);
3755       handled = TRUE;
3756       goto out;
3757     }
3758
3759   /* Check that the incoming args are of the right type - if they are not, return
3760    * the org.freedesktop.DBus.Error.InvalidArgs error to the caller
3761    *
3762    * TODO: might also be worth caching the combined signature.
3763    */
3764   in_signature = _g_dbus_compute_complete_signature (method_info->in_args, FALSE);
3765   if (g_strcmp0 (g_dbus_message_get_signature (message), in_signature) != 0)
3766     {
3767       reply = g_dbus_message_new_method_error (message,
3768                                                "org.freedesktop.DBus.Error.InvalidArgs",
3769                                                _("Signature of message, `%s', does not match expected signature `%s'"),
3770                                                g_dbus_message_get_signature (message),
3771                                                in_signature);
3772       g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
3773       g_object_unref (reply);
3774       g_free (in_signature);
3775       handled = TRUE;
3776       goto out;
3777     }
3778   g_free (in_signature);
3779
3780   parameters = g_dbus_message_get_body (message);
3781   if (parameters == NULL)
3782     {
3783       parameters = g_variant_new ("()");
3784       g_variant_ref_sink (parameters);
3785     }
3786   else
3787     {
3788       g_variant_ref (parameters);
3789     }
3790
3791   /* schedule the call in idle */
3792   invocation = g_dbus_method_invocation_new (g_dbus_message_get_sender (message),
3793                                              g_dbus_message_get_path (message),
3794                                              g_dbus_message_get_interface (message),
3795                                              g_dbus_message_get_member (message),
3796                                              method_info,
3797                                              connection,
3798                                              message,
3799                                              parameters,
3800                                              user_data);
3801   g_variant_unref (parameters);
3802   g_object_set_data (G_OBJECT (invocation),
3803                      "g-dbus-interface-vtable",
3804                      (gpointer) vtable);
3805
3806   idle_source = g_idle_source_new ();
3807   g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3808   g_source_set_callback (idle_source,
3809                          call_in_idle_cb,
3810                          invocation,
3811                          g_object_unref);
3812   g_source_attach (idle_source, main_context);
3813   g_source_unref (idle_source);
3814
3815   handled = TRUE;
3816
3817  out:
3818   return handled;
3819 }
3820
3821 /* ---------------------------------------------------------------------------------------------------- */
3822
3823 /* called in message handler thread with lock held */
3824 static gboolean
3825 obj_message_func (GDBusConnection *connection,
3826                   ExportedObject  *eo,
3827                   GDBusMessage    *message)
3828 {
3829   const gchar *interface_name;
3830   const gchar *member;
3831   const gchar *signature;
3832   gboolean handled;
3833
3834   handled = FALSE;
3835
3836   interface_name = g_dbus_message_get_interface (message);
3837   member = g_dbus_message_get_member (message);
3838   signature = g_dbus_message_get_signature (message);
3839
3840   /* see if we have an interface for handling this call */
3841   if (interface_name != NULL)
3842     {
3843       ExportedInterface *ei;
3844       ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
3845       if (ei != NULL)
3846         {
3847           /* we do - invoke the handler in idle in the right thread */
3848
3849           /* handle no vtable or handler being present */
3850           if (ei->vtable == NULL || ei->vtable->method_call == NULL)
3851             goto out;
3852
3853           handled = validate_and_maybe_schedule_method_call (connection,
3854                                                              message,
3855                                                              ei->introspection_data,
3856                                                              ei->vtable,
3857                                                              ei->context,
3858                                                              ei->user_data);
3859           goto out;
3860         }
3861     }
3862
3863   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
3864       g_strcmp0 (member, "Introspect") == 0 &&
3865       g_strcmp0 (signature, "") == 0)
3866     {
3867       handled = handle_introspect (connection, eo, message);
3868       goto out;
3869     }
3870   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
3871            g_strcmp0 (member, "Get") == 0 &&
3872            g_strcmp0 (signature, "ss") == 0)
3873     {
3874       handled = handle_getset_property (connection, eo, message, TRUE);
3875       goto out;
3876     }
3877   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
3878            g_strcmp0 (member, "Set") == 0 &&
3879            g_strcmp0 (signature, "ssv") == 0)
3880     {
3881       handled = handle_getset_property (connection, eo, message, FALSE);
3882       goto out;
3883     }
3884   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
3885            g_strcmp0 (member, "GetAll") == 0 &&
3886            g_strcmp0 (signature, "s") == 0)
3887     {
3888       handled = handle_get_all_properties (connection, eo, message);
3889       goto out;
3890     }
3891
3892  out:
3893   return handled;
3894 }
3895
3896 /**
3897  * g_dbus_connection_register_object:
3898  * @connection: A #GDBusConnection.
3899  * @object_path: The object path to register at.
3900  * @interface_name: The D-Bus interface to register.
3901  * @introspection_data: Introspection data for the interface.
3902  * @vtable: A #GDBusInterfaceVTable to call into or %NULL.
3903  * @user_data: Data to pass to functions in @vtable.
3904  * @user_data_free_func: Function to call when the object path is unregistered.
3905  * @error: Return location for error or %NULL.
3906  *
3907  * Registers callbacks for exported objects at @object_path with the
3908  * D-Bus interface @interface_name.
3909  *
3910  * Calls to functions in @vtable (and @user_data_free_func) will
3911  * happen in the <link linkend="g-main-context-push-thread-default">thread-default main
3912  * loop</link> of the thread you are calling this method from.
3913  *
3914  * Note that all #GVariant values passed to functions in @vtable will match
3915  * the signature given in @introspection_data - if a remote caller passes
3916  * incorrect values, the <literal>org.freedesktop.DBus.Error.InvalidArgs</literal>
3917  * is returned to the remote caller.
3918  *
3919  * Additionally, if the remote caller attempts to invoke methods or
3920  * access properties not mentioned in @introspection_data the
3921  * <literal>org.freedesktop.DBus.Error.UnknownMethod</literal> resp.
3922  * <literal>org.freedesktop.DBus.Error.InvalidArgs</literal> errors
3923  * are returned to the caller.
3924  *
3925  * It is considered a programming error if the
3926  * #GDBusInterfaceGetPropertyFunc function in @vtable returns a
3927  * #GVariant of incorrect type.
3928  *
3929  * If an existing callback is already registered at @object_path and
3930  * @interface_name, then @error is set to #G_IO_ERROR_EXISTS.
3931  *
3932  * See <xref linkend="gdbus-server"/> for an example of how to use this method.
3933  *
3934  * Returns: 0 if @error is set, otherwise a registration id (never 0)
3935  * that can be used with g_dbus_connection_unregister_object() .
3936  *
3937  * Since: 2.26
3938  */
3939 guint
3940 g_dbus_connection_register_object (GDBusConnection            *connection,
3941                                    const gchar                *object_path,
3942                                    const gchar                *interface_name,
3943                                    const GDBusInterfaceInfo   *introspection_data,
3944                                    const GDBusInterfaceVTable *vtable,
3945                                    gpointer                    user_data,
3946                                    GDestroyNotify              user_data_free_func,
3947                                    GError                    **error)
3948 {
3949   ExportedObject *eo;
3950   ExportedInterface *ei;
3951   guint ret;
3952
3953   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
3954   g_return_val_if_fail (!g_dbus_connection_is_closed (connection), 0);
3955   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
3956   g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), 0);
3957   g_return_val_if_fail (introspection_data != NULL, 0);
3958   g_return_val_if_fail (error == NULL || *error == NULL, 0);
3959
3960   ret = 0;
3961
3962   CONNECTION_LOCK (connection);
3963
3964   eo = g_hash_table_lookup (connection->priv->map_object_path_to_eo, object_path);
3965   if (eo == NULL)
3966     {
3967       eo = g_new0 (ExportedObject, 1);
3968       eo->object_path = g_strdup (object_path);
3969       eo->connection = connection;
3970       eo->map_if_name_to_ei = g_hash_table_new_full (g_str_hash,
3971                                                      g_str_equal,
3972                                                      NULL,
3973                                                      (GDestroyNotify) exported_interface_free);
3974       g_hash_table_insert (connection->priv->map_object_path_to_eo, eo->object_path, eo);
3975     }
3976
3977   ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
3978   if (ei != NULL)
3979     {
3980       g_set_error (error,
3981                    G_IO_ERROR,
3982                    G_IO_ERROR_EXISTS,
3983                    _("An object is already exported for the interface %s at %s"),
3984                    interface_name,
3985                    object_path);
3986       goto out;
3987     }
3988
3989   ei = g_new0 (ExportedInterface, 1);
3990   ei->id = _global_registration_id++; /* TODO: overflow etc. */
3991   ei->eo = eo;
3992   ei->user_data = user_data;
3993   ei->user_data_free_func = user_data_free_func;
3994   ei->vtable = vtable;
3995   ei->introspection_data = introspection_data;
3996   ei->interface_name = g_strdup (interface_name);
3997   ei->context = g_main_context_get_thread_default ();
3998   if (ei->context != NULL)
3999     g_main_context_ref (ei->context);
4000
4001   g_hash_table_insert (eo->map_if_name_to_ei,
4002                        (gpointer) ei->interface_name,
4003                        ei);
4004   g_hash_table_insert (connection->priv->map_id_to_ei,
4005                        GUINT_TO_POINTER (ei->id),
4006                        ei);
4007
4008   ret = ei->id;
4009
4010  out:
4011   CONNECTION_UNLOCK (connection);
4012
4013   return ret;
4014 }
4015
4016 /**
4017  * g_dbus_connection_unregister_object:
4018  * @connection: A #GDBusConnection.
4019  * @registration_id: A registration id obtained from g_dbus_connection_register_object().
4020  *
4021  * Unregisters an object.
4022  *
4023  * Returns: %TRUE if the object was unregistered, %FALSE otherwise.
4024  *
4025  * Since: 2.26
4026  */
4027 gboolean
4028 g_dbus_connection_unregister_object (GDBusConnection *connection,
4029                                      guint            registration_id)
4030 {
4031   ExportedInterface *ei;
4032   ExportedObject *eo;
4033   gboolean ret;
4034
4035   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
4036
4037   ret = FALSE;
4038
4039   CONNECTION_LOCK (connection);
4040
4041   ei = g_hash_table_lookup (connection->priv->map_id_to_ei,
4042                             GUINT_TO_POINTER (registration_id));
4043   if (ei == NULL)
4044     goto out;
4045
4046   eo = ei->eo;
4047
4048   g_warn_if_fail (g_hash_table_remove (connection->priv->map_id_to_ei, GUINT_TO_POINTER (ei->id)));
4049   g_warn_if_fail (g_hash_table_remove (eo->map_if_name_to_ei, ei->interface_name));
4050   /* unregister object path if we have no more exported interfaces */
4051   if (g_hash_table_size (eo->map_if_name_to_ei) == 0)
4052     g_warn_if_fail (g_hash_table_remove (connection->priv->map_object_path_to_eo,
4053                                          eo->object_path));
4054
4055   ret = TRUE;
4056
4057  out:
4058   CONNECTION_UNLOCK (connection);
4059
4060   return ret;
4061 }
4062
4063 /* ---------------------------------------------------------------------------------------------------- */
4064
4065 /**
4066  * g_dbus_connection_emit_signal:
4067  * @connection: A #GDBusConnection.
4068  * @destination_bus_name: The unique bus name for the destination for the signal or %NULL to emit to all listeners.
4069  * @object_path: Path of remote object.
4070  * @interface_name: D-Bus interface to emit a signal on.
4071  * @signal_name: The name of the signal to emit.
4072  * @parameters: A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
4073  * @error: Return location for error or %NULL.
4074  *
4075  * Emits a signal.
4076  *
4077  * This can only fail if @parameters is not compatible with the D-Bus protocol.
4078  *
4079  * Returns: %TRUE unless @error is set.
4080  *
4081  * Since: 2.26
4082  */
4083 gboolean
4084 g_dbus_connection_emit_signal (GDBusConnection  *connection,
4085                                const gchar      *destination_bus_name,
4086                                const gchar      *object_path,
4087                                const gchar      *interface_name,
4088                                const gchar      *signal_name,
4089                                GVariant         *parameters,
4090                                GError          **error)
4091 {
4092   GDBusMessage *message;
4093   gboolean ret;
4094
4095   message = NULL;
4096   ret = FALSE;
4097
4098   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
4099   g_return_val_if_fail (destination_bus_name == NULL || g_dbus_is_name (destination_bus_name), FALSE);
4100   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), FALSE);
4101   g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), FALSE);
4102   g_return_val_if_fail (signal_name != NULL && g_dbus_is_member_name (signal_name), FALSE);
4103   g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), FALSE);
4104
4105   message = g_dbus_message_new_signal (object_path,
4106                                        interface_name,
4107                                        signal_name);
4108
4109   if (destination_bus_name != NULL)
4110     g_dbus_message_set_header (message,
4111                                G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION,
4112                                g_variant_new_string (destination_bus_name));
4113
4114   if (parameters != NULL)
4115     g_dbus_message_set_body (message, parameters);
4116
4117   ret = g_dbus_connection_send_message (connection, message, NULL, error);
4118   g_object_unref (message);
4119
4120   return ret;
4121 }
4122
4123 static void
4124 add_call_flags (GDBusMessage           *message,
4125                          GDBusCallFlags  flags)
4126 {
4127   if (flags & G_DBUS_CALL_FLAGS_NO_AUTO_START)
4128     g_dbus_message_set_flags (message, G_DBUS_MESSAGE_FLAGS_NO_AUTO_START);
4129 }
4130
4131 /**
4132  * g_dbus_connection_call:
4133  * @connection: A #GDBusConnection.
4134  * @bus_name: A unique or well-known bus name or %NULL if @connection is not a message bus connection.
4135  * @object_path: Path of remote object.
4136  * @interface_name: D-Bus interface to invoke method on.
4137  * @method_name: The name of the method to invoke.
4138  * @parameters: A #GVariant tuple with parameters for the method or %NULL if not passing parameters.
4139  * @flags: Flags from the #GDBusCallFlags enumeration.
4140  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
4141  * @cancellable: A #GCancellable or %NULL.
4142  * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
4143  * care about the result of the method invocation.
4144  * @user_data: The data to pass to @callback.
4145  *
4146  * Asynchronously invokes the @method_name method on the
4147  * @interface_name D-Bus interface on the remote object at
4148  * @object_path owned by @bus_name.
4149  *
4150  * If @connection is closed then the operation will fail with
4151  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
4152  * fail with %G_IO_ERROR_CANCELLED. If @parameters contains a value
4153  * not compatible with the D-Bus protocol, the operation fails with
4154  * %G_IO_ERROR_INVALID_ARGUMENT.
4155  *
4156  * This is an asynchronous method. When the operation is finished, @callback will be invoked
4157  * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
4158  * of the thread you are calling this method from. You can then call
4159  * g_dbus_connection_call_finish() to get the result of the operation.
4160  * See g_dbus_connection_call_sync() for the synchronous version of this
4161  * function.
4162  *
4163  * Since: 2.26
4164  */
4165 void
4166 g_dbus_connection_call (GDBusConnection        *connection,
4167                         const gchar            *bus_name,
4168                         const gchar            *object_path,
4169                         const gchar            *interface_name,
4170                         const gchar            *method_name,
4171                         GVariant               *parameters,
4172                         GDBusCallFlags          flags,
4173                         gint                    timeout_msec,
4174                         GCancellable           *cancellable,
4175                         GAsyncReadyCallback     callback,
4176                         gpointer                user_data)
4177 {
4178   GDBusMessage *message;
4179
4180   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
4181   g_return_if_fail (bus_name == NULL || g_dbus_is_name (bus_name));
4182   g_return_if_fail (object_path != NULL && g_variant_is_object_path (object_path));
4183   g_return_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name));
4184   g_return_if_fail (method_name != NULL && g_dbus_is_member_name (method_name));
4185   g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
4186   g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
4187
4188   message = g_dbus_message_new_method_call (bus_name,
4189                                             object_path,
4190                                             interface_name,
4191                                             method_name);
4192   add_call_flags (message, flags);
4193   if (parameters != NULL)
4194     g_dbus_message_set_body (message, parameters);
4195
4196   g_dbus_connection_send_message_with_reply (connection,
4197                                              message,
4198                                              timeout_msec,
4199                                              NULL, /* volatile guint32 *out_serial */
4200                                              cancellable,
4201                                              callback,
4202                                              user_data);
4203
4204   if (message != NULL)
4205     g_object_unref (message);
4206 }
4207
4208 static GVariant *
4209 decode_method_reply (GDBusMessage  *reply,
4210                      GError       **error)
4211 {
4212   GVariant *result;
4213
4214   result = NULL;
4215   switch (g_dbus_message_get_message_type (reply))
4216     {
4217     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
4218       result = g_dbus_message_get_body (reply);
4219       if (result == NULL)
4220         {
4221           result = g_variant_new ("()");
4222           g_variant_ref_sink (result);
4223         }
4224       else
4225         {
4226           g_variant_ref (result);
4227         }
4228       break;
4229
4230     case G_DBUS_MESSAGE_TYPE_ERROR:
4231       g_dbus_message_to_gerror (reply, error);
4232       break;
4233
4234     default:
4235       g_assert_not_reached ();
4236       break;
4237     }
4238
4239   return result;
4240 }
4241
4242 /**
4243  * g_dbus_connection_call_finish:
4244  * @connection: A #GDBusConnection.
4245  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_call().
4246  * @error: Return location for error or %NULL.
4247  *
4248  * Finishes an operation started with g_dbus_connection_call().
4249  *
4250  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
4251  * return values. Free with g_variant_unref().
4252  *
4253  * Since: 2.26
4254  */
4255 GVariant *
4256 g_dbus_connection_call_finish (GDBusConnection  *connection,
4257                                GAsyncResult     *res,
4258                                GError          **error)
4259 {
4260   GDBusMessage *reply;
4261   GVariant *result;
4262
4263   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
4264   g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
4265   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
4266
4267   result = NULL;
4268
4269   reply = g_dbus_connection_send_message_with_reply_finish (connection, res, error);
4270   if (reply == NULL)
4271     goto out;
4272
4273   result = decode_method_reply (reply, error);
4274
4275   g_object_unref (reply);
4276
4277  out:
4278   return result;
4279 }
4280
4281 /* ---------------------------------------------------------------------------------------------------- */
4282
4283 /**
4284  * g_dbus_connection_call_sync:
4285  * @connection: A #GDBusConnection.
4286  * @bus_name: A unique or well-known bus name.
4287  * @object_path: Path of remote object.
4288  * @interface_name: D-Bus interface to invoke method on.
4289  * @method_name: The name of the method to invoke.
4290  * @parameters: A #GVariant tuple with parameters for the method or %NULL if not passing parameters.
4291  * @flags: Flags from the #GDBusCallFlags enumeration.
4292  * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
4293  * @cancellable: A #GCancellable or %NULL.
4294  * @error: Return location for error or %NULL.
4295  *
4296  * Synchronously invokes the @method_name method on the
4297  * @interface_name D-Bus interface on the remote object at
4298  * @object_path owned by @bus_name.
4299  *
4300  * If @connection is closed then the operation will fail with
4301  * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the
4302  * operation will fail with %G_IO_ERROR_CANCELLED. If @parameters
4303  * contains a value not compatible with the D-Bus protocol, the operation
4304  * fails with %G_IO_ERROR_INVALID_ARGUMENT.
4305  *
4306  * The calling thread is blocked until a reply is received. See
4307  * g_dbus_connection_call() for the asynchronous version of
4308  * this method.
4309  *
4310  * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
4311  * return values. Free with g_variant_unref().
4312  *
4313  * Since: 2.26
4314  */
4315 GVariant *
4316 g_dbus_connection_call_sync (GDBusConnection         *connection,
4317                              const gchar             *bus_name,
4318                              const gchar             *object_path,
4319                              const gchar             *interface_name,
4320                              const gchar             *method_name,
4321                              GVariant                *parameters,
4322                              GDBusCallFlags           flags,
4323                              gint                     timeout_msec,
4324                              GCancellable            *cancellable,
4325                              GError                 **error)
4326 {
4327   GDBusMessage *message;
4328   GDBusMessage *reply;
4329   GVariant *result;
4330
4331   message = NULL;
4332   reply = NULL;
4333   result = NULL;
4334
4335   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
4336   g_return_val_if_fail (bus_name == NULL || g_dbus_is_name (bus_name), NULL);
4337   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), NULL);
4338   g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), NULL);
4339   g_return_val_if_fail (method_name != NULL && g_dbus_is_member_name (method_name), NULL);
4340   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
4341   g_return_val_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
4342
4343   message = g_dbus_message_new_method_call (bus_name,
4344                                             object_path,
4345                                             interface_name,
4346                                             method_name);
4347   add_call_flags (message, flags);
4348   if (parameters != NULL)
4349     g_dbus_message_set_body (message, parameters);
4350
4351   reply = g_dbus_connection_send_message_with_reply_sync (connection,
4352                                                           message,
4353                                                           timeout_msec,
4354                                                           NULL, /* volatile guint32 *out_serial */
4355                                                           cancellable,
4356                                                           error);
4357
4358   if (reply == NULL)
4359     goto out;
4360
4361   result = decode_method_reply (reply, error);
4362
4363  out:
4364   if (message != NULL)
4365     g_object_unref (message);
4366   if (reply != NULL)
4367     g_object_unref (reply);
4368
4369   return result;
4370 }
4371
4372 /* ---------------------------------------------------------------------------------------------------- */
4373
4374 struct ExportedSubtree
4375 {
4376   guint                     id;
4377   gchar                    *object_path;
4378   GDBusConnection          *connection;
4379   const GDBusSubtreeVTable *vtable;
4380   GDBusSubtreeFlags         flags;
4381
4382   GMainContext             *context;
4383   gpointer                  user_data;
4384   GDestroyNotify            user_data_free_func;
4385 };
4386
4387 static void
4388 exported_subtree_free (ExportedSubtree *es)
4389 {
4390   if (es->user_data_free_func != NULL)
4391     /* TODO: push to thread-default mainloop */
4392     es->user_data_free_func (es->user_data);
4393
4394   if (es->context != NULL)
4395     g_main_context_unref (es->context);
4396
4397   g_free (es->object_path);
4398   g_free (es);
4399 }
4400
4401 /* called without lock held */
4402 static gboolean
4403 handle_subtree_introspect (GDBusConnection *connection,
4404                            ExportedSubtree *es,
4405                            GDBusMessage    *message)
4406 {
4407   GString *s;
4408   gboolean handled;
4409   GDBusMessage *reply;
4410   gchar **children;
4411   gboolean is_root;
4412   const gchar *sender;
4413   const gchar *requested_object_path;
4414   const gchar *requested_node;
4415   GPtrArray *interfaces;
4416   guint n;
4417   gchar **subnode_paths;
4418
4419   handled = FALSE;
4420
4421   requested_object_path = g_dbus_message_get_path (message);
4422   sender = g_dbus_message_get_sender (message);
4423   is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
4424
4425   s = g_string_new (NULL);
4426   introspect_append_header (s);
4427
4428   /* Strictly we don't need the children in dynamic mode, but we avoid the
4429    * conditionals to preserve code clarity
4430    */
4431   children = es->vtable->enumerate (es->connection,
4432                                     sender,
4433                                     es->object_path,
4434                                     es->user_data);
4435
4436   if (!is_root)
4437     {
4438       requested_node = strrchr (requested_object_path, '/') + 1;
4439
4440       /* Assert existence of object if we are not dynamic */
4441       if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
4442           !_g_strv_has_string ((const gchar * const *) children, requested_node))
4443         goto out;
4444     }
4445   else
4446     {
4447       requested_node = "/";
4448     }
4449
4450   interfaces = es->vtable->introspect (es->connection,
4451                                        sender,
4452                                        es->object_path,
4453                                        requested_node,
4454                                        es->user_data);
4455   if (interfaces != NULL)
4456     {
4457       if (interfaces->len > 0)
4458         {
4459           /* we're in business */
4460           introspect_append_standard_interfaces (s);
4461
4462           for (n = 0; n < interfaces->len; n++)
4463             {
4464               const GDBusInterfaceInfo *interface_info = interfaces->pdata[n];
4465               g_dbus_interface_info_generate_xml (interface_info, 2, s);
4466             }
4467         }
4468       g_ptr_array_unref (interfaces);
4469     }
4470
4471   /* then include <node> entries from the Subtree for the root */
4472   if (is_root)
4473     {
4474       for (n = 0; children != NULL && children[n] != NULL; n++)
4475         g_string_append_printf (s, "  <node name=\"%s\"/>\n", children[n]);
4476     }
4477
4478   /* finally include nodes registered below us */
4479   subnode_paths = g_dbus_connection_list_registered (es->connection, requested_object_path);
4480   for (n = 0; subnode_paths != NULL && subnode_paths[n] != NULL; n++)
4481     g_string_append_printf (s, "  <node name=\"%s\"/>\n", subnode_paths[n]);
4482   g_strfreev (subnode_paths);
4483
4484   g_string_append (s, "</node>\n");
4485
4486   reply = g_dbus_message_new_method_reply (message);
4487   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
4488   g_dbus_connection_send_message (connection, reply, NULL, NULL);
4489   g_object_unref (reply);
4490
4491   handled = TRUE;
4492
4493  out:
4494   g_string_free (s, TRUE);
4495   g_strfreev (children);
4496   return handled;
4497 }
4498
4499 /* called without lock held */
4500 static gboolean
4501 handle_subtree_method_invocation (GDBusConnection *connection,
4502                                   ExportedSubtree *es,
4503                                   GDBusMessage    *message)
4504 {
4505   gboolean handled;;
4506   const gchar *sender;
4507   const gchar *interface_name;
4508   const gchar *member;
4509   const gchar *signature;
4510   const gchar *requested_object_path;
4511   const gchar *requested_node;
4512   gboolean is_root;
4513   gchar **children;
4514   const GDBusInterfaceInfo *introspection_data;
4515   const GDBusInterfaceVTable *interface_vtable;
4516   gpointer interface_user_data;
4517   guint n;
4518   GPtrArray *interfaces;
4519   gboolean is_property_get;
4520   gboolean is_property_set;
4521   gboolean is_property_get_all;
4522
4523   handled = FALSE;
4524   interfaces = NULL;
4525
4526   requested_object_path = g_dbus_message_get_path (message);
4527   sender = g_dbus_message_get_sender (message);
4528   interface_name = g_dbus_message_get_interface (message);
4529   member = g_dbus_message_get_member (message);
4530   signature = g_dbus_message_get_signature (message);
4531   is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
4532
4533   is_property_get = FALSE;
4534   is_property_set = FALSE;
4535   is_property_get_all = FALSE;
4536   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0)
4537     {
4538       if (g_strcmp0 (member, "Get") == 0 && g_strcmp0 (signature, "ss") == 0)
4539         is_property_get = TRUE;
4540       else if (g_strcmp0 (member, "Set") == 0 && g_strcmp0 (signature, "ssv") == 0)
4541         is_property_set = TRUE;
4542       else if (g_strcmp0 (member, "GetAll") == 0 && g_strcmp0 (signature, "s") == 0)
4543         is_property_get_all = TRUE;
4544     }
4545
4546   children = es->vtable->enumerate (es->connection,
4547                                     sender,
4548                                     es->object_path,
4549                                     es->user_data);
4550
4551   if (!is_root)
4552     {
4553       requested_node = strrchr (requested_object_path, '/') + 1;
4554
4555       /* If not dynamic, skip if requested node is not part of children */
4556       if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
4557           !_g_strv_has_string ((const gchar * const *) children, requested_node))
4558         goto out;
4559     }
4560   else
4561     {
4562       requested_node = "/";
4563     }
4564
4565   /* get introspection data for the node */
4566   interfaces = es->vtable->introspect (es->connection,
4567                                        sender,
4568                                        requested_object_path,
4569                                        requested_node,
4570                                        es->user_data);
4571   g_assert (interfaces != NULL);
4572   introspection_data = NULL;
4573   for (n = 0; n < interfaces->len; n++)
4574     {
4575       const GDBusInterfaceInfo *id_n = (const GDBusInterfaceInfo *) interfaces->pdata[n];
4576       if (g_strcmp0 (id_n->name, interface_name) == 0)
4577         introspection_data = id_n;
4578     }
4579
4580   /* dispatch the call if the user wants to handle it */
4581   if (introspection_data != NULL)
4582     {
4583       /* figure out where to dispatch the method call */
4584       interface_user_data = NULL;
4585       interface_vtable = es->vtable->dispatch (es->connection,
4586                                                sender,
4587                                                es->object_path,
4588                                                interface_name,
4589                                                requested_node,
4590                                                &interface_user_data,
4591                                                es->user_data);
4592       if (interface_vtable == NULL)
4593         goto out;
4594
4595       CONNECTION_LOCK (connection);
4596       handled = validate_and_maybe_schedule_method_call (es->connection,
4597                                                          message,
4598                                                          introspection_data,
4599                                                          interface_vtable,
4600                                                          es->context,
4601                                                          interface_user_data);
4602       CONNECTION_UNLOCK (connection);
4603     }
4604   /* handle org.freedesktop.DBus.Properties interface if not explicitly handled */
4605   else if (is_property_get || is_property_set || is_property_get_all)
4606     {
4607       if (is_property_get)
4608         g_variant_get (g_dbus_message_get_body (message), "(ss)", &interface_name, NULL);
4609       else if (is_property_set)
4610         g_variant_get (g_dbus_message_get_body (message), "(ssv)", &interface_name, NULL, NULL);
4611       else if (is_property_get_all)
4612         g_variant_get (g_dbus_message_get_body (message), "(s)", &interface_name, NULL, NULL);
4613       else
4614         g_assert_not_reached ();
4615
4616       /* see if the object supports this interface at all */
4617       for (n = 0; n < interfaces->len; n++)
4618         {
4619           const GDBusInterfaceInfo *id_n = (const GDBusInterfaceInfo *) interfaces->pdata[n];
4620           if (g_strcmp0 (id_n->name, interface_name) == 0)
4621             introspection_data = id_n;
4622         }
4623
4624       /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the user-code
4625        * claims it won't support the interface
4626        */
4627       if (introspection_data == NULL)
4628         {
4629           GDBusMessage *reply;
4630           reply = g_dbus_message_new_method_error (message,
4631                                                    "org.freedesktop.DBus.Error.InvalidArgs",
4632                                                    _("No such interface `%s'"),
4633                                                    interface_name);
4634           g_dbus_connection_send_message (es->connection, reply, NULL, NULL);
4635           g_object_unref (reply);
4636           handled = TRUE;
4637           goto out;
4638         }
4639
4640       /* figure out where to dispatch the property get/set/getall calls */
4641       interface_user_data = NULL;
4642       interface_vtable = es->vtable->dispatch (es->connection,
4643                                                sender,
4644                                                es->object_path,
4645                                                interface_name,
4646                                                requested_node,
4647                                                &interface_user_data,
4648                                                es->user_data);
4649       if (interface_vtable == NULL)
4650         goto out;
4651
4652       if (is_property_get || is_property_set)
4653         {
4654           CONNECTION_LOCK (connection);
4655           handled = validate_and_maybe_schedule_property_getset (es->connection,
4656                                                                  message,
4657                                                                  is_property_get,
4658                                                                  introspection_data,
4659                                                                  interface_vtable,
4660                                                                  es->context,
4661                                                                  interface_user_data);
4662           CONNECTION_UNLOCK (connection);
4663         }
4664       else if (is_property_get_all)
4665         {
4666           CONNECTION_LOCK (connection);
4667           handled = validate_and_maybe_schedule_property_get_all (es->connection,
4668                                                                   message,
4669                                                                   introspection_data,
4670                                                                   interface_vtable,
4671                                                                   es->context,
4672                                                                   interface_user_data);
4673           CONNECTION_UNLOCK (connection);
4674         }
4675     }
4676
4677  out:
4678   if (interfaces != NULL)
4679     g_ptr_array_unref (interfaces);
4680   g_strfreev (children);
4681   return handled;
4682 }
4683
4684 typedef struct
4685 {
4686   GDBusMessage *message;
4687   ExportedSubtree *es;
4688 } SubtreeDeferredData;
4689
4690 static void
4691 subtree_deferred_data_free (SubtreeDeferredData *data)
4692 {
4693   g_object_unref (data->message);
4694   g_free (data);
4695 }
4696
4697 /* called without lock held in the thread where the caller registered the subtree */
4698 static gboolean
4699 process_subtree_vtable_message_in_idle_cb (gpointer _data)
4700 {
4701   SubtreeDeferredData *data = _data;
4702   gboolean handled;
4703
4704   handled = FALSE;
4705
4706   if (g_strcmp0 (g_dbus_message_get_interface (data->message), "org.freedesktop.DBus.Introspectable") == 0 &&
4707       g_strcmp0 (g_dbus_message_get_member (data->message), "Introspect") == 0 &&
4708       g_strcmp0 (g_dbus_message_get_signature (data->message), "") == 0)
4709     handled = handle_subtree_introspect (data->es->connection,
4710                                          data->es,
4711                                          data->message);
4712   else
4713     handled = handle_subtree_method_invocation (data->es->connection,
4714                                                 data->es,
4715                                                 data->message);
4716
4717   if (!handled)
4718     {
4719       CONNECTION_LOCK (data->es->connection);
4720       handled = handle_generic_unlocked (data->es->connection, data->message);
4721       CONNECTION_UNLOCK (data->es->connection);
4722     }
4723
4724   /* if we couldn't handle the request, just bail with the UnknownMethod error */
4725   if (!handled)
4726     {
4727       GDBusMessage *reply;
4728       reply = g_dbus_message_new_method_error (data->message,
4729                                                "org.freedesktop.DBus.Error.UnknownMethod",
4730                                                _("Method `%s' on interface `%s' with signature `%s' does not exist"),
4731                                                g_dbus_message_get_member (data->message),
4732                                                g_dbus_message_get_interface (data->message),
4733                                                g_dbus_message_get_signature (data->message));
4734       g_dbus_connection_send_message (data->es->connection, reply, NULL, NULL);
4735       g_object_unref (reply);
4736     }
4737
4738   return FALSE;
4739 }
4740
4741 /* called in message handler thread with lock held */
4742 static gboolean
4743 subtree_message_func (GDBusConnection *connection,
4744                       ExportedSubtree *es,
4745                       GDBusMessage    *message)
4746 {
4747   GSource *idle_source;
4748   SubtreeDeferredData *data;
4749
4750   data = g_new0 (SubtreeDeferredData, 1);
4751   data->message = g_object_ref (message);
4752   data->es = es;
4753
4754   /* defer this call to an idle handler in the right thread */
4755   idle_source = g_idle_source_new ();
4756   g_source_set_priority (idle_source, G_PRIORITY_HIGH);
4757   g_source_set_callback (idle_source,
4758                          process_subtree_vtable_message_in_idle_cb,
4759                          data,
4760                          (GDestroyNotify) subtree_deferred_data_free);
4761   g_source_attach (idle_source, es->context);
4762   g_source_unref (idle_source);
4763
4764   /* since we own the entire subtree, handlers for objects not in the subtree have been
4765    * tried already by libdbus-1 - so we just need to ensure that we're always going
4766    * to reply to the message
4767    */
4768   return TRUE;
4769 }
4770
4771 /**
4772  * g_dbus_connection_register_subtree:
4773  * @connection: A #GDBusConnection.
4774  * @object_path: The object path to register the subtree at.
4775  * @vtable: A #GDBusSubtreeVTable to enumerate, introspect and dispatch nodes in the subtree.
4776  * @flags: Flags used to fine tune the behavior of the subtree.
4777  * @user_data: Data to pass to functions in @vtable.
4778  * @user_data_free_func: Function to call when the subtree is unregistered.
4779  * @error: Return location for error or %NULL.
4780  *
4781  * Registers a whole subtree of <quote>dynamic</quote> objects.
4782  *
4783  * The @enumerate and @introspection functions in @vtable are used to
4784  * convey, to remote callers, what nodes exist in the subtree rooted
4785  * by @object_path.
4786  *
4787  * When handling remote calls into any node in the subtree, first the
4788  * @enumerate function is used to check if the node exists. If the node exists
4789  * or the #G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag is set
4790  * the @introspection function is used to check if the node supports the
4791  * requested method. If so, the @dispatch function is used to determine
4792  * where to dispatch the call. The collected #GDBusInterfaceVTable and
4793  * #gpointer will be used to call into the interface vtable for processing
4794  * the request.
4795  *
4796  * All calls into user-provided code will be invoked in the <link
4797  * linkend="g-main-context-push-thread-default">thread-default main
4798  * loop</link> of the thread you are calling this method from.
4799  *
4800  * If an existing subtree is already registered at @object_path or
4801  * then @error is set to #G_IO_ERROR_EXISTS.
4802  *
4803  * Note that it is valid to register regular objects (using
4804  * g_dbus_connection_register_object()) in a subtree registered with
4805  * g_dbus_connection_register_subtree() - if so, the subtree handler
4806  * is tried as the last resort. One way to think about a subtree
4807  * handler is to consider it a <quote>fallback handler</quote>
4808  * for object paths not registered via g_dbus_connection_register_object()
4809  * or other bindings.
4810  *
4811  * See <xref linkend="gdbus-subtree-server"/> for an example of how to use this method.
4812  *
4813  * Returns: 0 if @error is set, otherwise a subtree registration id (never 0)
4814  * that can be used with g_dbus_connection_unregister_subtree() .
4815  *
4816  * Since: 2.26
4817  */
4818 guint
4819 g_dbus_connection_register_subtree (GDBusConnection           *connection,
4820                                     const gchar               *object_path,
4821                                     const GDBusSubtreeVTable  *vtable,
4822                                     GDBusSubtreeFlags          flags,
4823                                     gpointer                   user_data,
4824                                     GDestroyNotify             user_data_free_func,
4825                                     GError                   **error)
4826 {
4827   guint ret;
4828   ExportedSubtree *es;
4829
4830   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
4831   g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
4832   g_return_val_if_fail (vtable != NULL, 0);
4833   g_return_val_if_fail (error == NULL || *error == NULL, 0);
4834
4835   ret = 0;
4836
4837   CONNECTION_LOCK (connection);
4838
4839   es = g_hash_table_lookup (connection->priv->map_object_path_to_es, object_path);
4840   if (es != NULL)
4841     {
4842       g_set_error (error,
4843                    G_IO_ERROR,
4844                    G_IO_ERROR_EXISTS,
4845                    _("A subtree is already exported for %s"),
4846                    object_path);
4847       goto out;
4848     }
4849
4850   es = g_new0 (ExportedSubtree, 1);
4851   es->object_path = g_strdup (object_path);
4852   es->connection = connection;
4853
4854   es->vtable = vtable;
4855   es->flags = flags;
4856   es->id = _global_subtree_registration_id++; /* TODO: overflow etc. */
4857   es->user_data = user_data;
4858   es->user_data_free_func = user_data_free_func;
4859   es->context = g_main_context_get_thread_default ();
4860   if (es->context != NULL)
4861     g_main_context_ref (es->context);
4862
4863   g_hash_table_insert (connection->priv->map_object_path_to_es, es->object_path, es);
4864   g_hash_table_insert (connection->priv->map_id_to_es,
4865                        GUINT_TO_POINTER (es->id),
4866                        es);
4867
4868   ret = es->id;
4869
4870  out:
4871   CONNECTION_UNLOCK (connection);
4872
4873   return ret;
4874 }
4875
4876 /* ---------------------------------------------------------------------------------------------------- */
4877
4878 /**
4879  * g_dbus_connection_unregister_subtree:
4880  * @connection: A #GDBusConnection.
4881  * @registration_id: A subtree registration id obtained from g_dbus_connection_register_subtree().
4882  *
4883  * Unregisters a subtree.
4884  *
4885  * Returns: %TRUE if the subtree was unregistered, %FALSE otherwise.
4886  *
4887  * Since: 2.26
4888  */
4889 gboolean
4890 g_dbus_connection_unregister_subtree (GDBusConnection *connection,
4891                                       guint            registration_id)
4892 {
4893   ExportedSubtree *es;
4894   gboolean ret;
4895
4896   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
4897
4898   ret = FALSE;
4899
4900   CONNECTION_LOCK (connection);
4901
4902   es = g_hash_table_lookup (connection->priv->map_id_to_es,
4903                             GUINT_TO_POINTER (registration_id));
4904   if (es == NULL)
4905     goto out;
4906
4907   g_warn_if_fail (g_hash_table_remove (connection->priv->map_id_to_es, GUINT_TO_POINTER (es->id)));
4908   g_warn_if_fail (g_hash_table_remove (connection->priv->map_object_path_to_es, es->object_path));
4909
4910   ret = TRUE;
4911
4912  out:
4913   CONNECTION_UNLOCK (connection);
4914
4915   return ret;
4916 }
4917
4918 /* ---------------------------------------------------------------------------------------------------- */
4919
4920 /* must be called with lock held */
4921 static void
4922 handle_generic_ping_unlocked (GDBusConnection *connection,
4923                               const gchar     *object_path,
4924                               GDBusMessage    *message)
4925 {
4926   GDBusMessage *reply;
4927   reply = g_dbus_message_new_method_reply (message);
4928   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
4929   g_object_unref (reply);
4930 }
4931
4932 /* must be called with lock held */
4933 static void
4934 handle_generic_get_machine_id_unlocked (GDBusConnection *connection,
4935                                         const gchar     *object_path,
4936                                         GDBusMessage    *message)
4937 {
4938   GDBusMessage *reply;
4939
4940   reply = NULL;
4941   if (connection->priv->machine_id == NULL)
4942     {
4943       GError *error;
4944       error = NULL;
4945       /* TODO: use PACKAGE_LOCALSTATEDIR ? */
4946       if (!g_file_get_contents ("/var/lib/dbus/machine-id",
4947                                 &connection->priv->machine_id,
4948                                 NULL,
4949                                 &error))
4950         {
4951           reply = g_dbus_message_new_method_error (message,
4952                                                    "org.freedesktop.DBus.Error.Failed",
4953                                                    _("Unable to load /var/lib/dbus/machine-id: %s"),
4954                                                    error->message);
4955           g_error_free (error);
4956         }
4957       else
4958         {
4959           g_strstrip (connection->priv->machine_id);
4960           /* TODO: validate value */
4961         }
4962     }
4963
4964   if (reply == NULL)
4965     {
4966       reply = g_dbus_message_new_method_reply (message);
4967       g_dbus_message_set_body (reply, g_variant_new ("(s)", connection->priv->machine_id));
4968     }
4969   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
4970   g_object_unref (reply);
4971 }
4972
4973 /* must be called with lock held */
4974 static void
4975 handle_generic_introspect_unlocked (GDBusConnection *connection,
4976                                     const gchar     *object_path,
4977                                     GDBusMessage    *message)
4978 {
4979   guint n;
4980   GString *s;
4981   gchar **registered;
4982   GDBusMessage *reply;
4983
4984   /* first the header */
4985   s = g_string_new (NULL);
4986   introspect_append_header (s);
4987
4988   registered = g_dbus_connection_list_registered_unlocked (connection, object_path);
4989   for (n = 0; registered != NULL && registered[n] != NULL; n++)
4990       g_string_append_printf (s, "  <node name=\"%s\"/>\n", registered[n]);
4991   g_strfreev (registered);
4992   g_string_append (s, "</node>\n");
4993
4994   reply = g_dbus_message_new_method_reply (message);
4995   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
4996   g_dbus_connection_send_message_unlocked (connection, reply, NULL, NULL);
4997   g_object_unref (reply);
4998   g_string_free (s, TRUE);
4999 }
5000
5001 /* must be called with lock held */
5002 static gboolean
5003 handle_generic_unlocked (GDBusConnection *connection,
5004                          GDBusMessage    *message)
5005 {
5006   gboolean handled;
5007   const gchar *interface_name;
5008   const gchar *member;
5009   const gchar *signature;
5010   const gchar *path;
5011
5012   CONNECTION_ENSURE_LOCK (connection);
5013
5014   handled = FALSE;
5015
5016   interface_name = g_dbus_message_get_interface (message);
5017   member = g_dbus_message_get_member (message);
5018   signature = g_dbus_message_get_signature (message);
5019   path = g_dbus_message_get_path (message);
5020
5021   if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
5022       g_strcmp0 (member, "Introspect") == 0 &&
5023       g_strcmp0 (signature, "") == 0)
5024     {
5025       handle_generic_introspect_unlocked (connection, path, message);
5026       handled = TRUE;
5027     }
5028   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
5029            g_strcmp0 (member, "Ping") == 0 &&
5030            g_strcmp0 (signature, "") == 0)
5031     {
5032       handle_generic_ping_unlocked (connection, path, message);
5033       handled = TRUE;
5034     }
5035   else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
5036            g_strcmp0 (member, "GetMachineId") == 0 &&
5037            g_strcmp0 (signature, "") == 0)
5038     {
5039       handle_generic_get_machine_id_unlocked (connection, path, message);
5040       handled = TRUE;
5041     }
5042
5043   return handled;
5044 }
5045
5046 /* ---------------------------------------------------------------------------------------------------- */
5047
5048 /* called in message handler thread with lock held */
5049 static void
5050 distribute_method_call (GDBusConnection *connection,
5051                         GDBusMessage    *message)
5052 {
5053   ExportedObject *eo;
5054   ExportedSubtree *es;
5055   const gchar *object_path;
5056   const gchar *interface_name;
5057   const gchar *member;
5058   const gchar *signature;
5059   const gchar *path;
5060   gchar *subtree_path;
5061   gchar *needle;
5062
5063   g_assert (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL);
5064
5065   interface_name = g_dbus_message_get_interface (message);
5066   member = g_dbus_message_get_member (message);
5067   signature = g_dbus_message_get_signature (message);
5068   path = g_dbus_message_get_path (message);
5069   subtree_path = g_strdup (path);
5070   needle = strrchr (subtree_path, '/');
5071   if (needle != NULL && needle != subtree_path)
5072     {
5073       *needle = '\0';
5074     }
5075   else
5076     {
5077       g_free (subtree_path);
5078       subtree_path = NULL;
5079     }
5080
5081 #if 0
5082   g_debug ("interface    = `%s'", interface_name);
5083   g_debug ("member       = `%s'", member);
5084   g_debug ("signature    = `%s'", signature);
5085   g_debug ("path         = `%s'", path);
5086   g_debug ("subtree_path = `%s'", subtree_path != NULL ? subtree_path : "N/A");
5087 #endif
5088
5089   object_path = g_dbus_message_get_path (message);
5090   g_assert (object_path != NULL);
5091
5092   eo = g_hash_table_lookup (connection->priv->map_object_path_to_eo, object_path);
5093   if (eo != NULL)
5094     {
5095       if (obj_message_func (connection, eo, message))
5096         goto out;
5097     }
5098
5099   es = g_hash_table_lookup (connection->priv->map_object_path_to_es, object_path);
5100   if (es != NULL)
5101     {
5102       if (subtree_message_func (connection, es, message))
5103         goto out;
5104     }
5105
5106   if (subtree_path != NULL)
5107     {
5108       es = g_hash_table_lookup (connection->priv->map_object_path_to_es, subtree_path);
5109       if (es != NULL)
5110         {
5111           if (subtree_message_func (connection, es, message))
5112             goto out;
5113         }
5114     }
5115
5116   if (handle_generic_unlocked (connection, message))
5117     goto out;
5118
5119   /* if we end up here, the message has not been not handled */
5120
5121  out:
5122   g_free (subtree_path);
5123 }
5124
5125 /* ---------------------------------------------------------------------------------------------------- */
5126
5127 static GDBusConnection **
5128 message_bus_get_singleton (GBusType   bus_type,
5129                            GError   **error)
5130 {
5131   GDBusConnection **ret;
5132   const gchar *starter_bus;
5133
5134   ret = NULL;
5135
5136   switch (bus_type)
5137     {
5138     case G_BUS_TYPE_SESSION:
5139       ret = &the_session_bus;
5140       break;
5141
5142     case G_BUS_TYPE_SYSTEM:
5143       ret = &the_system_bus;
5144       break;
5145
5146     case G_BUS_TYPE_STARTER:
5147       starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE");
5148       if (g_strcmp0 (starter_bus, "session") == 0)
5149         {
5150           ret = message_bus_get_singleton (G_BUS_TYPE_SESSION, error);
5151           goto out;
5152         }
5153       else if (g_strcmp0 (starter_bus, "system") == 0)
5154         {
5155           ret = message_bus_get_singleton (G_BUS_TYPE_SYSTEM, error);
5156           goto out;
5157         }
5158       else
5159         {
5160           if (starter_bus != NULL)
5161             {
5162               g_set_error (error,
5163                            G_IO_ERROR,
5164                            G_IO_ERROR_INVALID_ARGUMENT,
5165                            _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable"
5166                              " - unknown value `%s'"),
5167                            starter_bus);
5168             }
5169           else
5170             {
5171               g_set_error_literal (error,
5172                                    G_IO_ERROR,
5173                                    G_IO_ERROR_INVALID_ARGUMENT,
5174                                    _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment "
5175                                      "variable is not set"));
5176             }
5177         }
5178       break;
5179
5180     default:
5181       g_assert_not_reached ();
5182       break;
5183     }
5184
5185  out:
5186   return ret;
5187 }
5188
5189 static GDBusConnection *
5190 get_uninitialized_connection (GBusType       bus_type,
5191                               GCancellable  *cancellable,
5192                               GError       **error)
5193 {
5194   GDBusConnection **singleton;
5195   GDBusConnection *ret;
5196
5197   ret = NULL;
5198
5199   G_LOCK (message_bus_lock);
5200   singleton = message_bus_get_singleton (bus_type, error);
5201   if (singleton == NULL)
5202     goto out;
5203
5204   if (*singleton == NULL)
5205     {
5206       gchar *address;
5207       address = g_dbus_address_get_for_bus_sync (bus_type, cancellable, error);
5208       if (address == NULL)
5209         goto out;
5210       ret = *singleton = g_object_new (G_TYPE_DBUS_CONNECTION,
5211                                        "address", address,
5212                                        "flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
5213                                                 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
5214                                        "exit-on-close", TRUE,
5215                                        NULL);
5216     }
5217   else
5218     {
5219       ret = g_object_ref (*singleton);
5220     }
5221
5222   g_assert (ret != NULL);
5223
5224  out:
5225   G_UNLOCK (message_bus_lock);
5226   return ret;
5227 }
5228
5229 /**
5230  * g_bus_get_sync:
5231  * @bus_type: A #GBusType.
5232  * @cancellable: A #GCancellable or %NULL.
5233  * @error: Return location for error or %NULL.
5234  *
5235  * Synchronously connects to the message bus specified by @bus_type.
5236  * Note that the returned object may shared with other callers,
5237  * e.g. if two separate parts of a process calls this function with
5238  * the same @bus_type, they will share the same object.
5239  *
5240  * This is a synchronous failable function. See g_bus_get() and
5241  * g_bus_get_finish() for the asynchronous version.
5242  *
5243  * The returned object is a singleton, that is, shared with other
5244  * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
5245  * event that you need a private message bus connection, use
5246  * g_dbus_address_get_for_bus_sync() and
5247  * g_dbus_connection_new_for_address().
5248  *
5249  * Note that the returned #GDBusConnection object will (usually) have
5250  * the #GDBusConnection:exit-on-close property set to %TRUE.
5251  *
5252  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
5253  *
5254  * Since: 2.26
5255  */
5256 GDBusConnection *
5257 g_bus_get_sync (GBusType       bus_type,
5258                 GCancellable  *cancellable,
5259                 GError       **error)
5260 {
5261   GDBusConnection *connection;
5262
5263   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
5264
5265   connection = get_uninitialized_connection (bus_type, cancellable, error);
5266   if (connection == NULL)
5267     goto out;
5268
5269   if (!g_initable_init (G_INITABLE (connection), cancellable, error))
5270     {
5271       g_object_unref (connection);
5272       connection = NULL;
5273     }
5274
5275  out:
5276   return connection;
5277 }
5278
5279 static void
5280 bus_get_async_initable_cb (GObject      *source_object,
5281                            GAsyncResult *res,
5282                            gpointer      user_data)
5283 {
5284   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
5285   GError *error;
5286
5287   error = NULL;
5288   if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
5289                                      res,
5290                                      &error))
5291     {
5292       g_assert (error != NULL);
5293       g_simple_async_result_set_from_error (simple, error);
5294       g_error_free (error);
5295       g_object_unref (source_object);
5296     }
5297   else
5298     {
5299       g_simple_async_result_set_op_res_gpointer (simple,
5300                                                  source_object,
5301                                                  g_object_unref);
5302     }
5303   g_simple_async_result_complete_in_idle (simple);
5304   g_object_unref (simple);
5305 }
5306
5307 /**
5308  * g_bus_get:
5309  * @bus_type: A #GBusType.
5310  * @cancellable: A #GCancellable or %NULL.
5311  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
5312  * @user_data: The data to pass to @callback.
5313  *
5314  * Asynchronously connects to the message bus specified by @bus_type.
5315  *
5316  * When the operation is finished, @callback will be invoked. You can
5317  * then call g_bus_get_finish() to get the result of the operation.
5318  *
5319  * This is a asynchronous failable function. See g_bus_get_sync() for
5320  * the synchronous version.
5321  *
5322  * Since: 2.26
5323  */
5324 void
5325 g_bus_get (GBusType             bus_type,
5326            GCancellable        *cancellable,
5327            GAsyncReadyCallback  callback,
5328            gpointer             user_data)
5329 {
5330   GDBusConnection *connection;
5331   GSimpleAsyncResult *simple;
5332   GError *error;
5333
5334   simple = g_simple_async_result_new (NULL,
5335                                       callback,
5336                                       user_data,
5337                                       g_bus_get);
5338
5339   error = NULL;
5340   connection = get_uninitialized_connection (bus_type, cancellable, &error);
5341   if (connection == NULL)
5342     {
5343       g_assert (error != NULL);
5344       g_simple_async_result_set_from_error (simple, error);
5345       g_error_free (error);
5346       g_simple_async_result_complete_in_idle (simple);
5347       g_object_unref (simple);
5348     }
5349   else
5350     {
5351       g_async_initable_init_async (G_ASYNC_INITABLE (connection),
5352                                    G_PRIORITY_DEFAULT,
5353                                    cancellable,
5354                                    bus_get_async_initable_cb,
5355                                    simple);
5356     }
5357 }
5358
5359 /**
5360  * g_bus_get_finish:
5361  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_bus_get().
5362  * @error: Return location for error or %NULL.
5363  *
5364  * Finishes an operation started with g_bus_get().
5365  *
5366  * The returned object is a singleton, that is, shared with other
5367  * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
5368  * event that you need a private message bus connection, use
5369  * g_dbus_address_get_for_bus() and
5370  * g_dbus_connection_new_for_address().
5371  *
5372  * Note that the returned #GDBusConnection object will (usually) have
5373  * the #GDBusConnection:exit-on-close property set to %TRUE.
5374  *
5375  * Returns: A #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
5376  *
5377  * Since: 2.26
5378  */
5379 GDBusConnection *
5380 g_bus_get_finish (GAsyncResult  *res,
5381                   GError       **error)
5382 {
5383   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
5384   GObject *object;
5385   GDBusConnection *ret;
5386
5387   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
5388
5389   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_bus_get);
5390
5391   ret = NULL;
5392
5393   if (g_simple_async_result_propagate_error (simple, error))
5394     goto out;
5395
5396   object = g_simple_async_result_get_op_res_gpointer (simple);
5397   g_assert (object != NULL);
5398   ret = g_object_ref (G_DBUS_CONNECTION (object));
5399
5400  out:
5401   return ret;
5402 }
5403
5404 /* ---------------------------------------------------------------------------------------------------- */
5405
5406 #define __G_DBUS_CONNECTION_C__
5407 #include "gioaliasdef.c"