2003-04-02 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / driver.c
index eacca93..0cea1d6 100644 (file)
  *
  */
 
+#include "activation.h"
 #include "connection.h"
 #include "driver.h"
+#include "dispatch.h"
 #include "services.h"
-#include <dbus/dbus-message-internal.h>
-#include <dbus/dbus-internals.h>
+#include "utils.h"
 #include <dbus/dbus-string.h>
+#include <dbus/dbus-internals.h>
 #include <string.h>
 
-#define BUS_DRIVER_SERVICE_NAME "org.freedesktop.DBus"
-#define BUS_DRIVER_HELLO_NAME "org.freedesktop.DBus.Hello"
-#define BUS_DRIVER_WELCOME_NAME "org.freedesktop.DBus.Welcome"
-#define BUS_DRIVER_LIST_SERVICES_NAME "org.freedesktop.DBus.ListServices"
-#define BUS_DRIVER_SERVICES_NAME "org.freedesktop.DBus.Services"
+static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
+                                                    DBusMessage    *hello_message,
+                                                    BusTransaction *transaction,
+                                                    DBusError      *error);
 
-#define BUS_DRIVER_SERVICE_CREATED_NAME "org.freedesktop.DBus.ServiceCreated"
-#define BUS_DRIVER_SERVICE_DELETED_NAME "org.freedesktop.DBus.ServiceDeleted"
+dbus_bool_t
+bus_driver_send_service_deleted (const char     *service_name,
+                                 BusTransaction *transaction,
+                                 DBusError      *error)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
 
-static dbus_bool_t  bus_driver_send_welcome_message (DBusConnection *connection,
-                                                    DBusMessage    *hello_message);
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  _dbus_verbose ("sending service deleted: %s\n", service_name);
 
-static void
-send_one_message (DBusConnection *connection, void *data)
-{
-  dbus_connection_send_message (connection, data, NULL, NULL);
+  message = dbus_message_new (DBUS_SERVICE_BROADCAST,
+                              DBUS_MESSAGE_SERVICE_DELETED);
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
+      !dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, service_name,
+                                 0))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  retval = bus_dispatch_broadcast_message (transaction, message, error);
+  dbus_message_unref (message);
+
+  return retval;
 }
 
-static void
-bus_driver_broadcast_message (DBusMessage *message)
+dbus_bool_t
+bus_driver_send_service_created (const char     *service_name,
+                                 BusTransaction *transaction,
+                                 DBusError      *error)
 {
-  bus_connection_foreach (send_one_message, message);
+  DBusMessage *message;
+  dbus_bool_t retval;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  message = dbus_message_new (DBUS_SERVICE_BROADCAST,
+                              DBUS_MESSAGE_SERVICE_CREATED);
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, service_name,
+                                 0))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  retval = bus_dispatch_broadcast_message (transaction, message, error);
+  dbus_message_unref (message);
+
+  return retval;
 }
 
-static dbus_bool_t
-bus_driver_send_service_created (DBusConnection *connection, const char *name)
+dbus_bool_t
+bus_driver_send_service_lost (DBusConnection *connection,
+                             const char     *service_name,
+                              BusTransaction *transaction,
+                              DBusError      *error)
 {
   DBusMessage *message;
 
-  message = dbus_message_new (NULL, BUS_DRIVER_SERVICE_CREATED_NAME);
-
-  if (!message)
-    return FALSE;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  message = dbus_message_new (bus_connection_get_name (connection),
+                              DBUS_MESSAGE_SERVICE_LOST);
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, service_name,
+                                 0))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
 
-  if (!dbus_message_append_fields (message,
-                                  DBUS_TYPE_STRING, name,
-                                  0))
+  if (!bus_transaction_send_message (transaction, connection, message))
     {
       dbus_message_unref (message);
+      BUS_SET_OOM (error);
       return FALSE;
     }
