patch applied On Wed, 2019-05-08 at 14:50 -0700, Inga Stotland wrote: > This implements CreateNetwork() method on org.bluez.mesh.Network1 > interface. Invoking this method generates a self-provisioned > local node associated with a brand new mesh network. This new > network is bare bones: only one network key is defined. The new node > assumes the role of mesh network manager and will be able to use > soon to be implemented methods of org.bluez.mesh.Management1 interface > to provision remote nodes into its network and to add/update/remove > network and application keys. > --- > mesh/mesh.c | 70 ++++++++++++++++- > mesh/node.c | 218 ++++++++++++++++++++++++++++++++++------------------ > mesh/node.h | 8 +- > 3 files changed, 218 insertions(+), 78 deletions(-) > > diff --git a/mesh/mesh.c b/mesh/mesh.c > index 4d65f266a..5e0bbb009 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 5904b116c..8b8642fea 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 1be4de1da..74ac5981a 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);