Merge "Optional autogen.sh flag --enable-kdbus-transport added allowing to compile...
[platform/upstream/dbus.git] / bus / services.c
index a1563ba..8a18627 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2003  Red Hat, Inc.
  * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2013  Samsung Electronics
  *
  * Licensed under the Academic Free License version 2.1
  * 
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-mempool.h>
 #include <dbus/dbus-marshal-validate.h>
+#ifdef ENABLE_KDBUS_TRANSPORT
 #include <linux/types.h>
 #include <errno.h>
 #include <stdlib.h>
-
+#endif
 
 #include "driver.h"
 #include "services.h"
 #include "policy.h"
 #include "bus.h"
 #include "selinux.h"
+#ifdef ENABLE_KDBUS_TRANSPORT
 #include "kdbus-d.h"
+#include "dbus/kdbus.h"
+#endif
 
 struct BusService
 {
@@ -60,6 +65,9 @@ struct BusOwner
 
   unsigned int allow_replacement : 1;
   unsigned int do_not_queue : 1;
+#ifdef ENABLE_KDBUS_TRANSPORT
+  unsigned int is_kdbus_starter : 1;
+#endif
 };
 
 struct BusRegistry
@@ -177,6 +185,7 @@ _bus_service_find_owner_link (BusService *service,
   return link;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
 static DBusConnection *
 _bus_service_find_owner_connection (BusService *service,
                                    const char* unique_name)
@@ -198,6 +207,7 @@ _bus_service_find_owner_connection (BusService *service,
 
   return NULL;
 }
+#endif
 
 static void
 bus_owner_set_flags (BusOwner *owner,
@@ -208,6 +218,11 @@ bus_owner_set_flags (BusOwner *owner,
 
    owner->do_not_queue =
         (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
+
+#ifdef ENABLE_KDBUS_TRANSPORT
+   owner->is_kdbus_starter =
+        (flags & KDBUS_NAME_STARTER) != FALSE;
+#endif
 }
 
 static BusOwner *
@@ -622,6 +637,7 @@ bus_registry_acquire_service (BusRegistry      *registry,
   return retval;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
 dbus_bool_t
 bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                               DBusConnection   *connection,
@@ -639,6 +655,7 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
   char* name;
   dbus_uint32_t flags;
   __u64 sender_id;
+  dbus_bool_t rm_owner_daemon = FALSE;
 
   if (!dbus_message_get_args (message, error,
                               DBUS_TYPE_STRING, &name,
@@ -695,6 +712,7 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                if (service == NULL)
                  goto out;
 
+               rm_owner_daemon = TRUE;
                if(!kdbus_register_policy(service_name, connection))
                {
                        dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
@@ -725,16 +743,18 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
        if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
        {
            DBusConnection* phantom;
+           const char* name;
+//         DBusList *link;
 
-           phantom = create_phantom_connection(connection, dbus_message_get_sender(message), error);
+           name = dbus_message_get_sender(message);
+           phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
+        if(phantom == NULL)
+            phantom = create_phantom_connection(connection, name, error);
            if(phantom == NULL)
                goto failed2;
            if (!bus_service_add_owner (service, phantom, flags, transaction, error))
-           {
-               dbus_connection_unref_phantom(phantom);
                goto failed2;
-           }
-           if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+           if((*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) && rm_owner_daemon)
            {
             /* Here we are removing DBus daemon as an owner of the service,
              * which is set by bus_registry_ensure.
@@ -744,6 +764,17 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                if(_bus_service_find_owner_link (service, connection))
                 bus_service_remove_owner (service, connection, transaction, NULL);
            }
+           /*if(bus_service_get_is_kdbus_starter(service))
+           {
+               if (!bus_service_swap_owner (service, bus_service_get_primary_owners_connection(service),
+                                              transaction, error))
+                   goto failed2;
+           }*/
+           /*if((link = _bus_service_find_owner_link (service, connection)))  //if daemon is a starter
+           {
+               _dbus_list_unlink (&service->owners, link);
+               _dbus_list_append_link (&service->owners, link);  //it must be moved at the end of the queue
+           }*/
        }
 
   activation = bus_context_get_activation (registry->context);
@@ -762,6 +793,7 @@ failed:
 
   return FALSE;
 }
+#endif
 
 dbus_bool_t
 bus_registry_release_service (BusRegistry      *registry,
@@ -814,67 +846,120 @@ bus_registry_release_service (BusRegistry      *registry,
       goto out;
     }
 
-  if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
-  {
-       __u64 sender_id;
+  service = bus_registry_lookup (registry, service_name);
 
-       sender_id = sender_name_to_id((const char*)registry, error);
-       if(dbus_error_is_set(error))
-               return FALSE;
+  if (service == NULL)
+    {
+      *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
+    }
+  else if (!bus_service_has_owner (service, connection))
+    {
+      *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
+    }
+  else
+    {
+      if (!bus_service_remove_owner (service, connection,
+                                     transaction, error))
+        goto out;
 
-       *result = kdbus_release_name(connection, service_name, sender_id);
+      _dbus_assert (!bus_service_has_owner (service, connection));
+      *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
+    }
 
-       if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
-       {
-           const char* name;
+  retval = TRUE;
 
-           name = (const char*)registry;  //get name passed in registry pointer
-           registry = bus_connection_get_registry (connection);  //than take original registry address
+ out:
+  return retval;
+}
 
-           service = bus_registry_lookup (registry, service_name);
-           if(service)
-           {
-               DBusConnection* phantom;
-
-               phantom = _bus_service_find_owner_connection(service, name);
-               if(phantom)
-               {
-                   bus_service_remove_owner (service, phantom, transaction, NULL);
-                dbus_connection_unref_phantom(phantom);
-               }
-               else
-                   _dbus_verbose ("Didn't find phantom connection for released name!\n");
-           }
-       }
-  }
-  else
-  {
-         service = bus_registry_lookup (registry, service_name);
+#ifdef ENABLE_KDBUS_TRANSPORT
+dbus_bool_t
+bus_registry_release_service_kdbus (const char* sender_name,
+                              DBusConnection   *connection,
+                              const DBusString *service_name,
+                              dbus_uint32_t    *result,
+                              BusTransaction   *transaction,
+                              DBusError        *error)
+{
+  dbus_bool_t retval = FALSE;
+  __u64 sender_id;
 
-         if (service == NULL)
-               {
-                 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
-               }
-         else if (!bus_service_has_owner (service, connection))
-               {
-                 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
-               }
-         else
-               {
-                 if (!bus_service_remove_owner (service, connection,
-                                                                                transaction, error))
-                       goto out;
+  if (!_dbus_validate_bus_name (service_name, 0,
+                                _dbus_string_get_length (service_name)))
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Given bus name \"%s\" is not valid",
+                      _dbus_string_get_const_data (service_name));
 
-                 _dbus_assert (!bus_service_has_owner (service, connection));
-                 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
-               }
-  }
+      _dbus_verbose ("Attempt to release invalid service name\n");
+
+      goto out;
+    }
+
+  if (_dbus_string_get_byte (service_name, 0) == ':')
+    {
+      /* Not allowed; the base service name cannot be created or released */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Cannot release a service starting with ':' such as \"%s\"",
+                      _dbus_string_get_const_data (service_name));
+
+      _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
+                     _dbus_string_get_const_data (service_name));
+
+      goto out;
+    }
+
+   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
+    {
+      /* Not allowed; the base service name cannot be created or released */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Cannot release the %s service because it is owned by the bus",
+                     DBUS_SERVICE_DBUS);
+
+      _dbus_verbose ("Attempt to release service name \"%s\"",
+                     DBUS_SERVICE_DBUS);
+
+      goto out;
+    }
+
+    sender_id = sender_name_to_id(sender_name, error);
+    if(dbus_error_is_set(error))
+        return FALSE;
+
+    *result = kdbus_release_name(connection, service_name, sender_id);
+
+    if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
+    {
+        BusRegistry* registry;
+        BusService *service;
+
+        registry = bus_connection_get_registry (connection);
+        service = bus_registry_lookup (registry, service_name);
+        if(service)
+        {
+            DBusConnection* phantom;
+
+            phantom = _bus_service_find_owner_connection(service, sender_name);
+            if(phantom)
+            {
+                bus_service_remove_owner (service, phantom, transaction, NULL);
+                /* todo we could remove phantom if he doesn't own any name
+                 * to do this we should write function in connection.c to check if
+                 * _dbus_list_get_last (&d->services_owned) returns not NULL
+                 *  or we can leave phantom - he will be removed when he disconnects from the bus
+                 */
+            }
+            else
+                _dbus_verbose ("Didn't find phantom connection for released name!\n");
+        }
+   }
 
   retval = TRUE;
 
  out:
   return retval;
 }
+#endif
 
 dbus_bool_t
 bus_registry_set_service_context_table (BusRegistry   *registry,
@@ -1459,6 +1544,22 @@ bus_service_get_allow_replacement (BusService *service)
   return owner->allow_replacement;
 }
 
+#ifdef ENABLE_KDBUS_TRANSPORT
+dbus_bool_t
+bus_service_get_is_kdbus_starter (BusService *service)
+{
+  BusOwner *owner;
+  DBusList *link;
+
+  _dbus_assert (service->owners != NULL);
+
+  link = _dbus_list_get_first_link (&service->owners);
+  owner = (BusOwner *) link->data;
+
+  return owner->is_kdbus_starter;
+}
+#endif
+
 dbus_bool_t
 bus_service_has_owner (BusService     *service,
                       DBusConnection *connection)
@@ -1493,8 +1594,11 @@ bus_service_list_queued_owners (BusService *service,
       owner = (BusOwner *) link->data;
       uname = bus_connection_get_name (owner->conn);
 
-      if (!_dbus_list_append (return_list, (char *)uname))
-        goto oom;
+#ifdef ENABLE_KDBUS_TRANSPORT
+      if(!owner->is_kdbus_starter)
+#endif
+          if (!_dbus_list_append (return_list, (char *)uname))
+              goto oom;
 
       link = _dbus_list_get_next_link (&service->owners, link);
     }