+  else
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+}
+
+dbus_bool_t
+bus_driver_send_service_acquired (DBusConnection *connection,
+                                  const char     *service_name,
+                                  BusTransaction *transaction,
+                                  DBusError      *error)
+{
+  DBusMessage *message;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  dbus_message_set_sender (message, BUS_DRIVER_SERVICE_NAME);
-  bus_driver_broadcast_message (message);
-  dbus_message_unref (message);
+  message = dbus_message_new (bus_connection_get_name (connection),
+                              DBUS_MESSAGE_SERVICE_ACQUIRED);
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
   
-  return TRUE;
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, service_name,
+                                 0))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_message (transaction, connection, message))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
 }
 
 static dbus_bool_t
-create_unique_client_name (const char *name,
-                           DBusString *str)
+create_unique_client_name (BusRegistry *registry,
+                           DBusString  *str)
 {
   /* We never want to use the same unique client name twice, because
    * we want to guarantee that if you send a message to a given unique
@@ -92,9 +220,6 @@ create_unique_client_name (const char *name,
   static int next_minor_number = 0;
   int len;
 
-  if (!_dbus_string_append (str, name))
-    return FALSE;
-  
   len = _dbus_string_get_length (str);
   
   while (TRUE)
@@ -130,7 +255,7 @@ create_unique_client_name (const char *name,
       next_minor_number += 1;
       
       /* Check if a client with the name exists */
-      if (bus_service_lookup (str, FALSE) == NULL)
+      if (bus_registry_lookup (registry, str) == NULL)
        break;
 
       /* drop the number again, try the next one. */
@@ -142,199 +267,466 @@ create_unique_client_name (const char *name,
 
 static dbus_bool_t
 bus_driver_handle_hello (DBusConnection *connection,
-                        DBusMessage    *message)
+                         BusTransaction *transaction,
+                         DBusMessage    *message,
+                         DBusError      *error)
 {
-  DBusResultCode result;
-  char *name;
   DBusString unique_name;
   BusService *service;
   dbus_bool_t retval;
-  
-  result = dbus_message_get_fields (message,
-                                   DBUS_TYPE_STRING, &name,
-                                   0);
-
-  /* FIXME: Handle this in a better way */
-  if (result != DBUS_RESULT_SUCCESS)
-    return FALSE;
+  BusRegistry *registry;
 
-  if (!_dbus_string_init (&unique_name, _DBUS_INT_MAX))
-    return FALSE;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  if (!create_unique_client_name (name, &unique_name))
+  if (!_dbus_string_init (&unique_name))
     {
-      _dbus_string_free (&unique_name);
+      BUS_SET_OOM (error);
       return FALSE;
     }
 
-  /* Create the service */
-  service = bus_service_lookup (&unique_name, TRUE);
-  if (!service)
+  retval = FALSE;
+
+  registry = bus_connection_get_registry (connection);
+  
+  if (!create_unique_client_name (registry, &unique_name))
     {
-      _dbus_string_free (&unique_name);
-      return FALSE;
+      BUS_SET_OOM (error);
+      goto out_0;
     }
 
-  /* FIXME: Error checks from this point */
+  if (!bus_connection_set_name (connection, &unique_name))
+    {
+      BUS_SET_OOM (error);
+      goto out_0;
+    }
   
-  /* Add the connection as the owner */
-  bus_service_add_owner (service, connection);
-  bus_connection_set_name (connection, &unique_name);
-
-  /* We need to assign the sender to the message here */
-  dbus_message_set_sender (message,
-                          bus_connection_get_name (connection));
+  if (!dbus_message_set_sender (message,
+                                bus_connection_get_name (connection)))
+    {
+      BUS_SET_OOM (error);
+      goto out_0;
+    }
   
-  _dbus_string_free (&unique_name);
-
-  retval = bus_driver_send_welcome_message (connection, message);
+  if (!bus_driver_send_welcome_message (connection, message, transaction, error))
+    goto out_0;
 
-  if (!retval)
-    return FALSE;
+  /* Create the service */
+  service = bus_registry_ensure (registry,
+                                 &unique_name, connection, transaction, error);
+  if (service == NULL)
+    goto out_0;
   
-  /* Broadcast a ServiceCreated message */
-  retval = bus_driver_send_service_created (connection, bus_connection_get_name (connection));
+  bus_service_set_prohibit_replacement (service, TRUE);
+
+  retval = TRUE;
   
+ out_0:
+  _dbus_string_free (&unique_name);
   return retval;
 }
 
 static dbus_bool_t
 bus_driver_send_welcome_message (DBusConnection *connection,
-                                DBusMessage    *hello_message)
+                                 DBusMessage    *hello_message,
+                                 BusTransaction *transaction,
+                                 DBusError      *error)
 {
   DBusMessage *welcome;
   const char *name;
-  dbus_bool_t retval;
-  
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
   name = bus_connection_get_name (connection);
   _dbus_assert (name != NULL);
   
-  welcome = dbus_message_new_reply (BUS_DRIVER_WELCOME_NAME,
-                                   hello_message);
+  welcome = dbus_message_new_reply (hello_message);
   if (welcome == NULL)
-    return FALSE;
-
-  /* FIXME: Return value */
-  dbus_message_set_sender (welcome, BUS_DRIVER_SERVICE_NAME);
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
   
-  if (!dbus_message_append_fields (welcome,
-                                  DBUS_TYPE_STRING, name,
-                                  NULL))
+  if (!dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS))
     {
       dbus_message_unref (welcome);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_append_args (welcome,
+                                 DBUS_TYPE_STRING, name,
+                                 NULL))
+    {
+      dbus_message_unref (welcome);
+      BUS_SET_OOM (error);
       return FALSE;
     }
 
