Clear the bridge backoff on re-enable and fail the table build closed

set_enabled(true) resets the hold-off (neutral-engine parity), and every
failing build() return now resets the counts so a failed build can never
present a non-empty view.
This commit is contained in:
J. Nick Koston
2026-08-12 17:24:34 -05:00
parent ba10832ed7
commit a41dbed69c
3 changed files with 15 additions and 5 deletions
@@ -57,7 +57,13 @@ void BLEClient::set_enabled(bool enabled) {
if (!enabled) {
ESP_LOGI(TAG, "[%s] Disabling BLE client.", this->address_str());
this->disconnect();
return;
}
#ifdef USE_BLE_CLIENT_GATT_NODES
// A re-enable clears the backoff (neutral-engine parity).
this->gatt_consecutive_failures_ = 0;
this->gatt_hold_off_ms_ = 0;
#endif
}
bool BLEClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
@@ -301,6 +307,7 @@ int BLEClient::notify_characteristic(uint16_t handle, bool enable) {
if (enable) {
for (uint8_t i = 0; i < this->pending_gatt_reg_count_; i++) {
if (this->pending_gatt_regs_[i] == handle) {
// ESP_OK: the in-flight registration's completion fans out to all nodes.
ESP_LOGW(TAG, "[%s] Notify registration already pending for handle 0x%04x", this->address_str(), handle);
return ESP_OK;
}
@@ -111,6 +111,7 @@ bool BluedroidServiceTable::build(esp_gatt_if_t gattc_if, uint16_t conn_id, uint
});
if (!counted) {
ESP_LOGW(TAG, "[%d] Service table walk failed during count", this->log_index_);
this->free();
return false;
}
@@ -124,6 +125,7 @@ bool BluedroidServiceTable::build(esp_gatt_if_t gattc_if, uint16_t conn_id, uint
if (this->storage_ == nullptr) {
ESP_LOGW(TAG, "[%d] Service table allocation failed (%u bytes)", this->log_index_,
static_cast<unsigned>(total_bytes));
this->free();
return false;
}
auto *services = reinterpret_cast<ble_device_base::GattService *>(this->storage_);
@@ -41,13 +41,14 @@ class BluedroidServiceTable {
this->desc_total_};
}
// Always resets the counts: a failed build must never leave a non-zero
// service_total_ behind a null table.
void free() {
if (this->storage_ == nullptr) {
return;
if (this->storage_ != nullptr) {
RAMAllocator<uint8_t> allocator(RAMAllocator<uint8_t>::ALLOC_INTERNAL);
allocator.deallocate(this->storage_, 0);
this->storage_ = nullptr;
}
RAMAllocator<uint8_t> allocator(RAMAllocator<uint8_t>::ALLOC_INTERNAL);
allocator.deallocate(this->storage_, 0);
this->storage_ = nullptr;
this->service_total_ = 0;
this->char_total_ = 0;
this->desc_total_ = 0;