[daemon-dev] List of queued owners read from kdbus
authorRadoslaw Pajak <r.pajak@samsung.com>
Thu, 21 Nov 2013 12:52:29 +0000 (13:52 +0100)
committerRadoslaw Pajak <r.pajak@samsung.com>
Thu, 21 Nov 2013 12:52:29 +0000 (13:52 +0100)
From now, when method org.freedesktop.DBus.ListQueuedOwners is called,
daemon asks kdbus for the list, instead of preparing it from it's own
data.
Needs kdbus with commit
816abfc [feature] added ioctl KDBUS_CMD_NAME_LIST_QUEUED
from 21.11.2013

Change-Id: If6a6f4bbe8dc910160a661191ec1b067a796da34
Signed-off-by: Radoslaw Pajak <r.pajak@samsung.com>
bus/driver.c
bus/kdbus-d.c
bus/kdbus-d.h
dbus/kdbus.h

index 57265e5..9633bc5 100644 (file)
@@ -46,6 +46,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <limits.h>
+#include <stdlib.h>
 #endif
 
 static DBusConnection *
@@ -473,7 +474,6 @@ bus_driver_handle_list_services (DBusConnection *connection,
   else
 #endif
   {
-
       if (!bus_registry_list_services (registry, &services, &len))
         {
           dbus_message_unref (reply);
@@ -1366,7 +1366,11 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
       if (! _dbus_list_append (&base_names, dbus_service_name))
         goto oom;
     }
+#ifdef ENABLE_KDBUS_TRANSPORT
+  else if (!bus_context_is_kdbus(bus_transaction_get_context (transaction)) && (service == NULL))
+#else
   else if (service == NULL)
+#endif
     {
       dbus_set_error (error,
                       DBUS_ERROR_NAME_HAS_NO_OWNER,
@@ -1375,10 +1379,20 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
     }
   else
     {
-      if (!bus_service_list_queued_owners (service,
-                                           &base_names,
-                                           error))
-        goto failed;
+#ifdef ENABLE_KDBUS_TRANSPORT
+      if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
+        {
+          if(!kdbus_list_queued (connection,  &base_names, text ,error))
+            goto failed;
+        }
+      else
+#endif
+        {
+          if (!bus_service_list_queued_owners (service,
+              &base_names,
+              error))
+            goto failed;
+        }
     }
 
   _dbus_assert (base_names != NULL);
@@ -1419,6 +1433,21 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
 
   dbus_message_unref (reply);
 
+  if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
+    {
+      link = _dbus_list_get_first_link (&base_names);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&base_names, link);
+
+          if(link->data != NULL)
+            free(link->data);
+
+          _dbus_list_free_link (link);
+          link = next;
+        }
+    }
+
   return TRUE;
 
  oom:
@@ -1428,10 +1457,8 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
   _DBUS_ASSERT_ERROR_IS_SET (error);
   if (reply)
     dbus_message_unref (reply);
-
   if (base_names)
     _dbus_list_clear (&base_names);
-
   return FALSE;
 }
 
