mesh: Clean up node.c
authorInga Stotland <inga.stotland@intel.com>
Fri, 6 Dec 2019 20:57:48 +0000 (12:57 -0800)
committerAnupam Roy <anupam.r@samsung.com>
Wed, 18 Dec 2019 11:49:13 +0000 (17:19 +0530)
This change makes the node initialization a bit easier to follow.
Replace if-else with switch when processing request type, descriptive
function names, more predictable code flow.

Change-Id: Id81f673224878a64d3ff341c7eb574a78bd8be0b
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
mesh/model.c
mesh/model.h
mesh/node.c

index 45cdb93..578fb79 100644 (file)
@@ -1173,7 +1173,7 @@ void mesh_model_free(void *data)
        l_free(mod);
 }
 
-static struct mesh_model *model_new(uint8_t ele_idx, uint32_t id)
+struct mesh_model *mesh_model_new(uint8_t ele_idx, uint32_t id)
 {
        struct mesh_model *mod = l_new(struct mesh_model, 1);
 
@@ -1183,19 +1183,6 @@ static struct mesh_model *model_new(uint8_t ele_idx, uint32_t id)
        return mod;
 }
 
-struct mesh_model *mesh_model_new(uint8_t ele_idx, uint16_t id)
-{
-       return model_new(ele_idx, id | VENDOR_ID_MASK);
-}
-
-struct mesh_model *mesh_model_vendor_new(uint8_t ele_idx, uint16_t vendor_id,
-                                                               uint16_t mod_id)
-{
-       uint32_t id = mod_id | (vendor_id << 16);
-
-       return model_new(ele_idx, id);
-}
-
 /* Internal models only */
 static void restore_model_state(struct mesh_model *mod)
 {
@@ -1504,7 +1491,7 @@ struct mesh_model *mesh_model_setup(struct mesh_node *node, uint8_t ele_idx,
                return NULL;
        }
 
-       mod = model_new(ele_idx, db_mod->vendor ? db_mod->id :
+       mod = mesh_model_new(ele_idx, db_mod->vendor ? db_mod->id :
                                                db_mod->id | VENDOR_ID_MASK);
 
        /* Implicitly bind config server model to device key */
index f30ca2e..9c7ce93 100644 (file)
@@ -62,9 +62,7 @@ struct mesh_model_ops {
        mesh_model_sub_cb sub;
 };
 
-struct mesh_model *mesh_model_new(uint8_t ele_idx, uint16_t mod_id);
-struct mesh_model *mesh_model_vendor_new(uint8_t ele_idx, uint16_t vendor_id,
-                                                       uint16_t mod_id);
+struct mesh_model *mesh_model_new(uint8_t ele_idx, uint32_t mod_id);
 void mesh_model_free(void *data);
 uint32_t mesh_model_get_model_id(const struct mesh_model *model);
 bool mesh_model_register(struct mesh_node *node, uint8_t ele_idx,
index 8cc3255..d173059 100644 (file)
@@ -218,7 +218,6 @@ static int compare_model_id(const void *a, const void *b, void *user_data)
        return 0;
 }
 
-
 struct mesh_node *node_find_by_addr(uint16_t addr)
 {
        if (!IS_UNICAST(addr))
@@ -244,13 +243,46 @@ uint8_t *node_uuid_get(struct mesh_node *node)
        return node->uuid;
 }
 
+static void add_internal_model(struct mesh_node *node, uint32_t mod_id,
+                                                               uint8_t ele_idx)
+{
+       struct node_element *ele;
+       struct mesh_model *mod;
+
+       ele = l_queue_find(node->elements, match_element_idx,
+                                                       L_UINT_TO_PTR(ele_idx));
+       if (!ele)
+               return;
+
+       if (l_queue_find(ele->models, match_model_id, L_UINT_TO_PTR(mod_id)))
+               return;
+
+       mod = mesh_model_new(ele_idx, mod_id);
+
+       l_queue_insert(ele->models, mod, compare_model_id, NULL);
+}
+
+static void set_defaults(struct mesh_node *node)
+{
+       /* TODO: these values should come from mesh.conf */
+       node->lpn = MESH_MODE_UNSUPPORTED;
+       node->proxy = MESH_MODE_UNSUPPORTED;
+       node->friend = MESH_MODE_UNSUPPORTED;
+       node->beacon = MESH_MODE_DISABLED;
+       node->relay.mode = MESH_MODE_DISABLED;
+       node->ttl = TTL_MASK;
+       node->seq_number = DEFAULT_SEQUENCE_NUMBER;
+}
+
 static struct mesh_node *node_new(const uint8_t uuid[16])
 {
        struct mesh_node *node;
 
        node = l_new(struct mesh_node, 1);
        node->net = mesh_net_new(node);
+       node->elements = l_queue_new();
        memcpy(node->uuid, uuid, sizeof(node->uuid));
+       set_defaults(node);
 
        return node;
 }
@@ -335,18 +367,8 @@ void node_remove(struct mesh_node *node)
        free_node_resources(node);
 }
 
-static bool element_add_model(struct node_element *ele, struct mesh_model *mod)
-{
-       uint32_t mod_id = mesh_model_get_model_id(mod);
-
-       if (l_queue_find(ele->models, match_model_id, L_UINT_TO_PTR(mod_id)))
-               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,
+static bool add_models_from_storage(struct mesh_node *node,
+                                       struct node_element *ele,
                                        struct mesh_config_element *db_ele)
 {
        const struct l_queue_entry *entry;
@@ -355,52 +377,31 @@ static bool add_models(struct mesh_node *node, struct node_element *ele,
                ele->models = l_queue_new();
 
        entry = l_queue_get_entries(db_ele->models);
+
        for (; entry; entry = entry->next) {
                struct mesh_model *mod;
                struct mesh_config_model *db_mod;
+               uint32_t id;
 
                db_mod = entry->data;
+
+               id = db_mod->vendor ? db_mod->id : db_mod->id | VENDOR_ID_MASK;
+
+               if (l_queue_find(ele->models, match_model_id,
+                                                       L_UINT_TO_PTR(id)))
+                       return false;
+
                mod = mesh_model_setup(node, ele->idx, db_mod);
                if (!mod)
                        return false;
 
-               if (!element_add_model(ele, mod)) {
-                       mesh_model_free(mod);
-                       return false;
-               }
+               l_queue_insert(ele->models, mod, compare_model_id, NULL);
        }
 
        return true;
 }
 
-static void add_internal_model(struct mesh_node *node, uint32_t mod_id,
-                                                               uint8_t ele_idx)
-{
-       struct node_element *ele;
-       struct mesh_model *mod;
-       struct mesh_config_model db_mod;
-
-       ele = l_queue_find(node->elements, match_element_idx,
-                                                       L_UINT_TO_PTR(ele_idx));
-
-       if (!ele)
-               return;
-
-       memset(&db_mod, 0, sizeof(db_mod));
-       db_mod.id = mod_id;
-
-       mod = mesh_model_setup(node, ele_idx, &db_mod);
-       if (!mod)
-               return;
-
-       if (!ele->models)
-               ele->models = l_queue_new();
-
-       if (!element_add_model(ele, mod))
-               mesh_model_free(mod);
-}
-
-static bool add_element(struct mesh_node *node,
+static bool add_element_from_storage(struct mesh_node *node,
                                        struct mesh_config_element *db_ele)
 {
        struct node_element *ele;
@@ -412,26 +413,26 @@ static bool add_element(struct mesh_node *node,
        ele->idx = db_ele->index;
        ele->location = db_ele->location;
 
-       if (!db_ele->models || !add_models(node, ele, db_ele))
+       if (!db_ele->models || !add_models_from_storage(node, ele, db_ele))
                return false;
 
        l_queue_push_tail(node->elements, ele);
        return true;
 }
 
-static bool add_elements(struct mesh_node *node,
+static bool add_elements_from_storage(struct mesh_node *node,
                                        struct mesh_config_node *db_node)
 {
        const struct l_queue_entry *entry;
 
-       if (!node->elements)
-               node->elements = l_queue_new();
-
        entry = l_queue_get_entries(db_node->elements);
        for (; entry; entry = entry->next)
-               if (!add_element(node, entry->data))
+               if (!add_element_from_storage(node, entry->data))
                        return false;
 
+       /* Add configuration server model on the primary element */
+       add_internal_model(node, CONFIG_SRV_MODEL, PRIMARY_ELE_IDX);
+
        return true;
 }
 
@@ -453,13 +454,35 @@ static void set_appkey(void *a, void *b)
                                                appkey->key, appkey->new_key);
 }
 
+static bool init_storage_dir(struct mesh_node *node)
+{
+       char uuid[33];
+       char dir_name[PATH_MAX];
+
+       if (node->storage_dir)
+               return true;
+
+       if (!hex2str(node->uuid, 16, uuid, sizeof(uuid)))
+               return false;
+
+       snprintf(dir_name, PATH_MAX, "%s/%s", mesh_get_storage_dir(), uuid);
+
+       if (strlen(dir_name) >= PATH_MAX)
+               return false;
+
+       create_dir(dir_name);
+
+       node->storage_dir = l_strdup(dir_name);
+
+       return true;
+}
+
 static bool init_from_storage(struct mesh_config_node *db_node,
                        const uint8_t uuid[16], struct mesh_config *cfg,
                        void *user_data)
 {
        unsigned int num_ele;
        uint8_t mode;
-
        struct mesh_node *node = node_new(uuid);
 
        if (!nodes)
@@ -495,7 +518,7 @@ static bool init_from_storage(struct mesh_config_node *db_node,
 
        node->num_ele = num_ele;
 
-       if (num_ele != 0 && !add_elements(node, db_node))
+       if (num_ele != 0 && !add_elements_from_storage(node, db_node))
                goto fail;
 
        node->primary = db_node->unicast;
@@ -503,6 +526,10 @@ static bool init_from_storage(struct mesh_config_node *db_node,
        if (!db_node->netkeys)
                goto fail;
 
+       if (!IS_UNASSIGNED(node->primary) &&
+               !mesh_net_register_unicast(node->net, node->primary, num_ele))
+               goto fail;
+
        mesh_net_set_iv_index(node->net, db_node->iv_index, db_node->iv_update);
 
        if (db_node->net_transmit)
@@ -535,15 +562,14 @@ static bool init_from_storage(struct mesh_config_node *db_node,
        if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
                mesh_net_set_beacon_mode(node->net, mode == MESH_MODE_ENABLED);
 
-       if (!IS_UNASSIGNED(node->primary) &&
-               !mesh_net_register_unicast(node->net, node->primary, num_ele))
-               goto fail;
-
        /* Initialize configuration server model */
        cfgmod_server_init(node, PRIMARY_ELE_IDX);
 
        node->cfg = cfg;
 
+       /* Initialize directory for storing keyring info */
+       init_storage_dir(node);
+
        return true;
 fail:
        node_remove(node);
@@ -867,8 +893,6 @@ uint16_t node_generate_comp(struct mesh_node *node, uint8_t *buf, uint16_t sz)
 {
        uint16_t n, features;
        uint16_t num_ele = 0;
-       uint8_t *cfgmod_idx = NULL;
-
        const struct l_queue_entry *ele_entry;
 
        if (!node || !node->comp || sz < MIN_COMP_SIZE)
@@ -931,9 +955,6 @@ uint16_t node_generate_comp(struct mesh_node *node, uint8_t *buf, uint16_t sz)
                        mod_id = mesh_model_get_model_id(
                                        (const struct mesh_model *) mod);
 
-                       if (mod_id == CONFIG_SRV_MODEL)
-                               cfgmod_idx = &ele->idx;
-
                        if ((mod_id & VENDOR_ID_MASK) == VENDOR_ID_MASK) {
                                if (n + 2 > sz)
                                        goto element_done;
@@ -979,9 +1000,6 @@ element_done:
        if (!num_ele)
                return 0;
 
-       if (!cfgmod_idx || *cfgmod_idx != PRIMARY_ELE_IDX)
-               return 0;
-
        return n;
 }
 
@@ -1038,39 +1056,57 @@ static void app_disc_cb(struct l_dbus *bus, void *user_data)
        free_node_dbus_resources(node);
 }
 
-static void get_models_from_properties(struct node_element *ele,
-                                       struct l_dbus_message_iter *property,
-                                                               bool vendor)
+static void get_sig_models_from_properties(struct node_element *ele,
+                                       struct l_dbus_message_iter *property)
 {
        struct l_dbus_message_iter ids;
-       uint16_t mod_id, vendor_id;
-       const char *signature = !vendor ? "aq" : "a(qq)";
+       uint16_t mod_id;
 
        if (!ele->models)
                ele->models = l_queue_new();
 
-       if (!l_dbus_message_iter_get_variant(property, signature, &ids))
+       if (!l_dbus_message_iter_get_variant(property, "aq", &ids))
                return;
 
        /* Bluetooth SIG defined models */
-       if (!vendor) {
-               while (l_dbus_message_iter_next_entry(&ids, &mod_id)) {
-                       struct mesh_model *mod;
+       while (l_dbus_message_iter_next_entry(&ids, &mod_id)) {
+               struct mesh_model *mod;
+               uint32_t id = mod_id | VENDOR_ID_MASK;
 
-                       mod = mesh_model_new(ele->idx, mod_id);
-                       if (!element_add_model(ele, mod))
-                               mesh_model_free(mod);
-               }
-               return;
+               if (l_queue_find(ele->models, match_model_id,
+                                               L_UINT_TO_PTR(id)))
+                       continue;
+
+               mod = mesh_model_new(ele->idx, id);
+
+               l_queue_insert(ele->models, mod, compare_model_id, NULL);
        }
+}
+
+static void get_vendor_models_from_properties(struct node_element *ele,
+                                       struct l_dbus_message_iter *property)
+{
+       struct l_dbus_message_iter ids;
+       uint16_t mod_id, vendor_id;
+
+       if (!ele->models)
+               ele->models = l_queue_new();
+
+       if (!l_dbus_message_iter_get_variant(property, "a(qq)", &ids))
+               return;
 
        /* Vendor defined models */
        while (l_dbus_message_iter_next_entry(&ids, &vendor_id, &mod_id)) {
                struct mesh_model *mod;
+               uint32_t id = mod_id | (vendor_id << 16);
+
+               if (l_queue_find(ele->models, match_model_id,
+                                                       L_UINT_TO_PTR(id)))
+                       continue;
+
+               mod = mesh_model_new(ele->idx, id);
 
-               mod = mesh_model_vendor_new(ele->idx, vendor_id, mod_id);
-               if (!element_add_model(ele, mod))
-                       mesh_model_free(mod);
+               l_queue_insert(ele->models, mod, compare_model_id, NULL);
        }
 }
 
@@ -1098,13 +1134,13 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
                }
 
                if (!mods && !strcmp(key, "Models")) {
-                       get_models_from_properties(ele, &var, false);
+                       get_sig_models_from_properties(ele, &var);
                        mods = true;
                        continue;
                }
 
                if (!vendor_mods && !strcmp(key, "VendorModels")) {
-                       get_models_from_properties(ele, &var, true);
+                       get_vendor_models_from_properties(ele, &var);
                        vendor_mods = true;
                        continue;
                }
@@ -1128,6 +1164,16 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
 
        ele->path = l_strdup(path);
 
+       /*
+        * Add configuration server model on the primary element.
+        * We allow the application not to specify the presense of
+        * the Configuration Server model, since it's implemented by the
+        * daemon. If the model is present in the application properties,
+        * the operation below will be a "no-op".
+        */
+       if (ele->idx == PRIMARY_ELE_IDX)
+               add_internal_model(node, CONFIG_SRV_MODEL, PRIMARY_ELE_IDX);
+
        return true;
 fail:
        l_free(ele);
@@ -1200,6 +1246,9 @@ static bool create_node_config(struct mesh_node *node, const uint8_t uuid[16])
        storage_dir = mesh_get_storage_dir();
        node->cfg = mesh_config_create(storage_dir, uuid, &db_node);
 
+       if (node->cfg)
+               init_storage_dir(node);
+
        /* Free temporarily allocated resources */
        entry = l_queue_get_entries(db_node.elements);
        for (; entry; entry = entry->next) {
@@ -1213,21 +1262,6 @@ static bool create_node_config(struct mesh_node *node, const uint8_t uuid[16])
        return node->cfg != NULL;
 }
 
-static void set_defaults(struct mesh_node *node)
-{
-       /* TODO: these values should come from mesh.conf */
-       node->lpn = MESH_MODE_UNSUPPORTED;
-       node->proxy = MESH_MODE_UNSUPPORTED;
-       node->friend = MESH_MODE_UNSUPPORTED;
-       node->beacon = MESH_MODE_DISABLED;
-       node->relay.mode = MESH_MODE_DISABLED;
-       node->ttl = DEFAULT_TTL;
-       node->seq_number = DEFAULT_SEQUENCE_NUMBER;
-
-       /* Add configuration server model on primary element */
-       add_internal_model(node, CONFIG_SRV_MODEL, PRIMARY_ELE_IDX);
-}
-
 static bool get_app_properties(struct mesh_node *node, const char *path,
                                        struct l_dbus_message_iter *properties)
 {
@@ -1339,29 +1373,6 @@ static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
        return true;
 }
 
-static bool init_storage_dir(struct mesh_node *node)
-{
-       char uuid[33];
-       char dir_name[PATH_MAX];
-
-       if (node->storage_dir)
-               return true;
-
-       if (!hex2str(node->uuid, 16, uuid, sizeof(uuid)))
-               return false;
-
-       snprintf(dir_name, PATH_MAX, "%s/%s", mesh_get_storage_dir(), uuid);
-
-       if (strlen(dir_name) >= PATH_MAX)
-               return false;
-
-       create_dir(dir_name);
-
-       node->storage_dir = l_strdup(dir_name);
-
-       return true;
-}
-
 static bool check_req_node(struct managed_obj_request *req)
 {
        uint8_t node_comp[MAX_MSG_LEN - 2];
@@ -1387,12 +1398,19 @@ static bool check_req_node(struct managed_obj_request *req)
        return true;
 }
 
-static struct mesh_node *attach_req_node(struct mesh_node *attach,
-                                                       struct mesh_node *node)
+static bool attach_req_node(struct mesh_node *attach, struct mesh_node *node)
 {
        const struct l_queue_entry *attach_entry;
        const struct l_queue_entry *node_entry;
 
+       attach->obj_path = node->obj_path;
+       node->obj_path = NULL;
+
+       if (!register_node_object(attach)) {
+               free_node_dbus_resources(attach);
+               return false;
+       }
+
        attach_entry = l_queue_get_entries(attach->elements);
        node_entry = l_queue_get_entries(node->elements);
 
@@ -1425,7 +1443,7 @@ static struct mesh_node *attach_req_node(struct mesh_node *attach,
 
        node_remove(node);
 
-       return attach;
+       return true;
 }
 
 static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
@@ -1434,9 +1452,12 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
        struct managed_obj_request *req = user_data;
        const char *path;
        struct mesh_node *node = req->node;
+       struct node_import *import;
        void *agent = NULL;
        bool have_app = false;
        unsigned int num_ele;
+       struct keyring_net_key net_key;
+       uint8_t dev_key[16];
 
        if (l_dbus_message_is_error(msg)) {
                l_error("Failed to get app's dbus objects");
@@ -1448,9 +1469,6 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
                goto fail;
        }
 
-       if (!node->elements)
-               node->elements = l_queue_new();
-
        while (l_dbus_message_iter_next_entry(&objects, &path, &interfaces)) {
                struct l_dbus_message_iter properties;
                const char *interface;
@@ -1509,7 +1527,6 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
                goto fail;
        }
 
-       set_defaults(node);
        num_ele = l_queue_length(node->elements);
 
        if (num_ele > MAX_ELE_COUNT)
@@ -1520,26 +1537,19 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
        if (!check_req_node(req))
                goto fail;
 
-       if (req->type == REQUEST_TYPE_ATTACH) {
-               struct l_dbus *bus = dbus_get_bus();
-
-               node = attach_req_node(req->attach, node);
-
-               if (!register_node_object(node))
+       switch (req->type) {
+       case REQUEST_TYPE_ATTACH:
+               if (!attach_req_node(req->attach, node))
                        goto fail;
 
-               /*
-                * TODO: For now always initialize directory for storing
-                * keyring info. Need to figure out what checks need
-                * to be performed to do this conditionally, i.e., presence of
-                * Provisioner interface, etc.
-                */
-               init_storage_dir(node);
+               req->attach->disc_watch = l_dbus_add_disconnect_watch(
+                                       dbus_get_bus(), req->attach->owner,
+                                       app_disc_cb, req->attach, NULL);
 
-               node->disc_watch = l_dbus_add_disconnect_watch(bus,
-                               node->owner, app_disc_cb, node, NULL);
+               req->ready_cb(req->pending_msg, MESH_ERROR_NONE, req->attach);
+               return;
 
-       } else if (req->type == REQUEST_TYPE_JOIN) {
+       case REQUEST_TYPE_JOIN:
                if (!node->agent) {
                        l_error("Interface %s not found",
                                                MESH_PROVISION_AGENT_INTERFACE);
@@ -1549,26 +1559,27 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
                if (!create_node_config(node, node->uuid))
                        goto fail;
 
-       } else if (req->type == REQUEST_TYPE_IMPORT) {
-               struct node_import *import = req->import;
+               req->join_ready_cb(node, node->agent);
+
+               return;
 
+       case REQUEST_TYPE_IMPORT:
                if (!create_node_config(node, node->uuid))
                        goto fail;
 
+               import = req->import;
                if (!add_local_node(node, import->unicast, import->flags.kr,
                                        import->flags.ivu,
                                        import->iv_index, import->dev_key,
                                        import->net_idx, import->net_key))
                        goto fail;
 
-               /* Initialize directory for storing keyring info */
-               init_storage_dir(node);
+               req->ready_cb(req->pending_msg, MESH_ERROR_NONE, node);
+               l_free(import);
 
-       } else {
-               /* Callback for create node request */
-               struct keyring_net_key net_key;
-               uint8_t dev_key[16];
+               return;
 
+       case REQUEST_TYPE_CREATE:
                if (!create_node_config(node, node->uuid))
                        goto fail;
 
@@ -1584,9 +1595,6 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
                                                net_key.old_key))
                        goto fail;
 
-               /* Initialize directory for storing keyring info */
-               init_storage_dir(node);
-
                if (!keyring_put_remote_dev_key(node, DEFAULT_NEW_UNICAST,
                                                node->num_ele, dev_key))
                        goto fail;
@@ -1594,14 +1602,12 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
                if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key))
                        goto fail;
 
-       }
-
-       if (req->type == REQUEST_TYPE_JOIN)
-               req->join_ready_cb(node, node->agent);
-       else
                req->ready_cb(req->pending_msg, MESH_ERROR_NONE, node);
+               return;
 
-       goto done;
+       default:
+               goto fail;
+       }
 
 fail:
        if (agent)
@@ -1616,7 +1622,6 @@ fail:
        else
                req->ready_cb(req->pending_msg, MESH_ERROR_FAILED, NULL);
 
-done:
        if (req->type == REQUEST_TYPE_IMPORT)
                l_free(req->import);
 }