Fix runtime crashes and reduce excessive logging

- Fix Dictionary crash in ChatViewModel by adding deduplication logic for peer IDs
- Fix compilation errors: PeerData -> BitchatPeer type correction
- Fix Task async context issue with cancellables
- Remove excessive debug logging for handshake coordination
- Remove repetitive keep-alive timer logs
- Remove version cache logging spam
This commit is contained in:
jack
2025-08-01 21:39:09 +02:00
parent 172b06721b
commit 8ec39f566d
3 changed files with 6 additions and 20 deletions
@@ -85,8 +85,6 @@ class NoiseHandshakeCoordinator {
// Check role // Check role
let role = determineHandshakeRole(myPeerID: myPeerID, remotePeerID: remotePeerID) let role = determineHandshakeRole(myPeerID: myPeerID, remotePeerID: remotePeerID)
if role != .initiator { if role != .initiator {
SecureLogger.log("Not initiator for handshake with \(remotePeerID) (my: \(myPeerID), their: \(remotePeerID))",
category: SecureLogger.handshake, level: .debug)
return false return false
} }
@@ -6356,15 +6356,11 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
let currentPeerID = fingerprintToPeerID[fingerprint], let currentPeerID = fingerprintToPeerID[fingerprint],
currentPeerID == peerID else { currentPeerID == peerID else {
// This peer ID has rotated, skip it // This peer ID has rotated, skip it
SecureLogger.log("Skipping keepalive for rotated peer ID: \(peerID)",
category: SecureLogger.session, level: .debug)
return nil return nil
} }
// Check if we actually have a Noise session with this peer // Check if we actually have a Noise session with this peer
guard noiseService.hasEstablishedSession(with: peerID) else { guard noiseService.hasEstablishedSession(with: peerID) else {
SecureLogger.log("Skipping keepalive for \(peerID) - no established session",
category: SecureLogger.session, level: .debug)
return nil return nil
} }
@@ -6372,21 +6368,15 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
} }
} }
SecureLogger.log("Keep-alive timer: checking \(connectedPeers.count) peers for pings",
category: SecureLogger.session, level: .debug)
for peerID in connectedPeers { for peerID in connectedPeers {
// Don't spam if we recently heard from them // Don't spam if we recently heard from them
let lastHeard = self.peerSessions[peerID]?.lastHeardFromPeer let lastHeard = self.peerSessions[peerID]?.lastHeardFromPeer
if let lastHeard = lastHeard, if let lastHeard = lastHeard,
Date().timeIntervalSince(lastHeard) < keepAliveInterval / 2 { Date().timeIntervalSince(lastHeard) < keepAliveInterval / 2 {
SecureLogger.log("Skipping keepalive for \(peerID) - heard recently",
category: SecureLogger.session, level: .debug)
continue // Skip if we heard from them in the last 10 seconds continue // Skip if we heard from them in the last 10 seconds
} }
SecureLogger.log("Sending keepalive ping to \(peerID)",
category: SecureLogger.session, level: .debug)
validateNoiseSession(with: peerID) validateNoiseSession(with: peerID)
} }
} }
@@ -6485,8 +6475,6 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
} }
// Check with coordinator if we should initiate // Check with coordinator if we should initiate
SecureLogger.log("Checking handshake coordinator - myPeerID: \(myPeerID), remotePeerID: \(peerID), hasPending: \(hasPendingMessages)",
category: SecureLogger.handshake, level: .debug)
if !handshakeCoordinator.shouldInitiateHandshake(myPeerID: myPeerID, remotePeerID: peerID, forceIfStale: hasPendingMessages) { if !handshakeCoordinator.shouldInitiateHandshake(myPeerID: myPeerID, remotePeerID: peerID, forceIfStale: hasPendingMessages) {
// Coordinator says no handshake // Coordinator says no handshake
@@ -7107,9 +7095,6 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
// Check version cache for this peer // Check version cache for this peer
if let cached = versionCache[peerID], !cached.isExpired { if let cached = versionCache[peerID], !cached.isExpired {
// Skip negotiation - use cached version // Skip negotiation - use cached version
SecureLogger.log("📗 Using cached version \(cached.version) for \(peerID) (cached \(Int(Date().timeIntervalSince(cached.cachedAt)))s ago)",
category: SecureLogger.session, level: .info)
negotiatedVersions[peerID] = cached.version negotiatedVersions[peerID] = cached.version
versionNegotiationState[peerID] = .ackReceived(version: cached.version) versionNegotiationState[peerID] = .ackReceived(version: cached.version)
+6 -3
View File
@@ -208,7 +208,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
peerManager?.updatePeers() peerManager?.updatePeers()
// Bind peer manager's peer list to our published property // Bind peer manager's peer list to our published property
peerManager?.$peers let cancellable = peerManager?.$peers
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] peers in .sink { [weak self] peers in
SecureLogger.log("📱 UI: Received \(peers.count) peers from PeerManager", SecureLogger.log("📱 UI: Received \(peers.count) peers from PeerManager",
@@ -221,7 +221,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
self?.allPeers = peers self?.allPeers = peers
// Update peer index for O(1) lookups // Update peer index for O(1) lookups
// Deduplicate peers by ID to prevent crash from duplicate keys // Deduplicate peers by ID to prevent crash from duplicate keys
var uniquePeers: [String: PeerData] = [:] var uniquePeers: [String: BitchatPeer] = [:]
for peer in peers { for peer in peers {
// Keep the first occurrence of each peer ID // Keep the first occurrence of each peer ID
if uniquePeers[peer.id] == nil { if uniquePeers[peer.id] == nil {
@@ -242,7 +242,10 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
self?.updatePrivateChatPeerIfNeeded() self?.updatePrivateChatPeerIfNeeded()
} }
} }
.store(in: &cancellables)
if let cancellable = cancellable {
self.cancellables.insert(cancellable)
}
} }
// Set up Noise encryption callbacks // Set up Noise encryption callbacks