Diff between b723fafbbe582344e65e37ba1732a240cbd764cb and 97b8bbc47ec4262c968612dc49c8f92689723a5d

Changed Files

File Additions Deletions Status
mesh/mesh.c +68 -2 modified
mesh/node.c +145 -73 modified
mesh/node.h +5 -3 modified

Full Patch

diff --git a/mesh/mesh.c b/mesh/mesh.c
index 4d65f26..5e0bbb0 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -112,7 +112,7 @@ static void start_io(uint16_t index)
 
 	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 */
@@ -491,7 +491,7 @@ static bool prov_complete_cb(void *user_data, uint8_t status,
 	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) {
@@ -499,6 +499,7 @@ static bool prov_complete_cb(void *user_data, uint8_t status,
 		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,
@@ -701,6 +702,69 @@ 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,
+							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, "",
@@ -714,6 +778,8 @@ 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");
 }
 
 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
@@ -49,6 +49,11 @@
 #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
 
@@ -57,6 +62,7 @@
 
 #define REQUEST_TYPE_JOIN 0
 #define REQUEST_TYPE_ATTACH 1
+#define REQUEST_TYPE_CREATE 2
 
 struct node_element {
 	char *path;
@@ -378,6 +384,7 @@ bool node_init_from_storage(struct mesh_node *node, void *data)
 		return false;
 
 	node->num_ele = num_ele;
+
 	if (num_ele != 0 && !add_elements(node, db_node))
 		return false;
 
@@ -981,8 +988,14 @@ static void attach_io(void *a, void *b)
 		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);
 }
@@ -1354,6 +1367,60 @@ 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])
+{
+	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;
@@ -1365,6 +1432,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 	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;
@@ -1375,8 +1444,6 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 		goto fail;
 	}
 
-	is_new = (req->type != REQUEST_TYPE_ATTACH);
-
 	if (is_new) {
 		node = l_new(struct mesh_node, 1);
 		node->elements = l_queue_new();
@@ -1445,7 +1512,22 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 		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) {
@@ -1453,6 +1535,7 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 						MESH_PROVISION_AGENT_INTERFACE);
 			goto fail;
 		}
+
 		node->num_ele = num_ele;
 		set_defaults(node);
 		memcpy(node->uuid, req->data, 16);
@@ -1461,20 +1544,30 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 			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;
@@ -1482,15 +1575,8 @@ fail:
 	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);
@@ -1500,6 +1586,21 @@ fail:
 		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);
+		}
 	}
 }
 
@@ -1559,6 +1660,26 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
 					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;
@@ -1790,63 +1911,14 @@ const char *node_get_element_path(struct mesh_node *node, uint8_t ele_idx)
 	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
@@ -82,13 +82,15 @@ uint8_t node_friend_mode_get(struct mesh_node *node);
 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);