diff mbox series

[BlueZ,v4,4/4] mesh: Add Time-outs to critical dbus send-with-replies

Message ID 20200413174535.21488-5-brian.gix@intel.com
State New
Headers show
Series mesh: Always deliver tokens via JoinComplete | expand

Commit Message

Brian Gix April 13, 2020, 5:45 p.m. UTC
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 mbox series

Patch

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,