2019-07-05 15:23:20

by Jakub Witowski

[permalink] [raw]
Subject: [PATCH BlueZ v3 1/3] mesh: Add ImportLocalNode api documentation

This updates the mesh-api.txt with new ImportLocalNode() API.
---
doc/mesh-api.txt | 104 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 93 insertions(+), 11 deletions(-)

diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
index 893a1a6c0..f2ba164a9 100644
--- a/doc/mesh-api.txt
+++ b/doc/mesh-api.txt
@@ -151,16 +151,36 @@ Methods:
org.bluez.mesh.Error.InvalidArguments
org.bluez.mesh.Error.AlreadyExists,

- uint64 token ImportLocalNode(string json_data)
+ uint64 token ImportLocalNode(object app_root, array{byte}[16] uuid,
+ string data_type, array{byte} import_data)

This method creates a local mesh node based on node
configuration that has been generated outside bluetooth-meshd.

- The json_data parameter is a full JSON representation of a node
- configuration file. The format must conform to the schema
- defined in "Mesh Node Configuration Schema" section. Any
- included token will be ignored in favor of a locally generated
- token value.
+ The app_root parameter is a D-Bus object root path of the
+ application that implements org.bluez.mesh.Application1
+ interface, and a org.bluez.mesh.Provisioner1 interface.
+
+ The data_type parameter defines the import_data type. Supported
+ data_type parameters:
+ - “json”
+
+ The import_data parameter can be either:
+ - Simplified representation of node configuration with
+ provisioning data only
+ - Full representation of node configuration with both
+ provisioning and composition data
+
+ sequenceNumber parameter int the import_data is optional.
+
+ The format must conform to the schema defined in
+ "Mesh Node Configuration Examples" section. Any included token will
+ be ignored in favor of a locally generated token value. If
+ import_data contains composition data (determined by the presence of
+ Elements) it is validated against composition data provided by
+ the application. Otherwise, new node is created based on
+ composition data provided by the application using provisioning data
+ from import_data parameter.

The returned token must be preserved by the application in
order to authenticate itself to the mesh daemon and attach to
@@ -173,8 +193,8 @@ Methods:

PossibleErrors:
org.bluez.mesh.Error.InvalidArguments,
- org.bluez.mesh.Error.AlreadyExists
- org.bluez.mesh.Error.NotFound,
+ org.bluez.mesh.Error.AlreadyExists,
+ org.bluez.mesh.Error.NotSupported,
org.bluez.mesh.Error.Failed

Mesh Node Hierarchy
@@ -1061,6 +1081,68 @@ Properties:
Uniform Resource Identifier points to out-of-band (OOB)
information (e.g., a public key)

-Mesh Node Configuration Schema
-==============================
-<TBD>
+Mesh Node Configuration Examples
+================================
+Example of Json format for ImportLocalNode():
+
+ Import simplified node operation:
+ {
+ "IVindex":0,
+ "IVupdate":0,
+ "unicastAddress":"0012",
+ "deviceKey":"7daa45cd1e9e11a4b86eeef7d01efa11",
+ "sequenceNumber":15
+ "netKeys":[
+ {
+ "index":"0000",
+ "key":"2ddfef86d67144c394428ea3078f86f9",
+ "keyRefresh":0
+ }],
+ }
+
+ Import full node operation:
+ {
+ "cid":"fee5",
+ "pid":"0042",
+ "vid":"0001",
+ "crpl":"2710",
+ "relay":{
+ "mode":"disabled",
+ "count":0,
+ "interval":0
+ },
+ "lowPower":"unsupported",
+ "friend":"unsupported",
+ "proxy":"unsupported",
+ "beacon":"disabled",
+ "defaultTTL":255,
+ "elements":[
+ {
+ "elementIndex":0,
+ "location":"002a",
+ "models":[
+ {
+ "modelId":"0008",
+ "bind":[
+ "0000"]
+ }]
+ }],
+ "IVindex":0,
+ "IVupdate":0,
+ "unicastAddress":"0010",
+ "token":"bba7c60afaa85fc1",
+ "deviceKey":"56325fd145f3d5eee1b82136dc3e1454",
+ "netKeys":[
+ {
+ "index":"0000",
+ "key":"2ddfef86d67144c394428ea3078f86f9",
+ "keyRefresh":0
+ }],
+ "appKeys":[
+ {
+ "index":"0000",
+ "boundNetKey":"0000",
+ "key":"43886b02ca4343beaae26dc4b6773ba4"
+ }],
+ "sequenceNumber":15
+ }
--
2.20.1


2019-07-05 15:23:20

by Jakub Witowski

[permalink] [raw]
Subject: [PATCH BlueZ v3 2/3] mesh: Added ImportLocalNode call with its API

This implements ImportLocalNode() method on org.bluez.mesh.Network1
interface. Invoking this method creates a self-provisioned node based on
passed JSON definition. Also full functionality of import local node has
been implemented
---
mesh/mesh.c | 90 +++++++++++++++++--
mesh/node.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++----
mesh/node.h | 2 +
3 files changed, 317 insertions(+), 22 deletions(-)

diff --git a/mesh/mesh.c b/mesh/mesh.c
index 26acfd4dc..b3def7817 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -22,6 +22,8 @@
#endif

#define _GNU_SOURCE
+#include <json-c/json.h>
+#include <string.h>
#include <ell/ell.h>

#include "mesh/mesh-io.h"
@@ -60,7 +62,7 @@ struct bt_mesh {
uint8_t max_filters;
};

-struct join_data{
+struct join_data {
struct l_dbus_message *msg;
struct mesh_agent *agent;
const char *sender;
@@ -70,6 +72,10 @@ struct join_data{
uint8_t *uuid;
};

+static const char * const supported_import_data_types[] = {
+ "json"
+};
+
static struct bt_mesh mesh;

/* We allow only one outstanding Join request */
@@ -365,8 +371,8 @@ static void node_init_cb(struct mesh_node *node, struct mesh_agent *agent)

if (!acceptor_start(num_ele, join_pending->uuid, mesh.algorithms,
mesh.prov_timeout, agent, prov_complete_cb,
- &mesh))
- {
+ &mesh)) {
+
reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
"Failed to start provisioning acceptor");
goto fail;
@@ -383,6 +389,18 @@ fail:
free_pending_join_call(true);
}

+static bool validate_data_type(const char *data_type)
+{
+ uint8_t len = sizeof(supported_import_data_types) /
+ sizeof(supported_import_data_types[0]);
+
+ for (uint8_t idx = 0; idx < len; idx++) {
+ if (strcmp(data_type, supported_import_data_types[idx]) == 0)
+ return true;
+ }
+ return false;
+}
+
static struct l_dbus_message *join_network_call(struct l_dbus *dbus,
struct l_dbus_message *msg,
void *user_data)
@@ -536,7 +554,7 @@ static struct l_dbus_message *leave_call(struct l_dbus *dbus,
return l_dbus_message_new_method_return(msg);
}

