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 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)
92 * - use abstract sockets in test code
93 * - right now it doesn't work, dbus-daemon(1) fails with
95 * /gdbus/connection/filter: Failed to start message bus: Failed to bind
96 * socket "/tmp/g-dbus-tests-pid-28531": Address already in use
97 * ** WARNING **: Error reading address from dbus daemon, 0 bytes read
107 #include "gdbusauth.h"
108 #include "gdbusutils.h"
109 #include "gdbusaddress.h"
110 #include "gdbusmessage.h"
111 #include "gdbusconnection.h"
112 #include "gdbuserror.h"
113 #include "gioenumtypes.h"
114 #include "gdbusintrospection.h"
115 #include "gdbusmethodinvocation.h"
116 #include "gdbusprivate.h"
117 #include "gdbusauthobserver.h"
118 #include "ginitable.h"
119 #include "gasyncinitable.h"
120 #include "giostream.h"
121 #include "gasyncresult.h"
122 #include "gsimpleasyncresult.h"
125 #include "gunixconnection.h"
126 #include "gunixfdmessage.h"
129 #include "glibintl.h"
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 an #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://git.gnome.org/browse/glib/tree/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://git.gnome.org/browse/glib/tree/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://git.gnome.org/browse/glib/tree/gio/tests/gdbus-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://git.gnome.org/browse/glib/tree/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 (1<<31)
224 /* Same as SEND_MESSAGE_FLAGS_INITIALIZING, but in GDBusCallFlags */
225 #define CALL_FLAGS_INITIALIZING (1<<31)
227 /* ---------------------------------------------------------------------------------------------------- */
231 GDestroyNotify callback
;
233 GMainContext
*context
;
234 } CallDestroyNotifyData
;
237 call_destroy_notify_data_in_idle (gpointer user_data
)
239 CallDestroyNotifyData
*data
= user_data
;
240 data
->callback (data
->user_data
);
245 call_destroy_notify_data_free (CallDestroyNotifyData
*data
)
247 if (data
->context
!= NULL
)
248 g_main_context_unref (data
->context
);
253 * call_destroy_notify: <internal>
254 * @context: (allow-none): A #GMainContext or %NULL.
255 * @callback: (allow-none): A #GDestroyNotify or %NULL.
256 * @user_data: Data to pass to @callback.
258 * Schedules @callback to run in @context.
261 call_destroy_notify (GMainContext
*context
,
262 GDestroyNotify callback
,
265 GSource
*idle_source
;
266 CallDestroyNotifyData
*data
;
268 if (callback
== NULL
)
271 data
= g_new0 (CallDestroyNotifyData
, 1);
272 data
->callback
= callback
;
273 data
->user_data
= user_data
;
274 data
->context
= context
;
275 if (data
->context
!= NULL
)
276 g_main_context_ref (data
->context
);
278 idle_source
= g_idle_source_new ();
279 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
280 g_source_set_callback (idle_source
,
281 call_destroy_notify_data_in_idle
,
283 (GDestroyNotify
) call_destroy_notify_data_free
);
284 g_source_set_name (idle_source
, "[gio] call_destroy_notify_data_in_idle");
285 g_source_attach (idle_source
, data
->context
);
286 g_source_unref (idle_source
);
292 /* ---------------------------------------------------------------------------------------------------- */
295 _g_strv_has_string (const gchar
* const *haystack
,
300 for (n
= 0; haystack
!= NULL
&& haystack
[n
] != NULL
; n
++)
302 if (g_strcmp0 (haystack
[n
], needle
) == 0)
308 /* ---------------------------------------------------------------------------------------------------- */
311 #define CONNECTION_ENSURE_LOCK(obj) do { ; } while (FALSE)
313 // TODO: for some reason this doesn't work on Windows
314 #define CONNECTION_ENSURE_LOCK(obj) do { \
315 if (G_UNLIKELY (g_mutex_trylock(&(obj)->lock))) \
317 g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
318 "CONNECTION_ENSURE_LOCK: GDBusConnection object lock is not locked"); \
323 #define CONNECTION_LOCK(obj) do { \
324 g_mutex_lock (&(obj)->lock); \
327 #define CONNECTION_UNLOCK(obj) do { \
328 g_mutex_unlock (&(obj)->lock); \
331 /* Flags in connection->atomic_flags */
333 FLAG_INITIALIZED
= 1 << 0,
334 FLAG_EXIT_ON_CLOSE
= 1 << 1,
341 * The #GDBusConnection structure contains only private data and
342 * should only be accessed using the provided API.
346 struct _GDBusConnection
349 GObject parent_instance
;
351 /* ------------------------------------------------------------------------ */
352 /* -- General object state ------------------------------------------------ */
353 /* ------------------------------------------------------------------------ */
355 /* General-purpose lock for most fields */
358 /* A lock used in the init() method of the GInitable interface - see comments
359 * in initable_init() for why a separate lock is needed.
361 * If you need both @lock and @init_lock, you must take @init_lock first.
365 /* Set (by loading the contents of /var/lib/dbus/machine-id) the first time
366 * someone calls org.freedesktop.DBus.Peer.GetMachineId(). Protected by @lock.
370 /* The underlying stream used for communication
371 * Read-only after initable_init(), so it may be read if you either
372 * hold @init_lock or check for initialization first.
376 /* The object used for authentication (if any).
377 * Read-only after initable_init(), so it may be read if you either
378 * hold @init_lock or check for initialization first.
382 /* Last serial used. Protected by @lock. */
385 /* The object used to send/receive messages.
386 * Read-only after initable_init(), so it may be read if you either
387 * hold @init_lock or check for initialization first.
391 /* If connected to a message bus, this contains the unique name assigned to
392 * us by the bus (e.g. ":1.42").
393 * Read-only after initable_init(), so it may be read if you either
394 * hold @init_lock or check for initialization first.
396 gchar
*bus_unique_name
;
398 /* The GUID returned by the other side if we authenticed as a client or
399 * the GUID to use if authenticating as a server.
400 * Read-only after initable_init(), so it may be read if you either
401 * hold @init_lock or check for initialization first.
405 /* FLAG_INITIALIZED is set exactly when initable_init() has finished running.
406 * Inspect @initialization_error to see whether it succeeded or failed.
408 * FLAG_EXIT_ON_CLOSE is the exit-on-close property.
410 * FLAG_CLOSED is the closed property. It may be read at any time, but
411 * may only be written while holding @lock.
413 volatile gint atomic_flags
;
415 /* If the connection could not be established during initable_init(),
416 * this GError will be set.
417 * Read-only after initable_init(), so it may be read if you either
418 * hold @init_lock or check for initialization first.
420 GError
*initialization_error
;
422 /* The result of g_main_context_ref_thread_default() when the object
423 * was created (the GObject _init() function) - this is used for delivery
424 * of the :closed GObject signal.
426 * Only set in the GObject init function, so no locks are needed.
428 GMainContext
*main_context_at_construction
;
430 /* Read-only construct properties, no locks needed */
432 GDBusConnectionFlags flags
;
434 /* Map used for managing method replies, protected by @lock */
435 GHashTable
*map_method_serial_to_send_message_data
; /* guint32 -> SendMessageData* */
437 /* Maps used for managing signal subscription, protected by @lock */
438 GHashTable
*map_rule_to_signal_data
; /* match rule (gchar*) -> SignalData */
439 GHashTable
*map_id_to_signal_data
; /* id (guint) -> SignalData */
440 GHashTable
*map_sender_unique_name_to_signal_data_array
; /* unique sender (gchar*) -> GPtrArray* of SignalData */
442 /* Maps used for managing exported objects and subtrees,
445 GHashTable
*map_object_path_to_eo
; /* gchar* -> ExportedObject* */
446 GHashTable
*map_id_to_ei
; /* guint -> ExportedInterface* */
447 GHashTable
*map_object_path_to_es
; /* gchar* -> ExportedSubtree* */
448 GHashTable
*map_id_to_es
; /* guint -> ExportedSubtree* */
450 /* Map used for storing last used serials for each thread, protected by @lock */
451 GHashTable
*map_thread_to_last_serial
;
453 /* Structure used for message filters, protected by @lock */
456 /* Capabilities negotiated during authentication
457 * Read-only after initable_init(), so it may be read without holding a
458 * lock, if you check for initialization first.
460 GDBusCapabilityFlags capabilities
;
462 /* Protected by @init_lock */
463 GDBusAuthObserver
*authentication_observer
;
465 /* Read-only after initable_init(), so it may be read if you either
466 * hold @init_lock or check for initialization first.
468 GCredentials
*credentials
;
470 /* set to TRUE when finalizing */
474 typedef struct ExportedObject ExportedObject
;
475 static void exported_object_free (ExportedObject
*eo
);
477 typedef struct ExportedSubtree ExportedSubtree
;
478 static void exported_subtree_free (ExportedSubtree
*es
);
496 PROP_CAPABILITY_FLAGS
,
497 PROP_AUTHENTICATION_OBSERVER
,
500 static void distribute_signals (GDBusConnection
*connection
,
501 GDBusMessage
*message
);
503 static void distribute_method_call (GDBusConnection
*connection
,
504 GDBusMessage
*message
);
506 static gboolean
handle_generic_unlocked (GDBusConnection
*connection
,
507 GDBusMessage
*message
);
510 static void purge_all_signal_subscriptions (GDBusConnection
*connection
);
511 static void purge_all_filters (GDBusConnection
*connection
);
513 static void schedule_method_call (GDBusConnection
*connection
,
514 GDBusMessage
*message
,
515 guint registration_id
,
516 guint subtree_registration_id
,
517 const GDBusInterfaceInfo
*interface_info
,
518 const GDBusMethodInfo
*method_info
,
519 const GDBusPropertyInfo
*property_info
,
520 GVariant
*parameters
,
521 const GDBusInterfaceVTable
*vtable
,
522 GMainContext
*main_context
,
525 #define _G_ENSURE_LOCK(name) do { \
526 if (G_UNLIKELY (G_TRYLOCK(name))) \
528 g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
529 "_G_ENSURE_LOCK: Lock '" #name "' is not locked"); \
533 static guint signals[LAST_SIGNAL] = { 0 };
535 static void initable_iface_init (GInitableIface
*initable_iface
);
536 static void async_initable_iface_init (GAsyncInitableIface
*async_initable_iface
);
538 G_DEFINE_TYPE_WITH_CODE (GDBusConnection
, g_dbus_connection
, G_TYPE_OBJECT
,
539 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE
, initable_iface_init
)
540 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE
, async_initable_iface_init
)
544 * Check that all members of @connection that can only be accessed after
545 * the connection is initialized can safely be accessed. If not,
546 * log a critical warning. This function is a memory barrier.
548 * Returns: %TRUE if initialized
551 check_initialized (GDBusConnection
*connection
)
553 /* The access to @atomic_flags isn't conditional, so that this function
554 * provides a memory barrier for thread-safety even if checks are disabled.
555 * (If you don't want this stricter guarantee, you can call
556 * g_return_if_fail (check_initialized (c)).)
558 * This isn't strictly necessary now that we've decided use of an
559 * uninitialized GDBusConnection is undefined behaviour, but it seems
560 * better to be as deterministic as is feasible.
562 * (Anything that could suffer a crash from seeing undefined values
563 * must have a race condition - thread A initializes the connection while
564 * thread B calls a method without initialization, hoping that thread A will
565 * win the race - so its behaviour is undefined anyway.)
567 gint flags
= g_atomic_int_get (&connection
->atomic_flags
);
569 g_return_val_if_fail (flags
& FLAG_INITIALIZED
, FALSE
);
571 /* We can safely access this, due to the memory barrier above */
572 g_return_val_if_fail (connection
->initialization_error
== NULL
, FALSE
);
578 MAY_BE_UNINITIALIZED
= (1<<1)
579 } CheckUnclosedFlags
;
582 * Check the same thing as check_initialized(), and also that the
583 * connection is not closed. If the connection is uninitialized,
584 * raise a critical warning (it's programmer error); if it's closed,
585 * raise a recoverable GError (it's a runtime error).
587 * This function is a memory barrier.
589 * Returns: %TRUE if initialized and not closed
592 check_unclosed (GDBusConnection
*connection
,
593 CheckUnclosedFlags check
,
596 /* check_initialized() is effectively inlined, so we don't waste time
597 * doing two memory barriers
599 gint flags
= g_atomic_int_get (&connection
->atomic_flags
);
601 if (!(check
& MAY_BE_UNINITIALIZED
))
603 g_return_val_if_fail (flags
& FLAG_INITIALIZED
, FALSE
);
604 g_return_val_if_fail (connection
->initialization_error
== NULL
, FALSE
);
607 if (flags
& FLAG_CLOSED
)
609 g_set_error_literal (error
,
612 _("The connection is closed"));
619 static GHashTable
*alive_connections
= NULL
;
622 g_dbus_connection_dispose (GObject
*object
)
624 GDBusConnection
*connection
= G_DBUS_CONNECTION (object
);
626 G_LOCK (message_bus_lock
);
627 CONNECTION_LOCK (connection
);
628 if (connection
->worker
!= NULL
)
630 _g_dbus_worker_stop (connection
->worker
);
631 connection
->worker
= NULL
;
632 if (alive_connections
!= NULL
)
633 g_warn_if_fail (g_hash_table_remove (alive_connections
, connection
));
637 if (alive_connections
!= NULL
)
638 g_warn_if_fail (g_hash_table_lookup (alive_connections
, connection
) == NULL
);
640 CONNECTION_UNLOCK (connection
);
641 G_UNLOCK (message_bus_lock
);
643 if (G_OBJECT_CLASS (g_dbus_connection_parent_class
)->dispose
!= NULL
)
644 G_OBJECT_CLASS (g_dbus_connection_parent_class
)->dispose (object
);
648 g_dbus_connection_finalize (GObject
*object
)
650 GDBusConnection
*connection
= G_DBUS_CONNECTION (object
);
652 connection
->finalizing
= TRUE
;
654 purge_all_signal_subscriptions (connection
);
656 purge_all_filters (connection
);
657 g_ptr_array_unref (connection
->filters
);
659 if (connection
->authentication_observer
!= NULL
)
660 g_object_unref (connection
->authentication_observer
);
662 if (connection
->auth
!= NULL
)
663 g_object_unref (connection
->auth
);
665 if (connection
->credentials
)
666 g_object_unref (connection
->credentials
);
668 if (connection
->stream
!= NULL
)
670 g_object_unref (connection
->stream
);
671 connection
->stream
= NULL
;
674 g_free (connection
->address
);
676 g_free (connection
->guid
);
677 g_free (connection
->bus_unique_name
);
679 if (connection
->initialization_error
!= NULL
)
680 g_error_free (connection
->initialization_error
);
682 g_hash_table_unref (connection
->map_method_serial_to_send_message_data
);
684 g_hash_table_unref (connection
->map_rule_to_signal_data
);
685 g_hash_table_unref (connection
->map_id_to_signal_data
);
686 g_hash_table_unref (connection
->map_sender_unique_name_to_signal_data_array
);
688 g_hash_table_unref (connection
->map_id_to_ei
);
689 g_hash_table_unref (connection
->map_object_path_to_eo
);
690 g_hash_table_unref (connection
->map_id_to_es
);
691 g_hash_table_unref (connection
->map_object_path_to_es
);
693 g_hash_table_unref (connection
->map_thread_to_last_serial
);
695 g_main_context_unref (connection
->main_context_at_construction
);
697 g_free (connection
->machine_id
);
699 g_mutex_clear (&connection
->init_lock
);
700 g_mutex_clear (&connection
->lock
);
702 G_OBJECT_CLASS (g_dbus_connection_parent_class
)->finalize (object
);
705 /* called in any user thread, with the connection's lock not held */
707 g_dbus_connection_get_property (GObject
*object
,
712 GDBusConnection
*connection
= G_DBUS_CONNECTION (object
);
717 g_value_set_object (value
, g_dbus_connection_get_stream (connection
));
721 g_value_set_string (value
, g_dbus_connection_get_guid (connection
));
724 case PROP_UNIQUE_NAME
:
725 g_value_set_string (value
, g_dbus_connection_get_unique_name (connection
));
729 g_value_set_boolean (value
, g_dbus_connection_is_closed (connection
));
732 case PROP_EXIT_ON_CLOSE
:
733 g_value_set_boolean (value
, g_dbus_connection_get_exit_on_close (connection
));
736 case PROP_CAPABILITY_FLAGS
:
737 g_value_set_flags (value
, g_dbus_connection_get_capabilities (connection
));
741 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
746 /* called in any user thread, with the connection's lock not held */
748 g_dbus_connection_set_property (GObject
*object
,
753 GDBusConnection
*connection
= G_DBUS_CONNECTION (object
);
758 connection
->stream
= g_value_dup_object (value
);
762 connection
->guid
= g_value_dup_string (value
);
766 connection
->address
= g_value_dup_string (value
);
770 connection
->flags
= g_value_get_flags (value
);
773 case PROP_EXIT_ON_CLOSE
:
774 g_dbus_connection_set_exit_on_close (connection
, g_value_get_boolean (value
));
777 case PROP_AUTHENTICATION_OBSERVER
:
778 connection
->authentication_observer
= g_value_dup_object (value
);
782 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
787 /* Base-class implementation of GDBusConnection::closed.
789 * Called in a user thread, by the main context that was thread-default when
790 * the object was constructed.
793 g_dbus_connection_real_closed (GDBusConnection
*connection
,
794 gboolean remote_peer_vanished
,
797 gint flags
= g_atomic_int_get (&connection
->atomic_flags
);
799 /* Because atomic int access is a memory barrier, we can safely read
800 * initialization_error without a lock, as long as we do it afterwards.
802 if (remote_peer_vanished
&&
803 (flags
& FLAG_EXIT_ON_CLOSE
) != 0 &&
804 (flags
& FLAG_INITIALIZED
) != 0 &&
805 connection
->initialization_error
== NULL
)
809 g_printerr ("%s: Remote peer vanished with error: %s (%s, %d). Exiting.\n",
812 g_quark_to_string (error
->domain
), error
->code
);
816 g_printerr ("%s: Remote peer vanished. Exiting.\n", G_STRFUNC
);
823 g_dbus_connection_class_init (GDBusConnectionClass
*klass
)
825 GObjectClass
*gobject_class
;
827 gobject_class
= G_OBJECT_CLASS (klass
);
829 gobject_class
->finalize
= g_dbus_connection_finalize
;
830 gobject_class
->dispose
= g_dbus_connection_dispose
;
831 gobject_class
->set_property
= g_dbus_connection_set_property
;
832 gobject_class
->get_property
= g_dbus_connection_get_property
;
834 klass
->closed
= g_dbus_connection_real_closed
;
837 * GDBusConnection:stream:
839 * The underlying #GIOStream used for I/O.
841 * If this is passed on construction and is a #GSocketConnection,
842 * then the corresponding #GSocket will be put into non-blocking mode.
844 * While the #GDBusConnection is active, it will interact with this
845 * stream from a worker thread, so it is not safe to interact with
846 * the stream directly.
850 g_object_class_install_property (gobject_class
,
852 g_param_spec_object ("stream",
854 P_("The underlying streams used for I/O"),
858 G_PARAM_CONSTRUCT_ONLY
|
859 G_PARAM_STATIC_NAME
|
860 G_PARAM_STATIC_BLURB
|
861 G_PARAM_STATIC_NICK
));
864 * GDBusConnection:address:
866 * A D-Bus address specifying potential endpoints that can be used
867 * when establishing the connection.
871 g_object_class_install_property (gobject_class
,
873 g_param_spec_string ("address",
875 P_("D-Bus address specifying potential socket endpoints"),
878 G_PARAM_CONSTRUCT_ONLY
|
879 G_PARAM_STATIC_NAME
|
880 G_PARAM_STATIC_BLURB
|
881 G_PARAM_STATIC_NICK
));
884 * GDBusConnection:flags:
886 * Flags from the #GDBusConnectionFlags enumeration.
890 g_object_class_install_property (gobject_class
,
892 g_param_spec_flags ("flags",
895 G_TYPE_DBUS_CONNECTION_FLAGS
,
896 G_DBUS_CONNECTION_FLAGS_NONE
,
898 G_PARAM_CONSTRUCT_ONLY
|
899 G_PARAM_STATIC_NAME
|
900 G_PARAM_STATIC_BLURB
|
901 G_PARAM_STATIC_NICK
));
904 * GDBusConnection:guid:
906 * The GUID of the peer performing the role of server when
909 * If you are constructing a #GDBusConnection and pass
910 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER in the
911 * #GDBusConnection:flags property then you MUST also set this
912 * property to a valid guid.
914 * If you are constructing a #GDBusConnection and pass
915 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT in the
916 * #GDBusConnection:flags property you will be able to read the GUID
917 * of the other peer here after the connection has been successfully
922 g_object_class_install_property (gobject_class
,
924 g_param_spec_string ("guid",
926 P_("GUID of the server peer"),
930 G_PARAM_CONSTRUCT_ONLY
|
931 G_PARAM_STATIC_NAME
|
932 G_PARAM_STATIC_BLURB
|
933 G_PARAM_STATIC_NICK
));
936 * GDBusConnection:unique-name:
938 * The unique name as assigned by the message bus or %NULL if the
939 * connection is not open or not a message bus connection.
943 g_object_class_install_property (gobject_class
,
945 g_param_spec_string ("unique-name",
947 P_("Unique name of bus connection"),
950 G_PARAM_STATIC_NAME
|
951 G_PARAM_STATIC_BLURB
|
952 G_PARAM_STATIC_NICK
));
955 * GDBusConnection:closed:
957 * A boolean specifying whether the connection has been closed.
961 g_object_class_install_property (gobject_class
,
963 g_param_spec_boolean ("closed",
965 P_("Whether the connection is closed"),
968 G_PARAM_STATIC_NAME
|
969 G_PARAM_STATIC_BLURB
|
970 G_PARAM_STATIC_NICK
));
973 * GDBusConnection:exit-on-close:
975 * A boolean specifying whether the process will be terminated (by
976 * calling `raise(SIGTERM)`) if the connection is closed by the
979 * Note that #GDBusConnection objects returned by g_bus_get_finish()
980 * and g_bus_get_sync() will (usually) have this property set to %TRUE.
984 g_object_class_install_property (gobject_class
,
986 g_param_spec_boolean ("exit-on-close",
988 P_("Whether the process is terminated when the connection is closed"),
992 G_PARAM_STATIC_NAME
|
993 G_PARAM_STATIC_BLURB
|
994 G_PARAM_STATIC_NICK
));
997 * GDBusConnection:capabilities:
999 * Flags from the #GDBusCapabilityFlags enumeration
1000 * representing connection features negotiated with the other peer.
1004 g_object_class_install_property (gobject_class
,
1005 PROP_CAPABILITY_FLAGS
,
1006 g_param_spec_flags ("capabilities",
1009 G_TYPE_DBUS_CAPABILITY_FLAGS
,
1010 G_DBUS_CAPABILITY_FLAGS_NONE
,
1012 G_PARAM_STATIC_NAME
|
1013 G_PARAM_STATIC_BLURB
|
1014 G_PARAM_STATIC_NICK
));
1017 * GDBusConnection:authentication-observer:
1019 * A #GDBusAuthObserver object to assist in the authentication process or %NULL.
1023 g_object_class_install_property (gobject_class
,
1024 PROP_AUTHENTICATION_OBSERVER
,
1025 g_param_spec_object ("authentication-observer",
1026 P_("Authentication Observer"),
1027 P_("Object used to assist in the authentication process"),
1028 G_TYPE_DBUS_AUTH_OBSERVER
,
1030 G_PARAM_CONSTRUCT_ONLY
|
1031 G_PARAM_STATIC_NAME
|
1032 G_PARAM_STATIC_BLURB
|
1033 G_PARAM_STATIC_NICK
));
1036 * GDBusConnection::closed:
1037 * @connection: the #GDBusConnection emitting the signal
1038 * @remote_peer_vanished: %TRUE if @connection is closed because the
1039 * remote peer closed its end of the connection
1040 * @error: (allow-none): a #GError with more details about the event or %NULL
1042 * Emitted when the connection is closed.
1044 * The cause of this event can be
1046 * - If g_dbus_connection_close() is called. In this case
1047 * @remote_peer_vanished is set to %FALSE and @error is %NULL.
1049 * - If the remote peer closes the connection. In this case
1050 * @remote_peer_vanished is set to %TRUE and @error is set.
1052 * - If the remote peer sends invalid or malformed data. In this
1053 * case @remote_peer_vanished is set to %FALSE and @error is set.
1055 * Upon receiving this signal, you should give up your reference to
1056 * @connection. You are guaranteed that this signal is emitted only
1061 signals
[CLOSED_SIGNAL
] = g_signal_new ("closed",
1062 G_TYPE_DBUS_CONNECTION
,
1064 G_STRUCT_OFFSET (GDBusConnectionClass
, closed
),
1075 g_dbus_connection_init (GDBusConnection
*connection
)
1077 g_mutex_init (&connection
->lock
);
1078 g_mutex_init (&connection
->init_lock
);
1080 connection
->map_method_serial_to_send_message_data
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
1082 connection
->map_rule_to_signal_data
= g_hash_table_new (g_str_hash
,
1084 connection
->map_id_to_signal_data
= g_hash_table_new (g_direct_hash
,
1086 connection
->map_sender_unique_name_to_signal_data_array
= g_hash_table_new_full (g_str_hash
,
1089 (GDestroyNotify
) g_ptr_array_unref
);
1091 connection
->map_object_path_to_eo
= g_hash_table_new_full (g_str_hash
,
1094 (GDestroyNotify
) exported_object_free
);
1096 connection
->map_id_to_ei
= g_hash_table_new (g_direct_hash
,
1099 connection
->map_object_path_to_es
= g_hash_table_new_full (g_str_hash
,
1102 (GDestroyNotify
) exported_subtree_free
);
1104 connection
->map_id_to_es
= g_hash_table_new (g_direct_hash
,
1107 connection
->map_thread_to_last_serial
= g_hash_table_new (g_direct_hash
,
1110 connection
->main_context_at_construction
= g_main_context_ref_thread_default ();
1112 connection
->filters
= g_ptr_array_new ();
1116 * g_dbus_connection_get_stream:
1117 * @connection: a #GDBusConnection
1119 * Gets the underlying stream used for IO.
1121 * While the #GDBusConnection is active, it will interact with this
1122 * stream from a worker thread, so it is not safe to interact with
1123 * the stream directly.
1125 * Returns: (transfer none): the stream used for IO
1130 g_dbus_connection_get_stream (GDBusConnection
*connection
)
1132 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
1134 /* do not use g_return_val_if_fail(), we want the memory barrier */
1135 if (!check_initialized (connection
))
1138 return connection
->stream
;
1142 * g_dbus_connection_start_message_processing:
1143 * @connection: a #GDBusConnection
1145 * If @connection was created with
1146 * %G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, this method
1147 * starts processing messages. Does nothing on if @connection wasn't
1148 * created with this flag or if the method has already been called.
1153 g_dbus_connection_start_message_processing (GDBusConnection
*connection
)
1155 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
1157 /* do not use g_return_val_if_fail(), we want the memory barrier */
1158 if (!check_initialized (connection
))
1161 g_assert (connection
->worker
!= NULL
);
1162 _g_dbus_worker_unfreeze (connection
->worker
);
1166 * g_dbus_connection_is_closed:
1167 * @connection: a #GDBusConnection
1169 * Gets whether @connection is closed.
1171 * Returns: %TRUE if the connection is closed, %FALSE otherwise
1176 g_dbus_connection_is_closed (GDBusConnection
*connection
)
1180 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1182 flags
= g_atomic_int_get (&connection
->atomic_flags
);
1184 return (flags
& FLAG_CLOSED
) ? TRUE
: FALSE
;
1188 * g_dbus_connection_get_capabilities:
1189 * @connection: a #GDBusConnection
1191 * Gets the capabilities negotiated with the remote peer
1193 * Returns: zero or more flags from the #GDBusCapabilityFlags enumeration
1197 GDBusCapabilityFlags
1198 g_dbus_connection_get_capabilities (GDBusConnection
*connection
)
1200 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), G_DBUS_CAPABILITY_FLAGS_NONE
);
1202 /* do not use g_return_val_if_fail(), we want the memory barrier */
1203 if (!check_initialized (connection
))
1204 return G_DBUS_CAPABILITY_FLAGS_NONE
;
1206 return connection
->capabilities
;
1209 /* ---------------------------------------------------------------------------------------------------- */
1211 /* Called in a temporary thread without holding locks. */
1213 flush_in_thread_func (GSimpleAsyncResult
*res
,
1215 GCancellable
*cancellable
)
1220 if (!g_dbus_connection_flush_sync (G_DBUS_CONNECTION (object
),
1223 g_simple_async_result_take_error (res
, error
);
1227 * g_dbus_connection_flush:
1228 * @connection: a #GDBusConnection
1229 * @cancellable: (allow-none): a #GCancellable or %NULL
1230 * @callback: (allow-none): a #GAsyncReadyCallback to call when the
1231 * request is satisfied or %NULL if you don't care about the result
1232 * @user_data: The data to pass to @callback
1234 * Asynchronously flushes @connection, that is, writes all queued
1235 * outgoing message to the transport and then flushes the transport
1236 * (using g_output_stream_flush_async()). This is useful in programs
1237 * that wants to emit a D-Bus signal and then exit immediately. Without
1238 * flushing the connection, there is no guaranteed that the message has
1239 * been sent to the networking buffers in the OS kernel.
1241 * This is an asynchronous method. When the operation is finished,
1242 * @callback will be invoked in the
1243 * [thread-default main context][g-main-context-push-thread-default]
1244 * of the thread you are calling this method from. You can
1245 * then call g_dbus_connection_flush_finish() to get the result of the
1246 * operation. See g_dbus_connection_flush_sync() for the synchronous
1252 g_dbus_connection_flush (GDBusConnection
*connection
,
1253 GCancellable
*cancellable
,
1254 GAsyncReadyCallback callback
,
1257 GSimpleAsyncResult
*simple
;
1259 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
1261 simple
= g_simple_async_result_new (G_OBJECT (connection
),
1264 g_dbus_connection_flush
);
1265 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
1266 g_simple_async_result_run_in_thread (simple
,
1267 flush_in_thread_func
,
1270 g_object_unref (simple
);
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 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (res
);
1296 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1297 g_return_val_if_fail (G_IS_ASYNC_RESULT (res
), FALSE
);
1298 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
1300 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_dbus_connection_flush
);
1302 if (g_simple_async_result_propagate_error (simple
, error
))
1312 * g_dbus_connection_flush_sync:
1313 * @connection: a #GDBusConnection
1314 * @cancellable: (allow-none): a #GCancellable or %NULL
1315 * @error: return location for error or %NULL
1317 * Synchronously flushes @connection. The calling thread is blocked
1318 * until this is done. See g_dbus_connection_flush() for the
1319 * asynchronous version of this method and more details about what it
1322 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1327 g_dbus_connection_flush_sync (GDBusConnection
*connection
,
1328 GCancellable
*cancellable
,
1333 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1334 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
1338 /* This is only a best-effort attempt to see whether the connection is
1339 * closed, so it doesn't need the lock. If the connection closes just
1340 * after this check, but before scheduling the flush operation, the
1341 * result will be more or less the same as if the connection closed while
1342 * the flush operation was pending - it'll fail with either CLOSED or
1345 if (!check_unclosed (connection
, 0, error
))
1348 g_assert (connection
->worker
!= NULL
);
1350 ret
= _g_dbus_worker_flush_sync (connection
->worker
,
1358 /* ---------------------------------------------------------------------------------------------------- */
1362 GDBusConnection
*connection
;
1364 gboolean remote_peer_vanished
;
1368 emit_closed_data_free (EmitClosedData
*data
)
1370 g_object_unref (data
->connection
);
1371 if (data
->error
!= NULL
)
1372 g_error_free (data
->error
);
1376 /* Called in a user thread that has acquired the main context that was
1377 * thread-default when the object was constructed
1380 emit_closed_in_idle (gpointer user_data
)
1382 EmitClosedData
*data
= user_data
;
1385 g_object_notify (G_OBJECT (data
->connection
), "closed");
1386 g_signal_emit (data
->connection
,
1387 signals
[CLOSED_SIGNAL
],
1389 data
->remote_peer_vanished
,
1395 /* Can be called from any thread, must hold lock.
1396 * FLAG_CLOSED must already have been set.
1399 schedule_closed_unlocked (GDBusConnection
*connection
,
1400 gboolean remote_peer_vanished
,
1403 GSource
*idle_source
;
1404 EmitClosedData
*data
;
1406 CONNECTION_ENSURE_LOCK (connection
);
1408 data
= g_new0 (EmitClosedData
, 1);
1409 data
->connection
= g_object_ref (connection
);
1410 data
->remote_peer_vanished
= remote_peer_vanished
;
1411 data
->error
= error
!= NULL
? g_error_copy (error
) : NULL
;
1413 idle_source
= g_idle_source_new ();
1414 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
1415 g_source_set_callback (idle_source
,
1416 emit_closed_in_idle
,
1418 (GDestroyNotify
) emit_closed_data_free
);
1419 g_source_set_name (idle_source
, "[gio] emit_closed_in_idle");
1420 g_source_attach (idle_source
, connection
->main_context_at_construction
);
1421 g_source_unref (idle_source
);
1424 /* ---------------------------------------------------------------------------------------------------- */
1427 * g_dbus_connection_close:
1428 * @connection: a #GDBusConnection
1429 * @cancellable: (allow-none): a #GCancellable or %NULL
1430 * @callback: (allow-none): a #GAsyncReadyCallback to call when the request is
1431 * satisfied or %NULL if you don't care about the result
1432 * @user_data: The data to pass to @callback
1434 * Closes @connection. Note that this never causes the process to
1435 * exit (this might only happen if the other end of a shared message
1436 * bus connection disconnects, see #GDBusConnection:exit-on-close).
1438 * Once the connection is closed, operations such as sending a message
1439 * will return with the error %G_IO_ERROR_CLOSED. Closing a connection
1440 * will not automatically flush the connection so queued messages may
1441 * be lost. Use g_dbus_connection_flush() if you need such guarantees.
1443 * If @connection is already closed, this method fails with
1444 * %G_IO_ERROR_CLOSED.
1446 * When @connection has been closed, the #GDBusConnection::closed
1447 * signal is emitted in the
1448 * [thread-default main context][g-main-context-push-thread-default]
1449 * of the thread that @connection was constructed in.
1451 * This is an asynchronous method. When the operation is finished,
1452 * @callback will be invoked in the
1453 * [thread-default main context][g-main-context-push-thread-default]
1454 * of the thread you are calling this method from. You can
1455 * then call g_dbus_connection_close_finish() to get the result of the
1456 * operation. See g_dbus_connection_close_sync() for the synchronous
1462 g_dbus_connection_close (GDBusConnection
*connection
,
1463 GCancellable
*cancellable
,
1464 GAsyncReadyCallback callback
,
1467 GSimpleAsyncResult
*simple
;
1469 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
1471 /* do not use g_return_val_if_fail(), we want the memory barrier */
1472 if (!check_initialized (connection
))
1475 g_assert (connection
->worker
!= NULL
);
1477 simple
= g_simple_async_result_new (G_OBJECT (connection
),
1480 g_dbus_connection_close
);
1481 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
1482 _g_dbus_worker_close (connection
->worker
, cancellable
, simple
);
1483 g_object_unref (simple
);
1487 * g_dbus_connection_close_finish:
1488 * @connection: a #GDBusConnection
1489 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
1490 * to g_dbus_connection_close()
1491 * @error: return location for error or %NULL
1493 * Finishes an operation started with g_dbus_connection_close().
1495 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1500 g_dbus_connection_close_finish (GDBusConnection
*connection
,
1504 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (res
);
1509 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1510 g_return_val_if_fail (G_IS_ASYNC_RESULT (res
), FALSE
);
1511 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
1513 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_dbus_connection_close
);
1515 if (g_simple_async_result_propagate_error (simple
, error
))
1526 GAsyncResult
*result
;
1529 /* Can be called by any thread, without the connection lock */
1531 sync_close_cb (GObject
*source_object
,
1535 SyncCloseData
*data
= user_data
;
1537 data
->result
= g_object_ref (res
);
1538 g_main_loop_quit (data
->loop
);
1542 * g_dbus_connection_close_sync:
1543 * @connection: a #GDBusConnection
1544 * @cancellable: (allow-none): a #GCancellable or %NULL
1545 * @error: return location for error or %NULL
1547 * Synchronously closees @connection. The calling thread is blocked
1548 * until this is done. See g_dbus_connection_close() for the
1549 * asynchronous version of this method and more details about what it
1552 * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
1557 g_dbus_connection_close_sync (GDBusConnection
*connection
,
1558 GCancellable
*cancellable
,
1563 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1564 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
1568 if (check_unclosed (connection
, 0, error
))
1570 GMainContext
*context
;
1573 context
= g_main_context_new ();
1574 g_main_context_push_thread_default (context
);
1575 data
.loop
= g_main_loop_new (context
, TRUE
);
1578 g_dbus_connection_close (connection
, cancellable
, sync_close_cb
, &data
);
1579 g_main_loop_run (data
.loop
);
1580 ret
= g_dbus_connection_close_finish (connection
, data
.result
, error
);
1582 g_object_unref (data
.result
);
1583 g_main_loop_unref (data
.loop
);
1584 g_main_context_pop_thread_default (context
);
1585 g_main_context_unref (context
);
1591 /* ---------------------------------------------------------------------------------------------------- */
1594 * g_dbus_connection_get_last_serial:
1595 * @connection: a #GDBusConnection
1597 * Retrieves the last serial number assigned to a #GDBusMessage on
1598 * the current thread. This includes messages sent via both low-level
1599 * API such as g_dbus_connection_send_message() as well as
1600 * high-level API such as g_dbus_connection_emit_signal(),
1601 * g_dbus_connection_call() or g_dbus_proxy_call().
1603 * Returns: the last used serial or zero when no message has been sent
1604 * within the current thread
1609 g_dbus_connection_get_last_serial (GDBusConnection
*connection
)
1613 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), 0);
1615 CONNECTION_LOCK (connection
);
1616 ret
= GPOINTER_TO_UINT (g_hash_table_lookup (connection
->map_thread_to_last_serial
,
1618 CONNECTION_UNLOCK (connection
);
1623 /* ---------------------------------------------------------------------------------------------------- */
1625 /* Can be called by any thread, with the connection lock held */
1627 g_dbus_connection_send_message_unlocked (GDBusConnection
*connection
,
1628 GDBusMessage
*message
,
1629 GDBusSendMessageFlags flags
,
1630 volatile guint32
*out_serial
,
1635 guint32 serial_to_use
;
1638 CONNECTION_ENSURE_LOCK (connection
);
1640 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1641 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message
), FALSE
);
1643 /* TODO: check all necessary headers are present */
1648 if (out_serial
!= NULL
)
1651 /* If we're in initable_init(), don't check for being initialized, to avoid
1652 * chicken-and-egg problems. initable_init() is responsible for setting up
1653 * our prerequisites (mainly connection->worker), and only calling us
1654 * from its own thread (so no memory barrier is needed).
1656 if (!check_unclosed (connection
,
1657 (flags
& SEND_MESSAGE_FLAGS_INITIALIZING
) ? MAY_BE_UNINITIALIZED
: 0,
1661 blob
= g_dbus_message_to_blob (message
,
1663 connection
->capabilities
,
1668 if (flags
& G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
)
1669 serial_to_use
= g_dbus_message_get_serial (message
);
1671 serial_to_use
= ++connection
->last_serial
; /* TODO: handle overflow */
1676 ((guint32
*) blob
)[2] = GUINT32_TO_LE (serial_to_use
);
1679 ((guint32
*) blob
)[2] = GUINT32_TO_BE (serial_to_use
);
1682 g_assert_not_reached ();
1687 g_printerr ("Writing message of %" G_GSIZE_FORMAT
" bytes (serial %d) on %p:\n",
1688 blob_size
, serial_to_use
, connection
);
1689 g_printerr ("----\n");
1690 hexdump (blob
, blob_size
);
1691 g_printerr ("----\n");
1694 /* TODO: use connection->auth to encode the blob */
1696 if (out_serial
!= NULL
)
1697 *out_serial
= serial_to_use
;
1699 /* store used serial for the current thread */
1700 /* TODO: watch the thread disposal and remove associated record
1702 * - see https://bugzilla.gnome.org/show_bug.cgi?id=676825#c7
1704 g_hash_table_replace (connection
->map_thread_to_last_serial
,
1706 GUINT_TO_POINTER (serial_to_use
));
1708 if (!(flags
& G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
))
1709 g_dbus_message_set_serial (message
, serial_to_use
);
1711 g_dbus_message_lock (message
);
1712 _g_dbus_worker_send_message (connection
->worker
,
1716 blob
= NULL
; /* since _g_dbus_worker_send_message() steals the blob */
1727 * g_dbus_connection_send_message:
1728 * @connection: a #GDBusConnection
1729 * @message: a #GDBusMessage
1730 * @flags: flags affecting how the message is sent
1731 * @out_serial: (out) (allow-none): return location for serial number assigned
1732 * to @message when sending it or %NULL
1733 * @error: Return location for error or %NULL
1735 * Asynchronously sends @message to the peer represented by @connection.
1737 * Unless @flags contain the
1738 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
1739 * will be assigned by @connection and set on @message via
1740 * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
1741 * serial number used will be written to this location prior to
1742 * submitting the message to the underlying transport.
1744 * If @connection is closed then the operation will fail with
1745 * %G_IO_ERROR_CLOSED. If @message is not well-formed,
1746 * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
1748 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
1749 * for an example of how to use this low-level API to send and receive
1750 * UNIX file descriptors.
1752 * Note that @message must be unlocked, unless @flags contain the
1753 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
1755 * Returns: %TRUE if the message was well-formed and queued for
1756 * transmission, %FALSE if @error is set
1761 g_dbus_connection_send_message (GDBusConnection
*connection
,
1762 GDBusMessage
*message
,
1763 GDBusSendMessageFlags flags
,
1764 volatile guint32
*out_serial
,
1769 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
1770 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message
), FALSE
);
1771 g_return_val_if_fail ((flags
& G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
) || !g_dbus_message_get_locked (message
), FALSE
);
1772 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
1774 CONNECTION_LOCK (connection
);
1775 ret
= g_dbus_connection_send_message_unlocked (connection
, message
, flags
, out_serial
, error
);
1776 CONNECTION_UNLOCK (connection
);
1780 /* ---------------------------------------------------------------------------------------------------- */
1784 volatile gint ref_count
;
1785 GDBusConnection
*connection
;
1787 GSimpleAsyncResult
*simple
;
1789 GMainContext
*main_context
;
1791 GCancellable
*cancellable
;
1793 gulong cancellable_handler_id
;
1795 GSource
*timeout_source
;
1800 /* Can be called from any thread with or without lock held */
1801 static SendMessageData
*
1802 send_message_data_ref (SendMessageData
*data
)
1804 g_atomic_int_inc (&data
->ref_count
);
1808 /* Can be called from any thread with or without lock held */
1810 send_message_data_unref (SendMessageData
*data
)
1812 if (g_atomic_int_dec_and_test (&data
->ref_count
))
1814 g_assert (data
->timeout_source
== NULL
);
1815 g_assert (data
->simple
== NULL
);
1816 g_assert (data
->cancellable_handler_id
== 0);
1817 g_object_unref (data
->connection
);
1818 if (data
->cancellable
!= NULL
)
1819 g_object_unref (data
->cancellable
);
1820 g_main_context_unref (data
->main_context
);
1825 /* ---------------------------------------------------------------------------------------------------- */
1827 /* can be called from any thread with lock held - caller must have prepared GSimpleAsyncResult already */
1829 send_message_with_reply_deliver (SendMessageData
*data
, gboolean remove
)
1831 CONNECTION_ENSURE_LOCK (data
->connection
);
1833 g_assert (!data
->delivered
);
1835 data
->delivered
= TRUE
;
1837 g_simple_async_result_complete_in_idle (data
->simple
);
1838 g_object_unref (data
->simple
);
1839 data
->simple
= NULL
;
1841 if (data
->timeout_source
!= NULL
)
1843 g_source_destroy (data
->timeout_source
);
1844 data
->timeout_source
= NULL
;
1846 if (data
->cancellable_handler_id
> 0)
1848 g_cancellable_disconnect (data
->cancellable
, data
->cancellable_handler_id
);
1849 data
->cancellable_handler_id
= 0;
1854 g_warn_if_fail (g_hash_table_remove (data
->connection
->map_method_serial_to_send_message_data
,
1855 GUINT_TO_POINTER (data
->serial
)));
1858 send_message_data_unref (data
);
1861 /* ---------------------------------------------------------------------------------------------------- */
1863 /* Can be called from any thread with lock held */
1865 send_message_data_deliver_reply_unlocked (SendMessageData
*data
,
1866 GDBusMessage
*reply
)
1868 if (data
->delivered
)
1871 g_simple_async_result_set_op_res_gpointer (data
->simple
,
1872 g_object_ref (reply
),
1875 send_message_with_reply_deliver (data
, TRUE
);
1881 /* ---------------------------------------------------------------------------------------------------- */
1883 /* Called from a user thread, lock is not held */
1885 send_message_with_reply_cancelled_idle_cb (gpointer user_data
)
1887 SendMessageData
*data
= user_data
;
1889 CONNECTION_LOCK (data
->connection
);
1890 if (data
->delivered
)
1893 g_simple_async_result_set_error (data
->simple
,
1895 G_IO_ERROR_CANCELLED
,
1896 _("Operation was cancelled"));
1898 send_message_with_reply_deliver (data
, TRUE
);
1901 CONNECTION_UNLOCK (data
->connection
);
1905 /* Can be called from any thread with or without lock held */
1907 send_message_with_reply_cancelled_cb (GCancellable
*cancellable
,
1910 SendMessageData
*data
= user_data
;
1911 GSource
*idle_source
;
1913 /* postpone cancellation to idle handler since we may be called directly
1914 * via g_cancellable_connect() (e.g. holding lock)
1916 idle_source
= g_idle_source_new ();
1917 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
1918 g_source_set_callback (idle_source
,
1919 send_message_with_reply_cancelled_idle_cb
,
1920 send_message_data_ref (data
),
1921 (GDestroyNotify
) send_message_data_unref
);
1922 g_source_set_name (idle_source
, "[gio] send_message_with_reply_cancelled_idle_cb");
1923 g_source_attach (idle_source
, data
->main_context
);
1924 g_source_unref (idle_source
);
1927 /* ---------------------------------------------------------------------------------------------------- */
1929 /* Called from a user thread, lock is not held */
1931 send_message_with_reply_timeout_cb (gpointer user_data
)
1933 SendMessageData
*data
= user_data
;
1935 CONNECTION_LOCK (data
->connection
);
1936 if (data
->delivered
)
1939 g_simple_async_result_set_error (data
->simple
,
1941 G_IO_ERROR_TIMED_OUT
,
1942 _("Timeout was reached"));
1944 send_message_with_reply_deliver (data
, TRUE
);
1947 CONNECTION_UNLOCK (data
->connection
);
1952 /* ---------------------------------------------------------------------------------------------------- */
1954 /* Called from a user thread, connection's lock is held */
1956 g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection
*connection
,
1957 GDBusMessage
*message
,
1958 GDBusSendMessageFlags flags
,
1960 volatile guint32
*out_serial
,
1961 GCancellable
*cancellable
,
1962 GAsyncReadyCallback callback
,
1965 GSimpleAsyncResult
*simple
;
1966 SendMessageData
*data
;
1968 volatile guint32 serial
;
1972 if (out_serial
== NULL
)
1973 out_serial
= &serial
;
1975 if (timeout_msec
== -1)
1976 timeout_msec
= 25 * 1000;
1978 simple
= g_simple_async_result_new (G_OBJECT (connection
),
1981 g_dbus_connection_send_message_with_reply
);
1982 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
1984 if (g_cancellable_is_cancelled (cancellable
))
1986 g_simple_async_result_set_error (simple
,
1988 G_IO_ERROR_CANCELLED
,
1989 _("Operation was cancelled"));
1990 g_simple_async_result_complete_in_idle (simple
);
1991 g_object_unref (simple
);
1996 if (!g_dbus_connection_send_message_unlocked (connection
, message
, flags
, out_serial
, &error
))
1998 g_simple_async_result_take_error (simple
, error
);
1999 g_simple_async_result_complete_in_idle (simple
);
2000 g_object_unref (simple
);
2004 data
= g_new0 (SendMessageData
, 1);
2005 data
->ref_count
= 1;
2006 data
->connection
= g_object_ref (connection
);
2007 data
->simple
= simple
;
2008 data
->serial
= *out_serial
;
2009 data
->main_context
= g_main_context_ref_thread_default ();
2011 if (cancellable
!= NULL
)
2013 data
->cancellable
= g_object_ref (cancellable
);
2014 data
->cancellable_handler_id
= g_cancellable_connect (cancellable
,
2015 G_CALLBACK (send_message_with_reply_cancelled_cb
),
2016 send_message_data_ref (data
),
2017 (GDestroyNotify
) send_message_data_unref
);
2020 if (timeout_msec
!= G_MAXINT
)
2022 data
->timeout_source
= g_timeout_source_new (timeout_msec
);
2023 g_source_set_priority (data
->timeout_source
, G_PRIORITY_DEFAULT
);
2024 g_source_set_callback (data
->timeout_source
,
2025 send_message_with_reply_timeout_cb
,
2026 send_message_data_ref (data
),
2027 (GDestroyNotify
) send_message_data_unref
);
2028 g_source_attach (data
->timeout_source
, data
->main_context
);
2029 g_source_unref (data
->timeout_source
);
2032 g_hash_table_insert (connection
->map_method_serial_to_send_message_data
,
2033 GUINT_TO_POINTER (*out_serial
),
2041 * g_dbus_connection_send_message_with_reply:
2042 * @connection: a #GDBusConnection
2043 * @message: a #GDBusMessage
2044 * @flags: flags affecting how the message is sent
2045 * @timeout_msec: the timeout in milliseconds, -1 to use the default
2046 * timeout or %G_MAXINT for no timeout
2047 * @out_serial: (out) (allow-none): return location for serial number assigned
2048 * to @message when sending it or %NULL
2049 * @cancellable: (allow-none): a #GCancellable or %NULL
2050 * @callback: (allow-none): a #GAsyncReadyCallback to call when the request
2051 * is satisfied or %NULL if you don't care about the result
2052 * @user_data: The data to pass to @callback
2054 * Asynchronously sends @message to the peer represented by @connection.
2056 * Unless @flags contain the
2057 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
2058 * will be assigned by @connection and set on @message via
2059 * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
2060 * serial number used will be written to this location prior to
2061 * submitting the message to the underlying transport.
2063 * If @connection is closed then the operation will fail with
2064 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
2065 * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
2066 * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
2068 * This is an asynchronous method. When the operation is finished, @callback
2069 * will be invoked in the
2070 * [thread-default main context][g-main-context-push-thread-default]
2071 * of the thread you are calling this method from. You can then call
2072 * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
2073 * See g_dbus_connection_send_message_with_reply_sync() for the synchronous version.
2075 * Note that @message must be unlocked, unless @flags contain the
2076 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
2078 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
2079 * for an example of how to use this low-level API to send and receive
2080 * UNIX file descriptors.
2085 g_dbus_connection_send_message_with_reply (GDBusConnection
*connection
,
2086 GDBusMessage
*message
,
2087 GDBusSendMessageFlags flags
,
2089 volatile guint32
*out_serial
,
2090 GCancellable
*cancellable
,
2091 GAsyncReadyCallback callback
,
2094 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
2095 g_return_if_fail (G_IS_DBUS_MESSAGE (message
));
2096 g_return_if_fail ((flags
& G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
) || !g_dbus_message_get_locked (message
));
2097 g_return_if_fail (timeout_msec
>= 0 || timeout_msec
== -1);
2099 CONNECTION_LOCK (connection
);
2100 g_dbus_connection_send_message_with_reply_unlocked (connection
,
2108 CONNECTION_UNLOCK (connection
);
2112 * g_dbus_connection_send_message_with_reply_finish:
2113 * @connection: a #GDBusConnection
2114 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to
2115 * g_dbus_connection_send_message_with_reply()
2116 * @error: teturn location for error or %NULL
2118 * Finishes an operation started with g_dbus_connection_send_message_with_reply().
2120 * Note that @error is only set if a local in-process error
2121 * occurred. That is to say that the returned #GDBusMessage object may
2122 * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
2123 * g_dbus_message_to_gerror() to transcode this to a #GError.
2125 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
2126 * for an example of how to use this low-level API to send and receive
2127 * UNIX file descriptors.
2129 * Returns: (transfer full): a locked #GDBusMessage or %NULL if @error is set
2134 g_dbus_connection_send_message_with_reply_finish (GDBusConnection
*connection
,
2138 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (res
);
2139 GDBusMessage
*reply
;
2141 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
2142 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
2146 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_dbus_connection_send_message_with_reply
);
2148 if (g_simple_async_result_propagate_error (simple
, error
))
2151 reply
= g_object_ref (g_simple_async_result_get_op_res_gpointer (simple
));
2157 /* ---------------------------------------------------------------------------------------------------- */
2162 GMainContext
*context
;
2164 } SendMessageSyncData
;
2166 /* Called from a user thread, lock is not held */
2168 send_message_with_reply_sync_cb (GDBusConnection
*connection
,
2172 SendMessageSyncData
*data
= user_data
;
2173 data
->res
= g_object_ref (res
);
2174 g_main_loop_quit (data
->loop
);
2178 * g_dbus_connection_send_message_with_reply_sync:
2179 * @connection: a #GDBusConnection
2180 * @message: a #GDBusMessage
2181 * @flags: flags affecting how the message is sent.
2182 * @timeout_msec: the timeout in milliseconds, -1 to use the default
2183 * timeout or %G_MAXINT for no timeout
2184 * @out_serial: (out) (allow-none): return location for serial number
2185 * assigned to @message when sending it or %NULL
2186 * @cancellable: (allow-none): a #GCancellable or %NULL
2187 * @error: return location for error or %NULL
2189 * Synchronously sends @message to the peer represented by @connection
2190 * and blocks the calling thread until a reply is received or the
2191 * timeout is reached. See g_dbus_connection_send_message_with_reply()
2192 * for the asynchronous version of this method.
2194 * Unless @flags contain the
2195 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag, the serial number
2196 * will be assigned by @connection and set on @message via
2197 * g_dbus_message_set_serial(). If @out_serial is not %NULL, then the
2198 * serial number used will be written to this location prior to
2199 * submitting the message to the underlying transport.
2201 * If @connection is closed then the operation will fail with
2202 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
2203 * fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
2204 * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
2206 * Note that @error is only set if a local in-process error
2207 * occurred. That is to say that the returned #GDBusMessage object may
2208 * be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
2209 * g_dbus_message_to_gerror() to transcode this to a #GError.
2211 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
2212 * for an example of how to use this low-level API to send and receive
2213 * UNIX file descriptors.
2215 * Note that @message must be unlocked, unless @flags contain the
2216 * %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
2218 * Returns: (transfer full): a locked #GDBusMessage that is the reply
2219 * to @message or %NULL if @error is set
2224 g_dbus_connection_send_message_with_reply_sync (GDBusConnection
*connection
,
2225 GDBusMessage
*message
,
2226 GDBusSendMessageFlags flags
,
2228 volatile guint32
*out_serial
,
2229 GCancellable
*cancellable
,
2232 SendMessageSyncData
*data
;
2233 GDBusMessage
*reply
;
2235 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
2236 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message
), NULL
);
2237 g_return_val_if_fail ((flags
& G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
) || !g_dbus_message_get_locked (message
), NULL
);
2238 g_return_val_if_fail (timeout_msec
>= 0 || timeout_msec
== -1, NULL
);
2239 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
2241 data
= g_new0 (SendMessageSyncData
, 1);
2242 data
->context
= g_main_context_new ();
2243 data
->loop
= g_main_loop_new (data
->context
, FALSE
);
2245 g_main_context_push_thread_default (data
->context
);
2247 g_dbus_connection_send_message_with_reply (connection
,
2253 (GAsyncReadyCallback
) send_message_with_reply_sync_cb
,
2255 g_main_loop_run (data
->loop
);
2256 reply
= g_dbus_connection_send_message_with_reply_finish (connection
,
2260 g_main_context_pop_thread_default (data
->context
);
2262 g_main_context_unref (data
->context
);
2263 g_main_loop_unref (data
->loop
);
2264 g_object_unref (data
->res
);
2270 /* ---------------------------------------------------------------------------------------------------- */
2274 GDBusMessageFilterFunction func
;
2281 GDBusMessageFilterFunction filter_function
;
2283 GDestroyNotify user_data_free_func
;
2286 /* Called in GDBusWorker's thread - we must not block - with no lock held */
2288 on_worker_message_received (GDBusWorker
*worker
,
2289 GDBusMessage
*message
,
2292 GDBusConnection
*connection
;
2293 FilterCallback
*filters
;
2298 G_LOCK (message_bus_lock
);
2299 alive
= (g_hash_table_lookup (alive_connections
, user_data
) != NULL
);
2302 G_UNLOCK (message_bus_lock
);
2305 connection
= G_DBUS_CONNECTION (user_data
);
2306 g_object_ref (connection
);
2307 G_UNLOCK (message_bus_lock
);
2309 //g_debug ("in on_worker_message_received");
2311 g_object_ref (message
);
2312 g_dbus_message_lock (message
);
2314 //g_debug ("boo ref_count = %d %p %p", G_OBJECT (connection)->ref_count, connection, connection->worker);
2316 /* First collect the set of callback functions */
2317 CONNECTION_LOCK (connection
);
2318 num_filters
= connection
->filters
->len
;
2319 filters
= g_new0 (FilterCallback
, num_filters
);
2320 for (n
= 0; n
< num_filters
; n
++)
2322 FilterData
*data
= connection
->filters
->pdata
[n
];
2323 filters
[n
].func
= data
->filter_function
;
2324 filters
[n
].user_data
= data
->user_data
;
2326 CONNECTION_UNLOCK (connection
);
2328 /* then call the filters in order (without holding the lock) */
2329 for (n
= 0; n
< num_filters
; n
++)
2331 message
= filters
[n
].func (connection
,
2334 filters
[n
].user_data
);
2335 if (message
== NULL
)
2337 g_dbus_message_lock (message
);
2340 /* Standard dispatch unless the filter ate the message - no need to
2341 * do anything if the message was altered
2343 if (message
!= NULL
)
2345 GDBusMessageType message_type
;
2347 message_type
= g_dbus_message_get_message_type (message
);
2348 if (message_type
== G_DBUS_MESSAGE_TYPE_METHOD_RETURN
|| message_type
== G_DBUS_MESSAGE_TYPE_ERROR
)
2350 guint32 reply_serial
;
2351 SendMessageData
*send_message_data
;
2353 reply_serial
= g_dbus_message_get_reply_serial (message
);
2354 CONNECTION_LOCK (connection
);
2355 send_message_data
= g_hash_table_lookup (connection
->map_method_serial_to_send_message_data
,
2356 GUINT_TO_POINTER (reply_serial
));
2357 if (send_message_data
!= NULL
)
2359 //g_debug ("delivering reply/error for serial %d for %p", reply_serial, connection);
2360 send_message_data_deliver_reply_unlocked (send_message_data
, message
);
2364 //g_debug ("message reply/error for serial %d but no SendMessageData found for %p", reply_serial, connection);
2366 CONNECTION_UNLOCK (connection
);
2368 else if (message_type
== G_DBUS_MESSAGE_TYPE_SIGNAL
)
2370 CONNECTION_LOCK (connection
);
2371 distribute_signals (connection
, message
);
2372 CONNECTION_UNLOCK (connection
);
2374 else if (message_type
== G_DBUS_MESSAGE_TYPE_METHOD_CALL
)
2376 CONNECTION_LOCK (connection
);
2377 distribute_method_call (connection
, message
);
2378 CONNECTION_UNLOCK (connection
);
2382 if (message
!= NULL
)
2383 g_object_unref (message
);
2384 g_object_unref (connection
);
2388 /* Called in GDBusWorker's thread, lock is not held */
2389 static GDBusMessage
*
2390 on_worker_message_about_to_be_sent (GDBusWorker
*worker
,
2391 GDBusMessage
*message
,
2394 GDBusConnection
*connection
;
2395 FilterCallback
*filters
;
2400 G_LOCK (message_bus_lock
);
2401 alive
= (g_hash_table_lookup (alive_connections
, user_data
) != NULL
);
2404 G_UNLOCK (message_bus_lock
);
2407 connection
= G_DBUS_CONNECTION (user_data
);
2408 g_object_ref (connection
);
2409 G_UNLOCK (message_bus_lock
);
2411 //g_debug ("in on_worker_message_about_to_be_sent");
2413 /* First collect the set of callback functions */
2414 CONNECTION_LOCK (connection
);
2415 num_filters
= connection
->filters
->len
;
2416 filters
= g_new0 (FilterCallback
, num_filters
);
2417 for (n
= 0; n
< num_filters
; n
++)
2419 FilterData
*data
= connection
->filters
->pdata
[n
];
2420 filters
[n
].func
= data
->filter_function
;
2421 filters
[n
].user_data
= data
->user_data
;
2423 CONNECTION_UNLOCK (connection
);
2425 /* then call the filters in order (without holding the lock) */
2426 for (n
= 0; n
< num_filters
; n
++)
2428 g_dbus_message_lock (message
);
2429 message
= filters
[n
].func (connection
,
2432 filters
[n
].user_data
);
2433 if (message
== NULL
)
2437 g_object_unref (connection
);
2443 /* called with connection lock held, in GDBusWorker thread */
2445 cancel_method_on_close (gpointer key
, gpointer value
, gpointer user_data
)
2447 SendMessageData
*data
= value
;
2449 if (data
->delivered
)
2452 g_simple_async_result_set_error (data
->simple
,
2455 _("The connection is closed"));
2457 /* Ask send_message_with_reply_deliver not to remove the element from the
2458 * hash table - we're in the middle of a foreach; that would be unsafe.
2459 * Instead, return TRUE from this function so that it gets removed safely.
2461 send_message_with_reply_deliver (data
, FALSE
);
2465 /* Called in GDBusWorker's thread - we must not block - without lock held */
2467 on_worker_closed (GDBusWorker
*worker
,
2468 gboolean remote_peer_vanished
,
2472 GDBusConnection
*connection
;
2474 guint old_atomic_flags
;
2476 G_LOCK (message_bus_lock
);
2477 alive
= (g_hash_table_lookup (alive_connections
, user_data
) != NULL
);
2480 G_UNLOCK (message_bus_lock
);
2483 connection
= G_DBUS_CONNECTION (user_data
);
2484 g_object_ref (connection
);
2485 G_UNLOCK (message_bus_lock
);
2487 //g_debug ("in on_worker_closed: %s", error->message);
2489 CONNECTION_LOCK (connection
);
2490 /* Even though this is atomic, we do it inside the lock to avoid breaking
2491 * assumptions in remove_match_rule(). We'd need the lock in a moment
2492 * anyway, so, no loss.
2494 old_atomic_flags
= g_atomic_int_or (&connection
->atomic_flags
, FLAG_CLOSED
);
2496 if (!(old_atomic_flags
& FLAG_CLOSED
))
2498 g_hash_table_foreach_remove (connection
->map_method_serial_to_send_message_data
, cancel_method_on_close
, NULL
);
2499 schedule_closed_unlocked (connection
, remote_peer_vanished
, error
);
2501 CONNECTION_UNLOCK (connection
);
2503 g_object_unref (connection
);
2506 /* ---------------------------------------------------------------------------------------------------- */
2508 /* Determines the biggest set of capabilities we can support on this
2511 * Called with the init_lock held.
2513 static GDBusCapabilityFlags
2514 get_offered_capabilities_max (GDBusConnection
*connection
)
2516 GDBusCapabilityFlags ret
;
2517 ret
= G_DBUS_CAPABILITY_FLAGS_NONE
;
2519 if (G_IS_UNIX_CONNECTION (connection
->stream
))
2520 ret
|= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING
;
2525 /* Called in a user thread, lock is not held */
2527 initable_init (GInitable
*initable
,
2528 GCancellable
*cancellable
,
2531 GDBusConnection
*connection
= G_DBUS_CONNECTION (initable
);
2534 /* This method needs to be idempotent to work with the singleton
2535 * pattern. See the docs for g_initable_init(). We implement this by
2538 * Unfortunately we can't use the main lock since the on_worker_*()
2539 * callbacks above needs the lock during initialization (for message
2540 * bus connections we do a synchronous Hello() call on the bus).
2542 g_mutex_lock (&connection
->init_lock
);
2546 /* Make this a no-op if we're already initialized (successfully or
2549 if ((g_atomic_int_get (&connection
->atomic_flags
) & FLAG_INITIALIZED
))
2551 ret
= (connection
->initialization_error
== NULL
);
2555 /* Because of init_lock, we can't get here twice in different threads */
2556 g_assert (connection
->initialization_error
== NULL
);
2558 /* The user can pass multiple (but mutally exclusive) construct
2561 * - stream (of type GIOStream)
2562 * - address (of type gchar*)
2564 * At the end of the day we end up with a non-NULL GIOStream
2565 * object in connection->stream.
2567 if (connection
->address
!= NULL
)
2569 g_assert (connection
->stream
== NULL
);
2571 if ((connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER
) ||
2572 (connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS
))
2574 g_set_error_literal (&connection
->initialization_error
,
2576 G_IO_ERROR_INVALID_ARGUMENT
,
2577 _("Unsupported flags encountered when constructing a client-side connection"));
2581 connection
->stream
= g_dbus_address_get_stream_sync (connection
->address
,
2582 NULL
, /* TODO: out_guid */
2584 &connection
->initialization_error
);
2585 if (connection
->stream
== NULL
)
2588 else if (connection
->stream
!= NULL
)
2594 g_assert_not_reached ();
2597 /* Authenticate the connection */
2598 if (connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER
)
2600 g_assert (!(connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
));
2601 g_assert (connection
->guid
!= NULL
);
2602 connection
->auth
= _g_dbus_auth_new (connection
->stream
);
2603 if (!_g_dbus_auth_run_server (connection
->auth
,
2604 connection
->authentication_observer
,
2606 (connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS
),
2607 get_offered_capabilities_max (connection
),
2608 &connection
->capabilities
,
2609 &connection
->credentials
,
2611 &connection
->initialization_error
))
2614 else if (connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
)
2616 g_assert (!(connection
->flags
& G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER
));
2617 g_assert (connection
->guid
== NULL
);
2618 connection
->auth
= _g_dbus_auth_new (connection
->stream
);
2619 connection
->guid
= _g_dbus_auth_run_client (connection
->auth
,
2620 connection
->authentication_observer
,
2621 get_offered_capabilities_max (connection
),
2622 &connection
->capabilities
,
2624 &connection
->initialization_error
);
2625 if (connection
->guid
== NULL
)
2629 if (connection
->authentication_observer
!= NULL
)
2631 g_object_unref (connection
->authentication_observer
);
2632 connection
->authentication_observer
= NULL
;
2635 //g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
2637 //g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
2640 /* We want all IO operations to be non-blocking since they happen in
2641 * the worker thread which is shared by _all_ connections.
2643 if (G_IS_SOCKET_CONNECTION (connection
->stream
))
2645 g_socket_set_blocking (g_socket_connection_get_socket (G_SOCKET_CONNECTION (connection
->stream
)), FALSE
);
2649 G_LOCK (message_bus_lock
);
2650 if (alive_connections
== NULL
)
2651 alive_connections
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
2652 g_hash_table_insert (alive_connections
, connection
, connection
);
2653 G_UNLOCK (message_bus_lock
);
2655 connection
->worker
= _g_dbus_worker_new (connection
->stream
,
2656 connection
->capabilities
,
2657 ((connection
->flags
& G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING
) != 0),
2658 on_worker_message_received
,
2659 on_worker_message_about_to_be_sent
,
2663 /* if a bus connection, call org.freedesktop.DBus.Hello - this is how we're getting a name */
2664 if (connection
->flags
& G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION
)
2666 GVariant
*hello_result
;
2668 /* we could lift this restriction by adding code in gdbusprivate.c */
2669 if (connection
->flags
& G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING
)
2671 g_set_error_literal (&connection
->initialization_error
,
2674 "Cannot use DELAY_MESSAGE_PROCESSING with MESSAGE_BUS_CONNECTION");
2678 hello_result
= g_dbus_connection_call_sync (connection
,
2679 "org.freedesktop.DBus", /* name */
2680 "/org/freedesktop/DBus", /* path */
2681 "org.freedesktop.DBus", /* interface */
2683 NULL
, /* parameters */
2684 G_VARIANT_TYPE ("(s)"),
2685 CALL_FLAGS_INITIALIZING
,
2687 NULL
, /* TODO: cancellable */
2688 &connection
->initialization_error
);
2689 if (hello_result
== NULL
)
2692 g_variant_get (hello_result
, "(s)", &connection
->bus_unique_name
);
2693 g_variant_unref (hello_result
);
2694 //g_debug ("unique name is '%s'", connection->bus_unique_name);
2701 g_assert (connection
->initialization_error
!= NULL
);
2702 g_propagate_error (error
, g_error_copy (connection
->initialization_error
));
2705 g_atomic_int_or (&connection
->atomic_flags
, FLAG_INITIALIZED
);
2706 g_mutex_unlock (&connection
->init_lock
);
2712 initable_iface_init (GInitableIface
*initable_iface
)
2714 initable_iface
->init
= initable_init
;
2717 /* ---------------------------------------------------------------------------------------------------- */
2720 async_initable_iface_init (GAsyncInitableIface
*async_initable_iface
)
2725 /* ---------------------------------------------------------------------------------------------------- */
2728 * g_dbus_connection_new:
2729 * @stream: a #GIOStream
2730 * @guid: (allow-none): the GUID to use if a authenticating as a server or %NULL
2731 * @flags: flags describing how to make the connection
2732 * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2733 * @cancellable: (allow-none): a #GCancellable or %NULL
2734 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2735 * @user_data: the data to pass to @callback
2737 * Asynchronously sets up a D-Bus connection for exchanging D-Bus messages
2738 * with the end represented by @stream.
2740 * If @stream is a #GSocketConnection, then the corresponding #GSocket
2741 * will be put into non-blocking mode.
2743 * The D-Bus connection will interact with @stream from a worker thread.
2744 * As a result, the caller should not interact with @stream after this
2745 * method has been called, except by calling g_object_unref() on it.
2747 * If @observer is not %NULL it may be used to control the
2748 * authentication process.
2750 * When the operation is finished, @callback will be invoked. You can
2751 * then call g_dbus_connection_new_finish() to get the result of the
2754 * This is a asynchronous failable constructor. See
2755 * g_dbus_connection_new_sync() for the synchronous
2761 g_dbus_connection_new (GIOStream
*stream
,
2763 GDBusConnectionFlags flags
,
2764 GDBusAuthObserver
*observer
,
2765 GCancellable
*cancellable
,
2766 GAsyncReadyCallback callback
,
2769 g_return_if_fail (G_IS_IO_STREAM (stream
));
2770 g_async_initable_new_async (G_TYPE_DBUS_CONNECTION
,
2778 "authentication-observer", observer
,
2783 * g_dbus_connection_new_finish:
2784 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback
2785 * passed to g_dbus_connection_new().
2786 * @error: return location for error or %NULL
2788 * Finishes an operation started with g_dbus_connection_new().
2790 * Returns: a #GDBusConnection or %NULL if @error is set. Free
2791 * with g_object_unref().
2796 g_dbus_connection_new_finish (GAsyncResult
*res
,
2800 GObject
*source_object
;
2802 g_return_val_if_fail (G_IS_ASYNC_RESULT (res
), NULL
);
2803 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
2805 source_object
= g_async_result_get_source_object (res
);
2806 g_assert (source_object
!= NULL
);
2807 object
= g_async_initable_new_finish (G_ASYNC_INITABLE (source_object
),
2810 g_object_unref (source_object
);
2812 return G_DBUS_CONNECTION (object
);
2818 * g_dbus_connection_new_sync:
2819 * @stream: a #GIOStream
2820 * @guid: (allow-none): the GUID to use if a authenticating as a server or %NULL
2821 * @flags: flags describing how to make the connection
2822 * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2823 * @cancellable: (allow-none): a #GCancellable or %NULL
2824 * @error: return location for error or %NULL
2826 * Synchronously sets up a D-Bus connection for exchanging D-Bus messages
2827 * with the end represented by @stream.
2829 * If @stream is a #GSocketConnection, then the corresponding #GSocket
2830 * will be put into non-blocking mode.
2832 * The D-Bus connection will interact with @stream from a worker thread.
2833 * As a result, the caller should not interact with @stream after this
2834 * method has been called, except by calling g_object_unref() on it.
2836 * If @observer is not %NULL it may be used to control the
2837 * authentication process.
2839 * This is a synchronous failable constructor. See
2840 * g_dbus_connection_new() for the asynchronous version.
2842 * Returns: a #GDBusConnection or %NULL if @error is set. Free with g_object_unref().
2847 g_dbus_connection_new_sync (GIOStream
*stream
,
2849 GDBusConnectionFlags flags
,
2850 GDBusAuthObserver
*observer
,
2851 GCancellable
*cancellable
,
2854 g_return_val_if_fail (G_IS_IO_STREAM (stream
), NULL
);
2855 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
2856 return g_initable_new (G_TYPE_DBUS_CONNECTION
,
2862 "authentication-observer", observer
,
2866 /* ---------------------------------------------------------------------------------------------------- */
2869 * g_dbus_connection_new_for_address:
2870 * @address: a D-Bus address
2871 * @flags: flags describing how to make the connection
2872 * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2873 * @cancellable: (allow-none): a #GCancellable or %NULL
2874 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2875 * @user_data: the data to pass to @callback
2877 * Asynchronously connects and sets up a D-Bus client connection for
2878 * exchanging D-Bus messages with an endpoint specified by @address
2879 * which must be in the D-Bus address format.
2881 * This constructor can only be used to initiate client-side
2882 * connections - use g_dbus_connection_new() if you need to act as the
2883 * server. In particular, @flags cannot contain the
2884 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2885 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2887 * When the operation is finished, @callback will be invoked. You can
2888 * then call g_dbus_connection_new_finish() to get the result of the
2891 * If @observer is not %NULL it may be used to control the
2892 * authentication process.
2894 * This is a asynchronous failable constructor. See
2895 * g_dbus_connection_new_for_address_sync() for the synchronous
2901 g_dbus_connection_new_for_address (const gchar
*address
,
2902 GDBusConnectionFlags flags
,
2903 GDBusAuthObserver
*observer
,
2904 GCancellable
*cancellable
,
2905 GAsyncReadyCallback callback
,
2908 g_return_if_fail (address
!= NULL
);
2909 g_async_initable_new_async (G_TYPE_DBUS_CONNECTION
,
2916 "authentication-observer", observer
,
2921 * g_dbus_connection_new_for_address_finish:
2922 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
2923 * to g_dbus_connection_new()
2924 * @error: return location for error or %NULL
2926 * Finishes an operation started with g_dbus_connection_new_for_address().
2928 * Returns: a #GDBusConnection or %NULL if @error is set. Free with
2934 g_dbus_connection_new_for_address_finish (GAsyncResult
*res
,
2938 GObject
*source_object
;
2940 g_return_val_if_fail (G_IS_ASYNC_RESULT (res
), NULL
);
2941 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
2943 source_object
= g_async_result_get_source_object (res
);
2944 g_assert (source_object
!= NULL
);
2945 object
= g_async_initable_new_finish (G_ASYNC_INITABLE (source_object
),
2948 g_object_unref (source_object
);
2950 return G_DBUS_CONNECTION (object
);
2956 * g_dbus_connection_new_for_address_sync:
2957 * @address: a D-Bus address
2958 * @flags: flags describing how to make the connection
2959 * @observer: (allow-none): a #GDBusAuthObserver or %NULL
2960 * @cancellable: (allow-none): a #GCancellable or %NULL
2961 * @error: return location for error or %NULL
2963 * Synchronously connects and sets up a D-Bus client connection for
2964 * exchanging D-Bus messages with an endpoint specified by @address
2965 * which must be in the D-Bus address format.
2967 * This constructor can only be used to initiate client-side
2968 * connections - use g_dbus_connection_new_sync() if you need to act
2969 * as the server. In particular, @flags cannot contain the
2970 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or
2971 * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags.
2973 * This is a synchronous failable constructor. See
2974 * g_dbus_connection_new_for_address() for the asynchronous version.
2976 * If @observer is not %NULL it may be used to control the
2977 * authentication process.
2979 * Returns: a #GDBusConnection or %NULL if @error is set. Free with
2985 g_dbus_connection_new_for_address_sync (const gchar
*address
,
2986 GDBusConnectionFlags flags
,
2987 GDBusAuthObserver
*observer
,
2988 GCancellable
*cancellable
,
2991 g_return_val_if_fail (address
!= NULL
, NULL
);
2992 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
2993 return g_initable_new (G_TYPE_DBUS_CONNECTION
,
2998 "authentication-observer", observer
,
3002 /* ---------------------------------------------------------------------------------------------------- */
3005 * g_dbus_connection_set_exit_on_close:
3006 * @connection: a #GDBusConnection
3007 * @exit_on_close: whether the process should be terminated
3008 * when @connection is closed by the remote peer
3010 * Sets whether the process should be terminated when @connection is
3011 * closed by the remote peer. See #GDBusConnection:exit-on-close for
3014 * Note that this function should be used with care. Most modern UNIX
3015 * desktops tie the notion of a user session the session bus, and expect
3016 * all of a users applications to quit when their bus connection goes away.
3017 * If you are setting @exit_on_close to %FALSE for the shared session
3018 * bus connection, you should make sure that your application exits
3019 * when the user session ends.
3024 g_dbus_connection_set_exit_on_close (GDBusConnection
*connection
,
3025 gboolean exit_on_close
)
3027 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
3030 g_atomic_int_or (&connection
->atomic_flags
, FLAG_EXIT_ON_CLOSE
);
3032 g_atomic_int_and (&connection
->atomic_flags
, ~FLAG_EXIT_ON_CLOSE
);
3037 * g_dbus_connection_get_exit_on_close:
3038 * @connection: a #GDBusConnection
3040 * Gets whether the process is terminated when @connection is
3041 * closed by the remote peer. See
3042 * #GDBusConnection:exit-on-close for more details.
3044 * Returns: whether the process is terminated when @connection is
3045 * closed by the remote peer
3050 g_dbus_connection_get_exit_on_close (GDBusConnection
*connection
)
3052 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
3054 if (g_atomic_int_get (&connection
->atomic_flags
) & FLAG_EXIT_ON_CLOSE
)
3061 * g_dbus_connection_get_guid:
3062 * @connection: a #GDBusConnection
3064 * The GUID of the peer performing the role of server when
3065 * authenticating. See #GDBusConnection:guid for more details.
3067 * Returns: The GUID. Do not free this string, it is owned by
3073 g_dbus_connection_get_guid (GDBusConnection
*connection
)
3075 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
3076 return connection
->guid
;
3080 * g_dbus_connection_get_unique_name:
3081 * @connection: a #GDBusConnection
3083 * Gets the unique name of @connection as assigned by the message
3084 * bus. This can also be used to figure out if @connection is a
3085 * message bus connection.
3087 * Returns: the unique name or %NULL if @connection is not a message
3088 * bus connection. Do not free this string, it is owned by
3094 g_dbus_connection_get_unique_name (GDBusConnection
*connection
)
3096 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
3098 /* do not use g_return_val_if_fail(), we want the memory barrier */
3099 if (!check_initialized (connection
))
3102 return connection
->bus_unique_name
;
3106 * g_dbus_connection_get_peer_credentials:
3107 * @connection: a #GDBusConnection
3109 * Gets the credentials of the authenticated peer. This will always
3110 * return %NULL unless @connection acted as a server
3111 * (e.g. %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER was passed)
3112 * when set up and the client passed credentials as part of the
3113 * authentication process.
3115 * In a message bus setup, the message bus is always the server and
3116 * each application is a client. So this method will always return
3117 * %NULL for message bus clients.
3119 * Returns: (transfer none): a #GCredentials or %NULL if not available.
3120 * Do not free this object, it is owned by @connection.
3125 g_dbus_connection_get_peer_credentials (GDBusConnection
*connection
)
3127 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
3129 /* do not use g_return_val_if_fail(), we want the memory barrier */
3130 if (!check_initialized (connection
))
3133 return connection
->credentials
;
3136 /* ---------------------------------------------------------------------------------------------------- */
3138 static guint _global_filter_id
= 1;
3141 * g_dbus_connection_add_filter:
3142 * @connection: a #GDBusConnection
3143 * @filter_function: a filter function
3144 * @user_data: user data to pass to @filter_function
3145 * @user_data_free_func: function to free @user_data with when filter
3146 * is removed or %NULL
3148 * Adds a message filter. Filters are handlers that are run on all
3149 * incoming and outgoing messages, prior to standard dispatch. Filters
3150 * are run in the order that they were added. The same handler can be
3151 * added as a filter more than once, in which case it will be run more
3152 * than once. Filters added during a filter callback won't be run on
3153 * the message being processed. Filter functions are allowed to modify
3154 * and even drop messages.
3156 * Note that filters are run in a dedicated message handling thread so
3157 * they can't block and, generally, can't do anything but signal a
3158 * worker thread. Also note that filters are rarely needed - use API
3159 * such as g_dbus_connection_send_message_with_reply(),
3160 * g_dbus_connection_signal_subscribe() or g_dbus_connection_call() instead.
3162 * If a filter consumes an incoming message the message is not
3163 * dispatched anywhere else - not even the standard dispatch machinery
3164 * (that API such as g_dbus_connection_signal_subscribe() and
3165 * g_dbus_connection_send_message_with_reply() relies on) will see the
3166 * message. Similary, if a filter consumes an outgoing message, the
3167 * message will not be sent to the other peer.
3169 * Returns: a filter identifier that can be used with
3170 * g_dbus_connection_remove_filter()
3175 g_dbus_connection_add_filter (GDBusConnection
*connection
,
3176 GDBusMessageFilterFunction filter_function
,
3178 GDestroyNotify user_data_free_func
)
3182 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), 0);
3183 g_return_val_if_fail (filter_function
!= NULL
, 0);
3184 g_return_val_if_fail (check_initialized (connection
), 0);
3186 CONNECTION_LOCK (connection
);
3187 data
= g_new0 (FilterData
, 1);
3188 data
->id
= _global_filter_id
++; /* TODO: overflow etc. */
3189 data
->filter_function
= filter_function
;
3190 data
->user_data
= user_data
;
3191 data
->user_data_free_func
= user_data_free_func
;
3192 g_ptr_array_add (connection
->filters
, data
);
3193 CONNECTION_UNLOCK (connection
);
3198 /* only called from finalize(), removes all filters */
3200 purge_all_filters (GDBusConnection
*connection
)
3203 for (n
= 0; n
< connection
->filters
->len
; n
++)
3205 FilterData
*data
= connection
->filters
->pdata
[n
];
3206 if (data
->user_data_free_func
!= NULL
)
3207 data
->user_data_free_func (data
->user_data
);
3213 * g_dbus_connection_remove_filter:
3214 * @connection: a #GDBusConnection
3215 * @filter_id: an identifier obtained from g_dbus_connection_add_filter()
3222 g_dbus_connection_remove_filter (GDBusConnection
*connection
,
3226 FilterData
*to_destroy
;
3228 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
3229 g_return_if_fail (check_initialized (connection
));
3231 CONNECTION_LOCK (connection
);
3233 for (n
= 0; n
< connection
->filters
->len
; n
++)
3235 FilterData
*data
= connection
->filters
->pdata
[n
];
3236 if (data
->id
== filter_id
)
3238 g_ptr_array_remove_index (connection
->filters
, n
);
3243 CONNECTION_UNLOCK (connection
);
3245 /* do free without holding lock */
3246 if (to_destroy
!= NULL
)
3248 if (to_destroy
->user_data_free_func
!= NULL
)
3249 to_destroy
->user_data_free_func (to_destroy
->user_data
);
3250 g_free (to_destroy
);
3254 g_warning ("g_dbus_connection_remove_filter: No filter found for filter_id %d", filter_id
);
3258 /* ---------------------------------------------------------------------------------------------------- */
3264 gchar
*sender_unique_name
; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */
3265 gchar
*interface_name
;
3269 GDBusSignalFlags flags
;
3270 GArray
*subscribers
;
3275 GDBusSignalCallback callback
;
3277 GDestroyNotify user_data_free_func
;
3279 GMainContext
*context
;
3283 signal_data_free (SignalData
*signal_data
)
3285 g_free (signal_data
->rule
);
3286 g_free (signal_data
->sender
);
3287 g_free (signal_data
->sender_unique_name
);
3288 g_free (signal_data
->interface_name
);
3289 g_free (signal_data
->member
);
3290 g_free (signal_data
->object_path
);
3291 g_free (signal_data
->arg0
);
3292 g_array_free (signal_data
->subscribers
, TRUE
);
3293 g_free (signal_data
);
3297 args_to_rule (const gchar
*sender
,
3298 const gchar
*interface_name
,
3299 const gchar
*member
,
3300 const gchar
*object_path
,
3302 GDBusSignalFlags flags
)
3306 rule
= g_string_new ("type='signal'");
3307 if (flags
& G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE
)
3308 g_string_prepend_c (rule
, '-');
3310 g_string_append_printf (rule
, ",sender='%s'", sender
);
3311 if (interface_name
!= NULL
)
3312 g_string_append_printf (rule
, ",interface='%s'", interface_name
);
3314 g_string_append_printf (rule
, ",member='%s'", member
);
3315 if (object_path
!= NULL
)
3316 g_string_append_printf (rule
, ",path='%s'", object_path
);
3320 if (flags
& G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
)
3321 g_string_append_printf (rule
, ",arg0path='%s'", arg0
);
3322 else if (flags
& G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
)
3323 g_string_append_printf (rule
, ",arg0namespace='%s'", arg0
);
3325 g_string_append_printf (rule
, ",arg0='%s'", arg0
);
3328 return g_string_free (rule
, FALSE
);
3331 static guint _global_subscriber_id
= 1;
3332 static guint _global_registration_id
= 1;
3333 static guint _global_subtree_registration_id
= 1;
3335 /* ---------------------------------------------------------------------------------------------------- */
3337 /* Called in a user thread, lock is held */
3339 add_match_rule (GDBusConnection
*connection
,
3340 const gchar
*match_rule
)
3343 GDBusMessage
*message
;
3345 if (match_rule
[0] == '-')
3348 message
= g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
3349 "/org/freedesktop/DBus", /* path */
3350 "org.freedesktop.DBus", /* interface */
3352 g_dbus_message_set_body (message
, g_variant_new ("(s)", match_rule
));
3354 if (!g_dbus_connection_send_message_unlocked (connection
,
3356 G_DBUS_SEND_MESSAGE_FLAGS_NONE
,
3360 g_critical ("Error while sending AddMatch() message: %s", error
->message
);
3361 g_error_free (error
);
3363 g_object_unref (message
);
3366 /* ---------------------------------------------------------------------------------------------------- */
3368 /* Called in a user thread, lock is held */
3370 remove_match_rule (GDBusConnection
*connection
,
3371 const gchar
*match_rule
)
3374 GDBusMessage
*message
;
3376 if (match_rule
[0] == '-')
3379 message
= g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
3380 "/org/freedesktop/DBus", /* path */
3381 "org.freedesktop.DBus", /* interface */
3383 g_dbus_message_set_body (message
, g_variant_new ("(s)", match_rule
));
3386 if (!g_dbus_connection_send_message_unlocked (connection
,
3388 G_DBUS_SEND_MESSAGE_FLAGS_NONE
,
3392 /* If we could get G_IO_ERROR_CLOSED here, it wouldn't be reasonable to
3393 * critical; but we're holding the lock, and our caller checked whether
3394 * we were already closed, so we can't get that error.
3396 g_critical ("Error while sending RemoveMatch() message: %s", error
->message
);
3397 g_error_free (error
);
3399 g_object_unref (message
);
3402 /* ---------------------------------------------------------------------------------------------------- */
3405 is_signal_data_for_name_lost_or_acquired (SignalData
*signal_data
)
3407 return g_strcmp0 (signal_data
->sender_unique_name
, "org.freedesktop.DBus") == 0 &&
3408 g_strcmp0 (signal_data
->interface_name
, "org.freedesktop.DBus") == 0 &&
3409 g_strcmp0 (signal_data
->object_path
, "/org/freedesktop/DBus") == 0 &&
3410 (g_strcmp0 (signal_data
->member
, "NameLost") == 0 ||
3411 g_strcmp0 (signal_data
->member
, "NameAcquired") == 0);
3414 /* ---------------------------------------------------------------------------------------------------- */
3417 * g_dbus_connection_signal_subscribe:
3418 * @connection: a #GDBusConnection
3419 * @sender: (allow-none): sender name to match on (unique or well-known name)
3420 * or %NULL to listen from all senders
3421 * @interface_name: (allow-none): D-Bus interface name to match on or %NULL to
3422 * match on all interfaces
3423 * @member: (allow-none): D-Bus signal name to match on or %NULL to match on
3425 * @object_path: (allow-none): object path to match on or %NULL to match on
3427 * @arg0: (allow-none): contents of first string argument to match on or %NULL
3428 * to match on all kinds of arguments
3429 * @flags: flags describing how to subscribe to the signal (currently unused)
3430 * @callback: callback to invoke when there is a signal matching the requested data
3431 * @user_data: user data to pass to @callback
3432 * @user_data_free_func: (allow-none): function to free @user_data with when
3433 * subscription is removed or %NULL
3435 * Subscribes to signals on @connection and invokes @callback with a whenever
3436 * the signal is received. Note that @callback will be invoked in the
3437 * [thread-default main context][g-main-context-push-thread-default]
3438 * of the thread you are calling this method from.
3440 * If @connection is not a message bus connection, @sender must be
3443 * If @sender is a well-known name note that @callback is invoked with
3444 * the unique name for the owner of @sender, not the well-known name
3445 * as one would expect. This is because the message bus rewrites the
3446 * name. As such, to avoid certain race conditions, users should be
3447 * tracking the name owner of the well-known name and use that when
3448 * processing the received signal.
3450 * If one of %G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE or
3451 * %G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH are given, @arg0 is
3452 * interpreted as part of a namespace or path. The first argument
3453 * of a signal is matched against that part as specified by D-Bus.
3455 * Returns: a subscription identifier that can be used with g_dbus_connection_signal_unsubscribe()
3460 g_dbus_connection_signal_subscribe (GDBusConnection
*connection
,
3461 const gchar
*sender
,
3462 const gchar
*interface_name
,
3463 const gchar
*member
,
3464 const gchar
*object_path
,
3466 GDBusSignalFlags flags
,
3467 GDBusSignalCallback callback
,
3469 GDestroyNotify user_data_free_func
)
3472 SignalData
*signal_data
;
3473 SignalSubscriber subscriber
;
3474 GPtrArray
*signal_data_array
;
3475 const gchar
*sender_unique_name
;
3477 /* Right now we abort if AddMatch() fails since it can only fail with the bus being in
3478 * an OOM condition. We might want to change that but that would involve making
3479 * g_dbus_connection_signal_subscribe() asynchronous and having the call sites
3480 * handle that. And there's really no sensible way of handling this short of retrying
3481 * to add the match rule... and then there's the little thing that, hey, maybe there's
3482 * a reason the bus in an OOM condition.
3484 * Doable, but not really sure it's worth it...
3487 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), 0);
3488 g_return_val_if_fail (sender
== NULL
|| (g_dbus_is_name (sender
) && (connection
->flags
& G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION
)), 0);
3489 g_return_val_if_fail (interface_name
== NULL
|| g_dbus_is_interface_name (interface_name
), 0);
3490 g_return_val_if_fail (member
== NULL
|| g_dbus_is_member_name (member
), 0);
3491 g_return_val_if_fail (object_path
== NULL
|| g_variant_is_object_path (object_path
), 0);
3492 g_return_val_if_fail (callback
!= NULL
, 0);
3493 g_return_val_if_fail (check_initialized (connection
), 0);
3494 g_return_val_if_fail (!((flags
& G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
) && (flags
& G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
)), 0);
3495 g_return_val_if_fail (!(arg0
== NULL
&& (flags
& (G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
| G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
))), 0);
3497 CONNECTION_LOCK (connection
);
3499 /* If G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE was specified, we will end up
3500 * with a '-' character to prefix the rule (which will otherwise be
3503 * This allows us to hash the rule and do our lifecycle tracking in
3504 * the usual way, but the '-' prevents the match rule from ever
3505 * actually being send to the bus (either for add or remove).
3507 rule
= args_to_rule (sender
, interface_name
, member
, object_path
, arg0
, flags
);
3509 if (sender
!= NULL
&& (g_dbus_is_unique_name (sender
) || g_strcmp0 (sender
, "org.freedesktop.DBus") == 0))
3510 sender_unique_name
= sender
;
3512 sender_unique_name
= "";
3514 subscriber
.callback
= callback
;
3515 subscriber
.user_data
= user_data
;
3516 subscriber
.user_data_free_func
= user_data_free_func
;
3517 subscriber
.id
= _global_subscriber_id
++; /* TODO: overflow etc. */
3518 subscriber
.context
= g_main_context_ref_thread_default ();
3520 /* see if we've already have this rule */
3521 signal_data
= g_hash_table_lookup (connection
->map_rule_to_signal_data
, rule
);
3522 if (signal_data
!= NULL
)
3524 g_array_append_val (signal_data
->subscribers
, subscriber
);
3529 signal_data
= g_new0 (SignalData
, 1);
3530 signal_data
->rule
= rule
;
3531 signal_data
->sender
= g_strdup (sender
);
3532 signal_data
->sender_unique_name
= g_strdup (sender_unique_name
);
3533 signal_data
->interface_name
= g_strdup (interface_name
);
3534 signal_data
->member
= g_strdup (member
);
3535 signal_data
->object_path
= g_strdup (object_path
);
3536 signal_data
->arg0
= g_strdup (arg0
);
3537 signal_data
->flags
= flags
;
3538 signal_data
->subscribers
= g_array_new (FALSE
, FALSE
, sizeof (SignalSubscriber
));
3539 g_array_append_val (signal_data
->subscribers
, subscriber
);
3541 g_hash_table_insert (connection
->map_rule_to_signal_data
,
3545 /* Add the match rule to the bus...
3547 * Avoid adding match rules for NameLost and NameAcquired messages - the bus will
3548 * always send such messages to us.
3550 if (connection
->flags
& G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION
)
3552 if (!is_signal_data_for_name_lost_or_acquired (signal_data
))
3553 add_match_rule (connection
, signal_data
->rule
);
3556 signal_data_array
= g_hash_table_lookup (connection
->map_sender_unique_name_to_signal_data_array
,
3557 signal_data
->sender_unique_name
);
3558 if (signal_data_array
== NULL
)
3560 signal_data_array
= g_ptr_array_new ();
3561 g_hash_table_insert (connection
->map_sender_unique_name_to_signal_data_array
,
3562 g_strdup (signal_data
->sender_unique_name
),
3565 g_ptr_array_add (signal_data_array
, signal_data
);
3568 g_hash_table_insert (connection
->map_id_to_signal_data
,
3569 GUINT_TO_POINTER (subscriber
.id
),
3572 CONNECTION_UNLOCK (connection
);
3574 return subscriber
.id
;
3577 /* ---------------------------------------------------------------------------------------------------- */
3579 /* called in any thread */
3580 /* must hold lock when calling this (except if connection->finalizing is TRUE) */
3582 unsubscribe_id_internal (GDBusConnection
*connection
,
3583 guint subscription_id
,
3584 GArray
*out_removed_subscribers
)
3586 SignalData
*signal_data
;
3587 GPtrArray
*signal_data_array
;
3590 signal_data
= g_hash_table_lookup (connection
->map_id_to_signal_data
,
3591 GUINT_TO_POINTER (subscription_id
));
3592 if (signal_data
== NULL
)
3594 /* Don't warn here, we may have thrown all subscriptions out when the connection was closed */
3598 for (n
= 0; n
< signal_data
->subscribers
->len
; n
++)
3600 SignalSubscriber
*subscriber
;
3602 subscriber
= &(g_array_index (signal_data
->subscribers
, SignalSubscriber
, n
));
3603 if (subscriber
->id
!= subscription_id
)
3606 g_warn_if_fail (g_hash_table_remove (connection
->map_id_to_signal_data
,
3607 GUINT_TO_POINTER (subscription_id
)));
3608 g_array_append_val (out_removed_subscribers
, *subscriber
);
3609 g_array_remove_index (signal_data
->subscribers
, n
);
3611 if (signal_data
->subscribers
->len
== 0)
3613 g_warn_if_fail (g_hash_table_remove (connection
->map_rule_to_signal_data
, signal_data
->rule
));
3615 signal_data_array
= g_hash_table_lookup (connection
->map_sender_unique_name_to_signal_data_array
,
3616 signal_data
->sender_unique_name
);
3617 g_warn_if_fail (signal_data_array
!= NULL
);
3618 g_warn_if_fail (g_ptr_array_remove (signal_data_array
, signal_data
));
3620 if (signal_data_array
->len
== 0)
3622 g_warn_if_fail (g_hash_table_remove (connection
->map_sender_unique_name_to_signal_data_array
,
3623 signal_data
->sender_unique_name
));
3626 /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
3627 if ((connection
->flags
& G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION
) &&
3628 !is_signal_data_for_name_lost_or_acquired (signal_data
) &&
3629 !g_dbus_connection_is_closed (connection
) &&
3630 !connection
->finalizing
)
3632 /* The check for g_dbus_connection_is_closed() means that
3633 * sending the RemoveMatch message can't fail with
3634 * G_IO_ERROR_CLOSED, because we're holding the lock,
3635 * so on_worker_closed() can't happen between the check we just
3636 * did, and releasing the lock later.
3638 remove_match_rule (connection
, signal_data
->rule
);
3641 signal_data_free (signal_data
);
3647 g_assert_not_reached ();
3654 * g_dbus_connection_signal_unsubscribe:
3655 * @connection: a #GDBusConnection
3656 * @subscription_id: a subscription id obtained from
3657 * g_dbus_connection_signal_subscribe()
3659 * Unsubscribes from signals.
3664 g_dbus_connection_signal_unsubscribe (GDBusConnection
*connection
,
3665 guint subscription_id
)
3667 GArray
*subscribers
;
3670 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
3671 g_return_if_fail (check_initialized (connection
));
3673 subscribers
= g_array_new (FALSE
, FALSE
, sizeof (SignalSubscriber
));
3675 CONNECTION_LOCK (connection
);
3676 unsubscribe_id_internal (connection
,
3679 CONNECTION_UNLOCK (connection
);
3682 g_assert (subscribers
->len
== 0 || subscribers
->len
== 1);
3684 /* call GDestroyNotify without lock held */
3685 for (n
= 0; n
< subscribers
->len
; n
++)
3687 SignalSubscriber
*subscriber
;
3688 subscriber
= &(g_array_index (subscribers
, SignalSubscriber
, n
));
3689 call_destroy_notify (subscriber
->context
,
3690 subscriber
->user_data_free_func
,
3691 subscriber
->user_data
);
3692 g_main_context_unref (subscriber
->context
);
3695 g_array_free (subscribers
, TRUE
);
3698 /* ---------------------------------------------------------------------------------------------------- */
3702 guint subscription_id
;
3703 GDBusSignalCallback callback
;
3705 GDBusMessage
*message
;
3706 GDBusConnection
*connection
;
3707 const gchar
*sender
;
3709 const gchar
*interface
;
3710 const gchar
*member
;
3713 /* called on delivery thread (e.g. where g_dbus_connection_signal_subscribe() was called) with
3717 emit_signal_instance_in_idle_cb (gpointer data
)
3719 SignalInstance
*signal_instance
= data
;
3720 GVariant
*parameters
;
3721 gboolean has_subscription
;
3723 parameters
= g_dbus_message_get_body (signal_instance
->message
);
3724 if (parameters
== NULL
)
3726 parameters
= g_variant_new ("()");
3727 g_variant_ref_sink (parameters
);
3731 g_variant_ref_sink (parameters
);
3735 g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n",
3736 signal_instance
->subscription_id
,
3737 signal_instance
->sender
,
3738 signal_instance
->path
,
3739 signal_instance
->interface
,
3740 signal_instance
->member
,
3741 g_variant_print (parameters
, TRUE
));
3744 /* Careful here, don't do the callback if we no longer has the subscription */
3745 CONNECTION_LOCK (signal_instance
->connection
);
3746 has_subscription
= FALSE
;
3747 if (g_hash_table_lookup (signal_instance
->connection
->map_id_to_signal_data
,
3748 GUINT_TO_POINTER (signal_instance
->subscription_id
)) != NULL
)
3749 has_subscription
= TRUE
;
3750 CONNECTION_UNLOCK (signal_instance
->connection
);
3752 if (has_subscription
)
3753 signal_instance
->callback (signal_instance
->connection
,
3754 signal_instance
->sender
,
3755 signal_instance
->path
,
3756 signal_instance
->interface
,
3757 signal_instance
->member
,
3759 signal_instance
->user_data
);
3761 g_variant_unref (parameters
);
3767 signal_instance_free (SignalInstance
*signal_instance
)
3769 g_object_unref (signal_instance
->message
);
3770 g_object_unref (signal_instance
->connection
);
3771 g_free (signal_instance
);
3775 namespace_rule_matches (const gchar
*namespace,
3781 len_namespace
= strlen (namespace);
3782 len_name
= strlen (name
);
3784 if (len_name
< len_namespace
)
3787 if (memcmp (namespace, name
, len_namespace
) != 0)
3790 return len_namespace
== len_name
|| name
[len_namespace
] == '.';
3794 path_rule_matches (const gchar
*path_a
,
3795 const gchar
*path_b
)
3799 len_a
= strlen (path_a
);
3800 len_b
= strlen (path_b
);
3802 if (len_a
< len_b
&& path_a
[len_a
- 1] != '/')
3805 if (len_b
< len_a
&& path_b
[len_b
- 1] != '/')
3808 return memcmp (path_a
, path_b
, MIN (len_a
, len_b
)) == 0;
3811 /* called in GDBusWorker thread WITH lock held */
3813 schedule_callbacks (GDBusConnection
*connection
,
3814 GPtrArray
*signal_data_array
,
3815 GDBusMessage
*message
,
3816 const gchar
*sender
)
3819 const gchar
*interface
;
3820 const gchar
*member
;
3829 interface
= g_dbus_message_get_interface (message
);
3830 member
= g_dbus_message_get_member (message
);
3831 path
= g_dbus_message_get_path (message
);
3832 arg0
= g_dbus_message_get_arg0 (message
);
3835 g_print ("In schedule_callbacks:\n"
3837 " interface = '%s'\n"
3848 /* TODO: if this is slow, then we can change signal_data_array into
3849 * map_object_path_to_signal_data_array or something.
3851 for (n
= 0; n
< signal_data_array
->len
; n
++)
3853 SignalData
*signal_data
= signal_data_array
->pdata
[n
];
3855 if (signal_data
->interface_name
!= NULL
&& g_strcmp0 (signal_data
->interface_name
, interface
) != 0)
3858 if (signal_data
->member
!= NULL
&& g_strcmp0 (signal_data
->member
, member
) != 0)
3861 if (signal_data
->object_path
!= NULL
&& g_strcmp0 (signal_data
->object_path
, path
) != 0)
3864 if (signal_data
->arg0
!= NULL
)
3869 if (signal_data
->flags
& G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
)
3871 if (!namespace_rule_matches (signal_data
->arg0
, arg0
))
3874 else if (signal_data
->flags
& G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
)
3876 if (!path_rule_matches (signal_data
->arg0
, arg0
))
3879 else if (!g_str_equal (signal_data
->arg0
, arg0
))
3883 for (m
= 0; m
< signal_data
->subscribers
->len
; m
++)
3885 SignalSubscriber
*subscriber
;
3886 GSource
*idle_source
;
3887 SignalInstance
*signal_instance
;
3889 subscriber
= &(g_array_index (signal_data
->subscribers
, SignalSubscriber
, m
));
3891 signal_instance
= g_new0 (SignalInstance
, 1);
3892 signal_instance
->subscription_id
= subscriber
->id
;
3893 signal_instance
->callback
= subscriber
->callback
;
3894 signal_instance
->user_data
= subscriber
->user_data
;
3895 signal_instance
->message
= g_object_ref (message
);
3896 signal_instance
->connection
= g_object_ref (connection
);
3897 signal_instance
->sender
= sender
;
3898 signal_instance
->path
= path
;
3899 signal_instance
->interface
= interface
;
3900 signal_instance
->member
= member
;
3902 idle_source
= g_idle_source_new ();
3903 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
3904 g_source_set_callback (idle_source
,
3905 emit_signal_instance_in_idle_cb
,
3907 (GDestroyNotify
) signal_instance_free
);
3908 g_source_set_name (idle_source
, "[gio] emit_signal_instance_in_idle_cb");
3909 g_source_attach (idle_source
, subscriber
->context
);
3910 g_source_unref (idle_source
);
3915 /* called in GDBusWorker thread with lock held */
3917 distribute_signals (GDBusConnection
*connection
,
3918 GDBusMessage
*message
)
3920 GPtrArray
*signal_data_array
;
3921 const gchar
*sender
;
3923 sender
= g_dbus_message_get_sender (message
);
3925 if (G_UNLIKELY (_g_dbus_debug_signal ()))
3927 _g_dbus_debug_print_lock ();
3928 g_print ("========================================================================\n"
3929 "GDBus-debug:Signal:\n"
3930 " <<<< RECEIVED SIGNAL %s.%s\n"
3932 " sent by name %s\n",
3933 g_dbus_message_get_interface (message
),
3934 g_dbus_message_get_member (message
),
3935 g_dbus_message_get_path (message
),
3936 sender
!= NULL
? sender
: "(none)");
3937 _g_dbus_debug_print_unlock ();
3940 /* collect subscribers that match on sender */
3943 signal_data_array
= g_hash_table_lookup (connection
->map_sender_unique_name_to_signal_data_array
, sender
);
3944 if (signal_data_array
!= NULL
)
3945 schedule_callbacks (connection
, signal_data_array
, message
, sender
);
3948 /* collect subscribers not matching on sender */
3949 signal_data_array
= g_hash_table_lookup (connection
->map_sender_unique_name_to_signal_data_array
, "");
3950 if (signal_data_array
!= NULL
)
3951 schedule_callbacks (connection
, signal_data_array
, message
, sender
);
3954 /* ---------------------------------------------------------------------------------------------------- */
3956 /* only called from finalize(), removes all subscriptions */
3958 purge_all_signal_subscriptions (GDBusConnection
*connection
)
3960 GHashTableIter iter
;
3963 GArray
*subscribers
;
3966 ids
= g_array_new (FALSE
, FALSE
, sizeof (guint
));
3967 g_hash_table_iter_init (&iter
, connection
->map_id_to_signal_data
);
3968 while (g_hash_table_iter_next (&iter
, &key
, NULL
))
3970 guint subscription_id
= GPOINTER_TO_UINT (key
);
3971 g_array_append_val (ids
, subscription_id
);
3974 subscribers
= g_array_new (FALSE
, FALSE
, sizeof (SignalSubscriber
));
3975 for (n
= 0; n
< ids
->len
; n
++)
3977 guint subscription_id
= g_array_index (ids
, guint
, n
);
3978 unsubscribe_id_internal (connection
,
3982 g_array_free (ids
, TRUE
);
3984 /* call GDestroyNotify without lock held */
3985 for (n
= 0; n
< subscribers
->len
; n
++)
3987 SignalSubscriber
*subscriber
;
3988 subscriber
= &(g_array_index (subscribers
, SignalSubscriber
, n
));
3989 call_destroy_notify (subscriber
->context
,
3990 subscriber
->user_data_free_func
,
3991 subscriber
->user_data
);
3992 g_main_context_unref (subscriber
->context
);
3995 g_array_free (subscribers
, TRUE
);
3998 /* ---------------------------------------------------------------------------------------------------- */
4000 static GDBusInterfaceVTable
*
4001 _g_dbus_interface_vtable_copy (const GDBusInterfaceVTable
*vtable
)
4003 /* Don't waste memory by copying padding - remember to update this
4004 * when changing struct _GDBusInterfaceVTable in gdbusconnection.h
4006 return g_memdup ((gconstpointer
) vtable
, 3 * sizeof (gpointer
));
4010 _g_dbus_interface_vtable_free (GDBusInterfaceVTable
*vtable
)
4015 /* ---------------------------------------------------------------------------------------------------- */
4017 static GDBusSubtreeVTable
*
4018 _g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable
*vtable
)
4020 /* Don't waste memory by copying padding - remember to update this
4021 * when changing struct _GDBusSubtreeVTable in gdbusconnection.h
4023 return g_memdup ((gconstpointer
) vtable
, 3 * sizeof (gpointer
));
4027 _g_dbus_subtree_vtable_free (GDBusSubtreeVTable
*vtable
)
4032 /* ---------------------------------------------------------------------------------------------------- */
4034 struct ExportedObject
4037 GDBusConnection
*connection
;
4039 /* maps gchar* -> ExportedInterface* */
4040 GHashTable
*map_if_name_to_ei
;
4043 /* only called with lock held */
4045 exported_object_free (ExportedObject
*eo
)
4047 g_free (eo
->object_path
);
4048 g_hash_table_unref (eo
->map_if_name_to_ei
);
4057 gchar
*interface_name
;
4058 GDBusInterfaceVTable
*vtable
;
4059 GDBusInterfaceInfo
*interface_info
;
4061 GMainContext
*context
;
4063 GDestroyNotify user_data_free_func
;
4064 } ExportedInterface
;
4066 /* called with lock held */
4068 exported_interface_free (ExportedInterface
*ei
)
4070 g_dbus_interface_info_cache_release (ei
->interface_info
);
4071 g_dbus_interface_info_unref ((GDBusInterfaceInfo
*) ei
->interface_info
);
4073 call_destroy_notify (ei
->context
,
4074 ei
->user_data_free_func
,
4077 g_main_context_unref (ei
->context
);
4079 g_free (ei
->interface_name
);
4080 _g_dbus_interface_vtable_free (ei
->vtable
);
4084 /* ---------------------------------------------------------------------------------------------------- */
4086 /* Convenience function to check if @registration_id (if not zero) or
4087 * @subtree_registration_id (if not zero) has been unregistered. If
4088 * so, returns %TRUE.
4090 * May be called by any thread. Caller must *not* hold lock.
4093 has_object_been_unregistered (GDBusConnection
*connection
,
4094 guint registration_id
,
4095 guint subtree_registration_id
)
4099 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
4103 CONNECTION_LOCK (connection
);
4104 if (registration_id
!= 0 && g_hash_table_lookup (connection
->map_id_to_ei
,
4105 GUINT_TO_POINTER (registration_id
)) == NULL
)
4109 else if (subtree_registration_id
!= 0 && g_hash_table_lookup (connection
->map_id_to_es
,
4110 GUINT_TO_POINTER (subtree_registration_id
)) == NULL
)
4114 CONNECTION_UNLOCK (connection
);
4119 /* ---------------------------------------------------------------------------------------------------- */
4123 GDBusConnection
*connection
;
4124 GDBusMessage
*message
;
4126 const gchar
*property_name
;
4127 const GDBusInterfaceVTable
*vtable
;
4128 GDBusInterfaceInfo
*interface_info
;
4129 const GDBusPropertyInfo
*property_info
;
4130 guint registration_id
;
4131 guint subtree_registration_id
;
4135 property_data_free (PropertyData
*data
)
4137 g_object_unref (data
->connection
);
4138 g_object_unref (data
->message
);
4142 /* called in thread where object was registered - no locks held */
4144 invoke_get_property_in_idle_cb (gpointer _data
)
4146 PropertyData
*data
= _data
;
4149 GDBusMessage
*reply
;
4151 if (has_object_been_unregistered (data
->connection
,
4152 data
->registration_id
,
4153 data
->subtree_registration_id
))
4155 reply
= g_dbus_message_new_method_error (data
->message
,
4156 "org.freedesktop.DBus.Error.UnknownMethod",
4157 _("No such interface 'org.freedesktop.DBus.Properties' on object at path %s"),
4158 g_dbus_message_get_path (data
->message
));
4159 g_dbus_connection_send_message (data
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4160 g_object_unref (reply
);
4165 value
= data
->vtable
->get_property (data
->connection
,
4166 g_dbus_message_get_sender (data
->message
),
4167 g_dbus_message_get_path (data
->message
),
4168 data
->interface_info
->name
,
4169 data
->property_name
,
4176 g_assert_no_error (error
);
4178 g_variant_take_ref (value
);
4179 reply
= g_dbus_message_new_method_reply (data
->message
);
4180 g_dbus_message_set_body (reply
, g_variant_new ("(v)", value
));
4181 g_dbus_connection_send_message (data
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4182 g_variant_unref (value
);
4183 g_object_unref (reply
);
4187 gchar
*dbus_error_name
;
4188 g_assert (error
!= NULL
);
4189 dbus_error_name
= g_dbus_error_encode_gerror (error
);
4190 reply
= g_dbus_message_new_method_error_literal (data
->message
,
4193 g_dbus_connection_send_message (data
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4194 g_free (dbus_error_name
);
4195 g_error_free (error
);
4196 g_object_unref (reply
);
4203 /* called in thread where object was registered - no locks held */
4205 invoke_set_property_in_idle_cb (gpointer _data
)
4207 PropertyData
*data
= _data
;
4209 GDBusMessage
*reply
;
4215 g_variant_get (g_dbus_message_get_body (data
->message
),
4221 if (!data
->vtable
->set_property (data
->connection
,
4222 g_dbus_message_get_sender (data
->message
),
4223 g_dbus_message_get_path (data
->message
),
4224 data
->interface_info
->name
,
4225 data
->property_name
,
4230 gchar
*dbus_error_name
;
4231 g_assert (error
!= NULL
);
4232 dbus_error_name
= g_dbus_error_encode_gerror (error
);
4233 reply
= g_dbus_message_new_method_error_literal (data
->message
,
4236 g_free (dbus_error_name
);
4237 g_error_free (error
);
4241 reply
= g_dbus_message_new_method_reply (data
->message
);
4244 g_assert (reply
!= NULL
);
4245 g_dbus_connection_send_message (data
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4246 g_object_unref (reply
);
4247 g_variant_unref (value
);
4252 /* called in any thread with connection's lock held */
4254 validate_and_maybe_schedule_property_getset (GDBusConnection
*connection
,
4255 GDBusMessage
*message
,
4256 guint registration_id
,
4257 guint subtree_registration_id
,
4259 GDBusInterfaceInfo
*interface_info
,
4260 const GDBusInterfaceVTable
*vtable
,
4261 GMainContext
*main_context
,
4265 const char *interface_name
;
4266 const char *property_name
;
4267 const GDBusPropertyInfo
*property_info
;
4268 GSource
*idle_source
;
4269 PropertyData
*property_data
;
4270 GDBusMessage
*reply
;
4275 g_variant_get (g_dbus_message_get_body (message
),
4280 g_variant_get (g_dbus_message_get_body (message
),
4289 /* Check that the property exists - if not fail with org.freedesktop.DBus.Error.InvalidArgs
4291 property_info
= NULL
;
4293 /* TODO: the cost of this is O(n) - it might be worth caching the result */
4294 property_info
= g_dbus_interface_info_lookup_property (interface_info
, property_name
);
4295 if (property_info
== NULL
)
4297 reply
= g_dbus_message_new_method_error (message
,
4298 "org.freedesktop.DBus.Error.InvalidArgs",
4299 _("No such property '%s'"),
4301 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4302 g_object_unref (reply
);
4307 if (is_get
&& !(property_info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_READABLE
))
4309 reply
= g_dbus_message_new_method_error (message
,
4310 "org.freedesktop.DBus.Error.InvalidArgs",
4311 _("Property '%s' is not readable"),
4313 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4314 g_object_unref (reply
);
4318 else if (!is_get
&& !(property_info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
))
4320 reply
= g_dbus_message_new_method_error (message
,
4321 "org.freedesktop.DBus.Error.InvalidArgs",
4322 _("Property '%s' is not writable"),
4324 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4325 g_object_unref (reply
);
4334 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the type
4335 * of the given value is wrong
4337 g_variant_get_child (g_dbus_message_get_body (message
), 2, "v", &value
);
4338 if (g_strcmp0 (g_variant_get_type_string (value
), property_info
->signature
) != 0)
4340 reply
= g_dbus_message_new_method_error (message
,
4341 "org.freedesktop.DBus.Error.InvalidArgs",
4342 _("Error setting property '%s': Expected type '%s' but got '%s'"),
4343 property_name
, property_info
->signature
,
4344 g_variant_get_type_string (value
));
4345 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4346 g_variant_unref (value
);
4347 g_object_unref (reply
);
4352 g_variant_unref (value
);
4355 /* If the vtable pointer for get_property() resp. set_property() is
4356 * NULL then dispatch the call via the method_call() handler.
4360 if (vtable
->get_property
== NULL
)
4362 schedule_method_call (connection
, message
, registration_id
, subtree_registration_id
,
4363 interface_info
, NULL
, property_info
, g_dbus_message_get_body (message
),
4364 vtable
, main_context
, user_data
);
4371 if (vtable
->set_property
== NULL
)
4373 schedule_method_call (connection
, message
, registration_id
, subtree_registration_id
,
4374 interface_info
, NULL
, property_info
, g_dbus_message_get_body (message
),
4375 vtable
, main_context
, user_data
);
4381 /* ok, got the property info - call user code in an idle handler */
4382 property_data
= g_new0 (PropertyData
, 1);
4383 property_data
->connection
= g_object_ref (connection
);
4384 property_data
->message
= g_object_ref (message
);
4385 property_data
->user_data
= user_data
;
4386 property_data
->property_name
= property_name
;
4387 property_data
->vtable
= vtable
;
4388 property_data
->interface_info
= interface_info
;
4389 property_data
->property_info
= property_info
;
4390 property_data
->registration_id
= registration_id
;
4391 property_data
->subtree_registration_id
= subtree_registration_id
;
4393 idle_source
= g_idle_source_new ();
4394 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
4395 g_source_set_callback (idle_source
,
4396 is_get
? invoke_get_property_in_idle_cb
: invoke_set_property_in_idle_cb
,
4398 (GDestroyNotify
) property_data_free
);
4400 g_source_set_name (idle_source
, "[gio] invoke_get_property_in_idle_cb");
4402 g_source_set_name (idle_source
, "[gio] invoke_set_property_in_idle_cb");
4403 g_source_attach (idle_source
, main_context
);
4404 g_source_unref (idle_source
);
4412 /* called in GDBusWorker thread with connection's lock held */
4414 handle_getset_property (GDBusConnection
*connection
,
4416 GDBusMessage
*message
,
4419 ExportedInterface
*ei
;
4421 const char *interface_name
;
4422 const char *property_name
;
4427 g_variant_get (g_dbus_message_get_body (message
),
4432 g_variant_get (g_dbus_message_get_body (message
),
4438 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
4439 * no such interface registered
4441 ei
= g_hash_table_lookup (eo
->map_if_name_to_ei
, interface_name
);
4444 GDBusMessage
*reply
;
4445 reply
= g_dbus_message_new_method_error (message
,
4446 "org.freedesktop.DBus.Error.InvalidArgs",
4447 _("No such interface '%s'"),
4449 g_dbus_connection_send_message_unlocked (eo
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4450 g_object_unref (reply
);
4455 handled
= validate_and_maybe_schedule_property_getset (eo
->connection
,
4468 /* ---------------------------------------------------------------------------------------------------- */
4472 GDBusConnection
*connection
;
4473 GDBusMessage
*message
;
4475 const GDBusInterfaceVTable
*vtable
;
4476 GDBusInterfaceInfo
*interface_info
;
4477 guint registration_id
;
4478 guint subtree_registration_id
;
4479 } PropertyGetAllData
;
4482 property_get_all_data_free (PropertyData
*data
)
4484 g_object_unref (data
->connection
);
4485 g_object_unref (data
->message
);
4489 /* called in thread where object was registered - no locks held */
4491 invoke_get_all_properties_in_idle_cb (gpointer _data
)
4493 PropertyGetAllData
*data
= _data
;
4494 GVariantBuilder builder
;
4495 GDBusMessage
*reply
;
4498 if (has_object_been_unregistered (data
->connection
,
4499 data
->registration_id
,
4500 data
->subtree_registration_id
))
4502 reply
= g_dbus_message_new_method_error (data
->message
,
4503 "org.freedesktop.DBus.Error.UnknownMethod",
4504 _("No such interface 'org.freedesktop.DBus.Properties' on object at path %s"),
4505 g_dbus_message_get_path (data
->message
));
4506 g_dbus_connection_send_message (data
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4507 g_object_unref (reply
);
4511 /* TODO: Right now we never fail this call - we just omit values if
4512 * a get_property() call is failing.
4514 * We could fail the whole call if just a single get_property() call
4515 * returns an error. We need clarification in the D-Bus spec about this.
4517 g_variant_builder_init (&builder
, G_VARIANT_TYPE ("(a{sv})"));
4518 g_variant_builder_open (&builder
, G_VARIANT_TYPE ("a{sv}"));
4519 for (n
= 0; data
->interface_info
->properties
!= NULL
&& data
->interface_info
->properties
[n
] != NULL
; n
++)
4521 const GDBusPropertyInfo
*property_info
= data
->interface_info
->properties
[n
];
4524 if (!(property_info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_READABLE
))
4527 value
= data
->vtable
->get_property (data
->connection
,
4528 g_dbus_message_get_sender (data
->message
),
4529 g_dbus_message_get_path (data
->message
),
4530 data
->interface_info
->name
,
4531 property_info
->name
,
4538 g_variant_take_ref (value
);
4539 g_variant_builder_add (&builder
,
4541 property_info
->name
,
4543 g_variant_unref (value
);
4545 g_variant_builder_close (&builder
);
4547 reply
= g_dbus_message_new_method_reply (data
->message
);
4548 g_dbus_message_set_body (reply
, g_variant_builder_end (&builder
));
4549 g_dbus_connection_send_message (data
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4550 g_object_unref (reply
);
4557 interface_has_readable_properties (GDBusInterfaceInfo
*interface_info
)
4561 if (!interface_info
->properties
)
4564 for (i
= 0; interface_info
->properties
[i
]; i
++)
4565 if (interface_info
->properties
[i
]->flags
& G_DBUS_PROPERTY_INFO_FLAGS_READABLE
)
4571 /* called in any thread with connection's lock held */
4573 validate_and_maybe_schedule_property_get_all (GDBusConnection
*connection
,
4574 GDBusMessage
*message
,
4575 guint registration_id
,
4576 guint subtree_registration_id
,
4577 GDBusInterfaceInfo
*interface_info
,
4578 const GDBusInterfaceVTable
*vtable
,
4579 GMainContext
*main_context
,
4583 GSource
*idle_source
;
4584 PropertyGetAllData
*property_get_all_data
;
4591 /* If the vtable pointer for get_property() is NULL but we have a
4592 * non-zero number of readable properties, then dispatch the call via
4593 * the method_call() handler.
4595 if (vtable
->get_property
== NULL
&& interface_has_readable_properties (interface_info
))
4597 schedule_method_call (connection
, message
, registration_id
, subtree_registration_id
,
4598 interface_info
, NULL
, NULL
, g_dbus_message_get_body (message
),
4599 vtable
, main_context
, user_data
);
4604 /* ok, got the property info - call user in an idle handler */
4605 property_get_all_data
= g_new0 (PropertyGetAllData
, 1);
4606 property_get_all_data
->connection
= g_object_ref (connection
);
4607 property_get_all_data
->message
= g_object_ref (message
);
4608 property_get_all_data
->user_data
= user_data
;
4609 property_get_all_data
->vtable
= vtable
;
4610 property_get_all_data
->interface_info
= interface_info
;
4611 property_get_all_data
->registration_id
= registration_id
;
4612 property_get_all_data
->subtree_registration_id
= subtree_registration_id
;
4614 idle_source
= g_idle_source_new ();
4615 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
4616 g_source_set_callback (idle_source
,
4617 invoke_get_all_properties_in_idle_cb
,
4618 property_get_all_data
,
4619 (GDestroyNotify
) property_get_all_data_free
);
4620 g_source_set_name (idle_source
, "[gio] invoke_get_all_properties_in_idle_cb");
4621 g_source_attach (idle_source
, main_context
);
4622 g_source_unref (idle_source
);
4630 /* called in GDBusWorker thread with connection's lock held */
4632 handle_get_all_properties (GDBusConnection
*connection
,
4634 GDBusMessage
*message
)
4636 ExportedInterface
*ei
;
4638 const char *interface_name
;
4642 g_variant_get (g_dbus_message_get_body (message
),
4646 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if there is
4647 * no such interface registered
4649 ei
= g_hash_table_lookup (eo
->map_if_name_to_ei
, interface_name
);
4652 GDBusMessage
*reply
;
4653 reply
= g_dbus_message_new_method_error (message
,
4654 "org.freedesktop.DBus.Error.InvalidArgs",
4655 _("No such interface"),
4657 g_dbus_connection_send_message_unlocked (eo
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4658 g_object_unref (reply
);
4663 handled
= validate_and_maybe_schedule_property_get_all (eo
->connection
,
4675 /* ---------------------------------------------------------------------------------------------------- */
4677 static const gchar introspect_header
[] =
4678 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
4679 " \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
4680 "<!-- GDBus " PACKAGE_VERSION
" -->\n"
4683 static const gchar introspect_tail
[] =
4686 static const gchar introspect_properties_interface
[] =
4687 " <interface name=\"org.freedesktop.DBus.Properties\">\n"
4688 " <method name=\"Get\">\n"
4689 " <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
4690 " <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
4691 " <arg type=\"v\" name=\"value\" direction=\"out\"/>\n"
4693 " <method name=\"GetAll\">\n"
4694 " <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
4695 " <arg type=\"a{sv}\" name=\"properties\" direction=\"out\"/>\n"
4697 " <method name=\"Set\">\n"
4698 " <arg type=\"s\" name=\"interface_name\" direction=\"in\"/>\n"
4699 " <arg type=\"s\" name=\"property_name\" direction=\"in\"/>\n"
4700 " <arg type=\"v\" name=\"value\" direction=\"in\"/>\n"
4702 " <signal name=\"PropertiesChanged\">\n"
4703 " <arg type=\"s\" name=\"interface_name\"/>\n"
4704 " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"
4705 " <arg type=\"as\" name=\"invalidated_properties\"/>\n"
4709 static const gchar introspect_introspectable_interface
[] =
4710 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
4711 " <method name=\"Introspect\">\n"
4712 " <arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
4715 " <interface name=\"org.freedesktop.DBus.Peer\">\n"
4716 " <method name=\"Ping\"/>\n"
4717 " <method name=\"GetMachineId\">\n"
4718 " <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n"
4723 introspect_append_header (GString
*s
)
4725 g_string_append (s
, introspect_header
);
4729 maybe_add_path (const gchar
*path
, gsize path_len
, const gchar
*object_path
, GHashTable
*set
)
4731 if (g_str_has_prefix (object_path
, path
) && strlen (object_path
) > path_len
&& object_path
[path_len
-1] == '/')
4737 begin
= object_path
+ path_len
;
4738 end
= strchr (begin
, '/');
4740 s
= g_strndup (begin
, end
- begin
);
4742 s
= g_strdup (begin
);
4744 if (g_hash_table_lookup (set
, s
) == NULL
)
4745 g_hash_table_insert (set
, s
, GUINT_TO_POINTER (1));
4751 /* TODO: we want a nicer public interface for this */
4752 /* called in any thread with connection's lock held */
4754 g_dbus_connection_list_registered_unlocked (GDBusConnection
*connection
,
4759 GHashTableIter hash_iter
;
4760 const gchar
*object_path
;
4766 CONNECTION_ENSURE_LOCK (connection
);
4768 path_len
= strlen (path
);
4772 set
= g_hash_table_new (g_str_hash
, g_str_equal
);
4774 g_hash_table_iter_init (&hash_iter
, connection
->map_object_path_to_eo
);
4775 while (g_hash_table_iter_next (&hash_iter
, (gpointer
) &object_path
, NULL
))
4776 maybe_add_path (path
, path_len
, object_path
, set
);
4778 g_hash_table_iter_init (&hash_iter
, connection
->map_object_path_to_es
);
4779 while (g_hash_table_iter_next (&hash_iter
, (gpointer
) &object_path
, NULL
))
4780 maybe_add_path (path
, path_len
, object_path
, set
);
4782 p
= g_ptr_array_new ();
4783 keys
= g_hash_table_get_keys (set
);
4784 for (l
= keys
; l
!= NULL
; l
= l
->next
)
4785 g_ptr_array_add (p
, l
->data
);
4786 g_hash_table_unref (set
);
4789 g_ptr_array_add (p
, NULL
);
4790 ret
= (gchar
**) g_ptr_array_free (p
, FALSE
);
4794 /* called in any thread with connection's lock not held */
4796 g_dbus_connection_list_registered (GDBusConnection
*connection
,
4800 CONNECTION_LOCK (connection
);
4801 ret
= g_dbus_connection_list_registered_unlocked (connection
, path
);
4802 CONNECTION_UNLOCK (connection
);
4806 /* called in GDBusWorker thread with connection's lock held */
4808 handle_introspect (GDBusConnection
*connection
,
4810 GDBusMessage
*message
)
4814 GDBusMessage
*reply
;
4815 GHashTableIter hash_iter
;
4816 ExportedInterface
*ei
;
4819 /* first the header with the standard interfaces */
4820 s
= g_string_sized_new (sizeof (introspect_header
) +
4821 sizeof (introspect_properties_interface
) +
4822 sizeof (introspect_introspectable_interface
) +
4823 sizeof (introspect_tail
));
4824 introspect_append_header (s
);
4825 if (!g_hash_table_lookup (eo
->map_if_name_to_ei
,
4826 "org.freedesktop.DBus.Properties"))
4827 g_string_append (s
, introspect_properties_interface
);
4829 if (!g_hash_table_lookup (eo
->map_if_name_to_ei
,
4830 "org.freedesktop.DBus.Introspectable"))
4831 g_string_append (s
, introspect_introspectable_interface
);
4833 /* then include the registered interfaces */
4834 g_hash_table_iter_init (&hash_iter
, eo
->map_if_name_to_ei
);
4835 while (g_hash_table_iter_next (&hash_iter
, NULL
, (gpointer
) &ei
))
4836 g_dbus_interface_info_generate_xml (ei
->interface_info
, 2, s
);
4838 /* finally include nodes registered below us */
4839 registered
= g_dbus_connection_list_registered_unlocked (connection
, eo
->object_path
);
4840 for (n
= 0; registered
!= NULL
&& registered
[n
] != NULL
; n
++)
4841 g_string_append_printf (s
, " <node name=\"%s\"/>\n", registered
[n
]);
4842 g_strfreev (registered
);
4843 g_string_append (s
, introspect_tail
);
4845 reply
= g_dbus_message_new_method_reply (message
);
4846 g_dbus_message_set_body (reply
, g_variant_new ("(s)", s
->str
));
4847 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4848 g_object_unref (reply
);
4849 g_string_free (s
, TRUE
);
4854 /* called in thread where object was registered - no locks held */
4856 call_in_idle_cb (gpointer user_data
)
4858 GDBusMethodInvocation
*invocation
= G_DBUS_METHOD_INVOCATION (user_data
);
4859 GDBusInterfaceVTable
*vtable
;
4860 guint registration_id
;
4861 guint subtree_registration_id
;
4863 registration_id
= GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (invocation
), "g-dbus-registration-id"));
4864 subtree_registration_id
= GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (invocation
), "g-dbus-subtree-registration-id"));
4866 if (has_object_been_unregistered (g_dbus_method_invocation_get_connection (invocation
),
4868 subtree_registration_id
))
4870 GDBusMessage
*reply
;
4871 reply
= g_dbus_message_new_method_error (g_dbus_method_invocation_get_message (invocation
),
4872 "org.freedesktop.DBus.Error.UnknownMethod",
4873 _("No such interface '%s' on object at path %s"),
4874 g_dbus_method_invocation_get_interface_name (invocation
),
4875 g_dbus_method_invocation_get_object_path (invocation
));
4876 g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation
), reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4877 g_object_unref (reply
);
4881 vtable
= g_object_get_data (G_OBJECT (invocation
), "g-dbus-interface-vtable");
4882 g_assert (vtable
!= NULL
&& vtable
->method_call
!= NULL
);
4884 vtable
->method_call (g_dbus_method_invocation_get_connection (invocation
),
4885 g_dbus_method_invocation_get_sender (invocation
),
4886 g_dbus_method_invocation_get_object_path (invocation
),
4887 g_dbus_method_invocation_get_interface_name (invocation
),
4888 g_dbus_method_invocation_get_method_name (invocation
),
4889 g_dbus_method_invocation_get_parameters (invocation
),
4890 g_object_ref (invocation
),
4891 g_dbus_method_invocation_get_user_data (invocation
));
4897 /* called in GDBusWorker thread with connection's lock held */
4899 schedule_method_call (GDBusConnection
*connection
,
4900 GDBusMessage
*message
,
4901 guint registration_id
,
4902 guint subtree_registration_id
,
4903 const GDBusInterfaceInfo
*interface_info
,
4904 const GDBusMethodInfo
*method_info
,
4905 const GDBusPropertyInfo
*property_info
,
4906 GVariant
*parameters
,
4907 const GDBusInterfaceVTable
*vtable
,
4908 GMainContext
*main_context
,
4911 GDBusMethodInvocation
*invocation
;
4912 GSource
*idle_source
;
4914 invocation
= _g_dbus_method_invocation_new (g_dbus_message_get_sender (message
),
4915 g_dbus_message_get_path (message
),
4916 g_dbus_message_get_interface (message
),
4917 g_dbus_message_get_member (message
),
4925 /* TODO: would be nicer with a real MethodData like we already
4926 * have PropertyData and PropertyGetAllData... */
4927 g_object_set_data (G_OBJECT (invocation
), "g-dbus-interface-vtable", (gpointer
) vtable
);
4928 g_object_set_data (G_OBJECT (invocation
), "g-dbus-registration-id", GUINT_TO_POINTER (registration_id
));
4929 g_object_set_data (G_OBJECT (invocation
), "g-dbus-subtree-registration-id", GUINT_TO_POINTER (subtree_registration_id
));
4931 idle_source
= g_idle_source_new ();
4932 g_source_set_priority (idle_source
, G_PRIORITY_DEFAULT
);
4933 g_source_set_callback (idle_source
,
4937 g_source_set_name (idle_source
, "[gio] call_in_idle_cb");
4938 g_source_attach (idle_source
, main_context
);
4939 g_source_unref (idle_source
);
4942 /* called in GDBusWorker thread with connection's lock held */
4944 validate_and_maybe_schedule_method_call (GDBusConnection
*connection
,
4945 GDBusMessage
*message
,
4946 guint registration_id
,
4947 guint subtree_registration_id
,
4948 GDBusInterfaceInfo
*interface_info
,
4949 const GDBusInterfaceVTable
*vtable
,
4950 GMainContext
*main_context
,
4953 GDBusMethodInfo
*method_info
;
4954 GDBusMessage
*reply
;
4955 GVariant
*parameters
;
4957 GVariantType
*in_type
;
4961 /* TODO: the cost of this is O(n) - it might be worth caching the result */
4962 method_info
= g_dbus_interface_info_lookup_method (interface_info
, g_dbus_message_get_member (message
));
4964 /* if the method doesn't exist, return the org.freedesktop.DBus.Error.UnknownMethod
4965 * error to the caller
4967 if (method_info
== NULL
)
4969 reply
= g_dbus_message_new_method_error (message
,
4970 "org.freedesktop.DBus.Error.UnknownMethod",
4971 _("No such method '%s'"),
4972 g_dbus_message_get_member (message
));
4973 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
4974 g_object_unref (reply
);
4979 parameters
= g_dbus_message_get_body (message
);
4980 if (parameters
== NULL
)
4982 parameters
= g_variant_new ("()");
4983 g_variant_ref_sink (parameters
);
4987 g_variant_ref (parameters
);
4990 /* Check that the incoming args are of the right type - if they are not, return
4991 * the org.freedesktop.DBus.Error.InvalidArgs error to the caller
4993 in_type
= _g_dbus_compute_complete_signature (method_info
->in_args
);
4994 if (!g_variant_is_of_type (parameters
, in_type
))
4998 type_string
= g_variant_type_dup_string (in_type
);
5000 reply
= g_dbus_message_new_method_error (message
,
5001 "org.freedesktop.DBus.Error.InvalidArgs",
5002 _("Type of message, '%s', does not match expected type '%s'"),
5003 g_variant_get_type_string (parameters
),
5005 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
5006 g_variant_type_free (in_type
);
5007 g_variant_unref (parameters
);
5008 g_object_unref (reply
);
5009 g_free (type_string
);
5013 g_variant_type_free (in_type
);
5015 /* schedule the call in idle */
5016 schedule_method_call (connection
, message
, registration_id
, subtree_registration_id
,
5017 interface_info
, method_info
, NULL
, parameters
,
5018 vtable
, main_context
, user_data
);
5019 g_variant_unref (parameters
);
5026 /* ---------------------------------------------------------------------------------------------------- */
5028 /* called in GDBusWorker thread with connection's lock held */
5030 obj_message_func (GDBusConnection
*connection
,
5032 GDBusMessage
*message
)
5034 const gchar
*interface_name
;
5035 const gchar
*member
;
5036 const gchar
*signature
;
5041 interface_name
= g_dbus_message_get_interface (message
);
5042 member
= g_dbus_message_get_member (message
);
5043 signature
= g_dbus_message_get_signature (message
);
5045 /* see if we have an interface for handling this call */
5046 if (interface_name
!= NULL
)
5048 ExportedInterface
*ei
;
5049 ei
= g_hash_table_lookup (eo
->map_if_name_to_ei
, interface_name
);
5052 /* we do - invoke the handler in idle in the right thread */
5054 /* handle no vtable or handler being present */
5055 if (ei
->vtable
== NULL
|| ei
->vtable
->method_call
== NULL
)
5058 handled
= validate_and_maybe_schedule_method_call (connection
,
5070 if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Introspectable") == 0 &&
5071 g_strcmp0 (member
, "Introspect") == 0 &&
5072 g_strcmp0 (signature
, "") == 0)
5074 handled
= handle_introspect (connection
, eo
, message
);
5077 else if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Properties") == 0 &&
5078 g_strcmp0 (member
, "Get") == 0 &&
5079 g_strcmp0 (signature
, "ss") == 0)
5081 handled
= handle_getset_property (connection
, eo
, message
, TRUE
);
5084 else if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Properties") == 0 &&
5085 g_strcmp0 (member
, "Set") == 0 &&
5086 g_strcmp0 (signature
, "ssv") == 0)
5088 handled
= handle_getset_property (connection
, eo
, message
, FALSE
);
5091 else if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Properties") == 0 &&
5092 g_strcmp0 (member
, "GetAll") == 0 &&
5093 g_strcmp0 (signature
, "s") == 0)
5095 handled
= handle_get_all_properties (connection
, eo
, message
);
5104 * g_dbus_connection_register_object:
5105 * @connection: a #GDBusConnection
5106 * @object_path: the object path to register at
5107 * @interface_info: introspection data for the interface
5108 * @vtable: (allow-none): a #GDBusInterfaceVTable to call into or %NULL
5109 * @user_data: (allow-none): data to pass to functions in @vtable
5110 * @user_data_free_func: function to call when the object path is unregistered
5111 * @error: return location for error or %NULL
5113 * Registers callbacks for exported objects at @object_path with the
5114 * D-Bus interface that is described in @interface_info.
5116 * Calls to functions in @vtable (and @user_data_free_func) will happen
5118 * [thread-default main context][g-main-context-push-thread-default]
5119 * of the thread you are calling this method from.
5121 * Note that all #GVariant values passed to functions in @vtable will match
5122 * the signature given in @interface_info - if a remote caller passes
5123 * incorrect values, the `org.freedesktop.DBus.Error.InvalidArgs`
5124 * is returned to the remote caller.
5126 * Additionally, if the remote caller attempts to invoke methods or
5127 * access properties not mentioned in @interface_info the
5128 * `org.freedesktop.DBus.Error.UnknownMethod` resp.
5129 * `org.freedesktop.DBus.Error.InvalidArgs` errors
5130 * are returned to the caller.
5132 * It is considered a programming error if the
5133 * #GDBusInterfaceGetPropertyFunc function in @vtable returns a
5134 * #GVariant of incorrect type.
5136 * If an existing callback is already registered at @object_path and
5137 * @interface_name, then @error is set to #G_IO_ERROR_EXISTS.
5139 * GDBus automatically implements the standard D-Bus interfaces
5140 * org.freedesktop.DBus.Properties, org.freedesktop.DBus.Introspectable
5141 * and org.freedesktop.Peer, so you don't have to implement those for the
5142 * objects you export. You can implement org.freedesktop.DBus.Properties
5143 * yourself, e.g. to handle getting and setting of properties asynchronously.
5145 * Note that the reference count on @interface_info will be
5146 * incremented by 1 (unless allocated statically, e.g. if the
5147 * reference count is -1, see g_dbus_interface_info_ref()) for as long
5148 * as the object is exported. Also note that @vtable will be copied.
5150 * See this [server][gdbus-server] for an example of how to use this method.
5152 * Returns: 0 if @error is set, otherwise a registration id (never 0)
5153 * that can be used with g_dbus_connection_unregister_object()
5158 g_dbus_connection_register_object (GDBusConnection
*connection
,
5159 const gchar
*object_path
,
5160 GDBusInterfaceInfo
*interface_info
,
5161 const GDBusInterfaceVTable
*vtable
,
5163 GDestroyNotify user_data_free_func
,
5167 ExportedInterface
*ei
;
5170 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), 0);
5171 g_return_val_if_fail (object_path
!= NULL
&& g_variant_is_object_path (object_path
), 0);
5172 g_return_val_if_fail (interface_info
!= NULL
, 0);
5173 g_return_val_if_fail (g_dbus_is_interface_name (interface_info
->name
), 0);
5174 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, 0);
5175 g_return_val_if_fail (check_initialized (connection
), 0);
5179 CONNECTION_LOCK (connection
);
5181 eo
= g_hash_table_lookup (connection
->map_object_path_to_eo
, object_path
);
5184 eo
= g_new0 (ExportedObject
, 1);
5185 eo
->object_path
= g_strdup (object_path
);
5186 eo
->connection
= connection
;
5187 eo
->map_if_name_to_ei
= g_hash_table_new_full (g_str_hash
,
5190 (GDestroyNotify
) exported_interface_free
);
5191 g_hash_table_insert (connection
->map_object_path_to_eo
, eo
->object_path
, eo
);
5194 ei
= g_hash_table_lookup (eo
->map_if_name_to_ei
, interface_info
->name
);
5200 _("An object is already exported for the interface %s at %s"),
5201 interface_info
->name
,
5206 ei
= g_new0 (ExportedInterface
, 1);
5207 ei
->id
= _global_registration_id
++; /* TODO: overflow etc. */
5209 ei
->user_data
= user_data
;
5210 ei
->user_data_free_func
= user_data_free_func
;
5211 ei
->vtable
= _g_dbus_interface_vtable_copy (vtable
);
5212 ei
->interface_info
= g_dbus_interface_info_ref (interface_info
);
5213 g_dbus_interface_info_cache_build (ei
->interface_info
);
5214 ei
->interface_name
= g_strdup (interface_info
->name
);
5215 ei
->context
= g_main_context_ref_thread_default ();
5217 g_hash_table_insert (eo
->map_if_name_to_ei
,
5218 (gpointer
) ei
->interface_name
,
5220 g_hash_table_insert (connection
->map_id_to_ei
,
5221 GUINT_TO_POINTER (ei
->id
),
5227 CONNECTION_UNLOCK (connection
);
5233 * g_dbus_connection_unregister_object:
5234 * @connection: a #GDBusConnection
5235 * @registration_id: a registration id obtained from
5236 * g_dbus_connection_register_object()
5238 * Unregisters an object.
5240 * Returns: %TRUE if the object was unregistered, %FALSE otherwise
5245 g_dbus_connection_unregister_object (GDBusConnection
*connection
,
5246 guint registration_id
)
5248 ExportedInterface
*ei
;
5252 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
5253 g_return_val_if_fail (check_initialized (connection
), FALSE
);
5257 CONNECTION_LOCK (connection
);
5259 ei
= g_hash_table_lookup (connection
->map_id_to_ei
,
5260 GUINT_TO_POINTER (registration_id
));
5266 g_warn_if_fail (g_hash_table_remove (connection
->map_id_to_ei
, GUINT_TO_POINTER (ei
->id
)));
5267 g_warn_if_fail (g_hash_table_remove (eo
->map_if_name_to_ei
, ei
->interface_name
));
5268 /* unregister object path if we have no more exported interfaces */
5269 if (g_hash_table_size (eo
->map_if_name_to_ei
) == 0)
5270 g_warn_if_fail (g_hash_table_remove (connection
->map_object_path_to_eo
,
5276 CONNECTION_UNLOCK (connection
);
5281 /* ---------------------------------------------------------------------------------------------------- */
5284 * g_dbus_connection_emit_signal:
5285 * @connection: a #GDBusConnection
5286 * @destination_bus_name: (allow-none): the unique bus name for the destination
5287 * for the signal or %NULL to emit to all listeners
5288 * @object_path: path of remote object
5289 * @interface_name: D-Bus interface to emit a signal on
5290 * @signal_name: the name of the signal to emit
5291 * @parameters: (allow-none): a #GVariant tuple with parameters for the signal
5292 * or %NULL if not passing parameters
5293 * @error: Return location for error or %NULL
5297 * If the parameters GVariant is floating, it is consumed.
5299 * This can only fail if @parameters is not compatible with the D-Bus protocol.
5301 * Returns: %TRUE unless @error is set
5306 g_dbus_connection_emit_signal (GDBusConnection
*connection
,
5307 const gchar
*destination_bus_name
,
5308 const gchar
*object_path
,
5309 const gchar
*interface_name
,
5310 const gchar
*signal_name
,
5311 GVariant
*parameters
,
5314 GDBusMessage
*message
;
5320 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
5321 g_return_val_if_fail (destination_bus_name
== NULL
|| g_dbus_is_name (destination_bus_name
), FALSE
);
5322 g_return_val_if_fail (object_path
!= NULL
&& g_variant_is_object_path (object_path
), FALSE
);
5323 g_return_val_if_fail (interface_name
!= NULL
&& g_dbus_is_interface_name (interface_name
), FALSE
);
5324 g_return_val_if_fail (signal_name
!= NULL
&& g_dbus_is_member_name (signal_name
), FALSE
);
5325 g_return_val_if_fail (parameters
== NULL
|| g_variant_is_of_type (parameters
, G_VARIANT_TYPE_TUPLE
), FALSE
);
5326 g_return_val_if_fail (check_initialized (connection
), FALSE
);
5328 if (G_UNLIKELY (_g_dbus_debug_emission ()))
5330 _g_dbus_debug_print_lock ();
5331 g_print ("========================================================================\n"
5332 "GDBus-debug:Emission:\n"
5333 " >>>> SIGNAL EMISSION %s.%s()\n"
5335 " destination %s\n",
5336 interface_name
, signal_name
,
5338 destination_bus_name
!= NULL
? destination_bus_name
: "(none)");
5339 _g_dbus_debug_print_unlock ();
5342 message
= g_dbus_message_new_signal (object_path
,
5346 if (destination_bus_name
!= NULL
)
5347 g_dbus_message_set_header (message
,
5348 G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION
,
5349 g_variant_new_string (destination_bus_name
));
5351 if (parameters
!= NULL
)
5352 g_dbus_message_set_body (message
, parameters
);
5354 ret
= g_dbus_connection_send_message (connection
, message
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, error
);
5355 g_object_unref (message
);
5361 add_call_flags (GDBusMessage
*message
,
5362 GDBusCallFlags flags
)
5364 if (flags
& G_DBUS_CALL_FLAGS_NO_AUTO_START
)
5365 g_dbus_message_set_flags (message
, G_DBUS_MESSAGE_FLAGS_NO_AUTO_START
);
5369 decode_method_reply (GDBusMessage
*reply
,
5370 const gchar
*method_name
,
5371 const GVariantType
*reply_type
,
5372 GUnixFDList
**out_fd_list
,
5378 switch (g_dbus_message_get_message_type (reply
))
5380 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN
:
5381 result
= g_dbus_message_get_body (reply
);
5384 result
= g_variant_new ("()");
5385 g_variant_ref_sink (result
);
5389 g_variant_ref (result
);
5392 if (!g_variant_is_of_type (result
, reply_type
))
5394 gchar
*type_string
= g_variant_type_dup_string (reply_type
);
5398 G_IO_ERROR_INVALID_ARGUMENT
,
5399 _("Method '%s' returned type '%s', but expected '%s'"),
5400 method_name
, g_variant_get_type_string (result
), type_string
);
5402 g_variant_unref (result
);
5403 g_free (type_string
);
5410 if (out_fd_list
!= NULL
)
5412 *out_fd_list
= g_dbus_message_get_unix_fd_list (reply
);
5413 if (*out_fd_list
!= NULL
)
5414 g_object_ref (*out_fd_list
);
5420 case G_DBUS_MESSAGE_TYPE_ERROR
:
5421 g_dbus_message_to_gerror (reply
, error
);
5425 g_assert_not_reached ();
5435 GSimpleAsyncResult
*simple
;
5436 GVariantType
*reply_type
;
5437 gchar
*method_name
; /* for error message */
5441 GUnixFDList
*fd_list
;
5445 call_state_free (CallState
*state
)
5447 g_variant_type_free (state
->reply_type
);
5448 g_free (state
->method_name
);
5450 if (state
->value
!= NULL
)
5451 g_variant_unref (state
->value
);
5452 if (state
->fd_list
!= NULL
)
5453 g_object_unref (state
->fd_list
);
5454 g_slice_free (CallState
, state
);
5457 /* called in any thread, with the connection's lock not held */
5459 g_dbus_connection_call_done (GObject
*source
,
5460 GAsyncResult
*result
,
5463 GSimpleAsyncResult
*simple
;
5464 GDBusConnection
*connection
= G_DBUS_CONNECTION (source
);
5465 CallState
*state
= user_data
;
5467 GDBusMessage
*reply
;
5470 reply
= g_dbus_connection_send_message_with_reply_finish (connection
,
5474 if (G_UNLIKELY (_g_dbus_debug_call ()))
5476 _g_dbus_debug_print_lock ();
5477 g_print ("========================================================================\n"
5478 "GDBus-debug:Call:\n"
5479 " <<<< ASYNC COMPLETE %s() (serial %d)\n"
5485 g_print ("SUCCESS\n");
5489 g_print ("FAILED: %s\n",
5492 _g_dbus_debug_print_unlock ();
5496 state
->value
= decode_method_reply (reply
, state
->method_name
, state
->reply_type
, &state
->fd_list
, &error
);
5498 simple
= state
->simple
; /* why? because state is freed before we unref simple.. */
5501 g_simple_async_result_take_error (state
->simple
, error
);
5502 g_simple_async_result_complete (state
->simple
);
5503 call_state_free (state
);
5507 g_simple_async_result_set_op_res_gpointer (state
->simple
, state
, (GDestroyNotify
) call_state_free
);
5508 g_simple_async_result_complete (state
->simple
);
5510 g_clear_object (&reply
);
5511 g_object_unref (simple
);
5514 /* called in any thread, with the connection's lock not held */
5516 g_dbus_connection_call_internal (GDBusConnection
*connection
,
5517 const gchar
*bus_name
,
5518 const gchar
*object_path
,
5519 const gchar
*interface_name
,
5520 const gchar
*method_name
,
5521 GVariant
*parameters
,
5522 const GVariantType
*reply_type
,
5523 GDBusCallFlags flags
,
5525 GUnixFDList
*fd_list
,
5526 GCancellable
*cancellable
,
5527 GAsyncReadyCallback callback
,
5530 GDBusMessage
*message
;
5533 g_return_if_fail (G_IS_DBUS_CONNECTION (connection
));
5534 g_return_if_fail (bus_name
== NULL
|| g_dbus_is_name (bus_name
));
5535 g_return_if_fail (object_path
!= NULL
&& g_variant_is_object_path (object_path
));
5536 g_return_if_fail (interface_name
!= NULL
&& g_dbus_is_interface_name (interface_name
));
5537 g_return_if_fail (method_name
!= NULL
&& g_dbus_is_member_name (method_name
));
5538 g_return_if_fail (timeout_msec
>= 0 || timeout_msec
== -1);
5539 g_return_if_fail ((parameters
== NULL
) || g_variant_is_of_type (parameters
, G_VARIANT_TYPE_TUPLE
));
5540 g_return_if_fail (check_initialized (connection
));
5542 g_return_if_fail (fd_list
== NULL
|| G_IS_UNIX_FD_LIST (fd_list
));
5544 g_return_if_fail (fd_list
== NULL
);
5547 message
= g_dbus_message_new_method_call (bus_name
,
5551 add_call_flags (message
, flags
);
5552 if (parameters
!= NULL
)
5553 g_dbus_message_set_body (message
, parameters
);
5556 if (fd_list
!= NULL
)
5557 g_dbus_message_set_unix_fd_list (message
, fd_list
);
5560 /* If the user has no callback then we can just send the message with
5561 * the G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set and skip all
5562 * the logic for processing the reply. If the service sends the reply
5563 * anyway then it will just be ignored.
5565 if (callback
!= NULL
)
5569 state
= g_slice_new0 (CallState
);
5570 state
->simple
= g_simple_async_result_new (G_OBJECT (connection
),
5571 callback
, user_data
,
5572 g_dbus_connection_call_internal
);
5573 g_simple_async_result_set_check_cancellable (state
->simple
, cancellable
);
5574 state
->method_name
= g_strjoin (".", interface_name
, method_name
, NULL
);
5576 if (reply_type
== NULL
)
5577 reply_type
= G_VARIANT_TYPE_ANY
;
5579 state
->reply_type
= g_variant_type_copy (reply_type
);
5581 g_dbus_connection_send_message_with_reply (connection
,
5583 G_DBUS_SEND_MESSAGE_FLAGS_NONE
,
5587 g_dbus_connection_call_done
,
5589 serial
= state
->serial
;
5593 GDBusMessageFlags flags
;
5595 flags
= g_dbus_message_get_flags (message
);
5596 flags
|= G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED
;
5597 g_dbus_message_set_flags (message
, flags
);
5599 g_dbus_connection_send_message (connection
,
5601 G_DBUS_SEND_MESSAGE_FLAGS_NONE
,
5605 if (G_UNLIKELY (_g_dbus_debug_call ()))
5607 _g_dbus_debug_print_lock ();
5608 g_print ("========================================================================\n"
5609 "GDBus-debug:Call:\n"
5610 " >>>> ASYNC %s.%s()\n"
5612 " owned by name %s (serial %d)\n",
5616 bus_name
!= NULL
? bus_name
: "(none)",
5618 _g_dbus_debug_print_unlock ();
5621 if (message
!= NULL
)
5622 g_object_unref (message
);
5625 /* called in any thread, with the connection's lock not held */
5627 g_dbus_connection_call_finish_internal (GDBusConnection
*connection
,
5628 GUnixFDList
**out_fd_list
,
5632 GSimpleAsyncResult
*simple
;
5635 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
5636 g_return_val_if_fail (g_simple_async_result_is_valid (res
, G_OBJECT (connection
),
5637 g_dbus_connection_call_internal
), NULL
);
5638 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
5640 simple
= G_SIMPLE_ASYNC_RESULT (res
);
5642 if (g_simple_async_result_propagate_error (simple
, error
))
5645 state
= g_simple_async_result_get_op_res_gpointer (simple
);
5646 if (out_fd_list
!= NULL
)
5647 *out_fd_list
= state
->fd_list
!= NULL
? g_object_ref (state
->fd_list
) : NULL
;
5648 return g_variant_ref (state
->value
);
5651 /* called in any user thread, with the connection's lock not held */
5653 g_dbus_connection_call_sync_internal (GDBusConnection
*connection
,
5654 const gchar
*bus_name
,
5655 const gchar
*object_path
,
5656 const gchar
*interface_name
,
5657 const gchar
*method_name
,
5658 GVariant
*parameters
,
5659 const GVariantType
*reply_type
,
5660 GDBusCallFlags flags
,
5662 GUnixFDList
*fd_list
,
5663 GUnixFDList
**out_fd_list
,
5664 GCancellable
*cancellable
,
5667 GDBusMessage
*message
;
5668 GDBusMessage
*reply
;
5670 GError
*local_error
;
5671 GDBusSendMessageFlags send_flags
;
5677 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), NULL
);
5678 g_return_val_if_fail (bus_name
== NULL
|| g_dbus_is_name (bus_name
), NULL
);
5679 g_return_val_if_fail (object_path
!= NULL
&& g_variant_is_object_path (object_path
), NULL
);
5680 g_return_val_if_fail (interface_name
!= NULL
&& g_dbus_is_interface_name (interface_name
), NULL
);
5681 g_return_val_if_fail (method_name
!= NULL
&& g_dbus_is_member_name (method_name
), NULL
);
5682 g_return_val_if_fail (timeout_msec
>= 0 || timeout_msec
== -1, NULL
);
5683 g_return_val_if_fail ((parameters
== NULL
) || g_variant_is_of_type (parameters
, G_VARIANT_TYPE_TUPLE
), NULL
);
5685 g_return_val_if_fail (fd_list
== NULL
|| G_IS_UNIX_FD_LIST (fd_list
), NULL
);
5687 g_return_val_if_fail (fd_list
== NULL
, NULL
);
5689 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
5691 if (!(flags
& CALL_FLAGS_INITIALIZING
))
5692 g_return_val_if_fail (check_initialized (connection
), FALSE
);
5694 if (reply_type
== NULL
)
5695 reply_type
= G_VARIANT_TYPE_ANY
;
5697 message
= g_dbus_message_new_method_call (bus_name
,
5701 add_call_flags (message
, flags
);
5702 if (parameters
!= NULL
)
5703 g_dbus_message_set_body (message
, parameters
);
5706 if (fd_list
!= NULL
)
5707 g_dbus_message_set_unix_fd_list (message
, fd_list
);
5710 if (G_UNLIKELY (_g_dbus_debug_call ()))
5712 _g_dbus_debug_print_lock ();
5713 g_print ("========================================================================\n"
5714 "GDBus-debug:Call:\n"
5715 " >>>> SYNC %s.%s()\n"
5717 " owned by name %s\n",
5721 bus_name
!= NULL
? bus_name
: "(none)");
5722 _g_dbus_debug_print_unlock ();
5727 send_flags
= G_DBUS_SEND_MESSAGE_FLAGS_NONE
;
5729 /* translate from one flavour of flags to another... */
5730 if (flags
& CALL_FLAGS_INITIALIZING
)
5731 send_flags
|= SEND_MESSAGE_FLAGS_INITIALIZING
;
5733 reply
= g_dbus_connection_send_message_with_reply_sync (connection
,
5737 NULL
, /* volatile guint32 *out_serial */
5741 if (G_UNLIKELY (_g_dbus_debug_call ()))
5743 _g_dbus_debug_print_lock ();
5744 g_print ("========================================================================\n"
5745 "GDBus-debug:Call:\n"
5746 " <<<< SYNC COMPLETE %s.%s()\n"
5752 g_print ("SUCCESS\n");
5756 g_print ("FAILED: %s\n",
5757 local_error
->message
);
5759 _g_dbus_debug_print_unlock ();
5765 *error
= local_error
;
5767 g_error_free (local_error
);
5771 result
= decode_method_reply (reply
, method_name
, reply_type
, out_fd_list
, error
);
5774 if (message
!= NULL
)
5775 g_object_unref (message
);
5777 g_object_unref (reply
);
5782 /* ---------------------------------------------------------------------------------------------------- */
5785 * g_dbus_connection_call:
5786 * @connection: a #GDBusConnection
5787 * @bus_name: (allow-none): a unique or well-known bus name or %NULL if
5788 * @connection is not a message bus connection
5789 * @object_path: path of remote object
5790 * @interface_name: D-Bus interface to invoke method on
5791 * @method_name: the name of the method to invoke
5792 * @parameters: (allow-none): a #GVariant tuple with parameters for the method
5793 * or %NULL if not passing parameters
5794 * @reply_type: (allow-none): the expected type of the reply, or %NULL
5795 * @flags: flags from the #GDBusCallFlags enumeration
5796 * @timeout_msec: the timeout in milliseconds, -1 to use the default
5797 * timeout or %G_MAXINT for no timeout
5798 * @cancellable: (allow-none): a #GCancellable or %NULL
5799 * @callback: (allow-none): a #GAsyncReadyCallback to call when the request
5800 * is satisfied or %NULL if you don't care about the result of the
5802 * @user_data: the data to pass to @callback
5804 * Asynchronously invokes the @method_name method on the
5805 * @interface_name D-Bus interface on the remote object at
5806 * @object_path owned by @bus_name.
5808 * If @connection is closed then the operation will fail with
5809 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
5810 * fail with %G_IO_ERROR_CANCELLED. If @parameters contains a value
5811 * not compatible with the D-Bus protocol, the operation fails with
5812 * %G_IO_ERROR_INVALID_ARGUMENT.
5814 * If @reply_type is non-%NULL then the reply will be checked for having this type and an
5815 * error will be raised if it does not match. Said another way, if you give a @reply_type
5816 * then any non-%NULL return value will be of this type.
5818 * If the @parameters #GVariant is floating, it is consumed. This allows
5819 * convenient 'inline' use of g_variant_new(), e.g.:
5820 * |[<!-- language="C" -->
5821 * g_dbus_connection_call (connection,
5822 * "org.freedesktop.StringThings",
5823 * "/org/freedesktop/StringThings",
5824 * "org.freedesktop.StringThings",
5826 * g_variant_new ("(ss)",
5830 * G_DBUS_CALL_FLAGS_NONE,
5833 * (GAsyncReadyCallback) two_strings_done,
5837 * This is an asynchronous method. When the operation is finished,
5838 * @callback will be invoked in the
5839 * [thread-default main context][g-main-context-push-thread-default]
5840 * of the thread you are calling this method from. You can then call
5841 * g_dbus_connection_call_finish() to get the result of the operation.
5842 * See g_dbus_connection_call_sync() for the synchronous version of this
5845 * If @callback is %NULL then the D-Bus method call message will be sent with
5846 * the %G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED flag set.
5851 g_dbus_connection_call (GDBusConnection
*connection
,
5852 const gchar
*bus_name
,
5853 const gchar
*object_path
,
5854 const gchar
*interface_name
,
5855 const gchar
*method_name
,
5856 GVariant
*parameters
,
5857 const GVariantType
*reply_type
,
5858 GDBusCallFlags flags
,
5860 GCancellable
*cancellable
,
5861 GAsyncReadyCallback callback
,
5864 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
);
5868 * g_dbus_connection_call_finish:
5869 * @connection: a #GDBusConnection
5870 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_call()
5871 * @error: return location for error or %NULL
5873 * Finishes an operation started with g_dbus_connection_call().
5875 * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
5876 * return values. Free with g_variant_unref().
5881 g_dbus_connection_call_finish (GDBusConnection
*connection
,
5885 return g_dbus_connection_call_finish_internal (connection
, NULL
, res
, error
);
5889 * g_dbus_connection_call_sync:
5890 * @connection: a #GDBusConnection
5891 * @bus_name: (allow-none): a unique or well-known bus name or %NULL if
5892 * @connection is not a message bus connection
5893 * @object_path: path of remote object
5894 * @interface_name: D-Bus interface to invoke method on
5895 * @method_name: the name of the method to invoke
5896 * @parameters: (allow-none): a #GVariant tuple with parameters for the method
5897 * or %NULL if not passing parameters
5898 * @reply_type: (allow-none): the expected type of the reply, or %NULL
5899 * @flags: flags from the #GDBusCallFlags enumeration
5900 * @timeout_msec: the timeout in milliseconds, -1 to use the default
5901 * timeout or %G_MAXINT for no timeout
5902 * @cancellable: (allow-none): a #GCancellable or %NULL
5903 * @error: return location for error or %NULL
5905 * Synchronously invokes the @method_name method on the
5906 * @interface_name D-Bus interface on the remote object at
5907 * @object_path owned by @bus_name.
5909 * If @connection is closed then the operation will fail with
5910 * %G_IO_ERROR_CLOSED. If @cancellable is canceled, the
5911 * operation will fail with %G_IO_ERROR_CANCELLED. If @parameters
5912 * contains a value not compatible with the D-Bus protocol, the operation
5913 * fails with %G_IO_ERROR_INVALID_ARGUMENT.
5915 * If @reply_type is non-%NULL then the reply will be checked for having
5916 * this type and an error will be raised if it does not match. Said
5917 * another way, if you give a @reply_type then any non-%NULL return
5918 * value will be of this type.
5920 * If the @parameters #GVariant is floating, it is consumed.
5921 * This allows convenient 'inline' use of g_variant_new(), e.g.:
5922 * |[<!-- language="C" -->
5923 * g_dbus_connection_call_sync (connection,
5924 * "org.freedesktop.StringThings",
5925 * "/org/freedesktop/StringThings",
5926 * "org.freedesktop.StringThings",
5928 * g_variant_new ("(ss)",
5932 * G_DBUS_CALL_FLAGS_NONE,
5938 * The calling thread is blocked until a reply is received. See
5939 * g_dbus_connection_call() for the asynchronous version of
5942 * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
5943 * return values. Free with g_variant_unref().
5948 g_dbus_connection_call_sync (GDBusConnection
*connection
,
5949 const gchar
*bus_name
,
5950 const gchar
*object_path
,
5951 const gchar
*interface_name
,
5952 const gchar
*method_name
,
5953 GVariant
*parameters
,
5954 const GVariantType
*reply_type
,
5955 GDBusCallFlags flags
,
5957 GCancellable
*cancellable
,
5960 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
);
5963 /* ---------------------------------------------------------------------------------------------------- */
5968 * g_dbus_connection_call_with_unix_fd_list:
5969 * @connection: a #GDBusConnection
5970 * @bus_name: (allow-none): a unique or well-known bus name or %NULL if
5971 * @connection is not a message bus connection
5972 * @object_path: path of remote object
5973 * @interface_name: D-Bus interface to invoke method on
5974 * @method_name: the name of the method to invoke
5975 * @parameters: (allow-none): a #GVariant tuple with parameters for the method
5976 * or %NULL if not passing parameters
5977 * @reply_type: (allow-none): the expected type of the reply, or %NULL
5978 * @flags: flags from the #GDBusCallFlags enumeration
5979 * @timeout_msec: the timeout in milliseconds, -1 to use the default
5980 * timeout or %G_MAXINT for no timeout
5981 * @fd_list: (allow-none): a #GUnixFDList or %NULL
5982 * @cancellable: (allow-none): a #GCancellable or %NULL
5983 * @callback: (allow-none): a #GAsyncReadyCallback to call when the request is
5984 * satisfied or %NULL if you don't * care about the result of the
5986 * @user_data: The data to pass to @callback.
5988 * Like g_dbus_connection_call() but also takes a #GUnixFDList object.
5990 * This method is only available on UNIX.
5995 g_dbus_connection_call_with_unix_fd_list (GDBusConnection
*connection
,
5996 const gchar
*bus_name
,
5997 const gchar
*object_path
,
5998 const gchar
*interface_name
,
5999 const gchar
*method_name
,
6000 GVariant
*parameters
,
6001 const GVariantType
*reply_type
,
6002 GDBusCallFlags flags
,
6004 GUnixFDList
*fd_list
,
6005 GCancellable
*cancellable
,
6006 GAsyncReadyCallback callback
,
6009 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
);
6013 * g_dbus_connection_call_with_unix_fd_list_finish:
6014 * @connection: a #GDBusConnection
6015 * @out_fd_list: (out) (allow-none): return location for a #GUnixFDList or %NULL
6016 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed to
6017 * g_dbus_connection_call_with_unix_fd_list()
6018 * @error: return location for error or %NULL
6020 * Finishes an operation started with g_dbus_connection_call_with_unix_fd_list().
6022 * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
6023 * return values. Free with g_variant_unref().
6028 g_dbus_connection_call_with_unix_fd_list_finish (GDBusConnection
*connection
,
6029 GUnixFDList
**out_fd_list
,
6033 return g_dbus_connection_call_finish_internal (connection
, out_fd_list
, res
, error
);
6037 * g_dbus_connection_call_with_unix_fd_list_sync:
6038 * @connection: a #GDBusConnection
6039 * @bus_name: (allow-none): a unique or well-known bus name or %NULL
6040 * if @connection is not a message bus connection
6041 * @object_path: path of remote object
6042 * @interface_name: D-Bus interface to invoke method on
6043 * @method_name: the name of the method to invoke
6044 * @parameters: (allow-none): a #GVariant tuple with parameters for
6045 * the method or %NULL if not passing parameters
6046 * @reply_type: (allow-none): the expected type of the reply, or %NULL
6047 * @flags: flags from the #GDBusCallFlags enumeration
6048 * @timeout_msec: the timeout in milliseconds, -1 to use the default
6049 * timeout or %G_MAXINT for no timeout
6050 * @fd_list: (allow-none): a #GUnixFDList or %NULL
6051 * @out_fd_list: (out) (allow-none): return location for a #GUnixFDList or %NULL
6052 * @cancellable: (allow-none): a #GCancellable or %NULL
6053 * @error: return location for error or %NULL
6055 * Like g_dbus_connection_call_sync() but also takes and returns #GUnixFDList objects.
6057 * This method is only available on UNIX.
6059 * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
6060 * return values. Free with g_variant_unref().
6065 g_dbus_connection_call_with_unix_fd_list_sync (GDBusConnection
*connection
,
6066 const gchar
*bus_name
,
6067 const gchar
*object_path
,
6068 const gchar
*interface_name
,
6069 const gchar
*method_name
,
6070 GVariant
*parameters
,
6071 const GVariantType
*reply_type
,
6072 GDBusCallFlags flags
,
6074 GUnixFDList
*fd_list
,
6075 GUnixFDList
**out_fd_list
,
6076 GCancellable
*cancellable
,
6079 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
);
6082 #endif /* G_OS_UNIX */
6084 /* ---------------------------------------------------------------------------------------------------- */
6086 struct ExportedSubtree
6090 GDBusConnection
*connection
;
6091 GDBusSubtreeVTable
*vtable
;
6092 GDBusSubtreeFlags flags
;
6094 GMainContext
*context
;
6096 GDestroyNotify user_data_free_func
;
6100 exported_subtree_free (ExportedSubtree
*es
)
6102 call_destroy_notify (es
->context
,
6103 es
->user_data_free_func
,
6106 g_main_context_unref (es
->context
);
6108 _g_dbus_subtree_vtable_free (es
->vtable
);
6109 g_free (es
->object_path
);
6113 /* called without lock held in the thread where the caller registered
6117 handle_subtree_introspect (GDBusConnection
*connection
,
6118 ExportedSubtree
*es
,
6119 GDBusMessage
*message
)
6123 GDBusMessage
*reply
;
6126 const gchar
*sender
;
6127 const gchar
*requested_object_path
;
6128 const gchar
*requested_node
;
6129 GDBusInterfaceInfo
**interfaces
;
6131 gchar
**subnode_paths
;
6132 gboolean has_properties_interface
;
6133 gboolean has_introspectable_interface
;
6137 requested_object_path
= g_dbus_message_get_path (message
);
6138 sender
= g_dbus_message_get_sender (message
);
6139 is_root
= (g_strcmp0 (requested_object_path
, es
->object_path
) == 0);
6141 s
= g_string_new (NULL
);
6142 introspect_append_header (s
);
6144 /* Strictly we don't need the children in dynamic mode, but we avoid the
6145 * conditionals to preserve code clarity
6147 children
= es
->vtable
->enumerate (es
->connection
,
6154 requested_node
= strrchr (requested_object_path
, '/') + 1;
6156 /* Assert existence of object if we are not dynamic */
6157 if (!(es
->flags
& G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES
) &&
6158 !_g_strv_has_string ((const gchar
* const *) children
, requested_node
))
6163 requested_node
= NULL
;
6166 interfaces
= es
->vtable
->introspect (es
->connection
,
6171 if (interfaces
!= NULL
)
6173 has_properties_interface
= FALSE
;
6174 has_introspectable_interface
= FALSE
;
6176 for (n
= 0; interfaces
[n
] != NULL
; n
++)
6178 if (strcmp (interfaces
[n
]->name
, "org.freedesktop.DBus.Properties") == 0)
6179 has_properties_interface
= TRUE
;
6180 else if (strcmp (interfaces
[n
]->name
, "org.freedesktop.DBus.Introspectable") == 0)
6181 has_introspectable_interface
= TRUE
;
6183 if (!has_properties_interface
)
6184 g_string_append (s
, introspect_properties_interface
);
6185 if (!has_introspectable_interface
)
6186 g_string_append (s
, introspect_introspectable_interface
);
6188 for (n
= 0; interfaces
[n
] != NULL
; n
++)
6190 g_dbus_interface_info_generate_xml (interfaces
[n
], 2, s
);
6191 g_dbus_interface_info_unref (interfaces
[n
]);
6193 g_free (interfaces
);
6196 /* then include <node> entries from the Subtree for the root */
6199 for (n
= 0; children
!= NULL
&& children
[n
] != NULL
; n
++)
6200 g_string_append_printf (s
, " <node name=\"%s\"/>\n", children
[n
]);
6203 /* finally include nodes registered below us */
6204 subnode_paths
= g_dbus_connection_list_registered (es
->connection
, requested_object_path
);
6205 for (n
= 0; subnode_paths
!= NULL
&& subnode_paths
[n
] != NULL
; n
++)
6206 g_string_append_printf (s
, " <node name=\"%s\"/>\n", subnode_paths
[n
]);
6207 g_strfreev (subnode_paths
);
6209 g_string_append (s
, "</node>\n");
6211 reply
= g_dbus_message_new_method_reply (message
);
6212 g_dbus_message_set_body (reply
, g_variant_new ("(s)", s
->str
));
6213 g_dbus_connection_send_message (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6214 g_object_unref (reply
);
6219 g_string_free (s
, TRUE
);
6220 g_strfreev (children
);
6224 /* called without lock held in the thread where the caller registered
6228 handle_subtree_method_invocation (GDBusConnection
*connection
,
6229 ExportedSubtree
*es
,
6230 GDBusMessage
*message
)
6233 const gchar
*sender
;
6234 const gchar
*interface_name
;
6235 const gchar
*member
;
6236 const gchar
*signature
;
6237 const gchar
*requested_object_path
;
6238 const gchar
*requested_node
;
6240 GDBusInterfaceInfo
*interface_info
;
6241 const GDBusInterfaceVTable
*interface_vtable
;
6242 gpointer interface_user_data
;
6244 GDBusInterfaceInfo
**interfaces
;
6245 gboolean is_property_get
;
6246 gboolean is_property_set
;
6247 gboolean is_property_get_all
;
6252 requested_object_path
= g_dbus_message_get_path (message
);
6253 sender
= g_dbus_message_get_sender (message
);
6254 interface_name
= g_dbus_message_get_interface (message
);
6255 member
= g_dbus_message_get_member (message
);
6256 signature
= g_dbus_message_get_signature (message
);
6257 is_root
= (g_strcmp0 (requested_object_path
, es
->object_path
) == 0);
6259 is_property_get
= FALSE
;
6260 is_property_set
= FALSE
;
6261 is_property_get_all
= FALSE
;
6262 if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Properties") == 0)
6264 if (g_strcmp0 (member
, "Get") == 0 && g_strcmp0 (signature
, "ss") == 0)
6265 is_property_get
= TRUE
;
6266 else if (g_strcmp0 (member
, "Set") == 0 && g_strcmp0 (signature
, "ssv") == 0)
6267 is_property_set
= TRUE
;
6268 else if (g_strcmp0 (member
, "GetAll") == 0 && g_strcmp0 (signature
, "s") == 0)
6269 is_property_get_all
= TRUE
;
6274 requested_node
= strrchr (requested_object_path
, '/') + 1;
6276 if (~es
->flags
& G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES
)
6278 /* We don't want to dispatch to unenumerated
6279 * nodes, so ensure that the child exists.
6284 children
= es
->vtable
->enumerate (es
->connection
,
6289 exists
= _g_strv_has_string ((const gchar
* const *) children
, requested_node
);
6290 g_strfreev (children
);
6298 requested_node
= NULL
;
6301 /* get introspection data for the node */
6302 interfaces
= es
->vtable
->introspect (es
->connection
,
6304 requested_object_path
,
6308 if (interfaces
== NULL
)
6311 interface_info
= NULL
;
6312 for (n
= 0; interfaces
[n
] != NULL
; n
++)
6314 if (g_strcmp0 (interfaces
[n
]->name
, interface_name
) == 0)
6315 interface_info
= interfaces
[n
];
6318 /* dispatch the call if the user wants to handle it */
6319 if (interface_info
!= NULL
)
6321 /* figure out where to dispatch the method call */
6322 interface_user_data
= NULL
;
6323 interface_vtable
= es
->vtable
->dispatch (es
->connection
,
6328 &interface_user_data
,
6330 if (interface_vtable
== NULL
)
6333 CONNECTION_LOCK (connection
);
6334 handled
= validate_and_maybe_schedule_method_call (es
->connection
,
6341 interface_user_data
);
6342 CONNECTION_UNLOCK (connection
);
6344 /* handle org.freedesktop.DBus.Properties interface if not explicitly handled */
6345 else if (is_property_get
|| is_property_set
|| is_property_get_all
)
6347 if (is_property_get
)
6348 g_variant_get (g_dbus_message_get_body (message
), "(&s&s)", &interface_name
, NULL
);
6349 else if (is_property_set
)
6350 g_variant_get (g_dbus_message_get_body (message
), "(&s&sv)", &interface_name
, NULL
, NULL
);
6351 else if (is_property_get_all
)
6352 g_variant_get (g_dbus_message_get_body (message
), "(&s)", &interface_name
, NULL
, NULL
);
6354 g_assert_not_reached ();
6356 /* see if the object supports this interface at all */
6357 for (n
= 0; interfaces
[n
] != NULL
; n
++)
6359 if (g_strcmp0 (interfaces
[n
]->name
, interface_name
) == 0)
6360 interface_info
= interfaces
[n
];
6363 /* Fail with org.freedesktop.DBus.Error.InvalidArgs if the user-code
6364 * claims it won't support the interface
6366 if (interface_info
== NULL
)
6368 GDBusMessage
*reply
;
6369 reply
= g_dbus_message_new_method_error (message
,
6370 "org.freedesktop.DBus.Error.InvalidArgs",
6371 _("No such interface '%s'"),
6373 g_dbus_connection_send_message (es
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6374 g_object_unref (reply
);
6379 /* figure out where to dispatch the property get/set/getall calls */
6380 interface_user_data
= NULL
;
6381 interface_vtable
= es
->vtable
->dispatch (es
->connection
,
6386 &interface_user_data
,
6388 if (interface_vtable
== NULL
)
6390 g_warning ("The subtree introspection function indicates that '%s' "
6391 "is a valid interface name, but calling the dispatch "
6392 "function on that interface gave us NULL", interface_name
);
6396 if (is_property_get
|| is_property_set
)
6398 CONNECTION_LOCK (connection
);
6399 handled
= validate_and_maybe_schedule_property_getset (es
->connection
,
6407 interface_user_data
);
6408 CONNECTION_UNLOCK (connection
);
6410 else if (is_property_get_all
)
6412 CONNECTION_LOCK (connection
);
6413 handled
= validate_and_maybe_schedule_property_get_all (es
->connection
,
6420 interface_user_data
);
6421 CONNECTION_UNLOCK (connection
);
6426 if (interfaces
!= NULL
)
6428 for (n
= 0; interfaces
[n
] != NULL
; n
++)
6429 g_dbus_interface_info_unref (interfaces
[n
]);
6430 g_free (interfaces
);
6438 GDBusMessage
*message
;
6439 ExportedSubtree
*es
;
6440 } SubtreeDeferredData
;
6443 subtree_deferred_data_free (SubtreeDeferredData
*data
)
6445 g_object_unref (data
->message
);
6449 /* called without lock held in the thread where the caller registered the subtree */
6451 process_subtree_vtable_message_in_idle_cb (gpointer _data
)
6453 SubtreeDeferredData
*data
= _data
;
6458 if (g_strcmp0 (g_dbus_message_get_interface (data
->message
), "org.freedesktop.DBus.Introspectable") == 0 &&
6459 g_strcmp0 (g_dbus_message_get_member (data
->message
), "Introspect") == 0 &&
6460 g_strcmp0 (g_dbus_message_get_signature (data
->message
), "") == 0)
6461 handled
= handle_subtree_introspect (data
->es
->connection
,
6465 handled
= handle_subtree_method_invocation (data
->es
->connection
,
6471 CONNECTION_LOCK (data
->es
->connection
);
6472 handled
= handle_generic_unlocked (data
->es
->connection
, data
->message
);
6473 CONNECTION_UNLOCK (data
->es
->connection
);
6476 /* if we couldn't handle the request, just bail with the UnknownMethod error */
6479 GDBusMessage
*reply
;
6480 reply
= g_dbus_message_new_method_error (data
->message
,
6481 "org.freedesktop.DBus.Error.UnknownMethod",
6482 _("Method '%s' on interface '%s' with signature '%s' does not exist"),
6483 g_dbus_message_get_member (data
->message
),
6484 g_dbus_message_get_interface (data
->message
),
6485 g_dbus_message_get_signature (data
->message
));
6486 g_dbus_connection_send_message (data
->es
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6487 g_object_unref (reply
);
6493 /* called in GDBusWorker thread with connection's lock held */
6495 subtree_message_func (GDBusConnection
*connection
,
6496 ExportedSubtree
*es
,
6497 GDBusMessage
*message
)
6499 GSource
*idle_source
;
6500 SubtreeDeferredData
*data
;
6502 data
= g_new0 (SubtreeDeferredData
, 1);
6503 data
->message
= g_object_ref (message
);
6506 /* defer this call to an idle handler in the right thread */
6507 idle_source
= g_idle_source_new ();
6508 g_source_set_priority (idle_source
, G_PRIORITY_HIGH
);
6509 g_source_set_callback (idle_source
,
6510 process_subtree_vtable_message_in_idle_cb
,
6512 (GDestroyNotify
) subtree_deferred_data_free
);
6513 g_source_set_name (idle_source
, "[gio] process_subtree_vtable_message_in_idle_cb");
6514 g_source_attach (idle_source
, es
->context
);
6515 g_source_unref (idle_source
);
6517 /* since we own the entire subtree, handlers for objects not in the subtree have been
6518 * tried already by libdbus-1 - so we just need to ensure that we're always going
6519 * to reply to the message
6525 * g_dbus_connection_register_subtree:
6526 * @connection: a #GDBusConnection
6527 * @object_path: the object path to register the subtree at
6528 * @vtable: a #GDBusSubtreeVTable to enumerate, introspect and
6529 * dispatch nodes in the subtree
6530 * @flags: flags used to fine tune the behavior of the subtree
6531 * @user_data: data to pass to functions in @vtable
6532 * @user_data_free_func: function to call when the subtree is unregistered
6533 * @error: return location for error or %NULL
6535 * Registers a whole subtree of dynamic objects.
6537 * The @enumerate and @introspection functions in @vtable are used to
6538 * convey, to remote callers, what nodes exist in the subtree rooted
6541 * When handling remote calls into any node in the subtree, first the
6542 * @enumerate function is used to check if the node exists. If the node exists
6543 * or the #G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag is set
6544 * the @introspection function is used to check if the node supports the
6545 * requested method. If so, the @dispatch function is used to determine
6546 * where to dispatch the call. The collected #GDBusInterfaceVTable and
6547 * #gpointer will be used to call into the interface vtable for processing
6550 * All calls into user-provided code will be invoked in the
6551 * [thread-default main context][g-main-context-push-thread-default]
6552 * of the thread you are calling this method from.
6554 * If an existing subtree is already registered at @object_path or
6555 * then @error is set to #G_IO_ERROR_EXISTS.
6557 * Note that it is valid to register regular objects (using
6558 * g_dbus_connection_register_object()) in a subtree registered with
6559 * g_dbus_connection_register_subtree() - if so, the subtree handler
6560 * is tried as the last resort. One way to think about a subtree
6561 * handler is to consider it a fallback handler for object paths not
6562 * registered via g_dbus_connection_register_object() or other bindings.
6564 * Note that @vtable will be copied so you cannot change it after
6567 * See this [server][gdbus-subtree-server] for an example of how to use
6570 * Returns: 0 if @error is set, otherwise a subtree registration id (never 0)
6571 * that can be used with g_dbus_connection_unregister_subtree() .
6576 g_dbus_connection_register_subtree (GDBusConnection
*connection
,
6577 const gchar
*object_path
,
6578 const GDBusSubtreeVTable
*vtable
,
6579 GDBusSubtreeFlags flags
,
6581 GDestroyNotify user_data_free_func
,
6585 ExportedSubtree
*es
;
6587 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), 0);
6588 g_return_val_if_fail (object_path
!= NULL
&& g_variant_is_object_path (object_path
), 0);
6589 g_return_val_if_fail (vtable
!= NULL
, 0);
6590 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, 0);
6591 g_return_val_if_fail (check_initialized (connection
), 0);
6595 CONNECTION_LOCK (connection
);
6597 es
= g_hash_table_lookup (connection
->map_object_path_to_es
, object_path
);
6603 _("A subtree is already exported for %s"),
6608 es
= g_new0 (ExportedSubtree
, 1);
6609 es
->object_path
= g_strdup (object_path
);
6610 es
->connection
= connection
;
6612 es
->vtable
= _g_dbus_subtree_vtable_copy (vtable
);
6614 es
->id
= _global_subtree_registration_id
++; /* TODO: overflow etc. */
6615 es
->user_data
= user_data
;
6616 es
->user_data_free_func
= user_data_free_func
;
6617 es
->context
= g_main_context_ref_thread_default ();
6619 g_hash_table_insert (connection
->map_object_path_to_es
, es
->object_path
, es
);
6620 g_hash_table_insert (connection
->map_id_to_es
,
6621 GUINT_TO_POINTER (es
->id
),
6627 CONNECTION_UNLOCK (connection
);
6632 /* ---------------------------------------------------------------------------------------------------- */
6635 * g_dbus_connection_unregister_subtree:
6636 * @connection: a #GDBusConnection
6637 * @registration_id: a subtree registration id obtained from
6638 * g_dbus_connection_register_subtree()
6640 * Unregisters a subtree.
6642 * Returns: %TRUE if the subtree was unregistered, %FALSE otherwise
6647 g_dbus_connection_unregister_subtree (GDBusConnection
*connection
,
6648 guint registration_id
)
6650 ExportedSubtree
*es
;
6653 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection
), FALSE
);
6654 g_return_val_if_fail (check_initialized (connection
), FALSE
);
6658 CONNECTION_LOCK (connection
);
6660 es
= g_hash_table_lookup (connection
->map_id_to_es
,
6661 GUINT_TO_POINTER (registration_id
));
6665 g_warn_if_fail (g_hash_table_remove (connection
->map_id_to_es
, GUINT_TO_POINTER (es
->id
)));
6666 g_warn_if_fail (g_hash_table_remove (connection
->map_object_path_to_es
, es
->object_path
));
6671 CONNECTION_UNLOCK (connection
);
6676 /* ---------------------------------------------------------------------------------------------------- */
6678 /* may be called in any thread, with connection's lock held */
6680 handle_generic_ping_unlocked (GDBusConnection
*connection
,
6681 const gchar
*object_path
,
6682 GDBusMessage
*message
)
6684 GDBusMessage
*reply
;
6685 reply
= g_dbus_message_new_method_reply (message
);
6686 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6687 g_object_unref (reply
);
6690 /* may be called in any thread, with connection's lock held */
6692 handle_generic_get_machine_id_unlocked (GDBusConnection
*connection
,
6693 const gchar
*object_path
,
6694 GDBusMessage
*message
)
6696 GDBusMessage
*reply
;
6699 if (connection
->machine_id
== NULL
)
6704 connection
->machine_id
= _g_dbus_get_machine_id (&error
);
6705 if (connection
->machine_id
== NULL
)
6707 reply
= g_dbus_message_new_method_error_literal (message
,
6708 "org.freedesktop.DBus.Error.Failed",
6710 g_error_free (error
);
6716 reply
= g_dbus_message_new_method_reply (message
);
6717 g_dbus_message_set_body (reply
, g_variant_new ("(s)", connection
->machine_id
));
6719 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6720 g_object_unref (reply
);
6723 /* may be called in any thread, with connection's lock held */
6725 handle_generic_introspect_unlocked (GDBusConnection
*connection
,
6726 const gchar
*object_path
,
6727 GDBusMessage
*message
)
6732 GDBusMessage
*reply
;
6734 /* first the header */
6735 s
= g_string_new (NULL
);
6736 introspect_append_header (s
);
6738 registered
= g_dbus_connection_list_registered_unlocked (connection
, object_path
);
6739 for (n
= 0; registered
!= NULL
&& registered
[n
] != NULL
; n
++)
6740 g_string_append_printf (s
, " <node name=\"%s\"/>\n", registered
[n
]);
6741 g_strfreev (registered
);
6742 g_string_append (s
, "</node>\n");
6744 reply
= g_dbus_message_new_method_reply (message
);
6745 g_dbus_message_set_body (reply
, g_variant_new ("(s)", s
->str
));
6746 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6747 g_object_unref (reply
);
6748 g_string_free (s
, TRUE
);
6751 /* may be called in any thread, with connection's lock held */
6753 handle_generic_unlocked (GDBusConnection
*connection
,
6754 GDBusMessage
*message
)
6757 const gchar
*interface_name
;
6758 const gchar
*member
;
6759 const gchar
*signature
;
6762 CONNECTION_ENSURE_LOCK (connection
);
6766 interface_name
= g_dbus_message_get_interface (message
);
6767 member
= g_dbus_message_get_member (message
);
6768 signature
= g_dbus_message_get_signature (message
);
6769 path
= g_dbus_message_get_path (message
);
6771 if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Introspectable") == 0 &&
6772 g_strcmp0 (member
, "Introspect") == 0 &&
6773 g_strcmp0 (signature
, "") == 0)
6775 handle_generic_introspect_unlocked (connection
, path
, message
);
6778 else if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Peer") == 0 &&
6779 g_strcmp0 (member
, "Ping") == 0 &&
6780 g_strcmp0 (signature
, "") == 0)
6782 handle_generic_ping_unlocked (connection
, path
, message
);
6785 else if (g_strcmp0 (interface_name
, "org.freedesktop.DBus.Peer") == 0 &&
6786 g_strcmp0 (member
, "GetMachineId") == 0 &&
6787 g_strcmp0 (signature
, "") == 0)
6789 handle_generic_get_machine_id_unlocked (connection
, path
, message
);
6796 /* ---------------------------------------------------------------------------------------------------- */
6798 /* called in GDBusWorker thread with connection's lock held */
6800 distribute_method_call (GDBusConnection
*connection
,
6801 GDBusMessage
*message
)
6803 GDBusMessage
*reply
;
6805 ExportedSubtree
*es
;
6806 const gchar
*object_path
;
6807 const gchar
*interface_name
;
6808 const gchar
*member
;
6810 gchar
*subtree_path
;
6813 g_assert (g_dbus_message_get_message_type (message
) == G_DBUS_MESSAGE_TYPE_METHOD_CALL
);
6815 interface_name
= g_dbus_message_get_interface (message
);
6816 member
= g_dbus_message_get_member (message
);
6817 path
= g_dbus_message_get_path (message
);
6818 subtree_path
= g_strdup (path
);
6819 needle
= strrchr (subtree_path
, '/');
6820 if (needle
!= NULL
&& needle
!= subtree_path
)
6826 g_free (subtree_path
);
6827 subtree_path
= NULL
;
6831 if (G_UNLIKELY (_g_dbus_debug_incoming ()))
6833 _g_dbus_debug_print_lock ();
6834 g_print ("========================================================================\n"
6835 "GDBus-debug:Incoming:\n"
6836 " <<<< METHOD INVOCATION %s.%s()\n"
6838 " invoked by name %s\n"
6840 interface_name
, member
,
6842 g_dbus_message_get_sender (message
) != NULL
? g_dbus_message_get_sender (message
) : "(none)",
6843 g_dbus_message_get_serial (message
));
6844 _g_dbus_debug_print_unlock ();
6847 object_path
= g_dbus_message_get_path (message
);
6848 g_assert (object_path
!= NULL
);
6850 eo
= g_hash_table_lookup (connection
->map_object_path_to_eo
, object_path
);
6853 if (obj_message_func (connection
, eo
, message
))
6857 es
= g_hash_table_lookup (connection
->map_object_path_to_es
, object_path
);
6860 if (subtree_message_func (connection
, es
, message
))
6864 if (subtree_path
!= NULL
)
6866 es
= g_hash_table_lookup (connection
->map_object_path_to_es
, subtree_path
);
6869 if (subtree_message_func (connection
, es
, message
))
6874 if (handle_generic_unlocked (connection
, message
))
6877 /* if we end up here, the message has not been not handled - so return an error saying this */
6878 reply
= g_dbus_message_new_method_error (message
,
6879 "org.freedesktop.DBus.Error.UnknownMethod",
6880 _("No such interface '%s' on object at path %s"),
6883 g_dbus_connection_send_message_unlocked (connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
);
6884 g_object_unref (reply
);
6887 g_free (subtree_path
);
6890 /* ---------------------------------------------------------------------------------------------------- */
6892 /* Called in any user thread, with the message_bus_lock held. */
6894 message_bus_get_singleton (GBusType bus_type
,
6898 const gchar
*starter_bus
;
6904 case G_BUS_TYPE_SESSION
:
6905 ret
= &the_session_bus
;
6908 case G_BUS_TYPE_SYSTEM
:
6909 ret
= &the_system_bus
;
6912 case G_BUS_TYPE_STARTER
:
6913 starter_bus
= g_getenv ("DBUS_STARTER_BUS_TYPE");
6914 if (g_strcmp0 (starter_bus
, "session") == 0)
6916 ret
= message_bus_get_singleton (G_BUS_TYPE_SESSION
, error
);
6919 else if (g_strcmp0 (starter_bus
, "system") == 0)
6921 ret
= message_bus_get_singleton (G_BUS_TYPE_SYSTEM
, error
);
6926 if (starter_bus
!= NULL
)
6930 G_IO_ERROR_INVALID_ARGUMENT
,
6931 _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable"
6932 " - unknown value '%s'"),
6937 g_set_error_literal (error
,
6939 G_IO_ERROR_INVALID_ARGUMENT
,
6940 _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment "
6941 "variable is not set"));
6947 g_assert_not_reached ();
6955 /* Called in any user thread, without holding locks. */
6956 static GDBusConnection
*
6957 get_uninitialized_connection (GBusType bus_type
,
6958 GCancellable
*cancellable
,
6961 GWeakRef
*singleton
;
6962 GDBusConnection
*ret
;
6966 G_LOCK (message_bus_lock
);
6967 singleton
= message_bus_get_singleton (bus_type
, error
);
6968 if (singleton
== NULL
)
6971 ret
= g_weak_ref_get (singleton
);
6976 address
= g_dbus_address_get_for_bus_sync (bus_type
, cancellable
, error
);
6977 if (address
== NULL
)
6979 ret
= g_object_new (G_TYPE_DBUS_CONNECTION
,
6981 "flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
|
6982 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION
,
6983 "exit-on-close", TRUE
,
6986 g_weak_ref_set (singleton
, ret
);
6990 g_assert (ret
!= NULL
);
6993 G_UNLOCK (message_bus_lock
);
6997 /* May be called from any thread. Must not hold message_bus_lock. */
6999 _g_bus_get_singleton_if_exists (GBusType bus_type
)
7001 GWeakRef
*singleton
;
7002 GDBusConnection
*ret
= NULL
;
7004 G_LOCK (message_bus_lock
);
7005 singleton
= message_bus_get_singleton (bus_type
, NULL
);
7006 if (singleton
== NULL
)
7009 ret
= g_weak_ref_get (singleton
);
7012 G_UNLOCK (message_bus_lock
);
7018 * @bus_type: a #GBusType
7019 * @cancellable: (allow-none): a #GCancellable or %NULL
7020 * @error: return location for error or %NULL
7022 * Synchronously connects to the message bus specified by @bus_type.
7023 * Note that the returned object may shared with other callers,
7024 * e.g. if two separate parts of a process calls this function with
7025 * the same @bus_type, they will share the same object.
7027 * This is a synchronous failable function. See g_bus_get() and
7028 * g_bus_get_finish() for the asynchronous version.
7030 * The returned object is a singleton, that is, shared with other
7031 * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
7032 * event that you need a private message bus connection, use
7033 * g_dbus_address_get_for_bus_sync() and
7034 * g_dbus_connection_new_for_address().
7036 * Note that the returned #GDBusConnection object will (usually) have
7037 * the #GDBusConnection:exit-on-close property set to %TRUE.
7039 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
7040 * Free with g_object_unref().
7045 g_bus_get_sync (GBusType bus_type
,
7046 GCancellable
*cancellable
,
7049 GDBusConnection
*connection
;
7051 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
7053 connection
= get_uninitialized_connection (bus_type
, cancellable
, error
);
7054 if (connection
== NULL
)
7057 if (!g_initable_init (G_INITABLE (connection
), cancellable
, error
))
7059 g_object_unref (connection
);
7068 bus_get_async_initable_cb (GObject
*source_object
,
7072 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (user_data
);
7076 if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object
),
7080 g_assert (error
!= NULL
);
7081 g_simple_async_result_take_error (simple
, error
);
7082 g_object_unref (source_object
);
7086 g_simple_async_result_set_op_res_gpointer (simple
,
7090 g_simple_async_result_complete_in_idle (simple
);
7091 g_object_unref (simple
);
7096 * @bus_type: a #GBusType
7097 * @cancellable: (allow-none): a #GCancellable or %NULL
7098 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
7099 * @user_data: the data to pass to @callback
7101 * Asynchronously connects to the message bus specified by @bus_type.
7103 * When the operation is finished, @callback will be invoked. You can
7104 * then call g_bus_get_finish() to get the result of the operation.
7106 * This is a asynchronous failable function. See g_bus_get_sync() for
7107 * the synchronous version.
7112 g_bus_get (GBusType bus_type
,
7113 GCancellable
*cancellable
,
7114 GAsyncReadyCallback callback
,
7117 GDBusConnection
*connection
;
7118 GSimpleAsyncResult
*simple
;
7121 simple
= g_simple_async_result_new (NULL
,
7125 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
7128 connection
= get_uninitialized_connection (bus_type
, cancellable
, &error
);
7129 if (connection
== NULL
)
7131 g_assert (error
!= NULL
);
7132 g_simple_async_result_take_error (simple
, error
);
7133 g_simple_async_result_complete_in_idle (simple
);
7134 g_object_unref (simple
);
7138 g_async_initable_init_async (G_ASYNC_INITABLE (connection
),
7141 bus_get_async_initable_cb
,
7148 * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
7150 * @error: return location for error or %NULL
7152 * Finishes an operation started with g_bus_get().
7154 * The returned object is a singleton, that is, shared with other
7155 * callers of g_bus_get() and g_bus_get_sync() for @bus_type. In the
7156 * event that you need a private message bus connection, use
7157 * g_dbus_address_get_for_bus_sync() and
7158 * g_dbus_connection_new_for_address().
7160 * Note that the returned #GDBusConnection object will (usually) have
7161 * the #GDBusConnection:exit-on-close property set to %TRUE.
7163 * Returns: (transfer full): a #GDBusConnection or %NULL if @error is set.
7164 * Free with g_object_unref().
7169 g_bus_get_finish (GAsyncResult
*res
,
7172 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (res
);
7174 GDBusConnection
*ret
;
7176 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
7178 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_bus_get
);
7182 if (g_simple_async_result_propagate_error (simple
, error
))
7185 object
= g_simple_async_result_get_op_res_gpointer (simple
);
7186 g_assert (object
!= NULL
);
7187 ret
= g_object_ref (G_DBUS_CONNECTION (object
));
7193 /* ---------------------------------------------------------------------------------------------------- */