properties: ignore some property updates

Ignore property updates for keys that we manage ourselves like the
object.id, node.id etc. Otherwise a client can replace this with
their local ids and cause confusion.
This commit is contained in:
Wim Taymans 2021-02-19 11:43:46 +01:00
parent dd1bf796cb
commit 08ea7d5cd6
6 changed files with 88 additions and 23 deletions

View file

@ -133,21 +133,39 @@ static int client_error(void *object, uint32_t id, int res, const char *error)
return 0;
}
static bool has_key(const char *keys[], const char *key)
{
int i;
for (i = 0; keys[i]; i++) {
if (strcmp(keys[i], key) == 0)
return true;
}
return false;
}
static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter)
{
struct pw_resource *resource;
int changed = 0;
uint32_t i;
const char *old;
const char *old, *ignored[] = {
PW_KEY_OBJECT_ID,
NULL
};
for (i = 0; i < dict->n_items; i++) {
if (filter && strstr(dict->items[i].key, "pipewire.") == dict->items[i].key &&
(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;
if (filter) {
if (strstr(dict->items[i].key, "pipewire.") == dict->items[i].key &&
(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;
}
if (has_key(ignored, dict->items[i].key))
continue;
}
changed += pw_properties_set(client->properties, dict->items[i].key, dict->items[i].value);
}

View file

@ -643,11 +643,18 @@ static void emit_info_changed(struct pw_impl_device *device)
device->info.change_mask = 0;
}
static int update_properties(struct pw_impl_device *device, const struct spa_dict *dict)
static int update_properties(struct pw_impl_device *device, const struct spa_dict *dict, bool filter)
{
int changed;
const char *ignored[] = {
PW_KEY_OBJECT_ID,
PW_KEY_MODULE_ID,
PW_KEY_FACTORY_ID,
PW_KEY_CLIENT_ID,
NULL
};
changed = pw_properties_update(device->properties, dict);
changed = pw_properties_update_ignore(device->properties, dict, filter ? ignored : NULL);
device->info.props = &device->properties->dict;
pw_log_debug(NAME" %p: updated %d properties", device, changed);
@ -726,7 +733,7 @@ static void device_info(void *data, const struct spa_device_info *info)
device, info->flags, info->change_mask);
if (info->change_mask & SPA_DEVICE_CHANGE_MASK_PROPS) {
update_properties(device, info->props);
update_properties(device, info->props, true);
}
if (info->change_mask & SPA_DEVICE_CHANGE_MASK_PARAMS) {
uint32_t i;
@ -894,7 +901,7 @@ const struct pw_properties *pw_impl_device_get_properties(struct pw_impl_device
SPA_EXPORT
int pw_impl_device_update_properties(struct pw_impl_device *device, const struct spa_dict *dict)
{
int changed = update_properties(device, dict);
int changed = update_properties(device, dict, false);
emit_info_changed(device);
return changed;
}

View file

@ -1220,11 +1220,19 @@ const struct pw_properties *pw_impl_node_get_properties(struct pw_impl_node *nod
return node->properties;
}
static int update_properties(struct pw_impl_node *node, const struct spa_dict *dict)
static int update_properties(struct pw_impl_node *node, const struct spa_dict *dict, bool filter)
{
int changed;
const char *ignored[] = {
PW_KEY_OBJECT_ID,
PW_KEY_MODULE_ID,
PW_KEY_FACTORY_ID,
PW_KEY_CLIENT_ID,
PW_KEY_DEVICE_ID,
NULL
};
changed = pw_properties_update(node->properties, dict);
changed = pw_properties_update_ignore(node->properties, dict, filter ? ignored : NULL);
node->info.props = &node->properties->dict;
pw_log_debug(NAME" %p: updated %d properties", node, changed);
@ -1239,7 +1247,7 @@ static int update_properties(struct pw_impl_node *node, const struct spa_dict *d
SPA_EXPORT
int pw_impl_node_update_properties(struct pw_impl_node *node, const struct spa_dict *dict)
{
int changed = update_properties(node, dict);
int changed = update_properties(node, dict, false);
emit_info_changed(node, false);
return changed;
}
@ -1265,7 +1273,7 @@ static void node_info(void *data, const struct spa_node_info *info)
}
}
if (info->change_mask & SPA_NODE_CHANGE_MASK_PROPS) {
update_properties(node, info->props);
update_properties(node, info->props, true);
}
if (info->change_mask & SPA_NODE_CHANGE_MASK_PARAMS) {
uint32_t i;

View file

@ -266,11 +266,19 @@ int pw_impl_port_release_mix(struct pw_impl_port *port, struct pw_impl_port_mix
return res;
}
static int update_properties(struct pw_impl_port *port, const struct spa_dict *dict)
static int update_properties(struct pw_impl_port *port, const struct spa_dict *dict, bool filter)
{
int changed;
const char *ignored[] = {
PW_KEY_OBJECT_ID,
PW_KEY_PORT_DIRECTION,
PW_KEY_PORT_CONTROL,
PW_KEY_NODE_ID,
PW_KEY_PORT_ID,
NULL
};
changed = pw_properties_update(port->properties, dict);
changed = pw_properties_update_ignore(port->properties, dict, filter ? ignored : NULL);
port->info.props = &port->properties->dict;
if (changed) {
@ -354,7 +362,7 @@ static void update_info(struct pw_impl_port *port, const struct spa_port_info *i
}
if (info->change_mask & SPA_PORT_CHANGE_MASK_PROPS) {
if (info->props) {
update_properties(port, info->props);
update_properties(port, info->props, true);
} else {
pw_log_warn(NAME" %p: port PROPS update but no properties", port);
}
@ -617,10 +625,8 @@ const struct pw_properties *pw_impl_port_get_properties(struct pw_impl_port *por
SPA_EXPORT
int pw_impl_port_update_properties(struct pw_impl_port *port, const struct spa_dict *dict)
{
int changed = update_properties(port, dict);
int changed = update_properties(port, dict, false);
emit_info_changed(port);
return changed;
}

View file

@ -248,6 +248,30 @@ int pw_properties_update_keys(struct pw_properties *props,
return changed;
}
static bool has_key(const char *keys[], const char *key)
{
int i;
for (i = 0; keys[i]; i++) {
if (strcmp(keys[i], key) == 0)
return true;
}
return false;
}
SPA_EXPORT
int pw_properties_update_ignore(struct pw_properties *props,
const struct spa_dict *dict, const char *ignore[])
{
const struct spa_dict_item *it;
int changed = 0;
spa_dict_for_each(it, dict) {
if (ignore == NULL || !has_key(ignore, it->key))
changed += pw_properties_set(props, it->key, it->value);
}
return changed;
}
/** Clear a properties object
*
* \param properties properties to clear

View file

@ -30,7 +30,7 @@ extern "C" {
#endif
#include <stdarg.h>
#include <spa/utils/dict.h>
/** \class pw_properties
@ -61,6 +61,8 @@ pw_properties_copy(const struct pw_properties *properties);
int pw_properties_update_keys(struct pw_properties *props,
const struct spa_dict *dict, const char *keys[]);
int pw_properties_update_ignore(struct pw_properties *props,
const struct spa_dict *dict, const char *ignore[]);
int pw_properties_update(struct pw_properties *oldprops,
const struct spa_dict *dict);