-static void create_network_ready_cb(void *user_data, int status,
+static void create_node_ready_cb(void *user_data, int status,
struct mesh_node *node)
{
struct l_dbus_message *reply;
@@ -593,12 +611,67 @@ static struct l_dbus_message *create_network_call(struct l_dbus *dbus,

l_queue_push_tail(pending_queue, pending_msg);

- node_create(app_path, sender, uuid, create_network_ready_cb,
+ node_create(app_path, sender, uuid, create_node_ready_cb,
pending_msg);

return NULL;
}

+static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
+ struct l_dbus_message *msg,
+ void *user_data)
+{
+ const char *app_path, *sender;
+ struct l_dbus_message *pending_msg;
+ struct l_dbus_message_iter iter_uuid, iter_import_data;
+ const char *data_type, *import_data;
+ uint8_t *uuid;
+ uint32_t n;
+ struct json_object *jnode;
+
+ l_debug("Import local node request");
+
+ if (!l_dbus_message_get_arguments(msg, "oaysay", &app_path, &iter_uuid,
+ &data_type, &iter_import_data))
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
+
+ if (!validate_data_type(data_type))
+ return dbus_error(msg, MESH_ERROR_NOT_IMPLEMENTED,
+ "Unsupported data type");
+
+ if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
+ n != 16)
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Bad dev UUID");
+
+ if (node_find_by_uuid(uuid))
+ return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
+ "Node already exists");
+
+ if (!l_dbus_message_iter_get_fixed_array(&iter_import_data,
+ &import_data, &n))
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+ "Bad import_data");
+
+ jnode = json_tokener_parse(import_data);
+
+ sender = l_dbus_message_get_sender(msg);
+ pending_msg = l_dbus_message_ref(msg);
+
+ if (!pending_queue)
+ pending_queue = l_queue_new();
+
+ l_queue_push_tail(pending_queue, pending_msg);
+
+ if (!node_import(app_path, sender, jnode, uuid, create_node_ready_cb,
+ pending_msg)) {
+ l_dbus_message_unref(msg);
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+ "Node import failed");
+ }
+
+ return NULL;
+}
+
static void setup_network_interface(struct l_dbus_interface *iface)
{
l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
@@ -612,8 +685,15 @@ static void setup_network_interface(struct l_dbus_interface *iface)

l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
"token");
+
l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
"t", "oay", "token", "app", "uuid");
+
+ l_dbus_interface_method(iface, "ImportLocalNode", 0,
+ import_local_node_call,
+ "t", "oaysay", "token",
+ "app", "uuid", "data_type",
+ "import_data");
}

bool mesh_dbus_init(struct l_dbus *dbus)
diff --git a/mesh/node.c b/mesh/node.c
index 1f781cfe9..00c3270fd 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -27,6 +27,7 @@

#include <ell/ell.h>
#include <json-c/json.h>
+#include <stdio.h>

#include "mesh/mesh-defs.h"
#include "mesh/mesh.h"
@@ -57,9 +58,12 @@
#define DEFAULT_CRPL 10
#define DEFAULT_SEQUENCE_NUMBER 0

-#define REQUEST_TYPE_JOIN 0
-#define REQUEST_TYPE_ATTACH 1
-#define REQUEST_TYPE_CREATE 2
+enum request_type {
+ REQUEST_TYPE_JOIN = 0,
+ REQUEST_TYPE_ATTACH,
+ REQUEST_TYPE_CREATE,
+ REQUEST_TYPE_IMPORT,
+};

struct node_element {
char *path;
@@ -110,7 +114,19 @@ struct managed_obj_request {
void *data;
void *cb;
void *user_data;
- uint8_t type;
+ enum request_type type;
+};
+
+struct node_import_request {
+ uint8_t uuid[16];
+ uint8_t dev_key[16];
+ uint8_t net_key[16];
+ uint16_t net_idx;
+ uint16_t unicast;
+ uint32_t iv_idx;
+ bool iv_update;
+ uint32_t sequence;
+ void *user_data;
};

static struct l_queue *nodes;
@@ -870,7 +886,7 @@ element_done:
#define MIN_COMPOSITION_LEN 16

bool node_parse_composition(struct mesh_node *node, uint8_t *data,
- uint16_t len)
+ uint16_t len)
{
struct node_composition *comp;
uint16_t features;
@@ -965,7 +981,7 @@ bool node_parse_composition(struct mesh_node *node, uint8_t *data,
vendor_id = l_get_le16(data);
mod_id |= (vendor_id << 16);
mod = mesh_model_vendor_new(ele->idx, vendor_id,
- mod_id);
+ mod_id);
if (!mod) {
element_free(ele);
goto fail;
@@ -996,7 +1012,6 @@ fail:

return false;
}
-
static void attach_io(void *a, void *b)
{
struct mesh_node *node = a;
@@ -1385,17 +1400,86 @@ static bool get_app_properties(struct mesh_node *node, const char *path,
return true;
}

-static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
- bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
- uint16_t net_key_idx, uint8_t net_key[16])
+static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast)
{
- node->net = mesh_net_new(node);
+ char *str;

- if (!nodes)
- nodes = l_queue_new();
+ str = (char *)json_object_get_string(jobj);

- l_queue_push_tail(nodes, node);
+ if (sscanf(str, "%04hx", unicast) != 1)
+ return false;
+
+ return true;
+}
+
+static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16])
+{
+ char *str;
+
+ if (!key_buf)
+ return false;

+ str = (char *)json_object_get_string(jobj);
+
+ if (!str2hex(str, strlen(str), key_buf, 16))
+ return false;
+
+ return true;
+}
+
+static void parse_imported_sequence_nr(json_object *jobj, uint32_t *seq)
+{
+ json_object *jvalue;
+
+ if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue))
+ *seq = (uint32_t) json_object_get_int(jvalue);
+ else
+ *seq = DEFAULT_SEQUENCE_NUMBER;
+}
+
+static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
+ uint16_t *net_idx)
+{
+ json_object *jtemp, *jvalue;
+ char *str;
+ uint8_t key[16];
+
+ if (json_object_get_type(jobj) != json_type_array)
+ return false;
+
+ jtemp = json_object_array_get_idx(jobj, 0);
+
+ if (!json_object_object_get_ex(jtemp, "index", &jvalue))
+ return false;
+
+ *net_idx = (uint16_t)json_object_get_int(jvalue);
+
+ if (*net_idx > 4095)
+ return false;
+
+ if (!json_object_object_get_ex(jtemp, "key", &jvalue))
+ return false;
+
+ str = (char *)json_object_get_string(jvalue);
+ if (!str2hex(str, strlen(str), key, 16))
+ return false;
+
+ memcpy(&key_buf[0], &key[0], 16);
+
+ /* Imported node shouldn't contain oldKey or keyRefresh */
+ if (json_object_object_get_ex(jtemp, "oldKey", NULL))
+ return false;
+
+ if (json_object_object_get_ex(jtemp, "keyRefresh", NULL))
+ return false;
+
+ return true;
+}
+
+static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
+ bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
+ uint16_t net_key_idx, uint8_t net_key[16])
+{
if (!storage_set_iv_index(node->net, iv_idx, ivu))
return false;

@@ -1463,14 +1547,13 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
}

if (is_new) {
- node = l_new(struct mesh_node, 1);
+ node = node_new(req->data);
node->elements = l_queue_new();
} else {
node = req->data;
}

num_ele = 0;
-
while (l_dbus_message_iter_next_entry(&objects, &path, &interfaces)) {
struct l_dbus_message_iter properties;
const char *interface;
@@ -1566,6 +1649,48 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)

cb(node, agent);

