diff --git a/TelegramCore/CallSessionManager.swift b/TelegramCore/CallSessionManager.swift index c9b6f0a263..91e6c42b1c 100644 --- a/TelegramCore/CallSessionManager.swift +++ b/TelegramCore/CallSessionManager.swift @@ -283,7 +283,7 @@ private final class CallSessionManagerContext { disposable.dispose() dropData = (id, accessHash, .abort) case let .requested(id, accessHash, _, _, _, _): - dropData = (id, accessHash, .abort) + dropData = (id, accessHash, .busy) case let .requesting(_, disposable): disposable.dispose() context.state = .terminated(reason: .ended(.hungUp), reportRating: false) diff --git a/TelegramCore/ManagedSecretChatOutgoingOperations.swift b/TelegramCore/ManagedSecretChatOutgoingOperations.swift index e7e5eee411..8124aced10 100644 --- a/TelegramCore/ManagedSecretChatOutgoingOperations.swift +++ b/TelegramCore/ManagedSecretChatOutgoingOperations.swift @@ -28,7 +28,7 @@ func addSecretChatOutgoingOperation(modifier: Modifier, peerId: PeerId, operatio } private final class ManagedSecretChatOutgoingOperationsHelper { - var operationDisposables: [Int32: Disposable] = [:] + var operationDisposables: [Int32: (PeerMergedOperationLogEntry, Disposable)] = [:] func update(_ entries: [PeerMergedOperationLogEntry]) -> (disposeOperations: [Disposable], beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)]) { var disposeOperations: [Disposable] = [] @@ -37,6 +37,23 @@ private final class ManagedSecretChatOutgoingOperationsHelper { var hasRunningOperationForPeerId = Set() var validMergedIndices = Set() for entry in entries { + if let entryAndDisposable = self.operationDisposables[entry.mergedIndex] { + if let lhsOperation = entryAndDisposable.0.contents as? SecretChatOutgoingOperation, let rhsOperation = entry.contents as? SecretChatOutgoingOperation { + var lhsDelete = false + if case .deleteMessages = lhsOperation.contents { + lhsDelete = true + } + var rhsDelete = false + if case .deleteMessages = rhsOperation.contents { + rhsDelete = true + } + if lhsDelete != rhsDelete { + disposeOperations.append(entryAndDisposable.1) + self.operationDisposables.removeValue(forKey: entry.mergedIndex) + } + } + } + if !hasRunningOperationForPeerId.contains(entry.peerId) { hasRunningOperationForPeerId.insert(entry.peerId) validMergedIndices.insert(entry.mergedIndex) @@ -44,16 +61,16 @@ private final class ManagedSecretChatOutgoingOperationsHelper { if self.operationDisposables[entry.mergedIndex] == nil { let disposable = MetaDisposable() beginOperations.append((entry, disposable)) - self.operationDisposables[entry.mergedIndex] = disposable + self.operationDisposables[entry.mergedIndex] = (entry, disposable) } } } var removeMergedIndices: [Int32] = [] - for (mergedIndex, disposable) in self.operationDisposables { + for (mergedIndex, entryAndDisposable) in self.operationDisposables { if !validMergedIndices.contains(mergedIndex) { removeMergedIndices.append(mergedIndex) - disposeOperations.append(disposable) + disposeOperations.append(entryAndDisposable.1) } } @@ -67,7 +84,7 @@ private final class ManagedSecretChatOutgoingOperationsHelper { func reset() -> [Disposable] { let disposables = Array(self.operationDisposables.values) self.operationDisposables.removeAll() - return disposables + return disposables.map { $0.1 } } } @@ -615,7 +632,7 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B } } -private func markOutgoingOperationAsCompleted(modifier: Modifier, peerId: PeerId, tagLocalIndex: Int32) { +private func markOutgoingOperationAsCompleted(modifier: Modifier, peerId: PeerId, tagLocalIndex: Int32, forceRemove: Bool) { var removeFromTagMergedIndexOnly = false if let state = modifier.getPeerChatState(peerId) as? SecretChatState { switch state.embeddedState { @@ -627,7 +644,7 @@ private func markOutgoingOperationAsCompleted(modifier: Modifier, peerId: PeerId break } } - if removeFromTagMergedIndexOnly { + if removeFromTagMergedIndexOnly && !forceRemove { modifier.operationLogUpdateEntry(peerId: peerId, tag: OperationLogTags.SecretOutgoing, tagLocalIndex: tagLocalIndex, { entry in if let operation = entry?.contents as? SecretChatOutgoingOperation { return PeerOperationLogEntryUpdate(mergedIndex: .remove, contents: .update(operation.withUpdatedDelivered(true))) @@ -637,7 +654,35 @@ private func markOutgoingOperationAsCompleted(modifier: Modifier, peerId: PeerId } }) } else { - modifier.operationLogRemoveEntry(peerId: peerId, tag: OperationLogTags.SecretOutgoing, tagLocalIndex: tagLocalIndex) + let _ = modifier.operationLogRemoveEntry(peerId: peerId, tag: OperationLogTags.SecretOutgoing, tagLocalIndex: tagLocalIndex) + } +} + +private func replaceOutgoingOperationWithEmptyMessage(modifier: Modifier, peerId: PeerId, tagLocalIndex: Int32, globallyUniqueId: Int64) { + var layer: SecretChatLayer? + let state = modifier.getPeerChatState(peerId) as? SecretChatState + if let state = state { + switch state.embeddedState { + case .terminated, .handshake: + break + case .basicLayer: + layer = .layer8 + case let .sequenceBasedLayer(sequenceState): + layer = SecretChatLayer(rawValue: sequenceState.layerNegotiationState.activeLayer) + } + } + if let layer = layer { + modifier.operationLogUpdateEntry(peerId: peerId, tag: OperationLogTags.SecretOutgoing, tagLocalIndex: tagLocalIndex, { entry in + if let _ = entry?.contents as? SecretChatOutgoingOperation { + return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .update(SecretChatOutgoingOperation(contents: SecretChatOutgoingOperationContents.deleteMessages(layer: layer, actionGloballyUniqueId: arc4random64(), globallyUniqueIds: [globallyUniqueId]), mutable: true, delivered: false))) + } else { + assertionFailure() + return PeerOperationLogEntryUpdate(mergedIndex: .remove, contents: .none) + } + }) + } else { + assertionFailure() + let _ = modifier.operationLogRemoveEntry(peerId: peerId, tag: OperationLogTags.SecretOutgoing, tagLocalIndex: tagLocalIndex) } } @@ -649,7 +694,11 @@ private func sendMessage(postbox: Postbox, network: Network, messageId: MessageI return sendBoxedDecryptedMessage(postbox: postbox, network: network, peer: peer, state: state, operationIndex: tagLocalIndex, decryptedMessage: decryptedMessage, globallyUniqueId: globallyUniqueId, file: file, asService: wasDelivered, wasDelivered: wasDelivered) |> mapToSignal { result in return postbox.modify { modifier -> Void in - markOutgoingOperationAsCompleted(modifier: modifier, peerId: messageId.peerId, tagLocalIndex: tagLocalIndex) + if result == nil { + replaceOutgoingOperationWithEmptyMessage(modifier: modifier, peerId: messageId.peerId, tagLocalIndex: tagLocalIndex, globallyUniqueId: globallyUniqueId) + } else { + markOutgoingOperationAsCompleted(modifier: modifier, peerId: messageId.peerId, tagLocalIndex: tagLocalIndex, forceRemove: result == nil) + } modifier.updateMessage(message.id, update: { currentMessage in var flags = StoreMessageFlags(currentMessage.flags) var timestamp = message.timestamp @@ -690,7 +739,11 @@ private func sendServiceActionMessage(postbox: Postbox, network: Network, peerId return sendBoxedDecryptedMessage(postbox: postbox, network: network, peer: peer, state: state, operationIndex: tagLocalIndex, decryptedMessage: decryptedMessage, globallyUniqueId: action.globallyUniqueId, file: nil, asService: true, wasDelivered: wasDelivered) |> mapToSignal { result in return postbox.modify { modifier -> Void in - markOutgoingOperationAsCompleted(modifier: modifier, peerId: peerId, tagLocalIndex: tagLocalIndex) + if result == nil { + replaceOutgoingOperationWithEmptyMessage(modifier: modifier, peerId: peerId, tagLocalIndex: tagLocalIndex, globallyUniqueId: action.globallyUniqueId) + } else { + markOutgoingOperationAsCompleted(modifier: modifier, peerId: peerId, tagLocalIndex: tagLocalIndex, forceRemove: result == nil) + } if let messageId = action.messageId { modifier.updateMessage(messageId, update: { currentMessage in var flags = StoreMessageFlags(currentMessage.flags) @@ -786,7 +839,7 @@ private func requestTerminateSecretChat(postbox: Postbox, network: Network, peer } |> mapToSignal { _ -> Signal in return postbox.modify { modifier -> Void in - markOutgoingOperationAsCompleted(modifier: modifier, peerId: peerId, tagLocalIndex: tagLocalIndex) + markOutgoingOperationAsCompleted(modifier: modifier, peerId: peerId, tagLocalIndex: tagLocalIndex, forceRemove: true) } } } diff --git a/TelegramCore/MultipartUpload.swift b/TelegramCore/MultipartUpload.swift index fe44f200dc..709983039a 100644 --- a/TelegramCore/MultipartUpload.swift +++ b/TelegramCore/MultipartUpload.swift @@ -236,7 +236,8 @@ private final class MultipartUploadManager { if let resourceData = self.resourceData, resourceData.complete, self.committedOffset >= resourceData.size { if self.headerPartReady { let effectiveSize = self.state.finalize() - self.completed(MultipartIntermediateResult(id: self.fileId, partCount: Int32(effectiveSize / self.defaultPartSize + (effectiveSize % self.defaultPartSize == 0 ? 0 : 1)), md5Digest: "", size: Int32(resourceData.size), bigTotalParts: self.bigTotalParts)) + let effectivePartCount = Int32(effectiveSize / self.defaultPartSize + (effectiveSize % self.defaultPartSize == 0 ? 0 : 1)) + self.completed(MultipartIntermediateResult(id: self.fileId, partCount: effectivePartCount, md5Digest: "", size: Int32(resourceData.size), bigTotalParts: self.bigTotalParts)) } else { let partOffset = 0 let partSize = min(resourceData.size - partOffset, self.defaultPartSize) @@ -372,8 +373,13 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload uintPtr[3] = bytes[3] ^ bytes[7] }) } - let inputFile = Api.InputEncryptedFile.inputEncryptedFileUploaded(id: result.id, parts: result.partCount, md5Checksum: result.md5Digest, keyFingerprint: fingerprint) - subscriber.putNext(.inputSecretFile(inputFile, result.size, encryptionKey)) + if let _ = result.bigTotalParts { + let inputFile = Api.InputEncryptedFile.inputEncryptedFileBigUploaded(id: result.id, parts: result.partCount, keyFingerprint: fingerprint) + subscriber.putNext(.inputSecretFile(inputFile, result.size, encryptionKey)) + } else { + let inputFile = Api.InputEncryptedFile.inputEncryptedFileUploaded(id: result.id, parts: result.partCount, md5Checksum: result.md5Digest, keyFingerprint: fingerprint) + subscriber.putNext(.inputSecretFile(inputFile, result.size, encryptionKey)) + } } else { if let _ = result.bigTotalParts { let inputFile = Api.InputFile.inputFileBig(id: result.id, parts: result.partCount, name: "file.jpg") diff --git a/TelegramCore/RemovePeerChat.swift b/TelegramCore/RemovePeerChat.swift index 61d445f816..3143a55f4c 100644 --- a/TelegramCore/RemovePeerChat.swift +++ b/TelegramCore/RemovePeerChat.swift @@ -11,6 +11,7 @@ public func removePeerChat(postbox: Postbox, peerId: PeerId, reportChatSpam: Boo return postbox.modify { modifier -> Void in if peerId.namespace == Namespaces.Peer.SecretChat { if let state = modifier.getPeerChatState(peerId) as? SecretChatState { + let updatedState = addSecretChatOutgoingOperation(modifier: modifier, peerId: peerId, operation: SecretChatOutgoingOperationContents.terminate, state: state).withUpdatedEmbeddedState(.terminated) if updatedState != state { modifier.setPeerChatState(peerId, state: updatedState)