dbus/bus activation.c, 1.41, 1.42 activation.h, 1.13,
1.14 dispatch.c, 1.74, 1.75 driver.c, 1.76, 1.77
John Palmieri
johnp at kemper.freedesktop.org
Thu Jul 13 18:18:02 PDT 2006
Update of /cvs/dbus/dbus/bus
In directory kemper:/tmp/cvs-serv19443/bus
Modified Files:
activation.c activation.h dispatch.c driver.c
Log Message:
* bus/activation.[ch] (bus_activation_list_services): new function to
get the list of services that can be activated
* bus/dispatch.c: test coverage for the new bus method
ListActivatableNames
* bus/driver.c: new bus method ListActivatableNames to get the list of
services that can be activated
* doc/dbus-specification.xml: ListActivatableNames method documentation
Index: activation.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- activation.c 22 Nov 2005 20:37:00 -0000 1.41
+++ activation.c 14 Jul 2006 01:17:59 -0000 1.42
@@ -1565,6 +1565,51 @@
return TRUE;
}
+dbus_bool_t
+bus_activation_list_services (BusActivation *activation,
+ char ***listp,
+ int *array_len)
+{
+ int i, j, len;
+ char **retval;
+ DBusHashIter iter;
+
+ len = _dbus_hash_table_get_n_entries (activation->entries);
+ retval = dbus_new (char *, len + 1);
+
+ if (retval == NULL)
+ return FALSE;
+
+ _dbus_hash_iter_init (activation->entries, &iter);
+ i = 0;
+ while (_dbus_hash_iter_next (&iter))
+ {
+ BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
+
+ retval[i] = _dbus_strdup (entry->name);
+ if (retval[i] == NULL)
+ goto error;
+
+ i++;
+ }
+
+ retval[i] = NULL;
+
+ if (array_len)
+ *array_len = len;
+
+ *listp = retval;
+ return TRUE;
+
+ error:
+ for (j = 0; j < i; j++)
+ dbus_free (retval[i]);
+ dbus_free (retval);
+
+ return FALSE;
+}
+
+
#ifdef DBUS_BUILD_TESTS
#include <stdio.h>
Index: activation.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- activation.h 10 Aug 2004 03:06:59 -0000 1.13
+++ activation.h 14 Jul 2006 01:17:59 -0000 1.14
@@ -45,6 +45,9 @@
const char *service_name,
BusTransaction *transaction,
DBusError *error);
+dbus_bool_t bus_activation_list_services (BusActivation *registry,
+ char ***listp,
+ int *array_len);
dbus_bool_t bus_activation_send_pending_auto_activation_messages (BusActivation *activation,
BusService *service,
Index: dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- dispatch.c 22 Nov 2005 20:37:00 -0000 1.74
+++ dispatch.c 14 Jul 2006 01:17:59 -0000 1.75
@@ -2590,9 +2590,9 @@
goto out;
}
- if (!check_send_exit_to_service (context, connection,
+ if (!check_send_exit_to_service (context, connection,
EXISTENT_SERVICE_NAME, base_service))
- goto out;
+ goto out;
break;
}
@@ -3512,6 +3512,348 @@
_dbus_assert_not_reached ("test failed");
}
+static dbus_bool_t
+check_get_services (BusContext *context,
+ DBusConnection *connection,
+ const char *method,
+ char ***services,
+ int *len)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ DBusError error;
+ char **srvs;
+ int l;
+
+ retval = FALSE;
+ dbus_error_init (&error);
+ message = NULL;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ method);
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ /* send our message */
+ bus_test_run_clients_loop (SEND_PENDING (connection));
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ dbus_connection_ref (connection); /* because we may get disconnected */
+ block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames");
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+ }
+
+ dbus_connection_unref (connection);
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ method, serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ ; /* good, expected */
+ }
+ else
+ {
+ warn_unexpected (connection, message,
+ "method_return for ListActivatableNames/ListNames");
+
+ goto out;
+ }
+
+ retry_get_property:
+
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING,
+ &srvs, &l,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ _dbus_verbose ("no memory to list services by %s\n", method);
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto retry_get_property;
+ }
+ else
+ {
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method);
+ goto out;
+ }
+ } else {
+ *services = srvs;
+ *len = l;
+ }
+ }
+
+ if (!check_no_leftovers (context))
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ dbus_error_free (&error);
+
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_list_services (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ DBusMessage *base_service_message;
+ const char *base_service;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ const char *existent = EXISTENT_SERVICE_NAME;
+ dbus_uint32_t flags;
+ char **services;
+ int len;
+
+ _dbus_verbose ("check_list_services for %p\n", connection);
+
+ if (!check_get_services (context, connection, "ListActivatableNames", &services, &len))
+ {
+ return TRUE;
+ }
+
+ if (!_dbus_string_array_contains ((const char **)services, existent))
+ {
+ _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent);
+ return FALSE;
+ }
+
+ dbus_free_string_array (services);
+
+ base_service_message = NULL;
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "StartServiceByName");
+
+ if (message == NULL)
+ return TRUE;
+
+ dbus_message_set_auto_start (message, FALSE);
+
+ flags = 0;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &existent,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* now wait for the message bus to hear back from the activated
+ * service.
+ */
+ block_connection_until_message_from_bus (context, connection, "activated service to connect");
+
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__);
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+ "StartServiceByName", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+ _dbus_verbose (" (after sending %s)\n", "StartServiceByName");
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_EXITED) ||
+ dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
+ dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_EXEC_FAILED))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ _dbus_warn ("Did not expect error %s\n",
+ dbus_message_get_error_name (message));
+ goto out;
+ }
+ }
+ else
+ {
+ GotServiceInfo message_kind;
+
+ if (!check_base_service_activated (context, connection,
+ message, &base_service))
+ goto out;
+
+ base_service_message = message;
+ message = NULL;
+
+ /* We may need to block here for the test service to exit or finish up */
+ block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
+
+ message = dbus_connection_borrow_message (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after base service creation notification\n");
+ goto out;
+ }
+
+ message_kind = check_got_service_info (message);
+
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+
+ switch (message_kind)
+ {
+ case GOT_SOMETHING_ELSE:
+ case GOT_ERROR:
+ case GOT_SERVICE_DELETED:
+ _dbus_warn ("Unexpected message after ActivateService "
+ "(should be an error or a service announcement");
+ goto out;
+
+ case GOT_SERVICE_CREATED:
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message we just put back! "
+ "should have been a NameOwnerChanged (creation)\n");
+ goto out;
+ }
+
+ if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
+ base_service, message))
+ goto out;
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after successful activation\n");
+ goto out;
+ }
+
+ break;
+ }
+ }
+
+ if (!check_get_services (context, connection, "ListNames", &services, &len))
+ {
+ return TRUE;
+ }
+
+ if (!_dbus_string_array_contains ((const char **)services, existent))
+ {
+ _dbus_warn ("Did not get the expected %s from ListNames\n", existent);
+ goto out;
+ }
+
+ dbus_free_string_array (services);
+
+ if (!check_send_exit_to_service (context, connection,
+ EXISTENT_SERVICE_NAME, base_service))
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ if (base_service_message)
+ dbus_message_unref (base_service_message);
+
+ return retval;
+}
+
typedef struct
{
Check2Func func;
@@ -3625,6 +3967,9 @@
if (!check_get_connection_unix_process_id (context, baz))
_dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
+
+ if (!check_list_services (context, baz))
+ _dbus_assert_not_reached ("ListActivatableNames message failed");
if (!check_no_leftovers (context))
{
Index: driver.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -d -r1.76 -r1.77
--- driver.c 22 Nov 2005 20:37:00 -0000 1.76
+++ driver.c 14 Jul 2006 01:17:59 -0000 1.77
@@ -436,16 +436,108 @@
++i;
}
+ dbus_free_string_array (services);
+
if (!dbus_message_iter_close_container (&iter, &sub))
{
- dbus_free_string_array (services);
dbus_message_unref (reply);
BUS_SET_OOM (error);
return FALSE;
}
+ if (!bus_transaction_send_from_driver (transaction, connection, reply))
+ {
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ else
+ {
+ dbus_message_unref (reply);
+ return TRUE;
+ }
+}
+
+static dbus_bool_t
+bus_driver_handle_list_activatable_services (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ DBusMessage *reply;
+ int len;
+ char **services;
+ BusActivation *activation;
+ int i;
+ DBusMessageIter iter;
+ DBusMessageIter sub;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ activation = bus_connection_get_activation (connection);
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!bus_activation_list_services (activation, &services, &len))
+ {
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &sub))
+ {
+ dbus_free_string_array (services);
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ {
+ /* Include the bus driver in the list */
+ const char *v_STRING = DBUS_SERVICE_DBUS;
+ if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
+ &v_STRING))
+ {
+ dbus_free_string_array (services);
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+
+ i = 0;
+ while (i < len)
+ {
+ if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
+ &services[i]))
+ {
+ dbus_free_string_array (services);
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ ++i;
+ }
+
dbus_free_string_array (services);
-
+
+ if (!dbus_message_iter_close_container (&iter, &sub))
+ {
+ dbus_message_unref (reply);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
if (!bus_transaction_send_from_driver (transaction, connection, reply))
{
dbus_message_unref (reply);
@@ -1328,6 +1420,10 @@
"",
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
bus_driver_handle_list_services },
+ { "ListActivatableNames",
+ "",
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+ bus_driver_handle_list_activatable_services },
{ "AddMatch",
DBUS_TYPE_STRING_AS_STRING,
"",
More information about the dbus-commit
mailing list