JoinComplete() dbus method calls are the only time that node tokens are delivered to client Applications, so if the call fails for any reason (including time-outs) the daemon has a way to clean-up the stale unused node data. --- mesh/dbus.c | 43 +++++++++++++++++++++++++++++++++++++++++++ mesh/dbus.h | 6 ++++++ mesh/mesh.c | 22 ++++++++++++---------- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/mesh/dbus.c b/mesh/dbus.c index 6b9694ab7..2c9dd3ae0 100644 --- a/mesh/dbus.c +++ b/mesh/dbus.c @@ -37,6 +37,14 @@ struct error_entry { const char *default_desc; }; +struct send_info { + struct l_dbus *dbus; + struct l_timeout *timeout; + dbus_send_with_to_func_t cb; + void *user_data; + uint32_t serial; +}; + /* * Important: The entries in this table follow the order of * enumerated values in mesh_error (file error.h) @@ -143,3 +151,38 @@ void dbus_append_dict_entry_basic(struct l_dbus_message_builder *builder, l_dbus_message_builder_leave_variant(builder); l_dbus_message_builder_leave_dict(builder); } + +static void send_reply(struct l_dbus_message *message, void *user_data) +{ + struct send_info *info = user_data; + bool failed = l_dbus_message_is_error(message); + + l_timeout_remove(info->timeout); + info->cb(failed, info->user_data); + l_free(info); +} + +static void send_to(struct l_timeout *timeout, void *user_data) +{ + struct send_info *info = user_data; + + l_dbus_cancel(info->dbus, info->serial); + l_timeout_remove(info->timeout); + info->cb(true, info->user_data); + l_free(info); +} + +void dbus_send_with_timeout(struct l_dbus *dbus, struct l_dbus_message *msg, + dbus_send_with_to_func_t cb, + void *user_data, + unsigned int seconds) +{ + struct send_info *info = l_new(struct send_info, 1); + + info->dbus = dbus; + info->cb = cb; + info->user_data = user_data; + info->serial = l_dbus_send_with_reply(dbus, msg, send_reply, + info, NULL); + info->timeout = l_timeout_create(seconds, send_to, info, NULL); +} diff --git a/mesh/dbus.h b/mesh/dbus.h index e7643a59d..31c174367 100644 --- a/mesh/dbus.h +++ b/mesh/dbus.h @@ -20,6 +20,8 @@ #define BLUEZ_MESH_PATH "/org/bluez/mesh" #define BLUEZ_MESH_SERVICE "org.bluez.mesh" +typedef void (*dbus_send_with_to_func_t) (bool failed, void *user_data); + bool dbus_init(struct l_dbus *dbus); struct l_dbus *dbus_get_bus(void); void dbus_append_byte_array(struct l_dbus_message_builder *builder, @@ -31,3 +33,7 @@ bool dbus_match_interface(struct l_dbus_message_iter *interfaces, const char *match); struct l_dbus_message *dbus_error(struct l_dbus_message *msg, int err, const char *description); +void dbus_send_with_timeout(struct l_dbus *dbus, struct l_dbus_message *msg, + dbus_send_with_to_func_t cb, + void *user_data, + unsigned int seconds); diff --git a/mesh/mesh.c b/mesh/mesh.c index 8c9aa9187..f46e676d9 100644 --- a/mesh/mesh.c +++ b/mesh/mesh.c @@ -429,10 +429,9 @@ static void send_join_failed(const char *owner, const char *path, free_pending_join_call(true); } -static void prov_join_complete_reply_cb(struct l_dbus_message *message, - void *user_data) +static void prov_join_complete_reply_cb(bool failed, void *user_data) { - bool failed = l_dbus_message_is_error(message); + l_debug("prov_join_complete_reply_cb"); if (!failed) node_attach_io(join_pending->node, mesh.io); @@ -468,13 +467,14 @@ static bool prov_complete_cb(void *user_data, uint8_t status, token = node_get_token(join_pending->node); + l_debug("Calling JoinComplete (prov)"); msg = l_dbus_message_new_method_call(dbus, owner, path, MESH_APPLICATION_INTERFACE, "JoinComplete"); l_dbus_message_set_arguments(msg, "t", l_get_be64(token)); - l_dbus_send_with_reply(dbus, msg, - prov_join_complete_reply_cb, NULL, NULL); + dbus_send_with_timeout(dbus, msg, prov_join_complete_reply_cb, + NULL, 30); return true; } @@ -668,12 +668,13 @@ static struct l_dbus_message *leave_call(struct l_dbus *dbus, return l_dbus_message_new_method_return(msg); } -static void create_join_complete_reply_cb(struct l_dbus_message *message, - void *user_data) +static void create_join_complete_reply_cb(bool failed, void *user_data) { struct mesh_node *node = user_data; - if (l_dbus_message_is_error(message)) { + l_debug("create_join_complete_reply_cb"); + + if (failed) { node_remove(node); return; } @@ -713,13 +714,14 @@ static void create_node_ready_cb(void *user_data, int status, path = node_get_app_path(node); token = node_get_token(node); + l_debug("Calling JoinComplete (create)"); msg = l_dbus_message_new_method_call(dbus, owner, path, MESH_APPLICATION_INTERFACE, "JoinComplete"); l_dbus_message_set_arguments(msg, "t", l_get_be64(token)); - l_dbus_send_with_reply(dbus, msg, - create_join_complete_reply_cb, node, NULL); + dbus_send_with_timeout(dbus, msg, create_join_complete_reply_cb, + node, 30); } static struct l_dbus_message *create_network_call(struct l_dbus *dbus, -- 2.21.1