Skip to content

Commit cbb3172

Browse files
committed
nimble/host: Fix available packets counter leak
Mark connection as disconnected as soon as HCI Disconnection Complete event is processed. At this point ACL handle is no longer valid and controller will ignore any ACL data sent to it. Since later GAP Disconnected event is not handled atomically it may lead to TX data on that handle and thus 'leaking' available packets count on host. This is especially possible when there is connection timoue while host is in the middle of data transmission (eg sending nitifications).
1 parent 8e8eb4d commit cbb3172

3 files changed

Lines changed: 14 additions & 1 deletion

File tree

nimble/host/src/ble_hs_conn_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef uint8_t ble_hs_conn_flags_t;
3737
#define BLE_HS_CONN_F_MASTER 0x01
3838
#define BLE_HS_CONN_F_TERMINATING 0x02
3939
#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */
40+
#define BLE_HS_CONN_F_TERMINATED 0x08
4041

4142
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
4243
#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM \

nimble/host/src/ble_hs_hci.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,17 @@ ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om)
515515

516516
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
517517

518+
/* conn may be already disconnected but GAP events were not yet
519+
* processed and thus connection object is stil on list, just ignore it
520+
* in such case as ACL handle is not valid anymore and conn object will
521+
* be removed shortly.
522+
*/
523+
if (conn->bhc_flags & BLE_HS_CONN_F_TERMINATED) {
524+
os_mbuf_free_chain(*om);
525+
*om = NULL;
526+
return 0;
527+
}
528+
518529
txom = *om;
519530
*om = NULL;
520531

nimble/host/src/ble_hs_hci_evt.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data,
213213
unsigned int len)
214214
{
215215
const struct ble_hci_ev_disconn_cmp *ev = data;
216-
const struct ble_hs_conn *conn;
216+
struct ble_hs_conn *conn;
217217

218218
if (len != sizeof(*ev)) {
219219
return BLE_HS_ECONTROLLER;
@@ -223,6 +223,7 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data,
223223
conn = ble_hs_conn_find(le16toh(ev->conn_handle));
224224
if (conn != NULL) {
225225
ble_hs_hci_add_avail_pkts(conn->bhc_outstanding_pkts);
226+
conn->bhc_flags |= BLE_HS_CONN_F_TERMINATED;
226227
}
227228
ble_hs_unlock();
228229

0 commit comments

Comments
 (0)