fix(nimble): Fix adding device to resolving list when defer connection

This commit is contained in:
Rahul Tank
2026-08-13 10:22:29 +05:30
parent c186c40278
commit 4c282bd44a
2 changed files with 66 additions and 7 deletions
+55 -1
View File
@@ -27,6 +27,7 @@
#include "ble_hs_priv.h"
#include "ble_gap_priv.h"
#include "ble_hs_resolv_priv.h"
#include "ble_sm_priv.h"
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS)
#include "ble_hs_pvcy_priv.h"
#include "ble_att_priv.h"
@@ -1263,6 +1264,7 @@ static void ble_gap_notify_conn_event(uint16_t conn_handle,
static enum ble_gap_defer_result
ble_gap_defer_event(uint16_t conn_handle, const struct ble_gap_event *event,
const struct ble_gap_defer_meta *meta);
static bool ble_gap_connect_delivered(uint16_t conn_handle);
static void ble_gap_mark_connect_delivered(uint16_t conn_handle);
static bool
@@ -1382,6 +1384,9 @@ ble_gap_notify_conn_event(uint16_t conn_handle, struct ble_gap_event *event)
BLE_HS_LOG(ERROR,
"ble_gap_notify_conn_event: defer failed; type=%d conn=%u\n",
event->type, conn_handle);
if (!ble_gap_connect_delivered(conn_handle)) {
return;
}
ble_gap_event_listener_call(event);
ble_gap_call_conn_event_cb(event, conn_handle);
break;
@@ -1562,6 +1567,20 @@ ble_gap_mark_connect_delivered(uint16_t conn_handle)
ble_hs_unlock();
}
static bool
ble_gap_connect_delivered(uint16_t conn_handle)
{
struct ble_hs_conn *conn;
bool delivered;
ble_hs_lock();
conn = ble_hs_conn_find(conn_handle);
delivered = conn != NULL && conn->bhc_connect_delivered;
ble_hs_unlock();
return delivered;
}
void
ble_gap_conn_deferred_init(struct ble_hs_conn *conn)
{
@@ -10067,9 +10086,19 @@ ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev)
BLE_HS_LOG(ERROR,
"ble_gap_rx_param_req: defer failed; conn=%u\n",
conn_handle);
if (!ble_gap_connect_delivered(conn_handle)) {
rc = ble_gap_tx_param_neg_reply(conn_handle, BLE_ERR_CONN_PARMS);
if (rc != 0) {
BLE_HS_LOG(ERROR,
"ble_gap_rx_param_req: negative reply failed; "
"conn=%u rc=%d\n",
conn_handle, rc);
}
return;
}
}
/* NOT_NEEDED or FAILED: fall through to the normal path. */
/* NOT_NEEDED, or FAILED after CONNECT was delivered: normal path. */
}
}
#endif
@@ -10836,6 +10865,16 @@ ble_gap_passkey_event(uint16_t conn_handle,
BLE_HS_LOG(ERROR,
"ble_gap_passkey_event: defer failed; conn=%u\n",
conn_handle);
if (!ble_gap_connect_delivered(conn_handle)) {
struct ble_sm_result res;
memset(&res, 0, sizeof res);
res.sm_err = BLE_SM_ERR_UNSPECIFIED;
res.app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
res.enc_cb = 1;
ble_sm_process_result(conn_handle, &res, true);
return;
}
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
break;
@@ -10876,6 +10915,11 @@ ble_gap_enc_event(uint16_t conn_handle, int status,
BLE_HS_LOG(ERROR,
"ble_gap_enc_event: defer failed; conn=%u status=%d\n",
conn_handle, status);
if (!ble_gap_connect_delivered(conn_handle)) {
ble_gap_enc_side_effects(conn_handle, status,
security_restored, bonded);
return;
}
break;
}
}
@@ -11002,6 +11046,9 @@ ble_gap_pairing_complete_event(uint16_t conn_handle, int status)
BLE_HS_LOG(ERROR,
"ble_gap_pairing_complete_event: defer failed; conn=%u\n",
conn_handle);
if (!ble_gap_connect_delivered(conn_handle)) {
return;
}
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
break;
@@ -11039,6 +11086,9 @@ ble_gap_assoc_event(uint16_t conn_handle, int status, uint8_t cache_state)
BLE_HS_LOG(ERROR,
"ble_gap_assoc_event: defer failed; conn=%u\n",
conn_handle);
if (!ble_gap_connect_delivered(conn_handle)) {
return;
}
ble_gap_call_conn_event_cb(&event, conn_handle);
break;
}
@@ -11115,6 +11165,10 @@ ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
BLE_HS_LOG(ERROR,
"ble_gap_notify_rx_event: defer failed; conn=%u\n",
conn_handle);
if (!ble_gap_connect_delivered(conn_handle)) {
os_mbuf_free_chain(event.notify_rx.om);
return;
}
}
}
#endif
+11 -6
View File
@@ -283,6 +283,9 @@ ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec)
#if NIMBLE_BLE_CONNECT
int rc;
int valid_peer_addr;
valid_peer_addr = ble_addr_cmp(&value_sec->peer_addr, BLE_ADDR_ANY);
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS) && MYNEWT_VAL(BLE_HS_PVCY)
struct ble_store_key_sec key_sec;
struct ble_store_value_sec old_sec;
@@ -303,19 +306,21 @@ ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec)
return rc;
}
if (ble_addr_cmp(&value_sec->peer_addr, BLE_ADDR_ANY) &&
if (valid_peer_addr &&
value_sec->irk_present) {
#if MYNEWT_VAL(BLE_HS_PVCY)
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS)
/* Do not update the controller resolving list while this peer is still
* connected. The bond is already persisted for the current link, and
* some controllers reject LE Add Device To Resolving List in this
* state even when GAP is preempted.
/* Defer the controller resolving-list update only until the CONNECT
* event has been delivered. Once the application knows about the
* connection, resolving-list setup must proceed so scanning can use
* the newly exchanged IRK while the connection remains active.
*/
#if !MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
ble_hs_lock();
struct ble_hs_conn *conn = ble_hs_conn_find_by_addr(&value_sec->peer_addr);
if (conn != NULL) {
if (conn != NULL && !conn->bhc_connect_delivered) {
BLE_HS_LOG(INFO, "PVCY: deferring controller resolving-list add "
"until CONNECT is delivered\n");
conn->bhc_deferred_pvcy_add = 1;
conn->bhc_deferred_pvcy_replace = replace_entry;
conn->bhc_deferred_pvcy_addr = value_sec->peer_addr;