mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-04 01:17:58 +02:00
Add dbus_connection_try_register_object_path and dbus_connection_try_register_fallback, to make object path registration less painful for bindings
This commit is contained in:
parent
1a5ef4003d
commit
557da17406
4 changed files with 178 additions and 31 deletions
|
|
@ -5265,18 +5265,20 @@ 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
|
||||
* @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_connection_register_object_path (DBusConnection *connection,
|
||||
const char *path,
|
||||
const DBusObjectPathVTable *vtable,
|
||||
void *user_data)
|
||||
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;
|
||||
|
|
@ -5294,7 +5296,108 @@ 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);
|
||||
|
||||
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
|
||||
* @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_object_path (DBusConnection *connection,
|
||||
const char *path,
|
||||
const DBusObjectPathVTable *vtable,
|
||||
void *user_data)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
|
||||
|
|
@ -5309,6 +5412,10 @@ dbus_connection_register_object_path (DBusConnection *connection,
|
|||
* 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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
#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)
|
||||
_DBUS_SET_OOM (error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (subtree->message_function != 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 <stdio.h>
|
||||
|
||||
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 <stdio.h>
|
||||
|
||||
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) ==
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue