Centralize repeated queue-checking logic (#791)

This commit is contained in:
Islam
2025-10-11 21:38:04 +02:00
committed by GitHub
parent 239064e4eb
commit 9f74266527
+84 -101
View File
@@ -315,48 +315,49 @@ final class BLEService: NSObject {
startServices() startServices()
} }
// Ensure this runs on message queue to avoid main thread blocking
func sendMessage(_ content: String, mentions: [String] = [], to recipientID: String? = nil, messageID: String? = nil, timestamp: Date? = nil) { func sendMessage(_ content: String, mentions: [String] = [], to recipientID: String? = nil, messageID: String? = nil, timestamp: Date? = nil) {
// Ensure this runs on message queue to avoid main thread blocking // Call directly if already on messageQueue, otherwise dispatch
messageQueue.async { [weak self] in if DispatchQueue.getSpecific(key: messageQueueKey) == nil {
guard let self = self else { return } messageQueue.async { [weak self] in
self?.sendMessage(content, mentions: mentions, to: recipientID, messageID: messageID, timestamp: timestamp)
guard content.count <= self.maxMessageLength else {
SecureLogger.error("Message too long: \(content.count) chars", category: .session)
return
}
let finalMessageID = messageID ?? UUID().uuidString
let _ = UInt64(Date().timeIntervalSince1970 * 1000)
if let recipientID = recipientID {
// Private message
self.sendPrivateMessage(content, to: recipientID, messageID: finalMessageID)
} else {
// Public broadcast
// Create packet with explicit fields so we can sign it
let basePacket = BitchatPacket(
type: MessageType.message.rawValue,
senderID: Data(hexString: self.myPeerID.id) ?? Data(),
recipientID: nil,
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
payload: Data(content.utf8),
signature: nil,
ttl: self.messageTTL
)
guard let signedPacket = self.noiseService.signPacket(basePacket) else {
SecureLogger.error("❌ Failed to sign public message", category: .security)
return
}
// Pre-mark our own broadcast as processed to avoid handling relayed self copy
let senderHex = signedPacket.senderID.hexEncodedString()
let dedupID = "\(senderHex)-\(signedPacket.timestamp)-\(signedPacket.type)"
self.messageDeduplicator.markProcessed(dedupID)
// Call synchronously since we're already on background queue
self.broadcastPacket(signedPacket)
// Track our own broadcast for sync
self.gossipSyncManager?.onPublicPacketSeen(signedPacket)
} }
return
} }
guard content.count <= maxMessageLength else {
SecureLogger.error("Message too long: \(content.count) chars", category: .session)
return
}
if let recipientID {
sendPrivateMessage(content, to: recipientID, messageID: messageID ?? UUID().uuidString)
return
}
// Public broadcast
// Create packet with explicit fields so we can sign it
let basePacket = BitchatPacket(
type: MessageType.message.rawValue,
senderID: Data(hexString: myPeerID.id) ?? Data(),
recipientID: nil,
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
payload: Data(content.utf8),
signature: nil,
ttl: messageTTL
)
guard let signedPacket = noiseService.signPacket(basePacket) else {
SecureLogger.error("❌ Failed to sign public message", category: .security)
return
}
// Pre-mark our own broadcast as processed to avoid handling relayed self copy
let senderHex = signedPacket.senderID.hexEncodedString()
let dedupID = "\(senderHex)-\(signedPacket.timestamp)-\(signedPacket.type)"
messageDeduplicator.markProcessed(dedupID)
// Call synchronously since we're already on background queue
broadcastPacket(signedPacket)
// Track our own broadcast for sync
gossipSyncManager?.onPublicPacketSeen(signedPacket)
} }
// MARK: - Transport Protocol Conformance // MARK: - Transport Protocol Conformance
@@ -590,11 +591,7 @@ final class BLEService: NSObject {
signature: nil, signature: nil,
ttl: messageTTL ttl: messageTTL
) )
if DispatchQueue.getSpecific(key: messageQueueKey) != nil { broadcastPacket(packet)
broadcastPacket(packet)
} else {
messageQueue.async { [weak self] in self?.broadcastPacket(packet) }
}
} catch { } catch {
SecureLogger.error("Failed to send read receipt: \(error)") SecureLogger.error("Failed to send read receipt: \(error)")
} }
@@ -677,19 +674,11 @@ final class BLEService: NSObject {
// MARK: - GossipSyncManager Delegate // MARK: - GossipSyncManager Delegate
extension BLEService: GossipSyncManager.Delegate { extension BLEService: GossipSyncManager.Delegate {
func sendPacket(_ packet: BitchatPacket) { func sendPacket(_ packet: BitchatPacket) {
if DispatchQueue.getSpecific(key: messageQueueKey) != nil { broadcastPacket(packet)
broadcastPacket(packet)
} else {
messageQueue.async { [weak self] in self?.broadcastPacket(packet) }
}
} }
func sendPacket(to peerID: PeerID, packet: BitchatPacket) { func sendPacket(to peerID: PeerID, packet: BitchatPacket) {
if DispatchQueue.getSpecific(key: messageQueueKey) != nil { sendPacketDirected(packet, to: peerID)
sendPacketDirected(packet, to: peerID)
} else {
messageQueue.async { [weak self] in self?.sendPacketDirected(packet, to: peerID) }
}
} }
func signPacketForBroadcast(_ packet: BitchatPacket) -> BitchatPacket { func signPacketForBroadcast(_ packet: BitchatPacket) -> BitchatPacket {
@@ -1056,13 +1045,7 @@ extension BLEService {
peers[normalizedID] = p peers[normalizedID] = p
} }
} }
if DispatchQueue.getSpecific(key: messageQueueKey) != nil { handleReceivedPacket(packet, from: fromPeerID)
handleReceivedPacket(packet, from: fromPeerID)
} else {
messageQueue.async { [weak self] in
self?.handleReceivedPacket(packet, from: fromPeerID)
}
}
} }
} }
#endif #endif
@@ -1570,11 +1553,7 @@ extension BLEService {
signature: nil, signature: nil,
ttl: messageTTL ttl: messageTTL
) )
if DispatchQueue.getSpecific(key: messageQueueKey) != nil { broadcastPacket(packet)
broadcastPacket(packet)
} else {
messageQueue.async { [weak self] in self?.broadcastPacket(packet) }
}
} catch { } catch {
SecureLogger.error("Failed to send verification payload: \(error)") SecureLogger.error("Failed to send verification payload: \(error)")
} }
@@ -1765,23 +1744,17 @@ extension BLEService {
} }
} }
let packet = BitchatPacket( let packet = BitchatPacket(
type: MessageType.noiseEncrypted.rawValue, type: MessageType.noiseEncrypted.rawValue,
senderID: myPeerIDData, senderID: myPeerIDData,
recipientID: recipientData, recipientID: recipientData,
timestamp: UInt64(Date().timeIntervalSince1970 * 1000), timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
payload: encrypted, payload: encrypted,
signature: nil, signature: nil,
ttl: messageTTL ttl: messageTTL
) )
// Call directly if already on messageQueue, otherwise dispatch
if DispatchQueue.getSpecific(key: messageQueueKey) != nil { broadcastPacket(packet)
broadcastPacket(packet)
} else {
messageQueue.async { [weak self] in
self?.broadcastPacket(packet)
}
}
// Notify delegate that message was sent // Notify delegate that message was sent
notifyUI { [weak self] in notifyUI { [weak self] in
@@ -1828,14 +1801,7 @@ extension BLEService {
signature: nil, signature: nil,
ttl: messageTTL ttl: messageTTL
) )
// Call directly if on messageQueue, otherwise dispatch broadcastPacket(packet)
if DispatchQueue.getSpecific(key: messageQueueKey) != nil {
broadcastPacket(packet)
} else {
messageQueue.async { [weak self] in
self?.broadcastPacket(packet)
}
}
} catch { } catch {
SecureLogger.error("Failed to initiate handshake: \(error)") SecureLogger.error("Failed to initiate handshake: \(error)")
} }
@@ -1901,6 +1867,14 @@ extension BLEService {
// MARK: Packet Broadcasting // MARK: Packet Broadcasting
private func broadcastPacket(_ packet: BitchatPacket) { private func broadcastPacket(_ packet: BitchatPacket) {
// Call directly if already on messageQueue, otherwise dispatch
if DispatchQueue.getSpecific(key: messageQueueKey) == nil {
messageQueue.async { [weak self] in
self?.broadcastPacket(packet)
}
return
}
// Encode once using a small per-type padding policy, then delegate by type // Encode once using a small per-type padding policy, then delegate by type
let padForBLE = padPolicy(for: packet.type) let padForBLE = padPolicy(for: packet.type)
guard let data = packet.toBinaryData(padding: padForBLE) else { guard let data = packet.toBinaryData(padding: padForBLE) else {
@@ -2091,6 +2065,14 @@ extension BLEService {
// Directed send helper (unicast to a specific peerID) without altering packet contents // Directed send helper (unicast to a specific peerID) without altering packet contents
private func sendPacketDirected(_ packet: BitchatPacket, to peerID: PeerID) { private func sendPacketDirected(_ packet: BitchatPacket, to peerID: PeerID) {
// Call directly if already on messageQueue, otherwise dispatch
if DispatchQueue.getSpecific(key: messageQueueKey) == nil {
messageQueue.async { [weak self] in
self?.sendPacketDirected(packet, to: peerID)
}
return
}
guard let data = packet.toBinaryData(padding: false) else { return } guard let data = packet.toBinaryData(padding: false) else { return }
sendOnAllLinks(packet: packet, data: data, pad: false, directedOnlyPeer: peerID) sendOnAllLinks(packet: packet, data: data, pad: false, directedOnlyPeer: peerID)
} }
@@ -2125,9 +2107,8 @@ extension BLEService {
} }
return out return out
} }
guard !toSend.isEmpty else { return }
for (_, packet) in toSend { for (_, packet) in toSend {
messageQueue.async { [weak self] in self?.broadcastPacket(packet) } broadcastPacket(packet)
} }
} }
@@ -2288,6 +2269,14 @@ extension BLEService {
// MARK: Packet Reception // MARK: Packet Reception
private func handleReceivedPacket(_ packet: BitchatPacket, from peerID: PeerID) { private func handleReceivedPacket(_ packet: BitchatPacket, from peerID: PeerID) {
// Call directly if already on messageQueue, otherwise dispatch
if DispatchQueue.getSpecific(key: messageQueueKey) == nil {
messageQueue.async { [weak self] in
self?.handleReceivedPacket(packet, from: peerID)
}
return
}
// Deduplication (thread-safe) // Deduplication (thread-safe)
let senderID = PeerID(hexData: packet.senderID) let senderID = PeerID(hexData: packet.senderID)
// Include packet type in message ID to prevent collisions between different packet types // Include packet type in message ID to prevent collisions between different packet types
@@ -2888,14 +2877,8 @@ extension BLEService {
return return
} }
// Call directly if on messageQueue, otherwise dispatch broadcastPacket(signedPacket)
if DispatchQueue.getSpecific(key: messageQueueKey) != nil {
broadcastPacket(signedPacket)
} else {
messageQueue.async { [weak self] in
self?.broadcastPacket(signedPacket)
}
}
// Ensure our own announce is included in sync state // Ensure our own announce is included in sync state
gossipSyncManager?.onPublicPacketSeen(signedPacket) gossipSyncManager?.onPublicPacketSeen(signedPacket)
} }