[daemon-dev][daemon-fix] starting services by direct message (autostart) and some...
authorRadoslaw Pajak <r.pajak@samsung.com>
Wed, 2 Oct 2013 12:38:17 +0000 (14:38 +0200)
committerRadoslaw Pajak <r.pajak@samsung.com>
Wed, 2 Oct 2013 12:52:49 +0000 (14:52 +0200)
- added auto starting services (by directly addressed message) - daemon starts the service and then pass a pending message to it
this needs appropiriate kdbus changes - KDBUS_NAME_STARTER must be handled by kdbus (since 02.10.2013)
- fixes for name aquiring and releasing

Change-Id: Ied7746233132a9ab3bd3377fb563c85558486650
Signed-off-by: Radoslaw Pajak <r.pajak@samsung.com>
autogen.sh
bus/activation.c
bus/driver.c
bus/kdbus-d.c
bus/kdbus-d.h
bus/services.c
dbus/dbus-connection.c
dbus/dbus-connection.h
dbus/dbus-transport-kdbus.c
dbus/kdbus-common.c
dbus/kdbus.h

index a1e97f4..2338244 100755 (executable)
@@ -102,7 +102,7 @@ fi
 
 #--enable-developer --enable-verbose-mode 
 if $run_configure; then
-    $srcdir/configure --enable-verbose-mode --config-cache "$@" || exit $?
+    $srcdir/configure --enable-developer --config-cache "$@" || exit $?
     echo 
     echo "Now type 'make' to compile $PROJECT."
 else
