summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-bus.c')
-rw-r--r--dbus/dbus-bus.c218
1 files changed, 210 insertions, 8 deletions
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index cc612a78..3e409257 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -31,26 +31,177 @@
* @ingroup DBus
* @brief Functions for communicating with the message bus
*
+ */
+
+
+/**
+ * @defgroup DBusBusInternals Message bus APIs internals
+ * @ingroup DBusInternals
+ * @brief Internals of functions for communicating with the message bus
+ *
+ * @{
+ */
+
+/**
+ * Block of message-bus-related data we attach to each
+ * #DBusConnection used with these convenience functions.
+ *
+ */
+typedef struct
+{
+ char *base_service;
+
+} BusData;
+
+/** The slot we have reserved to store BusData
+ */
+static int bus_data_slot = -1;
+/** Number of connections using the slot
+ */
+static int bus_data_slot_refcount = 0;
+
+/**
+ * Lock for bus_data_slot and bus_data_slot_refcount
+ */
+static DBusMutex *slot_lock;
+
+/**
+ * Initialize the mutex used for bus_data_slot
+ *
+ * @returns the mutex
+ */
+DBusMutex *
+_dbus_bus_init_lock (void)
+{
+ slot_lock = dbus_mutex_new ();
+ return slot_lock;
+}
+
+static dbus_bool_t
+data_slot_ref (void)
+{
+ dbus_mutex_lock (slot_lock);
+
+ if (bus_data_slot < 0)
+ bus_data_slot = dbus_connection_allocate_data_slot ();
+
+ if (bus_data_slot < 0)
+ {
+ dbus_mutex_unlock (slot_lock);
+ return FALSE;
+ }
+
+ bus_data_slot_refcount += 1;
+
+ dbus_mutex_unlock (slot_lock);
+
+ return TRUE;
+}
+
+static void
+data_slot_unref (void)
+{
+ dbus_mutex_lock (slot_lock);
+
+ _dbus_assert (bus_data_slot >= 0);
+ _dbus_assert (bus_data_slot_refcount > 0);
+
+ bus_data_slot_refcount -= 1;
+
+ if (bus_data_slot_refcount == 0)
+ {
+ dbus_connection_free_data_slot (bus_data_slot);
+ bus_data_slot = -1;
+ }
+
+ dbus_mutex_unlock (slot_lock);
+}
+
+static void
+bus_data_free (void *data)
+{
+ BusData *bd = data;
+
+ dbus_free (bd->base_service);
+ dbus_free (bd);
+
+ data_slot_unref ();
+}
+
+static BusData*
+ensure_bus_data (DBusConnection *connection)
+{
+ BusData *bd;
+
+ if (!data_slot_ref ())
+ return NULL;
+
+ bd = dbus_connection_get_data (connection, bus_data_slot);
+ if (bd == NULL)
+ {
+ bd = dbus_new0 (BusData, 1);
+ if (bd == NULL)
+ {
+ data_slot_unref ();
+ return NULL;
+ }
+
+ dbus_connection_set_data (connection, bus_data_slot, bd,
+ bus_data_free);
+
+ /* Data slot refcount now held by the BusData */
+ }
+ else
+ {
+ data_slot_unref ();
+ }
+
+ return bd;
+}
+
+/** @} */ /* end of implementation details docs */
+
+/**
+ * @addtogroup DBusBus
* @{
*/
/**
* Registers a connection with the bus. This must be the first
* thing an application does when connecting to the message bus.
+ * If registration succeeds, the base service name will be set,
+ * and can be obtained using dbus_bus_get_base_service().
*
* @todo if we get an error reply, it has to be converted into
* DBusError and returned
*
* @param connection the connection
* @param error place to store errors
- * @returns the client's unique service name, #NULL on error
+ * @returns #TRUE on success
*/
-char*
-dbus_bus_register_client (DBusConnection *connection,
- DBusError *error)
+dbus_bool_t
+dbus_bus_register (DBusConnection *connection,
+ DBusError *error)
{
DBusMessage *message, *reply;
char *name;
+ BusData *bd;
+
+ bd = ensure_bus_data (connection);
+ if (bd == NULL)
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (bd->base_service != NULL)
+ {
+ _dbus_warn ("Attempt to register the same DBusConnection with the message bus, but it is already registered\n");
+ /* This isn't an error, it's a programming bug. We'll be nice
+ * and not _dbus_assert_not_reached()
+ */
+ return TRUE;
+ }
message = dbus_message_new (DBUS_SERVICE_DBUS,
DBUS_MESSAGE_HELLO);
@@ -58,7 +209,7 @@ dbus_bus_register_client (DBusConnection *connection,
if (!message)
{
_DBUS_SET_OOM (error);
- return NULL;
+ return FALSE;
}
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
@@ -68,7 +219,7 @@ dbus_bus_register_client (DBusConnection *connection,
if (reply == NULL)
{
_DBUS_ASSERT_ERROR_IS_SET (error);
- return NULL;
+ return FALSE;
}
if (!dbus_message_get_args (reply, error,
@@ -76,10 +227,61 @@ dbus_bus_register_client (DBusConnection *connection,
0))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
- return NULL;
+ return FALSE;
}
+
+ bd->base_service = name;
+
+ return TRUE;
+}
+
+
+/**
+ * Sets the base service name of the connection.
+ * Can only be used if you registered with the
+ * bus manually (i.e. if you did not call
+ * dbus_bus_register()). Can only be called
+ * once per connection.
+ *
+ * @param connection the connection
+ * @param the base service name
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_bus_set_base_service (DBusConnection *connection,
+ const char *base_service)
+{
+ BusData *bd;
+
+ bd = ensure_bus_data (connection);
+ if (bd == NULL)
+ return FALSE;
+
+ _dbus_assert (bd->base_service == NULL);
+ _dbus_assert (base_service != NULL);
+
+ bd->base_service = _dbus_strdup (base_service);
+ return bd->base_service != NULL;
+}
+
+/**
+ * Gets the base service name of the connection.
+ * Only possible after the connection has been registered
+ * with the message bus.
+ *
+ * @param connection the connection
+ * @returns the base service name
+ */
+const char*
+dbus_bus_get_base_service (DBusConnection *connection)
+{
+ BusData *bd;
+
+ bd = ensure_bus_data (connection);
+ if (bd == NULL)
+ return NULL;
- return name;
+ return bd->base_service;
}
/**