2019-04-29 19:45:50

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 0/4] Cleanup of org.bluez.mesh.Network1 interface

This set of patches tightens the existing implementation of Join() and
Attach() methods. Some redundacies are removed, common code is combined and
validation of node composition is added for Attach method.

Inga Stotland (4):
mesh: Remove Node interface if node owner disconnects
mesh: Clean up processing of Attach() method
mesh: Consolidate processing of mesh element properties
mesh: Unify processing of GetManagedObjects result

mesh/mesh-defs.h | 2 +
mesh/mesh.c | 69 +++---
mesh/node.c | 558 ++++++++++++++++++++++++++---------------------
mesh/node.h | 9 +-
4 files changed, 344 insertions(+), 294 deletions(-)

--
2.17.2


2019-04-29 19:45:50

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 2/4] mesh: Clean up processing of Attach() method

This changes the prototype for the callback function of
Attach() method call: remove unused node_path argument and make the
callback more generalized and re-usable for other method calls.
---
mesh/mesh.c | 69 ++++++++++++++++++++---------------------------------
mesh/node.c | 19 +++++++--------
mesh/node.h | 9 +++----
3 files changed, 39 insertions(+), 58 deletions(-)

diff --git a/mesh/mesh.c b/mesh/mesh.c
index e7eef0473..a084f9200 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -76,12 +76,6 @@ struct join_data{
uint8_t *uuid;
};

-struct attach_data {
- uint64_t token;
- struct l_dbus_message *msg;
- const char *app;
-};
-
static struct bt_mesh mesh;
static struct l_queue *controllers;
static struct mgmt *mgmt_mesh;
@@ -90,8 +84,8 @@ static bool initialized;
/* We allow only one outstanding Join request */
static struct join_data *join_pending;

-/* Pending Attach requests */
-static struct l_queue *attach_queue;
+/* Pending method requests */
+static struct l_queue *pending_queue;

static bool simple_match(const void *a, const void *b)
{
@@ -341,14 +335,13 @@ bool mesh_init(uint16_t index, const char *config_dir)
return true;
}

-static void attach_exit(void *data)
+static void pending_request_exit(void *data)
{
struct l_dbus_message *reply;
- struct attach_data *pending = data;
+ struct l_dbus_message *msg = data;

- reply = dbus_error(pending->msg, MESH_ERROR_FAILED, "Failed. Exiting");
+ reply = dbus_error(msg, MESH_ERROR_FAILED, "Failed. Exiting");
l_dbus_send(dbus_get_bus(), reply);
- l_free(pending);
}

static void free_pending_join_call(bool failed)
@@ -388,7 +381,7 @@ void mesh_cleanup(void)
free_pending_join_call(true);
}

- l_queue_destroy(attach_queue, attach_exit);
+ l_queue_destroy(pending_queue, pending_request_exit);
node_cleanup_all();
mesh_model_cleanup();

@@ -628,38 +621,29 @@ done:
return reply;
}

-static bool match_attach_request(const void *a, const void *b)
-{
- const struct attach_data *pending = a;
- const uint64_t *token = b;
-
- return *token == pending->token;
-}
-
-static void attach_ready_cb(int status, char *node_path, uint64_t token)
+static void attach_ready_cb(void *user_data, int status, struct mesh_node *node)
{
struct l_dbus_message *reply;
- struct attach_data *pending;
+ struct l_dbus_message *pending_msg;

- pending = l_queue_find(attach_queue, match_attach_request, &token);
- if (!pending)
+ pending_msg = l_queue_find(pending_queue, simple_match, user_data);
+ if (!pending_msg)
return;

if (status != MESH_ERROR_NONE) {
const char *desc = (status == MESH_ERROR_NOT_FOUND) ?
"Node match not found" : "Attach failed";
- reply = dbus_error(pending->msg, status, desc);
+ reply = dbus_error(pending_msg, status, desc);
goto done;
}

- reply = l_dbus_message_new_method_return(pending->msg);
+ reply = l_dbus_message_new_method_return(pending_msg);

- node_build_attach_reply(reply, token);
+ node_build_attach_reply(node, reply);

done:
l_dbus_send(dbus_get_bus(), reply);
- l_queue_remove(attach_queue, pending);
- l_free(pending);
+ l_queue_remove(pending_queue, pending_msg);
}

