1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
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.1 of the License, or (at your option) any later version.
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.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
24 * - would be nice to expose GDBusAuthMechanism and an extension point
26 * - Need to rewrite GDBusAuth and rework GDBusAuthMechanism. In particular
27 * the mechanism VFuncs need to be able to set an error.
29 * - Need to document other mechanisms/sources for determining the D-Bus
30 * address of a well-known bus.
32 * - e.g. on Win32 we need code like from here
34 * http://cgit.freedesktop.org/~david/gdbus-standalone/tree/gdbus/gdbusaddress.c#n900
36 * that was never copied over here because it originally was copy-paste
37 * from the GPLv2 / AFL 2.1 libdbus sources.
39 * - on OS X we need to look in launchd for the address
41 * https://bugs.freedesktop.org/show_bug.cgi?id=14259
43 * - on X11 we need to look in a X11 property on the X server
44 * - (we can also just use dbus-launch(1) from the D-Bus
47 * - (ideally) this requires D-Bus spec work because none of
48 * this has never really been specced out properly (except
51 * - Related to the above, we also need to be able to launch a message bus
52 * instance.... Since we don't want to write our own bus daemon we should
53 * launch dbus-daemon(1) (thus: Win32 and OS X need to bundle it)
55 * - probably want a G_DBUS_NONCE_TCP_TMPDIR environment variable
56 * to specify where the nonce is stored. This will allow people to use
57 * G_DBUS_NONCE_TCP_TMPDIR=/mnt/secure.company.server/dbus-nonce-dir
58 * to easily achieve secure RPC via nonce-tcp.
60 * - need to expose an extension point for resolving D-Bus address and
61 * turning them into GIOStream objects. This will allow us to implement
62 * e.g. X11 D-Bus transports without dlopen()'ing or linking against
64 * - see g_dbus_address_connect() in gdbusaddress.c
66 * - would be cute to use kernel-specific APIs to resolve fds for
67 * debug output when using G_DBUS_DEBUG=message, e.g. in addition to
69 * fd 21: dev=8:1,mode=0100644,ino=1171231,uid=0,gid=0,rdev=0:0,size=234,atime=1273070640,mtime=1267126160,ctime=1267126160
71 * maybe we can show more information about what fd 21 really is.
72 * Ryan suggests looking in /proc/self/fd for clues / symlinks!
73 * Initial experiments on Linux 2.6 suggests that the symlink looks
78 * e.g. not of much use.
80 * - GDBus High-Level docs
81 * - Proxy: properties, signals...
82 * - Connection: IOStream based, ::close, connection setup steps
83 * mainloop integration, threading
84 * - Differences from libdbus (extend "Migrating from")
85 * - the message handling thread
86 * - Using GVariant instead of GValue
87 * - Explain why the high-level API is a good thing and what
88 * kind of pitfalls it avoids
89 * - Export objects before claiming names
90 * - Talk about auto-starting services (cf. GBusNameWatcherFlags)
98 #include "gdbusauth.h"
99 #include "gdbusutils.h"
100 #include "gdbusaddress.h"
101 #include "gdbusmessage.h"
102 #include "gdbusconnection.h"
103 #include "gdbuserror.h"
104 #include "gioenumtypes.h"
105 #include "gdbusintrospection.h"
106 #include "gdbusmethodinvocation.h"
107 #include "gdbusprivate.h"
108 #include "gdbusauthobserver.h"
109 #include "ginitable.h"
110 #include "gasyncinitable.h"
111 #include "giostream.h"
112 #include "gasyncresult.h"
114 #include "gmarshal-internal.h"
117 #include "gunixconnection.h"
118 #include "gunixfdmessage.h"
121 #include "glibintl.h"
123 #define G_DBUS_CONNECTION_FLAGS_ALL \
124 (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | \
125 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | \
126 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \
127 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | \
128 G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING | \
129 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)
132 * SECTION:gdbusconnection
133 * @short_description: D-Bus Connections
134 * @include: gio/gio.h
136 * The #GDBusConnection type is used for D-Bus connections to remote
137 * peers such as a message buses. It is a low-level API that offers a
138 * lot of flexibility. For instance, it lets you establish a connection
139 * over any transport that can by represented as a #GIOStream.
141 * This class is rarely used directly in D-Bus clients. If you are writing
142 * a D-Bus client, it is often easier to use the g_bus_own_name(),
143 * g_bus_watch_name() or g_dbus_proxy_new_for_bus() APIs.
145 * As an exception to the usual GLib rule that a particular object must not
146 * be used by two threads at the same time, #GDBusConnection's methods may be
147 * called from any thread. This is so that g_bus_get() and g_bus_get_sync()
148 * can safely return the same #GDBusConnection when called from any thread.
150 * Most of the ways to obtain a #GDBusConnection automatically initialize it
151 * (i.e. connect to D-Bus): for instance, g_dbus_connection_new() and
152 * g_bus_get(), and the synchronous versions of those methods, give you an
153 * initialized connection. Language bindings for GIO should use
154 * g_initable_new() or g_async_initable_new_async(), which also initialize the
157 * If you construct an uninitialized #GDBusConnection, such as via
158 * g_object_new(), you must initialize it via g_initable_init() or
159 * g_async_initable_init_async() before using its methods or properties.
160 * Calling methods or accessing properties on a #GDBusConnection that has not
161 * completed initialization successfully is considered to be invalid, and leads
162 * to undefined behaviour. In particular, if initialization fails with a
163 * #GError, the only valid thing you can do with that #GDBusConnection is to
164 * free it with g_object_unref().
166 * ## An example D-Bus server # {#gdbus-server}
168 * Here is an example for a D-Bus server:
169 * [gdbus-example-server.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-server.c)
171 * ## An example for exporting a subtree # {#gdbus-subtree-server}
173 * Here is an example for exporting a subtree:
174 * [gdbus-example-subtree.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-subtree.c)
176 * ## An example for file descriptor passing # {#gdbus-unix-fd-client}
178 * Here is an example for passing UNIX file descriptors:
179 * [gdbus-unix-fd-client.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-unix-fd-client.c)
181 * ## An example for exporting a GObject # {#gdbus-export}
183 * Here is an example for exporting a #GObject:
184 * [gdbus-example-export.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-export.c)
187 /* ---------------------------------------------------------------------------------------------------- */
189 typedef struct _GDBusConnectionClass GDBusConnectionClass;
192 * GDBusConnectionClass:
193 * @closed: Signal class handler for the #GDBusConnection::closed signal.
195 * Class structure for #GDBusConnection.
199 struct _GDBusConnectionClass
202 GObjectClass parent_class;
206 void (*closed) (GDBusConnection *connection,
207 gboolean remote_peer_vanished,
211 G_LOCK_DEFINE_STATIC (message_bus_lock);
213 static GWeakRef the_session_bus;
214 static GWeakRef the_system_bus;
216 /* Extra pseudo-member of GDBusSendMessageFlags.
217 * Set by initable_init() to indicate that despite not being initialized yet,
218 * enough of the only-valid-after-init members are set that we can send a
219 * message, and we're being called from its thread, so no memory barrier is
220 * required before accessing them.
222 #define SEND_MESSAGE_FLAGS_INITIALIZING (1u << 31)
224 /* Same as SEND_MESSAGE_FLAGS_INITIALIZING, but in GDBusCallFlags */
225 #define CALL_FLAGS_INITIALIZING (1u << 31)
227 /* ---------------------------------------------------------------------------------------------------- */
231 GDestroyNotify callback;
233 } CallDestroyNotifyData;
236 call_destroy_notify_data_in_idle (gpointer user_data)
238 CallDestroyNotifyData *data = user_data;
239 data->callback (data->user_data);
244 call_destroy_notify_data_free (CallDestroyNotifyData *data)
250 * call_destroy_notify: <internal>
251 * @context: (nullable): A #GMainContext or %NULL.
252 * @callback: (nullable): A #GDestroyNotify or %NULL.
253 * @user_data: Data to pass to @callback.
255 * Schedules @callback to run in @context.
258 call_destroy_notify (GMainContext *context,
259 GDestroyNotify callback,
262 GSource *idle_source;
263 CallDestroyNotifyData *data;
265 if (callback == NULL)
268 data = g_new0 (CallDestroyNotifyData, 1);
269 data->callback = callback;
270 data->user_data = user_data;
272 idle_source = g_idle_source_new ();
273 g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
274 g_source_set_callback (idle_source,
275 call_destroy_notify_data_in_idle,
277 (GDestroyNotify) call_destroy_notify_data_free);
278 g_source_set_static_name (idle_source, "[gio] call_destroy_notify_data_in_idle");
279 g_source_attach (idle_source, context);
280 g_source_unref (idle_source);
283 /* ---------------------------------------------------------------------------------------------------- */
286 #define CONNECTION_ENSURE_LOCK(obj) do { ; } while (FALSE)
288 // TODO: for some reason this doesn't work on Windows
289 #define CONNECTION_ENSURE_LOCK(obj) do { \
290 if (G_UNLIKELY (g_mutex_trylock(&(obj)->lock))) \
292 g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
293 "CONNECTION_ENSURE_LOCK: GDBusConnection object lock is not locked"); \
298 #define CONNECTION_LOCK(obj) do { \
299 g_mutex_lock (&(obj)->lock); \
302 #define CONNECTION_UNLOCK(obj) do { \
303 g_mutex_unlock (&(obj)->lock); \
306 /* Flags in connection->atomic_flags */
308 FLAG_INITIALIZED = 1 << 0,
309 FLAG_EXIT_ON_CLOSE = 1 << 1,
316 * The #GDBusConnection structure contains only private data and
317 * should only be accessed using the provided API.
321 struct _GDBusConnection
324 GObject parent_instance;
326 /* ------------------------------------------------------------------------ */
327 /* -- General object state ------------------------------------------------ */
328 /* ------------------------------------------------------------------------ */
330 /* General-purpose lock for most fields */
333 /* A lock used in the init() method of the GInitable interface - see comments
334 * in initable_init() for why a separate lock is needed.
336 * If you need both @lock and @init_lock, you must take @init_lock first.
340 /* Set (by loading the contents of /var/lib/dbus/machine-id) the first time
341 * someone calls org.freedesktop.DBus.Peer.GetMachineId(). Protected by @lock.
345 /* The underlying stream used for communication
346 * Read-only after initable_init(), so it may be read if you either
347 * hold @init_lock or check for initialization first.
351 /* The object used for authentication (if any).
352 * Read-only after initable_init(), so it may be read if you either
353 * hold @init_lock or check for initialization first.
357 /* Last serial used. Protected by @lock. */
360 /* The object used to send/receive messages.
361 * Read-only after initable_init(), so it may be read if you either
362 * hold @init_lock or check for initialization first.
366 /* If connected to a message bus, this contains the unique name assigned to
367 * us by the bus (e.g. ":1.42").
368 * Read-only after initable_init(), so it may be read if you either
369 * hold @init_lock or check for initialization first.
371 gchar *bus_unique_name;
373 /* The GUID returned by the other side if we authenticated as a client or
374 * the GUID to use if authenticating as a server.
375 * Read-only after initable_init(), so it may be read if you either
376 * hold @init_lock or check for initialization first.
380 /* FLAG_INITIALIZED is set exactly when initable_init() has finished running.
381 * Inspect @initialization_error to see whether it succeeded or failed.
383 * FLAG_EXIT_ON_CLOSE is the exit-on-close property.
385 * FLAG_CLOSED is the closed property. It may be read at any time, but
386 * may only be written while holding @lock.
388 gint atomic_flags; /* (atomic) */
390 /* If the connection could not be established during initable_init(),
391 * this GError will be set.
392 * Read-only after initable_init(), so it may be read if you either
393 * hold @init_lock or check for initialization first.
395 GError *initialization_error;
397 /* The result of g_main_context_ref_thread_default() when the object
398 * was created (the GObject _init() function) - this is used for delivery
399 * of the :closed GObject signal.
401 * Only set in the GObject init function, so no locks are needed.
403 GMainContext *main_context_at_construction;
405 /* Read-only construct properties, no locks needed */
407 GDBusConnectionFlags flags;
409 /* Map used for managing method replies, protected by @lock */
410 GHashTable *map_method_serial_to_task; /* guint32 -> GTask* */
412 /* Maps used for managing signal subscription, protected by @lock */
413 GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */
414 GHashTable *map_id_to_signal_data; /* id (guint) -> SignalData */
415 GHashTable *map_sender_unique_name_to_signal_data_array; /* unique sender (gchar*) -> GPtrArray* of SignalData */
417 /* Maps used for managing exported objects and subtrees,
420 GHashTable *map_object_path_to_eo; /* gchar* -> ExportedObject* */
421 GHashTable *map_id_to_ei; /* guint -> ExportedInterface* */
422 GHashTable *map_object_path_to_es; /* gchar* -> ExportedSubtree* */
423 GHashTable *map_id_to_es; /* guint -> ExportedSubtree* */
425 /* Map used for storing last used serials for each thread, protected by @lock */
426 GHashTable *map_thread_to_last_serial;
428 /* Structure used for message filters, protected by @lock */
431 /* Capabilities negotiated during authentication
432 * Read-only after initable_init(), so it may be read without holding a
433 * lock, if you check for initialization first.
435 GDBusCapabilityFlags capabilities;
437 /* Protected by @init_lock */
438 GDBusAuthObserver *authentication_observer;
440 /* Read-only after initable_init(), so it may be read if you either
441 * hold @init_lock or check for initialization first.
443 GCredentials *credentials;
445 /* set to TRUE when finalizing */
449 typedef struct ExportedObject ExportedObject;
450 static void exported_object_free (ExportedObject *eo);
452 typedef struct ExportedSubtree ExportedSubtree;
453 static ExportedSubtree *exported_subtree_ref (ExportedSubtree *es);
454 static void exported_subtree_unref (ExportedSubtree *es);
472 PROP_CAPABILITY_FLAGS,
473 PROP_AUTHENTICATION_OBSERVER,
476 static void distribute_signals (GDBusConnection *connection,
477 GDBusMessage *message);
479 static void distribute_method_call (GDBusConnection *connection,
480 GDBusMessage *message);
482 static gboolean handle_generic_unlocked (GDBusConnection *connection,
483 GDBusMessage *message);
486 static void purge_all_signal_subscriptions (GDBusConnection *connection);
487 static void purge_all_filters (GDBusConnection *connection);
489 static void schedule_method_call (GDBusConnection *connection,
490 GDBusMessage *message,
491 guint registration_id,
492 guint subtree_registration_id,
493 const GDBusInterfaceInfo *interface_info,
494 const GDBusMethodInfo *method_info,
495 const GDBusPropertyInfo *property_info,
496 GVariant *parameters,
497 const GDBusInterfaceVTable *vtable,
498 GMainContext *main_context,
501 #define _G_ENSURE_LOCK(name) do { \
502 if (G_UNLIKELY (G_TRYLOCK(name))) \
504 g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
505 "_G_ENSURE_LOCK: Lock '" #name "' is not locked"); \
509 static guint signals[LAST_SIGNAL] = { 0 };
511 static void initable_iface_init (GInitableIface *initable_iface);
512 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
514 G_DEFINE_TYPE_WITH_CODE (GDBusConnection, g_dbus_connection, G_TYPE_OBJECT,
515 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
516 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
520 * Check that all members of @connection that can only be accessed after
521 * the connection is initialized can safely be accessed. If not,
522 * log a critical warning. This function is a memory barrier.
524 * Returns: %TRUE if initialized
527 check_initialized (GDBusConnection *connection)
529 /* The access to @atomic_flags isn't conditional, so that this function
530 * provides a memory barrier for thread-safety even if checks are disabled.
531 * (If you don't want this stricter guarantee, you can call
532 * g_return_if_fail (check_initialized (c)).)
534 * This isn't strictly necessary now that we've decided use of an
535 * uninitialized GDBusConnection is undefined behaviour, but it seems
536 * better to be as deterministic as is feasible.
538 * (Anything that could suffer a crash from seeing undefined values
539 * must have a race condition - thread A initializes the connection while
540 * thread B calls a method without initialization, hoping that thread A will
541 * win the race - so its behaviour is undefined anyway.)
543 gint flags = g_atomic_int_get (&connection->atomic_flags);
545 g_return_val_if_fail (flags & FLAG_INITIALIZED, FALSE);
547 /* We can safely access this, due to the memory barrier above */
548 g_return_val_if_fail (connection->initialization_error == NULL, FALSE);
554 MAY_BE_UNINITIALIZED = (1<<1)
555 } CheckUnclosedFlags;
558 * Check the same thing as check_initialized(), and also that the
559 * connection is not closed. If the connection is uninitialized,
560 * raise a critical warning (it's programmer error); if it's closed,
561 * raise a recoverable GError (it's a runtime error).
563 * This function is a memory barrier.
565 * Returns: %TRUE if initialized and not closed
568 check_unclosed (GDBusConnection *connection,
569 CheckUnclosedFlags check,
572 /* check_initialized() is effectively inlined, so we don't waste time
573 * doing two memory barriers
575 gint flags = g_atomic_int_get (&connection->atomic_flags);
577 if (!(check & MAY_BE_UNINITIALIZED))
579 g_return_val_if_fail (flags & FLAG_INITIALIZED, FALSE);
580 g_return_val_if_fail (connection->initialization_error == NULL, FALSE);
583 if (flags & FLAG_CLOSED)
585 g_set_error_literal (error,
588 _("The connection is closed"));
595 static GHashTable *alive_connections = NULL;
598 g_dbus_connection_dispose (GObject *object)
600 GDBusConnection *connection = G_DBUS_CONNECTION (object);
602 G_LOCK (message_bus_lock);
603 CONNECTION_LOCK (connection);
604 if (connection->worker != NULL)
606 _g_dbus_worker_stop (connection->worker);
607 connection->worker = NULL;
608 if (alive_connections != NULL)
609 g_warn_if_fail (g_hash_table_remove (alive_connections, connection));
613 if (alive_connections != NULL)
614 g_warn_if_fail (!g_hash_table_contains (alive_connections, connection));
616 CONNECTION_UNLOCK (connection);
617 G_UNLOCK (message_bus_lock);
619 if (G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose != NULL)
620 G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose (object);
624 g_dbus_connection_finalize (GObject *object)
626 GDBusConnection *connection = G_DBUS_CONNECTION (object);
628 connection->finalizing = TRUE;
630 purge_all_signal_subscriptions (connection);
632 purge_all_filters (connection);
633 g_ptr_array_unref (connection->filters);
635 if (connection->authentication_observer != NULL)
636 g_object_unref (connection->authentication_observer);
638 if (connection->auth != NULL)
639 g_object_unref (connection->auth);
641 if (connection->credentials)
642 g_object_unref (connection->credentials);
644 if (connection->stream != NULL)
646 g_object_unref (connection->stream);
647 connection->stream = NULL;
650 g_free (connection->address);
652 g_free (connection->guid);
653 g_free (connection->bus_unique_name);
655 if (connection->initialization_error != NULL)
656 g_error_free (connection->initialization_error);
658 g_hash_table_unref (connection->map_method_serial_to_task);
660 g_hash_table_unref (connection->map_rule_to_signal_data);
661 g_hash_table_unref (connection->map_id_to_signal_data);
662 g_hash_table_unref (connection->map_sender_unique_name_to_signal_data_array);
664 g_hash_table_unref (connection->map_id_to_ei);
665 g_hash_table_unref (connection->map_object_path_to_eo);
666 g_hash_table_unref (connection->map_id_to_es);
667 g_hash_table_unref (connection->map_object_path_to_es);
669 g_hash_table_unref (connection->map_thread_to_last_serial);
671 g_main_context_unref (connection->main_context_at_construction);
673 g_free (connection->machine_id);
675 g_mutex_clear (&connection->init_lock);
676 g_mutex_clear (&connection->lock);
678 G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize (object);
681 /* called in any user thread, with the connection's lock not held */
683 g_dbus_connection_get_property (GObject *object,
688 GDBusConnection *connection = G_DBUS_CONNECTION (object);
693 g_value_set_object (value, g_dbus_connection_get_stream (connection));
697 g_value_set_string (value, g_dbus_connection_get_guid (connection));
700 case PROP_UNIQUE_NAME:
701 g_value_set_string (value, g_dbus_connection_get_unique_name (connection));
705 g_value_set_boolean (value, g_dbus_connection_is_closed (connection));
708 case PROP_EXIT_ON_CLOSE:
709 g_value_set_boolean (value, g_dbus_connection_get_exit_on_close (connection));
712 case PROP_CAPABILITY_FLAGS:
713 g_value_set_flags (value, g_dbus_connection_get_capabilities (connection));
717 g_value_set_flags (value, g_dbus_connection_get_flags (connection));
721 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
726 /* called in any user thread, with the connection's lock not held */
728 g_dbus_connection_set_property (GObject *object,
733 GDBusConnection *connection = G_DBUS_CONNECTION (object);
738 connection->stream = g_value_dup_object (value);
742 connection->guid = g_value_dup_string (value);
746 connection->address = g_value_dup_string (value);
750 connection->flags = g_value_get_flags (value);
753 case PROP_EXIT_ON_CLOSE:
754 g_dbus_connection_set_exit_on_close (connection, g_value_get_boolean (value));
757 case PROP_AUTHENTICATION_OBSERVER:
758 connection->authentication_observer = g_value_dup_object (value);
762 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
767 /* Base-class implementation of GDBusConnection::closed.
769 * Called in a user thread, by the main context that was thread-default when
770 * the object was constructed.
773 g_dbus_connection_real_closed (GDBusConnection *connection,
774 gboolean remote_peer_vanished,
777 gint flags = g_atomic_int_get (&connection->atomic_flags);
779 /* Because atomic int access is a memory barrier, we can safely read
780 * initialization_error without a lock, as long as we do it afterwards.
782 if (remote_peer_vanished &&
783 (flags & FLAG_EXIT_ON_CLOSE) != 0 &&
784 (flags & FLAG_INITIALIZED) != 0 &&
785 connection->initialization_error == NULL)
792 g_dbus_connection_class_init (GDBusConnectionClass *klass)
794 GObjectClass *gobject_class;
796 gobject_class = G_OBJECT_CLASS (klass);
798 gobject_class->finalize = g_dbus_connection_finalize;
799 gobject_class->dispose = g_dbus_connection_dispose;
800 gobject_class->set_property = g_dbus_connection_set_property;
801 gobject_class->get_property = g_dbus_connection_get_property;
803 klass->closed = g_dbus_connection_real_closed;
806 * GDBusConnection:stream:
808 * The underlying #GIOStream used for I/O.
810 * If this is passed on construction and is a #GSocketConnection,
811 * then the corresponding #GSocket will be put into non-blocking mode.
813 * While the #GDBusConnection is active, it will interact with this
814 * stream from a worker thread, so it is not safe to interact with
815 * the stream directly.
819 g_object_class_install_property (gobject_class,
821 g_param_spec_object ("stream",
823 P_("The underlying streams used for I/O"),
827 G_PARAM_CONSTRUCT_ONLY |
828 G_PARAM_STATIC_NAME |
829 G_PARAM_STATIC_BLURB |
830 G_PARAM_STATIC_NICK));
833 * GDBusConnection:address:
835 * A D-Bus address specifying potential endpoints that can be used
836 * when establishing the connection.
840 g_object_class_install_property (gobject_class,
842 g_param_spec_string ("address",
844 P_("D-Bus address specifying potential socket endpoints"),
847 G_PARAM_CONSTRUCT_ONLY |
848 G_PARAM_STATIC_NAME |
849 G_PARAM_STATIC_BLURB |
850 G_PARAM_STATIC_NICK));
853 * GDBusConnection:flags:
855 * Flags from the #GDBusConnectionFlags enumeration.
859 g_object_class_install_property (gobject_class,
861 g_param_spec_flags ("flags",
864 G_TYPE_DBUS_CONNECTION_FLAGS,
865 G_DBUS_CONNECTION_FLAGS_NONE,
868 G_PARAM_CONSTRUCT_ONLY |
869 G_PARAM_STATIC_NAME |
870 G_PARAM_STATIC_BLURB |
871 G_PARAM_STATIC_NICK));
874 * GDBusConnection:guid:
876 * The GUID of the peer performing the role of server when
879 * If you are constructing a #GDBusConnection and pass
880 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER in the
881 * #GDBusConnection:flags property then you **must** also set this
882 * property to a valid guid.
884 * If you are constructing a #GDBusConnection and pass
885 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT in the
886 * #GDBusConnection:flags property you will be able to read the GUID
887 * of the other peer here after the connection has been successfully
891 * [D-Bus specification](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses)
892 * uses the term ‘UUID’ to refer to this, whereas GLib consistently uses the
893 * term ‘GUID’ for historical reasons.
895 * Despite its name, the format of #GDBusConnection:guid does not follow
896 * [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) or the Microsoft
901 g_object_class_install_property (gobject_class,
903 g_param_spec_string ("guid",
905 P_("GUID of the server peer"),
909 G_PARAM_CONSTRUCT_ONLY |
910 G_PARAM_STATIC_NAME |
911 G_PARAM_STATIC_BLURB |
912 G_PARAM_STATIC_NICK));
915 * GDBusConnection:unique-name:
917 * The unique name as assigned by the message bus or %NULL if the
918 * connection is not open or not a message bus connection.
922 g_object_class_install_property (gobject_class,
924 g_param_spec_string ("unique-name",
926 P_("Unique name of bus connection"),
929 G_PARAM_STATIC_NAME |
930 G_PARAM_STATIC_BLURB |
931 G_PARAM_STATIC_NICK));
934 * GDBusConnection:closed:
936 * A boolean specifying whether the connection has been closed.
940 g_object_class_install_property (gobject_class,
942 g_param_spec_boolean ("closed",
944 P_("Whether the connection is closed"),
947 G_PARAM_STATIC_NAME |
948 G_PARAM_STATIC_BLURB |
949 G_PARAM_STATIC_NICK));
952 * GDBusConnection:exit-on-close:
954 * A boolean specifying whether the process will be terminated (by
955 * calling `raise(SIGTERM)`) if the connection is closed by the
958 * Note that #GDBusConnection objects returned by g_bus_get_finish()
959 * and g_bus_get_sync() will (usually) have this property set to %TRUE.
963 g_object_class_install_property (gobject_class,
965 g_param_spec_boolean ("exit-on-close",
967 P_("Whether the process is terminated when the connection is closed"),
971 G_PARAM_STATIC_NAME |
972 G_PARAM_STATIC_BLURB |
973 G_PARAM_STATIC_NICK));
976 * GDBusConnection:capabilities:
978 * Flags from the #GDBusCapabilityFlags enumeration
979 * representing connection features negotiated with the other peer.
983 g_object_class_install_property (gobject_class,
984 PROP_CAPABILITY_FLAGS,
985 g_param_spec_flags ("capabilities",
988 G_TYPE_DBUS_CAPABILITY_FLAGS,
989 G_DBUS_CAPABILITY_FLAGS_NONE,
991 G_PARAM_STATIC_NAME |
992 G_PARAM_STATIC_BLURB |
993 G_PARAM_STATIC_NICK));
996 * GDBusConnection:authentication-observer:
998 * A #GDBusAuthObserver object to assist in the authentication process or %NULL.
1002 g_object_class_install_property (gobject_class,
1003 PROP_AUTHENTICATION_OBSERVER,
1004 g_param_spec_object ("authentication-observer",
1005 P_("Authentication Observer"),
1006 P_("Object used to assist in the authentication process"),
1007 G_TYPE_DBUS_AUTH_OBSERVER,
1009 G_PARAM_CONSTRUCT_ONLY |
1010 G_PARAM_STATIC_NAME |
1011 G_PARAM_STATIC_BLURB |
1012 G_PARAM_STATIC_NICK));
1015 * GDBusConnection::closed:
1016 * @connection: the #GDBusConnection emitting the signal
1017 * @remote_peer_vanished: %TRUE if @connection is closed because the
1018 * remote peer closed its end of the connection
1019 * @error: (nullable): a #GError with more details about the event or %NULL
1021 * Emitted when the connection is closed.
1023 * The cause of this event can be
1025 * - If g_dbus_connection_close() is called. In this case
1026 * @remote_peer_vanished is set to %FALSE and @error is %NULL.
1028 * - If the remote peer closes the connection. In this case
1029 * @remote_peer_vanished is set to %TRUE and @error is set.
1031 * - If the remote peer sends invalid or malformed data. In this
1032 * case @remote_peer_vanished is set to %FALSE and @error is set.
1034 * Upon receiving this signal, you should give up your reference to
1035 * @connection. You are guaranteed that this signal is emitted only
1040 signals[CLOSED_SIGNAL] = g_signal_new (I_("closed"),
1041 G_TYPE_DBUS_CONNECTION,
1043 G_STRUCT_OFFSET (GDBusConnectionClass, closed),
1046 _g_cclosure_marshal_VOID__BOOLEAN_BOXED,
1051 g_signal_set_va_marshaller (signals[CLOSED_SIGNAL],
1052 G_TYPE_FROM_CLASS (klass),
1053 _g_cclosure_marshal_VOID__BOOLEAN_BOXEDv);
1057 g_dbus_connection_init (GDBusConnection *connection)
1059 g_mutex_init (&connection->lock);
1060 g_mutex_init (&connection->init_lock);
1062 connection->map_method_serial_to_task = g_hash_table_new (g_direct_hash, g_direct_equal);
1064 connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash,
1066 connection->map_id_to_signal_data = g_hash_table_new (g_direct_hash,
1068 connection->map_sender_unique_name_to_signal_data_array = g_hash_table_new_full (g_str_hash,
1071 (GDestroyNotify) g_ptr_array_unref);
1073 connection->map_object_path_to_eo = g_hash_table_new_full (g_str_hash,
1076 (GDestroyNotify) exported_object_free);
1078 connection->map_id_to_ei = g_hash_table_new (g_direct_hash,
1081 connection->map_object_path_to_es = g_hash_table_new_full (g_str_hash,
1084 (GDestroyNotify) exported_subtree_unref);
1086 connection->map_id_to_es = g_hash_table_new (g_direct_hash,
1089 connection->map_thread_to_last_serial = g_hash_table_new (g_direct_hash,
1092 connection->main_context_at_construction = g_main_context_ref_thread_default ();
1094 connection->filters = g_ptr_array_new ();
1098 * g_dbus_connection_get_stream:
1099 * @connection: a #GDBusConnection
1101 * Gets the underlying stream used for IO.
1103 * While the #GDBusConnection is active, it will interact with this
1104 * stream from a worker thread, so it is not safe to interact with
1105 * the stream directly.
1107 * Returns: (transfer none) (not nullable): the stream used for IO
1112 g_dbus_connection_get_stream (GDBusConnection *connection)
1114 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1116 /* do not use g_return_val_if_fail(), we want the memory barrier */
1117 if (!check_initialized (connection))
1120 return connection->stream;
1124 * g_dbus_connection_start_message_processing:
1125 * @connection: a #GDBusConnection
1127 * If @connection was created with
1128 * %G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, this method
1129 * starts processing messages. Does nothing on if @connection wasn't
1130 * created with this flag or if the method has already been called.
1135 g_dbus_connection_start_message_processing (GDBusConnection *connection)
1137 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1139 /* do not use g_return_val_if_fail(), we want the memory barrier */
1140 if (!check_initialized (connection))
1143 g_assert (connection->worker != NULL);
1144 _g_dbus_worker_unfreeze (connection->worker);
1148 * g_dbus_connection_is_closed:
1149 * @connection: a #GDBusConnection
1151 * Gets whether @connection is closed.
1153 * Returns: %TRUE if the connection is closed, %FALSE otherwise
1158 g_dbus_connection_is_closed (GDBusConnection *connection)
1162 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1164 flags = g_atomic_int_get (&connection->atomic_flags);
1166 return (flags & FLAG_CLOSED) ? TRUE : FALSE;
1170 * g_dbus_connection_get_capabilities:
1171 * @connection: a #GDBusConnection
1173 * Gets the capabilities negotiated with the remote peer
1175 * Returns: zero or more flags from the #GDBusCapabilityFlags enumeration
1179 GDBusCapabilityFlags
1180 g_dbus_connection_get_capabilities (GDBusConnection *connection)
1182 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_DBUS_CAPABILITY_FLAGS_NONE);
1184 /* do not use g_return_val_if_fail(), we want the memory barrier */
1185 if (!check_initialized (connection))
1186 return G_DBUS_CAPABILITY_FLAGS_NONE;
1188 return connection->capabilities;
1192 * g_dbus_connection_get_flags:
1193 * @connection: a #GDBusConnection
1195 * Gets the flags used to construct this connection
1197 * Returns: zero or more flags from the #GDBusConnectionFlags enumeration
1201 GDBusConnectionFlags
1202 g_dbus_connection_get_flags (GDBusConnection *connection)
1204 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_DBUS_CONNECTION_FLAGS_NONE);
1206 /* do not use g_return_val_if_fail(), we want the memory barrier */
1207 if (!check_initialized (connection))
1208 return G_DBUS_CONNECTION_FLAGS_NONE;
1210 return connection->flags;
1213 /* ---------------------------------------------------------------------------------------------------- */
1215 /* Called in a temporary thread without holding locks. */
1217 flush_in_thread_func (GTask *task,
1218 gpointer source_object,
1220 GCancellable *cancellable)
1222 GError *error = NULL;
1224 if (g_dbus_connection_flush_sync (source_object,
1227 g_task_return_boolean (task, TRUE);
1229 g_task_return_error (task, error);
1233 * g_dbus_connection_flush:
1234 * @connection: a #GDBusConnection
1235 * @cancellable: (nullable): a #GCancellable or %NULL
1236 * @callback: (nullable): a #GAsyncReadyCallback to call when the
1237 * request is satisfied or %NULL if you don't care about the result
1238 * @user_data: The data to pass to @callback
1240 * Asynchronously flushes @connection, that is, writes all queued
1241 * outgoing message to the transport and then flushes the transport
1242 * (using g_output_stream_flush_async()). This is useful in programs
1243 * that wants to emit a D-Bus signal and then exit immediately. Without
1244 * flushing the connection, there is no guaranteed that the message has
1245 * been sent to the networking buffers in the OS kernel.
1247 * This is an asynchronous method. When the operation is finished,
1248 * @callback will be invoked in the
1249 * [thread-default main context][g-main-context-push-thread-default]
1250 * of the thread you are calling this method from. You can
1251 * then call g_dbus_connection_flush_finish() to get the result of the
1252 * operation. See g_dbus_connection_flush_sync() for the synchronous
1258 g_dbus_connection_flush (GDBusConnection *connection,
1259 GCancellable *cancellable,
1260 GAsyncReadyCallback callback,
1265 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1267 task = g_task_new (connection, cancellable, callback, user_data);
1268 g_task_set_source_tag (task, g_dbus_connection_flush);
1269 g_task_run_in_thread (task, flush_in_thread_func);
1270 g_object_unref (task);
1274 * g_dbus_connection_flush_finish:
1275 * @connection: a #GDBusConnection
1276 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
1277 * to g_dbus_connection_flush()
1278 * @error: return location for error or %NULL
1280 * Finishes an operation started with g_dbus_connection_flush().
1282 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1287 g_dbus_connection_flush_finish (GDBusConnection *connection,
1291 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1292 g_return_val_if_fail (g_task_is_valid (res, connection), FALSE);
1293 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1295 return g_task_propagate_boolean (G_TASK (res), error);
1299 * g_dbus_connection_flush_sync:
1300 * @connection: a #GDBusConnection
1301 * @cancellable: (nullable): a #GCancellable or %NULL
1302 * @error: return location for error or %NULL
1304 * Synchronously flushes @connection. The calling thread is blocked
1305 * until this is done. See g_dbus_connection_flush() for the
1306 * asynchronous version of this method and more details about what it
1309 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1314 g_dbus_connection_flush_sync (GDBusConnection *connection,
1315 GCancellable *cancellable,
1320 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1321 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1325 /* This is only a best-effort attempt to see whether the connection is
1326 * closed, so it doesn't need the lock. If the connection closes just
1327 * after this check, but before scheduling the flush operation, the
1328 * result will be more or less the same as if the connection closed while
1329 * the flush operation was pending - it'll fail with either CLOSED or
1332 if (!check_unclosed (connection, 0, error))
1335 g_assert (connection->worker != NULL);
1337 ret = _g_dbus_worker_flush_sync (connection->worker,
1345 /* ---------------------------------------------------------------------------------------------------- */
1349 GDBusConnection *connection;
1351 gboolean remote_peer_vanished;
1355 emit_closed_data_free (EmitClosedData *data)
1357 g_object_unref (data->connection);
1358 if (data->error != NULL)
1359 g_error_free (data->error);
1363 /* Called in a user thread that has acquired the main context that was
1364 * thread-default when the object was constructed
1367 emit_closed_in_idle (gpointer user_data)
1369 EmitClosedData *data = user_data;
1372 g_object_notify (G_OBJECT (data->connection), "closed");
1373 g_signal_emit (data->connection,
1374 signals[CLOSED_SIGNAL],
1376 data->remote_peer_vanished,
1382 /* Can be called from any thread, must hold lock.
1383 * FLAG_CLOSED must already have been set.
1386 schedule_closed_unlocked (GDBusConnection *connection,
1387 gboolean remote_peer_vanished,
1390 GSource *idle_source;
1391 EmitClosedData *data;
1393 CONNECTION_ENSURE_LOCK (connection);
1395 data = g_new0 (EmitClosedData, 1);
1396 data->connection = g_object_ref (connection);
1397 data->remote_peer_vanished = remote_peer_vanished;
1398 data->error = error != NULL ? g_error_copy (error) : NULL;
1400 idle_source = g_idle_source_new ();
1401 g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
1402 g_source_set_callback (idle_source,
1403 emit_closed_in_idle,
1405 (GDestroyNotify) emit_closed_data_free);
1406 g_source_set_static_name (idle_source, "[gio] emit_closed_in_idle");
1407 g_source_attach (idle_source, connection->main_context_at_construction);
1408 g_source_unref (idle_source);
1411 /* ---------------------------------------------------------------------------------------------------- */
1414 * g_dbus_connection_close:
1415 * @connection: a #GDBusConnection
1416 * @cancellable: (nullable): a #GCancellable or %NULL
1417 * @callback: (nullable): a #GAsyncReadyCallback to call when the request is
1418 * satisfied or %NULL if you don't care about the result
1419 * @user_data: The data to pass to @callback
1421 * Closes @connection. Note that this never causes the process to
1422 * exit (this might only happen if the other end of a shared message
1423 * bus connection disconnects, see #GDBusConnection:exit-on-close).
1425 * Once the connection is closed, operations such as sending a message
1426 * will return with the error %G_IO_ERROR_CLOSED. Closing a connection
1427 * will not automatically flush the connection so queued messages may
1428 * be lost. Use g_dbus_connection_flush() if you need such guarantees.
1430 * If @connection is already closed, this method fails with
1431 * %G_IO_ERROR_CLOSED.
1433 * When @connection has been closed, the #GDBusConnection::closed
1434 * signal is emitted in the
1435 * [thread-default main context][g-main-context-push-thread-default]
1436 * of the thread that @connection was constructed in.
1438 * This is an asynchronous method. When the operation is finished,
1439 * @callback will be invoked in the
1440 * [thread-default main context][g-main-context-push-thread-default]
1441 * of the thread you are calling this method from. You can
1442 * then call g_dbus_connection_close_finish() to get the result of the
1443 * operation. See g_dbus_connection_close_sync() for the synchronous
1449 g_dbus_connection_close (GDBusConnection *connection,
1450 GCancellable *cancellable,
1451 GAsyncReadyCallback callback,
1456 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
1458 /* do not use g_return_val_if_fail(), we want the memory barrier */
1459 if (!check_initialized (connection))
1462 g_assert (connection->worker != NULL);
1464 task = g_task_new (connection, cancellable, callback, user_data);
1465 g_task_set_source_tag (task, g_dbus_connection_close);
1466 _g_dbus_worker_close (connection->worker, task);
1467 g_object_unref (task);
1471 * g_dbus_connection_close_finish:
1472 * @connection: a #GDBusConnection
1473 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
1474 * to g_dbus_connection_close()
1475 * @error: return location for error or %NULL
1477 * Finishes an operation started with g_dbus_connection_close().
1479 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1484 g_dbus_connection_close_finish (GDBusConnection *connection,
1488 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1489 g_return_val_if_fail (g_task_is_valid (res, connection), FALSE);
1490 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1492 return g_task_propagate_boolean (G_TASK (res), error);
1497 GAsyncResult *result;
1500 /* Can be called by any thread, without the connection lock */
1502 sync_close_cb (GObject *source_object,
1506 SyncCloseData *data = user_data;
1508 data->result = g_object_ref (res);
1509 g_main_loop_quit (data->loop);
1513 * g_dbus_connection_close_sync:
1514 * @connection: a #GDBusConnection
1515 * @cancellable: (nullable): a #GCancellable or %NULL
1516 * @error: return location for error or %NULL
1518 * Synchronously closes @connection. The calling thread is blocked
1519 * until this is done. See g_dbus_connection_close() for the
1520 * asynchronous version of this method and more details about what it
1523 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1528 g_dbus_connection_close_sync (GDBusConnection *connection,
1529 GCancellable *cancellable,
1534 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1535 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1539 if (check_unclosed (connection, 0, error))
1541 GMainContext *context;
1544 context = g_main_context_new ();
1545 g_main_context_push_thread_default (context);
1546 data.loop = g_main_loop_new (context, TRUE);
1549 g_dbus_connection_close (connection, cancellable, sync_close_cb, &data);
1550 g_main_loop_run (data.loop);
1551 ret = g_dbus_connection_close_finish (connection, data.result, error);
1553 g_object_unref (data.result);
1554 g_main_loop_unref (data.loop);
1555 g_main_context_pop_thread_default (context);
1556 g_main_context_unref (context);
1562 /* ---------------------------------------------------------------------------------------------------- */
1565 * g_dbus_connection_get_last_serial:
1566 * @connection: a #GDBusConnection
1568 * Retrieves the last serial number assigned to a #GDBusMessage on
1569 * the current thread. This includes messages sent via both low-level
1570 * API such as g_dbus_connection_send_message() as well as
1571 * high-level API such as g_dbus_connection_emit_signal(),
1572 * g_dbus_connection_call() or g_dbus_proxy_call().
1574 * Returns: the last used serial or zero when no message has been sent
1575 * within the current thread
1580 g_dbus_connection_get_last_serial (GDBusConnection *connection)
1584 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
1586 CONNECTION_LOCK (connection);
1587 ret = GPOINTER_TO_UINT (g_hash_table_lookup (connection->map_thread_to_last_serial,
1589 CONNECTION_UNLOCK (connection);
1594 /* ---------------------------------------------------------------------------------------------------- */
1596 /* Can be called by any thread, with the connection lock held */
1598 g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
1599 GDBusMessage *message,
1600 GDBusSendMessageFlags flags,
1601 guint32 *out_serial,
1606 guint32 serial_to_use;
1608 CONNECTION_ENSURE_LOCK (connection);
1610 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1611 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1613 /* TODO: check all necessary headers are present */
1615 if (out_serial != NULL)
1618 /* If we're in initable_init(), don't check for being initialized, to avoid
1619 * chicken-and-egg problems. initable_init() is responsible for setting up
1620 * our prerequisites (mainly connection->worker), and only calling us
1621 * from its own thread (so no memory barrier is needed).
1623 if (!check_unclosed (connection,
1624 (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0,
1628 blob = g_dbus_message_to_blob (message,
1630 connection->capabilities,
1635 if (flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL)
1636 serial_to_use = g_dbus_message_get_serial (message);
1638 serial_to_use = ++connection->last_serial; /* TODO: handle overflow */
1643 ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
1646 ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
1649 g_assert_not_reached ();
1654 g_printerr ("Writing message of %" G_GSIZE_FORMAT " bytes (serial %d) on %p:\n",
1655 blob_size, serial_to_use, connection);
1656 g_printerr ("----\n");
1657 hexdump (blob, blob_size);
1658 g_printerr ("----\n");
1661 /* TODO: use connection->auth to encode the blob */
1663 if (out_serial != NULL)
1664 *out_serial = serial_to_use;
1666 /* store used serial for the current thread */
1667 /* TODO: watch the thread disposal and remove associated record
1669 * - see https://bugzilla.gnome.org/show_bug.cgi?id=676825#c7
1671 g_hash_table_replace (connection->map_thread_to_last_serial,
1673 GUINT_TO_POINTER (serial_to_use));
1675 if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
1676 g_dbus_message_set_serial (message, serial_to_use);
1678 g_dbus_message_lock (message);
1680 _g_dbus_worker_send_message (connection->worker,
1682 (gchar*) blob, /* transfer ownership */
1689 * g_dbus_connection_send_message:
1690 * @connection: a #GDBusConnection
1691 * @message: a #GDBusMessage
1692 * @flags: flags affecting how the message is sent
1693 * @out_serial: (out) (optional): return location for serial number assigned
1694 * to @message when sending it or %NULL
1695 * @error: Return location for error or %NULL
1697 * Asynchronously sends @message to the peer represented by @connection.
1699 * Unless @flags contain the
1700 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
1701 * will be assigned by @connection and set on @message via
1702 * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
1703 * serial number used will be written to this location prior to
1704 * submitting the message to the underlying transport. While it has a `volatile`
1705 * qualifier, this is a historical artifact and the argument passed to it should
1706 * not be `volatile`.
1708 * If @connection is closed then the operation will fail with
1709 * %G_IO_ERROR_CLOSED. If @message is not well-formed,
1710 * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1712 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
1713 * for an example of how to use this low-level API to send and receive
1714 * UNIX file descriptors.
1716 * Note that @message must be unlocked, unless @flags contain the
1717 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
1719 * Returns: %TRUE if the message was well-formed and queued for
1720 * transmission, %FALSE if @error is set
1725 g_dbus_connection_send_message (GDBusConnection *connection,
1726 GDBusMessage *message,
1727 GDBusSendMessageFlags flags,
1728 volatile guint32 *out_serial,
1733 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
1734 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1735 g_return_val_if_fail ((flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL) || !g_dbus_message_get_locked (message), FALSE);
1736 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1738 CONNECTION_LOCK (connection);
1739 ret = g_dbus_connection_send_message_unlocked (connection, message, flags, (guint32 *) out_serial, error);
1740 CONNECTION_UNLOCK (connection);
1744 /* ---------------------------------------------------------------------------------------------------- */
1750 gulong cancellable_handler_id;
1752 GSource *timeout_source;
1757 /* Can be called from any thread with or without lock held */
1759 send_message_data_free (SendMessageData *data)
1761 g_assert (data->timeout_source == NULL);
1762 g_assert (data->cancellable_handler_id == 0);
1764 g_slice_free (SendMessageData, data);
1767 /* ---------------------------------------------------------------------------------------------------- */
1769 /* can be called from any thread with lock held; @task is (transfer full) */
1771 send_message_with_reply_cleanup (GTask *task, gboolean remove)
1773 GDBusConnection *connection = g_task_get_source_object (task);
1774 SendMessageData *data = g_task_get_task_data (task);
1776 CONNECTION_ENSURE_LOCK (connection);
1778 g_assert (!data->delivered);
1780 data->delivered = TRUE;
1782 if (data->timeout_source != NULL)
1784 g_source_destroy (data->timeout_source);
1785 data->timeout_source = NULL;
1787 if (data->cancellable_handler_id > 0)
1789 g_cancellable_disconnect (g_task_get_cancellable (task), data->cancellable_handler_id);
1790 data->cancellable_handler_id = 0;
1795 gboolean removed = g_hash_table_remove (connection->map_method_serial_to_task,
1796 GUINT_TO_POINTER (data->serial));
1797 g_warn_if_fail (removed);
1800 g_object_unref (task);
1803 /* ---------------------------------------------------------------------------------------------------- */
1805 /* Called from GDBus worker thread with lock held; @task is (transfer full). */
1807 send_message_data_deliver_reply_unlocked (GTask *task,
1808 GDBusMessage *reply)
1810 SendMessageData *data = g_task_get_task_data (task);
1812 if (data->delivered)
1815 g_task_return_pointer (task, g_object_ref (reply), g_object_unref);
1817 send_message_with_reply_cleanup (task, TRUE);
1823 /* Called from a user thread, lock is not held */
1825 send_message_data_deliver_error (GTask *task,
1828 const char *message)
1830 GDBusConnection *connection = g_task_get_source_object (task);
1831 SendMessageData *data = g_task_get_task_data (task);
1833 CONNECTION_LOCK (connection);
1834 if (data->delivered)
1836 CONNECTION_UNLOCK (connection);
1840 g_object_ref (task);
1841 send_message_with_reply_cleanup (task, TRUE);
1842 CONNECTION_UNLOCK (connection);
1844 g_task_return_new_error (task, domain, code, "%s", message);
1845 g_object_unref (task);
1848 /* ---------------------------------------------------------------------------------------------------- */
1850 /* Called from a user thread, lock is not held; @task is (transfer full) */
1852 send_message_with_reply_cancelled_idle_cb (gpointer user_data)
1854 GTask *task = user_data;
1856 send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED,
1857 _("Operation was cancelled"));
1861 /* Can be called from any thread with or without lock held */
1863 send_message_with_reply_cancelled_cb (GCancellable *cancellable,
1866 GTask *task = user_data;
1867 GSource *idle_source;
1869 /* postpone cancellation to idle handler since we may be called directly
1870 * via g_cancellable_connect() (e.g. holding lock)
1872 idle_source = g_idle_source_new ();
1873 g_source_set_static_name (idle_source, "[gio] send_message_with_reply_cancelled_idle_cb");
1874 g_task_attach_source (task, idle_source, send_message_with_reply_cancelled_idle_cb);
1875 g_source_unref (idle_source);
1878 /* ---------------------------------------------------------------------------------------------------- */
1880 /* Called from a user thread, lock is not held; @task is (transfer full) */
1882 send_message_with_reply_timeout_cb (gpointer user_data)
1884 GTask *task = user_data;
1886 send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
1887 _("Timeout was reached"));
1891 /* ---------------------------------------------------------------------------------------------------- */
1893 /* Called from a user thread, connection's lock is held */
1895 g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection *connection,
1896 GDBusMessage *message,
1897 GDBusSendMessageFlags flags,
1899 guint32 *out_serial,
1900 GCancellable *cancellable,
1901 GAsyncReadyCallback callback,
1905 SendMessageData *data;
1906 GError *error = NULL;
1909 if (out_serial == NULL)
1910 out_serial = &serial;
1912 if (timeout_msec == -1)
1913 timeout_msec = 25 * 1000;
1915 data = g_slice_new0 (SendMessageData);
1916 task = g_task_new (connection, cancellable, callback, user_data);
1917 g_task_set_source_tag (task,
1918 g_dbus_connection_send_message_with_reply_unlocked);
1919 g_task_set_task_data (task, data, (GDestroyNotify) send_message_data_free);
1921 if (g_task_return_error_if_cancelled (task))
1923 g_object_unref (task);
1927 if (!g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, &error))
1929 g_task_return_error (task, error);
1930 g_object_unref (task);
1933 data->serial = *out_serial;
1935 if (cancellable != NULL)
1937 data->cancellable_handler_id = g_cancellable_connect (cancellable,
1938 G_CALLBACK (send_message_with_reply_cancelled_cb),
1939 g_object_ref (task),
1943 if (timeout_msec != G_MAXINT)
1945 data->timeout_source = g_timeout_source_new (timeout_msec);
1946 g_task_attach_source (task, data->timeout_source,
1947 (GSourceFunc) send_message_with_reply_timeout_cb);
1948 g_source_unref (data->timeout_source);
1951 g_hash_table_insert (connection->map_method_serial_to_task,
1952 GUINT_TO_POINTER (*out_serial),
1953 g_steal_pointer (&task));
1957 * g_dbus_connection_send_message_with_reply:
1958 * @connection: a #GDBusConnection
1959 * @message: a #GDBusMessage
1960 * @flags: flags affecting how the message is sent
1961 * @timeout_msec: the timeout in milliseconds, -1 to use the default
1962 * timeout or %G_MAXINT for no timeout
1963 * @out_serial: (out) (optional): return location for serial number assigned
1964 * to @message when sending it or %NULL
1965 * @cancellable: (nullable): a #GCancellable or %NULL
1966 * @callback: (nullable): a #GAsyncReadyCallback to call when the request
1967 * is satisfied or %NULL if you don't care about the result
1968 * @user_data: The data to pass to @callback
1970 * Asynchronously sends @message to the peer represented by @connection.
1972 * Unless @flags contain the
1973 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
1974 * will be assigned by @connection and set on @message via
1975 * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
1976 * serial number used will be written to this location prior to
1977 * submitting the message to the underlying transport. While it has a `volatile`
1978 * qualifier, this is a historical artifact and the argument passed to it should
1979 * not be `volatile`.
1981 * If @connection is closed then the operation will fail with
1982 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
1983 * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
1984 * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1986 * This is an asynchronous method. When the operation is finished, @callback
1987 * will be invoked in the
1988 * [thread-default main context][g-main-context-push-thread-default]
1989 * of the thread you are calling this method from. You can then call
1990 * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
1991 * See g_dbus_connection_send_message_with_reply_sync() for the synchronous version.
1993 * Note that @message must be unlocked, unless @flags contain the
1994 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
1996 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
1997 * for an example of how to use this low-level API to send and receive
1998 * UNIX file descriptors.
2003 g_dbus_connection_send_message_with_reply (GDBusConnection *connection,
2004 GDBusMessage *message,
2005 GDBusSendMessageFlags flags,
2007 volatile guint32 *out_serial,
2008 GCancellable *cancellable,
2009 GAsyncReadyCallback callback,
2012 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2013 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2014 g_return_if_fail ((flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL) || !g_dbus_message_get_locked (message));
2015 g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
2017 CONNECTION_LOCK (connection);
2018 g_dbus_connection_send_message_with_reply_unlocked (connection,
2022 (guint32 *) out_serial,
2026 CONNECTION_UNLOCK (connection);
2030 * g_dbus_connection_send_message_with_reply_finish:
2031 * @connection: a #GDBusConnection
2032 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to
2033 * g_dbus_connection_send_message_with_reply()
2034 * @error: teturn location for error or %NULL
2036 * Finishes an operation started with g_dbus_connection_send_message_with_reply().
2038 * Note that @error is only set if a local in-process error
2039 * occurred. That is to say that the returned #GDBusMessage object may
2040 * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
2041 * g_dbus_message_to_gerror() to transcode this to a #GError.
2043 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
2044 * for an example of how to use this low-level API to send and receive
2045 * UNIX file descriptors.
2047 * Returns: (transfer full): a locked #GDBusMessage or %NULL if @error is set
2052 g_dbus_connection_send_message_with_reply_finish (GDBusConnection *connection,
2056 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2057 g_return_val_if_fail (g_task_is_valid (res, connection), NULL);
2058 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2060 return g_task_propagate_pointer (G_TASK (res), error);
2063 /* ---------------------------------------------------------------------------------------------------- */
2068 GMainContext *context;
2070 } SendMessageSyncData;
2072 /* Called from a user thread, lock is not held */
2074 send_message_with_reply_sync_cb (GDBusConnection *connection,
2078 SendMessageSyncData *data = user_data;
2079 data->res = g_object_ref (res);
2080 g_main_loop_quit (data->loop);
2084 * g_dbus_connection_send_message_with_reply_sync:
2085 * @connection: a #GDBusConnection
2086 * @message: a #GDBusMessage
2087 * @flags: flags affecting how the message is sent.
2088 * @timeout_msec: the timeout in milliseconds, -1 to use the default
2089 * timeout or %G_MAXINT for no timeout
2090 * @out_serial: (out) (optional): return location for serial number
2091 * assigned to @message when sending it or %NULL
2092 * @cancellable: (nullable): a #GCancellable or %NULL
2093 * @error: return location for error or %NULL
2095 * Synchronously sends @message to the peer represented by @connection
2096 * and blocks the calling thread until a reply is received or the
2097 * timeout is reached. See g_dbus_connection_send_message_with_reply()
2098 * for the asynchronous version of this method.
2100 * Unless @flags contain the
2101 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
2102 * will be assigned by @connection and set on @message via
2103 * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
2104 * serial number used will be written to this location prior to
2105 * submitting the message to the underlying transport. While it has a `volatile`
2106 * qualifier, this is a historical artifact and the argument passed to it should
2107 * not be `volatile`.
2109 * If @connection is closed then the operation will fail with
2110 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
2111 * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
2112 * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
2114 * Note that @error is only set if a local in-process error
2115 * occurred. That is to say that the returned #GDBusMessage object may
2116 * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
2117 * g_dbus_message_to_gerror() to transcode this to a #GError.
2119 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
2120 * for an example of how to use this low-level API to send and receive
2121 * UNIX file descriptors.
2123 * Note that @message must be unlocked, unless @flags contain the
2124 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
2126 * Returns: (transfer full): a locked #GDBusMessage that is the reply
2127 * to @message or %NULL if @error is set
2132 g_dbus_connection_send_message_with_reply_sync (GDBusConnection *connection,
2133 GDBusMessage *message,
2134 GDBusSendMessageFlags flags,
2136 volatile guint32 *out_serial,
2137 GCancellable *cancellable,
2140 SendMessageSyncData data;
2141 GDBusMessage *reply;
2143 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2144 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2145 g_return_val_if_fail ((flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL) || !g_dbus_message_get_locked (message), NULL);
2146 g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
2147 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2150 data.context = g_main_context_new ();
2151 data.loop = g_main_loop_new (data.context, FALSE);
2153 g_main_context_push_thread_default (data.context);
2155 g_dbus_connection_send_message_with_reply (connection,
2161 (GAsyncReadyCallback) send_message_with_reply_sync_cb,
2163 g_main_loop_run (data.loop);
2164 reply = g_dbus_connection_send_message_with_reply_finish (connection,
2168 g_main_context_pop_thread_default (data.context);
2170 g_main_context_unref (data.context);
2171 g_main_loop_unref (data.loop);
2173 g_object_unref (data.res);
2178 /* ---------------------------------------------------------------------------------------------------- */
2184 GDBusMessageFilterFunction filter_function;
2186 GDestroyNotify user_data_free_func;
2187 GMainContext *context;
2191 filter_data_destroy (FilterData *filter, gboolean notify_sync)
2195 if (filter->user_data_free_func != NULL)
2196 filter->user_data_free_func (filter->user_data);
2200 call_destroy_notify (filter->context,
2201 filter->user_data_free_func,
2204 g_main_context_unref (filter->context);
2208 /* requires CONNECTION_LOCK */
2209 static FilterData **
2210 copy_filter_list (GPtrArray *filters)
2215 copy = g_new (FilterData *, filters->len + 1);
2216 for (n = 0; n < filters->len; n++)
2218 copy[n] = filters->pdata[n];
2219 copy[n]->ref_count++;
2226 /* requires CONNECTION_LOCK */
2228 free_filter_list (FilterData **filters)
2232 for (n = 0; filters[n]; n++)
2234 filters[n]->ref_count--;
2235 if (filters[n]->ref_count == 0)
2236 filter_data_destroy (filters[n], FALSE);
2241 /* Called in GDBusWorker's thread - we must not block - with no lock held */
2243 on_worker_message_received (GDBusWorker *worker,
2244 GDBusMessage *message,
2247 GDBusConnection *connection;
2248 FilterData **filters;
2252 G_LOCK (message_bus_lock);
2253 alive = g_hash_table_contains (alive_connections, user_data);
2256 G_UNLOCK (message_bus_lock);
2259 connection = G_DBUS_CONNECTION (user_data);
2260 g_object_ref (connection);
2261 G_UNLOCK (message_bus_lock);
2263 //g_debug ("in on_worker_message_received");
2265 g_object_ref (message);
2266 g_dbus_message_lock (message);
2268 //g_debug ("boo ref_count = %d %p %p", G_OBJECT (connection)->ref_count, connection, connection->worker);
2270 /* First collect the set of callback functions */
2271 CONNECTION_LOCK (connection);
2272 filters = copy_filter_list (connection->filters);
2273 CONNECTION_UNLOCK (connection);
2275 /* then call the filters in order (without holding the lock) */
2276 for (n = 0; filters[n]; n++)
2278 message = filters[n]->filter_function (connection,
2281 filters[n]->user_data);
2282 if (message == NULL)
2284 g_dbus_message_lock (message);
2287 CONNECTION_LOCK (connection);
2288 free_filter_list (filters);
2289 CONNECTION_UNLOCK (connection);
2291 /* Standard dispatch unless the filter ate the message - no need to
2292 * do anything if the message was altered
2294 if (message != NULL)
2296 GDBusMessageType message_type;
2298 message_type = g_dbus_message_get_message_type (message);
2299 if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN || message_type == G_DBUS_MESSAGE_TYPE_ERROR)
2301 guint32 reply_serial;
2304 reply_serial = g_dbus_message_get_reply_serial (message);
2305 CONNECTION_LOCK (connection);
2306 task = g_hash_table_lookup (connection->map_method_serial_to_task,
2307 GUINT_TO_POINTER (reply_serial));
2310 /* This removes @task from @map_method_serial_to_task. */
2311 //g_debug ("delivering reply/error for serial %d for %p", reply_serial, connection);
2312 send_message_data_deliver_reply_unlocked (task, message);
2316 //g_debug ("message reply/error for serial %d but no SendMessageData found for %p", reply_serial, connection);
2318 CONNECTION_UNLOCK (connection);
2320 else if (message_type == G_DBUS_MESSAGE_TYPE_SIGNAL)
2322 CONNECTION_LOCK (connection);
2323 distribute_signals (connection, message);
2324 CONNECTION_UNLOCK (connection);
2326 else if (message_type == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
2328 CONNECTION_LOCK (connection);
2329 distribute_method_call (connection, message);
2330 CONNECTION_UNLOCK (connection);
2334 if (message != NULL)
2335 g_object_unref (message);
2336 g_object_unref (connection);
2339 /* Called in GDBusWorker's thread, lock is not held */
2340 static GDBusMessage *
2341 on_worker_message_about_to_be_sent (GDBusWorker *worker,
2342 GDBusMessage *message,
2345 GDBusConnection *connection;
2346 FilterData **filters;
2350 G_LOCK (message_bus_lock);
2351 alive = g_hash_table_contains (alive_connections, user_data);
2354 G_UNLOCK (message_bus_lock);
2357 connection = G_DBUS_CONNECTION (user_data);
2358 g_object_ref (connection);
2359 G_UNLOCK (message_bus_lock);
2361 //g_debug ("in on_worker_message_about_to_be_sent");
2363 /* First collect the set of callback functions */
2364 CONNECTION_LOCK (connection);
2365 filters = copy_filter_list (connection->filters);
2366 CONNECTION_UNLOCK (connection);
2368 /* then call the filters in order (without holding the lock) */
2369 for (n = 0; filters[n]; n++)
2371 g_dbus_message_lock (message);
2372 message = filters[n]->filter_function (connection,
2375 filters[n]->user_data);
2376 if (message == NULL)
2380 CONNECTION_LOCK (connection);
2381 free_filter_list (filters);
2382 CONNECTION_UNLOCK (connection);
2384 g_object_unref (connection);
2389 /* called with connection lock held, in GDBusWorker thread */
2391 cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
2393 GTask *task = value;
2394 SendMessageData *data = g_task_get_task_data (task);
2396 if (data->delivered)
2399 g_task_return_new_error (task,
2402 _("The connection is closed"));
2404 /* Ask send_message_with_reply_cleanup not to remove the element from the
2405 * hash table - we're in the middle of a foreach; that would be unsafe.
2406 * Instead, return TRUE from this function so that it gets removed safely.
2408 send_message_with_reply_cleanup (task, FALSE);
2412 /* Called in GDBusWorker's thread - we must not block - without lock held */
2414 on_worker_closed (GDBusWorker *worker,
2415 gboolean remote_peer_vanished,
2419 GDBusConnection *connection;
2421 guint old_atomic_flags;
2423 G_LOCK (message_bus_lock);
2424 alive = g_hash_table_contains (alive_connections, user_data);
2427 G_UNLOCK (message_bus_lock);
2430 connection = G_DBUS_CONNECTION (user_data);
2431 g_object_ref (connection);
2432 G_UNLOCK (message_bus_lock);
2434 //g_debug ("in on_worker_closed: %s", error->message);
2436 CONNECTION_LOCK (connection);
2437 /* Even though this is atomic, we do it inside the lock to avoid breaking
2438 * assumptions in remove_match_rule(). We'd need the lock in a moment
2439 * anyway, so, no loss.
2441 old_atomic_flags = g_atomic_int_or (&connection->atomic_flags, FLAG_CLOSED);
2443 if (!(old_atomic_flags & FLAG_CLOSED))
2445 g_hash_table_foreach_remove (connection->map_method_serial_to_task, cancel_method_on_close, NULL);
2446 schedule_closed_unlocked (connection, remote_peer_vanished, error);
2448 CONNECTION_UNLOCK (connection);
2450 g_object_unref (connection);
2453 /* ---------------------------------------------------------------------------------------------------- */
2455 /* Determines the biggest set of capabilities we can support on this
2458 * Called with the init_lock held.
2460 static GDBusCapabilityFlags
2461 get_offered_capabilities_max (GDBusConnection *connection)
2463 GDBusCapabilityFlags ret;
2464 ret = G_DBUS_CAPABILITY_FLAGS_NONE;
2466 if (G_IS_UNIX_CONNECTION (connection->stream))
2467 ret |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
2472 /* Called in a user thread, lock is not held */
2474 initable_init (GInitable *initable,
2475 GCancellable *cancellable,
2478 GDBusConnection *connection = G_DBUS_CONNECTION (initable);
2481 /* This method needs to be idempotent to work with the singleton
2482 * pattern. See the docs for g_initable_init(). We implement this by
2485 * Unfortunately we can't use the main lock since the on_worker_*()
2486 * callbacks above needs the lock during initialization (for message
2487 * bus connections we do a synchronous Hello() call on the bus).
2489 g_mutex_lock (&connection->init_lock);
2493 /* Make this a no-op if we're already initialized (successfully or
2496 if ((g_atomic_int_get (&connection->atomic_flags) & FLAG_INITIALIZED))
2498 ret = (connection->initialization_error == NULL);
2502 /* Because of init_lock, we can't get here twice in different threads */
2503 g_assert (connection->initialization_error == NULL);
2505 /* The user can pass multiple (but mutally exclusive) construct
2508 * - stream (of type GIOStream)
2509 * - address (of type gchar*)
2511 * At the end of the day we end up with a non-NULL GIOStream
2512 * object in connection->stream.
2514 if (connection->address != NULL)
2516 g_assert (connection->stream == NULL);
2518 if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
2519 (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) ||
2520 (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER))
2522 g_set_error_literal (&connection->initialization_error,
2524 G_IO_ERROR_INVALID_ARGUMENT,
2525 _("Unsupported flags encountered when constructing a client-side connection"));
2529 connection->stream = g_dbus_address_get_stream_sync (connection->address,
2530 NULL, /* TODO: out_guid */
2532 &connection->initialization_error);
2533 if (connection->stream == NULL)
2536 else if (connection->stream != NULL)
2542 g_assert_not_reached ();
2545 /* Authenticate the connection */
2546 if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
2548 g_assert (!(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT));
2549 g_assert (connection->guid != NULL);
2550 connection->auth = _g_dbus_auth_new (connection->stream);
2551 if (!_g_dbus_auth_run_server (connection->auth,
2552 connection->authentication_observer,
2554 (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS),
2555 (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER),
2556 get_offered_capabilities_max (connection),
2557 &connection->capabilities,
2558 &connection->credentials,
2560 &connection->initialization_error))
2563 else if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT)
2565 g_assert (!(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER));
2566 g_assert (connection->guid == NULL);
2567 connection->auth = _g_dbus_auth_new (connection->stream);
2568 connection->guid = _g_dbus_auth_run_client (connection->auth,
2569 connection->authentication_observer,
2570 get_offered_capabilities_max (connection),
2571 &connection->capabilities,
2573 &connection->initialization_error);
2574 if (connection->guid == NULL)
2578 if (connection->authentication_observer != NULL)
2580 g_object_unref (connection->authentication_observer);
2581 connection->authentication_observer = NULL;
2584 //g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
2586 //g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
2589 /* We want all IO operations to be non-blocking since they happen in
2590 * the worker thread which is shared by _all_ connections.
2592 if (G_IS_SOCKET_CONNECTION (connection->stream))
2594 g_socket_set_blocking (g_socket_connection_get_socket (G_SOCKET_CONNECTION (connection->stream)), FALSE);
2598 G_LOCK (message_bus_lock);
2599 if (alive_connections == NULL)
2600 alive_connections = g_hash_table_new (g_direct_hash, g_direct_equal);
2601 g_hash_table_add (alive_connections, connection);
2602 G_UNLOCK (message_bus_lock);
2604 connection->worker = _g_dbus_worker_new (connection->stream,
2605 connection->capabilities,
2606 ((connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) != 0),
2607 on_worker_message_received,
2608 on_worker_message_about_to_be_sent,
2612 /* if a bus connection, call org.freedesktop.DBus.Hello - this is how we're getting a name */
2613 if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
2615 GVariant *hello_result;
2617 /* we could lift this restriction by adding code in gdbusprivate.c */
2618 if (connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING)
2620 g_set_error_literal (&connection->initialization_error,
2623 "Cannot use DELAY_MESSAGE_PROCESSING with MESSAGE_BUS_CONNECTION");
2627 hello_result = g_dbus_connection_call_sync (connection,
2628 "org.freedesktop.DBus", /* name */
2629 "/org/freedesktop/DBus", /* path */
2630 "org.freedesktop.DBus", /* interface */
2632 NULL, /* parameters */
2633 G_VARIANT_TYPE ("(s)"),
2634 CALL_FLAGS_INITIALIZING,
2636 NULL, /* TODO: cancellable */
2637 &connection->initialization_error);
2638 if (hello_result == NULL)
2641 g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
2642 g_variant_unref (hello_result);
2643 //g_debug ("unique name is '%s'", connection->bus_unique_name);
2650 g_assert (connection->initialization_error != NULL);
2651 g_propagate_error (error, g_error_copy (connection->initialization_error));
2654 g_atomic_int_or (&connection->atomic_flags, FLAG_INITIALIZED);
2655 g_mutex_unlock (&connection->init_lock);
2661 initable_iface_init (GInitableIface *initable_iface)
2663 initable_iface->init = initable_init;
2666 /* ---------------------------------------------------------------------------------------------------- */
2669 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
2674 /* ---------------------------------------------------------------------------------------------------- */
2677 * g_dbus_connection_new:
2678 * @stream: a #GIOStream
2679 * @guid: (nullable): the GUID to use if authenticating as a server or %NULL
2680 * @flags: flags describing how to make the connection
2681 * @observer: (nullable): a #GDBusAuthObserver or %NULL
2682 * @cancellable: (nullable): a #GCancellable or %NULL
2683 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2684 * @user_data: the data to pass to @callback
2686 * Asynchronously sets up a D-Bus connection for exchanging D-Bus messages
2687 * with the end represented by @stream.
2689 * If @stream is a #GSocketConnection, then the corresponding #GSocket
2690 * will be put into non-blocking mode.
2692 * The D-Bus connection will interact with @stream from a worker thread.
2693 * As a result, the caller should not interact with @stream after this
2694 * method has been called, except by calling g_object_unref() on it.
2696 * If @observer is not %NULL it may be used to control the
2697 * authentication process.
2699 * When the operation is finished, @callback will be invoked. You can
2700 * then call g_dbus_connection_new_finish() to get the result of the
2703 * This is an asynchronous failable constructor. See
2704 * g_dbus_connection_new_sync() for the synchronous
2710 g_dbus_connection_new (GIOStream *stream,
2712 GDBusConnectionFlags flags,
2713 GDBusAuthObserver *observer,
2714 GCancellable *cancellable,
2715 GAsyncReadyCallback callback,
2718 _g_dbus_initialize ();
2720 g_return_if_fail (G_IS_IO_STREAM (stream));
2721 g_return_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0);
2723 g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2731 "authentication-observer", observer,
2736 * g_dbus_connection_new_finish:
2737 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback
2738 * passed to g_dbus_connection_new().
2739 * @error: return location for error or %NULL
2741 * Finishes an operation started with g_dbus_connection_new().
2743 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set. Free
2744 * with g_object_unref().
2749 g_dbus_connection_new_finish (GAsyncResult *res,
2753 GObject *source_object;
2755 g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2756 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2758 source_object = g_async_result_get_source_object (res);
2759 g_assert (source_object != NULL);
2760 object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2763 g_object_unref (source_object);
2765 return G_DBUS_CONNECTION (object);
2771 * g_dbus_connection_new_sync:
2772 * @stream: a #GIOStream
2773 * @guid: (nullable): the GUID to use if authenticating as a server or %NULL
2774 * @flags: flags describing how to make the connection
2775 * @observer: (nullable): a #GDBusAuthObserver or %NULL
2776 * @cancellable: (nullable): a #GCancellable or %NULL
2777 * @error: return location for error or %NULL
2779 * Synchronously sets up a D-Bus connection for exchanging D-Bus messages
2780 * with the end represented by @stream.
2782 * If @stream is a #GSocketConnection, then the corresponding #GSocket
2783 * will be put into non-blocking mode.
2785 * The D-Bus connection will interact with @stream from a worker thread.
2786 * As a result, the caller should not interact with @stream after this
2787 * method has been called, except by calling g_object_unref() on it.
2789 * If @observer is not %NULL it may be used to control the
2790 * authentication process.
2792 * This is a synchronous failable constructor. See
2793 * g_dbus_connection_new() for the asynchronous version.
2795 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
2796 * Free with g_object_unref().
2801 g_dbus_connection_new_sync (GIOStream *stream,
2803 GDBusConnectionFlags flags,
2804 GDBusAuthObserver *observer,
2805 GCancellable *cancellable,
2808 _g_dbus_initialize ();
2809 g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL);
2810 g_return_val_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0, NULL);
2811 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2812 return g_initable_new (G_TYPE_DBUS_CONNECTION,
2818 "authentication-observer", observer,
2822 /* ---------------------------------------------------------------------------------------------------- */
2825 * g_dbus_connection_new_for_address:
2826 * @address: a D-Bus address
2827 * @flags: flags describing how to make the connection
2828 * @observer: (nullable): a #GDBusAuthObserver or %NULL
2829 * @cancellable: (nullable): a #GCancellable or %NULL
2830 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2831 * @user_data: the data to pass to @callback
2833 * Asynchronously connects and sets up a D-Bus client connection for
2834 * exchanging D-Bus messages with an endpoint specified by @address
2835 * which must be in the
2836 * [D-Bus address format](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses).
2838 * This constructor can only be used to initiate client-side
2839 * connections - use g_dbus_connection_new() if you need to act as the
2840 * server. In particular, @flags cannot contain the
2841 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
2842 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS or
2843 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flags.
2845 * When the operation is finished, @callback will be invoked. You can
2846 * then call g_dbus_connection_new_for_address_finish() to get the result of
2849 * If @observer is not %NULL it may be used to control the
2850 * authentication process.
2852 * This is an asynchronous failable constructor. See
2853 * g_dbus_connection_new_for_address_sync() for the synchronous
2859 g_dbus_connection_new_for_address (const gchar *address,
2860 GDBusConnectionFlags flags,
2861 GDBusAuthObserver *observer,
2862 GCancellable *cancellable,
2863 GAsyncReadyCallback callback,
2866 _g_dbus_initialize ();
2868 g_return_if_fail (address != NULL);
2869 g_return_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0);
2871 g_async_initable_new_async (G_TYPE_DBUS_CONNECTION,
2878 "authentication-observer", observer,
2883 * g_dbus_connection_new_for_address_finish:
2884 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
2885 * to g_dbus_connection_new()
2886 * @error: return location for error or %NULL
2888 * Finishes an operation started with g_dbus_connection_new_for_address().
2890 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
2891 * Free with g_object_unref().
2896 g_dbus_connection_new_for_address_finish (GAsyncResult *res,
2900 GObject *source_object;
2902 g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
2903 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2905 source_object = g_async_result_get_source_object (res);
2906 g_assert (source_object != NULL);
2907 object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
2910 g_object_unref (source_object);
2912 return G_DBUS_CONNECTION (object);
2918 * g_dbus_connection_new_for_address_sync:
2919 * @address: a D-Bus address
2920 * @flags: flags describing how to make the connection
2921 * @observer: (nullable): a #GDBusAuthObserver or %NULL
2922 * @cancellable: (nullable): a #GCancellable or %NULL
2923 * @error: return location for error or %NULL
2925 * Synchronously connects and sets up a D-Bus client connection for
2926 * exchanging D-Bus messages with an endpoint specified by @address
2927 * which must be in the
2928 * [D-Bus address format](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses).
2930 * This constructor can only be used to initiate client-side
2931 * connections - use g_dbus_connection_new_sync() if you need to act
2932 * as the server. In particular, @flags cannot contain the
2933 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
2934 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS or
2935 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flags.
2937 * This is a synchronous failable constructor. See
2938 * g_dbus_connection_new_for_address() for the asynchronous version.
2940 * If @observer is not %NULL it may be used to control the
2941 * authentication process.
2943 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
2944 * Free with g_object_unref().
2949 g_dbus_connection_new_for_address_sync (const gchar *address,
2950 GDBusConnectionFlags flags,
2951 GDBusAuthObserver *observer,
2952 GCancellable *cancellable,
2955 _g_dbus_initialize ();
2957 g_return_val_if_fail (address != NULL, NULL);
2958 g_return_val_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0, NULL);
2959 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2960 return g_initable_new (G_TYPE_DBUS_CONNECTION,
2965 "authentication-observer", observer,
2969 /* ---------------------------------------------------------------------------------------------------- */
2972 * g_dbus_connection_set_exit_on_close:
2973 * @connection: a #GDBusConnection
2974 * @exit_on_close: whether the process should be terminated
2975 * when @connection is closed by the remote peer
2977 * Sets whether the process should be terminated when @connection is
2978 * closed by the remote peer. See #GDBusConnection:exit-on-close for
2981 * Note that this function should be used with care. Most modern UNIX
2982 * desktops tie the notion of a user session with the session bus, and expect
2983 * all of a user's applications to quit when their bus connection goes away.
2984 * If you are setting @exit_on_close to %FALSE for the shared session
2985 * bus connection, you should make sure that your application exits
2986 * when the user session ends.
2991 g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
2992 gboolean exit_on_close)
2994 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
2997 g_atomic_int_or (&connection->atomic_flags, FLAG_EXIT_ON_CLOSE);
2999 g_atomic_int_and (&connection->atomic_flags, ~FLAG_EXIT_ON_CLOSE);
3004 * g_dbus_connection_get_exit_on_close:
3005 * @connection: a #GDBusConnection
3007 * Gets whether the process is terminated when @connection is
3008 * closed by the remote peer. See
3009 * #GDBusConnection:exit-on-close for more details.
3011 * Returns: whether the process is terminated when @connection is
3012 * closed by the remote peer
3017 g_dbus_connection_get_exit_on_close (GDBusConnection *connection)
3019 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
3021 if (g_atomic_int_get (&connection->atomic_flags) & FLAG_EXIT_ON_CLOSE)
3028 * g_dbus_connection_get_guid:
3029 * @connection: a #GDBusConnection
3031 * The GUID of the peer performing the role of server when
3032 * authenticating. See #GDBusConnection:guid for more details.
3034 * Returns: (not nullable): The GUID. Do not free this string, it is owned by
3040 g_dbus_connection_get_guid (GDBusConnection *connection)
3042 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
3043 return connection->guid;
3047 * g_dbus_connection_get_unique_name:
3048 * @connection: a #GDBusConnection
3050 * Gets the unique name of @connection as assigned by the message
3051 * bus. This can also be used to figure out if @connection is a
3052 * message bus connection.
3054 * Returns: (nullable): the unique name or %NULL if @connection is not a message
3055 * bus connection. Do not free this string, it is owned by
3061 g_dbus_connection_get_unique_name (GDBusConnection *connection)
3063 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
3065 /* do not use g_return_val_if_fail(), we want the memory barrier */
3066 if (!check_initialized (connection))
3069 return connection->bus_unique_name;
3073 * g_dbus_connection_get_peer_credentials:
3074 * @connection: a #GDBusConnection
3076 * Gets the credentials of the authenticated peer. This will always
3077 * return %NULL unless @connection acted as a server
3078 * (e.g. %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER was passed)
3079 * when set up and the client passed credentials as part of the
3080 * authentication process.
3082 * In a message bus setup, the message bus is always the server and
3083 * each application is a client. So this method will always return
3084 * %NULL for message bus clients.
3086 * Returns: (transfer none) (nullable): a #GCredentials or %NULL if not
3087 * available. Do not free this object, it is owned by @connection.
3092 g_dbus_connection_get_peer_credentials (GDBusConnection *connection)
3094 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
3096 /* do not use g_return_val_if_fail(), we want the memory barrier */
3097 if (!check_initialized (connection))
3100 return connection->credentials;
3103 /* ---------------------------------------------------------------------------------------------------- */
3105 static guint _global_filter_id = 1; /* (atomic) */
3108 * g_dbus_connection_add_filter:
3109 * @connection: a #GDBusConnection
3110 * @filter_function: a filter function
3111 * @user_data: user data to pass to @filter_function
3112 * @user_data_free_func: function to free @user_data with when filter
3113 * is removed or %NULL
3115 * Adds a message filter. Filters are handlers that are run on all
3116 * incoming and outgoing messages, prior to standard dispatch. Filters
3117 * are run in the order that they were added. The same handler can be
3118 * added as a filter more than once, in which case it will be run more
3119 * than once. Filters added during a filter callback won't be run on
3120 * the message being processed. Filter functions are allowed to modify
3121 * and even drop messages.
3123 * Note that filters are run in a dedicated message handling thread so
3124 * they can't block and, generally, can't do anything but signal a
3125 * worker thread. Also note that filters are rarely needed - use API
3126 * such as g_dbus_connection_send_message_with_reply(),
3127 * g_dbus_connection_signal_subscribe() or g_dbus_connection_call() instead.
3129 * If a filter consumes an incoming message the message is not
3130 * dispatched anywhere else - not even the standard dispatch machinery
3131 * (that API such as g_dbus_connection_signal_subscribe() and
3132 * g_dbus_connection_send_message_with_reply() relies on) will see the
3133 * message. Similarly, if a filter consumes an outgoing message, the
3134 * message will not be sent to the other peer.
3136 * If @user_data_free_func is non-%NULL, it will be called (in the
3137 * thread-default main context of the thread you are calling this
3138 * method from) at some point after @user_data is no longer
3139 * needed. (It is not guaranteed to be called synchronously when the
3140 * filter is removed, and may be called after @connection has been
3143 * Returns: a filter identifier that can be used with
3144 * g_dbus_connection_remove_filter()
3149 g_dbus_connection_add_filter (GDBusConnection *connection,
3150 GDBusMessageFilterFunction filter_function,
3152 GDestroyNotify user_data_free_func)
3156 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
3157 g_return_val_if_fail (filter_function != NULL, 0);
3158 g_return_val_if_fail (check_initialized (connection), 0);
3160 CONNECTION_LOCK (connection);
3161 data = g_new0 (FilterData, 1);
3162 data->id = (guint) g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */
3163 data->ref_count = 1;
3164 data->filter_function = filter_function;
3165 data->user_data = user_data;
3166 data->user_data_free_func = user_data_free_func;
3167 data->context = g_main_context_ref_thread_default ();
3168 g_ptr_array_add (connection->filters, data);
3169 CONNECTION_UNLOCK (connection);
3174 /* only called from finalize(), removes all filters */
3176 purge_all_filters (GDBusConnection *connection)
3180 for (n = 0; n < connection->filters->len; n++)
3181 filter_data_destroy (connection->filters->pdata[n], FALSE);
3185 * g_dbus_connection_remove_filter:
3186 * @connection: a #GDBusConnection
3187 * @filter_id: an identifier obtained from g_dbus_connection_add_filter()
3191 * Note that since filters run in a different thread, there is a race
3192 * condition where it is possible that the filter will be running even
3193 * after calling g_dbus_connection_remove_filter(), so you cannot just
3194 * free data that the filter might be using. Instead, you should pass
3195 * a #GDestroyNotify to g_dbus_connection_add_filter(), which will be
3196 * called when it is guaranteed that the data is no longer needed.
3201 g_dbus_connection_remove_filter (GDBusConnection *connection,
3206 FilterData *to_destroy;
3208 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
3209 g_return_if_fail (check_initialized (connection));
3211 CONNECTION_LOCK (connection);
3214 for (n = 0; n < connection->filters->len; n++)
3216 FilterData *data = connection->filters->pdata[n];
3217 if (data->id == filter_id)
3220 g_ptr_array_remove_index (connection->filters, n);
3222 if (data->ref_count == 0)
3227 CONNECTION_UNLOCK (connection);
3229 /* do free without holding lock */
3230 if (to_destroy != NULL)
3231 filter_data_destroy (to_destroy, TRUE);
3234 g_warning ("g_dbus_connection_remove_filter: No filter found for filter_id %d", filter_id);
3238 /* ---------------------------------------------------------------------------------------------------- */
3244 gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */
3245 gchar *interface_name;
3249 GDBusSignalFlags flags;
3250 GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */
3254 signal_data_free (SignalData *signal_data)
3256 g_free (signal_data->rule);
3257 g_free (signal_data->sender);
3258 g_free (signal_data->sender_unique_name);
3259 g_free (signal_data->interface_name);
3260 g_free (signal_data->member);
3261 g_free (signal_data->object_path);
3262 g_free (signal_data->arg0);
3263 g_ptr_array_unref (signal_data->subscribers);
3264 g_free (signal_data);
3269 /* All fields are immutable after construction. */
3270 gatomicrefcount ref_count;
3271 GDBusSignalCallback callback;
3273 GDestroyNotify user_data_free_func;
3275 GMainContext *context;
3278 static SignalSubscriber *
3279 signal_subscriber_ref (SignalSubscriber *subscriber)
3281 g_atomic_ref_count_inc (&subscriber->ref_count);
3286 signal_subscriber_unref (SignalSubscriber *subscriber)
3288 if (g_atomic_ref_count_dec (&subscriber->ref_count))
3290 /* Destroy the user data. It doesn’t matter which thread
3291 * signal_subscriber_unref() is called in (or whether it’s called with a
3292 * lock held), as call_destroy_notify() always defers to the next
3293 * #GMainContext iteration. */
3294 call_destroy_notify (subscriber->context,
3295 subscriber->user_data_free_func,
3296 subscriber->user_data);
3298 g_main_context_unref (subscriber->context);
3299 g_free (subscriber);
3304 args_to_rule (const gchar *sender,
3305 const gchar *interface_name,
3306 const gchar *member,
3307 const gchar *object_path,
3309 GDBusSignalFlags flags)
3313 rule = g_string_new ("type='signal'");
3314 if (flags & G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE)
3315 g_string_prepend_c (rule, '-');
3317 g_string_append_printf (rule, ",sender='%s'", sender);
3318 if (interface_name != NULL)
3319 g_string_append_printf (rule, ",interface='%s'", interface_name);
3321 g_string_append_printf (rule, ",member='%s'", member);
3322 if (object_path != NULL)
3323 g_string_append_printf (rule, ",path='%s'", object_path);
3327 if (flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH)
3328 g_string_append_printf (rule, ",arg0path='%s'", arg0);
3329 else if (flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE)
3330 g_string_append_printf (rule, ",arg0namespace='%s'", arg0);
3332 g_string_append_printf (rule, ",arg0='%s'", arg0);
3335 return g_string_free (rule, FALSE);
3338 static guint _global_subscriber_id = 1; /* (atomic) */
3339 static guint _global_registration_id = 1; /* (atomic) */
3340 static guint _global_subtree_registration_id = 1; /* (atomic) */
3342 /* ---------------------------------------------------------------------------------------------------- */
3344 /* Called in a user thread, lock is held */
3346 add_match_rule (GDBusConnection *connection,
3347 const gchar *match_rule)
3350 GDBusMessage *message;
3352 if (match_rule[0] == '-')
3355 message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
3356 "/org/freedesktop/DBus", /* path */
3357 "org.freedesktop.DBus", /* interface */
3359 g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
3361 if (!g_dbus_connection_send_message_unlocked (connection,
3363 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
3367 g_critical ("Error while sending AddMatch() message: %s", error->message);
3368 g_error_free (error);
3370 g_object_unref (message);
3373 /* ---------------------------------------------------------------------------------------------------- */
3375 /* Called in a user thread, lock is held */
3377 remove_match_rule (GDBusConnection *connection,
3378 const gchar *match_rule)
3381 GDBusMessage *message;
3383 if (match_rule[0] == '-')
3386 message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
3387 "/org/freedesktop/DBus", /* path */
3388 "org.freedesktop.DBus", /* interface */
3390 g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule));
3393 if (!g_dbus_connection_send_message_unlocked (connection,
3395 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
3399 /* If we could get G_IO_ERROR_CLOSED here, it wouldn't be reasonable to
3400 * critical; but we're holding the lock, and our caller checked whether
3401 * we were already closed, so we can't get that error.
3403 g_critical ("Error while sending RemoveMatch() message: %s", error->message);
3404 g_error_free (error);
3406 g_object_unref (message);
3409 /* ---------------------------------------------------------------------------------------------------- */
3412 is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
3414 return g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 &&
3415 g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
3416 g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
3417 (g_strcmp0 (signal_data->member, "NameLost") == 0 ||
3418 g_strcmp0 (signal_data->member, "NameAcquired") == 0);
3421 /* ---------------------------------------------------------------------------------------------------- */
3424 * g_dbus_connection_signal_subscribe:
3425 * @connection: a #GDBusConnection
3426 * @sender: (nullable): sender name to match on (unique or well-known name)
3427 * or %NULL to listen from all senders
3428 * @interface_name: (nullable): D-Bus interface name to match on or %NULL to
3429 * match on all interfaces
3430 * @member: (nullable): D-Bus signal name to match on or %NULL to match on
3432 * @object_path: (nullable): object path to match on or %NULL to match on
3434 * @arg0: (nullable): contents of first string argument to match on or %NULL
3435 * to match on all kinds of arguments
3436 * @flags: #GDBusSignalFlags describing how arg0 is used in subscribing to the
3438 * @callback: callback to invoke when there is a signal matching the requested data
3439 * @user_data: user data to pass to @callback
3440 * @user_data_free_func: (nullable): function to free @user_data with when
3441 * subscription is removed or %NULL
3443 * Subscribes to signals on @connection and invokes @callback with a whenever
3444 * the signal is received. Note that @callback will be invoked in the
3445 * [thread-default main context][g-main-context-push-thread-default]
3446 * of the thread you are calling this method from.
3448 * If @connection is not a message bus connection, @sender must be
3451 * If @sender is a well-known name note that @callback is invoked with
3452 * the unique name for the owner of @sender, not the well-known name
3453 * as one would expect. This is because the message bus rewrites the
3454 * name. As such, to avoid certain race conditions, users should be
3455 * tracking the name owner of the well-known name and use that when
3456 * processing the received signal.
3458 * If one of %G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE or
3459 * %G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH are given, @arg0 is
3460 * interpreted as part of a namespace or path. The first argument
3461 * of a signal is matched against that part as specified by D-Bus.
3463 * If @user_data_free_func is non-%NULL, it will be called (in the
3464 * thread-default main context of the thread you are calling this
3465 * method from) at some point after @user_data is no longer
3466 * needed. (It is not guaranteed to be called synchronously when the
3467 * signal is unsubscribed from, and may be called after @connection
3468 * has been destroyed.)
3470 * As @callback is potentially invoked in a different thread from where it’s
3471 * emitted, it’s possible for this to happen after
3472 * g_dbus_connection_signal_unsubscribe() has been called in another thread.
3473 * Due to this, @user_data should have a strong reference which is freed with
3474 * @user_data_free_func, rather than pointing to data whose lifecycle is tied
3475 * to the signal subscription. For example, if a #GObject is used to store the
3476 * subscription ID from g_dbus_connection_signal_subscribe(), a strong reference
3477 * to that #GObject must be passed to @user_data, and g_object_unref() passed to
3478 * @user_data_free_func. You are responsible for breaking the resulting
3479 * reference count cycle by explicitly unsubscribing from the signal when
3480 * dropping the last external reference to the #GObject. Alternatively, a weak
3481 * reference may be used.
3483 * It is guaranteed that if you unsubscribe from a signal using
3484 * g_dbus_connection_signal_unsubscribe() from the same thread which made the
3485 * corresponding g_dbus_connection_signal_subscribe() call, @callback will not
3486 * be invoked after g_dbus_connection_signal_unsubscribe() returns.
3488 * The returned subscription identifier is an opaque value which is guaranteed
3491 * This function can never fail.
3493 * Returns: a subscription identifier that can be used with g_dbus_connection_signal_unsubscribe()
3498 g_dbus_connection_signal_subscribe (GDBusConnection *connection,
3499 const gchar *sender,
3500 const gchar *interface_name,
3501 const gchar *member,
3502 const gchar *object_path,
3504 GDBusSignalFlags flags,
3505 GDBusSignalCallback callback,
3507 GDestroyNotify user_data_free_func)
3510 SignalData *signal_data;
3511 SignalSubscriber *subscriber;
3512 GPtrArray *signal_data_array;
3513 const gchar *sender_unique_name;
3515 /* Right now we abort if AddMatch() fails since it can only fail with the bus being in
3516 * an OOM condition. We might want to change that but that would involve making
3517 * g_dbus_connection_signal_subscribe() asynchronous and having the call sites
3518 * handle that. And there's really no sensible way of handling this short of retrying
3519 * to add the match rule... and then there's the little thing that, hey, maybe there's
3520 * a reason the bus in an OOM condition.
3522 * Doable, but not really sure it's worth it...
3525 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
3526 g_return_val_if_fail (sender == NULL || (g_dbus_is_name (sender) && (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)), 0);
3527 g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), 0);
3528 g_return_val_if_fail (member == NULL || g_dbus_is_member_name (member), 0);
3529 g_return_val_if_fail (object_path == NULL || g_variant_is_object_path (object_path), 0);
3530 g_return_val_if_fail (callback != NULL, 0);
3531 g_return_val_if_fail (check_initialized (connection), 0);
3532 g_return_val_if_fail (!((flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH) && (flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE)), 0);
3533 g_return_val_if_fail (!(arg0 == NULL && (flags & (G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH | G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE))), 0);
3535 CONNECTION_LOCK (connection);
3537 /* If G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE was specified, we will end up
3538 * with a '-' character to prefix the rule (which will otherwise be
3541 * This allows us to hash the rule and do our lifecycle tracking in
3542 * the usual way, but the '-' prevents the match rule from ever
3543 * actually being send to the bus (either for add or remove).
3545 rule = args_to_rule (sender, interface_name, member, object_path, arg0, flags);
3547 if (sender != NULL && (g_dbus_is_unique_name (sender) || g_strcmp0 (sender, "org.freedesktop.DBus") == 0))
3548 sender_unique_name = sender;
3550 sender_unique_name = "";
3552 subscriber = g_new0 (SignalSubscriber, 1);
3553 subscriber->ref_count = 1;
3554 subscriber->callback = callback;
3555 subscriber->user_data = user_data;
3556 subscriber->user_data_free_func = user_data_free_func;
3557 subscriber->id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
3558 subscriber->context = g_main_context_ref_thread_default ();
3560 /* see if we've already have this rule */
3561 signal_data = g_hash_table_lookup (connection->map_rule_to_signal_data, rule);
3562 if (signal_data != NULL)
3564 g_ptr_array_add (signal_data->subscribers, subscriber);
3569 signal_data = g_new0 (SignalData, 1);
3570 signal_data->rule = rule;
3571 signal_data->sender = g_strdup (sender);
3572 signal_data->sender_unique_name = g_strdup (sender_unique_name);
3573 signal_data->interface_name = g_strdup (interface_name);
3574 signal_data->member = g_strdup (member);
3575 signal_data->object_path = g_strdup (object_path);
3576 signal_data->arg0 = g_strdup (arg0);
3577 signal_data->flags = flags;
3578 signal_data->subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
3579 g_ptr_array_add (signal_data->subscribers, subscriber);
3581 g_hash_table_insert (connection->map_rule_to_signal_data,
3585 /* Add the match rule to the bus...
3587 * Avoid adding match rules for NameLost and NameAcquired messages - the bus will
3588 * always send such messages to us.
3590 if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
3592 if (!is_signal_data_for_name_lost_or_acquired (signal_data))
3593 add_match_rule (connection, signal_data->rule);
3596 signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
3597 signal_data->sender_unique_name);
3598 if (signal_data_array == NULL)
3600 signal_data_array = g_ptr_array_new ();
3601 g_hash_table_insert (connection->map_sender_unique_name_to_signal_data_array,
3602 g_strdup (signal_data->sender_unique_name),
3605 g_ptr_array_add (signal_data_array, signal_data);
3608 g_hash_table_insert (connection->map_id_to_signal_data,
3609 GUINT_TO_POINTER (subscriber->id),
3612 CONNECTION_UNLOCK (connection);
3614 return subscriber->id;
3617 /* ---------------------------------------------------------------------------------------------------- */
3619 /* called in any thread */
3620 /* must hold lock when calling this (except if connection->finalizing is TRUE)
3621 * returns the number of removed subscribers */
3623 unsubscribe_id_internal (GDBusConnection *connection,
3624 guint subscription_id)
3626 SignalData *signal_data;
3627 GPtrArray *signal_data_array;
3629 guint n_removed = 0;
3631 signal_data = g_hash_table_lookup (connection->map_id_to_signal_data,
3632 GUINT_TO_POINTER (subscription_id));
3633 if (signal_data == NULL)
3635 /* Don't warn here, we may have thrown all subscriptions out when the connection was closed */
3639 for (n = 0; n < signal_data->subscribers->len; n++)
3641 SignalSubscriber *subscriber = signal_data->subscribers->pdata[n];
3643 if (subscriber->id != subscription_id)
3646 /* It’s OK to rearrange the array order using the ‘fast’ #GPtrArray
3647 * removal functions, since we’re going to exit the loop below anyway — we
3648 * never move on to the next element. Secondly, subscription IDs are
3649 * guaranteed to be unique. */
3650 g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data,
3651 GUINT_TO_POINTER (subscription_id)));
3653 g_ptr_array_remove_index_fast (signal_data->subscribers, n);
3655 if (signal_data->subscribers->len == 0)
3657 g_warn_if_fail (g_hash_table_remove (connection->map_rule_to_signal_data, signal_data->rule));
3659 signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
3660 signal_data->sender_unique_name);
3661 g_warn_if_fail (signal_data_array != NULL);
3662 g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data));
3664 if (signal_data_array->len == 0)
3666 g_warn_if_fail (g_hash_table_remove (connection->map_sender_unique_name_to_signal_data_array,
3667 signal_data->sender_unique_name));
3670 /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
3671 if ((connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) &&
3672 !is_signal_data_for_name_lost_or_acquired (signal_data) &&
3673 !g_dbus_connection_is_closed (connection) &&
3674 !connection->finalizing)
3676 /* The check for g_dbus_connection_is_closed() means that
3677 * sending the RemoveMatch message can't fail with
3678 * G_IO_ERROR_CLOSED, because we're holding the lock,
3679 * so on_worker_closed() can't happen between the check we just
3680 * did, and releasing the lock later.
3682 remove_match_rule (connection, signal_data->rule);
3685 signal_data_free (signal_data);
3691 g_assert_not_reached ();
3698 * g_dbus_connection_signal_unsubscribe:
3699 * @connection: a #GDBusConnection
3700 * @subscription_id: a subscription id obtained from
3701 * g_dbus_connection_signal_subscribe()
3703 * Unsubscribes from signals.
3705 * Note that there may still be D-Bus traffic to process (relating to this
3706 * signal subscription) in the current thread-default #GMainContext after this
3707 * function has returned. You should continue to iterate the #GMainContext
3708 * until the #GDestroyNotify function passed to
3709 * g_dbus_connection_signal_subscribe() is called, in order to avoid memory
3710 * leaks through callbacks queued on the #GMainContext after it’s stopped being
3712 * Alternatively, any idle source with a priority lower than %G_PRIORITY_DEFAULT
3713 * that was scheduled after unsubscription, also indicates that all resources
3714 * of this subscription are released.
3719 g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
3720 guint subscription_id)
3722 guint n_subscribers_removed G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
3724 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
3725 g_return_if_fail (check_initialized (connection));
3727 CONNECTION_LOCK (connection);
3728 n_subscribers_removed = unsubscribe_id_internal (connection, subscription_id);
3729 CONNECTION_UNLOCK (connection);
3732 g_assert (n_subscribers_removed == 0 || n_subscribers_removed == 1);
3735 /* ---------------------------------------------------------------------------------------------------- */
3739 SignalSubscriber *subscriber; /* (owned) */
3740 GDBusMessage *message;
3741 GDBusConnection *connection;
3742 const gchar *sender; /* (nullable) for peer-to-peer connections */
3744 const gchar *interface;
3745 const gchar *member;
3748 /* called on delivery thread (e.g. where g_dbus_connection_signal_subscribe() was called) with
3752 emit_signal_instance_in_idle_cb (gpointer data)
3754 SignalInstance *signal_instance = data;
3755 GVariant *parameters;
3756 gboolean has_subscription;
3758 parameters = g_dbus_message_get_body (signal_instance->message);
3759 if (parameters == NULL)
3761 parameters = g_variant_new ("()");
3762 g_variant_ref_sink (parameters);
3766 g_variant_ref_sink (parameters);
3770 g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n",
3771 signal_instance->subscriber->id,
3772 signal_instance->sender,
3773 signal_instance->path,
3774 signal_instance->interface,
3775 signal_instance->member,
3776 g_variant_print (parameters, TRUE));
3779 /* Careful here, don't do the callback if we no longer has the subscription */
3780 CONNECTION_LOCK (signal_instance->connection);
3781 has_subscription = FALSE;
3782 if (g_hash_table_lookup (signal_instance->connection->map_id_to_signal_data,
3783 GUINT_TO_POINTER (signal_instance->subscriber->id)) != NULL)
3784 has_subscription = TRUE;
3785 CONNECTION_UNLOCK (signal_instance->connection);
3787 if (has_subscription)
3788 signal_instance->subscriber->callback (signal_instance->connection,
3789 signal_instance->sender,
3790 signal_instance->path,
3791 signal_instance->interface,
3792 signal_instance->member,
3794 signal_instance->subscriber->user_data);
3796 g_variant_unref (parameters);
3802 signal_instance_free (SignalInstance *signal_instance)
3804 g_object_unref (signal_instance->message);
3805 g_object_unref (signal_instance->connection);
3806 signal_subscriber_unref (signal_instance->subscriber);
3807 g_free (signal_instance);
3811 namespace_rule_matches (const gchar *namespace,
3817 len_namespace = strlen (namespace);
3818 len_name = strlen (name);
3820 if (len_name < len_namespace)
3823 if (memcmp (namespace, name, len_namespace) != 0)
3826 return len_namespace == len_name || name[len_namespace] == '.';
3830 path_rule_matches (const gchar *path_a,
3831 const gchar *path_b)
3835 len_a = strlen (path_a);
3836 len_b = strlen (path_b);
3838 if (len_a < len_b && (len_a == 0 || path_a[len_a - 1] != '/'))
3841 if (len_b < len_a && (len_b == 0 || path_b[len_b - 1] != '/'))
3844 return memcmp (path_a, path_b, MIN (len_a, len_b)) == 0;
3847 /* called in GDBusWorker thread WITH lock held
3849 * @sender is (nullable) for peer-to-peer connections */
3851 schedule_callbacks (GDBusConnection *connection,
3852 GPtrArray *signal_data_array,
3853 GDBusMessage *message,
3854 const gchar *sender)
3857 const gchar *interface;
3858 const gchar *member;
3867 interface = g_dbus_message_get_interface (message);
3868 member = g_dbus_message_get_member (message);
3869 path = g_dbus_message_get_path (message);
3870 arg0 = g_dbus_message_get_arg0 (message);
3873 g_print ("In schedule_callbacks:\n"
3875 " interface = '%s'\n"
3886 /* TODO: if this is slow, then we can change signal_data_array into
3887 * map_object_path_to_signal_data_array or something.
3889 for (n = 0; n < signal_data_array->len; n++)
3891 SignalData *signal_data = signal_data_array->pdata[n];
3893 if (signal_data->interface_name != NULL && g_strcmp0 (signal_data->interface_name, interface) != 0)
3896 if (signal_data->member != NULL && g_strcmp0 (signal_data->member, member) != 0)
3899 if (signal_data->object_path != NULL && g_strcmp0 (signal_data->object_path, path) != 0)
3902 if (signal_data->arg0 != NULL)
3907 if (signal_data->flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE)
3909 if (!namespace_rule_matches (signal_data->arg0, arg0))
3912 else if (signal_data->flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH)
3914 if (!path_rule_matches (signal_data->arg0, arg0))
3917 else if (!g_str_equal (signal_data->arg0, arg0))
3921 for (m = 0; m < signal_data->subscribers->len; m++)
3923 SignalSubscriber *subscriber = signal_data->subscribers->pdata[m];
3924 GSource *idle_source;
3925 SignalInstance *signal_instance;
3927 signal_instance = g_new0 (SignalInstance, 1);
3928 signal_instance->subscriber = signal_subscriber_ref (subscriber);
3929 signal_instance->message = g_object_ref (message);
3930 signal_instance->connection = g_object_ref (connection);
3931 signal_instance->sender = sender;
3932 signal_instance->path = path;
3933 signal_instance->interface = interface;
3934 signal_instance->member = member;
3936 idle_source = g_idle_source_new ();
3937 g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
3938 g_source_set_callback (idle_source,
3939 emit_signal_instance_in_idle_cb,
3941 (GDestroyNotify) signal_instance_free);
3942 g_source_set_static_name (idle_source, "[gio] emit_signal_instance_in_idle_cb");
3943 g_source_attach (idle_source, subscriber->context);
3944 g_source_unref (idle_source);
3949 /* called in GDBusWorker thread with lock held */
3951 distribute_signals (GDBusConnection *connection,
3952 GDBusMessage *message)
3954 GPtrArray *signal_data_array;
3955 const gchar *sender;
3957 sender = g_dbus_message_get_sender (message);
3959 if (G_UNLIKELY (_g_dbus_debug_signal ()))
3961 _g_dbus_debug_print_lock ();
3962 g_print ("========================================================================\n"
3963 "GDBus-debug:Signal:\n"
3964 " <<<< RECEIVED SIGNAL %s.%s\n"
3966 " sent by name %s\n",
3967 g_dbus_message_get_interface (message),
3968 g_dbus_message_get_member (message),
3969 g_dbus_message_get_path (message),
3970 sender != NULL ? sender : "(none)");
3971 _g_dbus_debug_print_unlock ();
3974 /* collect subscribers that match on sender */
3977 signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, sender);
3978 if (signal_data_array != NULL)
3979 schedule_callbacks (connection, signal_data_array, message, sender);
3982 /* collect subscribers not matching on sender */
3983 signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, "");
3984 if (signal_data_array != NULL)
3985 schedule_callbacks (connection, signal_data_array, message, sender);
3988 /* ---------------------------------------------------------------------------------------------------- */
3990 /* only called from finalize(), removes all subscriptions */
3992 purge_all_signal_subscriptions (GDBusConnection *connection)
3994 GHashTableIter iter;
3999 ids = g_array_new (FALSE, FALSE, sizeof (guint));
4000 g_hash_table_iter_init (&iter, connection->map_id_to_signal_data);
4001 while (g_hash_table_iter_next (&iter, &key, NULL))
4003 guint subscription_id = GPOINTER_TO_UINT (key);
4004 g_array_append_val (ids, subscription_id);
4007 for (n = 0; n < ids->len; n++)
4009 guint subscription_id = g_array_index (ids, guint, n);
4010 unsubscribe_id_internal (connection, subscription_id);
4012 g_array_free (ids, TRUE);
4015 /* ---------------------------------------------------------------------------------------------------- */
4017 static GDBusInterfaceVTable *
4018 _g_dbus_interface_vtable_copy (const GDBusInterfaceVTable *vtable)
4020 /* Don't waste memory by copying padding - remember to update this
4021 * when changing struct _GDBusInterfaceVTable in gdbusconnection.h
4023 return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
4027 _g_dbus_interface_vtable_free (GDBusInterfaceVTable *vtable)
4032 /* ---------------------------------------------------------------------------------------------------- */
4034 static GDBusSubtreeVTable *
4035 _g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable *vtable)
4037 /* Don't waste memory by copying padding - remember to update this
4038 * when changing struct _GDBusSubtreeVTable in gdbusconnection.h
4040 return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
4044 _g_dbus_subtree_vtable_free (GDBusSubtreeVTable *vtable)
4049 /* ---------------------------------------------------------------------------------------------------- */
4051 struct ExportedObject
4054 GDBusConnection *connection;
4056 /* maps gchar* -> ExportedInterface* */
4057 GHashTable *map_if_name_to_ei;
4060 /* only called with lock held */
4062 exported_object_free (ExportedObject *eo)
4064 g_free (eo->object_path);
4065 g_hash_table_unref (eo->map_if_name_to_ei);
4073 gint refcount; /* (atomic) */
4076 gchar *interface_name; /* (owned) */
4077 GDBusInterfaceVTable *vtable; /* (owned) */
4078 GDBusInterfaceInfo *interface_info; /* (owned) */
4080 GMainContext *context; /* (owned) */
4082 GDestroyNotify user_data_free_func;
4083 } ExportedInterface;
4085 static ExportedInterface *
4086 exported_interface_ref (ExportedInterface *ei)
4088 g_atomic_int_inc (&ei->refcount);
4093 /* May be called with lock held */
4095 exported_interface_unref (ExportedInterface *ei)
4097 if (!g_atomic_int_dec_and_test (&ei->refcount))
4100 g_dbus_interface_info_cache_release (ei->interface_info);
4101 g_dbus_interface_info_unref ((GDBusInterfaceInfo *) ei->interface_info);
4103 /* All uses of ei->vtable from callbacks scheduled in idle functions must
4104 * have completed by this call_destroy_notify() call, as language bindings
4105 * may destroy function closures in this callback. */
4106 call_destroy_notify (ei->context,
4107 ei->user_data_free_func,
4110 g_main_context_unref (ei->context);
4112 g_free (ei->interface_name);
4113 _g_dbus_interface_vtable_free (ei->vtable);
4117 struct ExportedSubtree
4119 gint refcount; /* (atomic) */
4122 gchar *object_path; /* (owned) */
4123 GDBusConnection *connection; /* (unowned) */
4124 GDBusSubtreeVTable *vtable; /* (owned) */
4125 GDBusSubtreeFlags flags;
4127 GMainContext *context; /* (owned) */
4129 GDestroyNotify user_data_free_func;
4132 static ExportedSubtree *
4133 exported_subtree_ref (ExportedSubtree *es)
4135 g_atomic_int_inc (&es->refcount);
4140 /* May be called with lock held */
4142 exported_subtree_unref (ExportedSubtree *es)
4144 if (!g_atomic_int_dec_and_test (&es->refcount))
4147 /* All uses of es->vtable from callbacks scheduled in idle functions must
4148 * have completed by this call_destroy_notify() call, as language bindings
4149 * may destroy function closures in this callback. */
4150 call_destroy_notify (es->context,
4151 es->user_data_free_func,
4154 g_main_context_unref (es->context);
4156 _g_dbus_subtree_vtable_free (es->vtable);
4157 g_free (es->object_path);
4161 /* ---------------------------------------------------------------------------------------------------- */
4163 /* Convenience function to check if @registration_id (if not zero) or
4164 * @subtree_registration_id (if not zero) has been unregistered. If
4165 * so, returns %TRUE.
4167 * If not, sets @out_ei and/or @out_es to a strong reference to the relevant
4168 * #ExportedInterface/#ExportedSubtree and returns %FALSE.
4170 * May be called by any thread. Caller must *not* hold lock.
4173 has_object_been_unregistered (GDBusConnection *connection,
4174 guint registration_id,
4175 ExportedInterface **out_ei,
4176 guint subtree_registration_id,
4177 ExportedSubtree **out_es)
4180 ExportedInterface *ei = NULL;
4183 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
4187 CONNECTION_LOCK (connection);
4189 if (registration_id != 0)
4191 ei = g_hash_table_lookup (connection->map_id_to_ei, GUINT_TO_POINTER (registration_id));
4194 else if (out_ei != NULL)
4195 *out_ei = exported_interface_ref (ei);
4197 if (subtree_registration_id != 0)
4199 es = g_hash_table_lookup (connection->map_id_to_es, GUINT_TO_POINTER (subtree_registration_id));
4202 else if (out_es != NULL)
4203 *out_es = exported_subtree_ref (es);
4206 CONNECTION_UNLOCK (connection);
4211 /* ---------------------------------------------------------------------------------------------------- */
4215 GDBusConnection *connection;
4216 GDBusMessage *message;
4218 const gchar *property_name;
4219 const GDBusInterfaceVTable *vtable;
4220 GDBusInterfaceInfo *interface_info;
4221 const GDBusPropertyInfo *property_info;
4222 guint registration_id;
4223 guint subtree_registration_id;
4227 property_data_free (PropertyData *data)
4229 g_object_unref (data->connection);
4230 g_object_unref (data->message);
4234 /* called in thread where object was registered - no locks held */
4236 invoke_get_property_in_idle_cb (gpointer _data)
4238 PropertyData *data = _data;
4241 GDBusMessage *reply;
4242 ExportedInterface *ei = NULL;
4243 ExportedSubtree *es = NULL;
4245 if (has_object_been_unregistered (data->connection,
4246 data->registration_id,
4248 data->subtree_registration_id,
4251 reply = g_dbus_message_new_method_error (data->message,
4252 "org.freedesktop.DBus.Error.UnknownMethod",
4253 _("No such interface “org.freedesktop.DBus.Properties” on object at path %s"),
4254 g_dbus_message_get_path (data->message));
4255 g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4256 g_object_unref (reply);
4261 value = data->vtable->get_property (data->connection,
4262 g_dbus_message_get_sender (data->message),
4263 g_dbus_message_get_path (data->message),
4264 data->interface_info->name,
4265 data->property_name,
4272 g_assert_no_error (error);
4274 g_variant_take_ref (value);
4275 reply = g_dbus_message_new_method_reply (data->message);
4276 g_dbus_message_set_body (reply, g_variant_new ("(v)", value));
4277 g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4278 g_variant_unref (value);
4279 g_object_unref (reply);
4283 gchar *dbus_error_name;
4284 g_assert (error != NULL);
4285 dbus_error_name = g_dbus_error_encode_gerror (error);
4286 reply = g_dbus_message_new_method_error_literal (data->message,
4289 g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4290 g_free (dbus_error_name);
4291 g_error_free (error);
4292 g_object_unref (reply);
4296 g_clear_pointer (&ei, exported_interface_unref);
4297 g_clear_pointer (&es, exported_subtree_unref);
4302 /* called in thread where object was registered - no locks held */
4304 invoke_set_property_in_idle_cb (gpointer _data)
4306 PropertyData *data = _data;
4308 GDBusMessage *reply;
4314 g_variant_get (g_dbus_message_get_body (data->message),
4320 if (!data->vtable->set_property (data->connection,
4321 g_dbus_message_get_sender (data->message),
4322 g_dbus_message_get_path (data->message),
4323 data->interface_info->name,
4324 data->property_name,
4329 gchar *dbus_error_name;
4330 g_assert (error != NULL);
4331 dbus_error_name = g_dbus_error_encode_gerror (error);
4332 reply = g_dbus_message_new_method_error_literal (data->message,
4335 g_free (dbus_error_name);
4336 g_error_free (error);
4340 reply = g_dbus_message_new_method_reply (data->message);
4343 g_assert (reply != NULL);
4344 g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4345 g_object_unref (reply);
4346 g_variant_unref (value);
4351 /* called in any thread with connection's lock held */
4353 validate_and_maybe_schedule_property_getset (GDBusConnection *connection,
4354 GDBusMessage *message,
4355 guint registration_id,
4356 guint subtree_registration_id,
4358 GDBusInterfaceInfo *interface_info,
4359 const GDBusInterfaceVTable *vtable,
4360 GMainContext *main_context,
4364 const char *interface_name;
4365 const char *property_name;
4366 const GDBusPropertyInfo *property_info;
4367 GSource *idle_source;
4368 PropertyData *property_data;
4369 GDBusMessage *reply;
4374 g_variant_get (g_dbus_message_get_body (message),
4379 g_variant_get (g_dbus_message_get_body (message),
4388 /* Check that the property exists - if not fail with org.freedesktop.DBus.Error.InvalidArgs
4390 property_info = NULL;
4392 /* TODO: the cost of this is O(n) - it might be worth caching the result */
4393 property_info = g_dbus_interface_info_lookup_property (interface_info, property_name);
4394 if (property_info == NULL)
4396 reply = g_dbus_message_new_method_error (message,
4397 "org.freedesktop.DBus.Error.InvalidArgs",
4398 _("No such property “%s”"),
4400 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4401 g_object_unref (reply);
4406 if (is_get && !(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE))
4408 reply = g_dbus_message_new_method_error (message,
4409 "org.freedesktop.DBus.Error.InvalidArgs",
4410 _("Property “%s” is not readable"),
4412 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4413 g_object_unref (reply);
4417 else if (!is_get && !(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
4419 reply = g_dbus_message_new_method_error (message,
4420 "org.freedesktop.DBus.Error.InvalidArgs",
4421 _("Property “%s” is not writable"),
4423 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4424 g_object_unref (reply);
4433 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the type
4434 * of the given value is wrong
4436 g_variant_get_child (g_dbus_message_get_body (message), 2, "v", &value);
4437 if (g_strcmp0 (g_variant_get_type_string (value), property_info->signature) != 0)
4439 reply = g_dbus_message_new_method_error (message,
4440 "org.freedesktop.DBus.Error.InvalidArgs",
4441 _("Error setting property “%s”: Expected type “%s” but got “%s”"),
4442 property_name, property_info->signature,
4443 g_variant_get_type_string (value));
4444 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4445 g_variant_unref (value);
4446 g_object_unref (reply);
4451 g_variant_unref (value);
4454 /* If the vtable pointer for get_property() resp. set_property() is
4455 * NULL then dispatch the call via the method_call() handler.
4459 if (vtable->get_property == NULL)
4461 schedule_method_call (connection, message, registration_id, subtree_registration_id,
4462 interface_info, NULL, property_info, g_dbus_message_get_body (message),
4463 vtable, main_context, user_data);
4470 if (vtable->set_property == NULL)
4472 schedule_method_call (connection, message, registration_id, subtree_registration_id,
4473 interface_info, NULL, property_info, g_dbus_message_get_body (message),
4474 vtable, main_context, user_data);
4480 /* ok, got the property info - call user code in an idle handler */
4481 property_data = g_new0 (PropertyData, 1);
4482 property_data->connection = g_object_ref (connection);
4483 property_data->message = g_object_ref (message);
4484 property_data->user_data = user_data;
4485 property_data->property_name = property_name;
4486 property_data->vtable = vtable;
4487 property_data->interface_info = interface_info;
4488 property_data->property_info = property_info;
4489 property_data->registration_id = registration_id;
4490 property_data->subtree_registration_id = subtree_registration_id;
4492 idle_source = g_idle_source_new ();
4493 g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
4494 g_source_set_callback (idle_source,
4495 is_get ? invoke_get_property_in_idle_cb : invoke_set_property_in_idle_cb,
4497 (GDestroyNotify) property_data_free);
4499 g_source_set_static_name (idle_source, "[gio] invoke_get_property_in_idle_cb");
4501 g_source_set_static_name (idle_source, "[gio] invoke_set_property_in_idle_cb");
4502 g_source_attach (idle_source, main_context);
4503 g_source_unref (idle_source);
4511 /* called in GDBusWorker thread with connection's lock held */
4513 handle_getset_property (GDBusConnection *connection,
4515 GDBusMessage *message,
4518 ExportedInterface *ei;
4520 const char *interface_name;
4521 const char *property_name;
4526 g_variant_get (g_dbus_message_get_body (message),
4531 g_variant_get (g_dbus_message_get_body (message),
4537 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
4538 * no such interface registered
4540 ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
4543 GDBusMessage *reply;
4544 reply = g_dbus_message_new_method_error (message,
4545 "org.freedesktop.DBus.Error.InvalidArgs",
4546 _("No such interface “%s”"),
4548 g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4549 g_object_unref (reply);
4554 handled = validate_and_maybe_schedule_property_getset (eo->connection,
4567 /* ---------------------------------------------------------------------------------------------------- */
4571 GDBusConnection *connection;
4572 GDBusMessage *message;
4574 const GDBusInterfaceVTable *vtable;
4575 GDBusInterfaceInfo *interface_info;
4576 guint registration_id;
4577 guint subtree_registration_id;
4578 } PropertyGetAllData;
4581 property_get_all_data_free (PropertyData *data)
4583 g_object_unref (data->connection);
4584 g_object_unref (data->message);
4588 /* called in thread where object was registered - no locks held */
4590 invoke_get_all_properties_in_idle_cb (gpointer _data)
4592 PropertyGetAllData *data = _data;
4593 GVariantBuilder builder;
4594 GDBusMessage *reply;
4596 ExportedInterface *ei = NULL;
4597 ExportedSubtree *es = NULL;
4599 if (has_object_been_unregistered (data->connection,
4600 data->registration_id,
4602 data->subtree_registration_id,
4605 reply = g_dbus_message_new_method_error (data->message,
4606 "org.freedesktop.DBus.Error.UnknownMethod",
4607 _("No such interface “org.freedesktop.DBus.Properties” on object at path %s"),
4608 g_dbus_message_get_path (data->message));
4609 g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4610 g_object_unref (reply);
4614 /* TODO: Right now we never fail this call - we just omit values if
4615 * a get_property() call is failing.
4617 * We could fail the whole call if just a single get_property() call
4618 * returns an error. We need clarification in the D-Bus spec about this.
4620 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a{sv})"));
4621 g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
4622 for (n = 0; data->interface_info->properties != NULL && data->interface_info->properties[n] != NULL; n++)
4624 const GDBusPropertyInfo *property_info = data->interface_info->properties[n];
4627 if (!(property_info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE))
4630 value = data->vtable->get_property (data->connection,
4631 g_dbus_message_get_sender (data->message),
4632 g_dbus_message_get_path (data->message),
4633 data->interface_info->name,
4634 property_info->name,
4641 g_variant_take_ref (value);
4642 g_variant_builder_add (&builder,
4644 property_info->name,
4646 g_variant_unref (value);
4648 g_variant_builder_close (&builder);
4650 reply = g_dbus_message_new_method_reply (data->message);
4651 g_dbus_message_set_body (reply, g_variant_builder_end (&builder));
4652 g_dbus_connection_send_message (data->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4653 g_object_unref (reply);
4656 g_clear_pointer (&ei, exported_interface_unref);
4657 g_clear_pointer (&es, exported_subtree_unref);
4663 interface_has_readable_properties (GDBusInterfaceInfo *interface_info)
4667 if (!interface_info->properties)
4670 for (i = 0; interface_info->properties[i]; i++)
4671 if (interface_info->properties[i]->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
4677 /* called in any thread with connection's lock held */
4679 validate_and_maybe_schedule_property_get_all (GDBusConnection *connection,
4680 GDBusMessage *message,
4681 guint registration_id,
4682 guint subtree_registration_id,
4683 GDBusInterfaceInfo *interface_info,
4684 const GDBusInterfaceVTable *vtable,
4685 GMainContext *main_context,
4689 GSource *idle_source;
4690 PropertyGetAllData *property_get_all_data;
4697 /* If the vtable pointer for get_property() is NULL but we have a
4698 * non-zero number of readable properties, then dispatch the call via
4699 * the method_call() handler.
4701 if (vtable->get_property == NULL && interface_has_readable_properties (interface_info))
4703 schedule_method_call (connection, message, registration_id, subtree_registration_id,
4704 interface_info, NULL, NULL, g_dbus_message_get_body (message),
4705 vtable, main_context, user_data);
4710 /* ok, got the property info - call user in an idle handler */
4711 property_get_all_data = g_new0 (PropertyGetAllData, 1);
4712 property_get_all_data->connection = g_object_ref (connection);
4713 property_get_all_data->message = g_object_ref (message);
4714 property_get_all_data->user_data = user_data;
4715 property_get_all_data->vtable = vtable;
4716 property_get_all_data->interface_info = interface_info;
4717 property_get_all_data->registration_id = registration_id;
4718 property_get_all_data->subtree_registration_id = subtree_registration_id;
4720 idle_source = g_idle_source_new ();
4721 g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
4722 g_source_set_callback (idle_source,
4723 invoke_get_all_properties_in_idle_cb,
4724 property_get_all_data,
4725 (GDestroyNotify) property_get_all_data_free);
4726 g_source_set_static_name (idle_source, "[gio] invoke_get_all_properties_in_idle_cb");
4727 g_source_attach (idle_source, main_context);
4728 g_source_unref (idle_source);
4736 /* called in GDBusWorker thread with connection's lock held */
4738 handle_get_all_properties (GDBusConnection *connection,
4740 GDBusMessage *message)
4742 ExportedInterface *ei;
4744 const char *interface_name;
4748 g_variant_get (g_dbus_message_get_body (message),
4752 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
4753 * no such interface registered
4755 ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
4758 GDBusMessage *reply;
4759 reply = g_dbus_message_new_method_error (message,
4760 "org.freedesktop.DBus.Error.InvalidArgs",
4761 _("No such interface “%s”"),
4763 g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4764 g_object_unref (reply);
4769 handled = validate_and_maybe_schedule_property_get_all (eo->connection,
4781 /* ---------------------------------------------------------------------------------------------------- */
4783 static const gchar introspect_header[] =
4784 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
4785 " \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
4786 "<!-- GDBus " PACKAGE_VERSION " -->\n"
4789 static const gchar introspect_tail[] =
4792 static const gchar introspect_properties_interface[] =
4793 " <interface name=\"org.freedesktop.DBus.Properties\">\n"
4794 " <method name=\"Get\">\n"
4795 " <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
4796 " <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
4797 " <arg type=\"v\" name=\"value\" direction=\"out\"/>\n"
4799 " <method name=\"GetAll\">\n"
4800 " <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
4801 " <arg type=\"a{sv}\" name=\"properties\" direction=\"out\"/>\n"
4803 " <method name=\"Set\">\n"
4804 " <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
4805 " <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
4806 " <arg type=\"v\" name=\"value\" direction=\"in\"/>\n"
4808 " <signal name=\"PropertiesChanged\">\n"
4809 " <arg type=\"s\" name=\"interface_name\"/>\n"
4810 " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"
4811 " <arg type=\"as\" name=\"invalidated_properties\"/>\n"
4815 static const gchar introspect_introspectable_interface[] =
4816 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
4817 " <method name=\"Introspect\">\n"
4818 " <arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
4821 " <interface name=\"org.freedesktop.DBus.Peer\">\n"
4822 " <method name=\"Ping\"/>\n"
4823 " <method name=\"GetMachineId\">\n"
4824 " <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n"
4829 introspect_append_header (GString *s)
4831 g_string_append (s, introspect_header);
4835 maybe_add_path (const gchar *path, gsize path_len, const gchar *object_path, GHashTable *set)
4837 if (g_str_has_prefix (object_path, path) && strlen (object_path) > path_len && object_path[path_len-1] == '/')
4843 begin = object_path + path_len;
4844 end = strchr (begin, '/');
4846 s = g_strndup (begin, end - begin);
4848 s = g_strdup (begin);
4850 if (!g_hash_table_contains (set, s))
4851 g_hash_table_add (set, s);
4857 /* TODO: we want a nicer public interface for this */
4858 /* called in any thread with connection's lock held */
4860 g_dbus_connection_list_registered_unlocked (GDBusConnection *connection,
4865 GHashTableIter hash_iter;
4866 const gchar *object_path;
4872 CONNECTION_ENSURE_LOCK (connection);
4874 path_len = strlen (path);
4878 set = g_hash_table_new (g_str_hash, g_str_equal);
4880 g_hash_table_iter_init (&hash_iter, connection->map_object_path_to_eo);
4881 while (g_hash_table_iter_next (&hash_iter, (gpointer) &object_path, NULL))
4882 maybe_add_path (path, path_len, object_path, set);
4884 g_hash_table_iter_init (&hash_iter, connection->map_object_path_to_es);
4885 while (g_hash_table_iter_next (&hash_iter, (gpointer) &object_path, NULL))
4886 maybe_add_path (path, path_len, object_path, set);
4888 p = g_ptr_array_new ();
4889 keys = g_hash_table_get_keys (set);
4890 for (l = keys; l != NULL; l = l->next)
4891 g_ptr_array_add (p, l->data);
4892 g_hash_table_unref (set);
4895 g_ptr_array_add (p, NULL);
4896 ret = (gchar **) g_ptr_array_free (p, FALSE);
4900 /* called in any thread with connection's lock not held */
4902 g_dbus_connection_list_registered (GDBusConnection *connection,
4906 CONNECTION_LOCK (connection);
4907 ret = g_dbus_connection_list_registered_unlocked (connection, path);
4908 CONNECTION_UNLOCK (connection);
4912 /* called in GDBusWorker thread with connection's lock held */
4914 handle_introspect (GDBusConnection *connection,
4916 GDBusMessage *message)
4920 GDBusMessage *reply;
4921 GHashTableIter hash_iter;
4922 ExportedInterface *ei;
4925 /* first the header with the standard interfaces */
4926 s = g_string_sized_new (sizeof (introspect_header) +
4927 sizeof (introspect_properties_interface) +
4928 sizeof (introspect_introspectable_interface) +
4929 sizeof (introspect_tail));
4930 introspect_append_header (s);
4931 if (!g_hash_table_lookup (eo->map_if_name_to_ei,
4932 "org.freedesktop.DBus.Properties"))
4933 g_string_append (s, introspect_properties_interface);
4935 if (!g_hash_table_lookup (eo->map_if_name_to_ei,
4936 "org.freedesktop.DBus.Introspectable"))
4937 g_string_append (s, introspect_introspectable_interface);
4939 /* then include the registered interfaces */
4940 g_hash_table_iter_init (&hash_iter, eo->map_if_name_to_ei);
4941 while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &ei))
4942 g_dbus_interface_info_generate_xml (ei->interface_info, 2, s);
4944 /* finally include nodes registered below us */
4945 registered = g_dbus_connection_list_registered_unlocked (connection, eo->object_path);
4946 for (n = 0; registered != NULL && registered[n] != NULL; n++)
4947 g_string_append_printf (s, " <node name=\"%s\"/>\n", registered[n]);
4948 g_strfreev (registered);
4949 g_string_append (s, introspect_tail);
4951 reply = g_dbus_message_new_method_reply (message);
4952 g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
4953 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4954 g_object_unref (reply);
4955 g_string_free (s, TRUE);
4960 /* called in thread where object was registered - no locks held */
4962 call_in_idle_cb (gpointer user_data)
4964 GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data);
4965 GDBusInterfaceVTable *vtable;
4966 guint registration_id;
4967 guint subtree_registration_id;
4968 ExportedInterface *ei = NULL;
4969 ExportedSubtree *es = NULL;
4971 registration_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (invocation), "g-dbus-registration-id"));
4972 subtree_registration_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (invocation), "g-dbus-subtree-registration-id"));
4974 if (has_object_been_unregistered (g_dbus_method_invocation_get_connection (invocation),
4977 subtree_registration_id,
4980 GDBusMessage *reply;
4981 reply = g_dbus_message_new_method_error (g_dbus_method_invocation_get_message (invocation),
4982 "org.freedesktop.DBus.Error.UnknownMethod",
4983 _("No such interface “%s” on object at path %s"),
4984 g_dbus_method_invocation_get_interface_name (invocation),
4985 g_dbus_method_invocation_get_object_path (invocation));
4986 g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
4987 g_object_unref (reply);
4991 vtable = g_object_get_data (G_OBJECT (invocation), "g-dbus-interface-vtable");
4992 g_assert (vtable != NULL && vtable->method_call != NULL);
4994 vtable->method_call (g_dbus_method_invocation_get_connection (invocation),
4995 g_dbus_method_invocation_get_sender (invocation),
4996 g_dbus_method_invocation_get_object_path (invocation),
4997 g_dbus_method_invocation_get_interface_name (invocation),
4998 g_dbus_method_invocation_get_method_name (invocation),
4999 g_dbus_method_invocation_get_parameters (invocation),
5000 g_object_ref (invocation),
5001 g_dbus_method_invocation_get_user_data (invocation));
5004 g_clear_pointer (&ei, exported_interface_unref);
5005 g_clear_pointer (&es, exported_subtree_unref);
5010 /* called in GDBusWorker thread with connection's lock held */
5012 schedule_method_call (GDBusConnection *connection,
5013 GDBusMessage *message,
5014 guint registration_id,
5015 guint subtree_registration_id,
5016 const GDBusInterfaceInfo *interface_info,
5017 const GDBusMethodInfo *method_info,
5018 const GDBusPropertyInfo *property_info,
5019 GVariant *parameters,
5020 const GDBusInterfaceVTable *vtable,
5021 GMainContext *main_context,
5024 GDBusMethodInvocation *invocation;
5025 GSource *idle_source;
5027 invocation = _g_dbus_method_invocation_new (g_dbus_message_get_sender (message),
5028 g_dbus_message_get_path (message),
5029 g_dbus_message_get_interface (message),
5030 g_dbus_message_get_member (message),
5038 /* TODO: would be nicer with a real MethodData like we already
5039 * have PropertyData and PropertyGetAllData... */
5040 g_object_set_data (G_OBJECT (invocation), "g-dbus-interface-vtable", (gpointer) vtable);
5041 g_object_set_data (G_OBJECT (invocation), "g-dbus-registration-id", GUINT_TO_POINTER (registration_id));
5042 g_object_set_data (G_OBJECT (invocation), "g-dbus-subtree-registration-id", GUINT_TO_POINTER (subtree_registration_id));
5044 idle_source = g_idle_source_new ();
5045 g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
5046 g_source_set_callback (idle_source,
5050 g_source_set_static_name (idle_source, "[gio, " __FILE__ "] call_in_idle_cb");
5051 g_source_attach (idle_source, main_context);
5052 g_source_unref (idle_source);
5055 /* called in GDBusWorker thread with connection's lock held */
5057 validate_and_maybe_schedule_method_call (GDBusConnection *connection,
5058 GDBusMessage *message,
5059 guint registration_id,
5060 guint subtree_registration_id,
5061 GDBusInterfaceInfo *interface_info,
5062 const GDBusInterfaceVTable *vtable,
5063 GMainContext *main_context,
5066 GDBusMethodInfo *method_info;
5067 GDBusMessage *reply;
5068 GVariant *parameters;
5070 GVariantType *in_type;
5074 /* TODO: the cost of this is O(n) - it might be worth caching the result */
5075 method_info = g_dbus_interface_info_lookup_method (interface_info, g_dbus_message_get_member (message));
5077 /* if the method doesn't exist, return the org.freedesktop.DBus.Error.UnknownMethod
5078 * error to the caller
5080 if (method_info == NULL)
5082 reply = g_dbus_message_new_method_error (message,
5083 "org.freedesktop.DBus.Error.UnknownMethod",
5084 _("No such method “%s”"),
5085 g_dbus_message_get_member (message));
5086 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
5087 g_object_unref (reply);
5092 parameters = g_dbus_message_get_body (message);
5093 if (parameters == NULL)
5095 parameters = g_variant_new ("()");
5096 g_variant_ref_sink (parameters);
5100 g_variant_ref (parameters);
5103 /* Check that the incoming args are of the right type - if they are not, return
5104 * the org.freedesktop.DBus.Error.InvalidArgs error to the caller
5106 in_type = _g_dbus_compute_complete_signature (method_info->in_args);
5107 if (!g_variant_is_of_type (parameters, in_type))
5111 type_string = g_variant_type_dup_string (in_type);
5113 reply = g_dbus_message_new_method_error (message,
5114 "org.freedesktop.DBus.Error.InvalidArgs",
5115 _("Type of message, “%s”, does not match expected type “%s”"),
5116 g_variant_get_type_string (parameters),
5118 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
5119 g_variant_type_free (in_type);
5120 g_variant_unref (parameters);
5121 g_object_unref (reply);
5122 g_free (type_string);
5126 g_variant_type_free (in_type);
5128 /* schedule the call in idle */
5129 schedule_method_call (connection, message, registration_id, subtree_registration_id,
5130 interface_info, method_info, NULL, parameters,
5131 vtable, main_context, user_data);
5132 g_variant_unref (parameters);
5139 /* ---------------------------------------------------------------------------------------------------- */
5141 /* called in GDBusWorker thread with connection's lock held */
5143 obj_message_func (GDBusConnection *connection,
5145 GDBusMessage *message,
5146 gboolean *object_found)
5148 const gchar *interface_name;
5149 const gchar *member;
5150 const gchar *signature;
5155 interface_name = g_dbus_message_get_interface (message);
5156 member = g_dbus_message_get_member (message);
5157 signature = g_dbus_message_get_signature (message);
5159 /* see if we have an interface for handling this call */
5160 if (interface_name != NULL)
5162 ExportedInterface *ei;
5163 ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_name);
5166 /* we do - invoke the handler in idle in the right thread */
5168 /* handle no vtable or handler being present */
5169 if (ei->vtable == NULL || ei->vtable->method_call == NULL)
5172 handled = validate_and_maybe_schedule_method_call (connection,
5184 *object_found = TRUE;
5188 if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
5189 g_strcmp0 (member, "Introspect") == 0 &&
5190 g_strcmp0 (signature, "") == 0)
5192 handled = handle_introspect (connection, eo, message);
5195 else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
5196 g_strcmp0 (member, "Get") == 0 &&
5197 g_strcmp0 (signature, "ss") == 0)
5199 handled = handle_getset_property (connection, eo, message, TRUE);
5202 else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
5203 g_strcmp0 (member, "Set") == 0 &&
5204 g_strcmp0 (signature, "ssv") == 0)
5206 handled = handle_getset_property (connection, eo, message, FALSE);
5209 else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0 &&
5210 g_strcmp0 (member, "GetAll") == 0 &&
5211 g_strcmp0 (signature, "s") == 0)
5213 handled = handle_get_all_properties (connection, eo, message);
5222 * g_dbus_connection_register_object:
5223 * @connection: a #GDBusConnection
5224 * @object_path: the object path to register at
5225 * @interface_info: introspection data for the interface
5226 * @vtable: (nullable): a #GDBusInterfaceVTable to call into or %NULL
5227 * @user_data: (nullable): data to pass to functions in @vtable
5228 * @user_data_free_func: function to call when the object path is unregistered
5229 * @error: return location for error or %NULL
5231 * Registers callbacks for exported objects at @object_path with the
5232 * D-Bus interface that is described in @interface_info.
5234 * Calls to functions in @vtable (and @user_data_free_func) will happen
5236 * [thread-default main context][g-main-context-push-thread-default]
5237 * of the thread you are calling this method from.
5239 * Note that all #GVariant values passed to functions in @vtable will match
5240 * the signature given in @interface_info - if a remote caller passes
5241 * incorrect values, the `org.freedesktop.DBus.Error.InvalidArgs`
5242 * is returned to the remote caller.
5244 * Additionally, if the remote caller attempts to invoke methods or
5245 * access properties not mentioned in @interface_info the
5246 * `org.freedesktop.DBus.Error.UnknownMethod` resp.
5247 * `org.freedesktop.DBus.Error.InvalidArgs` errors
5248 * are returned to the caller.
5250 * It is considered a programming error if the
5251 * #GDBusInterfaceGetPropertyFunc function in @vtable returns a
5252 * #GVariant of incorrect type.
5254 * If an existing callback is already registered at @object_path and
5255 * @interface_name, then @error is set to %G_IO_ERROR_EXISTS.
5257 * GDBus automatically implements the standard D-Bus interfaces
5258 * org.freedesktop.DBus.Properties, org.freedesktop.DBus.Introspectable
5259 * and org.freedesktop.Peer, so you don't have to implement those for the
5260 * objects you export. You can implement org.freedesktop.DBus.Properties
5261 * yourself, e.g. to handle getting and setting of properties asynchronously.
5263 * Note that the reference count on @interface_info will be
5264 * incremented by 1 (unless allocated statically, e.g. if the
5265 * reference count is -1, see g_dbus_interface_info_ref()) for as long
5266 * as the object is exported. Also note that @vtable will be copied.
5268 * See this [server][gdbus-server] for an example of how to use this method.
5270 * Returns: 0 if @error is set, otherwise a registration id (never 0)
5271 * that can be used with g_dbus_connection_unregister_object()
5276 g_dbus_connection_register_object (GDBusConnection *connection,
5277 const gchar *object_path,
5278 GDBusInterfaceInfo *interface_info,
5279 const GDBusInterfaceVTable *vtable,
5281 GDestroyNotify user_data_free_func,
5285 ExportedInterface *ei;
5288 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
5289 g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
5290 g_return_val_if_fail (interface_info != NULL, 0);
5291 g_return_val_if_fail (g_dbus_is_interface_name (interface_info->name), 0);
5292 g_return_val_if_fail (error == NULL || *error == NULL, 0);
5293 g_return_val_if_fail (check_initialized (connection), 0);
5297 CONNECTION_LOCK (connection);
5299 eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path);
5302 eo = g_new0 (ExportedObject, 1);
5303 eo->object_path = g_strdup (object_path);
5304 eo->connection = connection;
5305 eo->map_if_name_to_ei = g_hash_table_new_full (g_str_hash,
5308 (GDestroyNotify) exported_interface_unref);
5309 g_hash_table_insert (connection->map_object_path_to_eo, eo->object_path, eo);
5312 ei = g_hash_table_lookup (eo->map_if_name_to_ei, interface_info->name);
5318 _("An object is already exported for the interface %s at %s"),
5319 interface_info->name,
5324 ei = g_new0 (ExportedInterface, 1);
5326 ei->id = (guint) g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */
5328 ei->user_data = user_data;
5329 ei->user_data_free_func = user_data_free_func;
5330 ei->vtable = _g_dbus_interface_vtable_copy (vtable);
5331 ei->interface_info = g_dbus_interface_info_ref (interface_info);
5332 g_dbus_interface_info_cache_build (ei->interface_info);
5333 ei->interface_name = g_strdup (interface_info->name);
5334 ei->context = g_main_context_ref_thread_default ();
5336 g_hash_table_insert (eo->map_if_name_to_ei,
5337 (gpointer) ei->interface_name,
5339 g_hash_table_insert (connection->map_id_to_ei,
5340 GUINT_TO_POINTER (ei->id),
5346 CONNECTION_UNLOCK (connection);
5352 * g_dbus_connection_unregister_object:
5353 * @connection: a #GDBusConnection
5354 * @registration_id: a registration id obtained from
5355 * g_dbus_connection_register_object()
5357 * Unregisters an object.
5359 * Returns: %TRUE if the object was unregistered, %FALSE otherwise
5364 g_dbus_connection_unregister_object (GDBusConnection *connection,
5365 guint registration_id)
5367 ExportedInterface *ei;
5371 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
5372 g_return_val_if_fail (check_initialized (connection), FALSE);
5376 CONNECTION_LOCK (connection);
5378 ei = g_hash_table_lookup (connection->map_id_to_ei,
5379 GUINT_TO_POINTER (registration_id));
5385 g_warn_if_fail (g_hash_table_remove (connection->map_id_to_ei, GUINT_TO_POINTER (ei->id)));
5386 g_warn_if_fail (g_hash_table_remove (eo->map_if_name_to_ei, ei->interface_name));
5387 /* unregister object path if we have no more exported interfaces */
5388 if (g_hash_table_size (eo->map_if_name_to_ei) == 0)
5389 g_warn_if_fail (g_hash_table_remove (connection->map_object_path_to_eo,
5395 CONNECTION_UNLOCK (connection);
5401 GClosure *method_call_closure;
5402 GClosure *get_property_closure;
5403 GClosure *set_property_closure;
5404 } RegisterObjectData;
5406 static RegisterObjectData *
5407 register_object_data_new (GClosure *method_call_closure,
5408 GClosure *get_property_closure,
5409 GClosure *set_property_closure)
5411 RegisterObjectData *data;
5413 data = g_new0 (RegisterObjectData, 1);
5415 if (method_call_closure != NULL)
5417 data->method_call_closure = g_closure_ref (method_call_closure);
5418 g_closure_sink (method_call_closure);
5419 if (G_CLOSURE_NEEDS_MARSHAL (method_call_closure))
5420 g_closure_set_marshal (method_call_closure, g_cclosure_marshal_generic);
5423 if (get_property_closure != NULL)
5425 data->get_property_closure = g_closure_ref (get_property_closure);
5426 g_closure_sink (get_property_closure);
5427 if (G_CLOSURE_NEEDS_MARSHAL (get_property_closure))
5428 g_closure_set_marshal (get_property_closure, g_cclosure_marshal_generic);
5431 if (set_property_closure != NULL)
5433 data->set_property_closure = g_closure_ref (set_property_closure);
5434 g_closure_sink (set_property_closure);
5435 if (G_CLOSURE_NEEDS_MARSHAL (set_property_closure))
5436 g_closure_set_marshal (set_property_closure, g_cclosure_marshal_generic);
5443 register_object_free_func (gpointer user_data)
5445 RegisterObjectData *data = user_data;
5447 g_clear_pointer (&data->method_call_closure, g_closure_unref);
5448 g_clear_pointer (&data->get_property_closure, g_closure_unref);
5449 g_clear_pointer (&data->set_property_closure, g_closure_unref);
5455 register_with_closures_on_method_call (GDBusConnection *connection,
5456 const gchar *sender,
5457 const gchar *object_path,
5458 const gchar *interface_name,
5459 const gchar *method_name,
5460 GVariant *parameters,
5461 GDBusMethodInvocation *invocation,
5464 RegisterObjectData *data = user_data;
5465 GValue params[] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
5467 g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
5468 g_value_set_object (¶ms[0], connection);
5470 g_value_init (¶ms[1], G_TYPE_STRING);
5471 g_value_set_string (¶ms[1], sender);
5473 g_value_init (¶ms[2], G_TYPE_STRING);
5474 g_value_set_string (¶ms[2], object_path);
5476 g_value_init (¶ms[3], G_TYPE_STRING);
5477 g_value_set_string (¶ms[3], interface_name);
5479 g_value_init (¶ms[4], G_TYPE_STRING);
5480 g_value_set_string (¶ms[4], method_name);
5482 g_value_init (¶ms[5], G_TYPE_VARIANT);
5483 g_value_set_variant (¶ms[5], parameters);
5485 g_value_init (¶ms[6], G_TYPE_DBUS_METHOD_INVOCATION);
5486 g_value_set_object (¶ms[6], invocation);
5488 g_closure_invoke (data->method_call_closure, NULL, G_N_ELEMENTS (params), params, NULL);
5490 g_value_unset (params + 0);
5491 g_value_unset (params + 1);
5492 g_value_unset (params + 2);
5493 g_value_unset (params + 3);
5494 g_value_unset (params + 4);
5495 g_value_unset (params + 5);
5496 g_value_unset (params + 6);
5500 register_with_closures_on_get_property (GDBusConnection *connection,
5501 const gchar *sender,
5502 const gchar *object_path,
5503 const gchar *interface_name,
5504 const gchar *property_name,
5508 RegisterObjectData *data = user_data;
5509 GValue params[] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
5510 GValue result_value = G_VALUE_INIT;
5513 g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
5514 g_value_set_object (¶ms[0], connection);
5516 g_value_init (¶ms[1], G_TYPE_STRING);
5517 g_value_set_string (¶ms[1], sender);
5519 g_value_init (¶ms[2], G_TYPE_STRING);
5520 g_value_set_string (¶ms[2], object_path);
5522 g_value_init (¶ms[3], G_TYPE_STRING);
5523 g_value_set_string (¶ms[3], interface_name);
5525 g_value_init (¶ms[4], G_TYPE_STRING);
5526 g_value_set_string (¶ms[4], property_name);
5528 g_value_init (&result_value, G_TYPE_VARIANT);
5530 g_closure_invoke (data->get_property_closure, &result_value, G_N_ELEMENTS (params), params, NULL);
5532 result = g_value_get_variant (&result_value);
5534 g_variant_ref (result);
5536 g_value_unset (params + 0);
5537 g_value_unset (params + 1);
5538 g_value_unset (params + 2);
5539 g_value_unset (params + 3);
5540 g_value_unset (params + 4);
5541 g_value_unset (&result_value);
5544 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
5545 _("Unable to retrieve property %s.%s"),
5546 interface_name, property_name);
5552 register_with_closures_on_set_property (GDBusConnection *connection,
5553 const gchar *sender,
5554 const gchar *object_path,
5555 const gchar *interface_name,
5556 const gchar *property_name,
5561 RegisterObjectData *data = user_data;
5562 GValue params[] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
5563 GValue result_value = G_VALUE_INIT;
5566 g_value_init (¶ms[0], G_TYPE_DBUS_CONNECTION);
5567 g_value_set_object (¶ms[0], connection);
5569 g_value_init (¶ms[1], G_TYPE_STRING);
5570 g_value_set_string (¶ms[1], sender);
5572 g_value_init (¶ms[2], G_TYPE_STRING);
5573 g_value_set_string (¶ms[2], object_path);
5575 g_value_init (¶ms[3], G_TYPE_STRING);
5576 g_value_set_string (¶ms[3], interface_name);
5578 g_value_init (¶ms[4], G_TYPE_STRING);
5579 g_value_set_string (¶ms[4], property_name);
5581 g_value_init (¶ms[5], G_TYPE_VARIANT);
5582 g_value_set_variant (¶ms[5], value);
5584 g_value_init (&result_value, G_TYPE_BOOLEAN);
5586 g_closure_invoke (data->set_property_closure, &result_value, G_N_ELEMENTS (params), params, NULL);
5588 result = g_value_get_boolean (&result_value);
5590 g_value_unset (params + 0);
5591 g_value_unset (params + 1);
5592 g_value_unset (params + 2);
5593 g_value_unset (params + 3);
5594 g_value_unset (params + 4);
5595 g_value_unset (params + 5);
5596 g_value_unset (&result_value);
5600 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
5601 _("Unable to set property %s.%s"),
5602 interface_name, property_name);
5608 * g_dbus_connection_register_object_with_closures: (rename-to g_dbus_connection_register_object)
5609 * @connection: A #GDBusConnection.
5610 * @object_path: The object path to register at.
5611 * @interface_info: Introspection data for the interface.
5612 * @method_call_closure: (nullable): #GClosure for handling incoming method calls.
5613 * @get_property_closure: (nullable): #GClosure for getting a property.
5614 * @set_property_closure: (nullable): #GClosure for setting a property.
5615 * @error: Return location for error or %NULL.
5617 * Version of g_dbus_connection_register_object() using closures instead of a
5618 * #GDBusInterfaceVTable for easier binding in other languages.
5620 * Returns: 0 if @error is set, otherwise a registration ID (never 0)
5621 * that can be used with g_dbus_connection_unregister_object() .
5626 g_dbus_connection_register_object_with_closures (GDBusConnection *connection,
5627 const gchar *object_path,
5628 GDBusInterfaceInfo *interface_info,
5629 GClosure *method_call_closure,
5630 GClosure *get_property_closure,
5631 GClosure *set_property_closure,
5634 RegisterObjectData *data;
5635 GDBusInterfaceVTable vtable =
5637 method_call_closure != NULL ? register_with_closures_on_method_call : NULL,
5638 get_property_closure != NULL ? register_with_closures_on_get_property : NULL,
5639 set_property_closure != NULL ? register_with_closures_on_set_property : NULL,
5643 data = register_object_data_new (method_call_closure, get_property_closure, set_property_closure);
5645 return g_dbus_connection_register_object (connection,
5650 register_object_free_func,
5654 /* ---------------------------------------------------------------------------------------------------- */
5657 * g_dbus_connection_emit_signal:
5658 * @connection: a #GDBusConnection
5659 * @destination_bus_name: (nullable): the unique bus name for the destination
5660 * for the signal or %NULL to emit to all listeners
5661 * @object_path: path of remote object
5662 * @interface_name: D-Bus interface to emit a signal on
5663 * @signal_name: the name of the signal to emit
5664 * @parameters: (nullable): a #GVariant tuple with parameters for the signal
5665 * or %NULL if not passing parameters
5666 * @error: Return location for error or %NULL
5670 * If the parameters GVariant is floating, it is consumed.
5672 * This can only fail if @parameters is not compatible with the D-Bus protocol
5673 * (%G_IO_ERROR_INVALID_ARGUMENT), or if @connection has been closed
5674 * (%G_IO_ERROR_CLOSED).
5676 * Returns: %TRUE unless @error is set
5681 g_dbus_connection_emit_signal (GDBusConnection *connection,
5682 const gchar *destination_bus_name,
5683 const gchar *object_path,
5684 const gchar *interface_name,
5685 const gchar *signal_name,
5686 GVariant *parameters,
5689 GDBusMessage *message;
5695 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
5696 g_return_val_if_fail (destination_bus_name == NULL || g_dbus_is_name (destination_bus_name), FALSE);
5697 g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), FALSE);
5698 g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), FALSE);
5699 g_return_val_if_fail (signal_name != NULL && g_dbus_is_member_name (signal_name), FALSE);
5700 g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), FALSE);
5701 g_return_val_if_fail (check_initialized (connection), FALSE);
5703 if (G_UNLIKELY (_g_dbus_debug_emission ()))
5705 _g_dbus_debug_print_lock ();
5706 g_print ("========================================================================\n"
5707 "GDBus-debug:Emission:\n"
5708 " >>>> SIGNAL EMISSION %s.%s()\n"
5710 " destination %s\n",
5711 interface_name, signal_name,
5713 destination_bus_name != NULL ? destination_bus_name : "(none)");
5714 _g_dbus_debug_print_unlock ();
5717 message = g_dbus_message_new_signal (object_path,
5721 if (destination_bus_name != NULL)
5722 g_dbus_message_set_header (message,
5723 G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION,
5724 g_variant_new_string (destination_bus_name));
5726 if (parameters != NULL)
5727 g_dbus_message_set_body (message, parameters);
5729 ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, error);
5730 g_object_unref (message);
5736 add_call_flags (GDBusMessage *message,
5737 GDBusCallFlags flags)
5739 GDBusMessageFlags msg_flags = 0;
5741 if (flags & G_DBUS_CALL_FLAGS_NO_AUTO_START)
5742 msg_flags |= G_DBUS_MESSAGE_FLAGS_NO_AUTO_START;
5743 if (flags & G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION)
5744 msg_flags |= G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION;
5746 g_dbus_message_set_flags (message, msg_flags);
5750 decode_method_reply (GDBusMessage *reply,
5751 const gchar *method_name,
5752 const GVariantType *reply_type,
5753 GUnixFDList **out_fd_list,
5759 switch (g_dbus_message_get_message_type (reply))
5761 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
5762 result = g_dbus_message_get_body (reply);
5765 result = g_variant_new ("()");
5766 g_variant_ref_sink (result);
5770 g_variant_ref (result);
5773 if (!g_variant_is_of_type (result, reply_type))
5775 gchar *type_string = g_variant_type_dup_string (reply_type);
5779 G_IO_ERROR_INVALID_ARGUMENT,
5780 _("Method “%s” returned type “%s”, but expected “%s”"),
5781 method_name, g_variant_get_type_string (result), type_string);
5783 g_variant_unref (result);
5784 g_free (type_string);
5791 if (out_fd_list != NULL)
5793 *out_fd_list = g_dbus_message_get_unix_fd_list (reply);
5794 if (*out_fd_list != NULL)
5795 g_object_ref (*out_fd_list);
5801 case G_DBUS_MESSAGE_TYPE_ERROR:
5802 g_dbus_message_to_gerror (reply, error);
5806 g_assert_not_reached ();
5816 GVariantType *reply_type;
5817 gchar *method_name; /* for error message */
5819 GUnixFDList *fd_list;
5823 call_state_free (CallState *state)
5825 g_variant_type_free (state->reply_type);
5826 g_free (state->method_name);
5828 if (state->fd_list != NULL)
5829 g_object_unref (state->fd_list);
5830 g_slice_free (CallState, state);
5833 /* called in any thread, with the connection's lock not held */
5835 g_dbus_connection_call_done (GObject *source,
5836 GAsyncResult *result,
5839 GDBusConnection *connection = G_DBUS_CONNECTION (source);
5840 GTask *task = user_data;
5841 CallState *state = g_task_get_task_data (task);
5842 GError *error = NULL;
5843 GDBusMessage *reply;
5844 GVariant *value = NULL;
5846 reply = g_dbus_connection_send_message_with_reply_finish (connection,
5850 if (G_UNLIKELY (_g_dbus_debug_call ()))
5852 _g_dbus_debug_print_lock ();
5853 g_print ("========================================================================\n"
5854 "GDBus-debug:Call:\n"
5855 " <<<< ASYNC COMPLETE %s()",
5856 state->method_name);
5860 g_print (" (serial %d)\n"
5862 g_dbus_message_get_reply_serial (reply));
5870 _g_dbus_debug_print_unlock ();
5874 value = decode_method_reply (reply, state->method_name, state->reply_type, &state->fd_list, &error);
5877 g_task_return_error (task, error);
5879 g_task_return_pointer (task, value, (GDestroyNotify) g_variant_unref);
5881 g_clear_object (&reply);
5882 g_object_unref (task);
5885 /* called in any thread, with the connection's lock not held */
5887 g_dbus_connection_call_internal (GDBusConnection *connection,
5888 const gchar *bus_name,
5889 const gchar *object_path,
5890 const gchar *interface_name,
5891 const gchar *method_name,
5892 GVariant *parameters,
5893 const GVariantType *reply_type,
5894 GDBusCallFlags flags,
5896 GUnixFDList *fd_list,
5897 GCancellable *cancellable,
5898 GAsyncReadyCallback callback,
5901 GDBusMessage *message;
5904 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
5905 g_return_if_fail (bus_name == NULL || g_dbus_is_name (bus_name));
5906 g_return_if_fail (object_path != NULL && g_variant_is_object_path (object_path));
5907 g_return_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name));
5908 g_return_if_fail (method_name != NULL && g_dbus_is_member_name (method_name));
5909 g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
5910 g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
5911 g_return_if_fail (check_initialized (connection));
5913 g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
5915 g_return_if_fail (fd_list == NULL);
5918 message = g_dbus_message_new_method_call (bus_name,
5922 add_call_flags (message, flags);
5923 if (parameters != NULL)
5924 g_dbus_message_set_body (message, parameters);
5927 if (fd_list != NULL)
5928 g_dbus_message_set_unix_fd_list (message, fd_list);
5931 /* If the user has no callback then we can just send the message with
5932 * the G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set and skip all
5933 * the logic for processing the reply. If the service sends the reply
5934 * anyway then it will just be ignored.
5936 if (callback != NULL)
5941 state = g_slice_new0 (CallState);
5942 state->method_name = g_strjoin (".", interface_name, method_name, NULL);
5944 if (reply_type == NULL)
5945 reply_type = G_VARIANT_TYPE_ANY;
5947 state->reply_type = g_variant_type_copy (reply_type);
5949 task = g_task_new (connection, cancellable, callback, user_data);
5950 g_task_set_source_tag (task, g_dbus_connection_call_internal);
5951 g_task_set_task_data (task, state, (GDestroyNotify) call_state_free);
5953 g_dbus_connection_send_message_with_reply (connection,
5955 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
5959 g_dbus_connection_call_done,
5964 GDBusMessageFlags flags;
5966 flags = g_dbus_message_get_flags (message);
5967 flags |= G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
5968 g_dbus_message_set_flags (message, flags);
5970 g_dbus_connection_send_message (connection,
5972 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
5976 if (G_UNLIKELY (_g_dbus_debug_call ()))
5978 _g_dbus_debug_print_lock ();
5979 g_print ("========================================================================\n"
5980 "GDBus-debug:Call:\n"
5981 " >>>> ASYNC %s.%s()\n"
5983 " owned by name %s (serial %d)\n",
5987 bus_name != NULL ? bus_name : "(none)",
5989 _g_dbus_debug_print_unlock ();
5992 if (message != NULL)
5993 g_object_unref (message);
5996 /* called in any thread, with the connection's lock not held */
5998 g_dbus_connection_call_finish_internal (GDBusConnection *connection,
5999 GUnixFDList **out_fd_list,
6007 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
6008 g_return_val_if_fail (g_task_is_valid (res, connection), NULL);
6009 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
6011 task = G_TASK (res);
6012 state = g_task_get_task_data (task);
6014 ret = g_task_propagate_pointer (task, error);
6018 if (out_fd_list != NULL)
6019 *out_fd_list = state->fd_list != NULL ? g_object_ref (state->fd_list) : NULL;
6023 /* called in any user thread, with the connection's lock not held */
6025 g_dbus_connection_call_sync_internal (GDBusConnection *connection,
6026 const gchar *bus_name,
6027 const gchar *object_path,
6028 const gchar *interface_name,
6029 const gchar *method_name,
6030 GVariant *parameters,
6031 const GVariantType *reply_type,
6032 GDBusCallFlags flags,
6034 GUnixFDList *fd_list,
6035 GUnixFDList **out_fd_list,
6036 GCancellable *cancellable,
6039 GDBusMessage *message;
6040 GDBusMessage *reply;
6042 GError *local_error;
6043 GDBusSendMessageFlags send_flags;
6049 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
6050 g_return_val_if_fail (bus_name == NULL || g_dbus_is_name (bus_name), NULL);
6051 g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), NULL);
6052 g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), NULL);
6053 g_return_val_if_fail (method_name != NULL && g_dbus_is_member_name (method_name), NULL);
6054 g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
6055 g_return_val_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
6057 g_return_val_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list), NULL);
6059 g_return_val_if_fail (fd_list == NULL, NULL);
6061 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
6063 if (!(flags & CALL_FLAGS_INITIALIZING))
6064 g_return_val_if_fail (check_initialized (connection), FALSE);
6066 if (reply_type == NULL)
6067 reply_type = G_VARIANT_TYPE_ANY;
6069 message = g_dbus_message_new_method_call (bus_name,
6073 add_call_flags (message, flags);
6074 if (parameters != NULL)
6075 g_dbus_message_set_body (message, parameters);
6078 if (fd_list != NULL)
6079 g_dbus_message_set_unix_fd_list (message, fd_list);
6082 if (G_UNLIKELY (_g_dbus_debug_call ()))
6084 _g_dbus_debug_print_lock ();
6085 g_print ("========================================================================\n"
6086 "GDBus-debug:Call:\n"
6087 " >>>> SYNC %s.%s()\n"
6089 " owned by name %s\n",
6093 bus_name != NULL ? bus_name : "(none)");
6094 _g_dbus_debug_print_unlock ();
6099 send_flags = G_DBUS_SEND_MESSAGE_FLAGS_NONE;
6101 /* translate from one flavour of flags to another... */
6102 if (flags & CALL_FLAGS_INITIALIZING)
6103 send_flags |= SEND_MESSAGE_FLAGS_INITIALIZING;
6105 reply = g_dbus_connection_send_message_with_reply_sync (connection,
6109 NULL, /* guint32 *out_serial */
6113 if (G_UNLIKELY (_g_dbus_debug_call ()))
6115 _g_dbus_debug_print_lock ();
6116 g_print ("========================================================================\n"
6117 "GDBus-debug:Call:\n"
6118 " <<<< SYNC COMPLETE %s.%s()\n"
6124 g_print ("SUCCESS\n");
6128 g_print ("FAILED: %s\n",
6129 local_error->message);
6131 _g_dbus_debug_print_unlock ();
6137 *error = local_error;
6139 g_error_free (local_error);
6143 result = decode_method_reply (reply, method_name, reply_type, out_fd_list, error);
6146 if (message != NULL)
6147 g_object_unref (message);
6149 g_object_unref (reply);
6154 /* ---------------------------------------------------------------------------------------------------- */
6157 * g_dbus_connection_call:
6158 * @connection: a #GDBusConnection
6159 * @bus_name: (nullable): a unique or well-known bus name or %NULL if
6160 * @connection is not a message bus connection
6161 * @object_path: path of remote object
6162 * @interface_name: D-Bus interface to invoke method on
6163 * @method_name: the name of the method to invoke
6164 * @parameters: (nullable): a #GVariant tuple with parameters for the method
6165 * or %NULL if not passing parameters
6166 * @reply_type: (nullable): the expected type of the reply (which will be a
6168 * @flags: flags from the #GDBusCallFlags enumeration
6169 * @timeout_msec: the timeout in milliseconds, -1 to use the default
6170 * timeout or %G_MAXINT for no timeout
6171 * @cancellable: (nullable): a #GCancellable or %NULL
6172 * @callback: (nullable): a #GAsyncReadyCallback to call when the request
6173 * is satisfied or %NULL if you don't care about the result of the
6175 * @user_data: the data to pass to @callback
6177 * Asynchronously invokes the @method_name method on the
6178 * @interface_name D-Bus interface on the remote object at
6179 * @object_path owned by @bus_name.
6181 * If @connection is closed then the operation will fail with
6182 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
6183 * fail with %G_IO_ERROR_CANCELLED. If @parameters contains a value
6184 * not compatible with the D-Bus protocol, the operation fails with
6185 * %G_IO_ERROR_INVALID_ARGUMENT.
6187 * If @reply_type is non-%NULL then the reply will be checked for having this type and an
6188 * error will be raised if it does not match. Said another way, if you give a @reply_type
6189 * then any non-%NULL return value will be of this type. Unless it’s
6190 * %G_VARIANT_TYPE_UNIT, the @reply_type will be a tuple containing one or more
6193 * If the @parameters #GVariant is floating, it is consumed. This allows
6194 * convenient 'inline' use of g_variant_new(), e.g.:
6195 * |[<!-- language="C" -->
6196 * g_dbus_connection_call (connection,
6197 * "org.freedesktop.StringThings",
6198 * "/org/freedesktop/StringThings",
6199 * "org.freedesktop.StringThings",
6201 * g_variant_new ("(ss)",
6205 * G_DBUS_CALL_FLAGS_NONE,
6208 * (GAsyncReadyCallback) two_strings_done,
6212 * This is an asynchronous method. When the operation is finished,
6213 * @callback will be invoked in the
6214 * [thread-default main context][g-main-context-push-thread-default]
6215 * of the thread you are calling this method from. You can then call
6216 * g_dbus_connection_call_finish() to get the result of the operation.
6217 * See g_dbus_connection_call_sync() for the synchronous version of this
6220 * If @callback is %NULL then the D-Bus method call message will be sent with
6221 * the %G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set.
6226 g_dbus_connection_call (GDBusConnection *connection,
6227 const gchar *bus_name,
6228 const gchar *object_path,
6229 const gchar *interface_name,
6230 const gchar *method_name,
6231 GVariant *parameters,
6232 const GVariantType *reply_type,
6233 GDBusCallFlags flags,
6235 GCancellable *cancellable,
6236 GAsyncReadyCallback callback,
6239 g_dbus_connection_call_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, NULL, cancellable, callback, user_data);
6243 * g_dbus_connection_call_finish:
6244 * @connection: a #GDBusConnection
6245 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_call()
6246 * @error: return location for error or %NULL
6248 * Finishes an operation started with g_dbus_connection_call().
6250 * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating
6251 * #GVariant tuple with return values. Free with g_variant_unref().
6256 g_dbus_connection_call_finish (GDBusConnection *connection,
6260 return g_dbus_connection_call_finish_internal (connection, NULL, res, error);
6264 * g_dbus_connection_call_sync:
6265 * @connection: a #GDBusConnection
6266 * @bus_name: (nullable): a unique or well-known bus name or %NULL if
6267 * @connection is not a message bus connection
6268 * @object_path: path of remote object
6269 * @interface_name: D-Bus interface to invoke method on
6270 * @method_name: the name of the method to invoke
6271 * @parameters: (nullable): a #GVariant tuple with parameters for the method
6272 * or %NULL if not passing parameters
6273 * @reply_type: (nullable): the expected type of the reply, or %NULL
6274 * @flags: flags from the #GDBusCallFlags enumeration
6275 * @timeout_msec: the timeout in milliseconds, -1 to use the default
6276 * timeout or %G_MAXINT for no timeout
6277 * @cancellable: (nullable): a #GCancellable or %NULL
6278 * @error: return location for error or %NULL
6280 * Synchronously invokes the @method_name method on the
6281 * @interface_name D-Bus interface on the remote object at
6282 * @object_path owned by @bus_name.
6284 * If @connection is closed then the operation will fail with
6285 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the
6286 * operation will fail with %G_IO_ERROR_CANCELLED. If @parameters
6287 * contains a value not compatible with the D-Bus protocol, the operation
6288 * fails with %G_IO_ERROR_INVALID_ARGUMENT.
6290 * If @reply_type is non-%NULL then the reply will be checked for having
6291 * this type and an error will be raised if it does not match. Said
6292 * another way, if you give a @reply_type then any non-%NULL return
6293 * value will be of this type.
6295 * If the @parameters #GVariant is floating, it is consumed.
6296 * This allows convenient 'inline' use of g_variant_new(), e.g.:
6297 * |[<!-- language="C" -->
6298 * g_dbus_connection_call_sync (connection,
6299 * "org.freedesktop.StringThings",
6300 * "/org/freedesktop/StringThings",
6301 * "org.freedesktop.StringThings",
6303 * g_variant_new ("(ss)",
6307 * G_DBUS_CALL_FLAGS_NONE,
6313 * The calling thread is blocked until a reply is received. See
6314 * g_dbus_connection_call() for the asynchronous version of
6317 * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating
6318 * #GVariant tuple with return values. Free with g_variant_unref().
6323 g_dbus_connection_call_sync (GDBusConnection *connection,
6324 const gchar *bus_name,
6325 const gchar *object_path,
6326 const gchar *interface_name,
6327 const gchar *method_name,
6328 GVariant *parameters,
6329 const GVariantType *reply_type,
6330 GDBusCallFlags flags,
6332 GCancellable *cancellable,
6335 return g_dbus_connection_call_sync_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, NULL, NULL, cancellable, error);
6338 /* ---------------------------------------------------------------------------------------------------- */
6343 * g_dbus_connection_call_with_unix_fd_list:
6344 * @connection: a #GDBusConnection
6345 * @bus_name: (nullable): a unique or well-known bus name or %NULL if
6346 * @connection is not a message bus connection
6347 * @object_path: path of remote object
6348 * @interface_name: D-Bus interface to invoke method on
6349 * @method_name: the name of the method to invoke
6350 * @parameters: (nullable): a #GVariant tuple with parameters for the method
6351 * or %NULL if not passing parameters
6352 * @reply_type: (nullable): the expected type of the reply, or %NULL
6353 * @flags: flags from the #GDBusCallFlags enumeration
6354 * @timeout_msec: the timeout in milliseconds, -1 to use the default
6355 * timeout or %G_MAXINT for no timeout
6356 * @fd_list: (nullable): a #GUnixFDList or %NULL
6357 * @cancellable: (nullable): a #GCancellable or %NULL
6358 * @callback: (nullable): a #GAsyncReadyCallback to call when the request is
6359 * satisfied or %NULL if you don't * care about the result of the
6361 * @user_data: The data to pass to @callback.
6363 * Like g_dbus_connection_call() but also takes a #GUnixFDList object.
6365 * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE
6366 * values in the body of the message. For example, if a message contains
6367 * two file descriptors, @fd_list would have length 2, and
6368 * `g_variant_new_handle (0)` and `g_variant_new_handle (1)` would appear
6369 * somewhere in the body of the message (not necessarily in that order!)
6370 * to represent the file descriptors at indexes 0 and 1 respectively.
6372 * When designing D-Bus APIs that are intended to be interoperable,
6373 * please note that non-GDBus implementations of D-Bus can usually only
6374 * access file descriptors if they are referenced in this way by a
6375 * value of type %G_VARIANT_TYPE_HANDLE in the body of the message.
6377 * This method is only available on UNIX.
6382 g_dbus_connection_call_with_unix_fd_list (GDBusConnection *connection,
6383 const gchar *bus_name,
6384 const gchar *object_path,
6385 const gchar *interface_name,
6386 const gchar *method_name,
6387 GVariant *parameters,
6388 const GVariantType *reply_type,
6389 GDBusCallFlags flags,
6391 GUnixFDList *fd_list,
6392 GCancellable *cancellable,
6393 GAsyncReadyCallback callback,
6396 g_dbus_connection_call_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, fd_list, cancellable, callback, user_data);
6400 * g_dbus_connection_call_with_unix_fd_list_finish:
6401 * @connection: a #GDBusConnection
6402 * @out_fd_list: (out) (optional): return location for a #GUnixFDList or %NULL
6403 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to
6404 * g_dbus_connection_call_with_unix_fd_list()
6405 * @error: return location for error or %NULL
6407 * Finishes an operation started with g_dbus_connection_call_with_unix_fd_list().
6409 * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE
6410 * values in the body of the message. For example,
6411 * if g_variant_get_handle() returns 5, that is intended to be a reference
6412 * to the file descriptor that can be accessed by
6413 * `g_unix_fd_list_get (*out_fd_list, 5, ...)`.
6415 * When designing D-Bus APIs that are intended to be interoperable,
6416 * please note that non-GDBus implementations of D-Bus can usually only
6417 * access file descriptors if they are referenced in this way by a
6418 * value of type %G_VARIANT_TYPE_HANDLE in the body of the message.
6420 * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating
6421 * #GVariant tuple with return values. Free with g_variant_unref().
6426 g_dbus_connection_call_with_unix_fd_list_finish (GDBusConnection *connection,
6427 GUnixFDList **out_fd_list,
6431 return g_dbus_connection_call_finish_internal (connection, out_fd_list, res, error);
6435 * g_dbus_connection_call_with_unix_fd_list_sync:
6436 * @connection: a #GDBusConnection
6437 * @bus_name: (nullable): a unique or well-known bus name or %NULL
6438 * if @connection is not a message bus connection
6439 * @object_path: path of remote object
6440 * @interface_name: D-Bus interface to invoke method on
6441 * @method_name: the name of the method to invoke
6442 * @parameters: (nullable): a #GVariant tuple with parameters for
6443 * the method or %NULL if not passing parameters
6444 * @reply_type: (nullable): the expected type of the reply, or %NULL
6445 * @flags: flags from the #GDBusCallFlags enumeration
6446 * @timeout_msec: the timeout in milliseconds, -1 to use the default
6447 * timeout or %G_MAXINT for no timeout
6448 * @fd_list: (nullable): a #GUnixFDList or %NULL
6449 * @out_fd_list: (out) (optional): return location for a #GUnixFDList or %NULL
6450 * @cancellable: (nullable): a #GCancellable or %NULL
6451 * @error: return location for error or %NULL
6453 * Like g_dbus_connection_call_sync() but also takes and returns #GUnixFDList objects.
6454 * See g_dbus_connection_call_with_unix_fd_list() and
6455 * g_dbus_connection_call_with_unix_fd_list_finish() for more details.
6457 * This method is only available on UNIX.
6459 * Returns: (transfer full): %NULL if @error is set. Otherwise a non-floating
6460 * #GVariant tuple with return values. Free with g_variant_unref().
6465 g_dbus_connection_call_with_unix_fd_list_sync (GDBusConnection *connection,
6466 const gchar *bus_name,
6467 const gchar *object_path,
6468 const gchar *interface_name,
6469 const gchar *method_name,
6470 GVariant *parameters,
6471 const GVariantType *reply_type,
6472 GDBusCallFlags flags,
6474 GUnixFDList *fd_list,
6475 GUnixFDList **out_fd_list,
6476 GCancellable *cancellable,
6479 return g_dbus_connection_call_sync_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, fd_list, out_fd_list, cancellable, error);
6482 #endif /* G_OS_UNIX */
6484 /* ---------------------------------------------------------------------------------------------------- */
6486 /* called without lock held in the thread where the caller registered
6490 handle_subtree_introspect (GDBusConnection *connection,
6491 ExportedSubtree *es,
6492 GDBusMessage *message)
6496 GDBusMessage *reply;
6499 const gchar *sender;
6500 const gchar *requested_object_path;
6501 const gchar *requested_node;
6502 GDBusInterfaceInfo **interfaces;
6504 gchar **subnode_paths;
6505 gboolean has_properties_interface;
6506 gboolean has_introspectable_interface;
6510 requested_object_path = g_dbus_message_get_path (message);
6511 sender = g_dbus_message_get_sender (message);
6512 is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
6514 s = g_string_new (NULL);
6515 introspect_append_header (s);
6517 /* Strictly we don't need the children in dynamic mode, but we avoid the
6518 * conditionals to preserve code clarity
6520 children = es->vtable->enumerate (es->connection,
6527 requested_node = strrchr (requested_object_path, '/') + 1;
6529 /* Assert existence of object if we are not dynamic */
6530 if (!(es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES) &&
6531 !g_strv_contains ((const gchar * const *) children, requested_node))
6536 requested_node = NULL;
6539 interfaces = es->vtable->introspect (es->connection,
6544 if (interfaces != NULL)
6546 has_properties_interface = FALSE;
6547 has_introspectable_interface = FALSE;
6549 for (n = 0; interfaces[n] != NULL; n++)
6551 if (strcmp (interfaces[n]->name, "org.freedesktop.DBus.Properties") == 0)
6552 has_properties_interface = TRUE;
6553 else if (strcmp (interfaces[n]->name, "org.freedesktop.DBus.Introspectable") == 0)
6554 has_introspectable_interface = TRUE;
6556 if (!has_properties_interface)
6557 g_string_append (s, introspect_properties_interface);
6558 if (!has_introspectable_interface)
6559 g_string_append (s, introspect_introspectable_interface);
6561 for (n = 0; interfaces[n] != NULL; n++)
6563 g_dbus_interface_info_generate_xml (interfaces[n], 2, s);
6564 g_dbus_interface_info_unref (interfaces[n]);
6566 g_free (interfaces);
6569 /* then include <node> entries from the Subtree for the root */
6572 for (n = 0; children != NULL && children[n] != NULL; n++)
6573 g_string_append_printf (s, " <node name=\"%s\"/>\n", children[n]);
6576 /* finally include nodes registered below us */
6577 subnode_paths = g_dbus_connection_list_registered (es->connection, requested_object_path);
6578 for (n = 0; subnode_paths != NULL && subnode_paths[n] != NULL; n++)
6579 g_string_append_printf (s, " <node name=\"%s\"/>\n", subnode_paths[n]);
6580 g_strfreev (subnode_paths);
6582 g_string_append (s, "</node>\n");
6584 reply = g_dbus_message_new_method_reply (message);
6585 g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
6586 g_dbus_connection_send_message (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6587 g_object_unref (reply);
6592 g_string_free (s, TRUE);
6593 g_strfreev (children);
6597 /* called without lock held in the thread where the caller registered
6601 handle_subtree_method_invocation (GDBusConnection *connection,
6602 ExportedSubtree *es,
6603 GDBusMessage *message)
6606 const gchar *sender;
6607 const gchar *interface_name;
6608 const gchar *member;
6609 const gchar *signature;
6610 const gchar *requested_object_path;
6611 const gchar *requested_node;
6613 GDBusInterfaceInfo *interface_info;
6614 const GDBusInterfaceVTable *interface_vtable;
6615 gpointer interface_user_data;
6617 GDBusInterfaceInfo **interfaces;
6618 gboolean is_property_get;
6619 gboolean is_property_set;
6620 gboolean is_property_get_all;
6625 requested_object_path = g_dbus_message_get_path (message);
6626 sender = g_dbus_message_get_sender (message);
6627 interface_name = g_dbus_message_get_interface (message);
6628 member = g_dbus_message_get_member (message);
6629 signature = g_dbus_message_get_signature (message);
6630 is_root = (g_strcmp0 (requested_object_path, es->object_path) == 0);
6632 is_property_get = FALSE;
6633 is_property_set = FALSE;
6634 is_property_get_all = FALSE;
6635 if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0)
6637 if (g_strcmp0 (member, "Get") == 0 && g_strcmp0 (signature, "ss") == 0)
6638 is_property_get = TRUE;
6639 else if (g_strcmp0 (member, "Set") == 0 && g_strcmp0 (signature, "ssv") == 0)
6640 is_property_set = TRUE;
6641 else if (g_strcmp0 (member, "GetAll") == 0 && g_strcmp0 (signature, "s") == 0)
6642 is_property_get_all = TRUE;
6647 requested_node = strrchr (requested_object_path, '/') + 1;
6649 if (~es->flags & G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES)
6651 /* We don't want to dispatch to unenumerated
6652 * nodes, so ensure that the child exists.
6657 children = es->vtable->enumerate (es->connection,
6662 exists = g_strv_contains ((const gchar * const *) children, requested_node);
6663 g_strfreev (children);
6671 requested_node = NULL;
6674 /* get introspection data for the node */
6675 interfaces = es->vtable->introspect (es->connection,
6677 requested_object_path,
6681 if (interfaces == NULL)
6684 interface_info = NULL;
6685 for (n = 0; interfaces[n] != NULL; n++)
6687 if (g_strcmp0 (interfaces[n]->name, interface_name) == 0)
6688 interface_info = interfaces[n];
6691 /* dispatch the call if the user wants to handle it */
6692 if (interface_info != NULL)
6694 /* figure out where to dispatch the method call */
6695 interface_user_data = NULL;
6696 interface_vtable = es->vtable->dispatch (es->connection,
6701 &interface_user_data,
6703 if (interface_vtable == NULL)
6706 CONNECTION_LOCK (connection);
6707 handled = validate_and_maybe_schedule_method_call (es->connection,
6714 interface_user_data);
6715 CONNECTION_UNLOCK (connection);
6717 /* handle org.freedesktop.DBus.Properties interface if not explicitly handled */
6718 else if (is_property_get || is_property_set || is_property_get_all)
6720 if (is_property_get)
6721 g_variant_get (g_dbus_message_get_body (message), "(&s&s)", &interface_name, NULL);
6722 else if (is_property_set)
6723 g_variant_get (g_dbus_message_get_body (message), "(&s&sv)", &interface_name, NULL, NULL);
6724 else if (is_property_get_all)
6725 g_variant_get (g_dbus_message_get_body (message), "(&s)", &interface_name, NULL, NULL);
6727 g_assert_not_reached ();
6729 /* see if the object supports this interface at all */
6730 for (n = 0; interfaces[n] != NULL; n++)
6732 if (g_strcmp0 (interfaces[n]->name, interface_name) == 0)
6733 interface_info = interfaces[n];
6736 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the user-code
6737 * claims it won't support the interface
6739 if (interface_info == NULL)
6741 GDBusMessage *reply;
6742 reply = g_dbus_message_new_method_error (message,
6743 "org.freedesktop.DBus.Error.InvalidArgs",
6744 _("No such interface “%s”"),
6746 g_dbus_connection_send_message (es->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6747 g_object_unref (reply);
6752 /* figure out where to dispatch the property get/set/getall calls */
6753 interface_user_data = NULL;
6754 interface_vtable = es->vtable->dispatch (es->connection,
6759 &interface_user_data,
6761 if (interface_vtable == NULL)
6763 g_warning ("The subtree introspection function indicates that '%s' "
6764 "is a valid interface name, but calling the dispatch "
6765 "function on that interface gave us NULL", interface_name);
6769 if (is_property_get || is_property_set)
6771 CONNECTION_LOCK (connection);
6772 handled = validate_and_maybe_schedule_property_getset (es->connection,
6780 interface_user_data);
6781 CONNECTION_UNLOCK (connection);
6783 else if (is_property_get_all)
6785 CONNECTION_LOCK (connection);
6786 handled = validate_and_maybe_schedule_property_get_all (es->connection,
6793 interface_user_data);
6794 CONNECTION_UNLOCK (connection);
6799 if (interfaces != NULL)
6801 for (n = 0; interfaces[n] != NULL; n++)
6802 g_dbus_interface_info_unref (interfaces[n]);
6803 g_free (interfaces);
6811 GDBusMessage *message; /* (owned) */
6812 ExportedSubtree *es; /* (owned) */
6813 } SubtreeDeferredData;
6816 subtree_deferred_data_free (SubtreeDeferredData *data)
6818 g_object_unref (data->message);
6819 exported_subtree_unref (data->es);
6823 /* called without lock held in the thread where the caller registered the subtree */
6825 process_subtree_vtable_message_in_idle_cb (gpointer _data)
6827 SubtreeDeferredData *data = _data;
6832 if (g_strcmp0 (g_dbus_message_get_interface (data->message), "org.freedesktop.DBus.Introspectable") == 0 &&
6833 g_strcmp0 (g_dbus_message_get_member (data->message), "Introspect") == 0 &&
6834 g_strcmp0 (g_dbus_message_get_signature (data->message), "") == 0)
6835 handled = handle_subtree_introspect (data->es->connection,
6839 handled = handle_subtree_method_invocation (data->es->connection,
6845 CONNECTION_LOCK (data->es->connection);
6846 handled = handle_generic_unlocked (data->es->connection, data->message);
6847 CONNECTION_UNLOCK (data->es->connection);
6850 /* if we couldn't handle the request, just bail with the UnknownMethod error */
6853 GDBusMessage *reply;
6854 reply = g_dbus_message_new_method_error (data->message,
6855 "org.freedesktop.DBus.Error.UnknownMethod",
6856 _("Method “%s” on interface “%s” with signature “%s” does not exist"),
6857 g_dbus_message_get_member (data->message),
6858 g_dbus_message_get_interface (data->message),
6859 g_dbus_message_get_signature (data->message));
6860 g_dbus_connection_send_message (data->es->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
6861 g_object_unref (reply);
6867 /* called in GDBusWorker thread with connection's lock held */
6869 subtree_message_func (GDBusConnection *connection,
6870 ExportedSubtree *es,
6871 GDBusMessage *message)
6873 GSource *idle_source;
6874 SubtreeDeferredData *data;
6876 data = g_new0 (SubtreeDeferredData, 1);
6877 data->message = g_object_ref (message);
6878 data->es = exported_subtree_ref (es);
6880 /* defer this call to an idle handler in the right thread */
6881 idle_source = g_idle_source_new ();
6882 g_source_set_priority (idle_source, G_PRIORITY_HIGH);
6883 g_source_set_callback (idle_source,
6884 process_subtree_vtable_message_in_idle_cb,
6886 (GDestroyNotify) subtree_deferred_data_free);
6887 g_source_set_static_name (idle_source, "[gio] process_subtree_vtable_message_in_idle_cb");
6888 g_source_attach (idle_source, es->context);
6889 g_source_unref (idle_source);
6891 /* since we own the entire subtree, handlers for objects not in the subtree have been
6892 * tried already by libdbus-1 - so we just need to ensure that we're always going
6893 * to reply to the message
6899 * g_dbus_connection_register_subtree:
6900 * @connection: a #GDBusConnection
6901 * @object_path: the object path to register the subtree at
6902 * @vtable: a #GDBusSubtreeVTable to enumerate, introspect and
6903 * dispatch nodes in the subtree
6904 * @flags: flags used to fine tune the behavior of the subtree
6905 * @user_data: data to pass to functions in @vtable
6906 * @user_data_free_func: function to call when the subtree is unregistered
6907 * @error: return location for error or %NULL
6909 * Registers a whole subtree of dynamic objects.
6911 * The @enumerate and @introspection functions in @vtable are used to
6912 * convey, to remote callers, what nodes exist in the subtree rooted
6915 * When handling remote calls into any node in the subtree, first the
6916 * @enumerate function is used to check if the node exists. If the node exists
6917 * or the %G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag is set
6918 * the @introspection function is used to check if the node supports the
6919 * requested method. If so, the @dispatch function is used to determine
6920 * where to dispatch the call. The collected #GDBusInterfaceVTable and
6921 * #gpointer will be used to call into the interface vtable for processing
6924 * All calls into user-provided code will be invoked in the
6925 * [thread-default main context][g-main-context-push-thread-default]
6926 * of the thread you are calling this method from.
6928 * If an existing subtree is already registered at @object_path or
6929 * then @error is set to %G_IO_ERROR_EXISTS.
6931 * Note that it is valid to register regular objects (using
6932 * g_dbus_connection_register_object()) in a subtree registered with
6933 * g_dbus_connection_register_subtree() - if so, the subtree handler
6934 * is tried as the last resort. One way to think about a subtree
6935 * handler is to consider it a fallback handler for object paths not
6936 * registered via g_dbus_connection_register_object() or other bindings.
6938 * Note that @vtable will be copied so you cannot change it after
6941 * See this [server][gdbus-subtree-server] for an example of how to use
6944 * Returns: 0 if @error is set, otherwise a subtree registration ID (never 0)
6945 * that can be used with g_dbus_connection_unregister_subtree()
6950 g_dbus_connection_register_subtree (GDBusConnection *connection,
6951 const gchar *object_path,
6952 const GDBusSubtreeVTable *vtable,
6953 GDBusSubtreeFlags flags,
6955 GDestroyNotify user_data_free_func,
6959 ExportedSubtree *es;
6961 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
6962 g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), 0);
6963 g_return_val_if_fail (vtable != NULL, 0);
6964 g_return_val_if_fail (error == NULL || *error == NULL, 0);
6965 g_return_val_if_fail (check_initialized (connection), 0);
6969 CONNECTION_LOCK (connection);
6971 es = g_hash_table_lookup (connection->map_object_path_to_es, object_path);
6977 _("A subtree is already exported for %s"),
6982 es = g_new0 (ExportedSubtree, 1);
6984 es->object_path = g_strdup (object_path);
6985 es->connection = connection;
6987 es->vtable = _g_dbus_subtree_vtable_copy (vtable);
6989 es->id = (guint) g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */
6990 es->user_data = user_data;
6991 es->user_data_free_func = user_data_free_func;
6992 es->context = g_main_context_ref_thread_default ();
6994 g_hash_table_insert (connection->map_object_path_to_es, es->object_path, es);
6995 g_hash_table_insert (connection->map_id_to_es,
6996 GUINT_TO_POINTER (es->id),
7002 CONNECTION_UNLOCK (connection);
7007 /* ---------------------------------------------------------------------------------------------------- */
7010 * g_dbus_connection_unregister_subtree:
7011 * @connection: a #GDBusConnection
7012 * @registration_id: a subtree registration id obtained from
7013 * g_dbus_connection_register_subtree()
7015 * Unregisters a subtree.
7017 * Returns: %TRUE if the subtree was unregistered, %FALSE otherwise
7022 g_dbus_connection_unregister_subtree (GDBusConnection *connection,
7023 guint registration_id)
7025 ExportedSubtree *es;
7028 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
7029 g_return_val_if_fail (check_initialized (connection), FALSE);
7033 CONNECTION_LOCK (connection);
7035 es = g_hash_table_lookup (connection->map_id_to_es,
7036 GUINT_TO_POINTER (registration_id));
7040 g_warn_if_fail (g_hash_table_remove (connection->map_id_to_es, GUINT_TO_POINTER (es->id)));
7041 g_warn_if_fail (g_hash_table_remove (connection->map_object_path_to_es, es->object_path));
7046 CONNECTION_UNLOCK (connection);
7051 /* ---------------------------------------------------------------------------------------------------- */
7053 /* may be called in any thread, with connection's lock held */
7055 handle_generic_ping_unlocked (GDBusConnection *connection,
7056 const gchar *object_path,
7057 GDBusMessage *message)
7059 GDBusMessage *reply;
7060 reply = g_dbus_message_new_method_reply (message);
7061 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
7062 g_object_unref (reply);
7065 /* may be called in any thread, with connection's lock held */
7067 handle_generic_get_machine_id_unlocked (GDBusConnection *connection,
7068 const gchar *object_path,
7069 GDBusMessage *message)
7071 GDBusMessage *reply;
7074 if (connection->machine_id == NULL)
7079 connection->machine_id = _g_dbus_get_machine_id (&error);
7080 if (connection->machine_id == NULL)
7082 reply = g_dbus_message_new_method_error_literal (message,
7083 "org.freedesktop.DBus.Error.Failed",
7085 g_error_free (error);
7091 reply = g_dbus_message_new_method_reply (message);
7092 g_dbus_message_set_body (reply, g_variant_new ("(s)", connection->machine_id));
7094 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
7095 g_object_unref (reply);
7098 /* may be called in any thread, with connection's lock held */
7100 handle_generic_introspect_unlocked (GDBusConnection *connection,
7101 const gchar *object_path,
7102 GDBusMessage *message)
7107 GDBusMessage *reply;
7109 /* first the header */
7110 s = g_string_new (NULL);
7111 introspect_append_header (s);
7113 registered = g_dbus_connection_list_registered_unlocked (connection, object_path);
7114 for (n = 0; registered != NULL && registered[n] != NULL; n++)
7115 g_string_append_printf (s, " <node name=\"%s\"/>\n", registered[n]);
7116 g_strfreev (registered);
7117 g_string_append (s, "</node>\n");
7119 reply = g_dbus_message_new_method_reply (message);
7120 g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
7121 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
7122 g_object_unref (reply);
7123 g_string_free (s, TRUE);
7126 /* may be called in any thread, with connection's lock held */
7128 handle_generic_unlocked (GDBusConnection *connection,
7129 GDBusMessage *message)
7132 const gchar *interface_name;
7133 const gchar *member;
7134 const gchar *signature;
7137 CONNECTION_ENSURE_LOCK (connection);
7141 interface_name = g_dbus_message_get_interface (message);
7142 member = g_dbus_message_get_member (message);
7143 signature = g_dbus_message_get_signature (message);
7144 path = g_dbus_message_get_path (message);
7146 if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 &&
7147 g_strcmp0 (member, "Introspect") == 0 &&
7148 g_strcmp0 (signature, "") == 0)
7150 handle_generic_introspect_unlocked (connection, path, message);
7153 else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
7154 g_strcmp0 (member, "Ping") == 0 &&
7155 g_strcmp0 (signature, "") == 0)
7157 handle_generic_ping_unlocked (connection, path, message);
7160 else if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Peer") == 0 &&
7161 g_strcmp0 (member, "GetMachineId") == 0 &&
7162 g_strcmp0 (signature, "") == 0)
7164 handle_generic_get_machine_id_unlocked (connection, path, message);
7171 /* ---------------------------------------------------------------------------------------------------- */
7173 /* called in GDBusWorker thread with connection's lock held */
7175 distribute_method_call (GDBusConnection *connection,
7176 GDBusMessage *message)
7178 GDBusMessage *reply;
7180 ExportedSubtree *es;
7181 const gchar *object_path;
7182 const gchar *interface_name;
7183 const gchar *member;
7185 gchar *subtree_path;
7187 gboolean object_found = FALSE;
7189 g_assert (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL);
7191 interface_name = g_dbus_message_get_interface (message);
7192 member = g_dbus_message_get_member (message);
7193 path = g_dbus_message_get_path (message);
7194 subtree_path = g_strdup (path);
7195 needle = strrchr (subtree_path, '/');
7196 if (needle != NULL && needle != subtree_path)
7202 g_free (subtree_path);
7203 subtree_path = NULL;
7207 if (G_UNLIKELY (_g_dbus_debug_incoming ()))
7209 _g_dbus_debug_print_lock ();
7210 g_print ("========================================================================\n"
7211 "GDBus-debug:Incoming:\n"
7212 " <<<< METHOD INVOCATION %s.%s()\n"
7214 " invoked by name %s\n"
7216 interface_name, member,
7218 g_dbus_message_get_sender (message) != NULL ? g_dbus_message_get_sender (message) : "(none)",
7219 g_dbus_message_get_serial (message));
7220 _g_dbus_debug_print_unlock ();
7223 object_path = g_dbus_message_get_path (message);
7224 g_assert (object_path != NULL);
7226 eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path);
7229 if (obj_message_func (connection, eo, message, &object_found))
7233 es = g_hash_table_lookup (connection->map_object_path_to_es, object_path);
7236 if (subtree_message_func (connection, es, message))
7240 if (subtree_path != NULL)
7242 es = g_hash_table_lookup (connection->map_object_path_to_es, subtree_path);
7245 if (subtree_message_func (connection, es, message))
7250 if (handle_generic_unlocked (connection, message))
7253 /* if we end up here, the message has not been not handled - so return an error saying this */
7254 if (object_found == TRUE)
7256 reply = g_dbus_message_new_method_error (message,
7257 "org.freedesktop.DBus.Error.UnknownMethod",
7258 _("No such interface “%s” on object at path %s"),
7264 reply = g_dbus_message_new_method_error (message,
7265 "org.freedesktop.DBus.Error.UnknownMethod",
7266 _("Object does not exist at path “%s”"),
7270 g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
7271 g_object_unref (reply);
7274 g_free (subtree_path);
7277 /* ---------------------------------------------------------------------------------------------------- */
7279 /* Called in any user thread, with the message_bus_lock held. */
7281 message_bus_get_singleton (GBusType bus_type,
7285 const gchar *starter_bus;
7291 case G_BUS_TYPE_SESSION:
7292 ret = &the_session_bus;
7295 case G_BUS_TYPE_SYSTEM:
7296 ret = &the_system_bus;
7299 case G_BUS_TYPE_STARTER:
7300 starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE");
7301 if (g_strcmp0 (starter_bus, "session") == 0)
7303 ret = message_bus_get_singleton (G_BUS_TYPE_SESSION, error);
7306 else if (g_strcmp0 (starter_bus, "system") == 0)
7308 ret = message_bus_get_singleton (G_BUS_TYPE_SYSTEM, error);
7313 if (starter_bus != NULL)
7317 G_IO_ERROR_INVALID_ARGUMENT,
7318 _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable"
7319 " — unknown value “%s”"),
7324 g_set_error_literal (error,
7326 G_IO_ERROR_INVALID_ARGUMENT,
7327 _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment "
7328 "variable is not set"));
7334 g_assert_not_reached ();
7342 /* Called in any user thread, without holding locks. */
7343 static GDBusConnection *
7344 get_uninitialized_connection (GBusType bus_type,
7345 GCancellable *cancellable,
7348 GWeakRef *singleton;
7349 GDBusConnection *ret;
7353 G_LOCK (message_bus_lock);
7354 singleton = message_bus_get_singleton (bus_type, error);
7355 if (singleton == NULL)
7358 ret = g_weak_ref_get (singleton);
7363 address = g_dbus_address_get_for_bus_sync (bus_type, cancellable, error);
7364 if (address == NULL)
7366 ret = g_object_new (G_TYPE_DBUS_CONNECTION,
7368 "flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
7369 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
7370 "exit-on-close", TRUE,
7373 g_weak_ref_set (singleton, ret);
7377 g_assert (ret != NULL);
7380 G_UNLOCK (message_bus_lock);
7384 /* May be called from any thread. Must not hold message_bus_lock. */
7386 _g_bus_get_singleton_if_exists (GBusType bus_type)
7388 GWeakRef *singleton;
7389 GDBusConnection *ret = NULL;
7391 G_LOCK (message_bus_lock);
7392 singleton = message_bus_get_singleton (bus_type, NULL);
7393 if (singleton == NULL)
7396 ret = g_weak_ref_get (singleton);
7399 G_UNLOCK (message_bus_lock);
7403 /* May be called from any thread. Must not hold message_bus_lock. */
7405 _g_bus_forget_singleton (GBusType bus_type)
7407 GWeakRef *singleton;
7409 G_LOCK (message_bus_lock);
7411 singleton = message_bus_get_singleton (bus_type, NULL);
7413 if (singleton != NULL)
7414 g_weak_ref_set (singleton, NULL);
7416 G_UNLOCK (message_bus_lock);
7421 * @bus_type: a #GBusType
7422 * @cancellable: (nullable): a #GCancellable or %NULL
7423 * @error: return location for error or %NULL
7425 * Synchronously connects to the message bus specified by @bus_type.
7426 * Note that the returned object may shared with other callers,
7427 * e.g. if two separate parts of a process calls this function with
7428 * the same @bus_type, they will share the same object.
7430 * This is a synchronous failable function. See g_bus_get() and
7431 * g_bus_get_finish() for the asynchronous version.
7433 * The returned object is a singleton, that is, shared with other
7434 * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
7435 * event that you need a private message bus connection, use
7436 * g_dbus_address_get_for_bus_sync() and
7437 * g_dbus_connection_new_for_address() with
7438 * G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT and
7439 * G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION flags.
7441 * Note that the returned #GDBusConnection object will (usually) have
7442 * the #GDBusConnection:exit-on-close property set to %TRUE.
7444 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
7445 * Free with g_object_unref().
7450 g_bus_get_sync (GBusType bus_type,
7451 GCancellable *cancellable,
7454 GDBusConnection *connection;
7456 _g_dbus_initialize ();
7458 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
7460 connection = get_uninitialized_connection (bus_type, cancellable, error);
7461 if (connection == NULL)
7464 if (!g_initable_init (G_INITABLE (connection), cancellable, error))
7466 g_object_unref (connection);
7475 bus_get_async_initable_cb (GObject *source_object,
7479 GTask *task = user_data;
7480 GError *error = NULL;
7482 if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
7486 g_assert (error != NULL);
7487 g_task_return_error (task, error);
7488 g_object_unref (source_object);
7492 g_task_return_pointer (task, source_object, g_object_unref);
7494 g_object_unref (task);
7499 * @bus_type: a #GBusType
7500 * @cancellable: (nullable): a #GCancellable or %NULL
7501 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
7502 * @user_data: the data to pass to @callback
7504 * Asynchronously connects to the message bus specified by @bus_type.
7506 * When the operation is finished, @callback will be invoked. You can
7507 * then call g_bus_get_finish() to get the result of the operation.
7509 * This is an asynchronous failable function. See g_bus_get_sync() for
7510 * the synchronous version.
7515 g_bus_get (GBusType bus_type,
7516 GCancellable *cancellable,
7517 GAsyncReadyCallback callback,
7520 GDBusConnection *connection;
7522 GError *error = NULL;
7524 _g_dbus_initialize ();
7526 task = g_task_new (NULL, cancellable, callback, user_data);
7527 g_task_set_source_tag (task, g_bus_get);
7529 connection = get_uninitialized_connection (bus_type, cancellable, &error);
7530 if (connection == NULL)
7532 g_assert (error != NULL);
7533 g_task_return_error (task, error);
7534 g_object_unref (task);
7538 g_async_initable_init_async (G_ASYNC_INITABLE (connection),
7541 bus_get_async_initable_cb,
7548 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
7550 * @error: return location for error or %NULL
7552 * Finishes an operation started with g_bus_get().
7554 * The returned object is a singleton, that is, shared with other
7555 * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
7556 * event that you need a private message bus connection, use
7557 * g_dbus_address_get_for_bus_sync() and
7558 * g_dbus_connection_new_for_address() with
7559 * G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT and
7560 * G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION flags.
7562 * Note that the returned #GDBusConnection object will (usually) have
7563 * the #GDBusConnection:exit-on-close property set to %TRUE.
7565 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
7566 * Free with g_object_unref().
7571 g_bus_get_finish (GAsyncResult *res,
7574 g_return_val_if_fail (g_task_is_valid (res, NULL), NULL);
7575 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
7577 return g_task_propagate_pointer (G_TASK (res), error);
7580 /* ---------------------------------------------------------------------------------------------------- */