+ } else if (req->type == REQUEST_TYPE_IMPORT) {
+
+ node_ready_func_t cb = req->cb;
+ struct node_import_request *import_data = req->user_data;
+ struct keyring_net_key net_key;
+
+ if (!agent) {
+ l_error("Interface %s not found",
+ MESH_PROVISION_AGENT_INTERFACE);
+ goto fail;
+ }
+
+ node->num_ele = num_ele;
+ set_defaults(node);
+
+ if (node->seq_number != import_data->sequence)
+ node->seq_number = import_data->sequence;
+
+ memcpy(node->uuid, import_data->uuid, 16);
+
+ if (!create_node_config(node))
+ goto fail;
+
+ if (!add_local_node(node, import_data->unicast, false,
+ import_data->iv_update, import_data->iv_idx,
+ import_data->dev_key, import_data->net_idx,
+ import_data->net_key))
+ goto fail;
+
+ memcpy(net_key.old_key, import_data->net_key, 16);
+ net_key.net_idx = import_data->net_idx;
+ net_key.phase = KEY_REFRESH_PHASE_NONE;
+
+ if (!keyring_put_remote_dev_key(node, import_data->unicast,
+ num_ele, import_data->dev_key))
+ goto fail;
+
+ if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key))
+ goto fail;
+
+ cb(import_data->user_data, MESH_ERROR_NONE, node);
+
} else {
/* Callback for create node request */
node_ready_func_t cb = req->cb;
@@ -1614,7 +1739,7 @@ fail:

cb(req->user_data, MESH_ERROR_FAILED, node);
} else {
- /* Handle failed Join and Create requests */
+ /* Handle failed Join, Create and Import requests */
if (node)
node_remove(node);

@@ -1622,6 +1747,14 @@ fail:
node_join_ready_func_t cb = req->cb;

cb(NULL, NULL);
+
+ } else if (req->type == REQUEST_TYPE_IMPORT) {
+ struct node_import_request *import_data =
+ req->user_data;
+ node_ready_func_t cb = req->cb;
+
+ cb(import_data->user_data, MESH_ERROR_FAILED, NULL);
+
} else {
node_ready_func_t cb = req->cb;

@@ -1686,6 +1819,86 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
req, l_free);
}

+static bool node_import_full(const char *app_path, const char *sender,
+ void *json_data, const uint8_t *uuid,
+ node_ready_func_t cb, void *user_data)
+{
+ return false;
+}
+
+static bool node_import_simplified(const char *app_path, const char *sender,
+ void *json_data, const uint8_t *uuid,
+ node_ready_func_t cb, void *user_data)
+{
+ struct managed_obj_request *req = l_new(struct managed_obj_request, 1);
+ struct node_import_request *node = l_new(struct node_import_request, 1);
+
+ json_object_object_foreach(json_data, key, val) {
+
+ if (!strcmp(key, "deviceKey")) {
+ if (!parse_imported_device_key(val, node->dev_key)) {
+ l_error("Failed to parse imported device key");
+ goto fail;
+ }
+
+ } else if (!strcmp(key, "unicastAddress")) {
+ if (!parse_imported_unicast_addr(val, &node->unicast)) {
+ l_error("Failed to parse imported unicast");
+ goto fail;
+ }
+
+ } else if (!strcmp(key, "IVindex")) {
+ node->iv_idx = (uint32_t) json_object_get_int(val);
+
+ } else if (!strcmp(key, "IVupdate")) {
+ node->iv_update = (bool) json_object_get_int(val);
+
+ } else if (!strcmp(key, "netKeys")) {
+ if (!parse_imported_net_key(val,
+ node->net_key, &node->net_idx)) {
+ l_error("Failed to parse imported network key");
+ goto fail;
+ }
+
+ } else {
+ if (strcmp(key, "sequenceNumber"))
+ goto fail;
+ }
+ }
+
+ parse_imported_sequence_nr(json_data, &node->sequence);
+ node->user_data = user_data;
+
+ memcpy(node->uuid, uuid, 16);
+ req->data = (void *) uuid;
+ req->user_data = node;
+ req->cb = cb;
+ req->type = REQUEST_TYPE_IMPORT;
+
+ l_dbus_method_call(dbus_get_bus(), sender, app_path,
+ L_DBUS_INTERFACE_OBJECT_MANAGER,
+ "GetManagedObjects", NULL,
+ get_managed_objects_cb,
+ req, l_free);
+ return true;
+
+fail:
+ json_object_put(json_data);
+ l_free(node);
+ return false;
+}
+
+bool node_import(const char *app_path, const char *sender, void *json_data,
+ const uint8_t *uuid, node_ready_func_t cb, void *user_data)
+{
+ if (!json_object_object_get_ex(json_data, "elements", NULL))
+ return node_import_simplified(app_path, sender, json_data,
+ uuid, cb, user_data);
+ else
+ return node_import_full(app_path, sender, json_data, uuid,
+ cb, user_data);
+}
+
void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
node_ready_func_t cb, void *user_data)
{
diff --git a/mesh/node.h b/mesh/node.h
index 142527b30..9559f9178 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -91,6 +91,8 @@ void node_build_attach_reply(struct mesh_node *node,
struct l_dbus_message *reply);
void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
node_ready_func_t cb, void *user_data);
+bool node_import(const char *app_path, const char *sender, void *jnode,
+ const uint8_t *uuid, node_ready_func_t cb, void *user_data);
void node_id_set(struct mesh_node *node, uint16_t node_id);
uint16_t node_id_get(struct mesh_node *node);
bool node_dbus_init(struct l_dbus *bus);
--
2.20.1

2019-07-05 15:23:20

by Jakub Witowski

[permalink] [raw]
Subject: [PATCH BlueZ v3 3/3] mesh: Separate json type from the node.c file

This creates intermediate layer between imported node data and parser.
---
mesh/mesh-db.c | 147 ++++++++++++++++++++++++++++++++++++-
mesh/mesh-db.h | 11 +++
mesh/mesh.c | 31 +++++---
mesh/node.c | 193 ++++++++++---------------------------------------
mesh/node.h | 3 +-
5 files changed, 215 insertions(+), 170 deletions(-)

diff --git a/mesh/mesh-db.c b/mesh/mesh-db.c
index e0a000261..0e8f40470 100644
--- a/mesh/mesh-db.c
+++ b/mesh/mesh-db.c
@@ -31,7 +31,7 @@

#include "mesh/mesh-defs.h"
#include "mesh/util.h"
-
+#include "mesh/node.h"
#include "mesh/mesh-db.h"

#define CHECK_KEY_IDX_RANGE(x) (((x) >= 0) && ((x) <= 4095))
@@ -253,6 +253,118 @@ static json_object *jarray_key_del(json_object *jarray, int16_t idx)
return jarray_new;
}

+static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast)
+{
+ char *str = (char *)json_object_get_string(jobj);
+
+ if (sscanf(str, "%04hx", unicast) != 1)
+ return false;
+
+ return true;
+}
+
+static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
+ uint16_t *net_idx)
+{
+ json_object *jtemp, *jvalue;
+ char *str;
+ uint8_t key[16];
+
+ if (json_object_get_type(jobj) != json_type_array)
+ return false;
+
+ jtemp = json_object_array_get_idx(jobj, 0);
+
+ if (!json_object_object_get_ex(jtemp, "index", &jvalue))
+ return false;
+
+ *net_idx = (uint16_t)json_object_get_int(jvalue);
+
+ if (*net_idx > 4095)
+ return false;
+
+ if (!json_object_object_get_ex(jtemp, "key", &jvalue))
+ return false;
+
+ str = (char *)json_object_get_string(jvalue);
+ if (!str2hex(str, strlen(str), key, 16))
+ return false;
+
+ memcpy(&key_buf[0], &key[0], 16);
+
+ /* Imported node shouldn't contain oldKey or keyRefresh */
+ if (json_object_object_get_ex(jtemp, "oldKey", NULL))
+ return false;
+
+ if (json_object_object_get_ex(jtemp, "keyRefresh", NULL))
+ return false;
+
+ return true;
+}
+
+static uint32_t parse_imported_sequence(json_object *jobj,
+ uint32_t default_seq_nr)
+{
+ json_object *jvalue;
+
+ if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue))
+ return (uint32_t) json_object_get_int(jvalue);
+ else
+ return default_seq_nr;
+}
+
+static bool json_iter(json_object *jobj, struct mesh_db_import *db_node)
+{
+ bool dev_key = false, unicast = false;
+ bool iv_index = false, net_key = false;
+
+ json_object_object_foreach(jobj, key, val) {
+
+ if (!strcmp(key, "deviceKey")) {
+
+ dev_key = true;
+ if (!mesh_db_read_device_key(jobj, db_node->dev_key)) {
+ l_error("Failed to parse imported device key");
+ return false;
+ }
+
+ } else if (!strcmp(key, "unicastAddress")) {
+
+ unicast = true;
+ if (!parse_imported_unicast_addr(val,
+ &db_node->node->unicast)) {
+ l_error("Failed to parse imported unicast");
+ return false;
+ }
+
+ } else if (!strcmp(key, "IVindex")) {
+
+ iv_index = true;
+ if (!mesh_db_read_iv_index(jobj, &db_node->iv_index,
+ &db_node->iv_update)) {
+ l_error("Failed to parse iv_index");
+ return false;
+ }
+
+ } else if (!strcmp(key, "netKeys")) {
+
+ net_key = true;
+ if (!parse_imported_net_key(val, db_node->net_key,
+ &db_node->net_idx)) {
+ l_error("Failed to parse imported network key");
+ return false;
+ }
+
+ } else {
+ if (strcmp(key, "sequenceNumber") &&
+ strcmp(key, "IVupdate"))
+ return false;
+ }
+ }
+
+ return dev_key && unicast && net_key && iv_index;
+}
+
bool mesh_db_read_iv_index(json_object *jobj, uint32_t *idx, bool *update)
{
int tmp;
@@ -1438,7 +1550,8 @@ static void add_model(void *a, void *b)
}