-  retval = dbus_connection_send_message (connection, welcome, NULL, NULL);
-  dbus_message_unref (welcome);
-
-  return retval;
+  if (!bus_transaction_send_message (transaction, connection, welcome))
+    {
+      dbus_message_unref (welcome);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (welcome);
+      return TRUE;
+    }
 }
 
-static void
+static dbus_bool_t
 bus_driver_handle_list_services (DBusConnection *connection,
-                                DBusMessage    *message)
+                                 BusTransaction *transaction,
+                                 DBusMessage    *message,
+                                 DBusError      *error)
 {
   DBusMessage *reply;
-  int len, i;
+  int len;
   char **services;
+  BusRegistry *registry;
 
-  reply = dbus_message_new_reply (BUS_DRIVER_SERVICES_NAME, message);
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
+  registry = bus_connection_get_registry (connection);
+  
+  reply = dbus_message_new_reply (message);
   if (reply == NULL)
-    return;
-
-  services = bus_services_list (&len);
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
 
-  if (!services)
-    goto error;
+  if (!bus_registry_list_services (registry, &services, &len))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
   
-  if (!dbus_message_append_fields (reply,
-                                  DBUS_TYPE_STRING_ARRAY, services, len,
-                                  0))
-    goto error;
+  if (!dbus_message_append_args (reply,
+                                 DBUS_TYPE_STRING_ARRAY, services, len,
+                                 0))
+    {
+      dbus_free_string_array (services);
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
 
-  if (!dbus_connection_send_message (connection, reply, NULL, NULL))
-    goto error;
+  dbus_free_string_array (services);
   
- error:
-  dbus_message_unref (reply);
-  if (services != NULL)
+  if (!bus_transaction_send_message (transaction, connection, reply))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
     {
-      for (i = 0; i < len; i++)
-        dbus_free (services[i]);
-      dbus_free (services);
+      dbus_message_unref (reply);
+      return TRUE;
     }
 }
 
-/* This is where all the magic occurs */
-static DBusHandlerResult
-bus_driver_message_handler (DBusMessageHandler *handler,
-                           DBusConnection     *connection,
-                           DBusMessage        *message,
-                           void               *user_data)
+static dbus_bool_t
+bus_driver_handle_acquire_service (DBusConnection *connection,
+                                   BusTransaction *transaction,
+                                   DBusMessage    *message,
+                                   DBusError      *error)
 {
-  const char *service, *name;
+  DBusMessage *reply;
+  DBusString service_name;
+  BusService *service;  
+  char *name;
+  int service_reply;
+  int flags;
+  dbus_bool_t retval;
+  DBusConnection *old_owner;
+  DBusConnection *current_owner;
+  BusRegistry *registry;
 
-  service = dbus_message_get_service (message);
-  name = dbus_message_get_name (message);
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  registry = bus_connection_get_registry (connection);
+  
+  if (!dbus_message_get_args (message,
+                              error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_UINT32, &flags,
+                              0))
+    return FALSE;
+  
+  _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags);
+
+  retval = FALSE;
+  reply = NULL;
 
-  dbus_message_set_sender (message,
-                          bus_connection_get_name (connection));
+  _dbus_string_init_const (&service_name, name);
   
-  if (strcmp (service, BUS_DRIVER_SERVICE_NAME) == 0)
+  service = bus_registry_lookup (registry, &service_name);
+
+  if (service != NULL)
+    old_owner = bus_service_get_primary_owner (service);
+  else
+    old_owner = NULL;  
+  
+  reply = dbus_message_new_reply (message);
+  if (reply == NULL)
     {
-      if (strcmp (name, BUS_DRIVER_HELLO_NAME) == 0)
-       bus_driver_handle_hello (connection, message);
-      else if (strcmp (name, BUS_DRIVER_LIST_SERVICES_NAME) == 0)
-       bus_driver_handle_list_services (connection, message);
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (service == NULL)
+    {
+      service = bus_registry_ensure (registry,
+                                     &service_name, connection, transaction, error);
+      if (service == NULL)
+        goto out;
+    }
+
+  current_owner = bus_service_get_primary_owner (service);
+
+  if (old_owner == NULL)
+    {
+      _dbus_assert (current_owner == connection);
+
+      bus_service_set_prohibit_replacement (service,
+                                           (flags & DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT));      
+                       
+      service_reply = DBUS_SERVICE_REPLY_PRIMARY_OWNER;      
+    }
+  else if (old_owner == connection)
+    service_reply = DBUS_SERVICE_REPLY_ALREADY_OWNER;
+  else if (!((flags & DBUS_SERVICE_FLAG_REPLACE_EXISTING)))
+    service_reply = DBUS_SERVICE_REPLY_SERVICE_EXISTS;
+  else if (bus_service_get_prohibit_replacement (service))
+    {
+      /* Queue the connection */
+      if (!bus_service_add_owner (service, connection,
+                                  transaction, error))
+        goto out;
+      
+      service_reply = DBUS_SERVICE_REPLY_IN_QUEUE;
     }
   else
     {
-      /* FIXME: Dispatch the message :-) */
+      /* Replace the current owner */
+
+      /* We enqueue the new owner and remove the first one because
+       * that will cause ServiceAcquired and ServiceLost messages to
+       * be sent.
+       */
+      
+      /* FIXME this is broken, if the remove_owner fails
+       * we don't undo the add_owner
+       * (easiest fix is probably to move all this to
+       * services.c and have a single routine for it)
+       */
+      
+      if (!bus_service_add_owner (service, connection,
+                                  transaction, error))
+        goto out;
+      
+      if (!bus_service_remove_owner (service, old_owner,
+                                     transaction, error))
+        goto out;
+      
+      _dbus_assert (connection == bus_service_get_primary_owner (service));
+      service_reply = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
     }
 
-  return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
+  if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, 0))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
 
