summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2017-06-22 22:18:34 +0100
committerSimon McVittie <smcv@collabora.com>2017-12-11 16:03:21 +0000
commit5d659d6e06a198cba81cdcd8f9b0fc811c393cd1 (patch)
treeeab8299cd291f1a19d8cbe7ca04cd2f00eee8df1
parenta0fd44f83d21cce3af1238edbfbe12b5987617e1 (diff)
bus/containers: Implement methods to stop containers explicitly
Signed-off-by: Simon McVittie <smcv@collabora.com> Reviewed-by: Philip Withnall <withnall@endlessm.com> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=101354
-rw-r--r--bus/containers.c100
-rw-r--r--bus/containers.h8
-rw-r--r--bus/driver.c4
-rw-r--r--dbus/dbus-protocol.h3
4 files changed, 115 insertions, 0 deletions
diff --git a/bus/containers.c b/bus/containers.c
index 91806dbe..9e81eb08 100644
--- a/bus/containers.c
+++ b/bus/containers.c
@@ -38,6 +38,7 @@
#include "dbus/dbus-sysdeps-unix.h"
#include "connection.h"
+#include "driver.h"
#include "utils.h"
/*
@@ -786,6 +787,105 @@ bus_containers_supported_arguments_getter (BusContext *context,
dbus_message_iter_close_container (var_iter, &arr_iter);
}
+dbus_bool_t
+bus_containers_handle_stop_instance (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ BusContext *context;
+ BusContainers *containers;
+ BusContainerInstance *instance = NULL;
+ DBusList *iter;
+ const char *path;
+
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ goto failed;
+
+ context = bus_transaction_get_context (transaction);
+ containers = bus_context_get_containers (context);
+
+ if (containers->instances_by_path != NULL)
+ {
+ instance = _dbus_hash_table_lookup_string (containers->instances_by_path,
+ path);
+ }
+
+ if (instance == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NOT_CONTAINER,
+ "There is no container with path '%s'", path);
+ goto failed;
+ }
+
+ bus_container_instance_ref (instance);
+ bus_container_instance_stop_listening (instance);
+
+ for (iter = _dbus_list_get_first_link (&instance->connections);
+ iter != NULL;
+ iter = _dbus_list_get_next_link (&instance->connections, iter))
+ dbus_connection_close (iter->data);
+
+ bus_container_instance_unref (instance);
+
+ if (!bus_driver_send_ack_reply (connection, transaction, message, error))
+ goto failed;
+
+ return TRUE;
+
+failed:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return FALSE;
+}
+
+dbus_bool_t
+bus_containers_handle_stop_listening (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ BusContext *context;
+ BusContainers *containers;
+ BusContainerInstance *instance = NULL;
+ const char *path;
+
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ goto failed;
+
+ context = bus_transaction_get_context (transaction);
+ containers = bus_context_get_containers (context);
+
+ if (containers->instances_by_path != NULL)
+ {
+ instance = _dbus_hash_table_lookup_string (containers->instances_by_path,
+ path);
+ }
+
+ if (instance == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NOT_CONTAINER,
+ "There is no container with path '%s'", path);
+ goto failed;
+ }
+
+ bus_container_instance_ref (instance);
+ bus_container_instance_stop_listening (instance);
+ bus_container_instance_unref (instance);
+
+ if (!bus_driver_send_ack_reply (connection, transaction, message, error))
+ goto failed;
+
+ return TRUE;
+
+failed:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return FALSE;
+}
+
void
bus_containers_stop_listening (BusContainers *self)
{
diff --git a/bus/containers.h b/bus/containers.h
index e51d6ba1..f3ecf1d4 100644
--- a/bus/containers.h
+++ b/bus/containers.h
@@ -36,6 +36,14 @@ dbus_bool_t bus_containers_handle_add_server (DBusConnection *connecti
BusTransaction *transaction,
DBusMessage *message,
DBusError *error);
+dbus_bool_t bus_containers_handle_stop_instance (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+dbus_bool_t bus_containers_handle_stop_listening (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
dbus_bool_t bus_containers_supported_arguments_getter (BusContext *context,
DBusMessageIter *var_iter);
diff --git a/bus/driver.c b/bus/driver.c
index 9529b07c..bcf38d05 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -2522,6 +2522,10 @@ static const MessageHandler introspectable_message_handlers[] = {
static const MessageHandler containers_message_handlers[] = {
{ "AddServer", "ssa{sv}a{sv}", "oays", bus_containers_handle_add_server,
METHOD_FLAG_PRIVILEGED },
+ { "StopInstance", "o", "", bus_containers_handle_stop_instance,
+ METHOD_FLAG_PRIVILEGED },
+ { "StopListening", "o", "", bus_containers_handle_stop_listening,
+ METHOD_FLAG_PRIVILEGED },
{ NULL, NULL, NULL, NULL }
};
static const PropertyHandler containers_property_handlers[] = {
diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h
index 933c3658..56be9832 100644
--- a/dbus/dbus-protocol.h
+++ b/dbus/dbus-protocol.h
@@ -455,6 +455,9 @@ extern "C" {
* but could have succeeded if an interactive authorization step was
* allowed. */
#define DBUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"
+/** The connection is not from a container, or the specified container instance
+ * does not exist. */
+#define DBUS_ERROR_NOT_CONTAINER "org.freedesktop.DBus.Error.NotContainer"
/* XML introspection format */