Skip to content

Commit

Permalink
nimble/host: Fix disconnect on host connection timeout
Browse files Browse the repository at this point in the history
We don't need to have double loop and lock-unlock host lock when
issuing disconnect. ble_gap_terminate_with_conn() can be used
to disconnect and it can be called with already provided conn object
under host lock.
  • Loading branch information
sjanc committed Feb 14, 2024
1 parent 4080f94 commit d42a0eb
Showing 1 changed file with 49 additions and 62 deletions.
111 changes: 49 additions & 62 deletions nimble/host/src/ble_hs_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,86 +477,73 @@ ble_hs_conn_timer(void)
#endif

struct ble_hs_conn *conn;
ble_npl_time_t now;
int32_t next_exp_in;
ble_npl_time_t now = ble_npl_time_get();
int32_t next_exp_in = BLE_HS_FOREVER;
int32_t next_exp_in_new;
bool next_exp_in_updated;
int32_t time_diff;
uint16_t conn_handle;

for (;;) {
conn_handle = BLE_HS_CONN_HANDLE_NONE;
next_exp_in = BLE_HS_FOREVER;
now = ble_npl_time_get();
ble_hs_lock();

ble_hs_lock();

/* This loop performs one of two tasks:
* 1. Determine if any connections need to be terminated due to timeout.
* If so, break out of the loop and terminate the connection. This
* function will need to be executed again.
* 2. Otherwise, determine when the next timeout will occur.
*/
SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) {
/* This loop performs one of two tasks:
* 1. Determine if any connections need to be terminated due to timeout. If
* so connection is disconnected.
* 2. Otherwise, determine when the next timeout will occur.
*/
SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) {
next_exp_in_updated = false;

#if MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT) != 0
/* Check each connection's rx fragment timer. If too much time
* passes after a partial packet is received, the connection is
* terminated.
*/
if (conn->bhc_rx_chan != NULL) {
time_diff = conn->bhc_rx_timeout - now;

if (time_diff <= 0) {
/* ACL reassembly has timed out. Remember the connection
* handle so it can be terminated after the mutex is
* unlocked.
*/
conn_handle = conn->bhc_handle;
break;
}

/* Determine if this connection is the soonest to time out. */
if (time_diff < next_exp_in) {
next_exp_in = time_diff;
}
}
#endif
/* Check each connection's rx fragment timer. If too much time
* passes after a partial packet is received, the connection is
* terminated.
*/
if (conn->bhc_rx_chan != NULL) {
time_diff = conn->bhc_rx_timeout - now;

#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO
/* Check each connection's rx queued write timer. If too much
* time passes after a prep write is received, the queue is
* cleared.
*/
time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now);
if (time_diff <= 0) {
/* ACL reassembly has timed out. Remember the connection
* handle so it can be terminated after the mutex is
* unlocked.
*/
conn_handle = conn->bhc_handle;
break;
/* ACL reassembly has timed out.*/
ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM);
continue;
}

/* Determine if this connection is the soonest to time out. */
if (time_diff < next_exp_in) {
next_exp_in = time_diff;
next_exp_in_new = time_diff;
next_exp_in_updated = true;
}
}
#endif

#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO
/* Check each connection's rx queued write timer. If too much
* time passes after a prep write is received, the queue is
* cleared.
*/
time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now);
if (time_diff <= 0) {
/* Queued write has timed out.*/
ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM);
continue;
}
}

ble_hs_unlock();
/* Determine if this connection is the soonest to time out. */
if (time_diff < next_exp_in) {
next_exp_in_new = time_diff;
next_exp_in_updated = true;
}
#endif

/* If a connection has timed out, terminate it. We need to repeatedly
* call this function again to determine when the next timeout is.
*/
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
continue;
if (next_exp_in_updated) {
next_exp_in = next_exp_in_new;
}
}

return next_exp_in;
}

ble_hs_unlock();

return next_exp_in;
}

int
Expand Down

0 comments on commit d42a0eb

Please sign in to comment.