From 666fe95480c14d7cbf5143b1a4e1bf0558403d4d Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 6 Sep 2003 18:21:00 +0000 Subject: [PATCH] 2003-09-06 Havoc Pennington * dbus/dbus-connection.c (dbus_connection_register_fallback): add this (dbus_connection_register_object_path): make this not handle messages to paths below the given path --- ChangeLog | 6 ++++++ dbus/dbus-connection.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- dbus/dbus-connection.h | 4 ++++ dbus/dbus-object-tree.c | 37 ++++++++++++++++++++++++++++--------- dbus/dbus-object-tree.h | 1 + 5 files changed, 82 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index ccca8a8..a9328da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2003-09-06 Havoc Pennington + + * dbus/dbus-connection.c (dbus_connection_register_fallback): add this + (dbus_connection_register_object_path): make this not handle + messages to paths below the given path + 2003-09-03 Havoc Pennington * test/glib/Makefile.am: add this with random glib-linked test diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 608634d..b8e67c1 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -3049,8 +3049,8 @@ dbus_connection_remove_filter (DBusConnection *connection, } /** - * Registers a handler for a given subsection of the object hierarchy. - * The given vtable handles messages at or below the given path. + * 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 @@ -3074,7 +3074,47 @@ dbus_connection_register_object_path (DBusConnection *connection, CONNECTION_LOCK (connection); - retval = _dbus_object_tree_register (connection->objects, path, vtable, + retval = _dbus_object_tree_register (connection->objects, + FALSE, + path, vtable, + user_data); + + CONNECTION_UNLOCK (connection); + + 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." + * + * + * @param connection the connection + * @param path #NULL-terminated array 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 +dbus_connection_register_fallback (DBusConnection *connection, + const char **path, + const DBusObjectPathVTable *vtable, + void *user_data) +{ + 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] != NULL, FALSE); + _dbus_return_val_if_fail (vtable != NULL, FALSE); + + CONNECTION_LOCK (connection); + + retval = _dbus_object_tree_register (connection->objects, + TRUE, + path, vtable, user_data); CONNECTION_UNLOCK (connection); diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index c5dee7f..bbdbcda 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -229,6 +229,10 @@ dbus_bool_t dbus_connection_register_object_path (DBusConnection const char **path, const DBusObjectPathVTable *vtable, void *user_data); +dbus_bool_t dbus_connection_register_fallback (DBusConnection *connection, + const char **path, + const DBusObjectPathVTable *vtable, + void *user_data); void dbus_connection_unregister_object_path (DBusConnection *connection, const char **path); diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c index 24e402a..8430b32 100644 --- a/dbus/dbus-object-tree.c +++ b/dbus/dbus-object-tree.c @@ -71,6 +71,7 @@ struct DBusObjectSubtree DBusObjectSubtree **subtrees; int n_subtrees; unsigned int subtrees_sorted : 1; + unsigned int invoke_as_fallback : 1; char name[1]; /**< Allocated as large as necessary */ }; @@ -93,7 +94,8 @@ _dbus_object_tree_new (DBusConnection *connection) tree->root = _dbus_object_subtree_new ("/", NULL, NULL); if (tree->root == NULL) goto oom; - + tree->root->invoke_as_fallback = TRUE; + return tree; oom: @@ -221,7 +223,8 @@ find_subtree_recurse (DBusObjectSubtree *subtree, next = find_subtree_recurse (subtree->subtrees[i], &path[1], return_deepest_match, create_if_not_found, index_in_parent); - if (next == NULL) + if (next == NULL && + subtree->invoke_as_fallback) { #if VERBOSE_FIND _dbus_verbose (" no deeper match found, returning %s\n", @@ -293,7 +296,7 @@ find_subtree_recurse (DBusObjectSubtree *subtree, create_if_not_found, index_in_parent); } else - return return_deepest_match ? subtree : NULL; + return (return_deepest_match && subtree->invoke_as_fallback) ? subtree : NULL; } static DBusObjectSubtree* @@ -339,6 +342,7 @@ ensure_subtree (DBusObjectTree *tree, * Registers a new subtree in the global object tree. * * @param tree the global object tree + * @param fallback #TRUE to handle messages to children of this path * @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 @@ -346,6 +350,7 @@ ensure_subtree (DBusObjectTree *tree, */ dbus_bool_t _dbus_object_tree_register (DBusObjectTree *tree, + dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, void *user_data) @@ -360,17 +365,22 @@ _dbus_object_tree_register (DBusObjectTree *tree, if (subtree == NULL) 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"); 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; } @@ -395,6 +405,7 @@ _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree, subtree = find_subtree (tree, path, &i); +#ifndef DBUS_DISABLE_CHECKS if (subtree == NULL) { _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n", @@ -402,6 +413,9 @@ _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree, path[1] ? path[1] : "null"); return; } +#else + _dbus_assert (subtree != NULL); +#endif _dbus_assert (subtree->parent == NULL || (i >= 0 && subtree->parent->subtrees[i] == subtree)); @@ -523,7 +537,7 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, DBusList *link; DBusHandlerResult result; DBusObjectSubtree *subtree; - + #if 0 _dbus_verbose ("Dispatch of message by object path\n"); #endif @@ -540,10 +554,10 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, _dbus_verbose ("No path field in message\n"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - + /* Find the deepest path that covers the path in the message */ subtree = find_handler (tree, (const char**) path); - + /* Build a list of all paths that cover the path in the message */ list = NULL; @@ -884,7 +898,7 @@ do_register (DBusObjectTree *tree, tree_test_data[i].handler_unregistered = FALSE; tree_test_data[i].path = path; - if (!_dbus_object_tree_register (tree, path, + if (!_dbus_object_tree_register (tree, TRUE, path, &vtable, &tree_test_data[i])) return FALSE; @@ -1269,7 +1283,12 @@ object_tree_test_iteration (void *data) out: if (tree) - _dbus_object_tree_unref (tree); + { + /* test ref */ + _dbus_object_tree_ref (tree); + _dbus_object_tree_unref (tree); + _dbus_object_tree_unref (tree); + } return TRUE; } diff --git a/dbus/dbus-object-tree.h b/dbus/dbus-object-tree.h index 5d44bbe..21d8b5f 100644 --- a/dbus/dbus-object-tree.h +++ b/dbus/dbus-object-tree.h @@ -34,6 +34,7 @@ void _dbus_object_tree_ref (DBusObjectTree *tree); void _dbus_object_tree_unref (DBusObjectTree *tree); dbus_bool_t _dbus_object_tree_register (DBusObjectTree *tree, + dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, void *user_data); -- 2.7.4