mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-27 05:05:20 +00:00
Persist authenticated private-media delivery receipts (#1466)
Adds a durable receiver-side ledger (BLEPrivateMediaReceiptStore) mapping a deterministic private-media message ID — hash-bound to sender, recipient, and entropy-bearing filename — to the stored file before UI delivery and before the Noise-encrypted delivery ACK, so sender retries and relaunches cannot create duplicate bubbles or files. Receipts are unforgeable without the Noise session; capability bit 9 rides the existing announce bitfield (no wire-format change; rolling upgrade safe both directions). Includes review fixes: corrupt receipt records are quarantined per-record (bytes preserved at <id>.json.corrupt, only that ID fail-closed — previously one bad record silently disabled ALL inbound private media forever); the panic reset now reaches BLEService's own store instance via completePanicReset with a production-wiring test; and both content.delivery.reason.* strings ship with full 30-locale coverage.
This commit is contained in:
@@ -252,9 +252,17 @@ final class ChatMediaTransferCoordinator {
|
||||
}
|
||||
|
||||
let targetPeer = context.selectedPrivateChatPeer
|
||||
let privateMessageID = targetPeer.flatMap { peerID in
|
||||
PrivateMediaMessageIdentity.stableID(
|
||||
senderPeerID: context.myPeerID,
|
||||
recipientPeerID: peerID,
|
||||
fileName: url.lastPathComponent
|
||||
)
|
||||
}
|
||||
let message = enqueueMediaMessage(
|
||||
content: "\(MimeType.Category.audio.messagePrefix)\(url.lastPathComponent)",
|
||||
targetPeer: targetPeer
|
||||
targetPeer: targetPeer,
|
||||
messageID: privateMessageID
|
||||
)
|
||||
let messageID = message.id
|
||||
let transferId = makeTransferID(messageID: messageID)
|
||||
@@ -419,9 +427,17 @@ final class ChatMediaTransferCoordinator {
|
||||
try? FileManager.default.removeItem(at: prepared.outputURL)
|
||||
return
|
||||
}
|
||||
let privateMessageID = targetPeer.flatMap { peerID in
|
||||
PrivateMediaMessageIdentity.stableID(
|
||||
for: prepared.packet,
|
||||
senderPeerID: self.context.myPeerID,
|
||||
recipientPeerID: peerID
|
||||
)
|
||||
}
|
||||
let message = self.enqueueMediaMessage(
|
||||
content: "\(MimeType.Category.image.messagePrefix)\(prepared.outputURL.lastPathComponent)",
|
||||
targetPeer: targetPeer
|
||||
targetPeer: targetPeer,
|
||||
messageID: privateMessageID
|
||||
)
|
||||
let messageID = message.id
|
||||
let transferId = self.makeTransferID(messageID: messageID)
|
||||
@@ -459,12 +475,17 @@ final class ChatMediaTransferCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
func enqueueMediaMessage(content: String, targetPeer: PeerID?) -> BitchatMessage {
|
||||
func enqueueMediaMessage(
|
||||
content: String,
|
||||
targetPeer: PeerID?,
|
||||
messageID: String? = nil
|
||||
) -> BitchatMessage {
|
||||
let timestamp = Date()
|
||||
let message: BitchatMessage
|
||||
|
||||
if let peerID = targetPeer {
|
||||
message = BitchatMessage(
|
||||
id: messageID,
|
||||
sender: context.nickname,
|
||||
content: content,
|
||||
timestamp: timestamp,
|
||||
|
||||
Reference in New Issue
Block a user