From e31164952535b07bf0230e1835cd0d7eef9c7e3f Mon Sep 17 00:00:00 2001 From: TheCodeSmith404 <160147037+TheCodeSmith404@users.noreply.github.com> Date: Thu, 30 Jul 2026 10:28:41 +0530 Subject: [PATCH] fix(panic): clear in-memory networking caches, router outbox, and Nostr queues on panic wipe (#807) --- .../android/mesh/BluetoothMeshService.kt | 1 + .../java/com/bitchat/android/mesh/MeshCore.kt | 1 + .../bitchat/android/nostr/NostrRelayManager.kt | 18 ++++++++++++++++++ .../android/service/MeshServiceHolder.kt | 1 + .../bitchat/android/services/MessageRouter.kt | 6 ++++++ .../bitchat/android/sync/GossipSyncManager.kt | 9 +++++++++ .../com/bitchat/android/ui/ChatViewModel.kt | 5 ++++- .../com/bitchat/android/ui/GeohashViewModel.kt | 2 ++ 8 files changed, 42 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt index 9c8f8eef..1ec24690 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -1583,6 +1583,7 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic securityManager.clearAllData() peerManager.clearAllPeers() peerManager.clearAllFingerprints() + try { gossipSyncManager.clear() } catch (_: Exception) { } } catch (e: Exception) { Log.e(TAG, "Error clearing mesh service internal data: ${e.message}") } diff --git a/app/src/main/java/com/bitchat/android/mesh/MeshCore.kt b/app/src/main/java/com/bitchat/android/mesh/MeshCore.kt index 093e3766..6542e6e8 100644 --- a/app/src/main/java/com/bitchat/android/mesh/MeshCore.kt +++ b/app/src/main/java/com/bitchat/android/mesh/MeshCore.kt @@ -987,6 +987,7 @@ class MeshCore( securityManager.clearAllData() peerManager.clearAllPeers() peerManager.clearAllFingerprints() + try { gossipSyncManager.clear() } catch (_: Exception) { } } fun clearAllEncryptionData() { diff --git a/app/src/main/java/com/bitchat/android/nostr/NostrRelayManager.kt b/app/src/main/java/com/bitchat/android/nostr/NostrRelayManager.kt index 3386a014..772e2a60 100644 --- a/app/src/main/java/com/bitchat/android/nostr/NostrRelayManager.kt +++ b/app/src/main/java/com/bitchat/android/nostr/NostrRelayManager.kt @@ -679,6 +679,24 @@ class NostrRelayManager private constructor() { Log.e(TAG, "Failed to clear subscriptions: ${e.message}") } } + + /** + * Clear all subscription tracking, deduplication cache, message queue, and connections for panic mode. + */ + fun clearAllOnPanic() { + try { + val wasConnected = desiredConnected.get() + clearAllSubscriptions() + clearDeduplicationCache() + disconnect() + if (wasConnected) { + desiredConnected.set(true) + } + Log.w(TAG, "🚨 Cleared NostrRelayManager subscriptions, cache, and connections for panic mode") + } catch (e: Exception) { + Log.e(TAG, "Failed to clear NostrRelayManager on panic: ${e.message}") + } + } /** * Get detailed status for all relays diff --git a/app/src/main/java/com/bitchat/android/service/MeshServiceHolder.kt b/app/src/main/java/com/bitchat/android/service/MeshServiceHolder.kt index 1ff4ec29..aea8fce6 100644 --- a/app/src/main/java/com/bitchat/android/service/MeshServiceHolder.kt +++ b/app/src/main/java/com/bitchat/android/service/MeshServiceHolder.kt @@ -136,6 +136,7 @@ object MeshServiceHolder { @Synchronized fun clear() { android.util.Log.d(TAG, "Clearing BluetoothMeshService from holder") + try { sharedGossipSyncManager?.clear() } catch (_: Exception) { } try { sharedGossipSyncManager?.stop() } catch (_: Exception) { } sharedGossipSyncManager = null activeGossipOwners.clear() diff --git a/app/src/main/java/com/bitchat/android/services/MessageRouter.kt b/app/src/main/java/com/bitchat/android/services/MessageRouter.kt index a09fa31e..dc6ad4d2 100644 --- a/app/src/main/java/com/bitchat/android/services/MessageRouter.kt +++ b/app/src/main/java/com/bitchat/android/services/MessageRouter.kt @@ -99,6 +99,12 @@ class MessageRouter private constructor( startOutboxScheduler() } + fun clearAll() { + outbox.clear() + retryState.clear() + Log.d(TAG, "Cleared all MessageRouter outbox messages and retry state") + } + // Listener for favorites changes to flush outbox when npub mapping appears/changes private val favoriteListener = object: com.bitchat.android.favorites.FavoritesChangeListener { diff --git a/app/src/main/java/com/bitchat/android/sync/GossipSyncManager.kt b/app/src/main/java/com/bitchat/android/sync/GossipSyncManager.kt index 5c786365..42a10ceb 100644 --- a/app/src/main/java/com/bitchat/android/sync/GossipSyncManager.kt +++ b/app/src/main/java/com/bitchat/android/sync/GossipSyncManager.kt @@ -79,6 +79,15 @@ class GossipSyncManager( cleanupJob?.cancel(); cleanupJob = null } + @Synchronized + fun clear() { + synchronized(messages) { + messages.clear() + } + latestAnnouncementByPeer.clear() + Log.d(TAG, "Cleared all gossip sync messages and announcements") + } + fun scheduleInitialSync(delayMs: Long = 5_000L) { scope.launch(Dispatchers.IO) { delay(delayMs) diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index 61c88523..16933537 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -1445,10 +1445,13 @@ class ChatViewModel( dataManager.clearAllData() conversationListPreferences.clearAll() - // Clear seen message store + // Clear seen message store and MessageRouter outbox try { com.bitchat.android.services.SeenMessageStore.getInstance(getApplication()).clear() } catch (_: Exception) { } + try { + com.bitchat.android.services.MessageRouter.tryGetInstance()?.clearAll() + } catch (_: Exception) { } // Clear all cryptographic data clearAllCryptographicData() diff --git a/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt b/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt index d2b706ec..63a5c0a7 100644 --- a/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/GeohashViewModel.kt @@ -119,6 +119,8 @@ class GeohashViewModel( geoTimer = null try { NostrIdentityBridge.clearAllAssociations(getApplication()) } catch (_: Exception) {} NostrBackgroundRuntime.resetSubscriptions() + try { com.bitchat.android.nostr.NostrRelayManager.getInstance(getApplication()).clearAllOnPanic() } catch (_: Exception) {} + try { com.bitchat.android.nostr.LocationNotesManager.getInstance().stop() } catch (_: Exception) {} } fun sendGeohashMessage(content: String, channel: com.bitchat.android.geohash.GeohashChannel, myPeerID: String, nickname: String?) {