/* Add unprovisioned node (local) */
-bool mesh_db_add_node(json_object *jnode, struct mesh_db_node *node) {
+bool mesh_db_add_node(json_object *jnode, struct mesh_db_node *node)
+{

struct mesh_db_modes *modes = &node->modes;
const struct l_queue_entry *entry;
@@ -1783,3 +1896,33 @@ bool mesh_db_model_sub_del_all(json_object *jnode, uint16_t addr,

return delete_model_property(jnode, addr, mod_id, vendor, "subscribe");
}
+
+
+
+struct mesh_db_import *mesh_db_parse_import_data(const char *import_data)
+{
+ json_object *jobj = json_tokener_parse(import_data);
+ struct mesh_db_import *db_node = l_new(struct mesh_db_import, 1);
+
+ if (!jobj)
+ goto fail;
+
+ db_node->node = l_new(struct mesh_db_node, 1);
+
+ if (!json_iter(jobj, db_node))
+ goto fail;
+
+ db_node->node->seq_number =
+ parse_imported_sequence(jobj, DEFAULT_SEQUENCE_NUMBER);
+
+ return db_node;
+fail:
+ if (jobj)
+ json_object_put(jobj);
+
+ if (db_node->node)
+ l_free(db_node->node);
+
+ l_free(db_node);
+ return NULL;
+}
diff --git a/mesh/mesh-db.h b/mesh/mesh-db.h
index da5efa12a..a227319ca 100644
--- a/mesh/mesh-db.h
+++ b/mesh/mesh-db.h
@@ -16,6 +16,7 @@
* Lesser General Public License for more details.
*
*/
+#include <json-c/json.h>

struct mesh_db_sub {
bool virt;
@@ -93,6 +94,15 @@ struct mesh_db_prov {
uint8_t priv_key[32];
};

+struct mesh_db_import {
+ struct mesh_db_node *node;
+ uint8_t dev_key[16];
+ uint8_t net_key[16];
+ uint16_t net_idx;
+ uint32_t iv_index;
+ bool iv_update;
+};
+
typedef bool (*mesh_db_net_key_cb)(uint16_t idx, uint8_t key[16],
uint8_t new_key[16], int phase, void *user_data);
typedef bool (*mesh_db_app_key_cb)(uint16_t idx, uint16_t net_idx,
@@ -155,3 +165,4 @@ bool mesh_db_net_key_set_phase(json_object *jobj, uint16_t idx, uint8_t phase);
bool mesh_db_write_address(json_object *jobj, uint16_t address);
bool mesh_db_write_iv_index(json_object *jobj, uint32_t idx, bool update);
void mesh_db_remove_property(json_object *jobj, const char *desc);
+struct mesh_db_import *mesh_db_parse_import_data(const char *import_data);
diff --git a/mesh/mesh.c b/mesh/mesh.c
index b3def7817..6234121c9 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -22,7 +22,6 @@
#endif

#define _GNU_SOURCE
-#include <json-c/json.h>
#include <string.h>
#include <ell/ell.h>

@@ -36,6 +35,7 @@
#include "mesh/error.h"
#include "mesh/agent.h"
#include "mesh/mesh.h"
+#include "mesh/mesh-db.h"

/*
* The default values for mesh configuration. Can be
@@ -391,10 +391,10 @@ fail:

static bool validate_data_type(const char *data_type)
{
- uint8_t len = sizeof(supported_import_data_types) /
- sizeof(supported_import_data_types[0]);
+ uint8_t idx = 0;
+ uint8_t len = L_ARRAY_SIZE(supported_import_data_types);

- for (uint8_t idx = 0; idx < len; idx++) {
+ for (idx = 0; idx < len; idx++) {
if (strcmp(data_type, supported_import_data_types[idx]) == 0)
return true;
}
@@ -624,10 +624,10 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
const char *app_path, *sender;
struct l_dbus_message *pending_msg;
struct l_dbus_message_iter iter_uuid, iter_import_data;
+ struct mesh_db_import *p_node;
const char *data_type, *import_data;
uint8_t *uuid;
uint32_t n;
- struct json_object *jnode;

l_debug("Import local node request");

@@ -652,7 +652,11 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
"Bad import_data");

- jnode = json_tokener_parse(import_data);
+ p_node = mesh_db_parse_import_data(import_data);
+
+ if (!p_node)
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+ "Failed to parse import_data");

sender = l_dbus_message_get_sender(msg);
pending_msg = l_dbus_message_ref(msg);
@@ -662,14 +666,17 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,

l_queue_push_tail(pending_queue, pending_msg);

- if (!node_import(app_path, sender, jnode, uuid, create_node_ready_cb,
- pending_msg)) {
- l_dbus_message_unref(msg);
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Node import failed");
- }
+ if (!node_import(app_path, sender, p_node, uuid, create_node_ready_cb,
+ pending_msg))
+ goto fail;

return NULL;
+
+fail:
+ l_free(p_node);
+ l_dbus_message_unref(msg);
+ l_queue_remove(pending_queue, pending_msg);
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Node import failed");
}

static void setup_network_interface(struct l_dbus_interface *iface)
diff --git a/mesh/node.c b/mesh/node.c
index 00c3270fd..db04c0c87 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -26,8 +26,6 @@
#include <sys/time.h>

#include <ell/ell.h>
-#include <json-c/json.h>
-#include <stdio.h>

#include "mesh/mesh-defs.h"
#include "mesh/mesh.h"
@@ -56,7 +54,6 @@
#define DEFAULT_LOCATION 0x0000

#define DEFAULT_CRPL 10
-#define DEFAULT_SEQUENCE_NUMBER 0

enum request_type {
REQUEST_TYPE_JOIN = 0,
@@ -119,13 +116,7 @@ struct managed_obj_request {

struct node_import_request {
uint8_t uuid[16];
- uint8_t dev_key[16];
- uint8_t net_key[16];
- uint16_t net_idx;
- uint16_t unicast;
- uint32_t iv_idx;
- bool iv_update;
- uint32_t sequence;
+ struct mesh_db_import *import;
void *user_data;
};

@@ -885,8 +876,7 @@ element_done:

#define MIN_COMPOSITION_LEN 16

-bool node_parse_composition(struct mesh_node *node, uint8_t *data,
- uint16_t len)
+bool node_parse_composition(struct mesh_node *node, uint8_t *data, uint16_t len)
{
struct node_composition *comp;
uint16_t features;
@@ -981,7 +971,7 @@ bool node_parse_composition(struct mesh_node *node, uint8_t *data,
vendor_id = l_get_le16(data);
mod_id |= (vendor_id << 16);
mod = mesh_model_vendor_new(ele->idx, vendor_id,
- mod_id);
+ mod_id);
if (!mod) {
element_free(ele);
goto fail;
@@ -1012,6 +1002,7 @@ fail:

return false;
}
+
static void attach_io(void *a, void *b)
{
struct mesh_node *node = a;
@@ -1400,82 +1391,6 @@ static bool get_app_properties(struct mesh_node *node, const char *path,
return true;
}

-static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast)
-{
- char *str;
-
- str = (char *)json_object_get_string(jobj);
-
- if (sscanf(str, "%04hx", unicast) != 1)
- return false;
-
- return true;
-}
-
-static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16])
-{
- char *str;
-
- if (!key_buf)
- return false;
-
- str = (char *)json_object_get_string(jobj);
-
- if (!str2hex(str, strlen(str), key_buf, 16))
- return false;
-
- return true;
-}
-
-static void parse_imported_sequence_nr(json_object *jobj, uint32_t *seq)
-{
- json_object *jvalue;
-
- if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue))
- *seq = (uint32_t) json_object_get_int(jvalue);
- else
- *seq = DEFAULT_SEQUENCE_NUMBER;
-}
-
-static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
- uint16_t *net_idx)
-{
- json_object *jtemp, *jvalue;
- char *str;
- uint8_t key[16];
-
- if (json_object_get_type(jobj) != json_type_array)
- return false;
-
- jtemp = json_object_array_get_idx(jobj, 0);
-
- if (!json_object_object_get_ex(jtemp, "index", &jvalue))
- return false;
-
- *net_idx = (uint16_t)json_object_get_int(jvalue);
-
- if (*net_idx > 4095)
- return false;
-
- if (!json_object_object_get_ex(jtemp, "key", &jvalue))
- return false;
-
- str = (char *)json_object_get_string(jvalue);
- if (!str2hex(str, strlen(str), key, 16))
- return false;
-
- memcpy(&key_buf[0], &key[0], 16);
-
- /* Imported node shouldn't contain oldKey or keyRefresh */
- if (json_object_object_get_ex(jtemp, "oldKey", NULL))
- return false;
-
- if (json_object_object_get_ex(jtemp, "keyRefresh", NULL))
- return false;
-
- return true;
-}
-
static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
uint16_t net_key_idx, uint8_t net_key[16])
@@ -1652,7 +1567,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
} else if (req->type == REQUEST_TYPE_IMPORT) {

node_ready_func_t cb = req->cb;
- struct node_import_request *import_data = req->user_data;
+ struct node_import_request *import_req = req->user_data;
+ struct mesh_db_import *db_node = import_req->import;
struct keyring_net_key net_key;

if (!agent) {
@@ -1664,32 +1580,32 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
node->num_ele = num_ele;
set_defaults(node);

- if (node->seq_number != import_data->sequence)
- node->seq_number = import_data->sequence;
+ if (node->seq_number != db_node->node->seq_number)
+ node->seq_number = db_node->node->seq_number;

- memcpy(node->uuid, import_data->uuid, 16);
+ memcpy(node->uuid, import_req->uuid, 16);

if (!create_node_config(node))
goto fail;

- if (!add_local_node(node, import_data->unicast, false,
- import_data->iv_update, import_data->iv_idx,
- import_data->dev_key, import_data->net_idx,
- import_data->net_key))
+ if (!add_local_node(node, db_node->node->unicast, false,
+ db_node->iv_update, db_node->iv_index,
+ db_node->dev_key, db_node->net_idx,
+ db_node->net_key))
goto fail;

- memcpy(net_key.old_key, import_data->net_key, 16);
- net_key.net_idx = import_data->net_idx;
+ memcpy(net_key.old_key, db_node->net_key, 16);
+ net_key.net_idx = db_node->net_idx;
net_key.phase = KEY_REFRESH_PHASE_NONE;

- if (!keyring_put_remote_dev_key(node, import_data->unicast,
- num_ele, import_data->dev_key))
+ if (!keyring_put_remote_dev_key(node, db_node->node->unicast,
+ num_ele, db_node->dev_key))
goto fail;

if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key))
goto fail;

- cb(import_data->user_data, MESH_ERROR_NONE, node);
+ cb(import_req->user_data, MESH_ERROR_NONE, node);

} else {
/* Callback for create node request */
@@ -1749,11 +1665,10 @@ fail:
cb(NULL, NULL);

} else if (req->type == REQUEST_TYPE_IMPORT) {
- struct node_import_request *import_data =
- req->user_data;
+ struct node_import_request *import_req = req->user_data;
node_ready_func_t cb = req->cb;

- cb(import_data->user_data, MESH_ERROR_FAILED, NULL);
+ cb(import_req->user_data, MESH_ERROR_FAILED, NULL);

} else {
node_ready_func_t cb = req->cb;
@@ -1820,58 +1735,29 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
}

