From 557da1740631818f96e40d0016a4cabdf34ed0f1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 9 Oct 2007 17:19:36 +0100 Subject: Add dbus_connection_try_register_object_path and dbus_connection_try_register_fallback, to make object path registration less painful for bindings --- dbus/dbus-connection.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++-- dbus/dbus-connection.h | 13 +++++ dbus/dbus-object-tree.c | 54 +++++++++++++-------- dbus/dbus-object-tree.h | 3 +- 4 files changed, 171 insertions(+), 24 deletions(-) diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index cc26b75c..b6ecc36d 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -5265,6 +5265,53 @@ dbus_connection_remove_filter (DBusConnection *connection, * Registers a handler for a given path in the object hierarchy. * The given vtable handles messages sent to exactly the given path. * + * @param connection the connection + * @param path a '/' delimited string of path elements + * @param vtable the virtual table + * @param user_data data to pass to functions in the vtable + * @param error address where an error can be returned + * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or + * #DBUS_ERROR_ADDRESS_IN_USE) is reported + */ +dbus_bool_t +dbus_connection_try_register_object_path (DBusConnection *connection, + const char *path, + const DBusObjectPathVTable *vtable, + void *user_data, + DBusError *error) +{ + char **decomposed_path; + dbus_bool_t retval; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (path != NULL, FALSE); + _dbus_return_val_if_fail (path[0] == '/', FALSE); + _dbus_return_val_if_fail (vtable != NULL, FALSE); + + if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) + return FALSE; + + CONNECTION_LOCK (connection); + + retval = _dbus_object_tree_register (connection->objects, + FALSE, + (const char **) decomposed_path, vtable, + user_data, error); + + CONNECTION_UNLOCK (connection); + + dbus_free_string_array (decomposed_path); + + return retval; +} + +/** + * Registers a handler for a given path in the object hierarchy. + * The given vtable handles messages sent to exactly the given path. + * + * It is a bug to call this function for object paths which already + * have a handler. Use dbus_connection_try_register_object_path() if this + * might be the case. * * @param connection the connection * @param path a '/' delimited string of path elements @@ -5280,12 +5327,15 @@ dbus_connection_register_object_path (DBusConnection *connection, { char **decomposed_path; dbus_bool_t retval; - + DBusError error; + _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (path != NULL, FALSE); _dbus_return_val_if_fail (path[0] == '/', FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); + dbus_error_init (&error); + if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) return FALSE; @@ -5294,12 +5344,19 @@ dbus_connection_register_object_path (DBusConnection *connection, retval = _dbus_object_tree_register (connection->objects, FALSE, (const char **) decomposed_path, vtable, - user_data); + user_data, &error); CONNECTION_UNLOCK (connection); dbus_free_string_array (decomposed_path); + if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) + { + _dbus_warn ("%s\n", error.message); + dbus_error_free (&error); + return FALSE; + } + return retval; } @@ -5313,6 +5370,56 @@ dbus_connection_register_object_path (DBusConnection *connection, * @param path a '/' delimited string of path elements * @param vtable the virtual table * @param user_data data to pass to functions in the vtable + * @param error address where an error can be returned + * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or + * #DBUS_ERROR_ADDRESS_IN_USE) is reported + */ +dbus_bool_t +dbus_connection_try_register_fallback (DBusConnection *connection, + const char *path, + const DBusObjectPathVTable *vtable, + void *user_data, + DBusError *error) +{ + char **decomposed_path; + dbus_bool_t retval; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (path != NULL, FALSE); + _dbus_return_val_if_fail (path[0] == '/', FALSE); + _dbus_return_val_if_fail (vtable != NULL, FALSE); + + if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) + return FALSE; + + CONNECTION_LOCK (connection); + + retval = _dbus_object_tree_register (connection->objects, + TRUE, + (const char **) decomposed_path, vtable, + user_data, error); + + CONNECTION_UNLOCK (connection); + + dbus_free_string_array (decomposed_path); + + return retval; +} + +/** + * Registers a fallback handler for a given subsection of the object + * hierarchy. The given vtable handles messages at or below the given + * path. You can use this to establish a default message handling + * policy for a whole "subdirectory." + * + * It is a bug to call this function for object paths which already + * have a handler. Use dbus_connection_try_register_fallback() if this + * might be the case. + * + * @param connection the connection + * @param path a '/' delimited string of path elements + * @param vtable the virtual table + * @param user_data data to pass to functions in the vtable * @returns #FALSE if not enough memory */ dbus_bool_t @@ -5323,12 +5430,15 @@ dbus_connection_register_fallback (DBusConnection *connection, { char **decomposed_path; dbus_bool_t retval; - + DBusError error; + _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (path != NULL, FALSE); _dbus_return_val_if_fail (path[0] == '/', FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); + dbus_error_init (&error); + if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) return FALSE; @@ -5337,12 +5447,19 @@ dbus_connection_register_fallback (DBusConnection *connection, retval = _dbus_object_tree_register (connection->objects, TRUE, (const char **) decomposed_path, vtable, - user_data); + user_data, &error); CONNECTION_UNLOCK (connection); dbus_free_string_array (decomposed_path); + if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) + { + _dbus_warn ("%s\n", error.message); + dbus_error_free (&error); + return FALSE; + } + return retval; } diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 2efda44e..5d7e493b 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -321,10 +321,23 @@ struct DBusObjectPathVTable void (* dbus_internal_pad4) (void *); /**< Reserved for future expansion */ }; +dbus_bool_t dbus_connection_try_register_object_path (DBusConnection *connection, + const char *path, + const DBusObjectPathVTable *vtable, + void *user_data, + DBusError *error); + dbus_bool_t dbus_connection_register_object_path (DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data); + +dbus_bool_t dbus_connection_try_register_fallback (DBusConnection *connection, + const char *path, + const DBusObjectPathVTable *vtable, + void *user_data, + DBusError *error); + dbus_bool_t dbus_connection_register_fallback (DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c index 18db1ee2..276ac955 100644 --- a/dbus/dbus-object-tree.c +++ b/dbus/dbus-object-tree.c @@ -371,6 +371,8 @@ ensure_subtree (DBusObjectTree *tree, return find_subtree_recurse (tree->root, path, TRUE, NULL, NULL); } +static char *flatten_path (const char **path); + /** * Registers a new subtree in the global object tree. * @@ -379,14 +381,17 @@ ensure_subtree (DBusObjectTree *tree, * @param path NULL-terminated array of path elements giving path to subtree * @param vtable the vtable used to traverse this subtree * @param user_data user data to pass to methods in the vtable - * @returns #FALSE if not enough memory + * @param error address where an error can be returned + * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or + * #DBUS_ERROR_ADDRESS_IN_USE) is reported */ dbus_bool_t _dbus_object_tree_register (DBusObjectTree *tree, dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, - void *user_data) + void *user_data, + DBusError *error) { DBusObjectSubtree *subtree; @@ -396,24 +401,34 @@ _dbus_object_tree_register (DBusObjectTree *tree, subtree = ensure_subtree (tree, path); if (subtree == NULL) - return FALSE; + { + if (error != NULL) + _DBUS_SET_OOM (error); + + return FALSE; + } -#ifndef DBUS_DISABLE_CHECKS if (subtree->message_function != NULL) { - _dbus_warn ("A handler is already registered for the path starting with path[0] = \"%s\"\n", - path[0] ? path[0] : "null"); + if (error != NULL) + { + char *complete_path = flatten_path (path); + + dbus_set_error (error, DBUS_ERROR_ADDRESS_IN_USE, "A handler is already registered for %s", + complete_path ? complete_path + : "(cannot represent path: out of memory!)"); + + dbus_free (complete_path); + } + return FALSE; } -#else - _dbus_assert (subtree->message_function == NULL); -#endif subtree->message_function = vtable->message_function; subtree->unregister_function = vtable->unregister_function; subtree->user_data = user_data; subtree->invoke_as_fallback = fallback != FALSE; - + return TRUE; } @@ -1140,13 +1155,6 @@ _dbus_decompose_path (const char* data, /** @} */ -#ifdef DBUS_BUILD_TESTS - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -#include "dbus-test.h" -#include - static char* flatten_path (const char **path) { @@ -1191,6 +1199,13 @@ flatten_path (const char **path) } +#ifdef DBUS_BUILD_TESTS + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#include "dbus-test.h" +#include + typedef enum { STR_EQUAL, @@ -1314,7 +1329,7 @@ do_register (DBusObjectTree *tree, { DBusObjectPathVTable vtable = { test_unregister_function, test_message_function, NULL }; - + tree_test_data[i].message_handled = FALSE; tree_test_data[i].handler_unregistered = FALSE; tree_test_data[i].handler_fallback = fallback; @@ -1322,7 +1337,8 @@ do_register (DBusObjectTree *tree, if (!_dbus_object_tree_register (tree, fallback, path, &vtable, - &tree_test_data[i])) + &tree_test_data[i], + NULL)) return FALSE; _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path) == diff --git a/dbus/dbus-object-tree.h b/dbus/dbus-object-tree.h index 4434097d..7e06c1f6 100644 --- a/dbus/dbus-object-tree.h +++ b/dbus/dbus-object-tree.h @@ -37,7 +37,8 @@ dbus_bool_t _dbus_object_tree_register (DBusObjectTree dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, - void *user_data); + void *user_data, + DBusError *error); void _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree, const char **path); DBusHandlerResult _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, -- cgit