index 70a1a86..be9fccc 100644 (file)
@@ -593,6 +593,110 @@ out:
 }
 
 /*
+ * Asks kdbus for list of connections being in the queue to own
+ * given well-known name. The list includes the owner of the name on the
+ * first position.
+ */
+dbus_bool_t kdbus_list_queued (DBusConnection *connection, DBusList  **return_list,
+                               const char *name, DBusError  *error)
+{
+  int fd;
+  struct kdbus_cmd_names* pCmd;
+  __u64 cmd_size;
+  dbus_bool_t ret_val = FALSE;
+  int name_length;
+
+  _dbus_assert (*return_list == NULL);
+
+  name_length = strlen(name) + 1;
+  cmd_size = sizeof(struct kdbus_cmd_names) + sizeof(struct kdbus_cmd_name) + name_length;
+  pCmd = malloc(cmd_size);
+  if(pCmd == NULL)
+    goto out;
+  pCmd->size = cmd_size;
+  pCmd->names[0].id = 0;
+  pCmd->names[0].size =  sizeof(struct kdbus_cmd_name) + name_length;
+  memcpy(pCmd->names[0].name, name, name_length);
+  _dbus_verbose ("Asking for queued owners of %s\n", pCmd->names[0].name);
+
+  _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
+
+  again:
+  cmd_size = 0;
+  if(ioctl(fd, KDBUS_CMD_NAME_LIST_QUEUED, pCmd))
+    {
+      if(errno == EINTR)
+        goto again;
+      if(errno == ENOBUFS)      //buffer to small to put all names into it
+        cmd_size = pCmd->size;    //here kernel tells how much memory it needs
+      else if(errno == ENOENT)
+        {
+          dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
+                      "Could not get owners of name '%s': no such name", name);
+          free(pCmd);
+          return FALSE;
+        }
+      else
+        {
+          _dbus_verbose("kdbus error asking for queued owners list: err %d (%m)\n",errno);
+          goto out;
+        }
+    }
+  if(cmd_size)  //kernel needs more memory
+    {
+      pCmd = realloc(pCmd, cmd_size);  //prepare memory
+      if(pCmd == NULL)
+        return FALSE;
+      goto again;           //and try again
+    }
+  else
+    {
+      struct kdbus_cmd_name* pCmd_name;
+
+      for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
+        {
+          char *uname = NULL;
+
+          _dbus_verbose ("Got queued owner id: %llu\n", (unsigned long long)pCmd_name->id);
+          uname = malloc(snprintf(uname, 0, ":1.%llu0", (unsigned long long)pCmd_name->id));
+          if(uname == NULL)
+            goto out;
+          sprintf(uname, ":1.%llu", (unsigned long long int)pCmd_name->id);
+          if (!_dbus_list_append (return_list, uname))
+            goto out;
+        }
+    }
+
+  ret_val = TRUE;
+
+  out:
+  if(pCmd)
+    free(pCmd);
+  if(ret_val == FALSE)
+    {
+      DBusList *link;
+
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+          "Failed to list queued owners of \"%s\": %s",
+          name, _dbus_strerror (errno));
+
+      link = _dbus_list_get_first_link (return_list);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (return_list, link);
+
+          if(link->data != NULL)
+            free(link->data);
+
+          _dbus_list_free_link (link);
+          link = next;
+        }
+    }
+
+  return ret_val;
+}
+
+/*
  *  Register match rule in kdbus on behalf of sender of the message
  */
 dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error)
index ce436da..0423221 100644 (file)
@@ -42,6 +42,7 @@ dbus_bool_t kdbus_register_policy (const DBusString *service_name, DBusConnectio
 dbus_uint32_t kdbus_request_name(DBusConnection* connection, const DBusString *service_name, dbus_uint32_t flags, __u64 sender_id);
 dbus_uint32_t kdbus_release_name(DBusConnection* connection, const DBusString *service_name, __u64 sender_id);
 dbus_bool_t kdbus_list_services (DBusConnection* connection, char ***listp, int *array_len);
+dbus_bool_t kdbus_list_queued (DBusConnection *connection, DBusList **return_list, const char *name, DBusError *error);
 dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error);
 dbus_bool_t kdbus_remove_match (DBusConnection* connection, DBusMessage* message, DBusError* error);
 
index 7eb9527..c6a58ef 100644 (file)
@@ -432,6 +432,7 @@ enum {
        KDBUS_CMD_NAME_RELEASE =        _IOW(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
        KDBUS_CMD_NAME_LIST =           _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_names),
        KDBUS_CMD_NAME_QUERY =          _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
+       KDBUS_CMD_NAME_LIST_QUEUED = _IOWR(KDBUS_IOC_MAGIC, 0x54, struct kdbus_cmd_names),
 
        KDBUS_CMD_MATCH_ADD =           _IOW(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
        KDBUS_CMD_MATCH_REMOVE =        _IOW(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),