From c53d19f177f56a3c8833fcb9ff0e7dd004e6062a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 12 Dec 2014 12:09:02 +0100
Subject: [PATCH 5/9] sbus: support multiple interfaces on single path

This patch removes the old message handler which is replaced
with a new one that supports multiple interfaces registered
on single object path.

It temporarily removes support of Introspect and Properties
standard D-Bus interfaces. The support is brought back by
following patches.

Resolves:
https://fedorahosted.org/sssd/ticket/2339
---
 src/sbus/sssd_dbus.h            |   9 +-
 src/sbus/sssd_dbus_connection.c | 197 ++-----------------------
 src/sbus/sssd_dbus_interface.c  | 310 +++++++++++++++++++++++++---------------
 src/sbus/sssd_dbus_private.h    |  20 +--
 4 files changed, 213 insertions(+), 323 deletions(-)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 7552fbcf1a4fd630970eec378f2f725c6d00eaa4..c50b4e9b659a3a35b50e38d8295dbccd9e1a062d 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -170,6 +170,9 @@ int sbus_conn_register_iface(struct sbus_connection *conn,
                              const char *object_path,
                              void *pvt);
 
+errno_t
+sbus_conn_reregister_paths(struct sbus_connection *conn);
+
 bool sbus_conn_disconnecting(struct sbus_connection *conn);
 
 /* max_retries < 0: retry forever
@@ -181,12 +184,6 @@ void sbus_reconnect_init(struct sbus_connection *conn,
                          sbus_conn_reconn_callback_fn callback,
                          void *pvt);
 
-/* Default message handler
- * Should be usable for most cases */
-DBusHandlerResult sbus_message_handler(DBusConnection *conn,
-                                  DBusMessage *message,
-                                  void *user_data);
-
 /*
  * Send a message across the SBUS
  * If requested, the DBusPendingCall object will
diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index d27fd2fadfec989935b238a2719bd34048844d8a..8ff279c1bf5f20d5396e1e41c6a162328657091f 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -161,6 +161,13 @@ int sbus_init_connection(TALLOC_CTX *ctx,
     conn->dbus.conn = dbus_conn;
     conn->connection_type = connection_type;
 
+    ret = sbus_opath_hash_init(conn, conn, &conn->managed_paths);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create object paths hash table\n");
+        talloc_free(conn);
+        return EIO;
+    }
+
     ret = sss_hash_create(conn, 32, &conn->clients);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create clients hash table\n");
@@ -313,7 +320,7 @@ void sbus_disconnect(struct sbus_connection *conn)
     conn->disconnect = 1;
 
     /* Unregister object paths */
-    sbus_unreg_object_paths(conn);
+    talloc_zfree(conn->managed_paths);
 
     /* Disable watch functions */
     dbus_connection_set_watch_functions(conn->dbus.conn,
@@ -342,185 +349,12 @@ void sbus_disconnect(struct sbus_connection *conn)
     DEBUG(SSSDBG_TRACE_FUNC ,"Disconnected %p\n", conn->dbus.conn);
 }
 