-dbus_bool_t
-bus_driver_add_connection (DBusConnection *connection)
+  if (!bus_transaction_send_message (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  retval = TRUE;
+  
+ out:
+  dbus_free (name);
+  if (reply)
+    dbus_message_unref (reply);
+  return retval;
+} 
+
+static dbus_bool_t
+bus_driver_handle_service_exists (DBusConnection *connection,
+                                  BusTransaction *transaction,
+                                  DBusMessage    *message,
+                                  DBusError      *error)
 {
-  DBusMessageHandler *handler;
+  DBusMessage *reply;
+  DBusString service_name;
+  BusService *service;
+  char *name;
+  dbus_bool_t retval;
+  BusRegistry *registry;
 
-  handler = dbus_message_handler_new (bus_driver_message_handler, NULL, NULL);
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  registry = bus_connection_get_registry (connection);
+  
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &name,
+                              0))
+    return FALSE;
 
-  if (!dbus_connection_add_filter (connection, handler))
+  retval = FALSE;
+  
+  _dbus_string_init_const (&service_name, name);
+  service = bus_registry_lookup (registry, &service_name);
+  reply = dbus_message_new_reply (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+  
+  if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
     {
-      dbus_message_handler_unref (handler);
+      BUS_SET_OOM (error);
+      goto out;
+    }
 
-      return FALSE;
+  if (!dbus_message_append_args (reply,
+                                 DBUS_TYPE_UINT32, service != NULL,
+                                 0))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!bus_transaction_send_message (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      goto out;
     }
 
-  /* FIXME we are leaking the DBusMessageHandler */
+  retval = TRUE;
+  
+ out:
+  if (reply)
+    dbus_message_unref (reply);
+  dbus_free (name);
+
+  return retval;
+}
+
+static dbus_bool_t
+bus_driver_handle_activate_service (DBusConnection *connection,
+                                    BusTransaction *transaction,
+                                    DBusMessage    *message,
+                                    DBusError      *error)
+{
+  dbus_uint32_t flags;
+  char *name;
+  dbus_bool_t retval;
+  BusActivation *activation;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  _dbus_verbose ("D-Bus driver on board...\n");
+  activation = bus_connection_get_activation (connection);
   
-  return TRUE;
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_UINT32, &flags,
+                              0))
+    return FALSE;
+
+  retval = FALSE;
+
+  if (!bus_activation_activate_service (activation, connection, transaction,
+                                        message, name, error))
+    goto out;
+
+  retval = TRUE;
+  
+ out:
+  dbus_free (name);
+  return retval;
 }
 
