link: listen for permission changes

Destroy the link when the ports or nodes are no longer visible
to the other side of the link.
This commit is contained in:
Wim Taymans 2019-05-13 18:03:27 +02:00
parent a224234acd
commit b474666e2e

View file

@ -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;