Remove grey overlay and reduce logging noise

- Removed grey background overlay during sidebar slide-over for cleaner UI
- Removed excessive logging while keeping critical error/security logs
- Kept only: error conditions, connection events, panic mode, security events
- Significantly reduced console noise for better production readiness
This commit is contained in:
jack
2025-07-04 12:28:00 +02:00
parent f77cec3fb2
commit 2cd8443292
5 changed files with 96 additions and 95 deletions
+2 -2
View File
@@ -261,7 +261,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = com.bitchat.app; PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
PRODUCT_NAME = bitchat; PRODUCT_NAME = bitchat;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
@@ -288,7 +288,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = com.bitchat.app; PRODUCT_BUNDLE_IDENTIFIER = chat.bitchat;
PRODUCT_NAME = bitchat; PRODUCT_NAME = bitchat;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
+85 -85
View File
@@ -99,7 +99,7 @@ class BluetoothMeshService: NSObject {
self.myPeerID = randomBytes.map { String(format: "%02x", $0) }.joined() self.myPeerID = randomBytes.map { String(format: "%02x", $0) }.joined()
super.init() super.init()
print("[STARTUP] Generated ephemeral peer ID: \(myPeerID)") // Generated ephemeral peer ID
centralManager = CBCentralManager(delegate: self, queue: nil) centralManager = CBCentralManager(delegate: self, queue: nil)
peripheralManager = CBPeripheralManager(delegate: self, queue: nil) peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
@@ -200,7 +200,7 @@ class BluetoothMeshService: NSObject {
payload: Data(vm.nickname.utf8) payload: Data(vm.nickname.utf8)
) )
print("[ANNOUNCE] Sending proactive broadcast announce with nickname: \(vm.nickname)") // Sending proactive broadcast announce
// Initial send with random delay // Initial send with random delay
let initialDelay = self.randomDelay() let initialDelay = self.randomDelay()
@@ -326,7 +326,7 @@ class BluetoothMeshService: NSObject {
let signature: Data? let signature: Data?
do { do {
signature = try self.encryptionService.sign(messageData) signature = try self.encryptionService.sign(messageData)
print("[CRYPTO] Successfully signed broadcast message") // Successfully signed broadcast message
} catch { } catch {
print("[CRYPTO] Failed to sign message: \(error)") print("[CRYPTO] Failed to sign message: \(error)")
signature = nil signature = nil
@@ -347,7 +347,7 @@ class BluetoothMeshService: NSObject {
let initialDelay = self.randomDelay() let initialDelay = self.randomDelay()
DispatchQueue.main.asyncAfter(deadline: .now() + initialDelay) { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + initialDelay) { [weak self] in
self?.broadcastPacket(packet) self?.broadcastPacket(packet)
print("[MESSAGE] Sending: \(content) (delayed by \(Int(initialDelay * 1000))ms)") // Sending message
} }
// Retry with randomized delays for reliability // Retry with randomized delays for reliability
@@ -386,13 +386,13 @@ class BluetoothMeshService: NSObject {
// Pad message to standard block size for privacy // Pad message to standard block size for privacy
let blockSize = MessagePadding.optimalBlockSize(for: messageData.count) let blockSize = MessagePadding.optimalBlockSize(for: messageData.count)
let paddedData = MessagePadding.pad(messageData, toSize: blockSize) let paddedData = MessagePadding.pad(messageData, toSize: blockSize)
print("[PRIVACY] Padded message from \(messageData.count) to \(paddedData.count) bytes") // Padded message for privacy
// Encrypt the padded message for the recipient // Encrypt the padded message for the recipient
let encryptedPayload: Data let encryptedPayload: Data
do { do {
encryptedPayload = try self.encryptionService.encrypt(paddedData, for: recipientPeerID) encryptedPayload = try self.encryptionService.encrypt(paddedData, for: recipientPeerID)
print("[CRYPTO] Successfully encrypted private message for \(recipientPeerID)") // Successfully encrypted private message
} catch { } catch {
print("[CRYPTO] Failed to encrypt private message: \(error)") print("[CRYPTO] Failed to encrypt private message: \(error)")
// Don't send unencrypted private messages // Don't send unencrypted private messages
@@ -403,7 +403,7 @@ class BluetoothMeshService: NSObject {
let signature: Data? let signature: Data?
do { do {
signature = try self.encryptionService.sign(encryptedPayload) signature = try self.encryptionService.sign(encryptedPayload)
print("[CRYPTO] Successfully signed private message") // Successfully signed private message
} catch { } catch {
print("[CRYPTO] Failed to sign private message: \(error)") print("[CRYPTO] Failed to sign private message: \(error)")
signature = nil signature = nil
@@ -420,13 +420,13 @@ class BluetoothMeshService: NSObject {
ttl: self.maxTTL ttl: self.maxTTL
) )
print("[PRIVATE] Sending encrypted message to \(recipientPeerID): \(content)") // Sending encrypted private message
// Add random delay for timing obfuscation // Add random delay for timing obfuscation
let delay = self.randomDelay() let delay = self.randomDelay()
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
self?.broadcastPacket(packet) self?.broadcastPacket(packet)
print("[PRIVACY] Private message sent with \(Int(delay * 1000))ms delay") // Private message sent with timing delay
} }
// Don't call didReceiveMessage here - let the view model handle it directly // Don't call didReceiveMessage here - let the view model handle it directly
@@ -437,7 +437,7 @@ class BluetoothMeshService: NSObject {
private func sendAnnouncementToPeer(_ peerID: String) { private func sendAnnouncementToPeer(_ peerID: String) {
guard let vm = delegate as? ChatViewModel else { return } guard let vm = delegate as? ChatViewModel else { return }
print("[ANNOUNCE] Sending announce to \(peerID) with nickname: \(vm.nickname)") // Sending announce to peer
// Always send announce, don't check if already announced // Always send announce, don't check if already announced
// This ensures peers get our nickname even if they reconnect // This ensures peers get our nickname even if they reconnect
@@ -450,20 +450,20 @@ class BluetoothMeshService: NSObject {
) )
if let data = packet.toBinaryData() { if let data = packet.toBinaryData() {
print("[ANNOUNCE] Broadcasting announce packet") // Broadcasting announce packet
// Try both broadcast and targeted send // Try both broadcast and targeted send
broadcastPacket(packet) broadcastPacket(packet)
// Also try targeted send if we have the peripheral // Also try targeted send if we have the peripheral
if let peripheral = connectedPeripherals[peerID], if let peripheral = connectedPeripherals[peerID],
let characteristic = peripheral.services?.first(where: { $0.uuid == BluetoothMeshService.serviceUUID })?.characteristics?.first(where: { $0.uuid == BluetoothMeshService.characteristicUUID }) { let characteristic = peripheral.services?.first(where: { $0.uuid == BluetoothMeshService.serviceUUID })?.characteristics?.first(where: { $0.uuid == BluetoothMeshService.characteristicUUID }) {
print("[ANNOUNCE] Also sending targeted announce to peripheral \(peerID)") // Also sending targeted announce
peripheral.writeValue(data, for: characteristic, type: .withResponse) peripheral.writeValue(data, for: characteristic, type: .withResponse)
} else { } else {
print("[ANNOUNCE] No peripheral found for targeted send to \(peerID)") // No peripheral found for targeted send
} }
} else { } else {
print("[ANNOUNCE] Failed to create binary data for announce packet") // Failed to create binary data for announce packet
} }
announcedToPeers.insert(peerID) announcedToPeers.insert(peerID)
@@ -597,7 +597,7 @@ class BluetoothMeshService: NSObject {
self.favoriteMessageQueue[recipientPeerID]?.removeFirst() self.favoriteMessageQueue[recipientPeerID]?.removeFirst()
} }
print("[CACHE] Cached message for favorite \(recipientPeerID), queue size: \(self.favoriteMessageQueue[recipientPeerID]?.count ?? 0)") // Cached message for favorite
} }
} else { } else {
// Clean up old messages first (only for regular cache) // Clean up old messages first (only for regular cache)
@@ -611,7 +611,7 @@ class BluetoothMeshService: NSObject {
self.messageCache.removeFirst() self.messageCache.removeFirst()
} }
print("[CACHE] Cached message (type: \(packet.type)), cache size: \(self.messageCache.count)") // Cached message
} }
} }
} }
@@ -640,13 +640,13 @@ class BluetoothMeshService: NSObject {
messagesToSend.append(contentsOf: favoriteMessages) messagesToSend.append(contentsOf: favoriteMessages)
// Clear the favorite queue after adding to send list // Clear the favorite queue after adding to send list
self.favoriteMessageQueue[peerID] = nil self.favoriteMessageQueue[peerID] = nil
print("[CACHE] Found \(favoriteMessages.count) favorite messages for \(peerID)") // Found favorite messages
} }
// Then add regular cached messages // Then add regular cached messages
messagesToSend.append(contentsOf: self.messageCache) messagesToSend.append(contentsOf: self.messageCache)
print("[CACHE] Sending \(messagesToSend.count) total cached messages to \(peerID)") // Sending cached messages
// Send cached messages with slight delay between each // Send cached messages with slight delay between each
for (index, storedMessage) in messagesToSend.enumerated() { for (index, storedMessage) in messagesToSend.enumerated() {
@@ -669,7 +669,7 @@ class BluetoothMeshService: NSObject {
if let data = updatedPacket.toBinaryData() { if let data = updatedPacket.toBinaryData() {
peripheral.writeValue(data, for: characteristic, type: .withoutResponse) peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
print("[CACHE] Sent cached message \(index + 1)/\(messagesToSend.count) to \(peerID)") // Sent cached message
} }
} }
} }
@@ -709,7 +709,7 @@ class BluetoothMeshService: NSObject {
peripheral.writeValue(data, for: characteristic, type: writeType) peripheral.writeValue(data, for: characteristic, type: writeType)
sentToPeripherals += 1 sentToPeripherals += 1
} else { } else {
print("[BROADCAST] Peripheral \(peerID) not connected (state: \(peripheral.state.rawValue))") // Peripheral not connected
} }
} else { } else {
// No characteristic for peripheral // No characteristic for peripheral
@@ -724,7 +724,7 @@ class BluetoothMeshService: NSObject {
if success { if success {
// Sent to centrals // Sent to centrals
} else { } else {
print("[BROADCAST] Failed to send to centrals - queue full, will retry on delegate callback") // Failed to send to centrals - queue full
} }
} else { } else {
if characteristic == nil { if characteristic == nil {
@@ -737,13 +737,13 @@ class BluetoothMeshService: NSObject {
messageQueue.async(flags: .barrier) { [weak self] in messageQueue.async(flags: .barrier) { [weak self] in
guard let self = self else { return } guard let self = self else { return }
guard packet.ttl > 0 else { guard packet.ttl > 0 else {
print("[PACKET] Dropping packet with TTL 0") // Dropping packet with TTL 0
return return
} }
// Validate packet has payload // Validate packet has payload
guard !packet.payload.isEmpty else { guard !packet.payload.isEmpty else {
print("[PACKET] Dropping packet with empty payload") // Dropping packet with empty payload
return return
} }
@@ -797,14 +797,14 @@ class BluetoothMeshService: NSObject {
if let recipientID = packet.recipientID { if let recipientID = packet.recipientID {
if recipientID == SpecialRecipients.broadcast { if recipientID == SpecialRecipients.broadcast {
// BROADCAST MESSAGE // BROADCAST MESSAGE
print("[MESSAGE] Received broadcast message") // Received broadcast message
// Verify signature if present // Verify signature if present
if let signature = packet.signature { if let signature = packet.signature {
do { do {
let isValid = try encryptionService.verify(signature, for: packet.payload, from: senderID) let isValid = try encryptionService.verify(signature, for: packet.payload, from: senderID)
if !isValid { if !isValid {
print("[CRYPTO] Invalid signature from \(senderID), dropping message") // Invalid signature, dropping message
return return
} }
} catch { } catch {
@@ -814,7 +814,7 @@ class BluetoothMeshService: NSObject {
// Parse broadcast message (not encrypted) // Parse broadcast message (not encrypted)
if let message = BitchatMessage.fromBinaryPayload(packet.payload) { if let message = BitchatMessage.fromBinaryPayload(packet.payload) {
print("[MESSAGE] Broadcast from \(message.sender): \(message.content)") // Received broadcast message
// Store nickname mapping // Store nickname mapping
peerNicknames[senderID] = message.sender peerNicknames[senderID] = message.sender
@@ -847,14 +847,14 @@ class BluetoothMeshService: NSObject {
} else if let recipientIDString = String(data: recipientID.trimmingNullBytes(), encoding: .utf8), } else if let recipientIDString = String(data: recipientID.trimmingNullBytes(), encoding: .utf8),
recipientIDString == myPeerID { recipientIDString == myPeerID {
// PRIVATE MESSAGE FOR US // PRIVATE MESSAGE FOR US
print("[MESSAGE] Received private message for us") // Received private message
// Verify signature if present // Verify signature if present
if let signature = packet.signature { if let signature = packet.signature {
do { do {
let isValid = try encryptionService.verify(signature, for: packet.payload, from: senderID) let isValid = try encryptionService.verify(signature, for: packet.payload, from: senderID)
if !isValid { if !isValid {
print("[CRYPTO] Invalid signature on private message from \(senderID), dropping") // Invalid signature on private message
return return
} }
} catch { } catch {
@@ -866,11 +866,11 @@ class BluetoothMeshService: NSObject {
let decryptedPayload: Data let decryptedPayload: Data
do { do {
let decryptedPadded = try encryptionService.decrypt(packet.payload, from: senderID) let decryptedPadded = try encryptionService.decrypt(packet.payload, from: senderID)
print("[CRYPTO] Successfully decrypted private message from \(senderID)") // Successfully decrypted private message
// Remove padding // Remove padding
decryptedPayload = MessagePadding.unpad(decryptedPadded) decryptedPayload = MessagePadding.unpad(decryptedPadded)
print("[PRIVACY] Unpadded message from \(decryptedPadded.count) to \(decryptedPayload.count) bytes") // Unpadded message
} catch { } catch {
print("[CRYPTO] Failed to decrypt private message from \(senderID): \(error)") print("[CRYPTO] Failed to decrypt private message from \(senderID): \(error)")
return return
@@ -880,11 +880,11 @@ class BluetoothMeshService: NSObject {
if let message = BitchatMessage.fromBinaryPayload(decryptedPayload) { if let message = BitchatMessage.fromBinaryPayload(decryptedPayload) {
// Check if this is a dummy message for cover traffic // Check if this is a dummy message for cover traffic
if message.content.hasPrefix(self.coverTrafficPrefix) { if message.content.hasPrefix(self.coverTrafficPrefix) {
print("[PRIVACY] Received and discarded cover traffic from \(senderID)") // Received and discarded cover traffic
return // Silently discard dummy messages return // Silently discard dummy messages
} }
print("[MESSAGE] Private from \(senderID): \(message.content)") // Received private message
// Store nickname mapping if we don't have it // Store nickname mapping if we don't have it
if peerNicknames[senderID] == nil { if peerNicknames[senderID] == nil {
@@ -909,7 +909,7 @@ class BluetoothMeshService: NSObject {
} else if packet.ttl > 0 { } else if packet.ttl > 0 {
// RELAY PRIVATE MESSAGE (not for us) // RELAY PRIVATE MESSAGE (not for us)
print("[MESSAGE] Relaying private message not meant for us (TTL: \(packet.ttl))") // Relaying private message
var relayPacket = packet var relayPacket = packet
relayPacket.ttl -= 1 relayPacket.ttl -= 1
@@ -918,7 +918,7 @@ class BluetoothMeshService: NSObject {
let publicKeyData = self.encryptionService.getPeerIdentityKey(recipientIDString) { let publicKeyData = self.encryptionService.getPeerIdentityKey(recipientIDString) {
let fingerprint = self.getPublicKeyFingerprint(publicKeyData) let fingerprint = self.getPublicKeyFingerprint(publicKeyData)
if self.delegate?.isFavorite(fingerprint: fingerprint) ?? false { if self.delegate?.isFavorite(fingerprint: fingerprint) ?? false {
print("[CACHE] Caching relayed message for offline favorite: \(recipientIDString)") // Caching message for offline favorite
self.cacheMessage(relayPacket, messageID: messageID) self.cacheMessage(relayPacket, messageID: messageID)
} }
} }
@@ -934,7 +934,7 @@ class BluetoothMeshService: NSObject {
let publicKeyData = packet.payload let publicKeyData = packet.payload
do { do {
try encryptionService.addPeerPublicKey(senderID, publicKeyData: publicKeyData) try encryptionService.addPeerPublicKey(senderID, publicKeyData: publicKeyData)
print("[KEY_EXCHANGE] Successfully added public key for \(senderID)") // Added public key
} catch { } catch {
print("[KEY_EXCHANGE] Failed to add public key for \(senderID): \(error)") print("[KEY_EXCHANGE] Failed to add public key for \(senderID): \(error)")
} }
@@ -955,13 +955,13 @@ class BluetoothMeshService: NSObject {
// Remove temp mapping and add real peer ID mapping // Remove temp mapping and add real peer ID mapping
self.connectedPeripherals.removeValue(forKey: tempID) self.connectedPeripherals.removeValue(forKey: tempID)
self.connectedPeripherals[senderID] = peripheral self.connectedPeripherals[senderID] = peripheral
print("[KEY_EXCHANGE] Updated peripheral mapping from temp ID \(tempID) to \(senderID)") // Updated peripheral mapping
// Transfer RSSI from temp ID to peer ID // Transfer RSSI from temp ID to peer ID
if let rssi = self.peripheralRSSI[tempID] { if let rssi = self.peripheralRSSI[tempID] {
self.peerRSSI[senderID] = rssi self.peerRSSI[senderID] = rssi
self.peripheralRSSI.removeValue(forKey: tempID) self.peripheralRSSI.removeValue(forKey: tempID)
print("[KEY_EXCHANGE] Transferred RSSI \(rssi) to peer \(senderID)") // Transferred RSSI to peer
} }
} }
} }
@@ -975,7 +975,7 @@ class BluetoothMeshService: NSObject {
} }
// Send announce with our nickname immediately // Send announce with our nickname immediately
print("[KEY_EXCHANGE] Calling sendAnnouncementToPeer for \(senderID)") // Sending announcement to peer
self.sendAnnouncementToPeer(senderID) self.sendAnnouncementToPeer(senderID)
// Check if this peer has cached messages (especially for favorites) // Check if this peer has cached messages (especially for favorites)
@@ -984,7 +984,7 @@ class BluetoothMeshService: NSObject {
} }
case .announce: case .announce:
print("[ANNOUNCE] Processing announce packet, payload size: \(packet.payload.count)") // Processing announce packet
if let nickname = String(data: packet.payload, encoding: .utf8), if let nickname = String(data: packet.payload, encoding: .utf8),
let senderID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) { let senderID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) {
// Received announce from \(senderID): \(nickname) // Received announce from \(senderID): \(nickname)
@@ -999,7 +999,7 @@ class BluetoothMeshService: NSObject {
// Store the nickname // Store the nickname
peerNicknames[senderID] = nickname peerNicknames[senderID] = nickname
print("[ANNOUNCE] Stored nickname for \(senderID): \(nickname)") // Stored nickname
// Updated nicknames // Updated nicknames
// Note: We can't update peripheral mapping here since we don't have // Note: We can't update peripheral mapping here since we don't have
@@ -1031,7 +1031,7 @@ class BluetoothMeshService: NSObject {
NotificationService.shared.sendFavoriteOnlineNotification(nickname: nickname) NotificationService.shared.sendFavoriteOnlineNotification(nickname: nickname)
// Send any cached messages for this favorite // Send any cached messages for this favorite
print("[CACHE] Favorite peer \(senderID) came online, checking for cached messages") // Favorite peer came online
self.sendCachedMessages(to: senderID) self.sendCachedMessages(to: senderID)
} }
} else if let viewModel = self.delegate as? ChatViewModel, } else if let viewModel = self.delegate as? ChatViewModel,
@@ -1050,15 +1050,15 @@ class BluetoothMeshService: NSObject {
} else { } else {
} }
} else { } else {
print("[ANNOUNCE] Failed to decode announce packet - senderID or nickname invalid") // Failed to decode announce packet
} }
case .leave: case .leave:
print("[LEAVE] Processing leave packet") // Processing leave packet
if let nickname = String(data: packet.payload, encoding: .utf8), if let nickname = String(data: packet.payload, encoding: .utf8),
let senderID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) { let senderID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) {
print("[LEAVE] \(nickname) (\(senderID)) is leaving") // Peer is leaving
// Remove from active peers // Remove from active peers
activePeers.remove(senderID) activePeers.remove(senderID)
@@ -1073,17 +1073,17 @@ class BluetoothMeshService: NSObject {
// Clean up peer data // Clean up peer data
peerNicknames.removeValue(forKey: senderID) peerNicknames.removeValue(forKey: senderID)
} else { } else {
print("[LEAVE] Failed to parse leave packet") // Failed to parse leave packet
} }
case .fragmentStart, .fragmentContinue, .fragmentEnd: case .fragmentStart, .fragmentContinue, .fragmentEnd:
let fragmentTypeStr = packet.type == MessageType.fragmentStart.rawValue ? "START" : let fragmentTypeStr = packet.type == MessageType.fragmentStart.rawValue ? "START" :
(packet.type == MessageType.fragmentContinue.rawValue ? "CONTINUE" : "END") (packet.type == MessageType.fragmentContinue.rawValue ? "CONTINUE" : "END")
print("[PACKET] Handling fragment type: \(fragmentTypeStr) (\(packet.type)), payload size: \(packet.payload.count), from: \(peerID)") // Handling fragment
// Validate fragment has minimum required size // Validate fragment has minimum required size
if packet.payload.count < 13 { if packet.payload.count < 13 {
print("[PACKET] Fragment payload too small: \(packet.payload.count) bytes, dropping") // Fragment payload too small
return return
} }
@@ -1093,7 +1093,7 @@ class BluetoothMeshService: NSObject {
var relayPacket = packet var relayPacket = packet
relayPacket.ttl -= 1 relayPacket.ttl -= 1
if relayPacket.ttl > 0 { if relayPacket.ttl > 0 {
print("[PACKET] Relaying fragment with TTL: \(relayPacket.ttl)") // Relaying fragment
self.broadcastPacket(relayPacket) self.broadcastPacket(relayPacket)
} }
@@ -1116,9 +1116,9 @@ class BluetoothMeshService: NSObject {
fullData[offset..<min(offset + maxFragmentSize, fullData.count)] fullData[offset..<min(offset + maxFragmentSize, fullData.count)]
} }
print("[FRAGMENT] Splitting into \(fragments.count) fragments of max \(maxFragmentSize) bytes") // Splitting into fragments
print("[FRAGMENT] Fragment ID: \(fragmentID.hexEncodedString())") // Fragment ID generated
print("[FRAGMENT] Original packet size: \(fullData.count) bytes") // Original packet size
// Optimize fragment transmission for speed // Optimize fragment transmission for speed
// Use minimal delay for BLE 5.0 which supports better throughput // Use minimal delay for BLE 5.0 which supports better throughput
@@ -1158,19 +1158,19 @@ class BluetoothMeshService: NSObject {
// Send fragments on background queue with calculated delay // Send fragments on background queue with calculated delay
messageQueue.asyncAfter(deadline: .now() + totalDelay) { [weak self] in messageQueue.asyncAfter(deadline: .now() + totalDelay) { [weak self] in
self?.broadcastPacket(fragmentPacket) self?.broadcastPacket(fragmentPacket)
print("[FRAGMENT] Sent fragment \(index + 1)/\(fragments.count) type: \(fragmentType) at +\(totalDelay)s") // Sent fragment
} }
} }
let totalTime = Double(fragments.count - 1) * delayBetweenFragments let totalTime = Double(fragments.count - 1) * delayBetweenFragments
print("[FRAGMENT] Total send time: \(totalTime)s for \(fragments.count) fragments") // Total fragment send time
} }
private func handleFragment(_ packet: BitchatPacket, from peerID: String) { private func handleFragment(_ packet: BitchatPacket, from peerID: String) {
print("[FRAGMENT] Starting to handle fragment, payload size: \(packet.payload.count)") // Handling fragment
guard packet.payload.count >= 13 else { guard packet.payload.count >= 13 else {
print("[FRAGMENT] Payload too small: \(packet.payload.count) bytes (need at least 13)") // Fragment payload too small
return return
} }
@@ -1180,41 +1180,41 @@ class BluetoothMeshService: NSObject {
// Extract fragment ID as binary data (8 bytes) // Extract fragment ID as binary data (8 bytes)
guard payloadArray.count >= 8 else { guard payloadArray.count >= 8 else {
print("[FRAGMENT] Payload too small for fragment ID") // Payload too small for fragment ID
return return
} }
let fragmentIDData = Data(payloadArray[0..<8]) let fragmentIDData = Data(payloadArray[0..<8])
let fragmentID = fragmentIDData.hexEncodedString() let fragmentID = fragmentIDData.hexEncodedString()
print("[FRAGMENT] Fragment ID: \(fragmentID)") // Fragment ID
offset = 8 offset = 8
// Safely extract index // Safely extract index
guard payloadArray.count >= offset + 2 else { guard payloadArray.count >= offset + 2 else {
print("[FRAGMENT] Not enough data for index at offset \(offset)") // Not enough data for index
return return
} }
let index = Int(payloadArray[offset]) << 8 | Int(payloadArray[offset + 1]) let index = Int(payloadArray[offset]) << 8 | Int(payloadArray[offset + 1])
offset += 2 offset += 2
print("[FRAGMENT] Index: \(index)") // Fragment index
// Safely extract total // Safely extract total
guard payloadArray.count >= offset + 2 else { guard payloadArray.count >= offset + 2 else {
print("[FRAGMENT] Not enough data for total at offset \(offset)") // Not enough data for total
return return
} }
let total = Int(payloadArray[offset]) << 8 | Int(payloadArray[offset + 1]) let total = Int(payloadArray[offset]) << 8 | Int(payloadArray[offset + 1])
offset += 2 offset += 2
print("[FRAGMENT] Total fragments: \(total)") // Total fragments
// Safely extract original type // Safely extract original type
guard payloadArray.count >= offset + 1 else { guard payloadArray.count >= offset + 1 else {
print("[FRAGMENT] Not enough data for type at offset \(offset)") // Not enough data for type
return return
} }
let originalType = payloadArray[offset] let originalType = payloadArray[offset]
offset += 1 offset += 1
print("[FRAGMENT] Original type: \(originalType)") // Original type
// Extract fragment data // Extract fragment data
let fragmentData: Data let fragmentData: Data
@@ -1224,19 +1224,19 @@ class BluetoothMeshService: NSObject {
fragmentData = Data() fragmentData = Data()
} }
print("[FRAGMENT] Received fragment \(index + 1)/\(total) for ID: \(fragmentID), data size: \(fragmentData.count)") // Received fragment
// Initialize fragment collection if needed // Initialize fragment collection if needed
if incomingFragments[fragmentID] == nil { if incomingFragments[fragmentID] == nil {
incomingFragments[fragmentID] = [:] incomingFragments[fragmentID] = [:]
fragmentMetadata[fragmentID] = (originalType, total, Date()) fragmentMetadata[fragmentID] = (originalType, total, Date())
print("[FRAGMENT] Started collecting fragments for ID: \(fragmentID), expecting \(total) fragments") // Started collecting fragments
} }
// Store fragment // Store fragment
incomingFragments[fragmentID]?[index] = fragmentData incomingFragments[fragmentID]?[index] = fragmentData
print("[FRAGMENT] Progress for ID \(fragmentID): \(incomingFragments[fragmentID]?.count ?? 0)/\(total) fragments collected") // Fragment collection progress
// Check if we have all fragments // Check if we have all fragments
if let fragments = incomingFragments[fragmentID], if let fragments = incomingFragments[fragmentID],
@@ -1248,12 +1248,12 @@ class BluetoothMeshService: NSObject {
if let fragment = fragments[i] { if let fragment = fragments[i] {
reassembledData.append(fragment) reassembledData.append(fragment)
} else { } else {
print("[FRAGMENT] Missing fragment \(i) for ID: \(fragmentID)") // Missing fragment
return return
} }
} }
print("[FRAGMENT] Successfully reassembled \(total) fragments into \(reassembledData.count) bytes") // Successfully reassembled fragments
// Parse and handle the reassembled packet // Parse and handle the reassembled packet
if let reassembledPacket = BitchatPacket.from(reassembledData) { if let reassembledPacket = BitchatPacket.from(reassembledData) {
@@ -1272,7 +1272,7 @@ class BluetoothMeshService: NSObject {
if metadata.timestamp < cutoffTime { if metadata.timestamp < cutoffTime {
incomingFragments.removeValue(forKey: fragID) incomingFragments.removeValue(forKey: fragID)
fragmentMetadata.removeValue(forKey: fragID) fragmentMetadata.removeValue(forKey: fragID)
print("[FRAGMENT] Cleaned up expired fragments for ID: \(fragID)") // Cleaned up expired fragments
} }
} }
} }
@@ -1313,7 +1313,7 @@ extension BluetoothMeshService: CBCentralManagerDelegate {
// Assume 8-character names are peer IDs // Assume 8-character names are peer IDs
let peerID = name let peerID = name
peerRSSI[peerID] = RSSI peerRSSI[peerID] = RSSI
print("[BLUETOOTH] Discovered potential peer: \(peerID) with RSSI: \(RSSI) dBm (range: ~\(estimateDistance(rssi: rssiValue))m)") // Discovered potential peer
} }
// Connect to any device we discover - we'll filter by service later // Connect to any device we discover - we'll filter by service later
@@ -1340,7 +1340,7 @@ extension BluetoothMeshService: CBCentralManagerDelegate {
let tempID = peripheral.identifier.uuidString let tempID = peripheral.identifier.uuidString
connectedPeripherals[tempID] = peripheral connectedPeripherals[tempID] = peripheral
print("[BLUETOOTH] Connected to peripheral (temp ID: \(tempID)), waiting for real peer ID...") // Connected to peripheral
// Request RSSI reading // Request RSSI reading
peripheral.readRSSI() peripheral.readRSSI()
@@ -1449,7 +1449,7 @@ extension BluetoothMeshService: CBPeripheralDelegate {
) )
if let data = announcePacket.toBinaryData() { if let data = announcePacket.toBinaryData() {
peripheral.writeValue(data, for: characteristic, type: .withResponse) peripheral.writeValue(data, for: characteristic, type: .withResponse)
print("[KEY_EXCHANGE] Sent targeted announce to peripheral") // Sent targeted announce
} }
} }
} }
@@ -1459,19 +1459,19 @@ extension BluetoothMeshService: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
guard let data = characteristic.value else { guard let data = characteristic.value else {
print("[PERIPHERAL] No data in characteristic") // No data in characteristic
return return
} }
guard let packet = BitchatPacket.from(data) else { guard let packet = BitchatPacket.from(data) else {
print("[PERIPHERAL] Failed to parse packet from data of size: \(data.count)") // Failed to parse packet
return return
} }
// Use the sender ID from the packet, not our local mapping which might still be a temp ID // Use the sender ID from the packet, not our local mapping which might still be a temp ID
let localPeerID = connectedPeripherals.first(where: { $0.value == peripheral })?.key ?? "unknown" let localPeerID = connectedPeripherals.first(where: { $0.value == peripheral })?.key ?? "unknown"
let packetSenderID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) ?? "unknown" let packetSenderID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) ?? "unknown"
print("[PERIPHERAL] Received data from localPeerID: \(localPeerID), packetSenderID: \(packetSenderID), packet type: \(packet.type)") // Received data from peer
// Always handle received packets // Always handle received packets
handleReceivedPacket(packet, from: packetSenderID, peripheral: peripheral) handleReceivedPacket(packet, from: packetSenderID, peripheral: peripheral)
@@ -1479,7 +1479,7 @@ extension BluetoothMeshService: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error { if let error = error {
print("[PERIPHERAL] Write failed: \(error)") print("[ERROR] Write failed: \(error)")
} else { } else {
// Write completed // Write completed
} }
@@ -1552,7 +1552,7 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
// Try to identify peer from packet // Try to identify peer from packet
let peerID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) ?? "unknown" let peerID = String(data: packet.senderID.trimmingNullBytes(), encoding: .utf8) ?? "unknown"
print("[PERIPHERAL_MANAGER] Received write from peer: \(peerID), packet type: \(packet.type)") // Received write from peer
// Store the central for updates // Store the central for updates
if !subscribedCentrals.contains(request.central) { if !subscribedCentrals.contains(request.central) {
@@ -1622,7 +1622,7 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
if let data = keyPacket.toBinaryData() { if let data = keyPacket.toBinaryData() {
peripheral.updateValue(data, for: self.characteristic, onSubscribedCentrals: [central]) peripheral.updateValue(data, for: self.characteristic, onSubscribedCentrals: [central])
print("[KEY_EXCHANGE] Sent initial key exchange as peripheral to new subscriber") // Sent initial key exchange
// We'll send announce when we receive their key exchange // We'll send announce when we receive their key exchange
} }
@@ -1695,7 +1695,7 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
} }
#endif #endif
print("[BATTERY] Current battery level: \(Int(currentBatteryLevel * 100))%") // Battery level updated
updateScanParametersForBattery() updateScanParametersForBattery()
} }
@@ -1727,22 +1727,22 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
// High battery: Normal operation // High battery: Normal operation
activeScanDuration = 2.0 activeScanDuration = 2.0
scanPauseDuration = 3.0 scanPauseDuration = 3.0
print("[BATTERY] High battery mode: normal scanning") // High battery mode
} else if currentBatteryLevel > 0.4 { } else if currentBatteryLevel > 0.4 {
// Medium battery: Moderate power saving // Medium battery: Moderate power saving
activeScanDuration = 1.5 activeScanDuration = 1.5
scanPauseDuration = 4.5 scanPauseDuration = 4.5
print("[BATTERY] Medium battery mode: moderate power saving") // Medium battery mode
} else if currentBatteryLevel > 0.2 { } else if currentBatteryLevel > 0.2 {
// Low battery: Aggressive power saving // Low battery: Aggressive power saving
activeScanDuration = 1.0 activeScanDuration = 1.0
scanPauseDuration = 8.0 scanPauseDuration = 8.0
print("[BATTERY] Low battery mode: aggressive power saving") // Low battery mode
} else { } else {
// Critical battery: Maximum power saving // Critical battery: Maximum power saving
activeScanDuration = 0.5 activeScanDuration = 0.5
scanPauseDuration = 15.0 scanPauseDuration = 15.0
print("[BATTERY] Critical battery mode: maximum power saving") // Critical battery mode
} }
// If we're currently in a duty cycle, restart it with new parameters // If we're currently in a duty cycle, restart it with new parameters
@@ -1784,7 +1784,7 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
// Skip if battery is low // Skip if battery is low
if currentBatteryLevel < 0.2 { if currentBatteryLevel < 0.2 {
print("[PRIVACY] Skipping cover traffic due to low battery") // Skipping cover traffic due to low battery
return return
} }
@@ -1794,7 +1794,7 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
// Generate random dummy content // Generate random dummy content
let dummyContent = generateDummyContent() let dummyContent = generateDummyContent()
print("[PRIVACY] Sending cover traffic to \(randomPeer)") // Sending cover traffic
// Send as a private message so it's encrypted // Send as a private message so it's encrypted
sendPrivateMessage(dummyContent, to: randomPeer, recipientNickname: peerNicknames[randomPeer] ?? "unknown") sendPrivateMessage(dummyContent, to: randomPeer, recipientNickname: peerNicknames[randomPeer] ?? "unknown")
+1 -1
View File
@@ -73,7 +73,7 @@ class EncryptionService {
let identityKey = try Curve25519.Signing.PublicKey(rawRepresentation: identityKeyData) let identityKey = try Curve25519.Signing.PublicKey(rawRepresentation: identityKeyData)
peerIdentityKeys[peerID] = identityKey peerIdentityKeys[peerID] = identityKey
print("[CRYPTO] Stored all three keys for peer \(peerID)") // Stored all three keys for peer
// Generate shared secret for encryption // Generate shared secret for encryption
if let publicKey = peerPublicKeys[peerID] { if let publicKey = peerPublicKeys[peerID] {
+6 -6
View File
@@ -14,7 +14,7 @@ class NotificationService {
func requestAuthorization() { func requestAuthorization() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if granted { if granted {
print("[NOTIFICATIONS] Permission granted") // Permission granted
} else if let error = error { } else if let error = error {
print("[NOTIFICATIONS] Permission error: \(error)") print("[NOTIFICATIONS] Permission error: \(error)")
} }
@@ -25,17 +25,17 @@ class NotificationService {
// Check if app is in foreground // Check if app is in foreground
#if os(iOS) #if os(iOS)
guard UIApplication.shared.applicationState != .active else { guard UIApplication.shared.applicationState != .active else {
print("[NOTIFICATIONS] App is active/foreground, skipping notification") // App is active/foreground, skipping notification
return return
} }
print("[NOTIFICATIONS] App state: \(UIApplication.shared.applicationState.rawValue), sending notification") // App state checked, sending notification
#elseif os(macOS) #elseif os(macOS)
// On macOS, check if app is active // On macOS, check if app is active
guard !NSApplication.shared.isActive else { guard !NSApplication.shared.isActive else {
print("[NOTIFICATIONS] App is active/foreground, skipping notification") // App is active/foreground, skipping notification
return return
} }
print("[NOTIFICATIONS] App is not active, sending notification") // App is not active, sending notification
#endif #endif
let content = UNMutableNotificationContent() let content = UNMutableNotificationContent()
@@ -53,7 +53,7 @@ class NotificationService {
if let error = error { if let error = error {
print("[NOTIFICATIONS] Error sending notification: \(error)") print("[NOTIFICATIONS] Error sending notification: \(error)")
} else { } else {
print("[NOTIFICATIONS] Notification sent: \(title)") // Notification sent
} }
} }
} }
+2 -1
View File
@@ -74,7 +74,8 @@ struct ContentView: View {
// Sidebar overlay // Sidebar overlay
HStack(spacing: 0) { HStack(spacing: 0) {
// Tap to dismiss area // Tap to dismiss area
Color.black.opacity(showSidebar ? 0.3 : 0.3 * (-sidebarDragOffset / (geometry.size.width * 0.7))) Color.clear
.contentShape(Rectangle())
.onTapGesture { .onTapGesture {
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) { withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
showSidebar = false showSidebar = false