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 8d6b357f..a6720384 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -150,6 +150,13 @@ class BluetoothMeshService(private val context: Context) { } override fun onPeerRemoved(peerID: String) { try { gossipSyncManager.removeAnnouncementForPeer(peerID) } catch (_: Exception) { } + // Also drop any Noise session state for this peer when they go offline + try { + encryptionService.removePeer(peerID) + Log.d(TAG, "Removed Noise session for offline peer $peerID") + } catch (e: Exception) { + Log.w(TAG, "Failed to remove Noise session for $peerID: ${e.message}") + } } } diff --git a/app/src/main/java/com/bitchat/android/mesh/SecurityManager.kt b/app/src/main/java/com/bitchat/android/mesh/SecurityManager.kt index f763424a..42f6e356 100644 --- a/app/src/main/java/com/bitchat/android/mesh/SecurityManager.kt +++ b/app/src/main/java/com/bitchat/android/mesh/SecurityManager.kt @@ -101,9 +101,17 @@ class SecurityManager(private val encryptionService: EncryptionService, private // Skip our own handshake messages if (peerID == myPeerID) return false + // If we already have an established session but the peer is initiating a new handshake, + // drop the existing session so we can re-establish cleanly. + var forcedRehandshake = false if (encryptionService.hasEstablishedSession(peerID)) { - Log.d(TAG, "Handshake already completed with $peerID") - return true + Log.d(TAG, "Received new Noise handshake from $peerID with an existing session. Dropping old session to re-handshake.") + try { + encryptionService.removePeer(peerID) + forcedRehandshake = true + } catch (e: Exception) { + Log.w(TAG, "Failed to remove existing Noise session for $peerID: ${e.message}") + } } if (packet.payload.isEmpty()) { @@ -114,7 +122,7 @@ class SecurityManager(private val encryptionService: EncryptionService, private // Prevent duplicate handshake processing val exchangeKey = "$peerID-${packet.payload.sliceArray(0 until minOf(16, packet.payload.size)).contentHashCode()}" - if (processedKeyExchanges.contains(exchangeKey)) { + if (!forcedRehandshake && processedKeyExchanges.contains(exchangeKey)) { Log.d(TAG, "Already processed handshake: $exchangeKey") return false }