-void
-bus_driver_remove_connection (DBusConnection *connection)
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+struct
 {
-  BusService *service;
-  DBusString service_name;
   const char *name;
+  dbus_bool_t (* handler) (DBusConnection *connection,
+                           BusTransaction *transaction,
+                           DBusMessage    *message,
+                           DBusError      *error);
+} message_handlers[] = {
+  { DBUS_MESSAGE_ACQUIRE_SERVICE, bus_driver_handle_acquire_service },
+  { DBUS_MESSAGE_ACTIVATE_SERVICE, bus_driver_handle_activate_service },
+  { DBUS_MESSAGE_HELLO, bus_driver_handle_hello },
+  { DBUS_MESSAGE_SERVICE_EXISTS, bus_driver_handle_service_exists },
+  { DBUS_MESSAGE_LIST_SERVICES, bus_driver_handle_list_services }
+};
 
-  name = bus_connection_get_name (connection);
+dbus_bool_t
+bus_driver_handle_message (DBusConnection *connection,
+                           BusTransaction *transaction,
+                          DBusMessage    *message,
+                           DBusError      *error)
+{
+  const char *name, *sender;
+  int i;
 
-  if (name == NULL)
-    return;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  _dbus_string_init_const (&service_name, name);
+  _dbus_verbose ("Driver got a message: %s\n",
+                dbus_message_get_name (message));
   
-  service = bus_service_lookup (&service_name, FALSE);
+  name = dbus_message_get_name (message);
+  sender = dbus_message_get_sender (message);
+
+  if (sender == NULL && (strcmp (name, DBUS_MESSAGE_HELLO) != 0))
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Client tried to send a message other than %s without being registered",
+                      DBUS_MESSAGE_HELLO);
 
-  if (service)
-    bus_service_free (service);
+      dbus_connection_disconnect (connection);
+      return FALSE;
+    }
+
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (message_handlers))
+    {
+      if (strcmp (message_handlers[i].name, name) == 0)
+        {
+          if ((* message_handlers[i].handler) (connection, transaction, message, error))
+            return TRUE;
+          else
+            return FALSE;
+        }
+      
+      ++i;
+    }
+
+  dbus_set_error (error, DBUS_ERROR_UNKNOWN_MESSAGE,
+                  "%s does not understand message %s",
+                  DBUS_SERVICE_DBUS, name);
+  
+  return FALSE;
+}
+
+void
+bus_driver_remove_connection (DBusConnection *connection)
+{
+  /* FIXME Does nothing for now, should unregister the connection
+   * with the bus driver.
+   */
 }