summaryrefslogtreecommitdiff
path: root/mesh/node.c
diff options
context:
space:
mode:
authorInga Stotland <inga.stotland@intel.com>2020-08-24 17:54:33 -0700
committerBrian Gix <brian.gix@intel.com>2020-08-26 08:46:55 -0700
commitf2dc6f99f08b2ac1ef310fce14abc69f9116a5d7 (patch)
tree530facaba992328d2c66a077f6dbfc00a6c88720 /mesh/node.c
parent879ea56829c49e94f1015ca13715709ffe970388 (diff)
downloadbluez-f2dc6f99f08b2ac1ef310fce14abc69f9116a5d7.tar.gz
mesh: Handle "options" dictionary in Send/Publish methods
This adds processing of "options" dictionary argument in Send, DevKeySend & Publish methods on mesh.Node interface. This new argument is a dictionary that currently has only one new key word defined for Send() and DevKeySend(): "ForceSegmented" - to force small payloads to be sent as one-segment messages In case of Publish(), and additional keyword is defined "Vendor" - 16-bit Company ID as defined by the Bluetooth SIG Other key words may be defined in future to accommodate evolving requirements of Mesh Profile specification. Also, the addition of "options" dictionary to Publish allows to eliminate VendorPublish() method (taken care by "Vendor" keyword).
Diffstat (limited to 'mesh/node.c')
-rw-r--r--mesh/node.c140
1 files changed, 68 insertions, 72 deletions
diff --git a/mesh/node.c b/mesh/node.c
index a6e9cee65..c564bdb91 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -134,6 +134,11 @@ struct managed_obj_request {
};
};
+struct send_options {
+ bool segmented;
+ uint16_t vendor_id;
+};
+
static struct l_queue *nodes;
static bool match_device_uuid(const void *a, const void *b)
@@ -1745,13 +1750,40 @@ void node_build_attach_reply(struct mesh_node *node,
l_dbus_message_builder_destroy(builder);
}
+static bool parse_send_options(struct l_dbus_message_iter *itr,
+ struct send_options *opts)
+{
+ const char *key;
+ struct l_dbus_message_iter var;
+
+ opts->segmented = false;
+ opts->vendor_id = SIG_VENDOR;
+
+ while (l_dbus_message_iter_next_entry(itr, &key, &var)) {
+ if (!strcmp(key, "ForceSegmented")) {
+ if (!l_dbus_message_iter_get_variant(&var, "b",
+ &opts->segmented))
+ return false;
+ }
+
+ if (!strcmp(key, "Vendor")) {
+ if (!l_dbus_message_iter_get_variant(&var, "q",
+ &opts->vendor_id))
+ return false;
+ }
+ }
+
+ return true;
+}
+
static struct l_dbus_message *send_call(struct l_dbus *dbus,
struct l_dbus_message *msg,
void *user_data)
{
struct mesh_node *node = user_data;
const char *sender, *ele_path;
- struct l_dbus_message_iter iter_data;
+ struct l_dbus_message_iter dict, iter_data;
+ struct send_options opts;
struct node_element *ele;
uint16_t dst, app_idx, net_idx, src;
uint8_t *data;
@@ -1764,8 +1796,8 @@ static struct l_dbus_message *send_call(struct l_dbus *dbus,
if (strcmp(sender, node->owner))
return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "oqqay", &ele_path, &dst,
- &app_idx, &iter_data))
+ if (!l_dbus_message_get_arguments(msg, "oqqa{sv}ay", &ele_path, &dst,
+ &app_idx, &dict, &iter_data))
return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
ele = l_queue_find(node->elements, match_element_path, ele_path);
@@ -1773,6 +1805,9 @@ static struct l_dbus_message *send_call(struct l_dbus *dbus,
return dbus_error(msg, MESH_ERROR_NOT_FOUND,
"Element not found");
+ if (!parse_send_options(&dict, &opts))
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
+
src = node_get_primary(node) + ele->idx;
if (!l_dbus_message_iter_get_fixed_array(&iter_data, &data, &len) ||
@@ -1790,7 +1825,7 @@ static struct l_dbus_message *send_call(struct l_dbus *dbus,
"Key not found");
if (!mesh_model_send(node, src, dst, app_idx, net_idx, DEFAULT_TTL,
- false, data, len))
+ opts.segmented, len, data))
return dbus_error(msg, MESH_ERROR_FAILED, NULL);
return l_dbus_message_new_method_return(msg);
@@ -1802,7 +1837,8 @@ static struct l_dbus_message *dev_key_send_call(struct l_dbus *dbus,
{
struct mesh_node *node = user_data;
const char *sender, *ele_path;
- struct l_dbus_message_iter iter_data;
+ struct l_dbus_message_iter iter_data, dict;
+ struct send_options opts;
struct node_element *ele;
uint16_t dst, app_idx, net_idx, src;
bool remote;
@@ -1816,8 +1852,8 @@ static struct l_dbus_message *dev_key_send_call(struct l_dbus *dbus,
if (strcmp(sender, node->owner))
return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "oqbqay", &ele_path, &dst,
- &remote, &net_idx, &iter_data))
+ if (!l_dbus_message_get_arguments(msg, "oqbqa{sv}ay", &ele_path, &dst,
+ &remote, &net_idx, &dict, &iter_data))
return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
/* Loopbacks to local servers must use *remote* addressing */
@@ -1829,6 +1865,9 @@ static struct l_dbus_message *dev_key_send_call(struct l_dbus *dbus,
return dbus_error(msg, MESH_ERROR_NOT_FOUND,
"Element not found");
+ if (!parse_send_options(&dict, &opts))
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
+
src = node_get_primary(node) + ele->idx;
if (!l_dbus_message_iter_get_fixed_array(&iter_data, &data, &len) ||
@@ -1838,7 +1877,7 @@ static struct l_dbus_message *dev_key_send_call(struct l_dbus *dbus,
app_idx = remote ? APP_IDX_DEV_REMOTE : APP_IDX_DEV_LOCAL;
if (!mesh_model_send(node, src, dst, app_idx, net_idx, DEFAULT_TTL,
- false, data, len))
+ opts.segmented, len, data))
return dbus_error(msg, MESH_ERROR_NOT_FOUND, NULL);
return l_dbus_message_new_method_return(msg);
@@ -1896,7 +1935,7 @@ static struct l_dbus_message *add_netkey_call(struct l_dbus *dbus,
l_put_le16(sub_idx, &data[2]);
if (!mesh_model_send(node, src, dst, APP_IDX_DEV_REMOTE, net_idx,
- DEFAULT_TTL, false, data, 20))
+ DEFAULT_TTL, false, 20, data))
return dbus_error(msg, MESH_ERROR_NOT_FOUND, NULL);
return l_dbus_message_new_method_return(msg);
@@ -1962,7 +2001,7 @@ static struct l_dbus_message *add_appkey_call(struct l_dbus *dbus,
data[3] = app_idx >> 4;
if (!mesh_model_send(node, src, dst, APP_IDX_DEV_REMOTE, net_idx,
- DEFAULT_TTL, false, data, 20))
+ DEFAULT_TTL, false, 20, data))
return dbus_error(msg, MESH_ERROR_NOT_FOUND, NULL);
return l_dbus_message_new_method_return(msg);
@@ -1974,8 +2013,9 @@ static struct l_dbus_message *publish_call(struct l_dbus *dbus,
{
struct mesh_node *node = user_data;
const char *sender, *ele_path;
- struct l_dbus_message_iter iter_data;
+ struct l_dbus_message_iter iter_data, dict;
uint16_t mod_id, src;
+ struct send_options opts;
struct node_element *ele;
uint8_t *data;
uint32_t len, id;
@@ -1988,8 +2028,8 @@ static struct l_dbus_message *publish_call(struct l_dbus *dbus,
if (strcmp(sender, node->owner))
return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "oqay", &ele_path, &mod_id,
- &iter_data))
+ if (!l_dbus_message_get_arguments(msg, "oqa{sv}ay", &ele_path, &mod_id,
+ &dict, &iter_data))
return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
ele = l_queue_find(node->elements, match_element_path, ele_path);
@@ -1997,51 +2037,9 @@ static struct l_dbus_message *publish_call(struct l_dbus *dbus,
return dbus_error(msg, MESH_ERROR_NOT_FOUND,
"Element not found");
- src = node_get_primary(node) + ele->idx;
-
- if (!l_dbus_message_iter_get_fixed_array(&iter_data, &data, &len) ||
- !len || len > MAX_MSG_LEN)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Incorrect data");
-
- id = SET_ID(SIG_VENDOR, mod_id);
- result = mesh_model_publish(node, id, src, data, len);
-
- if (result != MESH_ERROR_NONE)
- return dbus_error(msg, result, NULL);
-
- return l_dbus_message_new_method_return(msg);
-}
-
-static struct l_dbus_message *vendor_publish_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
-{
- struct mesh_node *node = user_data;
- const char *sender, *ele_path;
- struct l_dbus_message_iter iter_data;
- uint16_t src, mod_id, vendor_id;
- struct node_element *ele;
- uint8_t *data = NULL;
- uint32_t len;
- int result;
-
- l_debug("Publish");
-
- sender = l_dbus_message_get_sender(msg);
-
- if (strcmp(sender, node->owner))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
-
- if (!l_dbus_message_get_arguments(msg, "oqqay", &ele_path, &vendor_id,
- &mod_id, &iter_data))
+ if (!parse_send_options(&dict, &opts))
return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- ele = l_queue_find(node->elements, match_element_path, ele_path);
- if (!ele)
- return dbus_error(msg, MESH_ERROR_NOT_FOUND,
- "Element not found");
-
src = node_get_primary(node) + ele->idx;
if (!l_dbus_message_iter_get_fixed_array(&iter_data, &data, &len) ||
@@ -2049,13 +2047,14 @@ static struct l_dbus_message *vendor_publish_call(struct l_dbus *dbus,
return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
"Incorrect data");
- result = mesh_model_publish(node, SET_ID(vendor_id, mod_id), src,
- data, len);
+ id = SET_ID(opts.vendor_id, mod_id);
+
+ result = mesh_model_publish(node, id, src, opts.segmented, len, data);
if (result != MESH_ERROR_NONE)
return dbus_error(msg, result, NULL);
- return l_dbus_message_new_method_return(msg);
+ return l_dbus_message_new_method_return(msg);
}
static bool features_getter(struct l_dbus *dbus, struct l_dbus_message *msg,
@@ -2192,27 +2191,24 @@ static bool addresses_getter(struct l_dbus *dbus, struct l_dbus_message *msg,
static void setup_node_interface(struct l_dbus_interface *iface)
{
- l_dbus_interface_method(iface, "Send", 0, send_call, "", "oqqay",
+ l_dbus_interface_method(iface, "Send", 0, send_call, "", "oqqa{sv}ay",
"element_path", "destination",
- "key_index", "data");
- l_dbus_interface_method(iface, "DevKeySend", 0, dev_key_send_call,
- "", "oqbqay", "element_path",
+ "key_index", "options", "data");
+ l_dbus_interface_method(iface, "DevKeySend", 0, dev_key_send_call, "",
+ "oqbqa{sv}ay", "element_path",
"destination", "remote",
- "net_index", "data");
+ "net_index", "options", "data");
l_dbus_interface_method(iface, "AddNetKey", 0, add_netkey_call, "",
"oqqqb", "element_path", "destination",
"subnet_index", "net_index", "update");
l_dbus_interface_method(iface, "AddAppKey", 0, add_appkey_call, "",
"oqqqb", "element_path", "destination",
"app_index", "net_index", "update");
- l_dbus_interface_method(iface, "Publish", 0, publish_call, "", "oqay",
- "element_path", "model_id", "data");
- l_dbus_interface_method(iface, "VendorPublish", 0, vendor_publish_call,
- "", "oqqay", "element_path",
- "vendor", "model_id", "data");
-
- l_dbus_interface_property(iface, "Features", 0, "a{sv}", features_getter,
- NULL);
+ l_dbus_interface_method(iface, "Publish", 0, publish_call, "",
+ "oqa{sv}ay", "element_path", "model_id",
+ "options", "data");
+ l_dbus_interface_property(iface, "Features", 0, "a{sv}",
+ features_getter, NULL);
l_dbus_interface_property(iface, "Beacon", 0, "b", beacon_getter, NULL);
l_dbus_interface_property(iface, "IvUpdate", 0, "b", ivupdate_getter,
NULL);