summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2019-05-13 17:04:43 +0200
committerWim Taymans <wtaymans@redhat.com>2019-05-13 17:04:43 +0200
commit98da5a2e9e5524751aaa96e2043d475135a2bb9b (patch)
tree231bee25af176d63b99eacc93a9075bb9098fc0d
parent83bc033837f7525d898f1de91119f669f9bf97f5 (diff)
global: emit permissions_changed event
Add a permissions_changed event when the permissions change for a global for a client. Recheck if a link is still allowed when node permissions changed and destroy the link if not.
-rw-r--r--src/pipewire/client.c9
-rw-r--r--src/pipewire/global.h8
-rw-r--r--src/pipewire/link.c22
-rw-r--r--src/pipewire/private.h2
4 files changed, 38 insertions, 3 deletions
diff --git a/src/pipewire/client.c b/src/pipewire/client.c
index a09e3da8..4c647fe2 100644
--- a/src/pipewire/client.c
+++ b/src/pipewire/client.c
@@ -395,6 +395,7 @@ static int do_permissions(void *data, struct pw_global *global)
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
struct permission *p;
size_t len, i;
+ uint32_t old;
len = pw_array_get_len(&impl->permissions, struct permission);
if (len <= global->id) {
@@ -410,12 +411,16 @@ static int do_permissions(void *data, struct pw_global *global)
p = pw_array_get_unchecked(&impl->permissions, global->id, struct permission);
if (p->permissions == -1)
- p->permissions = impl->permissions_default;
+ old = p->permissions = impl->permissions_default;
else if (update->only_new)
return 0;
+ old = p->permissions;
p->permissions &= update->permissions;
- pw_log_debug("client %p: set global %d permissions to %08x", client, global->id, p->permissions);
+ pw_log_debug("client %p: change global %d permissions %08x -> %08x",
+ client, global->id, old, p->permissions);
+
+ pw_global_events_permissions_changed(global, client, old, p->permissions);
return 0;
}
diff --git a/src/pipewire/global.h b/src/pipewire/global.h
index 813409f9..2c5f07ff 100644
--- a/src/pipewire/global.h
+++ b/src/pipewire/global.h
@@ -57,7 +57,7 @@ struct pw_global;
/** Global events, use \ref pw_global_add_listener */
struct pw_global_events {
-#define PW_VERSION_GLOBAL_EVENTS 0
+#define PW_VERSION_GLOBAL_EVENTS 1
uint32_t version;
/** The global is destroyed */
@@ -72,6 +72,12 @@ struct pw_global_events {
uint32_t permissions, /**< permissions for the bind */
uint32_t version, /**< client interface version */
uint32_t id /**< client proxy id */);
+
+ /* permissions for the global changed, Since version 1 */
+ void (*permissions_changed) (void *data,
+ struct pw_client *client,
+ uint32_t old_permissions,
+ uint32_t new_permissions);
};
/** Create a new global object */
diff --git a/src/pipewire/link.c b/src/pipewire/link.c
index f4529be9..9b33c160 100644
--- a/src/pipewire/link.c
+++ b/src/pipewire/link.c
@@ -51,8 +51,10 @@ struct impl {
struct spa_hook input_port_listener;
struct spa_hook input_node_listener;
+ struct spa_hook input_global_listener;
struct spa_hook output_port_listener;
struct spa_hook output_node_listener;
+ struct spa_hook output_global_listener;
};
struct resource_data {
@@ -868,6 +870,7 @@ static void input_remove(struct pw_link *this, struct pw_port *port)
pw_log_debug("link %p: remove input port %p", this, port);
spa_hook_remove(&impl->input_port_listener);
spa_hook_remove(&impl->input_node_listener);
+ spa_hook_remove(&impl->input_global_listener);
pw_loop_invoke(port->node->data_loop,
do_remove_input, 1, NULL, 0, true, this);
@@ -897,6 +900,7 @@ static void output_remove(struct pw_link *this, struct pw_port *port)
pw_log_debug("link %p: remove output port %p", this, port);
spa_hook_remove(&impl->output_port_listener);
spa_hook_remove(&impl->output_node_listener);
+ spa_hook_remove(&impl->output_global_listener);
pw_loop_invoke(port->node->data_loop,
do_remove_output, 1, NULL, 0, true, this);
@@ -1105,9 +1109,25 @@ check_permission(struct pw_core *core,
if ((client = input_node->global->owner) != NULL &&
!PW_PERM_IS_R(pw_global_get_permissions(output_node->global, client)))
return -EPERM;
+
return 0;
}
+static void global_permissions_changed(void *data,
+ struct pw_client *client, uint32_t old, uint32_t new)
+{
+ struct pw_link *this = data;
+
+ if (check_permission(this->core, this->output, this->input, this->properties) < 0)
+ pw_link_destroy(this);
+}
+
+
+static const struct pw_global_events global_node_events = {
+ PW_VERSION_GLOBAL_EVENTS,
+ .permissions_changed = global_permissions_changed,
+};
+
SPA_EXPORT
struct pw_link *pw_link_new(struct pw_core *core,
struct pw_port *output,
@@ -1166,8 +1186,10 @@ struct pw_link *pw_link_new(struct pw_core *core,
pw_port_add_listener(input, &impl->input_port_listener, &input_port_events, impl);
pw_node_add_listener(input_node, &impl->input_node_listener, &input_node_events, impl);
+ pw_global_add_listener(input_node->global, &impl->input_global_listener, &global_node_events, impl);
pw_port_add_listener(output, &impl->output_port_listener, &output_port_events, impl);
pw_node_add_listener(output_node, &impl->output_node_listener, &output_node_events, impl);
+ pw_global_add_listener(output_node->global, &impl->output_global_listener, &global_node_events, impl);
input_node->live = output_node->live;
if (output_node->clock)
diff --git a/src/pipewire/private.h b/src/pipewire/private.h
index 9e51d21a..1bb314e7 100644
--- a/src/pipewire/private.h
+++ b/src/pipewire/private.h
@@ -124,6 +124,8 @@ struct pw_client {
#define pw_global_events_destroy(g) pw_global_events_emit(g, destroy, 0)
#define pw_global_events_free(g) pw_global_events_emit(g, free, 0)
#define pw_global_events_bind(g,...) pw_global_events_emit(g, bind, 0, __VA_ARGS__)
+#define pw_global_events_permissions_changed(g,...) \
+ pw_global_events_emit(g, permissions_changed, 1, __VA_ARGS__)
struct pw_global {
struct pw_core *core; /**< the core */