Bluetooth: Mesh: Call friendship callbacks at the end
If a user does some heavy operations in friendship callbacks unintentionally, this may break friendship communication as timers will be scheduled or messages will be queued only after code execution comes back from these callbacks. To avoid this issue, call callbacks only after required operations are done. Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
parent
56e912d1c1
commit
5b4b5c0d34
2 changed files with 48 additions and 37 deletions
|
@ -730,6 +730,23 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
|
|||
|
||||
friend_recv_delay(frnd);
|
||||
|
||||
if (msg->fsn == frnd->fsn && frnd->last) {
|
||||
LOG_DBG("Re-sending last PDU");
|
||||
frnd->send_last = 1U;
|
||||
} else {
|
||||
if (frnd->last) {
|
||||
net_buf_unref(frnd->last);
|
||||
frnd->last = NULL;
|
||||
}
|
||||
|
||||
frnd->fsn = msg->fsn;
|
||||
|
||||
if (sys_slist_is_empty(&frnd->queue)) {
|
||||
enqueue_update(frnd, 0);
|
||||
LOG_DBG("Enqueued Friend Update to empty queue");
|
||||
}
|
||||
}
|
||||
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_friend_cb, cb) {
|
||||
if (cb->polled) {
|
||||
cb->polled(frnd->subnet->net_idx, frnd->lpn);
|
||||
|
@ -748,23 +765,6 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
|
|||
}
|
||||
}
|
||||
|
||||
if (msg->fsn == frnd->fsn && frnd->last) {
|
||||
LOG_DBG("Re-sending last PDU");
|
||||
frnd->send_last = 1U;
|
||||
} else {
|
||||
if (frnd->last) {
|
||||
net_buf_unref(frnd->last);
|
||||
frnd->last = NULL;
|
||||
}
|
||||
|
||||
frnd->fsn = msg->fsn;
|
||||
|
||||
if (sys_slist_is_empty(&frnd->queue)) {
|
||||
enqueue_update(frnd, 0);
|
||||
LOG_DBG("Enqueued Friend Update to empty queue");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -217,6 +217,9 @@ static int send_friend_clear(void)
|
|||
static void clear_friendship(bool force, bool disable)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
bool established = lpn->established;
|
||||
uint16_t frnd = lpn->frnd;
|
||||
uint16_t net_idx = lpn->sub->net_idx;
|
||||
|
||||
LOG_DBG("force %u disable %u", force, disable);
|
||||
|
||||
|
@ -244,14 +247,6 @@ static void clear_friendship(bool force, bool disable)
|
|||
lpn->old_friend = lpn->frnd;
|
||||
}
|
||||
|
||||
if (lpn->established) {
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
|
||||
if (cb->terminated) {
|
||||
cb->terminated(lpn->sub->net_idx, lpn->frnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
|
||||
lpn->fsn = 0U;
|
||||
lpn->req_attempts = 0U;
|
||||
|
@ -284,6 +279,14 @@ static void clear_friendship(bool force, bool disable)
|
|||
|
||||
k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
|
||||
}
|
||||
|
||||
if (established) {
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
|
||||
if (cb->terminated) {
|
||||
cb->terminated(net_idx, frnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void friend_req_sent(uint16_t duration, int err, void *user_data)
|
||||
|
@ -358,6 +361,7 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
|
|||
static void req_sent(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
bool retry;
|
||||
|
||||
if (lpn->state == BT_MESH_LPN_DISABLED) {
|
||||
return;
|
||||
|
@ -375,11 +379,7 @@ static void req_sent(uint16_t duration, int err, void *user_data)
|
|||
return;
|
||||
}
|
||||
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
|
||||
if (cb->polled) {
|
||||
cb->polled(lpn->sub->net_idx, lpn->frnd, !!(lpn->req_attempts));
|
||||
}
|
||||
}
|
||||
retry = (lpn->req_attempts > 0);
|
||||
|
||||
lpn->req_attempts++;
|
||||
lpn->adv_duration = duration;
|
||||
|
@ -397,6 +397,12 @@ static void req_sent(uint16_t duration, int err, void *user_data)
|
|||
K_MSEC(LPN_RECV_DELAY + duration +
|
||||
lpn->recv_win));
|
||||
}
|
||||
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
|
||||
if (cb->polled) {
|
||||
cb->polled(lpn->sub->net_idx, lpn->frnd, retry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bt_mesh_send_cb req_sent_cb = {
|
||||
|
@ -984,6 +990,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
|
||||
struct bt_mesh_subnet *sub = rx->sub;
|
||||
uint32_t iv_index;
|
||||
bool established = false;
|
||||
|
||||
if (buf->len < sizeof(*msg)) {
|
||||
LOG_WRN("Too short Friend Update");
|
||||
|
@ -1023,16 +1030,11 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
|
||||
bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
|
||||
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
|
||||
if (cb->established) {
|
||||
cb->established(lpn->sub->net_idx, lpn->frnd,
|
||||
lpn->queue_size, lpn->recv_win);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set initial poll timeout */
|
||||
lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn),
|
||||
POLL_TIMEOUT_INIT);
|
||||
|
||||
established = true;
|
||||
}
|
||||
|
||||
friend_response_received(lpn);
|
||||
|
@ -1058,6 +1060,15 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
|
|||
send_friend_poll();
|
||||
}
|
||||
|
||||
if (established) {
|
||||
STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
|
||||
if (cb->established) {
|
||||
cb->established(lpn->sub->net_idx, lpn->frnd,
|
||||
lpn->queue_size, lpn->recv_win);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue