Use unique transfer identifiers

This commit is contained in:
jack
2025-10-15 17:37:19 +01:00
committed by islam
parent 93aa714ed4
commit a8ce4cbf64
2 changed files with 25 additions and 21 deletions
+12 -12
View File
@@ -707,7 +707,7 @@ final class BLEService: NSObject {
sendPrivateMessage(content, to: peerID.id, messageID: messageID) sendPrivateMessage(content, to: peerID.id, messageID: messageID)
func sendFileBroadcast(_ filePacket: BitchatFilePacket) { func sendFileBroadcast(_ filePacket: BitchatFilePacket, transferId: String) {
messageQueue.async { [weak self] in messageQueue.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
guard let payload = filePacket.encode() else { guard let payload = filePacket.encode() else {
@@ -731,12 +731,12 @@ final class BLEService: NSObject {
self.messageDeduplicator.markProcessed(dedupID) self.messageDeduplicator.markProcessed(dedupID)
SecureLogger.debug("📁 Broadcasting file transfer payload bytes=\(payload.count)", category: .session) SecureLogger.debug("📁 Broadcasting file transfer payload bytes=\(payload.count)", category: .session)
self.broadcastPacket(packet) self.broadcastPacket(packet, transferId: transferId)
self.gossipSyncManager?.onPublicPacketSeen(packet) self.gossipSyncManager?.onPublicPacketSeen(packet)
} }
} }
func sendFilePrivate(_ filePacket: BitchatFilePacket, to peerID: PeerID) { func sendFilePrivate(_ filePacket: BitchatFilePacket, to peerID: PeerID, transferId: String) {
messageQueue.async { [weak self] in messageQueue.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
guard let payload = filePacket.encode() else { guard let payload = filePacket.encode() else {
@@ -764,7 +764,7 @@ final class BLEService: NSObject {
} }
SecureLogger.debug("📁 Sending private file transfer to \(peerID.prefix(8))… bytes=\(payload.count)", category: .session) SecureLogger.debug("📁 Sending private file transfer to \(peerID.prefix(8))… bytes=\(payload.count)", category: .session)
self.broadcastPacket(packet) self.broadcastPacket(packet, transferId: transferId)
} }
} }
@@ -841,11 +841,11 @@ final class BLEService: NSObject {
// MARK: - Packet Broadcasting // MARK: - Packet Broadcasting
private func broadcastPacket(_ packet: BitchatPacket) { private func broadcastPacket(_ packet: BitchatPacket, transferId: String? = nil) {
// 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)
if packet.type == MessageType.fileTransfer.rawValue { if packet.type == MessageType.fileTransfer.rawValue {
sendFragmentedPacket(packet, pad: padForBLE, maxChunk: nil, directedOnlyPeer: nil) sendFragmentedPacket(packet, pad: padForBLE, maxChunk: nil, directedOnlyPeer: nil, transferId: transferId)
return return
} }
guard let data = packet.toBinaryData(padding: padForBLE) else { guard let data = packet.toBinaryData(padding: padForBLE) else {
@@ -1106,7 +1106,7 @@ final class BLEService: NSObject {
// MARK: - Fragmentation (Required for messages > BLE MTU) // 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: String? = nil, transferId: String? = nil) {
guard let fullData = packet.toBinaryData(padding: pad) else { return } guard let fullData = packet.toBinaryData(padding: pad) else { return }
// Fragment the unpadded frame; each fragment will be encoded independently // Fragment the unpadded frame; each fragment will be encoded independently
@@ -1134,9 +1134,9 @@ final class BLEService: NSObject {
} }
let perFragMs = (directedOnlyPeer != nil || packet.recipientID != nil) ? TransportConfig.bleFragmentSpacingDirectedMs : TransportConfig.bleFragmentSpacingMs let perFragMs = (directedOnlyPeer != nil || packet.recipientID != nil) ? TransportConfig.bleFragmentSpacingDirectedMs : TransportConfig.bleFragmentSpacingMs
let transferId: String? = { let transferIdentifier: String? = {
guard packet.type == MessageType.fileTransfer.rawValue else { return nil } guard packet.type == MessageType.fileTransfer.rawValue else { return nil }
let id = packet.payload.sha256Hex() let id = transferId ?? packet.payload.sha256Hex()
collectionsQueue.sync(flags: .barrier) { collectionsQueue.sync(flags: .barrier) {
self.activeTransfers[id] = ActiveTransferState(totalFragments: totalFragments, sentFragments: 0, workItems: []) self.activeTransfers[id] = ActiveTransferState(totalFragments: totalFragments, sentFragments: 0, workItems: [])
} }
@@ -1171,12 +1171,12 @@ final class BLEService: NSObject {
let workItem = DispatchWorkItem { [weak self] in let workItem = DispatchWorkItem { [weak self] in
guard let self = self else { return } guard let self = self else { return }
if let transferId = transferId { if let transferId = transferIdentifier {
let isActive = self.collectionsQueue.sync { self.activeTransfers[transferId] != nil } let isActive = self.collectionsQueue.sync { self.activeTransfers[transferId] != nil }
guard isActive else { return } guard isActive else { return }
} }
self.broadcastPacket(fragmentPacket) self.broadcastPacket(fragmentPacket)
if let transferId = transferId { if let transferId = transferIdentifier {
self.markFragmentSent(transferId: transferId) self.markFragmentSent(transferId: transferId)
} }
} }
@@ -1184,7 +1184,7 @@ final class BLEService: NSObject {
scheduledItems.append((item: workItem, index: index)) scheduledItems.append((item: workItem, index: index))
} }
if let transferId = transferId { if let transferId = transferIdentifier {
let workItems = scheduledItems.map { $0.item } let workItems = scheduledItems.map { $0.item }
collectionsQueue.async(flags: .barrier) { [weak self] in collectionsQueue.async(flags: .barrier) { [weak self] in
guard let self = self, var state = self.activeTransfers[transferId] else { return } guard let self = self, var state = self.activeTransfers[transferId] else { return }
+13 -9
View File
@@ -2386,6 +2386,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
let targetPeer = selectedPrivateChatPeer let targetPeer = selectedPrivateChatPeer
let message = enqueueMediaMessage(content: "[voice] \(url.path)", targetPeer: targetPeer) let message = enqueueMediaMessage(content: "[voice] \(url.path)", targetPeer: targetPeer)
let messageID = message.id let messageID = message.id
let transferId = makeTransferID(messageID: messageID)
Task.detached(priority: .userInitiated) { [weak self] in Task.detached(priority: .userInitiated) { [weak self] in
guard let self = self else { return } guard let self = self else { return }
@@ -2406,13 +2407,12 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
content: data content: data
) )
guard let payload = packet.encode() else { throw MediaSendError.encodingFailed } guard let payload = packet.encode() else { throw MediaSendError.encodingFailed }
let transferId = payload.sha256Hex()
await MainActor.run { await MainActor.run {
self.registerTransfer(transferId: transferId, messageID: messageID) self.registerTransfer(transferId: transferId, messageID: messageID)
if let peerID = targetPeer { if let peerID = targetPeer {
self.meshService.sendFilePrivate(packet, to: peerID) self.meshService.sendFilePrivate(packet, to: peerID, transferId: transferId)
} else { } else {
self.meshService.sendFileBroadcast(packet) self.meshService.sendFileBroadcast(packet, transferId: transferId)
} }
} }
} catch { } catch {
@@ -2450,15 +2450,15 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
content: data content: data
) )
guard let payload = packet.encode() else { throw MediaSendError.encodingFailed } guard let payload = packet.encode() else { throw MediaSendError.encodingFailed }
let transferId = payload.sha256Hex()
await MainActor.run { await MainActor.run {
let message = self.enqueueMediaMessage(content: "[image] \(outputURL.path)", targetPeer: targetPeer) let message = self.enqueueMediaMessage(content: "[image] \(outputURL.path)", targetPeer: targetPeer)
let messageID = message.id let messageID = message.id
let transferId = self.makeTransferID(messageID: messageID)
self.registerTransfer(transferId: transferId, messageID: messageID) self.registerTransfer(transferId: transferId, messageID: messageID)
if let peerID = targetPeer { if let peerID = targetPeer {
self.meshService.sendFilePrivate(packet, to: peerID) self.meshService.sendFilePrivate(packet, to: peerID, transferId: transferId)
} else { } else {
self.meshService.sendFileBroadcast(packet) self.meshService.sendFileBroadcast(packet, transferId: transferId)
} }
} }
} catch { } catch {
@@ -2500,16 +2500,16 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
try? FileManager.default.removeItem(at: destination) try? FileManager.default.removeItem(at: destination)
throw MediaSendError.encodingFailed throw MediaSendError.encodingFailed
} }
let transferId = payload.sha256Hex()
await MainActor.run { await MainActor.run {
let message = self.enqueueMediaMessage(content: "[file] \(destination.path)", targetPeer: targetPeer) let message = self.enqueueMediaMessage(content: "[file] \(destination.path)", targetPeer: targetPeer)
let messageID = message.id let messageID = message.id
let transferId = self.makeTransferID(messageID: messageID)
self.registerTransfer(transferId: transferId, messageID: messageID) self.registerTransfer(transferId: transferId, messageID: messageID)
if let peerID = targetPeer { if let peerID = targetPeer {
self.meshService.sendFilePrivate(packet, to: peerID) self.meshService.sendFilePrivate(packet, to: peerID, transferId: transferId)
} else { } else {
self.meshService.sendFileBroadcast(packet) self.meshService.sendFileBroadcast(packet, transferId: transferId)
} }
} }
} catch MediaSendError.tooLarge { } catch MediaSendError.tooLarge {
@@ -2637,6 +2637,10 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
messageIDToTransferId[messageID] = transferId messageIDToTransferId[messageID] = transferId
} }
private func makeTransferID(messageID: String) -> String {
"\(messageID)-\(UUID().uuidString)"
}
@MainActor @MainActor
private func clearTransferMapping(for messageID: String) { private func clearTransferMapping(for messageID: String) {
guard let transferId = messageIDToTransferId.removeValue(forKey: messageID) else { return } guard let transferId = messageIDToTransferId.removeValue(forKey: messageID) else { return }