-static void sbus_handler_got_caller_id(struct tevent_req *req);
-
-/* messsage_handler
- * Receive messages and process them
- */
-DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
-                                       DBusMessage *message,
-                                       void *user_data)
-{
-    struct sbus_interface_p *intf_p;
-    const char *msg_method;
-    const char *path;
-    const char *msg_interface;
-    const char *sender;
-    struct sbus_request *dbus_req = NULL;
-    struct tevent_req *req;
-
-    if (!user_data) {
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-    intf_p = talloc_get_type(user_data, struct sbus_interface_p);
-
-    msg_method = dbus_message_get_member(message);
-    DEBUG(SSSDBG_TRACE_ALL, "Received SBUS method [%s]\n", msg_method);
-    path = dbus_message_get_path(message);
-    msg_interface = dbus_message_get_interface(message);
-    sender = dbus_message_get_sender(message);
-
-    if (!msg_method || !path || !msg_interface) {
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    /* Validate the D-BUS path */
-    if (!sbus_iface_handles_path(intf_p, path)) {
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    /* Validate the method interface */
-    if (strcmp(msg_interface, intf_p->intf->vtable->meta->name) == 0 ||
-             strcmp(msg_interface, DBUS_PROPERTIES_INTERFACE) == 0 ||
-            (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 &&
-                strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0)) {
-
-        /* OK, this message for us. Get the sender ID if applicable */
-        dbus_req = sbus_new_request(intf_p->conn, intf_p->intf, message);
-        if (dbus_req == NULL) {
-            return DBUS_HANDLER_RESULT_NEED_MEMORY;
-        }
-
-        req = sbus_get_sender_id_send(dbus_req, dbus_req->conn->ev,
-                                      dbus_req->conn, sender);
-        if (req == NULL) {
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-        }
-        tevent_req_set_callback(req, sbus_handler_got_caller_id, dbus_req);
-        return DBUS_HANDLER_RESULT_HANDLED;
-    }
-
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static void sbus_handler_got_caller_id(struct tevent_req *req)
-{
-    struct sbus_request *dbus_req = \
-                      tevent_req_callback_data(req,
-                                               struct sbus_request);
-    errno_t ret;
-    DBusError *dberr;
-    DBusMessage *reply = NULL;
-    const struct sbus_method_meta *method;
-    const struct sbus_interface_meta *interface;
-    const char *msg_method;
-    const char *msg_interface;
-    sbus_msg_handler_fn handler_fn = NULL;
-    void *handler_data = NULL; /* Must be a talloc pointer! */
-    struct sbus_introspect_ctx *ictx = NULL;
-    const char *dbus_error = NULL;
-
-    ret = sbus_get_sender_id_recv(req, &dbus_req->client);
-    if (ret != EOK) {
-        dberr = sbus_error_new(dbus_req,
-                               DBUS_ERROR_FAILED,
-                               "Failed to retrieve called ID: %s\n",
-                               sss_strerror(ret));
-        sbus_request_fail_and_finish(dbus_req, dberr);
-        return;
-    }
-
-    msg_method = dbus_message_get_member(dbus_req->message);
-    msg_interface = dbus_message_get_interface(dbus_req->message);
-    DEBUG(SSSDBG_TRACE_ALL, "Received SBUS method [%s]\n", msg_method);
-
-    /* Prepare the handler */
-    interface = dbus_req->intf->vtable->meta;
-    if (strcmp(msg_interface, interface->name) == 0) {
-        method = sbus_meta_find_method(interface, msg_method);
-        if (method && method->vtable_offset)
-            handler_fn = VTABLE_FUNC(dbus_req->intf->vtable,
-                                     method->vtable_offset);
-
-        if (!method) {
-            /* Reply DBUS_ERROR_UNKNOWN_METHOD */
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "No matching method found for %s.\n", msg_method);
-            dbus_error = DBUS_ERROR_UNKNOWN_METHOD;
-            goto fail;
-        } else if (!handler_fn) {
-            /* Reply DBUS_ERROR_NOT_SUPPORTED */
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "No handler provided found for %s.\n", msg_method);
-            dbus_error = DBUS_ERROR_NOT_SUPPORTED;
-            goto fail;
-        }
-    } else if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 &&
-                strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0) {
-            DEBUG(SSSDBG_TRACE_LIBS, "Got introspection request\n");
-            ictx = talloc(dbus_req->conn, struct sbus_introspect_ctx);
-            if (ictx == NULL) {
-                dbus_error = DBUS_ERROR_NO_MEMORY;
-                goto fail;
-            }
-
-            handler_fn = sbus_introspect;
-            ictx->iface = interface;
-            handler_data = ictx;
-            method = &introspect_method;
-    } else if (strcmp(msg_interface, DBUS_PROPERTIES_INTERFACE) == 0) {
-        ret = sbus_properties_dispatch(dbus_req);
-        if (ret == ERR_SBUS_NOSUP) {
-            /* No known method matched */
-            dbus_error = DBUS_ERROR_NOT_SUPPORTED;
-            goto fail;
-        }
-        /* sbus_properties_dispatch handles all other errors
-         * or success internally
-         */
-        return;
-    }
-
-    if (handler_fn == NULL) {
-        DEBUG(SSSDBG_MINOR_FAILURE, "No handler matched!\n");
-        dbus_error = DBUS_ERROR_NOT_SUPPORTED;
-        goto fail;
-    }
-
-    dbus_req->method = method;
-    if (handler_data) {
-        /* If the handler uses private instance data, make
-         * sure they go away when the request does
-         */
-        talloc_steal(dbus_req, handler_data);
-    } else {
-        /* If no custom handler data is set, pass on the
-         * interface data
-         */
-        handler_data = dbus_req->intf->instance_data;
-    }
-
-    sbus_request_invoke_or_finish(dbus_req,
-                                  handler_fn,
-                                  handler_data,
-                                  method->invoker);
-    return;
-
-fail:
-    reply = dbus_message_new_error(dbus_req->message,
-                                   dbus_error ? dbus_error : DBUS_ERROR_FAILED,
-                                   NULL);
-    sbus_request_finish(dbus_req, reply);
-}
-
 static void sbus_reconnect(struct tevent_context *ev,
                            struct tevent_timer *te,
                            struct timeval tv, void *data)
 {
     struct sbus_connection *conn;
-    struct sbus_interface_p *iter;
     DBusError dbus_error;
-    dbus_bool_t dbret;
     int ret;
 
     conn = talloc_get_type(data, struct sbus_connection);
@@ -539,20 +373,7 @@ static void sbus_reconnect(struct tevent_context *ev,
         }
 
         /* Re-register object paths */
-        iter = conn->intf_list;
-        while (iter) {
-            dbret = dbus_connection_register_object_path(conn->dbus.conn,
-                                                         iter->intf->path,
-                                                         &dbus_object_path_vtable,
-                                                         iter);
-            if (!dbret) {
-                DEBUG(SSSDBG_FATAL_FAILURE,
-                      "Could not register object path.\n");
-                dbus_connection_unref(conn->dbus.conn);
-                goto failed;
-            }
-            iter = iter->next;
-        }
+        sbus_conn_reregister_paths(conn);
 
         /* Reset retries to 0 to resume dispatch processing */
         conn->retries = 0;
diff --git a/src/sbus/sssd_dbus_interface.c b/src/sbus/sssd_dbus_interface.c
index 876d26d9e4ae0c60402780e56bb1a6e2b98cfd72..41a39c7da281e334ef0043703bdfb0df88d4d963 100644
--- a/src/sbus/sssd_dbus_interface.c
+++ b/src/sbus/sssd_dbus_interface.c
@@ -24,11 +24,9 @@
 
 #include "util/util.h"
 #include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_meta.h"
 #include "sbus/sssd_dbus_private.h"
 
-DBusObjectPathVTable dbus_object_path_vtable =
-    { NULL, sbus_message_handler, NULL, NULL, NULL, NULL };
-
 struct sbus_interface_list {
     struct sbus_interface_list *prev, *next;
     struct sbus_interface *interface;
@@ -49,37 +47,6 @@ sbus_iface_list_lookup(struct sbus_interface_list *list,
     return NULL;
 }
 
-static bool path_in_interface_list(struct sbus_interface_p *list,
-                                   const char *path)
-{
-    struct sbus_interface_p *iter;
-
-    if (!list || !path) {
-        return false;
-    }
-
-    iter = list;
-    while (iter != NULL) {
-        if (strcmp(iter->intf->path, path) == 0) {
-            return true;
-        }
-        iter = iter->next;
-    }
-
-    return false;
-}
-
-void sbus_unreg_object_paths(struct sbus_connection *conn)
-{
-    struct sbus_interface_p *iter = conn->intf_list;
-
-    while (iter != NULL) {
-        dbus_connection_unregister_object_path(conn->dbus.conn,
-                                               iter->intf->path);
-        iter = iter->next;
-    }
-}
-
 /**
  * Object paths that represent all objects under the path:
  * /org/object/path/~* (without tilda)
@@ -97,24 +64,6 @@ static bool sbus_opath_is_subtree(const char *path)
     return path[len - 2] == '/' && path[len - 1] == '*';
 }
 
-static bool sbus_opath_match_tree(const char *object_path,
-                                  const char *tree_path)
-{
-    if (object_path == NULL || tree_path == NULL || tree_path[0] == '\0') {
-        return false;
-    };
-
-    /* first check if tree is a base path or a subtree path */
-    if (!sbus_opath_is_subtree(tree_path)) {
-        return strcmp(object_path, tree_path) == 0;
-    }
-
-    /* Compare without the asterisk, which is the last character.
-     * Slash, that has to be present before the asterisk, will ensure that only
-     * subtree object path matches. */
-    return strncmp(object_path, tree_path, strlen(tree_path) - 1) == 0;
-}
-
 /**
  * If the path represents a subtree object path, this function will
  * remove /~* from the end.
@@ -178,16 +127,6 @@ static char *sbus_opath_march_up(TALLOC_CTX *mem_ctx,
     return subtree;
 }
 
-bool sbus_iface_handles_path(struct sbus_interface_p *intf_p,
-                                    const char *path)
-{
-    if (sbus_opath_is_subtree(intf_p->intf->path)) {
-        return sbus_opath_match_tree(path, intf_p->intf->path);
-    }
-
-    return strcmp(path, intf_p->intf->path) == 0;
-}
-
 static void
 sbus_opath_hash_delete_cb(hash_entry_t *item,
                           hash_destroy_enum deltype,
@@ -202,7 +141,7 @@ sbus_opath_hash_delete_cb(hash_entry_t *item,
     dbus_connection_unregister_object_path(conn->dbus.conn, path);
 }
 
-static errno_t
+errno_t
 sbus_opath_hash_init(TALLOC_CTX *mem_ctx,
                      struct sbus_connection *conn,
                      hash_table_t **_table)
@@ -386,67 +325,210 @@ sbus_new_interface(TALLOC_CTX *mem_ctx,
     return intf;
 }
 
-int sbus_conn_register_iface(struct sbus_connection *conn,
-                             struct sbus_vtable *iface_vtable,
-                             const char *object_path,
-                             void *pvt)
+static DBusHandlerResult
+sbus_message_handler(DBusConnection *dbus_conn,
+                     DBusMessage *message,
+                     void *user_data);
+
+static errno_t
+sbus_conn_register_path(struct sbus_connection *conn,
+                        const char *path)
 {
-    struct sbus_interface_p *intf_p;
-    struct sbus_interface *intf;
+    static DBusObjectPathVTable vtable = {NULL, sbus_message_handler,
+                                          NULL, NULL, NULL, NULL};
+    char *reg_path = NULL;
     dbus_bool_t dbret;
-    const char *path;
-    bool fallback;
 
-    intf = sbus_new_interface(conn, object_path, iface_vtable, pvt);
-    if (intf == NULL) {
-        return ENOMEM;
-    }
+    DEBUG(SSSDBG_TRACE_FUNC, "Registering object path %s with D-Bus "
+          "connection\n", path);
 
-    if (!conn || !intf->vtable || !intf->vtable->meta) {
-        return EINVAL;
-    }
+    if (sbus_opath_is_subtree(path)) {
+        reg_path = sbus_opath_get_base_path(conn, path);
+        if (reg_path == NULL) {
+            return ENOMEM;
+        }
 
-    path = intf->path;
-    fallback = sbus_opath_is_subtree(path);
-
-    if (path_in_interface_list(conn->intf_list, path)) {
-        DEBUG(SSSDBG_FATAL_FAILURE,
-              "Cannot add method context with identical path.\n");
-        return EINVAL;
-    }
-
-    intf_p = talloc_zero(conn, struct sbus_interface_p);
-    if (!intf_p) {
-        return ENOMEM;
-    }
-    intf_p->conn = conn;
-    intf_p->intf = intf;
-    intf_p->reg_path = sbus_opath_get_base_path(intf_p, path);
-    if (intf_p->reg_path == NULL) {
-        return ENOMEM;
-    }
-
-    DLIST_ADD(conn->intf_list, intf_p);
-
-    DEBUG(SSSDBG_TRACE_LIBS, "Will register path %s with%s fallback\n",
-                             intf_p->reg_path, fallback ? "" : "out");
-
-    if (fallback) {
-        dbret = dbus_connection_register_fallback(conn->dbus.conn,
-                                                  intf_p->reg_path,
-                                                  &dbus_object_path_vtable,
-                                                  intf_p);
+        dbret = dbus_connection_register_fallback(conn->dbus.conn, reg_path,
+                                                  &vtable, conn);
+        talloc_free(reg_path);
     } else {
-        dbret = dbus_connection_register_object_path(conn->dbus.conn,
-                                                     intf_p->reg_path,
-                                                     &dbus_object_path_vtable,
-                                                     intf_p);
+        dbret = dbus_connection_register_object_path(conn->dbus.conn, path,
+                                                     &vtable, conn);
     }
+
     if (!dbret) {
-        DEBUG(SSSDBG_FATAL_FAILURE,
-              "Could not register object path to the connection.\n");
+        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register object path "
+              "%s with D-Bus connection.\n", path);
         return ENOMEM;
     }
 
     return EOK;
 }
+
+errno_t
+sbus_conn_register_iface(struct sbus_connection *conn,
+                         struct sbus_vtable *iface_vtable,
+                         const char *object_path,
+                         void *pvt)
+{
+    struct sbus_interface *iface = NULL;
+    bool path_known;
+    errno_t ret;
+
+    if (conn == NULL || iface_vtable == NULL || object_path == NULL) {
+        return EINVAL;
+    }
+
+    iface = sbus_new_interface(conn, object_path, iface_vtable, pvt);
+    if (iface == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sbus_opath_hash_add_iface(conn->managed_paths, object_path, iface,
+                                    &path_known);
+    if (ret != EOK) {
+        talloc_free(iface);
+        return ret;
+    }
+
+    if (path_known) {
+        /* this object path is already registered */
+        return EOK;
+    }
+
+    ret = sbus_conn_register_path(conn, object_path);
+
+    /* if ret != EOK we will still leave iface in the table, since
+     * we probably don't have enough memory to remove it correctly anyway */
+    return ret;
+}
+
+errno_t
+sbus_conn_reregister_paths(struct sbus_connection *conn)
+{
+    hash_key_t *keys = NULL;
+    unsigned long count;
+    unsigned long i;
+    errno_t ret;
+    int hret;
+
+    hret = hash_keys(conn->managed_paths, &count, &keys);
+    if (hret != HASH_SUCCESS) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    for (i = 0; i < count; i++) {
+        ret = sbus_conn_register_path(conn, keys[i].str);
+        if (ret != EOK) {
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(keys);
+    return ret;
+}
+
+static void
+sbus_message_handler_got_caller_id(struct tevent_req *req);
+
+static DBusHandlerResult
+sbus_message_handler(DBusConnection *dbus_conn,
+                     DBusMessage *message,
+                     void *user_data)
+{
+    struct tevent_req *req;
+    struct sbus_connection *conn;
+    struct sbus_interface *iface;
+    struct sbus_request *sbus_req;
+    const struct sbus_method_meta *method;
+    const char *iface_name;
+    const char *method_name;
+    const char *path;
+    const char *sender;
+
+    conn = talloc_get_type(user_data, struct sbus_connection);
+
+    /* header information */
+    iface_name = dbus_message_get_interface(message);
+    method_name = dbus_message_get_member(message);
+    path = dbus_message_get_path(message);
+    sender = dbus_message_get_sender(message);
+
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Received SBUS method %s.%s on path %s\n",
+          iface_name, method_name, path);
+
+    /* try to find the interface */
+    iface = sbus_opath_hash_lookup_iface(conn->managed_paths,
+                                         path, iface_name);
+    if (iface == NULL) {
+        goto fail;
+    }
+
+    method = sbus_meta_find_method(iface->vtable->meta, method_name);
+    if (method == NULL || method->vtable_offset == 0) {
+        goto fail;
+    }
+
+    /* we have a valid handler, create D-Bus request */
+    sbus_req = sbus_new_request(conn, iface, message);
+    if (sbus_req == NULL) {
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+    }
+
+    sbus_req->method = method;
+
+    /* now get the sender ID */
+    req = sbus_get_sender_id_send(sbus_req, conn->ev, conn, sender);
+    if (req == NULL) {
+        talloc_free(sbus_req);
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+    }
+    tevent_req_set_callback(req, sbus_message_handler_got_caller_id, sbus_req);
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+
+fail: ;
+    DBusMessage *reply;
+
+    DEBUG(SSSDBG_CRIT_FAILURE, "No matching handler found for method %s.%s "
+          "on path %s\n", iface_name, method_name, path);
+
+    reply = dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
+    sbus_conn_send_reply(conn, reply);
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+sbus_message_handler_got_caller_id(struct tevent_req *req)
+{
+    struct sbus_request *sbus_req;
+    const struct sbus_method_meta *method;
+    sbus_msg_handler_fn handler;
+    sbus_method_invoker_fn invoker;
+    void *pvt;
+    DBusError *error;
+    errno_t ret;
+
+    sbus_req = tevent_req_callback_data(req, struct sbus_request);
+    method = sbus_req->method;
+
+    ret = sbus_get_sender_id_recv(req, &sbus_req->client);
+    if (ret != EOK) {
+        error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to "
+                               "resolve caller's ID: %s\n", sss_strerror(ret));
+        sbus_request_fail_and_finish(sbus_req, error);
+        return;
+    }
+
+    handler = VTABLE_FUNC(sbus_req->intf->vtable, method->vtable_offset);
+    invoker = method->invoker;
+    pvt = sbus_req->intf->instance_data;
+
+    sbus_request_invoke_or_finish(sbus_req, handler, pvt, invoker);
+    return;
+}
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
index fc63405a13d417a17aa6b9c4803e74f2f165e494..23d2898f8377e188f94d2356e290626439dc763e 100644
--- a/src/sbus/sssd_dbus_private.h
+++ b/src/sbus/sssd_dbus_private.h
@@ -37,14 +37,6 @@ enum dbus_conn_type {
 
 struct sbus_watch_ctx;
 
-struct sbus_interface_p {
-    struct sbus_interface_p *prev, *next;
-    struct sbus_connection *conn;
-    struct sbus_interface *intf;
-
-    const char *reg_path;
-};
-
 struct sbus_connection {
     struct tevent_context *ev;
 
@@ -55,8 +47,7 @@ struct sbus_connection {
     int connection_type;
     int disconnect;
 
-    /* dbus tables and handlers */
-    struct sbus_interface_p *intf_list;
+    hash_table_t *managed_paths;
 
     /* reconnect settings */
     int retries;
@@ -75,8 +66,6 @@ struct sbus_connection {
     struct sbus_watch_ctx *watch_list;
 };
 
-extern DBusObjectPathVTable dbus_object_path_vtable;
-
 /* =Watches=============================================================== */
 
 struct sbus_watch_ctx {
@@ -114,9 +103,10 @@ sbus_new_request(struct sbus_connection *conn, struct sbus_interface *intf,
 
 /* =Interface=and=object=paths============================================ */
 
-void sbus_unreg_object_paths(struct sbus_connection *conn);
-bool sbus_iface_handles_path(struct sbus_interface_p *intf_p,
-                             const char *path);
+errno_t
+sbus_opath_hash_init(TALLOC_CTX *mem_ctx,
+                     struct sbus_connection *conn,
+                     hash_table_t **_table);
 
 /* =Interface=introspection=============================================== */
 extern const struct sbus_method_meta introspect_method;
-- 
1.7.11.7

