[bluetooth_proxy] Reset every owed reply in one place (#18276)

This commit is contained in:
J. Nick Koston
2026-08-11 19:15:21 -05:00
committed by GitHub
parent 201f843e95
commit 9f28638ee7
2 changed files with 33 additions and 19 deletions
@@ -704,6 +704,31 @@ void BluetoothProxy::bluetooth_set_connection_params(const api::BluetoothSetConn
#endif // !BLUETOOTH_CONNECTION_HAS_GATT
void BluetoothProxy::reset_owed_replies_() {
this->connections_free_pending_ = false;
#ifdef USE_BLE_SCANNER_STATE_CALLBACK
// Owed on unsubscribe; on subscribe the trailing send_scanner_state_()
// re-drives it from the hub, so clearing it there is free.
this->scanner_state_pending_ = false;
#else
// Force a poll-arm mismatch: a frame refused at subscribe time could
// otherwise match the stale detector and never be retried. Inert on
// unsubscribe: loop() returns at the no-subscriber gate before the
// detector runs, and a re-subscribe re-arms this anyway.
this->last_scan_running_ = !this->hub_->scan_running();
#endif
#ifdef BLUETOOTH_CONNECTION_HAS_GATT
this->pending_unpairing_.clear();
this->pending_disconnections_.fill({});
for (uint8_t i = 0; i < this->connection_count_; i++) {
// Neither a partial stream's tail nor an owed done belongs to the next
// session; silence (the client's timeout) arbitrates.
this->connections_[i]->park_service_stream_();
this->connections_[i]->clear_pending_ack_();
}
#endif
}
void BluetoothProxy::subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags) {
if (api_connection != this->api_connection_) {
if (this->api_connection_ != nullptr) {
@@ -720,18 +745,7 @@ void BluetoothProxy::subscribe_api_connection(api::APIConnection *api_connection
}
// Stale retry latches belong to the previous subscriber's session; a
// re-subscribe by the current one keeps what it is still owed.
this->connections_free_pending_ = false;
#ifdef BLUETOOTH_CONNECTION_HAS_GATT
this->pending_unpairing_.clear();
for (uint8_t i = 0; i < this->connection_count_; i++) {
// Neither a partial stream's tail nor an owed done belongs to the new
// session; silence (the client's timeout) arbitrates.
this->connections_[i]->park_service_stream_();
// An ack owed to the previous subscriber means nothing to the new one.
this->connections_[i]->clear_pending_ack_();
}
this->pending_disconnections_.fill({});
#endif
this->reset_owed_replies_();
}
this->api_connection_ = api_connection;
#ifdef USE_BLE_SCANNER_STATE_CALLBACK
@@ -748,13 +762,7 @@ void BluetoothProxy::unsubscribe_api_connection(api::APIConnection *api_connecti
return;
}
this->api_connection_ = nullptr;
this->connections_free_pending_ = false;
#ifdef BLUETOOTH_CONNECTION_HAS_GATT
this->pending_unpairing_.clear();
#endif
#ifdef USE_BLE_SCANNER_STATE_CALLBACK
this->scanner_state_pending_ = false;
#endif
this->reset_owed_replies_();
}
void BluetoothProxy::send_connections_free() {
@@ -286,6 +286,12 @@ class BluetoothProxy final : public Component {
void latch_pending_disconnection_(uint64_t address, conn_err_t error);
#endif
/// Drop everything the ending session was owed. One list, so a new latch is
/// one edit rather than two call sites where an omission looks deliberate.
/// Drops state only, never sends: api_connection_ is the departing
/// subscriber on subscribe and nullptr on unsubscribe.
void reset_owed_replies_();
// Memory optimized layout for 32-bit systems
// Group 1: Pointers (4 bytes each, naturally aligned)
api::APIConnection *api_connection_{nullptr};