diff options
author | Inga Stotland <inga.stotland@intel.com> | 2019-07-14 16:23:15 -0700 |
---|---|---|
committer | Brian Gix <brian.gix@intel.com> | 2019-07-15 14:47:36 -0700 |
commit | d8b2bef41b36971f567885cdefbf50d3269a9631 (patch) | |
tree | 956116a5ff5219cd6f0d90b13de1bf82ca9850c9 /mesh/mesh-config-json.c | |
parent | d1a76eb3f4d296fbd688edd9b3f2234b30459742 (diff) | |
download | bluez-d8b2bef41b36971f567885cdefbf50d3269a9631.tar.gz |
mesh: Confine dependency on json-c to mesh-config-json.c
This removes dependency on json-s/json.h header from everywhere
in the code except for mesh-config-json.c. The details about
node configuration storage format are obfuscated: a pointer
to an opaque mesh_config structure is stored with mesh_node and is
passed around to mae all the storage related operations.
Diffstat (limited to 'mesh/mesh-config-json.c')
-rw-r--r-- | mesh/mesh-config-json.c | 558 |
1 files changed, 381 insertions, 177 deletions
diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c index a0c3e27c0..4a9cf7c6e 100644 --- a/mesh/mesh-config-json.c +++ b/mesh/mesh-config-json.c @@ -22,9 +22,14 @@ #endif #define _GNU_SOURCE +#include <dirent.h> #include <errno.h> +#include <fcntl.h> +#include <ftw.h> +#include <libgen.h> #include <stdio.h> #include <string.h> +#include <unistd.h> #include <ell/ell.h> #include <json-c/json.h> @@ -35,6 +40,12 @@ #define CHECK_KEY_IDX_RANGE(x) (((x) >= 0) && ((x) <= 4095)) +struct mesh_config { + json_object *jnode; + char *node_path; + uint8_t uuid[16]; +}; + static bool get_int(json_object *jobj, const char *keyword, int *value) { json_object *jvalue; @@ -446,13 +457,18 @@ fail: return false; } -bool mesh_config_net_key_add(json_object *jobj, uint16_t idx, +bool mesh_config_net_key_add(struct mesh_config *cfg, uint16_t idx, const uint8_t key[16]) { - json_object *jarray = NULL, *jentry = NULL, *jstring; + json_object *jnode, *jarray = NULL, *jentry = NULL, *jstring; char buf[5]; - json_object_object_get_ex(jobj, "netKeys", &jarray); + if (!cfg) + return false; + + jnode = cfg->jnode; + + json_object_object_get_ex(jnode, "netKeys", &jarray); if (jarray) jentry = get_key_object(jarray, idx); @@ -481,7 +497,7 @@ bool mesh_config_net_key_add(json_object *jobj, uint16_t idx, jarray = json_object_new_array(); if (!jarray) goto fail; - json_object_object_add(jobj, "netKeys", jarray); + json_object_object_add(jnode, "netKeys", jarray); } json_object_array_add(jarray, jentry); @@ -494,13 +510,18 @@ fail: return false; } -bool mesh_config_net_key_update(json_object *jobj, uint16_t idx, +bool mesh_config_net_key_update(struct mesh_config *cfg, uint16_t idx, const uint8_t key[16]) { - json_object *jarray, *jentry, *jstring; + json_object *jnode, *jarray, *jentry, *jstring; const char *str; - if (!json_object_object_get_ex(jobj, "netKeys", &jarray)) + if (!cfg) + return false; + + jnode = cfg->jnode; + + if (!json_object_object_get_ex(jnode, "netKeys", &jarray)) return false; jentry = get_key_object(jarray, idx); @@ -525,11 +546,16 @@ bool mesh_config_net_key_update(json_object *jobj, uint16_t idx, return true; } -bool mesh_config_net_key_del(json_object *jobj, uint16_t idx) +bool mesh_config_net_key_del(struct mesh_config *cfg, uint16_t idx) { - json_object *jarray, *jarray_new; + json_object *jnode, *jarray, *jarray_new; - if (!json_object_object_get_ex(jobj, "netKeys", &jarray)) + if (!cfg) + return false; + + jnode = cfg->jnode; + + if (!json_object_object_get_ex(jnode, "netKeys", &jarray)) return true; /* Check if matching entry exists */ @@ -537,7 +563,7 @@ bool mesh_config_net_key_del(json_object *jobj, uint16_t idx) return true; if (json_object_array_length(jarray) == 1) { - json_object_object_del(jobj, "netKeys"); + json_object_object_del(jnode, "netKeys"); return true; } @@ -550,29 +576,40 @@ bool mesh_config_net_key_del(json_object *jobj, uint16_t idx) if (!jarray_new) return false; - json_object_object_del(jobj, "netKeys"); - json_object_object_add(jobj, "netKeys", jarray_new); + json_object_object_del(jnode, "netKeys"); + json_object_object_add(jnode, "netKeys", jarray_new); return true; } -bool mesh_config_write_device_key(json_object *jnode, uint8_t *key) +bool mesh_config_write_device_key(struct mesh_config *cfg, uint8_t *key) { - return add_key_value(jnode, "deviceKey", key); + if (!cfg) + return false; + + return add_key_value(cfg->jnode, "deviceKey", key); } -bool mesh_config_write_token(json_object *jnode, uint8_t *token) +bool mesh_config_write_token(struct mesh_config *cfg, uint8_t *token) { - return add_u64_value(jnode, "token", token); + if (!cfg) + return false; + + return add_u64_value(cfg->jnode, "token", token); } -bool mesh_config_app_key_add(json_object *jobj, uint16_t net_idx, +bool mesh_config_app_key_add(struct mesh_config *cfg, uint16_t net_idx, uint16_t app_idx, const uint8_t key[16]) { - json_object *jarray = NULL, *jentry = NULL, *jstring = NULL; + json_object *jnode, *jarray = NULL, *jentry = NULL, *jstring = NULL; char buf[5]; - json_object_object_get_ex(jobj, "appKeys", &jarray); + if (!cfg) + return false; + + jnode = cfg->jnode; + + json_object_object_get_ex(jnode, "appKeys", &jarray); if (jarray) jentry = get_key_object(jarray, app_idx); @@ -605,7 +642,7 @@ bool mesh_config_app_key_add(json_object *jobj, uint16_t net_idx, jarray = json_object_new_array(); if (!jarray) goto fail; - json_object_object_add(jobj, "appKeys", jarray); + json_object_object_add(jnode, "appKeys", jarray); } json_object_array_add(jarray, jentry); @@ -619,13 +656,18 @@ fail: return false; } -bool mesh_config_app_key_update(json_object *jobj, uint16_t app_idx, +bool mesh_config_app_key_update(struct mesh_config *cfg, uint16_t app_idx, const uint8_t key[16]) { - json_object *jarray, *jentry = NULL, *jstring = NULL; + json_object *jnode, *jarray, *jentry = NULL, *jstring = NULL; const char *str; - if (!json_object_object_get_ex(jobj, "appKeys", &jarray)) + if (!cfg) + return false; + + jnode = cfg->jnode; + + if (!json_object_object_get_ex(jnode, "appKeys", &jarray)) return false; /* The key entry should exist if the key is updated */ @@ -644,11 +686,17 @@ bool mesh_config_app_key_update(json_object *jobj, uint16_t app_idx, return add_key_value(jentry, "key", key); } -bool mesh_config_app_key_del(json_object *jobj, uint16_t net_idx, uint16_t idx) +bool mesh_config_app_key_del(struct mesh_config *cfg, uint16_t net_idx, + uint16_t idx) { - json_object *jarray, *jarray_new; + json_object *jnode, *jarray, *jarray_new; - if (!json_object_object_get_ex(jobj, "appKeys", &jarray)) + if (!cfg) + return false; + + jnode = cfg->jnode; + + if (!json_object_object_get_ex(jnode, "appKeys", &jarray)) return true; /* Check if matching entry exists */ @@ -656,7 +704,7 @@ bool mesh_config_app_key_del(json_object *jobj, uint16_t net_idx, uint16_t idx) return true; if (json_object_array_length(jarray) == 1) { - json_object_object_del(jobj, "appKeys"); + json_object_object_del(jnode, "appKeys"); return true; } @@ -669,19 +717,24 @@ bool mesh_config_app_key_del(json_object *jobj, uint16_t net_idx, uint16_t idx) if (!jarray_new) return false; - json_object_object_del(jobj, "appKeys"); - json_object_object_add(jobj, "appKeys", jarray_new); + json_object_object_del(jnode, "appKeys"); + json_object_object_add(jnode, "appKeys", jarray_new); return true; } -bool mesh_config_model_binding_add(json_object *jnode, uint8_t ele_idx, +bool mesh_config_model_binding_add(struct mesh_config *cfg, uint8_t ele_idx, bool vendor, uint32_t mod_id, uint16_t app_idx) { - json_object *jmodel, *jstring, *jarray = NULL; + json_object *jnode, *jmodel, *jstring, *jarray = NULL; char buf[5]; + if (!cfg) + return false; + + jnode = cfg->jnode; + jmodel = get_element_model(jnode, ele_idx, mod_id, vendor); if (!jmodel) return false; @@ -710,13 +763,18 @@ bool mesh_config_model_binding_add(json_object *jnode, uint8_t ele_idx, return true; } -bool mesh_config_model_binding_del(json_object *jnode, uint8_t ele_idx, +bool mesh_config_model_binding_del(struct mesh_config *cfg, uint8_t ele_idx, bool vendor, uint32_t mod_id, uint16_t app_idx) { - json_object *jmodel, *jarray, *jarray_new; + json_object *jnode, *jmodel, *jarray, *jarray_new; char buf[5]; + if (!cfg) + return false; + + jnode = cfg->jnode; + jmodel = get_element_model(jnode, ele_idx, mod_id, vendor); if (!jmodel) return false; @@ -1189,45 +1247,32 @@ static bool read_net_transmit(json_object *jobj, struct mesh_config_node *node) return true; } -bool mesh_config_read_node(json_object *jnode, mesh_config_node_cb cb, - void *user_data) +static bool read_node(json_object *jnode, struct mesh_config_node *node) { - struct mesh_config_node node; json_object *jvalue; char *str; - bool result = false; - - if (!jnode) - return false; - - if (!cb) { - l_info("Node read callback is required"); - return false; - } - memset(&node, 0, sizeof(node)); - - if (!read_iv_index(jnode, &node.iv_index, &node.iv_update)) { + if (!read_iv_index(jnode, &node->iv_index, &node->iv_update)) { l_info("Failed to read IV index"); return false; } - if (!read_token(jnode, node.token)) { + if (!read_token(jnode, node->token)) { l_info("Failed to read node token"); return false; } - if (!read_device_key(jnode, node.dev_key)) { + if (!read_device_key(jnode, node->dev_key)) { l_info("Failed to read node device key"); return false; } - if (!parse_composition(jnode, &node)) { + if (!parse_composition(jnode, node)) { l_info("Failed to parse local node composition"); return false; } - parse_features(jnode, &node); + parse_features(jnode, node); if (!json_object_object_get_ex(jnode, "unicastAddress", &jvalue)) { l_info("Bad config: Unicast address must be present"); @@ -1235,7 +1280,7 @@ bool mesh_config_read_node(json_object *jnode, mesh_config_node_cb cb, } str = (char *)json_object_get_string(jvalue); - if (sscanf(str, "%04hx", &node.unicast) != 1) + if (sscanf(str, "%04hx", &node->unicast) != 1) return false; if (json_object_object_get_ex(jnode, "defaultTTL", &jvalue)) { @@ -1243,55 +1288,45 @@ bool mesh_config_read_node(json_object *jnode, mesh_config_node_cb cb, if (ttl < 0 || ttl == 1 || ttl > DEFAULT_TTL) return false; - node.ttl = (uint8_t) ttl; + node->ttl = (uint8_t) ttl; } if (json_object_object_get_ex(jnode, "sequenceNumber", &jvalue)) - node.seq_number = json_object_get_int(jvalue); + node->seq_number = json_object_get_int(jvalue); /* Check for required "elements" property */ if (!json_object_object_get_ex(jnode, "elements", &jvalue)) return false; - if (!read_net_transmit(jnode, &node)) { + if (!read_net_transmit(jnode, node)) { l_info("Failed to read node net transmit parameters"); return false; } - if (!read_net_keys(jnode, &node)) { + if (!read_net_keys(jnode, node)) { l_info("Failed to read net keys"); - goto done; + return false; } - if (!read_app_keys(jnode, &node)) { + if (!read_app_keys(jnode, node)) { l_info("Failed to read app keys"); - goto done; + return false; } - if (!parse_elements(jvalue, &node)) { + if (!parse_elements(jvalue, node)) { l_info("Failed to parse elements"); - goto done; + return false; } - result = cb(&node, user_data); - -done: - l_free(node.net_transmit); - l_queue_destroy(node.netkeys, l_free); - l_queue_destroy(node.netkeys, l_free); - - return result; + return true; } -bool mesh_config_write_uint16_hex(json_object *jobj, const char *desc, +static bool write_uint16_hex(json_object *jobj, const char *desc, uint16_t value) { json_object *jstring; char buf[5]; - if (!jobj) - return false; - snprintf(buf, 5, "%4.4x", value); jstring = json_object_new_string(buf); if (!jstring) @@ -1301,15 +1336,21 @@ bool mesh_config_write_uint16_hex(json_object *jobj, const char *desc, return true; } -bool mesh_config_write_uint32_hex(json_object *jobj, const char *desc, +bool mesh_config_write_uint16_hex(struct mesh_config *cfg, const char *desc, + uint16_t value) +{ + if (!cfg) + return false; + + return write_uint16_hex(cfg->jnode, desc, value); +} + +static bool write_uint32_hex(json_object *jobj, const char *desc, uint32_t value) { json_object *jstring; char buf[9]; - if (!jobj) - return false; - snprintf(buf, 9, "%8.8x", value); jstring = json_object_new_string(buf); if (!jstring) @@ -1319,13 +1360,19 @@ bool mesh_config_write_uint32_hex(json_object *jobj, const char *desc, return true; } -bool mesh_config_write_int(json_object *jobj, const char *keyword, int value) +bool mesh_config_write_uint32_hex(struct mesh_config *cfg, const char *desc, + uint32_t value) { - json_object *jvalue; - - if (!jobj) + if (!cfg) return false; + return write_uint32_hex(cfg->jnode, desc, value); +} + +static bool write_int(json_object *jobj, const char *keyword, int value) +{ + json_object *jvalue; + json_object_object_del(jobj, keyword); jvalue = json_object_new_int(value); @@ -1336,20 +1383,32 @@ bool mesh_config_write_int(json_object *jobj, const char *keyword, int value) return true; } -bool mesh_config_write_bool(json_object *jobj, const char *keyword, bool value) +bool mesh_config_write_int(struct mesh_config *cfg, const char *keyword, + int value) { - json_object *jvalue; + if (!cfg) + return false; + + return write_int(cfg->jnode, keyword, value); +} - if (!jobj) +bool mesh_config_write_bool(struct mesh_config *cfg, const char *keyword, + bool value) +{ + json_object *jnode, *jvalue; + + if (!cfg) return false; - json_object_object_del(jobj, keyword); + jnode = cfg->jnode; + + json_object_object_del(jnode, keyword); jvalue = json_object_new_boolean(value); if (!jvalue) return false; - json_object_object_add(jobj, keyword, jvalue); + json_object_object_add(jnode, keyword, jvalue); return true; } @@ -1365,13 +1424,10 @@ static const char *mode_to_string(int mode) } } -bool mesh_config_write_mode(json_object *jobj, const char *keyword, int value) +static bool write_mode(json_object *jobj, const char *keyword, int value) { json_object *jstring; - if (!jobj) - return false; - jstring = json_object_new_string(mode_to_string(value)); if (!jstring) @@ -1382,30 +1438,36 @@ bool mesh_config_write_mode(json_object *jobj, const char *keyword, int value) return true; } -bool mesh_config_write_relay_mode(json_object *jnode, uint8_t mode, +bool mesh_config_write_mode(struct mesh_config *cfg, const char *keyword, + int value) +{ + if (!cfg) + return false; + + return write_mode(cfg->jnode, keyword, value); +} + +static bool write_relay_mode(json_object *jobj, uint8_t mode, uint8_t count, uint16_t interval) { json_object *jrelay; - if (!jnode) - return false; - - json_object_object_del(jnode, "relay"); + json_object_object_del(jobj, "relay"); jrelay = json_object_new_object(); if (!jrelay) return false; - if (!mesh_config_write_mode(jrelay, "mode", mode)) + if (!write_mode(jrelay, "mode", mode)) goto fail; - if (!mesh_config_write_int(jrelay, "count", count)) + if (!write_int(jrelay, "count", count)) goto fail; - if (!mesh_config_write_int(jrelay, "interval", interval)) + if (!write_int(jrelay, "interval", interval)) goto fail; - json_object_object_add(jnode, "relay", jrelay); + json_object_object_add(jobj, "relay", jrelay); return true; fail: @@ -1413,27 +1475,38 @@ fail: return false; } -bool mesh_config_write_net_transmit(json_object *jobj, uint8_t cnt, +bool mesh_config_write_relay_mode(struct mesh_config *cfg, uint8_t mode, + uint8_t count, uint16_t interval) +{ + + if (!cfg) + return false; + + return write_relay_mode(cfg->jnode, mode, count, interval); +} + +bool mesh_config_write_net_transmit(struct mesh_config *cfg, uint8_t cnt, uint16_t interval) { - json_object *jretransmit; + json_object *jnode, *jretransmit; - if (!jobj) + if (!cfg) return false; + jnode = cfg->jnode; - json_object_object_del(jobj, "retransmit"); + json_object_object_del(jnode, "retransmit"); jretransmit = json_object_new_object(); if (jretransmit) return false; - if (!mesh_config_write_int(jretransmit, "count", cnt)) + if (!write_int(jretransmit, "count", cnt)) goto fail; - if (!mesh_config_write_int(jretransmit, "interval", interval)) + if (!write_int(jretransmit, "interval", interval)) goto fail; - json_object_object_add(jobj, "retransmit", jretransmit); + json_object_object_add(jnode, "retransmit", jretransmit); return true; fail: @@ -1442,28 +1515,26 @@ fail: } -bool mesh_config_write_iv_index(json_object *jobj, uint32_t idx, bool update) +bool mesh_config_write_iv_index(struct mesh_config *cfg, uint32_t idx, + bool update) { + json_object *jnode; int tmp = update ? 1 : 0; - if (!jobj) + if (!cfg) return false; - if (!mesh_config_write_int(jobj, "IVindex", idx)) + jnode = cfg->jnode; + + if (!write_int(jnode, "IVindex", idx)) return false; - if (!mesh_config_write_int(jobj, "IVupdate", tmp)) + if (!write_int(jnode, "IVupdate", tmp)) return false; return true; } -void mesh_config_remove_property(json_object *jobj, const char *desc) -{ - if (jobj) - json_object_object_del(jobj, desc); -} - static void add_model(void *a, void *b) { struct mesh_config_model *mod = a; @@ -1474,55 +1545,59 @@ static void add_model(void *a, void *b) return; if (!mod->vendor) - mesh_config_write_uint16_hex(jmodel, "modelId", + write_uint16_hex(jmodel, "modelId", (uint16_t) mod->id); else - mesh_config_write_uint32_hex(jmodel, "modelId", mod->id); + write_uint32_hex(jmodel, "modelId", mod->id); json_object_array_add(jmodels, jmodel); } /* Add unprovisioned node (local) */ -bool mesh_config_add_node(json_object *jnode, struct mesh_config_node *node) +struct mesh_config *mesh_config_create(const char *cfg_path, + const uint8_t uuid[16], + struct mesh_config_node *node) { struct mesh_config_modes *modes = &node->modes; const struct l_queue_entry *entry; - json_object *jelems; + json_object *jnode, *jelems; + struct mesh_config *cfg; - if (!jnode) - return false; + if (!cfg_path || !node) + return NULL; + + jnode = json_object_new_object(); /* CID, PID, VID, crpl */ - if (!mesh_config_write_uint16_hex(jnode, "cid", node->cid)) - return false; + if (!write_uint16_hex(jnode, "cid", node->cid)) + return NULL; - if (!mesh_config_write_uint16_hex(jnode, "pid", node->pid)) - return false; + if (!write_uint16_hex(jnode, "pid", node->pid)) + return NULL; - if (!mesh_config_write_uint16_hex(jnode, "vid", node->vid)) - return false; + if (!write_uint16_hex(jnode, "vid", node->vid)) + return NULL; - if (!mesh_config_write_uint16_hex(jnode, "crpl", node->crpl)) - return false; + if (!write_uint16_hex(jnode, "crpl", node->crpl)) + return NULL; /* Features: relay, LPN, friend, proxy*/ - if (!mesh_config_write_relay_mode(jnode, modes->relay.state, - modes->relay.cnt, - modes->relay.interval)) - return false; + if (!write_relay_mode(jnode, modes->relay.state, + modes->relay.cnt, modes->relay.interval)) + return NULL; - if (!mesh_config_write_mode(jnode, "lowPower", modes->lpn)) - return false; + if (!write_mode(jnode, "lowPower", modes->lpn)) + return NULL; - if (!mesh_config_write_mode(jnode, "friend", modes->friend)) - return false; + if (!write_mode(jnode, "friend", modes->friend)) + return NULL; - if (!mesh_config_write_mode(jnode, "proxy", modes->proxy)) - return false; + if (!write_mode(jnode, "proxy", modes->proxy)) + return NULL; /* Beaconing state */ - if (!mesh_config_write_mode(jnode, "beacon", modes->beacon)) - return false; + if (!write_mode(jnode, "beacon", modes->beacon)) + return NULL; /* Sequence number */ json_object_object_add(jnode, "sequenceNumber", @@ -1535,7 +1610,7 @@ bool mesh_config_add_node(json_object *jnode, struct mesh_config_node *node) /* Elements */ jelems = json_object_new_array(); if (!jelems) - return false; + return NULL; entry = l_queue_get_entries(node->elements); @@ -1547,12 +1622,11 @@ bool mesh_config_add_node(json_object *jnode, struct mesh_config_node *node) if (!jelement) { json_object_put(jelems); - return false; + return NULL; } - mesh_config_write_int(jelement, "elementIndex", ele->index); - mesh_config_write_uint16_hex(jelement, "location", - ele->location); + write_int(jelement, "elementIndex", ele->index); + write_uint16_hex(jelement, "location", ele->location); json_object_array_add(jelems, jelement); /* Models */ @@ -1562,7 +1636,7 @@ bool mesh_config_add_node(json_object *jnode, struct mesh_config_node *node) jmodels = json_object_new_array(); if (!jmodels) { json_object_put(jelems); - return false; + return NULL; } json_object_object_add(jelement, "models", jmodels); @@ -1571,7 +1645,13 @@ bool mesh_config_add_node(json_object *jnode, struct mesh_config_node *node) json_object_object_add(jnode, "elements", jelems); - return true; + cfg = l_new(struct mesh_config, 1); + + cfg->jnode = jnode; + memcpy(cfg->uuid, uuid, 16); + cfg->node_path = l_strdup(cfg_path); + + return cfg; } static void finish_key_refresh(json_object *jobj, uint16_t net_idx) @@ -1605,15 +1685,17 @@ static void finish_key_refresh(json_object *jobj, uint16_t net_idx) } -bool mesh_config_net_key_set_phase(json_object *jobj, uint16_t idx, +bool mesh_config_net_key_set_phase(struct mesh_config *cfg, uint16_t idx, uint8_t phase) { - json_object *jarray, *jentry = NULL; + json_object *jnode, *jarray, *jentry = NULL; - if (!jobj) + if (!cfg) return false; - if (json_object_object_get_ex(jobj, "netKeys", &jarray)) + jnode = cfg->jnode; + + if (json_object_object_get_ex(jnode, "netKeys", &jarray)) jentry = get_key_object(jarray, idx); if (!jentry) @@ -1625,23 +1707,25 @@ bool mesh_config_net_key_set_phase(json_object *jobj, uint16_t idx, if (phase == KEY_REFRESH_PHASE_NONE) { json_object_object_del(jentry, "oldKey"); - finish_key_refresh(jobj, idx); + finish_key_refresh(jnode, idx); } return true; } -bool mesh_config_model_pub_add(json_object *jnode, uint16_t addr, +bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t addr, uint32_t mod_id, bool vendor, struct mesh_config_pub *pub) { - json_object *jmodel, *jpub, *jretransmit; + json_object *jnode, *jmodel, *jpub, *jretransmit; bool res; int ele_idx; - if (!jnode) + if (!cfg) return false; + jnode = cfg->jnode; + ele_idx = get_element_index(jnode, addr); if (ele_idx < 0) return false; @@ -1659,21 +1743,21 @@ bool mesh_config_model_pub_add(json_object *jnode, uint16_t addr, if (pub->virt) res = add_key_value(jpub, "address", pub->virt_addr); else - res = mesh_config_write_uint16_hex(jpub, "address", pub->addr); + res = write_uint16_hex(jpub, "address", pub->addr); if (!res) goto fail; - if (!mesh_config_write_uint16_hex(jpub, "index", pub->idx)) + if (!write_uint16_hex(jpub, "index", pub->idx)) goto fail; - if (!mesh_config_write_int(jpub, "ttl", pub->ttl)) + if (!write_int(jpub, "ttl", pub->ttl)) goto fail; - if (!mesh_config_write_int(jpub, "period", pub->period)) + if (!write_int(jpub, "period", pub->period)) goto fail; - if (!mesh_config_write_int(jpub, "credentials", + if (!write_int(jpub, "credentials", pub->credential ? 1 : 0)) goto fail; @@ -1681,10 +1765,10 @@ bool mesh_config_model_pub_add(json_object *jnode, uint16_t addr, if (!jretransmit) goto fail; - if (!mesh_config_write_int(jretransmit, "count", pub->count)) + if (!write_int(jretransmit, "count", pub->count)) goto fail; - if (!mesh_config_write_int(jretransmit, "interval", pub->interval)) + if (!write_int(jretransmit, "interval", pub->interval)) goto fail; json_object_object_add(jpub, "retransmit", jretransmit); @@ -1715,26 +1799,29 @@ static bool delete_model_property(json_object *jnode, uint16_t addr, return true; } -bool mesh_config_model_pub_del(json_object *jnode, uint16_t addr, +bool mesh_config_model_pub_del(struct mesh_config *cfg, uint16_t addr, uint32_t mod_id, bool vendor) { - if (!jnode) + if (!cfg) return false; - return delete_model_property(jnode, addr, mod_id, vendor, "publish"); + return delete_model_property(cfg->jnode, addr, mod_id, vendor, + "publish"); } -bool mesh_config_model_sub_add(json_object *jnode, uint16_t addr, +bool mesh_config_model_sub_add(struct mesh_config *cfg, uint16_t addr, uint32_t mod_id, bool vendor, struct mesh_config_sub *sub) { - json_object *jmodel, *jstring, *jarray = NULL; + json_object *jnode, *jmodel, *jstring, *jarray = NULL; int ele_idx, len; char buf[33]; - if (!jnode) + if (!cfg) return false; + jnode = cfg->jnode; + ele_idx = get_element_index(jnode, addr); if (ele_idx < 0) return false; @@ -1773,17 +1860,19 @@ bool mesh_config_model_sub_add(json_object *jnode, uint16_t addr, return true; } -bool mesh_config_model_sub_del(json_object *jnode, uint16_t addr, +bool mesh_config_model_sub_del(struct mesh_config *cfg, uint16_t addr, uint32_t mod_id, bool vendor, struct mesh_config_sub *sub) { - json_object *jmodel, *jarray, *jarray_new; + json_object *jnode, *jmodel, *jarray, *jarray_new; char buf[33]; int len, ele_idx; - if (!jnode) + if (!cfg) return false; + jnode = cfg->jnode; + ele_idx = get_element_index(jnode, addr); if (ele_idx < 0) return false; @@ -1826,11 +1915,126 @@ bool mesh_config_model_sub_del(json_object *jnode, uint16_t addr, return true; } -bool mesh_config_model_sub_del_all(json_object *jnode, uint16_t addr, +bool mesh_config_model_sub_del_all(struct mesh_config *cfg, uint16_t addr, uint32_t mod_id, bool vendor) { + if (!cfg) + return false; + + return delete_model_property(cfg->jnode, addr, mod_id, vendor, + "subscribe"); +} + +bool mesh_config_load_node(const char *cfg_path, const uint8_t uuid[16], + mesh_config_node_cb cb, void *user_data) +{ + int fd; + char *str; + struct stat st; + ssize_t sz; + bool result = false; + json_object *jnode; + struct mesh_config_node node; + + if (!cb) { + l_info("Node read callback is required"); + return false; + } + + l_info("Loading configuration from %s", cfg_path); + + fd = open(cfg_path, O_RDONLY); + if (fd < 0) + return false; + + if (fstat(fd, &st) == -1) { + close(fd); + return false; + } + + str = (char *) l_new(char, st.st_size + 1); + if (!str) { + close(fd); + return false; + } + + sz = read(fd, str, st.st_size); + if (sz != st.st_size) { + l_error("Failed to read configuration file %s", cfg_path); + goto done; + } + + jnode = json_tokener_parse(str); if (!jnode) + goto done; + + memset(&node, 0, sizeof(node)); + result = read_node(jnode, &node); + + if (result) { + struct mesh_config *cfg = l_new(struct mesh_config, 1); + + cfg->jnode = jnode; + memcpy(cfg->uuid, uuid, 16); + cfg->node_path = l_strdup(cfg_path); + result = cb(&node, uuid, cfg, user_data); + + if (!result) { + l_free(cfg->node_path); + l_free(cfg); + } + } + + /* Done with the node: free resources */ + l_free(node.net_transmit); + l_queue_destroy(node.netkeys, l_free); + l_queue_destroy(node.appkeys, l_free); + + if (!result) + json_object_put(jnode); + +done: + close(fd); + if (str) + l_free(str); + + return result; +} + +void mesh_config_release(struct mesh_config *cfg) +{ + if (!cfg) + return; + + l_free(cfg->node_path); + json_object_put(cfg->jnode); + l_free(cfg); +} + +bool mesh_config_save_config(struct mesh_config *cfg, const char *fname) +{ + FILE *outfile; + const char *str; + bool result = false; + + if (!cfg) + return false; + + outfile = fopen(fname, "w"); + if (!outfile) { + l_error("Failed to save configuration to %s", fname); return false; + } + + str = json_object_to_json_string_ext(cfg->jnode, + JSON_C_TO_STRING_PRETTY); + + if (fwrite(str, sizeof(char), strlen(str), outfile) < strlen(str)) + l_warn("Incomplete write of mesh configuration"); + else + result = true; + + fclose(outfile); - return delete_model_property(jnode, addr, mod_id, vendor, "subscribe"); + return result; } |