summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2019-05-13 18:03:27 +0200
committerWim Taymans <wtaymans@redhat.com>2019-05-13 18:03:27 +0200
commitb474666e2e841a2cd37cfb49558ca60b37d8501f (patch)
treec7d79523b1f47ddcc2ece46fe80042bd3fd647d6
parenta224234acd1fe1f4a4302bbaa1df2d1a4c7c8476 (diff)
link: listen for permission changes
Destroy the link when the ports or nodes are no longer visible to the other side of the link.
-rw-r--r--src/pipewire/link.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/src/pipewire/link.c b/src/pipewire/link.c
index 1e39da58..86c639d9 100644
--- a/src/pipewire/link.c
+++ b/src/pipewire/link.c
@@ -62,8 +62,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 spa_io_buffers io;
@@ -872,6 +874,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);
spa_list_remove(&this->input_link);
pw_port_emit_link_removed(this->input, this);
@@ -891,6 +894,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);
spa_list_remove(&this->output_link);
pw_port_emit_link_removed(this->output, this);
@@ -1177,22 +1181,34 @@ check_permission(struct pw_core *core,
struct pw_port *input,
struct pw_properties *properties)
{
- struct pw_node *input_node, *output_node;
struct pw_client *client;
- input_node = input->node;
- output_node = output->node;
-
- if ((client = output_node->global->owner) != NULL &&
- !PW_PERM_IS_R(pw_global_get_permissions(input_node->global, client)))
+ if ((client = output->global->owner) != NULL &&
+ !PW_PERM_IS_R(pw_global_get_permissions(input->global, client)))
return -EPERM;
- if ((client = input_node->global->owner) != NULL &&
- !PW_PERM_IS_R(pw_global_get_permissions(output_node->global, client)))
+ if ((client = input->global->owner) != NULL &&
+ !PW_PERM_IS_R(pw_global_get_permissions(output->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;
+
+ pw_log_debug("link %p: permissions changed", this);
+ 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,
@@ -1254,8 +1270,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;