mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-04-14 04:55:44 +00:00
BLE stability: defer disconnect processing, fix data races, harden operations
Critical fixes for NimBLE host task / BLE loop task concurrency: - Defer all disconnect map cleanup from NimBLE callbacks to loop task via SPSC ring buffer, preventing iterator invalidation and use-after-free - Defer enterErrorRecovery() from callback context to loop task - Add WDT feed in enterErrorRecovery() host-sync polling loop Operational hardening: - Cache NimBLERemoteCharacteristic* pointers in write() to avoid repeated service/characteristic lookups per fragment - Add isConnected() checks before GATT operations (read, enableNotifications) - Validate peer address in notification callback to guard against handle reuse - Skip stuck-state detector during CONNECTING/CONN_STARTING states - Expire stale pending data entries after HANDSHAKE_TIMEOUT (30s) - Read actual connection RSSI via ble_gap_conn_rssi() for peripheral connections instead of hardcoding 0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -220,6 +220,14 @@ void BLEInterface::loop() {
|
||||
if (resolved.size() == Limits::IDENTITY_SIZE) {
|
||||
stored_id = resolved;
|
||||
} else {
|
||||
// Expire entries that have waited longer than HANDSHAKE_TIMEOUT.
|
||||
// If a peer sends data but never completes handshake (e.g., disconnect
|
||||
// during handshake), these entries would stay indefinitely.
|
||||
if (now - _pending_data_pool[i].queued_at > Timing::HANDSHAKE_TIMEOUT) {
|
||||
DEBUG("BLEInterface: Expiring stale pending data (no identity after " +
|
||||
std::to_string((int)(now - _pending_data_pool[i].queued_at)) + "s)");
|
||||
continue; // Drop this entry
|
||||
}
|
||||
// Still no identity — keep for next loop iteration
|
||||
if (requeue_count != i) {
|
||||
_pending_data_pool[requeue_count] = _pending_data_pool[i];
|
||||
@@ -759,8 +767,8 @@ void BLEInterface::onCentralConnected(const ConnectionHandle& conn) {
|
||||
|
||||
Bytes mac = conn.peer_address.toBytes();
|
||||
|
||||
// Update peer manager
|
||||
_peer_manager.addDiscoveredPeer(mac, 0);
|
||||
// Update peer manager with connection RSSI
|
||||
_peer_manager.addDiscoveredPeer(mac, conn.rssi);
|
||||
_peer_manager.setPeerState(mac, PeerState::HANDSHAKING);
|
||||
_peer_manager.setPeerHandle(mac, conn.handle);
|
||||
|
||||
@@ -1086,6 +1094,7 @@ void BLEInterface::handleIncomingData(const ConnectionHandle& conn, const Bytes&
|
||||
PendingData& pending = _pending_data_pool[_pending_data_count];
|
||||
pending.identity = mac; // Use MAC as temporary key
|
||||
pending.data = data;
|
||||
pending.queued_at = Utilities::OS::time();
|
||||
_pending_data_count++;
|
||||
}
|
||||
return;
|
||||
@@ -1099,6 +1108,7 @@ void BLEInterface::handleIncomingData(const ConnectionHandle& conn, const Bytes&
|
||||
PendingData& pending = _pending_data_pool[_pending_data_count];
|
||||
pending.identity = identity;
|
||||
pending.data = data;
|
||||
pending.queued_at = Utilities::OS::time();
|
||||
_pending_data_count++;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user