2020-04-14 15:08:47

by Michał Lowas-Rzechonek

[permalink] [raw]
Subject: [PATCH BlueZ v5 0/4] mesh: Always deliver tokens via JoinComplete

This patchset implements API change discussed in
https://marc.info/?l=linux-bluetooth&m=157660821400352&w=2

v5:
- Updated wording in doc/mesh-api.txt
- Rearranged patches to include error checking fix and logs in
patch #2

v4:
- Restore original C parameters on the response for dbus
send_with_reply. Any parameters can now be "returned" by the App,
and a NULL message indicates an internally generated time-out

v3:
- Add distribution independant timeout for JoinComplete() method calls
such that a 30 second timeout of the call is treated as failure, so
stale nodes clean up correctly

v2:
- Fix mesh-cfgclient to send JoinComplete reply before calling Attach

Brian Gix (1):
mesh: Add Time-outs to critical dbus send-with-replies

Michał Lowas-Rzechonek (1):
doc/mesh: Change API to deliver tokens via JoinComplete

Przemysław Fierek (2):
mesh: Change API to deliver tokens via JoinComplete
tools/mesh-cfgclient: Add waiting for 'JoinComplete'

doc/mesh-api.txt | 30 +++++++++-------
mesh/dbus.c | 40 ++++++++++++++++++++++
mesh/dbus.h | 6 ++++
mesh/mesh.c | 68 ++++++++++++++++++++++++++++--------
tools/mesh-cfgclient.c | 78 +++++++++++++++++++++++++-----------------
5 files changed, 162 insertions(+), 60 deletions(-)

--
2.20.1


2020-04-14 15:09:07

by Michał Lowas-Rzechonek

[permalink] [raw]
Subject: [PATCH BlueZ v5 2/4] mesh: Change API to deliver tokens via JoinComplete

From: Przemysław Fierek <[email protected]>

This patch changes Import and CreateNetwork API to deliver tokens via
the JoinComplete method call. When application doesn't raise any error
during handling JoinComplete then it is assumed that the token has been
saved, otherwise when application replies with an error message then the
node is removed.
---
mesh/mesh.c | 68 +++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 53 insertions(+), 15 deletions(-)

diff --git a/mesh/mesh.c b/mesh/mesh.c
index 9b3768b69..01e39e916 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -430,6 +430,20 @@ 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)
+{
+ bool failed = false;
+
+ if (!message || l_dbus_message_is_error(message))
+ failed = true;
+
+ if (!failed)
+ node_attach_io(join_pending->node, mesh.io);
+
+ free_pending_join_call(failed);
+}
+
static bool prov_complete_cb(void *user_data, uint8_t status,
struct mesh_prov_node_info *info)
{
@@ -456,18 +470,16 @@ 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);

+ 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(dbus, msg);
-
- free_pending_join_call(false);
+ l_dbus_send_with_reply(dbus, msg,
+ prov_join_complete_reply_cb, NULL, NULL);

return true;
}
@@ -662,11 +674,28 @@ 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)
+{
+ struct mesh_node *node = user_data;
+
+ if (!message || l_dbus_message_is_error(message)) {
+ node_remove(node);
+ return;
+ }
+
+ node_attach_io(node, mesh.io);
+}
+
static void create_node_ready_cb(void *user_data, int status,
struct mesh_node *node)
{
+ struct l_dbus *dbus = dbus_get_bus();
struct l_dbus_message *reply;
struct l_dbus_message *pending_msg;
+ struct l_dbus_message *msg;
+ const char *owner;
+ const char *path;
const uint8_t *token;

pending_msg = l_queue_find(pending_queue, simple_match, user_data);
@@ -675,20 +704,29 @@ static void create_node_ready_cb(void *user_data, int status,

if (status != MESH_ERROR_NONE) {
reply = dbus_error(pending_msg, status, NULL);
- goto done;
- }

- node_attach_io(node, mesh.io);
+ l_dbus_send(dbus_get_bus(), reply);
+ l_queue_remove(pending_queue, pending_msg);
+ return;
+ }

reply = l_dbus_message_new_method_return(pending_msg);
+
+ l_dbus_send(dbus, reply);
+ l_queue_remove(pending_queue, pending_msg);
+
+ owner = l_dbus_message_get_sender(pending_msg);
+ path = node_get_app_path(node);
token = node_get_token(node);

- l_debug();
- l_dbus_message_set_arguments(reply, "t", l_get_be64(token));
+ l_debug("Calling JoinComplete (create)");
+ msg = l_dbus_message_new_method_call(dbus, owner, path,
+ MESH_APPLICATION_INTERFACE,
+ "JoinComplete");

-done:
- l_dbus_send(dbus_get_bus(), reply);
- l_queue_remove(pending_queue, pending_msg);
+ 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);
}

static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
@@ -842,11 +880,11 @@ static void setup_network_interface(struct l_dbus_interface *iface)
"token");

l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
- "t", "oay", "token", "app", "uuid");
+ "", "oay", "app", "uuid");

l_dbus_interface_method(iface, "Import", 0,
import_call,
- "t", "oayayayqa{sv}uq", "token",
+ "", "oayayayqa{sv}uq",
"app", "uuid", "dev_key", "net_key",
"net_index", "flags", "iv_index",
"unicast");
--
2.20.1

2020-04-14 15:11:10

by Michał Lowas-Rzechonek

[permalink] [raw]
Subject: [PATCH BlueZ v5 4/4] mesh: Add Time-outs to critical dbus send-with-replies

From: Brian Gix <[email protected]>

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 | 8 ++++----
3 files changed, 50 insertions(+), 4 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 01e39e916..21e1517db 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -478,8 +478,8 @@ static bool prov_complete_cb(void *user_data, uint8_t status,
"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;
}
@@ -725,8 +725,8 @@ static void create_node_ready_cb(void *user_data, int status,
"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.20.1

2020-04-14 16:51:16

by Gix, Brian

[permalink] [raw]
Subject: Re: [PATCH BlueZ v5 0/4] mesh: Always deliver tokens via JoinComplete

Patchset applied
On Tue, 2020-04-14 at 10:55 +0200, Michał Lowas-Rzechonek wrote:
> This patchset implements API change discussed in
> https://marc.info/?l=linux-bluetooth&m=157660821400352&w=2
>
> v5:
> - Updated wording in doc/mesh-api.txt
> - Rearranged patches to include error checking fix and logs in
> patch #2
>
> v4:
> - Restore original C parameters on the response for dbus
> send_with_reply. Any parameters can now be "returned" by the App,
> and a NULL message indicates an internally generated time-out
>
> v3:
> - Add distribution independant timeout for JoinComplete() method calls
> such that a 30 second timeout of the call is treated as failure, so
> stale nodes clean up correctly
>
> v2:
> - Fix mesh-cfgclient to send JoinComplete reply before calling Attach
>
> Brian Gix (1):
> mesh: Add Time-outs to critical dbus send-with-replies
>
> Michał Lowas-Rzechonek (1):
> doc/mesh: Change API to deliver tokens via JoinComplete
>
> Przemysław Fierek (2):
> mesh: Change API to deliver tokens via JoinComplete
> tools/mesh-cfgclient: Add waiting for 'JoinComplete'
>
> doc/mesh-api.txt | 30 +++++++++-------
> mesh/dbus.c | 40 ++++++++++++++++++++++
> mesh/dbus.h | 6 ++++
> mesh/mesh.c | 68 ++++++++++++++++++++++++++++--------
> tools/mesh-cfgclient.c | 78 +++++++++++++++++++++++++-----------------
> 5 files changed, 162 insertions(+), 60 deletions(-)
>