From 12e6dd89e23311e11328994a2a35fa896641bc7e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 9 Oct 2020 13:27:18 +0200 Subject: [PATCH] client: register client global after update properties This way we only expose the client after we have all the properties. Also add a new CLIENT_ACCESS property that contains the desired client access mode. --- src/examples/media-session/access-portal.c | 5 +-- src/pipewire/impl-client.c | 37 ++++++++++++++++++---- src/pipewire/keys.h | 2 ++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/examples/media-session/access-portal.c b/src/examples/media-session/access-portal.c index 027379761..7c5c43662 100644 --- a/src/examples/media-session/access-portal.c +++ b/src/examples/media-session/access-portal.c @@ -157,7 +157,7 @@ handle_client(struct impl *impl, struct sm_object *object) struct client *client; const char *str; - pw_log_debug(NAME" %p: client", impl); + pw_log_debug(NAME" %p: client %u", impl, object->id); client = sm_object_add_data(object, SESSION_KEY, sizeof(struct client)); client->obj = (struct sm_client*)object; @@ -168,7 +168,8 @@ handle_client(struct impl *impl, struct sm_object *object) client->obj->obj.mask |= SM_CLIENT_CHANGE_MASK_INFO; sm_object_add_listener(&client->obj->obj, &client->listener, &object_events, client); - if ((str = pw_properties_get(client->obj->obj.props, PW_KEY_ACCESS)) != NULL && + if (((str = pw_properties_get(client->obj->obj.props, PW_KEY_ACCESS)) != NULL || + (str = pw_properties_get(client->obj->obj.props, PW_KEY_CLIENT_ACCESS)) != NULL) && strcmp(str, "portal") == 0) { client->portal_managed = true; pw_log_info(NAME " %p: portal managed client %d added", diff --git a/src/pipewire/impl-client.c b/src/pipewire/impl-client.c index 1ff3f7caf..266b9e11b 100644 --- a/src/pipewire/impl-client.c +++ b/src/pipewire/impl-client.c @@ -36,6 +36,7 @@ struct impl { struct spa_hook context_listener; struct pw_array permissions; struct spa_hook pool_listener; + unsigned int registered:1; }; #define pw_client_resource(r,m,v,...) pw_resource_call(r,struct pw_client_events,m,v,__VA_ARGS__) @@ -137,12 +138,15 @@ static int update_properties(struct pw_impl_client *client, const struct spa_dic struct pw_resource *resource; int changed = 0; uint32_t i; + const char *old; for (i = 0; i < dict->n_items; i++) { if (filter && strstr(dict->items[i].key, "pipewire.") == dict->items[i].key && - pw_properties_get(client->properties, dict->items[i].key) != NULL) { - pw_log_warn(NAME" %p: refuse property update '%s' to '%s'", - client, dict->items[i].key, dict->items[i].value); + (old = pw_properties_get(client->properties, dict->items[i].key)) != NULL && + (dict->items[i].value == NULL || strcmp(old, dict->items[i].value) != 0)) { + pw_log_warn(NAME" %p: refuse property update '%s' from '%s' to '%s'", + client, dict->items[i].key, old, + dict->items[i].value); continue; } changed += pw_properties_set(client->properties, dict->items[i].key, dict->items[i].value); @@ -167,12 +171,32 @@ static int update_properties(struct pw_impl_client *client, const struct spa_dic return changed; } +static int finish_register(struct pw_impl_client *client) +{ + struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this); + const char *keys[] = { + PW_KEY_CLIENT_ACCESS, + PW_KEY_APP_NAME, + NULL + }; + if (impl->registered) + return 0; + + pw_global_update_keys(client->global, client->info.props, keys); + pw_global_register(client->global); + impl->registered = true; + + return 0; +} + static int client_update_properties(void *object, const struct spa_dict *props) { struct pw_resource *resource = object; struct resource_data *data = pw_resource_get_user_data(resource); struct pw_impl_client *client = data->client; - return update_properties(client, props, true); + int res = update_properties(client, props, true); + finish_register(client); + return res; } static int client_get_permissions(void *object, uint32_t index, uint32_t num) @@ -429,6 +453,7 @@ int pw_impl_client_register(struct pw_impl_client *client, PW_KEY_SEC_GID, PW_KEY_SEC_LABEL, PW_KEY_ACCESS, + PW_KEY_CLIENT_ACCESS, NULL }; @@ -452,14 +477,12 @@ int pw_impl_client_register(struct pw_impl_client *client, client->info.id = client->global->id; pw_properties_setf(client->properties, PW_KEY_OBJECT_ID, "%d", client->info.id); client->info.props = &client->properties->dict; + pw_global_add_listener(client->global, &client->global_listener, &global_events, client); pw_global_update_keys(client->global, client->info.props, keys); pw_impl_client_emit_initialized(client); - pw_global_add_listener(client->global, &client->global_listener, &global_events, client); - pw_global_register(client->global); - return 0; error_existed: diff --git a/src/pipewire/keys.h b/src/pipewire/keys.h index e0ee9ab8b..1499d91af 100644 --- a/src/pipewire/keys.h +++ b/src/pipewire/keys.h @@ -41,6 +41,8 @@ extern "C" { */ #define PW_KEY_PROTOCOL "pipewire.protocol" /**< protocol used for connection */ #define PW_KEY_ACCESS "pipewire.access" /**< how the client access is controlled */ +#define PW_KEY_CLIENT_ACCESS "pipewire.client.access"/**< how the client wants to be access + * controlled */ /** Various keys related to the identity of a client process and its security. * Must be obtained from trusted sources by the protocol and placed as