Add dbus_connection_try_register_object_path and dbus_connection_try_register_fallbac...
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Tue, 9 Oct 2007 16:19:36 +0000 (17:19 +0100)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Wed, 10 Oct 2007 16:33:18 +0000 (17:33 +0100)
dbus/dbus-connection.c
dbus/dbus-connection.h
dbus/dbus-object-tree.c
dbus/dbus-object-tree.h

index cc26b75..b6ecc36 100644 (file)
@@ -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;
 }
 
index 2efda44..5d7e493 100644 (file)
@@ -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,
index 18db1ee..276ac95 100644 (file)
@@ -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) ==
index 4434097..7e06c1f 100644 (file)
@@ -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,