mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 23:45:18 +00:00
PeerID 20/n: BLEService’s private functions (#771)
This commit is contained in:
@@ -549,7 +549,7 @@ final class BLEService: NSObject {
|
||||
}
|
||||
|
||||
func triggerHandshake(with peerID: PeerID) {
|
||||
initiateNoiseHandshake(with: peerID.id)
|
||||
initiateNoiseHandshake(with: peerID)
|
||||
}
|
||||
|
||||
func getNoiseService() -> NoiseEncryptionService {
|
||||
@@ -604,7 +604,7 @@ final class BLEService: NSObject {
|
||||
guard let self = self else { return }
|
||||
self.pendingNoisePayloadsAfterHandshake[peerID, default: []].append(payload)
|
||||
}
|
||||
if !noiseService.hasSession(with: peerID) { initiateNoiseHandshake(with: peerID.id) }
|
||||
if !noiseService.hasSession(with: peerID) { initiateNoiseHandshake(with: peerID) }
|
||||
SecureLogger.debug("🕒 Queued READ receipt for \(peerID) until handshake completes", category: .session)
|
||||
}
|
||||
}
|
||||
@@ -656,7 +656,7 @@ final class BLEService: NSObject {
|
||||
guard let self = self else { return }
|
||||
self.pendingNoisePayloadsAfterHandshake[peerID, default: []].append(payload)
|
||||
}
|
||||
if !noiseService.hasSession(with: peerID) { initiateNoiseHandshake(with: peerID.id) }
|
||||
if !noiseService.hasSession(with: peerID) { initiateNoiseHandshake(with: peerID) }
|
||||
SecureLogger.debug("🕒 Queued DELIVERED ack for \(peerID) until handshake completes", category: .session)
|
||||
}
|
||||
}
|
||||
@@ -665,12 +665,12 @@ final class BLEService: NSObject {
|
||||
|
||||
func sendVerifyChallenge(to peerID: PeerID, noiseKeyHex: String, nonceA: Data) {
|
||||
let payload = VerificationService.shared.buildVerifyChallenge(noiseKeyHex: noiseKeyHex, nonceA: nonceA)
|
||||
sendNoisePayload(payload, to: peerID.id)
|
||||
sendNoisePayload(payload, to: peerID)
|
||||
}
|
||||
|
||||
func sendVerifyResponse(to peerID: PeerID, noiseKeyHex: String, nonceA: Data) {
|
||||
guard let payload = VerificationService.shared.buildVerifyResponse(noiseKeyHex: noiseKeyHex, nonceA: nonceA) else { return }
|
||||
sendNoisePayload(payload, to: peerID.id)
|
||||
sendNoisePayload(payload, to: peerID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,9 +686,9 @@ extension BLEService: GossipSyncManager.Delegate {
|
||||
|
||||
func sendPacket(to peerID: PeerID, packet: BitchatPacket) {
|
||||
if DispatchQueue.getSpecific(key: messageQueueKey) != nil {
|
||||
sendPacketDirected(packet, to: peerID.id)
|
||||
sendPacketDirected(packet, to: peerID)
|
||||
} else {
|
||||
messageQueue.async { [weak self] in self?.sendPacketDirected(packet, to: peerID.id) }
|
||||
messageQueue.async { [weak self] in self?.sendPacketDirected(packet, to: peerID) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -939,8 +939,8 @@ func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeriph
|
||||
// Get current peer list (after removal)
|
||||
let currentPeerIDs = self.collectionsQueue.sync { self.currentPeerIDs }
|
||||
|
||||
if let peerID = peerID {
|
||||
self.notifyPeerDisconnectedDebounced(peerID.id)
|
||||
if let peerID {
|
||||
self.notifyPeerDisconnectedDebounced(peerID)
|
||||
}
|
||||
self.requestPeerDataPublish()
|
||||
self.delegate?.didUpdatePeerList(currentPeerIDs)
|
||||
@@ -1034,14 +1034,14 @@ extension BLEService {
|
||||
#if DEBUG
|
||||
// Test-only helper to inject packets into the receive pipeline
|
||||
extension BLEService {
|
||||
func _test_handlePacket(_ packet: BitchatPacket, fromPeerID: String) {
|
||||
func _test_handlePacket(_ packet: BitchatPacket, fromPeerID: PeerID) {
|
||||
// Ensure the synthetic peer is known and marked verified for public-message tests
|
||||
let normalizedID = PeerID(hexData: packet.senderID)
|
||||
collectionsQueue.sync(flags: .barrier) {
|
||||
if peers[normalizedID] == nil {
|
||||
peers[normalizedID] = PeerInfo(
|
||||
peerID: normalizedID,
|
||||
nickname: "TestPeer_\(fromPeerID.prefix(4))",
|
||||
nickname: "TestPeer_\(fromPeerID.id.prefix(4))",
|
||||
isConnected: true,
|
||||
noisePublicKey: packet.senderID,
|
||||
signingPublicKey: nil,
|
||||
@@ -1218,13 +1218,13 @@ extension BLEService: CBPeripheralDelegate {
|
||||
collectionsQueue.async(flags: .barrier) { [weak self] in
|
||||
self?.ingressByMessageID[msgID] = (.peripheral(peripheralUUID), Date())
|
||||
}
|
||||
handleReceivedPacket(packet, from: senderID.id)
|
||||
handleReceivedPacket(packet, from: senderID)
|
||||
} else {
|
||||
let msgID = makeMessageID(for: packet)
|
||||
collectionsQueue.async(flags: .barrier) { [weak self] in
|
||||
self?.ingressByMessageID[msgID] = (.peripheral(peripheralUUID), Date())
|
||||
}
|
||||
handleReceivedPacket(packet, from: senderID.id)
|
||||
handleReceivedPacket(packet, from: senderID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1360,7 +1360,7 @@ extension BLEService: CBPeripheralManagerDelegate {
|
||||
// Get current peer list (after removal)
|
||||
let currentPeerIDs = self.collectionsQueue.sync { self.currentPeerIDs }
|
||||
|
||||
self.notifyPeerDisconnectedDebounced(peerID.id)
|
||||
self.notifyPeerDisconnectedDebounced(peerID)
|
||||
// Publish snapshots so UnifiedPeerService can refresh icons promptly
|
||||
self.requestPeerDataPublish()
|
||||
self.delegate?.didUpdatePeerList(currentPeerIDs)
|
||||
@@ -1460,7 +1460,7 @@ extension BLEService: CBPeripheralManagerDelegate {
|
||||
if let packet = BinaryProtocol.decode(combined) {
|
||||
// Clear buffer on success
|
||||
pendingWriteBuffers.removeValue(forKey: centralUUID)
|
||||
let senderID = packet.senderID.hexEncodedString()
|
||||
let senderID = PeerID(hexData: packet.senderID)
|
||||
if packet.type != MessageType.announce.rawValue {
|
||||
SecureLogger.debug("📦 Decoded (combined) packet type: \(packet.type) from sender: \(senderID)", category: .session)
|
||||
}
|
||||
@@ -1468,7 +1468,7 @@ extension BLEService: CBPeripheralManagerDelegate {
|
||||
subscribedCentrals.append(sorted[0].central)
|
||||
}
|
||||
if packet.type == MessageType.announce.rawValue {
|
||||
if packet.ttl == messageTTL { centralToPeerID[centralUUID] = PeerID(str: senderID) }
|
||||
if packet.ttl == messageTTL { centralToPeerID[centralUUID] = senderID }
|
||||
// Record ingress link for last-hop suppression then process
|
||||
let msgID = makeMessageID(for: packet)
|
||||
collectionsQueue.async(flags: .barrier) { [weak self] in
|
||||
@@ -1527,6 +1527,7 @@ extension BLEService {
|
||||
|
||||
private func configureNoiseServiceCallbacks(for service: NoiseEncryptionService) {
|
||||
service.onPeerAuthenticated = { [weak self] peerID, fingerprint in
|
||||
let peerID = PeerID(str: peerID)
|
||||
SecureLogger.debug("🔐 Noise session authenticated with \(peerID), fingerprint: \(fingerprint.prefix(16))...")
|
||||
self?.messageQueue.async { [weak self] in
|
||||
self?.sendPendingMessagesAfterHandshake(for: peerID)
|
||||
@@ -1552,18 +1553,18 @@ extension BLEService {
|
||||
gossipSyncManager = sync
|
||||
}
|
||||
|
||||
private func sendNoisePayload(_ typedPayload: Data, to peerID: String) {
|
||||
guard noiseService.hasSession(with: PeerID(str: peerID)) else {
|
||||
private func sendNoisePayload(_ typedPayload: Data, to peerID: PeerID) {
|
||||
guard noiseService.hasSession(with: peerID) else {
|
||||
// Lazy-handshake path: queue? For now, initiate handshake and drop
|
||||
initiateNoiseHandshake(with: peerID)
|
||||
return
|
||||
}
|
||||
do {
|
||||
let encrypted = try noiseService.encrypt(typedPayload, for: PeerID(str: peerID))
|
||||
let encrypted = try noiseService.encrypt(typedPayload, for: peerID)
|
||||
let packet = BitchatPacket(
|
||||
type: MessageType.noiseEncrypted.rawValue,
|
||||
senderID: myPeerIDData,
|
||||
recipientID: Data(hexString: peerID),
|
||||
recipientID: Data(hexString: peerID.id),
|
||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||
payload: encrypted,
|
||||
signature: nil,
|
||||
@@ -1801,7 +1802,7 @@ extension BLEService {
|
||||
pendingMessagesAfterHandshake[recipientID]?.append((content, messageID))
|
||||
}
|
||||
|
||||
initiateNoiseHandshake(with: recipientID.id)
|
||||
initiateNoiseHandshake(with: recipientID)
|
||||
|
||||
// Notify delegate that message is pending
|
||||
notifyUI { [weak self] in
|
||||
@@ -1810,18 +1811,18 @@ extension BLEService {
|
||||
}
|
||||
}
|
||||
|
||||
private func initiateNoiseHandshake(with peerID: String) {
|
||||
private func initiateNoiseHandshake(with peerID: PeerID) {
|
||||
// Use NoiseEncryptionService for handshake
|
||||
guard !noiseService.hasSession(with: PeerID(str: peerID)) else { return }
|
||||
guard !noiseService.hasSession(with: peerID) else { return }
|
||||
|
||||
do {
|
||||
let handshakeData = try noiseService.initiateHandshake(with: PeerID(str: peerID))
|
||||
let handshakeData = try noiseService.initiateHandshake(with: peerID)
|
||||
|
||||
// Send handshake init
|
||||
let packet = BitchatPacket(
|
||||
type: MessageType.noiseHandshake.rawValue,
|
||||
senderID: myPeerIDData,
|
||||
recipientID: Data(hexString: peerID),
|
||||
recipientID: Data(hexString: peerID.id),
|
||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||
payload: handshakeData,
|
||||
signature: nil,
|
||||
@@ -1840,8 +1841,7 @@ extension BLEService {
|
||||
}
|
||||
}
|
||||
|
||||
private func sendPendingMessagesAfterHandshake(for peerID: String) {
|
||||
let peerID = PeerID(str: peerID)
|
||||
private func sendPendingMessagesAfterHandshake(for peerID: PeerID) {
|
||||
// Get and clear pending messages for this peer
|
||||
let pendingMessages = collectionsQueue.sync(flags: .barrier) { () -> [(content: String, messageID: String)]? in
|
||||
let messages = pendingMessagesAfterHandshake[peerID]
|
||||
@@ -1946,13 +1946,13 @@ extension BLEService {
|
||||
if let pm = peripheralMaxLen, data.count > pm {
|
||||
let overhead = 13 + 8 + 8 + 13
|
||||
let chunk = max(64, pm - overhead)
|
||||
sendFragmentedPacket(packet, pad: pad, maxChunk: chunk, directedOnlyPeer: recipientPeerID.id)
|
||||
sendFragmentedPacket(packet, pad: pad, maxChunk: chunk, directedOnlyPeer: recipientPeerID)
|
||||
return
|
||||
}
|
||||
if let cm = centralMaxLen, data.count > cm {
|
||||
let overhead = 13 + 8 + 8 + 13
|
||||
let chunk = max(64, cm - overhead)
|
||||
sendFragmentedPacket(packet, pad: pad, maxChunk: chunk, directedOnlyPeer: recipientPeerID.id)
|
||||
sendFragmentedPacket(packet, pad: pad, maxChunk: chunk, directedOnlyPeer: recipientPeerID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1983,7 +1983,7 @@ extension BLEService {
|
||||
|
||||
if !sentEncrypted {
|
||||
// Flood as last resort with recipient set; link aware
|
||||
sendOnAllLinks(packet: packet, data: data, pad: pad, directedOnlyPeer: recipientPeerID.id)
|
||||
sendOnAllLinks(packet: packet, data: data, pad: pad, directedOnlyPeer: recipientPeerID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1991,14 +1991,14 @@ extension BLEService {
|
||||
sendOnAllLinks(packet: packet, data: data, pad: pad, directedOnlyPeer: nil)
|
||||
}
|
||||
|
||||
private func sendOnAllLinks(packet: BitchatPacket, data: Data, pad: Bool, directedOnlyPeer: String?) {
|
||||
private func sendOnAllLinks(packet: BitchatPacket, data: Data, pad: Bool, directedOnlyPeer: PeerID?) {
|
||||
// Determine last-hop link for this message to avoid echoing back
|
||||
let messageID = makeMessageID(for: packet)
|
||||
let ingressLink: LinkID? = collectionsQueue.sync { ingressByMessageID[messageID]?.link }
|
||||
let directedPeerHint: String? = {
|
||||
let directedPeerHint: PeerID? = {
|
||||
if let explicit = directedOnlyPeer { return explicit }
|
||||
if let recipient = packet.recipientID?.hexEncodedString(), !recipient.isEmpty {
|
||||
return recipient
|
||||
return PeerID(str: recipient)
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
@@ -2090,14 +2090,13 @@ extension BLEService {
|
||||
}
|
||||
|
||||
// Directed send helper (unicast to a specific peerID) without altering packet contents
|
||||
private func sendPacketDirected(_ packet: BitchatPacket, to peerID: String) {
|
||||
private func sendPacketDirected(_ packet: BitchatPacket, to peerID: PeerID) {
|
||||
guard let data = packet.toBinaryData(padding: false) else { return }
|
||||
sendOnAllLinks(packet: packet, data: data, pad: false, directedOnlyPeer: peerID)
|
||||
}
|
||||
|
||||
// MARK: Directed store-and-forward
|
||||
private func spoolDirectedPacket(_ packet: BitchatPacket, recipientPeerID: String) {
|
||||
let recipientPeerID = PeerID(str: recipientPeerID)
|
||||
private func spoolDirectedPacket(_ packet: BitchatPacket, recipientPeerID: PeerID) {
|
||||
let msgID = makeMessageID(for: packet)
|
||||
collectionsQueue.async(flags: .barrier) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
@@ -2162,7 +2161,7 @@ extension BLEService {
|
||||
|
||||
// MARK: Fragmentation (Required for messages > BLE MTU)
|
||||
|
||||
private func sendFragmentedPacket(_ packet: BitchatPacket, pad: Bool, maxChunk: Int? = nil, directedOnlyPeer: String? = nil) {
|
||||
private func sendFragmentedPacket(_ packet: BitchatPacket, pad: Bool, maxChunk: Int? = nil, directedOnlyPeer: PeerID? = nil) {
|
||||
guard let fullData = packet.toBinaryData(padding: pad) else { return }
|
||||
// Fragment the unpadded frame; each fragment will be encoded independently
|
||||
|
||||
@@ -2197,7 +2196,7 @@ extension BLEService {
|
||||
|
||||
// Choose recipient for the fragment: directed override if provided
|
||||
let fragmentRecipient: Data? = {
|
||||
if let only = directedOnlyPeer { return Data(hexString: only) }
|
||||
if let only = directedOnlyPeer { return Data(hexString: only.id) }
|
||||
return packet.recipientID
|
||||
}()
|
||||
|
||||
@@ -2219,7 +2218,7 @@ extension BLEService {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleFragment(_ packet: BitchatPacket, from peerID: String) {
|
||||
private func handleFragment(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
// Don't process our own fragments
|
||||
if peerID == myPeerID {
|
||||
return
|
||||
@@ -2288,9 +2287,9 @@ extension BLEService {
|
||||
|
||||
// MARK: Packet Reception
|
||||
|
||||
private func handleReceivedPacket(_ packet: BitchatPacket, from peerID: String) {
|
||||
private func handleReceivedPacket(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
// Deduplication (thread-safe)
|
||||
let senderID = packet.senderID.hexEncodedString()
|
||||
let senderID = PeerID(hexData: packet.senderID)
|
||||
// Include packet type in message ID to prevent collisions between different packet types
|
||||
let messageID = "\(senderID)-\(packet.timestamp)-\(packet.type)"
|
||||
|
||||
@@ -2403,8 +2402,7 @@ extension BLEService {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleAnnounce(_ packet: BitchatPacket, from peerID: String) {
|
||||
let peerID = PeerID(str: peerID)
|
||||
private func handleAnnounce(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
guard let announcement = AnnouncementPacket.decode(from: packet.payload) else {
|
||||
SecureLogger.error("❌ Failed to decode announce packet from \(peerID)", category: .session)
|
||||
return
|
||||
@@ -2595,17 +2593,17 @@ extension BLEService {
|
||||
}
|
||||
|
||||
// Handle REQUEST_SYNC: decode payload and respond with missing packets via sync manager
|
||||
private func handleRequestSync(_ packet: BitchatPacket, from peerID: String) {
|
||||
private func handleRequestSync(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
guard let req = RequestSyncPacket.decode(from: packet.payload) else {
|
||||
SecureLogger.warning("⚠️ Malformed REQUEST_SYNC from \(peerID)", category: .session)
|
||||
return
|
||||
}
|
||||
gossipSyncManager?.handleRequestSync(from: PeerID(str: peerID), request: req)
|
||||
gossipSyncManager?.handleRequestSync(from: peerID, request: req)
|
||||
}
|
||||
|
||||
// Mention parsing moved to ChatViewModel
|
||||
|
||||
private func handleMessage(_ packet: BitchatPacket, from peerID: String) {
|
||||
private func handleMessage(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
// Ignore self-origin public messages except when returned via sync (TTL==0).
|
||||
// This allows our own messages to be surfaced when they come back via
|
||||
// the sync path without re-processing regular relayed copies.
|
||||
@@ -2625,7 +2623,7 @@ extension BLEService {
|
||||
if nowMs >= ageThresholdMs {
|
||||
let cutoffMs = nowMs - ageThresholdMs
|
||||
if packet.timestamp < cutoffMs {
|
||||
SecureLogger.debug("⏰ Ignoring stale broadcast message from \(peerID.prefix(8))… (age: \(Double(nowMs - packet.timestamp) / 1000.0)s)", category: .session)
|
||||
SecureLogger.debug("⏰ Ignoring stale broadcast message from \(peerID.id.prefix(8))… (age: \(Double(nowMs - packet.timestamp) / 1000.0)s)", category: .session)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -2639,20 +2637,20 @@ extension BLEService {
|
||||
accepted = true
|
||||
senderNickname = myNickname
|
||||
}
|
||||
else if let info = peers[PeerID(str: peerID)], info.isVerifiedNickname {
|
||||
else if let info = peers[peerID], info.isVerifiedNickname {
|
||||
// Known verified peer path
|
||||
accepted = true
|
||||
senderNickname = info.nickname
|
||||
// Handle nickname collisions
|
||||
let hasCollision = peers.values.contains { $0.isConnected && $0.nickname == info.nickname && $0.peerID != peerID } || (myNickname == info.nickname)
|
||||
if hasCollision {
|
||||
senderNickname += "#" + String(peerID.prefix(4))
|
||||
senderNickname += "#" + String(peerID.id.prefix(4))
|
||||
}
|
||||
} else {
|
||||
// Fallback: verify signature using persisted signing key for this peerID's fingerprint prefix
|
||||
if let signature = packet.signature, let packetData = packet.toBinaryDataForSigning() {
|
||||
// Find candidate identities by peerID prefix (16 hex)
|
||||
let candidates = identityManager.getCryptoIdentitiesByPeerIDPrefix(PeerID(str: peerID))
|
||||
let candidates = identityManager.getCryptoIdentitiesByPeerIDPrefix(peerID)
|
||||
for candidate in candidates {
|
||||
if let signingKey = candidate.signingPublicKey,
|
||||
noiseService.verifySignature(signature, for: packetData, publicKey: signingKey) {
|
||||
@@ -2661,7 +2659,7 @@ extension BLEService {
|
||||
if let social = identityManager.getSocialIdentity(for: candidate.fingerprint) {
|
||||
senderNickname = social.localPetname ?? social.claimedNickname
|
||||
} else {
|
||||
senderNickname = "anon" + String(peerID.prefix(4))
|
||||
senderNickname = "anon" + String(peerID.id.prefix(4))
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -2672,7 +2670,7 @@ extension BLEService {
|
||||
// peers we haven't verified yet.
|
||||
if !accepted && packet.ttl == 0 {
|
||||
accepted = true
|
||||
senderNickname = "anon" + String(peerID.prefix(4))
|
||||
senderNickname = "anon" + String(peerID.id.prefix(4))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2686,7 +2684,7 @@ extension BLEService {
|
||||
}
|
||||
|
||||
guard accepted else {
|
||||
SecureLogger.warning("🚫 Dropping public message from unverified or unknown peer \(peerID.prefix(8))…", category: .security)
|
||||
SecureLogger.warning("🚫 Dropping public message from unverified or unknown peer \(peerID.id.prefix(8))…", category: .security)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2696,9 +2694,9 @@ extension BLEService {
|
||||
}
|
||||
// Determine if we have a direct link to the sender
|
||||
let hasDirectLink: Bool = collectionsQueue.sync {
|
||||
let perUUID = peerToPeripheralUUID[PeerID(str: peerID)]
|
||||
let perUUID = peerToPeripheralUUID[peerID]
|
||||
let perConnected = perUUID != nil && peripherals[perUUID!]?.isConnected == true
|
||||
let hasCentral = centralToPeerID.values.contains(PeerID(str: peerID))
|
||||
let hasCentral = centralToPeerID.values.contains(peerID)
|
||||
return perConnected || hasCentral
|
||||
}
|
||||
|
||||
@@ -2707,22 +2705,22 @@ extension BLEService {
|
||||
|
||||
let ts = Date(timeIntervalSince1970: Double(packet.timestamp) / 1000)
|
||||
notifyUI { [weak self] in
|
||||
self?.delegate?.didReceivePublicMessage(from: PeerID(str: peerID), nickname: senderNickname, content: content, timestamp: ts)
|
||||
self?.delegate?.didReceivePublicMessage(from: peerID, nickname: senderNickname, content: content, timestamp: ts)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleNoiseHandshake(_ packet: BitchatPacket, from peerID: String) {
|
||||
private func handleNoiseHandshake(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
// Use NoiseEncryptionService for handshake processing
|
||||
if let recipientID = packet.recipientID,
|
||||
recipientID.hexEncodedString() == myPeerID {
|
||||
// Handshake is for us
|
||||
do {
|
||||
if let response = try noiseService.processHandshakeMessage(from: PeerID(str: peerID), message: packet.payload) {
|
||||
if let response = try noiseService.processHandshakeMessage(from: peerID, message: packet.payload) {
|
||||
// Send response
|
||||
let responsePacket = BitchatPacket(
|
||||
type: MessageType.noiseHandshake.rawValue,
|
||||
senderID: myPeerIDData,
|
||||
recipientID: Data(hexString: peerID),
|
||||
recipientID: Data(hexString: peerID.id),
|
||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||
payload: response,
|
||||
signature: nil,
|
||||
@@ -2737,15 +2735,14 @@ extension BLEService {
|
||||
} catch {
|
||||
SecureLogger.error("Failed to process handshake: \(error)")
|
||||
// Try initiating a new handshake
|
||||
if !noiseService.hasSession(with: PeerID(str: peerID)) {
|
||||
if !noiseService.hasSession(with: peerID) {
|
||||
initiateNoiseHandshake(with: peerID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handleNoiseEncrypted(_ packet: BitchatPacket, from peerID: String) {
|
||||
let peerID = PeerID(str: peerID)
|
||||
private func handleNoiseEncrypted(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
SecureLogger.debug("🔐 handleNoiseEncrypted called for packet from \(peerID)")
|
||||
|
||||
guard let recipientID = packet.recipientID else {
|
||||
@@ -2760,7 +2757,7 @@ extension BLEService {
|
||||
}
|
||||
|
||||
// Update lastSeen for the peer we received from (important for private messages)
|
||||
updatePeerLastSeen(peerID.id)
|
||||
updatePeerLastSeen(peerID)
|
||||
|
||||
do {
|
||||
let decrypted = try noiseService.decrypt(packet.payload, from: peerID)
|
||||
@@ -2804,20 +2801,20 @@ extension BLEService {
|
||||
// Trigger a handshake so future messages can be decrypted.
|
||||
SecureLogger.debug("🔑 Encrypted message from \(peerID) without session; initiating handshake")
|
||||
if !noiseService.hasSession(with: peerID) {
|
||||
initiateNoiseHandshake(with: peerID.id)
|
||||
initiateNoiseHandshake(with: peerID)
|
||||
}
|
||||
} catch {
|
||||
SecureLogger.error("❌ Failed to decrypt message from \(peerID): \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func handleLeave(_ packet: BitchatPacket, from peerID: String) {
|
||||
private func handleLeave(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
_ = collectionsQueue.sync(flags: .barrier) {
|
||||
// Remove the peer when they leave
|
||||
peers.removeValue(forKey: PeerID(str: peerID))
|
||||
peers.removeValue(forKey: peerID)
|
||||
}
|
||||
// Remove any stored announcement for sync purposes
|
||||
gossipSyncManager?.removeAnnouncementForPeer(PeerID(str: peerID))
|
||||
gossipSyncManager?.removeAnnouncementForPeer(peerID)
|
||||
// Send on main thread
|
||||
notifyUI { [weak self] in
|
||||
guard let self = self else { return }
|
||||
@@ -2825,7 +2822,7 @@ extension BLEService {
|
||||
// Get current peer list (after removal)
|
||||
let currentPeerIDs = self.collectionsQueue.sync { self.currentPeerIDs }
|
||||
|
||||
self.delegate?.didDisconnectFromPeer(PeerID(str: peerID))
|
||||
self.delegate?.didDisconnectFromPeer(peerID)
|
||||
self.delegate?.didUpdatePeerList(currentPeerIDs)
|
||||
}
|
||||
}
|
||||
@@ -2903,8 +2900,7 @@ extension BLEService {
|
||||
gossipSyncManager?.onPublicPacketSeen(signedPacket)
|
||||
}
|
||||
|
||||
private func sendPendingNoisePayloadsAfterHandshake(for peerID: String) {
|
||||
let peerID = PeerID(str: peerID)
|
||||
private func sendPendingNoisePayloadsAfterHandshake(for peerID: PeerID) {
|
||||
let payloads = collectionsQueue.sync(flags: .barrier) { () -> [Data] in
|
||||
let list = pendingNoisePayloadsAfterHandshake[peerID] ?? []
|
||||
pendingNoisePayloadsAfterHandshake.removeValue(forKey: peerID)
|
||||
@@ -2931,8 +2927,7 @@ extension BLEService {
|
||||
}
|
||||
}
|
||||
|
||||
private func updatePeerLastSeen(_ peerID: String) {
|
||||
let peerID = PeerID(str: peerID)
|
||||
private func updatePeerLastSeen(_ peerID: PeerID) {
|
||||
// Use async to avoid deadlock - we don't need immediate consistency for last seen updates
|
||||
collectionsQueue.async(flags: .barrier) {
|
||||
if var peer = self.peers[peerID] {
|
||||
@@ -2943,9 +2938,8 @@ extension BLEService {
|
||||
}
|
||||
|
||||
// Debounced disconnect notifier to avoid duplicate disconnect callbacks within a short window
|
||||
private func notifyPeerDisconnectedDebounced(_ peerID: String) {
|
||||
private func notifyPeerDisconnectedDebounced(_ peerID: PeerID) {
|
||||
let now = Date()
|
||||
let peerID = PeerID(str: peerID)
|
||||
let last = recentDisconnectNotifies[peerID]
|
||||
if last == nil || now.timeIntervalSince(last!) >= TransportConfig.bleDisconnectNotifyDebounceSeconds {
|
||||
delegate?.didDisconnectFromPeer(peerID)
|
||||
|
||||
@@ -28,7 +28,7 @@ struct FragmentationTests {
|
||||
ble.delegate = capture
|
||||
|
||||
// Construct a big packet (3KB) from a remote sender (not our own ID)
|
||||
let remoteShortID = "1122334455667788"
|
||||
let remoteShortID: PeerID = "1122334455667788"
|
||||
let original = makeLargePublicPacket(senderShortHex: remoteShortID, size: 3_000)
|
||||
|
||||
// Use a small fragment size to ensure multiple pieces
|
||||
@@ -59,7 +59,7 @@ struct FragmentationTests {
|
||||
let capture = CaptureDelegate()
|
||||
ble.delegate = capture
|
||||
|
||||
let remoteShortID = "A1B2C3D4E5F60708"
|
||||
let remoteShortID: PeerID = "A1B2C3D4E5F60708"
|
||||
let original = makeLargePublicPacket(senderShortHex: remoteShortID, size: 2048)
|
||||
var frags = fragmentPacket(original, fragmentSize: 300)
|
||||
|
||||
@@ -89,7 +89,7 @@ struct FragmentationTests {
|
||||
let capture = CaptureDelegate()
|
||||
ble.delegate = capture
|
||||
|
||||
let remoteShortID = "0011223344556677"
|
||||
let remoteShortID: PeerID = "0011223344556677"
|
||||
let original = makeLargePublicPacket(senderShortHex: remoteShortID, size: 1000)
|
||||
let fragments = fragmentPacket(original, fragmentSize: 250)
|
||||
|
||||
@@ -143,12 +143,12 @@ extension FragmentationTests {
|
||||
}
|
||||
|
||||
// Helper: build a large message packet (unencrypted public message)
|
||||
private func makeLargePublicPacket(senderShortHex: String, size: Int) -> BitchatPacket {
|
||||
private func makeLargePublicPacket(senderShortHex: PeerID, size: Int) -> BitchatPacket {
|
||||
let content = String(repeating: "A", count: size)
|
||||
let payload = Data(content.utf8)
|
||||
let pkt = BitchatPacket(
|
||||
type: MessageType.message.rawValue,
|
||||
senderID: Data(hexString: senderShortHex) ?? Data(),
|
||||
senderID: Data(hexString: senderShortHex.id) ?? Data(),
|
||||
recipientID: nil,
|
||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||
payload: payload,
|
||||
|
||||
Reference in New Issue
Block a user