static struct l_dbus_message *attach_call(struct l_dbus *dbus,
@@ -668,7 +652,8 @@ static struct l_dbus_message *attach_call(struct l_dbus *dbus,
{
uint64_t token;
const char *app_path, *sender;
- struct attach_data *pending;
+ struct l_dbus_message *pending_msg;
+ int status;

l_debug("Attach");

@@ -677,22 +662,20 @@ static struct l_dbus_message *attach_call(struct l_dbus *dbus,

sender = l_dbus_message_get_sender(msg);

- if (node_attach(app_path, sender, token, attach_ready_cb) !=
- MESH_ERROR_NONE)
- return dbus_error(msg, MESH_ERROR_NOT_FOUND,
- "Matching node not found");
+ pending_msg = l_dbus_message_ref(msg);
+ if (!pending_queue)
+ pending_queue = l_queue_new();

- pending = l_new(struct attach_data, 1);
+ l_queue_push_tail(pending_queue, pending_msg);

- pending->token = token;
- pending->msg = l_dbus_message_ref(msg);
+ status = node_attach(app_path, sender, token, attach_ready_cb,
+ pending_msg);
+ if (status == MESH_ERROR_NONE)
+ return NULL;

- if (!attach_queue)
- attach_queue = l_queue_new();
+ l_queue_remove(pending_queue, pending_msg);

- l_queue_push_tail(attach_queue, pending);
-
- return NULL;
+ return dbus_error(msg, status, NULL);
}

static struct l_dbus_message *leave_call(struct l_dbus *dbus,
diff --git a/mesh/node.c b/mesh/node.c
index a6c9332bc..a9eb41e87 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -101,8 +101,9 @@ struct mesh_node {
};

struct attach_obj_request {
- node_attach_ready_func_t cb;
+ node_ready_func_t cb;
struct mesh_node *node;
+ void *user_data;
};

struct join_obj_request {
@@ -1077,7 +1078,6 @@ static void get_managed_objects_attach_cb(struct l_dbus_message *msg,
struct attach_obj_request *req = user_data;
struct mesh_node *node = req->node;
const char *path;
- uint64_t token = l_get_be64(node->token);
uint8_t num_ele;

if (l_dbus_message_is_error(msg)) {
@@ -1124,12 +1124,12 @@ static void get_managed_objects_attach_cb(struct l_dbus_message *msg,

node->disc_watch = l_dbus_add_disconnect_watch(bus, node->owner,
app_disc_cb, node, NULL);
- req->cb(MESH_ERROR_NONE, node->path, token);
+ req->cb(req->user_data, MESH_ERROR_NONE, node);

return;
}
fail:
- req->cb(MESH_ERROR_FAILED, NULL, token);
+ req->cb(req->user_data, MESH_ERROR_FAILED, NULL);

l_queue_foreach(node->elements, free_element_path, NULL);
l_free(node->app_path);
@@ -1141,7 +1141,7 @@ fail:

/* Establish relationship between application and mesh node */
int node_attach(const char *app_path, const char *sender, uint64_t token,
- node_attach_ready_func_t cb)
+ node_ready_func_t cb, void *user_data)
{
struct attach_obj_request *req;
struct mesh_node *node;
@@ -1162,6 +1162,7 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,
req = l_new(struct attach_obj_request, 1);
req->node = node;
req->cb = cb;
+ req->user_data = user_data;

l_dbus_method_call(dbus_get_bus(), sender, app_path,
L_DBUS_INTERFACE_OBJECT_MANAGER,
@@ -1531,15 +1532,11 @@ static void build_element_config(void *a, void *b)
l_dbus_message_builder_leave_struct(builder);
}

-void node_build_attach_reply(struct l_dbus_message *reply, uint64_t token)
+void node_build_attach_reply(struct mesh_node *node,
+ struct l_dbus_message *reply)
{
- struct mesh_node *node;
struct l_dbus_message_builder *builder;

- node = l_queue_find(nodes, match_token, &token);
- if (!node)
- return;
-
builder = l_dbus_message_builder_new(reply);

/* Node object path */
diff --git a/mesh/node.h b/mesh/node.h
index ebc82ffb8..20b60099e 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -27,8 +27,8 @@ struct mesh_agent;
#define MIN_SEQ_CACHE (2*MIN_SEQ_TRIGGER)
#define MIN_SEQ_CACHE_TIME (5*60)

-typedef void (*node_attach_ready_func_t) (int status, char *node_path,
- uint64_t token);
+typedef void (*node_ready_func_t) (void *user_data, int status,
+ struct mesh_node *node);

typedef void (*node_join_ready_func_t) (struct mesh_node *node,
struct mesh_agent *agent);
@@ -86,8 +86,9 @@ bool node_add_pending_local(struct mesh_node *node, void *info,
struct mesh_io *io);
void node_attach_io(struct mesh_io *io);
int node_attach(const char *app_path, const char *sender, uint64_t token,
- node_attach_ready_func_t cb);
-void node_build_attach_reply(struct l_dbus_message *reply, uint64_t token);
+ node_ready_func_t cb, void *user_data);
+void node_build_attach_reply(struct mesh_node *node,
+ struct l_dbus_message *reply);
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.17.2

2019-04-29 19:48:06

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 1/4] mesh: Remove Node interface if node owner disconnects

This unregisters Node interface associated with a specific node
application when this application disconnects from D-Bus.
---
mesh/node.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/mesh/node.c b/mesh/node.c
index 157991dad..a6c9332bc 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -233,7 +233,7 @@ static void free_node_resources(void *data)

if (node->path)
l_dbus_object_remove_interface(dbus_get_bus(), node->path,
- MESH_NODE_INTERFACE);
+ MESH_NODE_INTERFACE);
l_free(node->path);

l_free(node);
@@ -1020,8 +1020,12 @@ static void app_disc_cb(struct l_dbus *bus, void *user_data)
l_free(node->owner);
node->owner = NULL;

- l_free(node->app_path);
- node->app_path = NULL;
+ if (node->path) {
+ l_dbus_object_remove_interface(dbus_get_bus(), node->path,
+ MESH_NODE_INTERFACE);
+ l_free(node->app_path);
+ node->app_path = NULL;
+ }
}

static bool validate_element_properties(struct mesh_node *node,
--
2.17.2

2019-04-29 19:48:06

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 4/4] mesh: Unify processing of GetManagedObjects result

This combines processing of results obtained from GetManagedObjects
request for both Attach() and Join() methods
---
mesh/mesh-defs.h | 2 +
mesh/node.c | 362 +++++++++++++++++++++++------------------------
2 files changed, 182 insertions(+), 182 deletions(-)

diff --git a/mesh/mesh-defs.h b/mesh/mesh-defs.h
index c30041e4a..131b3502c 100644
--- a/mesh/mesh-defs.h
+++ b/mesh/mesh-defs.h
@@ -75,6 +75,8 @@
#define VENDOR_ID_MASK 0xffff0000

#define MAX_KEY_IDX 0x0fff
+#define MAX_MODEL_COUNT 0xff
+#define MAX_ELE_COUNT 0xff

#define IS_UNASSIGNED(x) ((x) == UNASSIGNED_ADDRESS)
#define IS_UNICAST(x) (((x) > UNASSIGNED_ADDRESS) && \
diff --git a/mesh/node.c b/mesh/node.c
index 0c2fc7262..774d03d45 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -54,6 +54,9 @@
#define DEFAULT_CRPL 10
#define DEFAULT_SEQUENCE_NUMBER 0

+#define REQUEST_TYPE_JOIN 0
+#define REQUEST_TYPE_ATTACH 1
+
struct node_element {
char *path;
struct l_queue *models;
@@ -100,15 +103,11 @@ struct mesh_node {
uint8_t beacon;
};

-struct attach_obj_request {
- node_ready_func_t cb;
- struct mesh_node *node;
+struct managed_obj_request {
+ void *data;
+ void *cb;
void *user_data;
-};
-
-struct join_obj_request {
- node_join_ready_func_t cb;
- const uint8_t *uuid;
+ uint8_t type;
};

static struct l_queue *nodes;
@@ -1003,6 +1002,7 @@ void node_attach_io(struct mesh_io *io)
l_queue_foreach(nodes, attach_io, io);
}

+/* Register node object with D-Bus */
static bool register_node_object(struct mesh_node *node)
{
node->path = l_malloc(strlen(MESH_NODE_PATH_PREFIX) + 5);
@@ -1078,7 +1078,6 @@ static bool validate_model_property(struct node_element *ele,
while (l_dbus_message_iter_next_entry(&ids, &vendor_id,
&mod_id)) {
struct mesh_model *mod;
-
mod = l_queue_find(ele->models, match_model_id,
L_UINT_TO_PTR((vendor_id << 16) | mod_id));
if (!mod)
@@ -1132,7 +1131,7 @@ static void get_models_from_properties(struct node_element *ele,

static bool get_element_properties(struct mesh_node *node, const char *path,
struct l_dbus_message_iter *properties,
- bool create_new)
+ bool is_new)
{
struct node_element *ele;
const char *key;
@@ -1156,7 +1155,7 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
return false;
}

- if (!create_new) {
+ if (!is_new) {
/* Validate composition: check the element index */
ele = l_queue_find(node->elements, match_element_idx,
L_UINT_TO_PTR(idx));
@@ -1180,14 +1179,14 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
l_dbus_message_iter_get_variant(&var, "q", &loc);

/* Validate composition: location match */
- if (!create_new && (ele->location != loc))
+ if (!is_new && (ele->location != loc))
return false;

ele->location = loc;

} else if (!strcmp(key, "Models")) {

- if (create_new)
+ if (is_new)
get_models_from_properties(ele, &var, false);
else if (!validate_model_property(ele, &var, &mod_cnt,
false))
@@ -1195,15 +1194,16 @@ static bool get_element_properties(struct mesh_node *node, const char *path,

} else if (!strcmp(key, "VendorModels")) {

- if (create_new)
+ if (is_new)
get_models_from_properties(ele, &var, true);
else if (!validate_model_property(ele, &var,
&vendor_cnt, true))
return false;
+
}
}

- if (create_new) {
+ if (is_new) {
l_queue_push_tail(node->elements, ele);
} else {
/* Account for internal Configuration Server model */
@@ -1220,139 +1220,6 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
return true;
}

-static void get_managed_objects_attach_cb(struct l_dbus_message *msg,
- void *user_data)
-{
- struct l_dbus_message_iter objects, interfaces;
- struct attach_obj_request *req = user_data;
- struct mesh_node *node = req->node;
- const char *path;
- uint8_t num_ele;
-
- if (l_dbus_message_is_error(msg)) {
- l_error("Failed to get app's dbus objects");
- goto fail;
- }
-
- if (!l_dbus_message_get_arguments(msg, "a{oa{sa{sv}}}", &objects)) {
- l_error("Failed to parse app's dbus objects");
- goto fail;
- }
-
- num_ele = 0;
-
- while (l_dbus_message_iter_next_entry(&objects, &path, &interfaces)) {
- struct l_dbus_message_iter properties;
- const char *interface;
-
- while (l_dbus_message_iter_next_entry(&interfaces, &interface,
- &properties)) {
- if (strcmp(MESH_ELEMENT_INTERFACE, interface))
- continue;
-
- if (!get_element_properties(node, path, &properties,
- false))
- goto fail;
-
- num_ele++;
- }
- }
-
- /*
- * Check that the number of element objects matches the expected number
- * of elements on the node
- */
- if (num_ele != node->num_ele)
- goto fail;
-
- /* Register node object with D-Bus */
- register_node_object(node);
-
- if (node->path) {
- struct l_dbus *bus = dbus_get_bus();
-
- node->disc_watch = l_dbus_add_disconnect_watch(bus, node->owner,
- app_disc_cb, node, NULL);
- req->cb(req->user_data, MESH_ERROR_NONE, node);
-
- return;
- }
-fail:
- req->cb(req->user_data, MESH_ERROR_FAILED, NULL);
-
- l_queue_foreach(node->elements, free_element_path, NULL);
- l_free(node->app_path);
- node->app_path = NULL;
-
- l_free(node->owner);
- node->owner = NULL;
-}
-
-/* Establish relationship between application and mesh node */
-int node_attach(const char *app_path, const char *sender, uint64_t token,
- node_ready_func_t cb, void *user_data)
-{
- struct attach_obj_request *req;
- struct mesh_node *node;
-
- node = l_queue_find(nodes, match_token, (void *) &token);
- if (!node)
- return MESH_ERROR_NOT_FOUND;
-
- /* Check if the node is already in use */
- if (node->owner) {
- l_warn("The node is already in use");
- return MESH_ERROR_ALREADY_EXISTS;
- }
-
- node->app_path = l_strdup(app_path);
- node->owner = l_strdup(sender);
-
- req = l_new(struct attach_obj_request, 1);
- req->node = node;
- req->cb = cb;
- req->user_data = user_data;
-
- l_dbus_method_call(dbus_get_bus(), sender, app_path,
- L_DBUS_INTERFACE_OBJECT_MANAGER,
- "GetManagedObjects", NULL,
- get_managed_objects_attach_cb,
- req, l_free);
- return MESH_ERROR_NONE;
-
-}
-
-static bool get_app_properties(struct mesh_node *node, const char *path,
- struct l_dbus_message_iter *properties)
-{
- const char *key;
- struct l_dbus_message_iter variant;
-
- l_debug("path %s", path);
-
- if (!node->comp)
- node->comp = l_new(struct node_composition, 1);
-
- while (l_dbus_message_iter_next_entry(properties, &key, &variant)) {
-
- if (!strcmp(key, "CompanyID")) {
- if (!l_dbus_message_iter_get_variant(&variant, "q",
- &node->comp->cid))
- return false;
- } else if (!strcmp(key, "ProductID")) {
- if (!l_dbus_message_iter_get_variant(&variant, "q",
- &node->comp->pid))
- return false;
- } else if (!strcmp(key, "VersionID")) {
- if (!l_dbus_message_iter_get_variant(&variant, "q",
- &node->comp->vid))
- return false;
- }
- }
-
- return true;
-}
-
static void convert_node_to_storage(struct mesh_node *node,
struct mesh_db_node *db_node)
{
@@ -1451,14 +1318,66 @@ static void set_defaults(struct mesh_node *node)
add_internal_model(node, CONFIG_SRV_MODEL, PRIMARY_ELE_IDX);
}

-static void get_managed_objects_join_cb(struct l_dbus_message *msg,
- void *user_data)
+static bool get_app_properties(struct mesh_node *node, const char *path,
+ struct l_dbus_message_iter *properties,
+ bool is_new)
+{
+ const char *key;
+ struct l_dbus_message_iter variant;
+ uint16_t value;
+
+ l_debug("path %s", path);
+
+ if (is_new)
+ node->comp = l_new(struct node_composition, 1);
+
+ while (l_dbus_message_iter_next_entry(properties, &key, &variant)) {
+
+ if (!strcmp(key, "CompanyID")) {
+ if (!l_dbus_message_iter_get_variant(&variant, "q",
+ &value))
+ return false;
+
+ if (!is_new && node->comp->cid != value)
+ return false;
+
+ node->comp->cid = value;
+
+ } else if (!strcmp(key, "ProductID")) {
+ if (!l_dbus_message_iter_get_variant(&variant, "q",
+ &value))
+ return false;
+
+ if (!is_new && node->comp->pid != value)
+ return false;
+
+ node->comp->pid = value;
+
+ } else if (!strcmp(key, "VersionID")) {
+ if (!l_dbus_message_iter_get_variant(&variant, "q",
+ &value))
+ return false;
+
+ if (!is_new && node->comp->vid != value)
+ return false;
+
+ node->comp->vid = value;
+ }
+ }
+
+ return true;
+}
+
+static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
{
struct l_dbus_message_iter objects, interfaces;
- struct join_obj_request *req = user_data;
+ struct managed_obj_request *req = user_data;
const char *path;
struct mesh_node *node = NULL;
void *agent = NULL;
+ bool have_app = false;
+ bool is_new;
+ uint8_t num_ele;

if (l_dbus_message_is_error(msg)) {
l_error("Failed to get app's dbus objects");
@@ -1470,8 +1389,16 @@ static void get_managed_objects_join_cb(struct l_dbus_message *msg,
goto fail;
}

- node = l_new(struct mesh_node, 1);
- node->elements = l_queue_new();
+ is_new = (req->type != REQUEST_TYPE_ATTACH);
+
+ if (is_new) {
+ node = l_new(struct mesh_node, 1);
+ 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;
@@ -1482,26 +1409,27 @@ static void get_managed_objects_join_cb(struct l_dbus_message *msg,
bool res;

if (!strcmp(MESH_ELEMENT_INTERFACE, interface)) {
+
+ if (num_ele == MAX_ELE_COUNT)
+ goto fail;
+
res = get_element_properties(node, path,
- &properties, true);
+ &properties, is_new);
if (!res)
goto fail;

- node->num_ele++;
- continue;
-
- }
+ num_ele++;

- if (!strcmp(MESH_APPLICATION_INTERFACE, interface)) {
+ } else if (!strcmp(MESH_APPLICATION_INTERFACE,
+ interface)) {
res = get_app_properties(node, path,
- &properties);
+ &properties, is_new);
if (!res)
goto fail;

- continue;
- }
+ have_app = true;

- if (!strcmp(MESH_PROVISION_AGENT_INTERFACE,
+ } else if (!strcmp(MESH_PROVISION_AGENT_INTERFACE,
interface)) {
const char *sender;

@@ -1514,18 +1442,12 @@ static void get_managed_objects_join_cb(struct l_dbus_message *msg,
}
}

- if (!node->comp){
+ if (!have_app) {
l_error("Interface %s not found", MESH_APPLICATION_INTERFACE);
goto fail;
}

- if (!agent) {
- l_error("Interface %s not found",
- MESH_PROVISION_AGENT_INTERFACE);
- goto fail;
- }
-
- if (!node->num_ele) {
+ if (num_ele == 0) {
l_error("Interface %s not found", MESH_ELEMENT_INTERFACE);
goto fail;
}
@@ -1537,41 +1459,117 @@ static void get_managed_objects_join_cb(struct l_dbus_message *msg,
goto fail;
}

- set_defaults(node);
- memcpy(node->dev_uuid, req->uuid, 16);
+ if (req->type == REQUEST_TYPE_JOIN) {
+ node_join_ready_func_t cb = req->cb;

- if (!create_node_config(node))
- goto fail;
+ if (!agent) {
+ l_error("Interface %s not found",
+ MESH_PROVISION_AGENT_INTERFACE);
+ goto fail;
+ }
+ node->num_ele = num_ele;
+ set_defaults(node);
+ memcpy(node->dev_uuid, req->data, 16);
+
+ if (!create_node_config(node))
+ goto fail;
+
+ cb(node, agent);
+ } else {
+ node_ready_func_t cb = req->cb;
+
+ if (num_ele != node->num_ele)
+ goto fail;
+
+ if (register_node_object(node)) {
+ struct l_dbus *bus = dbus_get_bus();

- req->cb(node, agent);
+ node->disc_watch = l_dbus_add_disconnect_watch(bus,
+ node->owner, app_disc_cb, node, NULL);
+ cb(req->user_data, MESH_ERROR_NONE, node);
+ } else
+ goto fail;
+ }

return;
fail:
if (agent)
mesh_agent_remove(agent);

- if (node)
+ if (is_new && node)
free_node_resources(node);

- req->cb(NULL, NULL);
+ if (req->type == REQUEST_TYPE_JOIN) {
+ node_join_ready_func_t cb = req->cb;
+
+ cb(NULL, NULL);
+
+ } else {
+ node_ready_func_t cb = req->cb;
+
+ l_queue_foreach(node->elements, free_element_path, NULL);
+ l_free(node->app_path);
+ node->app_path = NULL;
+
+ l_free(node->owner);
+ node->owner = NULL;
+ cb(req->user_data, MESH_ERROR_FAILED, node);
+ }
+}
+
+/* Establish relationship between application and mesh node */
+int node_attach(const char *app_path, const char *sender, uint64_t token,
+ node_ready_func_t cb, void *user_data)
+{
+ struct managed_obj_request *req;
+ struct mesh_node *node;
+
+ node = l_queue_find(nodes, match_token, (void *) &token);
+ if (!node)
+ return MESH_ERROR_NOT_FOUND;
+
+ /* Check if the node is already in use */
+ if (node->owner) {
+ l_warn("The node is already in use");
+ return MESH_ERROR_ALREADY_EXISTS;
+ }
+
+ node->app_path = l_strdup(app_path);
+ node->owner = l_strdup(sender);
+
+ req = l_new(struct managed_obj_request, 1);
+ req->data = node;
+ req->cb = cb;
+ req->user_data = user_data;
+ req->type = REQUEST_TYPE_ATTACH;
+
+ 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 MESH_ERROR_NONE;
+
}

+
/* Create a temporary pre-provisioned node */
void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
node_join_ready_func_t cb)
{
- struct join_obj_request *req;
+ struct managed_obj_request *req;

l_debug("");

- req = l_new(struct join_obj_request, 1);
- req->uuid = uuid;
+ req = l_new(struct managed_obj_request, 1);
+ req->data = (void *) uuid;
req->cb = cb;
+ req->type = REQUEST_TYPE_JOIN;

l_dbus_method_call(dbus_get_bus(), sender, app_path,
L_DBUS_INTERFACE_OBJECT_MANAGER,
"GetManagedObjects", NULL,
- get_managed_objects_join_cb,
+ get_managed_objects_cb,
req, l_free);
}

--
2.17.2

2019-04-29 19:58:54

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 3/4] mesh: Consolidate processing of mesh element properties

Consolidate functions to parse and process properties of mesh
element objects. Also, add validation of element composition
when processing Attach() method.
---
mesh/node.c | 269 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 167 insertions(+), 102 deletions(-)

diff --git a/mesh/node.c b/mesh/node.c
index a9eb41e87..0c2fc7262 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -147,6 +147,14 @@ static bool match_element_idx(const void *a, const void *b)
return (element->idx == index);
}

+static bool match_model_id(const void *a, const void *b)
+{
+ const struct mesh_model *mod = a;
+ uint32_t mod_id = L_PTR_TO_UINT(b);
+
+ return mod_id == mesh_model_get_model_id(mod);
+}
+
static bool match_element_path(const void *a, const void *b)
{
const struct node_element *element = a;
@@ -1029,20 +1037,115 @@ static void app_disc_cb(struct l_dbus *bus, void *user_data)
}
}

-static bool validate_element_properties(struct mesh_node *node,
- const char *path,
- struct l_dbus_message_iter *properties)
+
+static bool validate_model_property(struct node_element *ele,
+ struct l_dbus_message_iter *property,
+ uint8_t *num_models, bool vendor)
+{
+ struct l_dbus_message_iter ids;
+ uint16_t mod_id, vendor_id;
+ uint8_t count;
+ const char *signature = !vendor ? "aq" : "a(qq)";
+
+ if (!l_dbus_message_iter_get_variant(property, signature, &ids)) {
+ /* Allow empty elements */
+ if (l_queue_length(ele->models) == 0) {
+ *num_models = 0;
+ return true;
+ } else
+ return false;
+ }
+
+ count = 0;
+ if (!vendor) {
+ /* Bluetooth SIG defined models */
+ while (l_dbus_message_iter_next_entry(&ids, &mod_id)) {
+ struct mesh_model *mod;
+ uint32_t m = mod_id;
+
+ /* Skip internally implemented models */
+ if (m == CONFIG_SRV_MODEL)
+ continue;
+
+ mod = l_queue_find(ele->models, match_model_id,
+ L_UINT_TO_PTR(VENDOR_ID_MASK | mod_id));
+ if (!mod)
+ return false;
+ count++;
+ }
+ } else {
+ /* Vendor defined models */
+ while (l_dbus_message_iter_next_entry(&ids, &vendor_id,
+ &mod_id)) {
+ struct mesh_model *mod;
+
+ mod = l_queue_find(ele->models, match_model_id,
+ L_UINT_TO_PTR((vendor_id << 16) | mod_id));
+ if (!mod)
+ return false;
+ count++;
+ }
+ }
+
+ *num_models = count;
+ return true;
+}
+
+static void get_models_from_properties(struct node_element *ele,
+ struct l_dbus_message_iter *property,
+ bool vendor)
+{
+ struct l_dbus_message_iter ids;
+ uint16_t mod_id, vendor_id;
+ const char *signature = !vendor ? "aq" : "a(qq)";
+
+ if (!ele->models)
+ ele->models = l_queue_new();
+
+ if (!l_dbus_message_iter_get_variant(property, signature, &ids))
+ return;
+
+ /* Bluetooth SIG defined models */
+ if (!vendor) {
+ while (l_dbus_message_iter_next_entry(&ids, &mod_id)) {
+ struct mesh_model *mod;
+ uint32_t m = mod_id;
+
+ /* Skip internally implemented models */
+ if (m == CONFIG_SRV_MODEL)
+ continue;
+
+ mod = mesh_model_new(ele->idx, mod_id);
+ l_queue_push_tail(ele->models, mod);
+ }
+ return;
+ }
+
+ /* Vendor defined models */
+ while (l_dbus_message_iter_next_entry(&ids, &vendor_id, &mod_id)) {
+ struct mesh_model *mod;
+
+ mod = mesh_model_vendor_new(ele->idx, vendor_id, mod_id);
+ l_queue_push_tail(ele->models, mod);
+ }
+}
+
+static bool get_element_properties(struct mesh_node *node, const char *path,
+ struct l_dbus_message_iter *properties,
+ bool create_new)
{
- uint8_t ele_idx;
struct node_element *ele;
const char *key;
- struct l_dbus_message_iter variant;
+ struct l_dbus_message_iter var;
bool have_index = false;
+ uint8_t idx, mod_cnt, vendor_cnt;

l_debug("path %s", path);

- while (l_dbus_message_iter_next_entry(properties, &key, &variant)) {
+ while (l_dbus_message_iter_next_entry(properties, &key, &var)) {
if (!strcmp(key, "Index")) {
+ if (!l_dbus_message_iter_get_variant(&var, "y", &idx))
+ return false;
have_index = true;
break;
}
@@ -1053,20 +1156,66 @@ static bool validate_element_properties(struct mesh_node *node,
return false;
}

- if (!l_dbus_message_iter_get_variant(&variant, "y", &ele_idx))
- return false;
+ if (!create_new) {
+ /* Validate composition: check the element index */
+ ele = l_queue_find(node->elements, match_element_idx,
+ L_UINT_TO_PTR(idx));
+ if (!ele) {
+ l_debug("Element with index %u not found", idx);
+ return false;
+ }
+ } else {
+ ele = l_new(struct node_element, 1);
+ ele->location = DEFAULT_LOCATION;
+ ele->idx = idx;
+ }

- ele = l_queue_find(node->elements, match_element_idx,
- L_UINT_TO_PTR(ele_idx));
+ mod_cnt = 0;
+ vendor_cnt = 0;

- if (!ele) {
- l_debug("Element with index %u not found", ele_idx);
- return false;
+ while (l_dbus_message_iter_next_entry(properties, &key, &var)) {
+ if (!strcmp(key, "Location")) {
+ uint8_t loc;
+
+ l_dbus_message_iter_get_variant(&var, "q", &loc);
+
+ /* Validate composition: location match */
+ if (!create_new && (ele->location != loc))
+ return false;
+
+ ele->location = loc;
+
+ } else if (!strcmp(key, "Models")) {
+
+ if (create_new)
+ get_models_from_properties(ele, &var, false);
+ else if (!validate_model_property(ele, &var, &mod_cnt,
+ false))
+ return false;
+
+ } else if (!strcmp(key, "VendorModels")) {
+
+ if (create_new)
+ get_models_from_properties(ele, &var, true);
+ else if (!validate_model_property(ele, &var,
+ &vendor_cnt, true))
+ return false;
+ }
}

- /* TODO: validate models */
+ if (create_new) {
+ l_queue_push_tail(node->elements, ele);
+ } else {
+ /* Account for internal Configuration Server model */
+ if (idx == 0)
+ mod_cnt += 1;

- ele->path = l_strdup(path);
+ /* Validate composition: number of models must match */
+ if (l_queue_length(ele->models) != (mod_cnt + vendor_cnt))
+ return false;
+
+ ele->path = l_strdup(path);
+ }

return true;
}
@@ -1101,8 +1250,8 @@ static void get_managed_objects_attach_cb(struct l_dbus_message *msg,
if (strcmp(MESH_ELEMENT_INTERFACE, interface))
continue;

- if (!validate_element_properties(node, path,
- &properties))
+ if (!get_element_properties(node, path, &properties,
+ false))
goto fail;

num_ele++;
@@ -1173,90 +1322,6 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,

}

-static void add_model_from_properties(struct node_element *ele,
- struct l_dbus_message_iter *property)
-{
- struct l_dbus_message_iter ids;
- uint16_t model_id;
- int i = 0;
-
- if (!ele->models)
- ele->models = l_queue_new();
-
- if (!l_dbus_message_iter_get_variant(property, "aq", &ids))
- return;
-
- while (l_dbus_message_iter_next_entry(&ids, &model_id)) {
- struct mesh_model *mod;
- l_debug("model_id %4.4x", model_id);
- mod = mesh_model_new(ele->idx, model_id);
- l_queue_push_tail(ele->models, mod);
- i++;
- if (i > 3)
- break;
- }
-}
-
-static void add_vendor_model_from_properties(struct node_element *ele,
- struct l_dbus_message_iter *property)
-{
- struct l_dbus_message_iter ids;
- uint16_t v;
- uint16_t m;
-
- if (!ele->models)
- ele->models = l_queue_new();
-
- if (!l_dbus_message_iter_get_variant(property, "a(qq)", &ids))
- return;
-
- while (l_dbus_message_iter_next_entry(&ids, &v, &m)) {
- struct mesh_model *mod;
-
- mod = mesh_model_vendor_new(ele->idx, v, m);
- l_queue_push_tail(ele->models, mod);
- }
-}
-
-static bool get_element_properties(struct mesh_node *node, const char *path,
- struct l_dbus_message_iter *properties)
-{
- struct node_element *ele;
- const char *key;
- struct l_dbus_message_iter variant;
- bool have_index = false;
-
- l_debug("path %s", path);
-
- ele = l_new(struct node_element, 1);
- ele->location = DEFAULT_LOCATION;
-
- while (l_dbus_message_iter_next_entry(properties, &key, &variant)) {
- if (!strcmp(key, "Index")) {
- if (!l_dbus_message_iter_get_variant(&variant, "y",
- &ele->idx))
- return false;
- have_index = true;
- } else if (!strcmp(key, "Location")) {
- l_dbus_message_iter_get_variant(&variant, "q",
- &ele->location);
- } else if (!strcmp(key, "Models")) {
- add_model_from_properties(ele, &variant);
- } else if (!strcmp(key, "VendorModels")) {
- add_vendor_model_from_properties(ele, &variant);
- }
- }
-
- if (!have_index) {
- l_debug("Mandatory property \"Index\" not found");
- return false;
- }
-
- l_queue_push_tail(node->elements, ele);
-
- return true;
-}
-
static bool get_app_properties(struct mesh_node *node, const char *path,
struct l_dbus_message_iter *properties)
{
@@ -1418,7 +1483,7 @@ static void get_managed_objects_join_cb(struct l_dbus_message *msg,

if (!strcmp(MESH_ELEMENT_INTERFACE, interface)) {
res = get_element_properties(node, path,
- &properties);
+ &properties, true);
if (!res)
goto fail;

--
2.17.2

2019-05-02 16:02:36

by Gix, Brian

[permalink] [raw]
Subject: Re: [PATCH BlueZ 0/4] Cleanup of org.bluez.mesh.Network1 interface

Patch-set applied

On Mon, 2019-04-29 at 12:45 -0700, Inga Stotland wrote:
> This set of patches tightens the existing implementation of Join() and
> Attach() methods. Some redundacies are removed, common code is combined and
> validation of node composition is added for Attach method.
>
> Inga Stotland (4):
> mesh: Remove Node interface if node owner disconnects
> mesh: Clean up processing of Attach() method
> mesh: Consolidate processing of mesh element properties
> mesh: Unify processing of GetManagedObjects result
>
> mesh/mesh-defs.h | 2 +
> mesh/mesh.c | 69 +++---
> mesh/node.c | 558 ++++++++++++++++++++++++++---------------------
> mesh/node.h | 9 +-
> 4 files changed, 344 insertions(+), 294 deletions(-)
>