mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 01:45:20 +00:00
Logs/robustness: debounce disconnect notifications (1.5s), debounce 'reconnected' logs (2s), add weak-link cooldown after timeouts on very weak RSSI (<= -90)
This commit is contained in:
@@ -328,7 +328,6 @@
|
||||
A2E8C336FA1ADBEC03261DFD /* bitchatShareExtension */,
|
||||
C3D98EB3E1B455E321F519F4 /* bitchatTests */,
|
||||
9F37F9F2C353B58AC809E93B /* Products */,
|
||||
048A4BE52E5CCC5C00162C4A /* Recovered References */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -743,14 +742,13 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
048A4BE72E5CCCC300162C4A /* TransportConfig.swift in Sources */,
|
||||
1234567890ABCDEFFEDCBA13 /* PeerDisplayNameResolver.swift in Sources */,
|
||||
048A4BE72E5CCCC300162C4A /* TransportConfig.swift in Sources */,
|
||||
1234567890ABCDEFFEDCBA13 /* PeerDisplayNameResolver.swift in Sources */,
|
||||
AA77BB12CC22DD33EE44FF56 /* VerificationService.swift in Sources */,
|
||||
AA77BB15CC22DD33EE44FF59 /* VerificationViews.swift in Sources */,
|
||||
A1B2C3D54E5F60718293A4B6 /* XChaCha20Poly1305Compat.swift in Sources */,
|
||||
AD11E46940D742AEAF547EB2 /* AppInfoView.swift in Sources */,
|
||||
9B51E9B63A3EA59B1A7874BD /* BinaryEncodingUtils.swift in Sources */,
|
||||
|
||||
049BD3B42E51F319001A566B /* NostrTransport.swift in Sources */,
|
||||
049BD3B52E51F319001A566B /* MessageRouter.swift in Sources */,
|
||||
4B747085D07A1BCE0F5BA612 /* BinaryProtocol.swift in Sources */,
|
||||
@@ -803,14 +801,13 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
048A4BE82E5CCCC300162C4A /* TransportConfig.swift in Sources */,
|
||||
1234567890ABCDEFFEDCBA14 /* PeerDisplayNameResolver.swift in Sources */,
|
||||
048A4BE82E5CCCC300162C4A /* TransportConfig.swift in Sources */,
|
||||
1234567890ABCDEFFEDCBA14 /* PeerDisplayNameResolver.swift in Sources */,
|
||||
AA77BB11CC22DD33EE44FF55 /* VerificationService.swift in Sources */,
|
||||
AA77BB14CC22DD33EE44FF58 /* VerificationViews.swift in Sources */,
|
||||
A1B2C3D44E5F60718293A4B5 /* XChaCha20Poly1305Compat.swift in Sources */,
|
||||
ABAF130D88561F4A646F0430 /* AppInfoView.swift in Sources */,
|
||||
AFB6AEFCABBE97441CB3102B /* BinaryEncodingUtils.swift in Sources */,
|
||||
|
||||
049BD3B22E51F319001A566B /* NostrTransport.swift in Sources */,
|
||||
049BD3B32E51F319001A566B /* MessageRouter.swift in Sources */,
|
||||
F455F011B3B648ADA233F998 /* BinaryProtocol.swift in Sources */,
|
||||
@@ -1007,7 +1004,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.2;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat.ShareExtension;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
@@ -1038,7 +1035,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.2;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
|
||||
PRODUCT_NAME = bitchat;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1093,7 +1090,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.2;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
|
||||
PRODUCT_NAME = bitchat;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1125,7 +1122,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 1.3.1;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
|
||||
PRODUCT_NAME = bitchat;
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
@@ -1214,7 +1211,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 1.3.1;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
|
||||
PRODUCT_NAME = bitchat;
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
@@ -1307,7 +1304,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.2;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat.ShareExtension;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
|
||||
@@ -128,9 +128,13 @@ final class BLEService: NSObject {
|
||||
|
||||
// Backpressure-aware write queue per peripheral
|
||||
private var pendingPeripheralWrites: [String: [Data]] = [:]
|
||||
// Debounce duplicate disconnect notifies
|
||||
private var recentDisconnectNotifies: [String: Date] = [:]
|
||||
// Store-and-forward for directed messages when we have no links
|
||||
// Keyed by recipient short peerID -> messageID -> (packet, enqueuedAt)
|
||||
private var pendingDirectedRelays: [String: [String: (packet: BitchatPacket, enqueuedAt: Date)]] = [:]
|
||||
// Debounce for 'reconnected' logs
|
||||
private var lastReconnectLogAt: [String: Date] = [:]
|
||||
|
||||
// MARK: - Maintenance Timer
|
||||
|
||||
@@ -1494,12 +1498,19 @@ final class BLEService: NSObject {
|
||||
)
|
||||
}
|
||||
|
||||
// Log connection status only for direct connectivity changes to avoid flapping on relayed announces
|
||||
// Log connection status only for direct connectivity changes; debounce to reduce spam
|
||||
if isDirectAnnounce || hasPeripheralConnection || hasCentralSubscription {
|
||||
let now = Date()
|
||||
if existingPeer == nil {
|
||||
SecureLogger.log("🆕 New peer: \(announcement.nickname)", category: SecureLogger.session, level: .debug)
|
||||
} else if wasDisconnected {
|
||||
SecureLogger.log("🔄 Peer \(announcement.nickname) reconnected", category: SecureLogger.session, level: .debug)
|
||||
// Debounce 'reconnected' logs within short window
|
||||
if let last = lastReconnectLogAt[peerID], now.timeIntervalSince(last) < TransportConfig.bleReconnectLogDebounceSeconds {
|
||||
// Skip duplicate log
|
||||
} else {
|
||||
SecureLogger.log("🔄 Peer \(announcement.nickname) reconnected", category: SecureLogger.session, level: .debug)
|
||||
lastReconnectLogAt[peerID] = now
|
||||
}
|
||||
} else if existingPeer?.nickname != announcement.nickname {
|
||||
SecureLogger.log("🔄 Peer \(peerID) changed nickname: \(existingPeer?.nickname ?? "Unknown") -> \(announcement.nickname)", category: SecureLogger.session, level: .debug)
|
||||
}
|
||||
@@ -1898,6 +1909,18 @@ final class BLEService: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
// Debounced disconnect notifier to avoid duplicate disconnect callbacks within a short window
|
||||
private func notifyPeerDisconnectedDebounced(_ peerID: String) {
|
||||
let now = Date()
|
||||
let last = recentDisconnectNotifies[peerID]
|
||||
if last == nil || now.timeIntervalSince(last!) >= TransportConfig.bleDisconnectNotifyDebounceSeconds {
|
||||
delegate?.didDisconnectFromPeer(peerID)
|
||||
recentDisconnectNotifies[peerID] = now
|
||||
} else {
|
||||
// Suppressed duplicate disconnect notification
|
||||
}
|
||||
}
|
||||
|
||||
// NEW: Publish peer snapshots to subscribers and notify Transport delegates
|
||||
private func publishFullPeerData() {
|
||||
let transportPeers: [TransportPeerSnapshot] = collectionsQueue.sync {
|
||||
@@ -2422,7 +2445,7 @@ func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeriph
|
||||
let currentPeerIDs = self.collectionsQueue.sync { Array(self.peers.keys) }
|
||||
|
||||
if let peerID = peerID {
|
||||
self.delegate?.didDisconnectFromPeer(peerID)
|
||||
self.notifyPeerDisconnectedDebounced(peerID)
|
||||
}
|
||||
self.publishFullPeerData()
|
||||
self.delegate?.didUpdatePeerList(currentPeerIDs)
|
||||
@@ -2474,6 +2497,18 @@ extension BLEService {
|
||||
guard candidate.isConnectable else { return }
|
||||
let peripheral = candidate.peripheral
|
||||
let peripheralID = peripheral.identifier.uuidString
|
||||
// Weak-link cooldown: if we recently timed out and RSSI is very weak, delay retries
|
||||
if let lastTO = recentConnectTimeouts[peripheralID] {
|
||||
let elapsed = Date().timeIntervalSince(lastTO)
|
||||
if elapsed < TransportConfig.bleWeakLinkCooldownSeconds && candidate.rssi <= TransportConfig.bleWeakLinkRSSICutoff {
|
||||
// Requeue the candidate and try again later
|
||||
connectionCandidates.append(candidate)
|
||||
let remaining = TransportConfig.bleWeakLinkCooldownSeconds - elapsed
|
||||
let delay = min(max(2.0, remaining), 15.0)
|
||||
bleQueue.asyncAfter(deadline: .now() + delay) { [weak self] in self?.tryConnectFromQueue() }
|
||||
return
|
||||
}
|
||||
}
|
||||
if peripherals[peripheralID]?.isConnected == true || peripherals[peripheralID]?.isConnecting == true {
|
||||
// Already in progress; skip
|
||||
bleQueue.async { [weak self] in self?.tryConnectFromQueue() }
|
||||
@@ -2811,7 +2846,7 @@ extension BLEService: CBPeripheralManagerDelegate {
|
||||
// Get current peer list (after removal)
|
||||
let currentPeerIDs = self.collectionsQueue.sync { Array(self.peers.keys) }
|
||||
|
||||
self.delegate?.didDisconnectFromPeer(peerID)
|
||||
self.notifyPeerDisconnectedDebounced(peerID)
|
||||
self.delegate?.didUpdatePeerList(currentPeerIDs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,14 @@ enum TransportConfig {
|
||||
// Store-and-forward for directed packets at relays
|
||||
static let bleDirectedSpoolWindowSeconds: TimeInterval = 15.0
|
||||
|
||||
// Log/UI debounce windows
|
||||
static let bleDisconnectNotifyDebounceSeconds: TimeInterval = 1.5
|
||||
static let bleReconnectLogDebounceSeconds: TimeInterval = 2.0
|
||||
|
||||
// Weak-link cooldown after connection timeouts
|
||||
static let bleWeakLinkCooldownSeconds: TimeInterval = 30.0
|
||||
static let bleWeakLinkRSSICutoff: Int = -90
|
||||
|
||||
// Content hashing / formatting
|
||||
static let contentKeyPrefixLength: Int = 256
|
||||
static let uiLongMessageLengthThreshold: Int = 2000
|
||||
|
||||
Reference in New Issue
Block a user