- 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>
#--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
{
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,
_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?
*/
}
#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;
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;
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);
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;
}
_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:
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_ */
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)
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)
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);
}
}
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
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
{
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;
_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)
{
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.
}
}
+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
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);
#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; \
return -1;
}
-/*todo uncomment if needed
+/*
static int reply_ack(DBusMessage *message, DBusConnection* connection)
{
DBusMessage *reply;
{
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;
((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);
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;
#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)
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);
{
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,
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
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;
KDBUS_NAME_QUEUE = 1 << 1,
KDBUS_NAME_ALLOW_REPLACEMENT = 1 << 2,
+ KDBUS_NAME_STARTER = 1 << 7,
+
/* kernel → userspace */
KDBUS_NAME_IN_QUEUE = 1 << 16,
};