index 124f91b..cd77faa 100644 (file)
@@ -1187,7 +1187,14 @@ bus_activation_send_pending_auto_activation_messages (BusActivation  *activation
         {
           DBusConnection *addressed_recipient;
 
-          addressed_recipient = bus_service_get_primary_owners_connection (service);
+          /* kdbus change - we can not send anything using phantom connections
+           * (DBusConnection structures for services other than daemon)
+           * so we have to use daemon connection
+           */
+          if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
+              addressed_recipient = entry->connection;
+          else
+              addressed_recipient = bus_service_get_primary_owners_connection (service);
 
           /* Resume dispatching where we left off in bus_dispatch() */
           if (!bus_dispatch_matches (transaction,
index 7861a52..a664517 100644 (file)
@@ -731,12 +731,11 @@ bus_driver_handle_release_service (DBusConnection *connection,
 
   _dbus_string_init_const (&service_name, name);
 
-  if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))  //todo kdbus incl
+  if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
   {
-         registry = (BusRegistry*) message;
-         /* looks like hack? Yes.
-          * But how to pass message to bus_registry_release_service in other way?
-          * In kdbus mode we don't need registry, though.
+         registry = (BusRegistry*) dbus_message_get_sender(message);
+         /* todo looks like hack? Yes.
+          * But how to pass sender of message to bus_registry_release_service in other way?
           */
   }
 
index e3202e5..fea4db4 100644 (file)
@@ -26,9 +26,6 @@
 #include <unistd.h>
 #include <errno.h>
 
-//todo there should be no include below - needed functions should be moved to kdbus-common
-#include <dbus/dbus-transport-kdbus.h>
-
 __u64 sender_name_to_id(const char* name, DBusError* error)
 {
        __u64 sender_id = 0;
@@ -114,7 +111,7 @@ DBusConnection* daemon_as_client(DBusBusType type, char* address, DBusError *err
        if(kdbus_request_name(connection, &daemon_name, 0, 0) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
                goto failed;
 
-       if(!add_match_kdbus (dbus_connection_get_transport(connection), 1, "type='signal', member='NameLost'"))  //todo handle tis in dispatch
+       if(!add_match_kdbus (dbus_connection_get_transport(connection), 1, "type='signal', member='NameLost'"))  //todo handle this in dispatch
        {
              dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:1, %s", _dbus_strerror_from_errno ());
              return FALSE;
@@ -285,11 +282,10 @@ dbus_bool_t kdbus_get_connection_unix_selinux_security_context(DBusConnection* c
        return ret;
 }
 
-DBusConnection* create_phantom_connection(DBusConnection* connection, const char* unique_name)
+DBusConnection* create_phantom_connection(DBusConnection* connection, const char* unique_name, DBusError* error)
 {
     DBusConnection *phantom_connection;
     DBusString name;
-    DBusError error;
 
     _dbus_string_init_const(&name, unique_name);
 
@@ -298,20 +294,21 @@ DBusConnection* create_phantom_connection(DBusConnection* connection, const char
         return FALSE;
     if(!bus_connections_setup_connection(bus_connection_get_connections(connection), phantom_connection))
     {
-        /*todo FIXME something should be done to clean up the phantom connection
-         * but we can't use standard disconnect, unref or last_unref because the transport is taken from connection
-         * so we probably should write own function on the basis of _dbus_connection_last_unref
-         */
+        dbus_connection_unref_phantom(phantom_connection);
         phantom_connection = NULL;
+        dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", unique_name);
+        goto out;
     }
-    if(!bus_connection_complete(phantom_connection, &name, &error))
+    if(!bus_connection_complete(phantom_connection, &name, error))
     {
-        /* todo FIXME exactly the same issue as above */
+        dbus_connection_unref_phantom(phantom_connection);
         phantom_connection = NULL;
+        goto out;
     }
 
     _dbus_verbose ("Created phantom connection for %s\n", bus_connection_get_name(phantom_connection));
 
+out:
     return phantom_connection;
 }
 
@@ -327,11 +324,14 @@ dbus_bool_t register_kdbus_starters(DBusConnection* connection)
 
     _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
 
-   /* for(i=0; i<len; i++)
+    for(i=0; i<len; i++)
     {
-        if (request_kdbus_name(fd, services[i], DBUS_NAME_FLAG_ALLOW_REPLACEMENT, 1) < 0)
+        if(!register_kdbus_policy(services[i], fd))
             goto out;
-    }*/
+
+        if (request_kdbus_name(fd, services[i], (DBUS_NAME_FLAG_ALLOW_REPLACEMENT | KDBUS_NAME_STARTER) , 0) < 0)
+            goto out;
+    }
     retval = TRUE;
 
 out:
index c9b8fcd..32d7ad8 100644 (file)
@@ -32,6 +32,6 @@ dbus_bool_t kdbus_get_connection_unix_user(DBusConnection* connection, DBusMessa
 dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, DBusMessage* message, unsigned long* pid, DBusError* error);
 dbus_bool_t kdbus_get_connection_unix_selinux_security_context(DBusConnection* connection, DBusMessage* message, DBusMessage* reply, DBusError* error);
 
-DBusConnection* create_phantom_connection(DBusConnection* connection, const char* unique_name);
+DBusConnection* create_phantom_connection(DBusConnection* connection, const char* unique_name, DBusError* error);
 dbus_bool_t register_kdbus_starters(DBusConnection* connection);
 #endif /* KDBUS_H_ */
index de99fea..a1563ba 100644 (file)
@@ -177,6 +177,28 @@ _bus_service_find_owner_link (BusService *service,
   return link;
 }
 
+static DBusConnection *
+_bus_service_find_owner_connection (BusService *service,
+                                   const char* unique_name)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (&service->owners);
+
+  while (link != NULL)
+    {
+      BusOwner *bus_owner;
+
+      bus_owner = (BusOwner *) link->data;
+      if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name))
+          return bus_owner->conn;
+
+      link = _dbus_list_get_next_link (&service->owners, link);
+    }
+
+  return NULL;
+}
+
 static void
 bus_owner_set_flags (BusOwner *owner,
                      dbus_uint32_t flags)
@@ -678,13 +700,13 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                        dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                                                  "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
                                                  _dbus_string_get_const_data (service_name));
-                       goto out;
+                       goto failed;
                }
        }
 
        sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
        if(dbus_error_is_set(error))
-               return FALSE;
+               goto failed;
 
        *result = kdbus_request_name(connection, service_name, flags, sender_id);
        if(*result == -EPERM)
@@ -692,28 +714,35 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                                          "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
                                          _dbus_string_get_const_data (service_name));
-               goto out;
+               goto failed;
        }
        else if(*result < 0)
        {
                dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
-               goto out;
+               goto failed;
        }
 
        if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
        {
            DBusConnection* phantom;
 
-           phantom = create_phantom_connection(connection, dbus_message_get_sender(message));
+           phantom = create_phantom_connection(connection, dbus_message_get_sender(message), error);
            if(phantom == NULL)
-               goto out;
+               goto failed2;
            if (!bus_service_add_owner (service, phantom, flags, transaction, error))
-               goto out;  /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
+           {
+               dbus_connection_unref_phantom(phantom);
+               goto failed2;
+           }
            if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
            {
+            /* Here we are removing DBus daemon as an owner of the service,
+             * which is set by bus_registry_ensure.
+             * If bus_service_remove_owner fail, we ignore it, because it has
+             * almost none impact on the usage
+             */
                if(_bus_service_find_owner_link (service, connection))
-                if (!bus_service_remove_owner (service, connection, transaction, error))
-                    goto out;  /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
+                bus_service_remove_owner (service, connection, transaction, NULL);
            }
        }
 
@@ -722,9 +751,16 @@ bus_registry_acquire_kdbus_service (BusRegistry      *registry,
                                                                 service,
                                                                 transaction,
                                                                 error);
-  
  out:
