diff --git a/mesh/mesh.c b/mesh/mesh.c
index 4d65f26..5e0bbb0 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
l_debug("Started mesh (io %p) on hci %u", mesh.io, index);
- node_attach_io(io);
+ node_attach_io_all(io);
}
/* Used for any outbound traffic that doesn't have Friendship Constraints */
path = join_pending->app_path;
if (status == PROV_ERR_SUCCESS &&
- !node_add_pending_local(join_pending->node, info, mesh.io))
+ !node_add_pending_local(join_pending->node, info))
status = PROV_ERR_UNEXPECTED_ERR;
if (status != PROV_ERR_SUCCESS) {
return false;
}
+ node_attach_io(join_pending->node, mesh.io);
token = node_get_token(join_pending->node);
msg = l_dbus_message_new_method_call(dbus, owner, path,
return l_dbus_message_new_method_return(msg);
}
+static void create_network_ready_cb(void *user_data, int status,
+ struct mesh_node *node)
+{
+ struct l_dbus_message *reply;
+ struct l_dbus_message *pending_msg;
+ const uint8_t *token;
+
+ pending_msg = l_queue_find(pending_queue, simple_match, user_data);
+ if (!pending_msg)
+ return;
+
+ if (status != MESH_ERROR_NONE) {
+ reply = dbus_error(pending_msg, status, NULL);
+ goto done;
+ }
+
+ node_attach_io(node, mesh.io);
+
+ reply = l_dbus_message_new_method_return(pending_msg);
+ token = node_get_token(node);
+
+ l_debug();
+ l_dbus_message_set_arguments(reply, "t", l_get_be64(token));
+
+done:
+ l_dbus_send(dbus_get_bus(), reply);
+ l_queue_remove(pending_queue, pending_msg);
+}
+
+static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
+ struct l_dbus_message *msg,
+ void *user_data)
+{
+ const char *app_path, *sender;
+ struct l_dbus_message_iter iter_uuid;
+ struct l_dbus_message *pending_msg;
+ uint8_t *uuid;
+ uint32_t n;
+
+ l_debug("Create network request");
+
+ if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
+ &iter_uuid))
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
+
+ if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n)
+ || n != 16)
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+ "Bad device UUID");
+
+ 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);
+
+ node_create(app_path, sender, uuid, create_network_ready_cb,
+ pending_msg);
+
+ return NULL;
+}
+
static void setup_network_interface(struct l_dbus_interface *iface)
{
l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
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");
}
bool mesh_dbus_init(struct l_dbus *dbus)
diff --git a/mesh/node.c b/mesh/node.c
index 5904b11..8b8642f 100644
--- a/mesh/node.c
+++ b/mesh/node.c
#define MESH_NODE_PATH_PREFIX "/node"
#define MESH_ELEMENT_PATH_PREFIX "/ele"
+/* Default values for a new locally created node */
+#define DEFAULT_NEW_UNICAST 0x0001
+#define DEFAULT_IV_INDEX 0x0000
+#define DEFAULT_PRIMARY_NET_INDEX 0x0000
+
/* Default element location: unknown */
#define DEFAULT_LOCATION 0x0000
#define REQUEST_TYPE_JOIN 0
#define REQUEST_TYPE_ATTACH 1
+#define REQUEST_TYPE_CREATE 2
struct node_element {
char *path;
return false;
node->num_ele = num_ele;
+
if (num_ele != 0 && !add_elements(node, db_node))
return false;
mesh_net_attach(node->net, io);
}
-/* Register callbacks for io */
-void node_attach_io(struct mesh_io *io)
+/* Register callback for the node's io */
+void node_attach_io(struct mesh_node *node, struct mesh_io *io)
+{
+ attach_io(node, io);
+}
+
+/* Register callbacks for all nodes io */
+void node_attach_io_all(struct mesh_io *io)
{
l_queue_foreach(nodes, attach_io, io);
}
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])
+{
+ node->net = mesh_net_new(node);
+
+ if (!nodes)
+ nodes = l_queue_new();
+
+ l_queue_push_tail(nodes, node);
+
+ if (!storage_set_iv_index(node->net, iv_idx, ivu))
+ return false;
+
+ mesh_net_set_iv_index(node->net, iv_idx, ivu);
+
+ if (!mesh_db_write_uint16_hex(node->jconfig, "unicastAddress",
+ unicast))
+ return false;
+
+ l_getrandom(node->token, sizeof(node->token));
+ if (!mesh_db_write_token(node->jconfig, node->token))
+ return false;
+
+ memcpy(node->dev_key, dev_key, 16);
+ if (!mesh_db_write_device_key(node->jconfig, dev_key))
+ return false;
+
+ node->primary = unicast;
+ mesh_net_register_unicast(node->net, unicast, node->num_ele);
+
+ if (mesh_net_add_key(node->net, net_key_idx, net_key) !=
+ MESH_STATUS_SUCCESS)
+ return false;
+
+ if (kr) {
+ /* Duplicate net key, if the key refresh is on */
+ if (mesh_net_update_key(node->net, net_key_idx, net_key) !=
+ MESH_STATUS_SUCCESS)
+ return false;
+
+ if (!mesh_db_net_key_set_phase(node->jconfig, net_key_idx,
+ KEY_REFRESH_PHASE_TWO))
+ return false;
+ }
+
+ storage_save_config(node, true, NULL, NULL);
+
+ /* Initialize configuration server model */
+ mesh_config_srv_init(node, PRIMARY_ELE_IDX);
+
+ return true;
+}
+
static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
{
struct l_dbus_message_iter objects, interfaces;
bool is_new;
uint8_t num_ele;
+ is_new = (req->type != REQUEST_TYPE_ATTACH);
+
if (l_dbus_message_is_error(msg)) {
l_error("Failed to get app's dbus objects");
goto fail;
goto fail;
}
- is_new = (req->type != REQUEST_TYPE_ATTACH);
-
if (is_new) {
node = l_new(struct mesh_node, 1);
node->elements = l_queue_new();
goto fail;
}
- if (req->type == REQUEST_TYPE_JOIN) {
+ if (req->type == REQUEST_TYPE_ATTACH) {
+ 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();
+
+ 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;
+
+ } else if (req->type == REQUEST_TYPE_JOIN) {
node_join_ready_func_t cb = req->cb;
if (!agent) {
MESH_PROVISION_AGENT_INTERFACE);
goto fail;
}
+
node->num_ele = num_ele;
set_defaults(node);
memcpy(node->uuid, req->data, 16);
goto fail;
cb(node, agent);
+
} else {
+ /* Callback for create node request */
node_ready_func_t cb = req->cb;
+ uint8_t dev_key[16];
+ uint8_t net_key[16];
- if (num_ele != node->num_ele)
+ node->num_ele = num_ele;
+ set_defaults(node);
+ memcpy(node->uuid, req->data, 16);
+
+ if (!create_node_config(node))
goto fail;
- if (register_node_object(node)) {
- struct l_dbus *bus = dbus_get_bus();
+ /* Generate device and primary network keys */
+ l_getrandom(dev_key, sizeof(dev_key));
+ l_getrandom(net_key, sizeof(net_key));
- 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
+ if (!add_local_node(node, DEFAULT_NEW_UNICAST, false, false,
+ DEFAULT_IV_INDEX, dev_key,
+ DEFAULT_PRIMARY_NET_INDEX, net_key))
goto fail;
+
+ cb(req->user_data, MESH_ERROR_NONE, node);
}
return;
if (agent)
mesh_agent_remove(agent);
- if (is_new && node)
- free_node_resources(node);
-
- if (req->type == REQUEST_TYPE_JOIN) {
- node_join_ready_func_t cb = req->cb;
-
- cb(NULL, NULL);
-
- } else {
+ if (!is_new) {
+ /* Handle failed Attach request */
node_ready_func_t cb = req->cb;
l_queue_foreach(node->elements, free_element_path, NULL);
l_free(node->owner);
node->owner = NULL;
cb(req->user_data, MESH_ERROR_FAILED, node);
+
+ } else {
+ /* Handle failed Join and Create requests */
+ if (node)
+ free_node_resources(node);
+
+ 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;
+
+ cb(req->user_data, MESH_ERROR_FAILED, NULL);
+ }
}
}
req, l_free);
}
+void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
+ node_ready_func_t cb, void *user_data)
+{
+ struct managed_obj_request *req;
+
+ l_debug("");
+
+ req = l_new(struct managed_obj_request, 1);
+ req->data = (void *) uuid;
+ req->cb = cb;
+ req->user_data = user_data;
+ req->type = REQUEST_TYPE_CREATE;
+
+ l_dbus_method_call(dbus_get_bus(), sender, app_path,
+ L_DBUS_INTERFACE_OBJECT_MANAGER,
+ "GetManagedObjects", NULL,
+ get_managed_objects_cb,
+ req, l_free);
+}
+
static void build_element_config(void *a, void *b)
{
struct node_element *ele = a;
return ele->path;
}
-bool node_add_pending_local(struct mesh_node *node, void *prov_node_info,
- struct mesh_io *io)
+bool node_add_pending_local(struct mesh_node *node, void *prov_node_info)
{
struct mesh_prov_node_info *info = prov_node_info;
bool kr = !!(info->flags & PROV_FLAG_KR);
bool ivu = !!(info->flags & PROV_FLAG_IVU);
- node->net = mesh_net_new(node);
-
- if (!nodes)
- nodes = l_queue_new();
-
- l_queue_push_tail(nodes, node);
-
- if (!storage_set_iv_index(node->net, info->iv_index, ivu))
- return false;
-
- mesh_net_set_iv_index(node->net, info->iv_index, ivu);
-
- if (!mesh_db_write_uint16_hex(node->jconfig, "unicastAddress",
- info->unicast))
- return false;
-
- node->primary = info->unicast;
- mesh_net_register_unicast(node->net, info->unicast, node->num_ele);
-
- l_getrandom(node->token, sizeof(node->token));
- if (!mesh_db_write_token(node->jconfig, node->token))
- return false;
-
- memcpy(node->dev_key, info->device_key, 16);
- if (!mesh_db_write_device_key(node->jconfig, info->device_key))
- return false;
-
- if (mesh_net_add_key(node->net, info->net_index, info->net_key) !=
- MESH_STATUS_SUCCESS)
- return false;
-
- if (kr) {
- /* Duplicate net key, if the key refresh is on */
- if (mesh_net_update_key(node->net, info->net_index,
- info->net_key) != MESH_STATUS_SUCCESS)
- return false;
-
- if (!mesh_db_net_key_set_phase(node->jconfig, info->net_index,
- KEY_REFRESH_PHASE_TWO))
- return false;
- }
-
- storage_save_config(node, true, NULL, NULL);
-
- /* Initialize configuration server model */
- mesh_config_srv_init(node, PRIMARY_ELE_IDX);
-
- mesh_net_attach(node->net, io);
-
- return true;
+ return add_local_node(node, info->unicast, kr, ivu, info->iv_index,
+ info->device_key, info->net_index, info->net_key);
}
void node_jconfig_set(struct mesh_node *node, void *jconfig)
diff --git a/mesh/node.h b/mesh/node.h
index 1be4de1..74ac598 100644
--- a/mesh/node.h
+++ b/mesh/node.h
uint32_t node_seq_cache(struct mesh_node *node);
const char *node_get_element_path(struct mesh_node *node, uint8_t ele_idx);
const char *node_get_owner(struct mesh_node *node);
-bool node_add_pending_local(struct mesh_node *node, void *info,
- struct mesh_io *io);
-void node_attach_io(struct mesh_io *io);
+bool node_add_pending_local(struct mesh_node *node, void *info);
+void node_attach_io_all(struct mesh_io *io);
+void node_attach_io(struct mesh_node *node, struct mesh_io *io);
int node_attach(const char *app_path, const char *sender, 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_create(const char *app_path, const char *sender, 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);