static bool node_import_full(const char *app_path, const char *sender,
- void *json_data, const uint8_t *uuid,
+ struct mesh_db_import *db_node,
+ const uint8_t *uuid,
node_ready_func_t cb, void *user_data)
{
return false;
}

static bool node_import_simplified(const char *app_path, const char *sender,
- void *json_data, const uint8_t *uuid,
+ struct mesh_db_import *db_node,
+ const uint8_t *uuid,
node_ready_func_t cb, void *user_data)
{
struct managed_obj_request *req = l_new(struct managed_obj_request, 1);
- struct node_import_request *node = l_new(struct node_import_request, 1);
-
- json_object_object_foreach(json_data, key, val) {
-
- if (!strcmp(key, "deviceKey")) {
- if (!parse_imported_device_key(val, node->dev_key)) {
- l_error("Failed to parse imported device key");
- goto fail;
- }
-
- } else if (!strcmp(key, "unicastAddress")) {
- if (!parse_imported_unicast_addr(val, &node->unicast)) {
- l_error("Failed to parse imported unicast");
- goto fail;
- }
+ struct node_import_request *import_req =
+ l_new(struct node_import_request, 1);

- } else if (!strcmp(key, "IVindex")) {
- node->iv_idx = (uint32_t) json_object_get_int(val);
-
- } else if (!strcmp(key, "IVupdate")) {
- node->iv_update = (bool) json_object_get_int(val);
-
- } else if (!strcmp(key, "netKeys")) {
- if (!parse_imported_net_key(val,
- node->net_key, &node->net_idx)) {
- l_error("Failed to parse imported network key");
- goto fail;
- }
-
- } else {
- if (strcmp(key, "sequenceNumber"))
- goto fail;
- }
- }
-
- parse_imported_sequence_nr(json_data, &node->sequence);
- node->user_data = user_data;
+ l_debug("");
+ import_req->user_data = user_data;
+ import_req->import = db_node;
+ memcpy(import_req->uuid, uuid, 16);

- memcpy(node->uuid, uuid, 16);
req->data = (void *) uuid;
- req->user_data = node;
+ req->user_data = import_req;
req->cb = cb;
req->type = REQUEST_TYPE_IMPORT;

@@ -1881,21 +1767,18 @@ static bool node_import_simplified(const char *app_path, const char *sender,
get_managed_objects_cb,
req, l_free);
return true;
-
-fail:
- json_object_put(json_data);
- l_free(node);
- return false;
}

