client: rework permissions

Keep the default permission at index 0 in our permission array.
This commit is contained in:
Wim Taymans 2019-01-10 16:36:33 +01:00
parent 2ab96db5b5
commit c2f0dea0f5

View file

@ -35,7 +35,6 @@
/** \cond */ /** \cond */
struct impl { struct impl {
struct pw_client this; struct pw_client this;
uint32_t permissions_default;
struct spa_hook core_listener; struct spa_hook core_listener;
struct pw_array permissions; struct pw_array permissions;
}; };
@ -45,41 +44,51 @@ struct resource_data {
struct pw_client *client; struct pw_client *client;
}; };
/** find a specific permission for a global or NULL when there is none */ /** find a specific permission for a global or the default when there is none */
static struct pw_permission * static struct pw_permission *
find_permission(struct pw_client *client, uint32_t id) find_permission(struct pw_client *client, uint32_t id)
{ {
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
struct pw_permission *p; struct pw_permission *p;
uint32_t idx = id + 1;
if (!pw_array_check_index(&impl->permissions, id, struct pw_permission)) if (id == SPA_ID_INVALID)
return NULL; goto do_default;
p = pw_array_get_unchecked(&impl->permissions, id, struct pw_permission); if (!pw_array_check_index(&impl->permissions, idx, struct pw_permission))
goto do_default;
p = pw_array_get_unchecked(&impl->permissions, idx, struct pw_permission);
if (p->permissions == SPA_ID_INVALID) if (p->permissions == SPA_ID_INVALID)
return NULL; goto do_default;
else
return p; return p;
do_default:
return pw_array_get_unchecked(&impl->permissions, 0, struct pw_permission);
} }
static struct pw_permission *ensure_permissions(struct pw_client *client, uint32_t id) static struct pw_permission *ensure_permissions(struct pw_client *client, uint32_t id)
{ {
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
struct pw_permission *p; struct pw_permission *p;
uint32_t idx = id + 1;
size_t len, i; size_t len, i;
len = pw_array_get_len(&impl->permissions, struct pw_permission); len = pw_array_get_len(&impl->permissions, struct pw_permission);
if (len <= id) { if (len <= idx) {
size_t diff = id - len + 1; size_t diff = idx - len + 1;
p = pw_array_add(&impl->permissions, diff * sizeof(struct pw_permission)); p = pw_array_add(&impl->permissions, diff * sizeof(struct pw_permission));
if (p == NULL) if (p == NULL)
return NULL; return NULL;
for (i = 0; i < diff; i++) for (i = 0; i < diff; i++) {
p[i].id = len + i - 1;
p[i].permissions = SPA_ID_INVALID; p[i].permissions = SPA_ID_INVALID;
}
} }
p = pw_array_get_unchecked(&impl->permissions, id, struct pw_permission); p = pw_array_get_unchecked(&impl->permissions, idx, struct pw_permission);
return p; return p;
} }
@ -89,14 +98,9 @@ static uint32_t
client_permission_func(struct pw_global *global, client_permission_func(struct pw_global *global,
struct pw_client *client, void *data) struct pw_client *client, void *data)
{ {
struct impl *impl = data;
struct pw_permission *p; struct pw_permission *p;
p = find_permission(client, global->id); p = find_permission(client, global->id);
if (p == NULL) return p->permissions;
return impl->permissions_default;
else
return p->permissions;
} }
static void client_error(void *object, uint32_t id, int res, const char *error) static void client_error(void *object, uint32_t id, int res, const char *error)
@ -195,7 +199,7 @@ core_global_removed(void *data, struct pw_global *global)
p = find_permission(client, global->id); p = find_permission(client, global->id);
pw_log_debug("client %p: global %d removed, %p", client, global->id, p); pw_log_debug("client %p: global %d removed, %p", client, global->id, p);
if (p != NULL) if (p->id != SPA_ID_INVALID)
p->permissions = SPA_ID_INVALID; p->permissions = SPA_ID_INVALID;
} }
@ -220,6 +224,7 @@ struct pw_client *pw_client_new(struct pw_core *core,
{ {
struct pw_client *this; struct pw_client *this;
struct impl *impl; struct impl *impl;
struct pw_permission *p;
impl = calloc(1, sizeof(struct impl) + user_data_size); impl = calloc(1, sizeof(struct impl) + user_data_size);
if (impl == NULL) if (impl == NULL)
@ -244,6 +249,9 @@ struct pw_client *pw_client_new(struct pw_core *core,
} }
pw_array_init(&impl->permissions, 1024); pw_array_init(&impl->permissions, 1024);
p = pw_array_add(&impl->permissions, sizeof(struct pw_permission));
p->id = SPA_ID_INVALID;
p->permissions = 0;
this->properties = properties; this->properties = properties;
this->permission_func = client_permission_func; this->permission_func = client_permission_func;
@ -440,17 +448,18 @@ int pw_client_update_properties(struct pw_client *client, const struct spa_dict
int pw_client_update_permissions(struct pw_client *client, int pw_client_update_permissions(struct pw_client *client,
uint32_t n_permissions, const struct pw_permission *permissions) uint32_t n_permissions, const struct pw_permission *permissions)
{ {
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
struct pw_core *core = client->core; struct pw_core *core = client->core;
uint32_t i; uint32_t i;
for (i = 0; i < n_permissions; i++) { for (i = 0; i < n_permissions; i++) {
struct pw_permission *p; struct pw_permission *p, *def;
uint32_t old_perm, new_perm; uint32_t old_perm, new_perm;
struct pw_global *global; struct pw_global *global;
def = find_permission(client, SPA_ID_INVALID);
if (permissions[i].id == SPA_ID_INVALID) { if (permissions[i].id == SPA_ID_INVALID) {
old_perm = impl->permissions_default; old_perm = def->permissions;
new_perm = permissions[i].permissions; new_perm = permissions[i].permissions;
if (core->current_client == client) if (core->current_client == client)
@ -461,23 +470,22 @@ int pw_client_update_permissions(struct pw_client *client,
spa_list_for_each(global, &core->global_list, link) { spa_list_for_each(global, &core->global_list, link) {
p = find_permission(client, global->id); p = find_permission(client, global->id);
if (p != NULL) if (p->id != SPA_ID_INVALID)
continue; continue;
pw_global_update_permissions(global, client, old_perm, new_perm); pw_global_update_permissions(global, client, old_perm, new_perm);
} }
impl->permissions_default = new_perm; def->permissions = new_perm;
} }
else { else {
struct pw_global *global; struct pw_global *global;
global = pw_core_find_global(client->core, permissions[i].id); global = pw_core_find_global(client->core, permissions[i].id);
if (global == NULL) { if (global == NULL || global->id != permissions[i].id) {
pw_log_warn("client %p: invalid global %d", client, permissions[i].id); pw_log_warn("client %p: invalid global %d", client, permissions[i].id);
continue; continue;
} }
p = ensure_permissions(client, global->id); p = ensure_permissions(client, permissions[i].id);
old_perm = p->permissions == SPA_ID_INVALID ? impl->permissions_default : p->permissions; old_perm = p->permissions == SPA_ID_INVALID ? def->permissions : p->permissions;
new_perm = permissions[i].permissions; new_perm = permissions[i].permissions;
if (core->current_client == client) if (core->current_client == client)