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 | 40 ++++++++++++++++++++++++++++++++++++++++ mesh/dbus.h | 6 ++++++ mesh/mesh.c | 19 ++++++++++++------- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/mesh/dbus.c b/mesh/dbus.c index 6b9694ab7..bf0f73bd9 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; + l_dbus_message_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,35 @@ 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; + + l_timeout_remove(info->timeout); + info->cb(message, info->user_data); + l_free(info); +} + +static void send_timeout(struct l_timeout *timeout, void *user_data) +{ + struct send_info *info = user_data; + + l_dbus_cancel(info->dbus, info->serial); + send_reply(NULL, info); +} + +void dbus_send_with_timeout(struct l_dbus *dbus, struct l_dbus_message *msg, + l_dbus_message_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_timeout, info, NULL); +} diff --git a/mesh/dbus.h b/mesh/dbus.h index e7643a59d..aafb85f6b 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" +#define DEFAULT_DBUS_TIMEOUT 30 + 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, + l_dbus_message_func_t cb, + void *user_data, + unsigned int seconds); diff --git a/mesh/mesh.c b/mesh/mesh.c index 8c9aa9187..58a124313 100644 --- a/mesh/mesh.c +++ b/mesh/mesh.c @@ -430,9 +430,12 @@ static void send_join_failed(const char *owner, const char *path, } static void prov_join_complete_reply_cb(struct l_dbus_message *message, - void *user_data) + void *user_data) { - bool failed = l_dbus_message_is_error(message); + bool failed = false; + + if (!message || l_dbus_message_is_error(message)) + failed = true; if (!failed) node_attach_io(join_pending->node, mesh.io); @@ -468,13 +471,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, DEFAULT_DBUS_TIMEOUT); return true; } @@ -673,7 +677,7 @@ static void create_join_complete_reply_cb(struct l_dbus_message *message, { struct mesh_node *node = user_data; - if (l_dbus_message_is_error(message)) { + if (!message || l_dbus_message_is_error(message)) { node_remove(node); return; } @@ -713,13 +717,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, DEFAULT_DBUS_TIMEOUT); } static struct l_dbus_message *create_network_call(struct l_dbus *dbus, -- 2.21.1