This keeps composition data unchanged even if models are registered in a different order. --- mesh/node.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/mesh/node.c b/mesh/node.c index d631b9324..3cf82e63c 100644 --- a/mesh/node.c +++ b/mesh/node.c @@ -180,6 +180,29 @@ static bool match_element_path(const void *a, const void *b) return (!strcmp(element->path, path)); } +static bool match_model(const void *a, const void *b) +{ + uint32_t a_id = mesh_model_get_model_id(a); + uint32_t b_id = mesh_model_get_model_id(b); + + return a_id == b_id; +} + +static int compare_model_id(const void *a, const void *b, void *user_data) +{ + uint32_t a_id = mesh_model_get_model_id(a); + uint32_t b_id = mesh_model_get_model_id(b); + + if (a_id < b_id) + return -1; + + if (a_id > b_id) + return 1; + + return 0; +} + + struct mesh_node *node_find_by_addr(uint16_t addr) { if (!IS_UNICAST(addr)) @@ -301,6 +324,17 @@ void node_remove(struct mesh_node *node) free_node_resources(node); } +static bool element_add_model(struct node_element *ele, struct mesh_model *mod) +{ + if (l_queue_find(ele->models, match_model, mod)) { + mesh_model_free(mod); + return false; + } + + l_queue_insert(ele->models, mod, compare_model_id, NULL); + return true; +} + static bool add_models(struct mesh_node *node, struct node_element *ele, struct mesh_config_element *db_ele) { @@ -319,7 +353,8 @@ static bool add_models(struct mesh_node *node, struct node_element *ele, if (!mod) return false; - l_queue_push_tail(ele->models, mod); + if (!element_add_model(ele, mod)) + return false; } return true; @@ -348,7 +383,7 @@ static void add_internal_model(struct mesh_node *node, uint32_t mod_id, if (!ele->models) ele->models = l_queue_new(); - l_queue_push_tail(ele->models, mod); + element_add_model(ele, mod); } static bool add_element(struct mesh_node *node, @@ -1035,12 +1070,11 @@ bool node_parse_composition(struct mesh_node *node, uint8_t *data, while (len >= 2 && m--) { mod_id = l_get_le16(data); mod = mesh_model_new(ele->idx, mod_id); - if (!mod) { + if (!mod || !element_add_model(ele, mod)) { element_free(ele); goto fail; } - l_queue_push_tail(ele->models, mod); data += 2; len -= 2; } @@ -1057,12 +1091,11 @@ bool node_parse_composition(struct mesh_node *node, uint8_t *data, mod_id |= (vendor_id << 16); mod = mesh_model_vendor_new(ele->idx, vendor_id, mod_id); - if (!mod) { + if (!mod || !element_add_model(ele, mod)) { element_free(ele); goto fail; } - l_queue_push_tail(ele->models, mod); data += 4; len -= 4; } @@ -1212,12 +1245,8 @@ static void get_models_from_properties(struct node_element *ele, while (l_dbus_message_iter_next_entry(&ids, &mod_id)) { struct mesh_model *mod; - /* Skip internally implemented models */ - if ((VENDOR_ID_MASK | mod_id) == CONFIG_SRV_MODEL) - continue; - mod = mesh_model_new(ele->idx, mod_id); - l_queue_push_tail(ele->models, mod); + element_add_model(ele, mod); } return; } @@ -1227,7 +1256,7 @@ static void get_models_from_properties(struct node_element *ele, struct mesh_model *mod; mod = mesh_model_vendor_new(ele->idx, vendor_id, mod_id); - l_queue_push_tail(ele->models, mod); + element_add_model(ele, mod); } } -- 2.22.0