diff options
| author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2007-10-09 17:19:36 +0100 | 
|---|---|---|
| committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2007-10-10 17:33:18 +0100 | 
| commit | 557da1740631818f96e40d0016a4cabdf34ed0f1 (patch) | |
| tree | 0374030e09240e0cca5a428dd6c0a7e64df823e8 | |
| parent | 1a5ef4003d07aab548e59621b1497b37ec84e59f (diff) | |
Add dbus_connection_try_register_object_path and dbus_connection_try_register_fallback, to make object path registration less painful for bindings
| -rw-r--r-- | dbus/dbus-connection.c | 125 | ||||
| -rw-r--r-- | dbus/dbus-connection.h | 13 | ||||
| -rw-r--r-- | dbus/dbus-object-tree.c | 54 | ||||
| -rw-r--r-- | 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 <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) == 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,  | 