-bool node_import(const char *app_path, const char *sender, void *json_data,
+bool node_import(const char *app_path, const char *sender, void *import,
const uint8_t *uuid, node_ready_func_t cb, void *user_data)
{
- if (!json_object_object_get_ex(json_data, "elements", NULL))
- return node_import_simplified(app_path, sender, json_data,
- uuid, cb, user_data);
+ struct mesh_db_import *db_node = (struct mesh_db_import *)import;
+
+ if (!db_node->node->elements)
+ return node_import_simplified(app_path, sender, db_node, uuid,
+ cb, user_data);
else
- return node_import_full(app_path, sender, json_data, uuid,
+ return node_import_full(app_path, sender, db_node, uuid,
cb, user_data);
}

diff --git a/mesh/node.h b/mesh/node.h
index 9559f9178..7f1093df7 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -26,6 +26,7 @@ struct mesh_agent;
#define MIN_SEQ_TRIGGER 32
#define MIN_SEQ_CACHE (2*MIN_SEQ_TRIGGER)
#define MIN_SEQ_CACHE_TIME (5*60)
+#define DEFAULT_SEQUENCE_NUMBER 0

typedef void (*node_ready_func_t) (void *user_data, int status,
struct mesh_node *node);
@@ -91,7 +92,7 @@ void node_build_attach_reply(struct mesh_node *node,
struct l_dbus_message *reply);
void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
node_ready_func_t cb, void *user_data);
-bool node_import(const char *app_path, const char *sender, void *jnode,
+bool node_import(const char *app_path, const char *sender, void *import,
const uint8_t *uuid, node_ready_func_t cb, void *user_data);
void node_id_set(struct mesh_node *node, uint16_t node_id);
uint16_t node_id_get(struct mesh_node *node);
--
2.20.1

2019-07-05 16:35:48

by Michał Lowas-Rzechonek

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 3/3] mesh: Separate json type from the node.c file

On 07/05, Jakub Witowski wrote:
> This creates intermediate layer between imported node data and parser.

I don't think it's worth having a separate patch for this, please squash
it with 2/3.

> ---
> mesh/mesh-db.c | 147 ++++++++++++++++++++++++++++++++++++-
> mesh/mesh-db.h | 11 +++
> mesh/mesh.c | 31 +++++---
> mesh/node.c | 193 ++++++++++---------------------------------------
> mesh/node.h | 3 +-
> 5 files changed, 215 insertions(+), 170 deletions(-)
>
> diff --git a/mesh/mesh-db.c b/mesh/mesh-db.c
> index e0a000261..0e8f40470 100644
> --- a/mesh/mesh-db.c
> +++ b/mesh/mesh-db.c
> @@ -31,7 +31,7 @@
>
> #include "mesh/mesh-defs.h"
> #include "mesh/util.h"
> -
> +#include "mesh/node.h"
> #include "mesh/mesh-db.h"
>
> #define CHECK_KEY_IDX_RANGE(x) (((x) >= 0) && ((x) <= 4095))
> @@ -253,6 +253,118 @@ static json_object *jarray_key_del(json_object *jarray, int16_t idx)
> return jarray_new;
> }
>
> +static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast)
> +{
> + char *str = (char *)json_object_get_string(jobj);
> +
> + if (sscanf(str, "%04hx", unicast) != 1)
> + return false;
> +
> + return true;
> +}
> +
> +static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
> + uint16_t *net_idx)
> +{
> + json_object *jtemp, *jvalue;
> + char *str;
> + uint8_t key[16];
> +
> + if (json_object_get_type(jobj) != json_type_array)
> + return false;
> +
> + jtemp = json_object_array_get_idx(jobj, 0);
> +
> + if (!json_object_object_get_ex(jtemp, "index", &jvalue))
> + return false;
> +
> + *net_idx = (uint16_t)json_object_get_int(jvalue);
> +
> + if (*net_idx > 4095)
> + return false;
> +
> + if (!json_object_object_get_ex(jtemp, "key", &jvalue))
> + return false;
> +
> + str = (char *)json_object_get_string(jvalue);
> + if (!str2hex(str, strlen(str), key, 16))
> + return false;
> +
> + memcpy(&key_buf[0], &key[0], 16);
> +
> + /* Imported node shouldn't contain oldKey or keyRefresh */
> + if (json_object_object_get_ex(jtemp, "oldKey", NULL))
> + return false;
> +
> + if (json_object_object_get_ex(jtemp, "keyRefresh", NULL))
> + return false;
> +
> + return true;
> +}
> +
> +static uint32_t parse_imported_sequence(json_object *jobj,
> + uint32_t default_seq_nr)
> +{
> + json_object *jvalue;
> +
> + if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue))
> + return (uint32_t) json_object_get_int(jvalue);
> + else
> + return default_seq_nr;
> +}
> +
> +static bool json_iter(json_object *jobj, struct mesh_db_import *db_node)
> +{
> + bool dev_key = false, unicast = false;
> + bool iv_index = false, net_key = false;
> +
> + json_object_object_foreach(jobj, key, val) {
> +
> + if (!strcmp(key, "deviceKey")) {
> +
> + dev_key = true;
> + if (!mesh_db_read_device_key(jobj, db_node->dev_key)) {
> + l_error("Failed to parse imported device key");
> + return false;
> + }
> +
> + } else if (!strcmp(key, "unicastAddress")) {
> +
> + unicast = true;
> + if (!parse_imported_unicast_addr(val,
> + &db_node->node->unicast)) {
> + l_error("Failed to parse imported unicast");
> + return false;
> + }
> +
> + } else if (!strcmp(key, "IVindex")) {
> +
> + iv_index = true;
> + if (!mesh_db_read_iv_index(jobj, &db_node->iv_index,
> + &db_node->iv_update)) {
> + l_error("Failed to parse iv_index");
> + return false;
> + }
> +
> + } else if (!strcmp(key, "netKeys")) {
> +
> + net_key = true;
> + if (!parse_imported_net_key(val, db_node->net_key,
> + &db_node->net_idx)) {
> + l_error("Failed to parse imported network key");
> + return false;
> + }
> +
> + } else {
> + if (strcmp(key, "sequenceNumber") &&
> + strcmp(key, "IVupdate"))
> + return false;
> + }
> + }
> +
> + return dev_key && unicast && net_key && iv_index;
> +}
> +
> bool mesh_db_read_iv_index(json_object *jobj, uint32_t *idx, bool *update)
> {
> int tmp;
> @@ -1438,7 +1550,8 @@ static void add_model(void *a, void *b)
> }
>
> /* Add unprovisioned node (local) */
> -bool mesh_db_add_node(json_object *jnode, struct mesh_db_node *node) {
> +bool mesh_db_add_node(json_object *jnode, struct mesh_db_node *node)
> +{
>
> struct mesh_db_modes *modes = &node->modes;
> const struct l_queue_entry *entry;
> @@ -1783,3 +1896,33 @@ bool mesh_db_model_sub_del_all(json_object *jnode, uint16_t addr,
>
> return delete_model_property(jnode, addr, mod_id, vendor, "subscribe");
> }
> +
> +
> +
> +struct mesh_db_import *mesh_db_parse_import_data(const char *import_data)
> +{
> + json_object *jobj = json_tokener_parse(import_data);
> + struct mesh_db_import *db_node = l_new(struct mesh_db_import, 1);
> +
> + if (!jobj)
> + goto fail;
> +
> + db_node->node = l_new(struct mesh_db_node, 1);
> +
> + if (!json_iter(jobj, db_node))
> + goto fail;
> +
> + db_node->node->seq_number =
> + parse_imported_sequence(jobj, DEFAULT_SEQUENCE_NUMBER);
> +
> + return db_node;
> +fail:
> + if (jobj)
> + json_object_put(jobj);
> +
> + if (db_node->node)
> + l_free(db_node->node);
> +
> + l_free(db_node);
> + return NULL;
> +}
> diff --git a/mesh/mesh-db.h b/mesh/mesh-db.h
> index da5efa12a..a227319ca 100644
> --- a/mesh/mesh-db.h
> +++ b/mesh/mesh-db.h
> @@ -16,6 +16,7 @@
> * Lesser General Public License for more details.
> *
> */
> +#include <json-c/json.h>
>
> struct mesh_db_sub {
> bool virt;
> @@ -93,6 +94,15 @@ struct mesh_db_prov {
> uint8_t priv_key[32];
> };
>
> +struct mesh_db_import {
> + struct mesh_db_node *node;
> + uint8_t dev_key[16];
> + uint8_t net_key[16];
> + uint16_t net_idx;
> + uint32_t iv_index;
> + bool iv_update;
> +};
> +
> typedef bool (*mesh_db_net_key_cb)(uint16_t idx, uint8_t key[16],
> uint8_t new_key[16], int phase, void *user_data);
> typedef bool (*mesh_db_app_key_cb)(uint16_t idx, uint16_t net_idx,
> @@ -155,3 +165,4 @@ bool mesh_db_net_key_set_phase(json_object *jobj, uint16_t idx, uint8_t phase);
> bool mesh_db_write_address(json_object *jobj, uint16_t address);
> bool mesh_db_write_iv_index(json_object *jobj, uint32_t idx, bool update);
> void mesh_db_remove_property(json_object *jobj, const char *desc);
> +struct mesh_db_import *mesh_db_parse_import_data(const char *import_data);
> diff --git a/mesh/mesh.c b/mesh/mesh.c
> index b3def7817..6234121c9 100644
> --- a/mesh/mesh.c
> +++ b/mesh/mesh.c
> @@ -22,7 +22,6 @@
> #endif
>
> #define _GNU_SOURCE
> -#include <json-c/json.h>
> #include <string.h>
> #include <ell/ell.h>
>
> @@ -36,6 +35,7 @@
> #include "mesh/error.h"
> #include "mesh/agent.h"
> #include "mesh/mesh.h"
> +#include "mesh/mesh-db.h"
>
> /*
> * The default values for mesh configuration. Can be
> @@ -391,10 +391,10 @@ fail:
>
> static bool validate_data_type(const char *data_type)
> {
> - uint8_t len = sizeof(supported_import_data_types) /
> - sizeof(supported_import_data_types[0]);
> + uint8_t idx = 0;
> + uint8_t len = L_ARRAY_SIZE(supported_import_data_types);
>
> - for (uint8_t idx = 0; idx < len; idx++) {
> + for (idx = 0; idx < len; idx++) {
> if (strcmp(data_type, supported_import_data_types[idx]) == 0)
> return true;
> }
> @@ -624,10 +624,10 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
> const char *app_path, *sender;
> struct l_dbus_message *pending_msg;
> struct l_dbus_message_iter iter_uuid, iter_import_data;
> + struct mesh_db_import *p_node;
> const char *data_type, *import_data;
> uint8_t *uuid;
> uint32_t n;
> - struct json_object *jnode;
>
> l_debug("Import local node request");
>
> @@ -652,7 +652,11 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
> return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
> "Bad import_data");
>
> - jnode = json_tokener_parse(import_data);
> + p_node = mesh_db_parse_import_data(import_data);
> +
> + if (!p_node)
> + return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
> + "Failed to parse import_data");
>
> sender = l_dbus_message_get_sender(msg);
> pending_msg = l_dbus_message_ref(msg);
> @@ -662,14 +666,17 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
>
> l_queue_push_tail(pending_queue, pending_msg);
>
> - if (!node_import(app_path, sender, jnode, uuid, create_node_ready_cb,
> - pending_msg)) {
> - l_dbus_message_unref(msg);
> - return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
> - "Node import failed");
> - }
> + if (!node_import(app_path, sender, p_node, uuid, create_node_ready_cb,
> + pending_msg))
> + goto fail;
>
> return NULL;
> +
> +fail:
> + l_free(p_node);
> + l_dbus_message_unref(msg);
> + l_queue_remove(pending_queue, pending_msg);
> + return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Node import failed");
> }
>
> static void setup_network_interface(struct l_dbus_interface *iface)
> diff --git a/mesh/node.c b/mesh/node.c
> index 00c3270fd..db04c0c87 100644
> --- a/mesh/node.c
> +++ b/mesh/node.c
> @@ -26,8 +26,6 @@
> #include <sys/time.h>
>
> #include <ell/ell.h>
> -#include <json-c/json.h>
> -#include <stdio.h>
>
> #include "mesh/mesh-defs.h"
> #include "mesh/mesh.h"
> @@ -56,7 +54,6 @@
> #define DEFAULT_LOCATION 0x0000
>
> #define DEFAULT_CRPL 10
> -#define DEFAULT_SEQUENCE_NUMBER 0
>
> enum request_type {
> REQUEST_TYPE_JOIN = 0,
> @@ -119,13 +116,7 @@ struct managed_obj_request {
>
> struct node_import_request {
> uint8_t uuid[16];
> - uint8_t dev_key[16];
> - uint8_t net_key[16];
> - uint16_t net_idx;
> - uint16_t unicast;
> - uint32_t iv_idx;
> - bool iv_update;
> - uint32_t sequence;
> + struct mesh_db_import *import;
> void *user_data;
> };
>
> @@ -885,8 +876,7 @@ element_done:
>
> #define MIN_COMPOSITION_LEN 16
>
> -bool node_parse_composition(struct mesh_node *node, uint8_t *data,
> - uint16_t len)
> +bool node_parse_composition(struct mesh_node *node, uint8_t *data, uint16_t len)
> {
> struct node_composition *comp;
> uint16_t features;
> @@ -981,7 +971,7 @@ bool node_parse_composition(struct mesh_node *node, uint8_t *data,
> vendor_id = l_get_le16(data);
> mod_id |= (vendor_id << 16);
> mod = mesh_model_vendor_new(ele->idx, vendor_id,
> - mod_id);
> + mod_id);
> if (!mod) {
> element_free(ele);
> goto fail;
> @@ -1012,6 +1002,7 @@ fail:
>
> return false;
> }
> +
> static void attach_io(void *a, void *b)
> {
> struct mesh_node *node = a;
> @@ -1400,82 +1391,6 @@ static bool get_app_properties(struct mesh_node *node, const char *path,
> return true;
> }
>
> -static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast)
> -{
> - char *str;
> -
> - str = (char *)json_object_get_string(jobj);
> -
> - if (sscanf(str, "%04hx", unicast) != 1)
> - return false;
> -
> - return true;
> -}
> -
> -static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16])
> -{
> - char *str;
> -
> - if (!key_buf)
> - return false;
> -
> - str = (char *)json_object_get_string(jobj);
> -
> - if (!str2hex(str, strlen(str), key_buf, 16))
> - return false;
> -
> - return true;
> -}
> -
> -static void parse_imported_sequence_nr(json_object *jobj, uint32_t *seq)
> -{
> - json_object *jvalue;
> -
> - if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue))
> - *seq = (uint32_t) json_object_get_int(jvalue);
> - else
> - *seq = DEFAULT_SEQUENCE_NUMBER;
> -}
> -
> -static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
> - uint16_t *net_idx)
> -{
> - json_object *jtemp, *jvalue;
> - char *str;
> - uint8_t key[16];
> -
> - if (json_object_get_type(jobj) != json_type_array)
> - return false;
> -
> - jtemp = json_object_array_get_idx(jobj, 0);
> -
> - if (!json_object_object_get_ex(jtemp, "index", &jvalue))
> - return false;
> -
> - *net_idx = (uint16_t)json_object_get_int(jvalue);
> -
> - if (*net_idx > 4095)
> - return false;
> -
> - if (!json_object_object_get_ex(jtemp, "key", &jvalue))
> - return false;
> -
> - str = (char *)json_object_get_string(jvalue);
> - if (!str2hex(str, strlen(str), key, 16))
> - return false;
> -
> - memcpy(&key_buf[0], &key[0], 16);
> -
> - /* Imported node shouldn't contain oldKey or keyRefresh */
> - if (json_object_object_get_ex(jtemp, "oldKey", NULL))
> - return false;
> -
> - if (json_object_object_get_ex(jtemp, "keyRefresh", NULL))
> - return false;
> -
> - return true;
> -}
> -
> static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
> bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
> uint16_t net_key_idx, uint8_t net_key[16])
> @@ -1652,7 +1567,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
> } else if (req->type == REQUEST_TYPE_IMPORT) {
>
> node_ready_func_t cb = req->cb;
> - struct node_import_request *import_data = req->user_data;
> + struct node_import_request *import_req = req->user_data;
> + struct mesh_db_import *db_node = import_req->import;
> struct keyring_net_key net_key;
>
> if (!agent) {
> @@ -1664,32 +1580,32 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
> node->num_ele = num_ele;
> set_defaults(node);
>
> - if (node->seq_number != import_data->sequence)
> - node->seq_number = import_data->sequence;
> + if (node->seq_number != db_node->node->seq_number)
> + node->seq_number = db_node->node->seq_number;
>
> - memcpy(node->uuid, import_data->uuid, 16);
> + memcpy(node->uuid, import_req->uuid, 16);
>
> if (!create_node_config(node))
> goto fail;
>
> - if (!add_local_node(node, import_data->unicast, false,
> - import_data->iv_update, import_data->iv_idx,
> - import_data->dev_key, import_data->net_idx,
> - import_data->net_key))
> + if (!add_local_node(node, db_node->node->unicast, false,
> + db_node->iv_update, db_node->iv_index,
> + db_node->dev_key, db_node->net_idx,
> + db_node->net_key))
> goto fail;
>
> - memcpy(net_key.old_key, import_data->net_key, 16);
> - net_key.net_idx = import_data->net_idx;
> + memcpy(net_key.old_key, db_node->net_key, 16);
> + net_key.net_idx = db_node->net_idx;
> net_key.phase = KEY_REFRESH_PHASE_NONE;
>
> - if (!keyring_put_remote_dev_key(node, import_data->unicast,
> - num_ele, import_data->dev_key))
> + if (!keyring_put_remote_dev_key(node, db_node->node->unicast,
> + num_ele, db_node->dev_key))
> goto fail;
>
> if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key))
> goto fail;
>
> - cb(import_data->user_data, MESH_ERROR_NONE, node);
> + cb(import_req->user_data, MESH_ERROR_NONE, node);
>
> } else {
> /* Callback for create node request */
> @@ -1749,11 +1665,10 @@ fail:
> cb(NULL, NULL);
>
> } else if (req->type == REQUEST_TYPE_IMPORT) {
> - struct node_import_request *import_data =
> - req->user_data;
> + struct node_import_request *import_req = req->user_data;
> node_ready_func_t cb = req->cb;
>
> - cb(import_data->user_data, MESH_ERROR_FAILED, NULL);
> + cb(import_req->user_data, MESH_ERROR_FAILED, NULL);
>
> } else {
> node_ready_func_t cb = req->cb;
> @@ -1820,58 +1735,29 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
> }
>
> static bool node_import_full(const char *app_path, const char *sender,
> - void *json_data, const uint8_t *uuid,
> + struct mesh_db_import *db_node,
> + const uint8_t *uuid,
> node_ready_func_t cb, void *user_data)
> {
> return false;
> }
>
> static bool node_import_simplified(const char *app_path, const char *sender,
> - void *json_data, const uint8_t *uuid,
> + struct mesh_db_import *db_node,
> + const uint8_t *uuid,
> node_ready_func_t cb, void *user_data)
> {
> struct managed_obj_request *req = l_new(struct managed_obj_request, 1);
> - struct node_import_request *node = l_new(struct node_import_request, 1);
> -
> - json_object_object_foreach(json_data, key, val) {
> -
> - if (!strcmp(key, "deviceKey")) {
> - if (!parse_imported_device_key(val, node->dev_key)) {
> - l_error("Failed to parse imported device key");
> - goto fail;
> - }
> -
> - } else if (!strcmp(key, "unicastAddress")) {
> - if (!parse_imported_unicast_addr(val, &node->unicast)) {
> - l_error("Failed to parse imported unicast");
> - goto fail;
> - }
> + struct node_import_request *import_req =
> + l_new(struct node_import_request, 1);
>
> - } else if (!strcmp(key, "IVindex")) {
> - node->iv_idx = (uint32_t) json_object_get_int(val);
> -
> - } else if (!strcmp(key, "IVupdate")) {
> - node->iv_update = (bool) json_object_get_int(val);
> -
> - } else if (!strcmp(key, "netKeys")) {
> - if (!parse_imported_net_key(val,
> - node->net_key, &node->net_idx)) {
> - l_error("Failed to parse imported network key");
> - goto fail;
> - }
> -
> - } else {
> - if (strcmp(key, "sequenceNumber"))
> - goto fail;
> - }
> - }
> -
> - parse_imported_sequence_nr(json_data, &node->sequence);
> - node->user_data = user_data;
> + l_debug("");
> + import_req->user_data = user_data;
> + import_req->import = db_node;
> + memcpy(import_req->uuid, uuid, 16);
>
> - memcpy(node->uuid, uuid, 16);
> req->data = (void *) uuid;
> - req->user_data = node;
> + req->user_data = import_req;
> req->cb = cb;
> req->type = REQUEST_TYPE_IMPORT;
>
> @@ -1881,21 +1767,18 @@ static bool node_import_simplified(const char *app_path, const char *sender,
> get_managed_objects_cb,
> req, l_free);
> return true;
> -
> -fail:
> - json_object_put(json_data);
> - l_free(node);
> - return false;
> }
>
> -bool node_import(const char *app_path, const char *sender, void *json_data,
> +bool node_import(const char *app_path, const char *sender, void *import,
> const uint8_t *uuid, node_ready_func_t cb, void *user_data)
> {
> - if (!json_object_object_get_ex(json_data, "elements", NULL))
> - return node_import_simplified(app_path, sender, json_data,
> - uuid, cb, user_data);
> + struct mesh_db_import *db_node = (struct mesh_db_import *)import;
> +
> + if (!db_node->node->elements)
> + return node_import_simplified(app_path, sender, db_node, uuid,
> + cb, user_data);
> else
> - return node_import_full(app_path, sender, json_data, uuid,
> + return node_import_full(app_path, sender, db_node, uuid,
> cb, user_data);
> }
>
> diff --git a/mesh/node.h b/mesh/node.h
> index 9559f9178..7f1093df7 100644
> --- a/mesh/node.h
> +++ b/mesh/node.h
> @@ -26,6 +26,7 @@ struct mesh_agent;
> #define MIN_SEQ_TRIGGER 32
> #define MIN_SEQ_CACHE (2*MIN_SEQ_TRIGGER)
> #define MIN_SEQ_CACHE_TIME (5*60)
> +#define DEFAULT_SEQUENCE_NUMBER 0
>
> typedef void (*node_ready_func_t) (void *user_data, int status,
> struct mesh_node *node);
> @@ -91,7 +92,7 @@ void node_build_attach_reply(struct mesh_node *node,
> struct l_dbus_message *reply);
> void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
> node_ready_func_t cb, void *user_data);
> -bool node_import(const char *app_path, const char *sender, void *jnode,
> +bool node_import(const char *app_path, const char *sender, void *import,
> const uint8_t *uuid, node_ready_func_t cb, void *user_data);
> void node_id_set(struct mesh_node *node, uint16_t node_id);
> uint16_t node_id_get(struct mesh_node *node);
> --
> 2.20.1
>

--
Michał Lowas-Rzechonek <[email protected]>
Silvair http://silvair.com
Jasnogórska 44, 31-358 Krakow, POLAND