summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2017-02-15 09:57:02 +0100
committerWim Taymans <wtaymans@redhat.com>2017-05-12 17:15:46 +0200
commit4b2f6ad5d1619e47be727cfed867a4c02ad3021d (patch)
tree225ee315cfd98d1cca96445db5608e6b63ea6953
parent4eb5ededabefc31f63317b205080dd3cf1ebd09e (diff)
module-flatpak: keep track of pending async checksflatpack
Keep a list of pending async requests indexed by the DBus path name. When we get a reply, we can find the associated access_data again and complete the check. Cancel the portal request when the free callback is called. This can happen when the client disconnects while we are waiting for the reply.
-rw-r--r--src/modules/module-flatpak.c84
1 files changed, 80 insertions, 4 deletions
diff --git a/src/modules/module-flatpak.c b/src/modules/module-flatpak.c
index c7a568814..a5b76b8e4 100644
--- a/src/modules/module-flatpak.c
+++ b/src/modules/module-flatpak.c
@@ -93,6 +93,14 @@ struct userdata {
pa_hashmap *clients;
};
+struct async_pending {
+ PA_LLIST_FIELDS(struct async_pending);
+ bool handled;
+ struct client_data *client_data;
+ char *handle;
+ pa_access_data *access_data;
+};
+
struct client_data {
struct userdata *u;
@@ -101,11 +109,66 @@ struct client_data {
pid_t pid;
struct async_cache cached[PA_ACCESS_HOOK_MAX];
- pa_access_data *access_data;
PA_LLIST_HEAD(struct visible_object, visible_objects);
+ PA_LLIST_HEAD(struct async_pending, pending);
};
+static void close_request(struct async_pending *p) {
+ DBusMessage *m = NULL;
+ struct userdata *u = p->client_data->u;
+
+ if (!(m = dbus_message_new_method_call("org.freedesktop.portal.Request",
+ p->handle,
+ "org.freedesktop.portal.Request",
+ "Close"))) {
+ pa_log_error("Failed to create message\n");
+ return;
+ }
+
+ if (!dbus_connection_send(pa_dbus_connection_get(u->connection), m, NULL))
+ pa_log_error("Failed to send message\n");
+
+ dbus_message_unref(m);
+}
+
+static void free_pending(void *userdata) {
+ struct async_pending *p = userdata;
+ struct client_data *cd = p->client_data;
+
+ if (!p->handled)
+ close_request(p);
+
+ PA_LLIST_REMOVE(struct async_pending, cd->pending, p);
+ pa_xfree(p->handle);
+ pa_xfree(p);
+}
+
+static void add_pending(struct client_data *cd, const char *handle, pa_access_data *access_data) {
+ struct async_pending *p;
+
+ p = pa_xnew0(struct async_pending, 1);
+ PA_LLIST_INIT(struct async_pending, p);
+ p->client_data = cd;
+ p->handle = pa_xstrdup(handle);
+ p->access_data = access_data;
+ p->handled = false;
+
+ access_data->userdata = p;
+ access_data->free_cb = free_pending;
+
+ PA_LLIST_PREPEND(struct async_pending, cd->pending, p);
+}
+
+static struct async_pending *find_pending(struct client_data *cd, const char *handle) {
+ struct async_pending *p;
+
+ PA_LLIST_FOREACH(p, cd->pending) {
+ if (pa_streq(p->handle, handle))
+ return p;
+ }
+ return NULL;
+}
static void add_object(struct client_data *cd, int facility, uint32_t oidx) {
struct visible_object *o;
@@ -158,10 +221,14 @@ static struct client_data * client_data_new(struct userdata *u, uint32_t index,
static void client_data_free(struct client_data *cd) {
struct visible_object *o;
+ struct async_pending *p;
while ((o = cd->visible_objects))
free_object(cd, o);
+ while ((p = cd->pending))
+ free_pending(p);
+
pa_log_debug("removed client %d", cd->index);
pa_xfree(cd);
}
@@ -227,11 +294,12 @@ static pa_access_result_t rule_block (pa_core *c, pa_access_data *d, void *u) {
static DBusHandlerResult portal_response(DBusConnection *connection, DBusMessage *msg, void *user_data) {
struct client_data *cd = user_data;
- pa_access_data *d = cd->access_data;
if (dbus_message_is_signal(msg, "org.freedesktop.portal.Request", "Response")) {
uint32_t response = 2;
DBusError error;
+ struct async_pending *p;
+ pa_access_data *d;
dbus_error_init(&error);
@@ -242,6 +310,13 @@ static DBusHandlerResult portal_response(DBusConnection *connection, DBusMessage
dbus_error_free(&error);
}
+ p = find_pending(cd, dbus_message_get_path(msg));
+ if (p == NULL)
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+ p->handled = true;
+ d = p->access_data;
+
cd->cached[d->hook].checked = true;
cd->cached[d->hook].result = response == 0 ? PA_ACCESS_GRANTED : PA_ACCESS_DENIED;
@@ -273,14 +348,13 @@ static pa_access_result_t rule_check_portal (pa_core *c, pa_access_data *d, void
pa_log_info("ask portal for operation %d/%d for client %d", d->hook, d->object_index, d->client_index);
- cd->access_data = d;
-
dbus_error_init(&error);
if (!(m = dbus_message_new_method_call("org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.Device",
"AccessDevice"))) {
+ pa_log_error("Failed to create message\n");
return PA_ACCESS_DENIED;
}
@@ -338,6 +412,8 @@ static pa_access_result_t rule_check_portal (pa_core *c, pa_access_data *d, void
dbus_connection_add_filter(pa_dbus_connection_get(u->connection), portal_response, cd, NULL);
+ add_pending(cd, handle, d);
+
return PA_ACCESS_ASYNC_CHECK;
}