-  return retval;
+     return retval;
+  
+failed2:
+    kdbus_release_name(connection, service_name, sender_id);
+failed:
+    if(_bus_service_find_owner_link (service, connection))
+        bus_service_remove_owner (service, connection, transaction, NULL);
+
+  return FALSE;
 }
 
 dbus_bool_t
@@ -778,15 +814,38 @@ bus_registry_release_service (BusRegistry      *registry,
       goto out;
     }
 
-  if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))  //todo kdbus incl
+  if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
   {
        __u64 sender_id;
 
-       sender_id = sender_name_to_id(dbus_message_get_sender((DBusMessage*)registry), error);
+       sender_id = sender_name_to_id((const char*)registry, 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)
+       {
+           const char* name;
+
+           name = (const char*)registry;  //get name passed in registry pointer
+           registry = bus_connection_get_registry (connection);  //than take original registry address
+
+           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
   {
index 21d0db9..4923812 100644 (file)
@@ -2702,12 +2702,8 @@ free_outgoing_message (void *element,
   dbus_message_unref (message);
 }
 
-/* This is run without the mutex held, but after the last reference
- * to the connection has been dropped we should have no thread-related
- * problems
- */
 static void
-_dbus_connection_last_unref (DBusConnection *connection)
+_dbus_connection_last_unref_internal (DBusConnection *connection, dbus_bool_t unref_transport)
 {
   DBusList *link;
 
@@ -2762,17 +2758,18 @@ _dbus_connection_last_unref (DBusConnection *connection)
   
   _dbus_list_foreach (&connection->outgoing_messages,
                       free_outgoing_message,
-                     connection);
+              connection);
   _dbus_list_clear (&connection->outgoing_messages);
   
   _dbus_list_foreach (&connection->incoming_messages,
-                     (DBusForeachFunction) dbus_message_unref,
-                     NULL);
+              (DBusForeachFunction) dbus_message_unref,
+              NULL);
   _dbus_list_clear (&connection->incoming_messages);
 
   _dbus_counter_unref (connection->outgoing_counter);
 
-  _dbus_transport_unref (connection->transport);
+  if(unref_transport)
+      _dbus_transport_unref (connection->transport);
 
   if (connection->disconnect_message_link)
     {
@@ -2794,6 +2791,16 @@ _dbus_connection_last_unref (DBusConnection *connection)
   dbus_free (connection);
 }
 
+/* This is run without the mutex held, but after the last reference
+ * to the connection has been dropped we should have no thread-related
+ * problems
+ */
+static void
+_dbus_connection_last_unref (DBusConnection *connection)
+{
+    _dbus_connection_last_unref_internal(connection, TRUE);
+}
+
 /**
  * Decrements the reference count of a DBusConnection, and finalizes
  * it if the count reaches zero.
@@ -2842,6 +2849,22 @@ dbus_connection_unref (DBusConnection *connection)
     }
 }
 
+void
+dbus_connection_unref_phantom (DBusConnection *connection)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
+
+  old_refcount = _dbus_atomic_dec (&connection->refcount);
+
+  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1, "unref");
+
+  if (old_refcount == 1)
+      _dbus_connection_last_unref_internal(connection, FALSE);
+}
+
 /*
  * Note that the transport can disconnect itself (other end drops us)
  * and in that case this function never runs. So this function must
index d223954..a3afb93 100644 (file)
@@ -185,6 +185,8 @@ DBusConnection*    dbus_connection_ref                          (DBusConnection
 DBUS_EXPORT
 void               dbus_connection_unref                        (DBusConnection             *connection);
 DBUS_EXPORT
+void               dbus_connection_unref_phantom               (DBusConnection             *connection);
+DBUS_EXPORT
 void               dbus_connection_close                        (DBusConnection             *connection);
 DBUS_EXPORT
 dbus_bool_t        dbus_connection_get_is_connected             (DBusConnection             *connection);
index a7b4477..6a33241 100644 (file)
@@ -33,8 +33,6 @@
 #include <sys/stat.h>
 #include <openssl/md5.h>
 
-//todo documentation need to be corrected
-
 #define KDBUS_PART_FOREACH(part, head, first)                          \
        for (part = (head)->first;                                      \
             (uint8_t *)(part) < (uint8_t *)(head) + (head)->size;      \
@@ -172,7 +170,7 @@ static int reply_1_data(DBusMessage *message, int data_type, void* pData, DBusCo
     return -1;
 }
 
-/*todo uncomment if needed
+/*
 static int reply_ack(DBusMessage *message, DBusConnection* connection)
 {
        DBusMessage *reply;
@@ -410,18 +408,21 @@ static int kdbus_write_msg(DBusTransportSocket *transport, DBusMessage *message,
        {
                if(errno == EINTR)
                        goto again;
-               if((errno == ESRCH) || (errno == ENXIO) || (errno = EADDRNOTAVAIL))  //when recipient is not available on the bus
+               else if(errno == ENXIO) //no such id on the bus
+               {
+            if(!reply_with_error(DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist", dbus_message_get_destination(message), message, transport->base.connection))
+                goto out;
+               }
+        else if((errno == ESRCH) || (errno = EADDRNOTAVAIL))  //when well known name is not available on the bus
                {
                        if(autostart)
                        {
-                               //todo start service here, otherwise
                                if(!reply_with_error(DBUS_ERROR_SERVICE_UNKNOWN, "The name %s was not provided by any .service files", dbus_message_get_destination(message), message, transport->base.connection))
                                        goto out;
                        }
                        else
-                               if(!reply_with_error(DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist", dbus_message_get_destination(message), message, transport->base.connection))
-                                       goto out;
-
+                   if(!reply_with_error(DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist", dbus_message_get_destination(message), message, transport->base.connection))
+                       goto out;
                }
                _dbus_verbose("kdbus error sending message: err %d (%m)\n", errno);
                ret_size = -1;
@@ -834,7 +835,7 @@ static int emulateOrgFreedesktopDBus(DBusTransport *transport, DBusMessage *mess
                ((DBusTransportSocket*)transport)->sender = sender;
 
                if(!reply_1_data(message, DBUS_TYPE_STRING, &name, transport->connection))
-                       return 0;  //todo why we cannot free name after sending reply?
+                       return 0;  //todo why we cannot free name after sending reply, shouldn't we?
                else
                        free(sender);
 
@@ -1066,7 +1067,7 @@ out:
                return ret_value;
        }
 #endif
-/*     else if(!strcmp(dbus_message_get_member(message), "GetAdtAuditSessionData"))  //todo to be implemented
+/*     else if(!strcmp(dbus_message_get_member(message), "GetAdtAuditSessionData"))  //todo to be implemented if needed and possible
        {
                char* name = NULL;
 
@@ -1102,7 +1103,6 @@ out:
 #endif
        else
                return 1;  //send to daemon
-//             return reply_with_error(DBUS_ERROR_UNKNOWN_METHOD, NULL, (char*)dbus_message_get_member(message), message, transport->connection);
 
 #ifdef DBUS_SERVICES_IN_LIB
        if(info.sec_label)
@@ -2106,9 +2106,12 @@ do_writing (DBusTransport *transport)
 
                message = _dbus_connection_get_message_to_send (transport->connection);
                _dbus_assert (message != NULL);
-               dbus_message_unlock(message);
-           dbus_message_set_sender(message, socket_transport->sender);
-               dbus_message_lock (message);
+               if(dbus_message_get_sender(message) == NULL)  //needed for daemon
+               {
+            dbus_message_unlock(message);
+            dbus_message_set_sender(message, socket_transport->sender);
+            dbus_message_lock (message);
+               }
                _dbus_message_get_network_data (message, &header, &body);
                total_bytes_to_write = _dbus_string_get_length(header) + _dbus_string_get_length(body);
                pDestination = dbus_message_get_destination(message);
@@ -2473,7 +2476,7 @@ kdbus_connection_set (DBusTransport *transport)
 {
   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
 
-  dbus_connection_set_is_authenticated(transport->connection); //todo remove when authentication will work
+  dbus_connection_set_is_authenticated(transport->connection); //now we don't have authentication in kdbus
 
   _dbus_watch_set_handler (socket_transport->write_watch,
                            _dbus_connection_handle_watch,
@@ -2501,7 +2504,7 @@ kdbus_connection_set (DBusTransport *transport)
   return TRUE;
 }
 
-/**
+/**  original dbus copy-pasted
  * @todo We need to have a way to wake up the select sleep if
  * a new iteration request comes in with a flag (read/write) that
  * we're not currently serving. Otherwise a call that just reads
index 0c96749..fe04a2e 100644 (file)
@@ -224,6 +224,8 @@ int request_kdbus_name(int fd, const char *name, const __u64 flags, __u64 id)
                flags_kdbus |= KDBUS_NAME_QUEUE;
        if(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
                flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
+       if(flags & KDBUS_NAME_STARTER)
+           flags_kdbus |= KDBUS_NAME_STARTER;
 
        cmd_name->flags = flags_kdbus;
        cmd_name->id = id;
index 368cec3..4e4c2cb 100644 (file)
@@ -343,6 +343,8 @@ enum {
        KDBUS_NAME_QUEUE                        = 1 <<  1,
        KDBUS_NAME_ALLOW_REPLACEMENT            = 1 <<  2,
 
+       KDBUS_NAME_STARTER        = 1 <<  7,
+
        /* kernel → userspace */
        KDBUS_NAME_IN_QUEUE                     = 1 << 16,
 };