mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-07 23:03:35 +00:00
Merge branch 'master' of https://github.com/peter-iakovlev/TelegramCore
This commit is contained in:
commit
dc46d2a473
@ -335,6 +335,8 @@
|
||||
D0B418BA1D7E05BB004562A4 /* NetworkLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = D03B0E421D631E6600955575 /* NetworkLogging.m */; };
|
||||
D0B418BB1D7E05BE004562A4 /* NetworkLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = D03B0E411D631E6600955575 /* NetworkLogging.h */; };
|
||||
D0B418BC1D7E05D0004562A4 /* TelegramCoreIncludes.h in Headers */ = {isa = PBXBuildFile; fileRef = D03B0E5B1D63240700955575 /* TelegramCoreIncludes.h */; };
|
||||
D0B477731EBF54A20033A0AB /* RecentCalls.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B477721EBF54A20033A0AB /* RecentCalls.swift */; };
|
||||
D0B477741EBF54A20033A0AB /* RecentCalls.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B477721EBF54A20033A0AB /* RecentCalls.swift */; };
|
||||
D0B843811DA6EDAE005F29E1 /* CachedUserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B843801DA6EDAE005F29E1 /* CachedUserData.swift */; };
|
||||
D0B843831DA6EDB8005F29E1 /* CachedGroupData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B843821DA6EDB8005F29E1 /* CachedGroupData.swift */; };
|
||||
D0B843851DA6EDC4005F29E1 /* CachedChannelData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B843841DA6EDC4005F29E1 /* CachedChannelData.swift */; };
|
||||
@ -418,8 +420,6 @@
|
||||
D0C48F3A1E8138DF0075317D /* ArchivedStickerPacksInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C48F381E8138DF0075317D /* ArchivedStickerPacksInfo.swift */; };
|
||||
D0C48F3C1E8142EF0075317D /* LoadedPeerFromMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C48F3B1E8142EF0075317D /* LoadedPeerFromMessage.swift */; };
|
||||
D0C48F3D1E8142EF0075317D /* LoadedPeerFromMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C48F3B1E8142EF0075317D /* LoadedPeerFromMessage.swift */; };
|
||||
D0C50E311E93A85E00F62E39 /* CallSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C50E301E93A85D00F62E39 /* CallSession.swift */; };
|
||||
D0C50E321E93A85E00F62E39 /* CallSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C50E301E93A85D00F62E39 /* CallSession.swift */; };
|
||||
D0C50E341E93A86600F62E39 /* CallSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C50E331E93A86600F62E39 /* CallSessionManager.swift */; };
|
||||
D0C50E351E93A86600F62E39 /* CallSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C50E331E93A86600F62E39 /* CallSessionManager.swift */; };
|
||||
D0CAF2EA1D75EC600011F558 /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */; };
|
||||
@ -704,6 +704,7 @@
|
||||
D0B418701D7E0409004562A4 /* PostboxMac.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PostboxMac.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug/PostboxMac.framework"; sourceTree = "<group>"; };
|
||||
D0B418711D7E0409004562A4 /* SwiftSignalKitMac.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftSignalKitMac.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug/SwiftSignalKitMac.framework"; sourceTree = "<group>"; };
|
||||
D0B4187E1D7E054E004562A4 /* MtProtoKitMac.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MtProtoKitMac.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug/MtProtoKitMac.framework"; sourceTree = "<group>"; };
|
||||
D0B477721EBF54A20033A0AB /* RecentCalls.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentCalls.swift; sourceTree = "<group>"; };
|
||||
D0B843801DA6EDAE005F29E1 /* CachedUserData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedUserData.swift; sourceTree = "<group>"; };
|
||||
D0B843821DA6EDB8005F29E1 /* CachedGroupData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedGroupData.swift; sourceTree = "<group>"; };
|
||||
D0B843841DA6EDC4005F29E1 /* CachedChannelData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedChannelData.swift; sourceTree = "<group>"; };
|
||||
@ -751,7 +752,6 @@
|
||||
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
||||
D0C48F381E8138DF0075317D /* ArchivedStickerPacksInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArchivedStickerPacksInfo.swift; sourceTree = "<group>"; };
|
||||
D0C48F3B1E8142EF0075317D /* LoadedPeerFromMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedPeerFromMessage.swift; sourceTree = "<group>"; };
|
||||
D0C50E301E93A85D00F62E39 /* CallSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSession.swift; sourceTree = "<group>"; };
|
||||
D0C50E331E93A86600F62E39 /* CallSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSessionManager.swift; sourceTree = "<group>"; };
|
||||
D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MtProtoKitDynamic.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/MtProtoKitDynamic.framework"; sourceTree = "<group>"; };
|
||||
D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerPackInteractiveOperations.swift; sourceTree = "<group>"; };
|
||||
@ -1275,8 +1275,8 @@
|
||||
D0C50E2F1E93A83B00F62E39 /* Calls */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0C50E301E93A85D00F62E39 /* CallSession.swift */,
|
||||
D0C50E331E93A86600F62E39 /* CallSessionManager.swift */,
|
||||
D0B477721EBF54A20033A0AB /* RecentCalls.swift */,
|
||||
);
|
||||
name = Calls;
|
||||
sourceTree = "<group>";
|
||||
@ -1616,6 +1616,7 @@
|
||||
D03B0D0A1D62255C00955575 /* Holes.swift in Sources */,
|
||||
D0B843CB1DA7FF30005F29E1 /* NBPhoneNumberUtil.m in Sources */,
|
||||
D03B0D5E1D631A6900955575 /* Network.swift in Sources */,
|
||||
D0B477731EBF54A20033A0AB /* RecentCalls.swift in Sources */,
|
||||
D0B8438E1DA7D296005F29E1 /* CachedGroupParticipants.swift in Sources */,
|
||||
D0B843BD1DA7FF30005F29E1 /* NBMetadataHelper.m in Sources */,
|
||||
D03B0CF51D62250800955575 /* TelegramMediaContact.swift in Sources */,
|
||||
@ -1756,7 +1757,6 @@
|
||||
D0E305A71E5B5CBE00D7A3A2 /* PeerAdmins.swift in Sources */,
|
||||
D0B843C51DA7FF30005F29E1 /* NBPhoneNumber.m in Sources */,
|
||||
D03B0D0D1D62255C00955575 /* SynchronizePeerReadState.swift in Sources */,
|
||||
D0C50E311E93A85E00F62E39 /* CallSession.swift in Sources */,
|
||||
D03B0D081D62255C00955575 /* ChannelState.swift in Sources */,
|
||||
C251D7431E65E50500283EDE /* StickerSetInstallation.swift in Sources */,
|
||||
);
|
||||
@ -1806,8 +1806,8 @@
|
||||
D0E23DE01E8082A400B9B6D2 /* ArchivedStickerPacks.swift in Sources */,
|
||||
D050F2521E4A59C200988324 /* JoinLink.swift in Sources */,
|
||||
D0F7B1E91E045C87007EB8A5 /* PeerCommands.swift in Sources */,
|
||||
D0B477741EBF54A20033A0AB /* RecentCalls.swift in Sources */,
|
||||
D00D97C81E32901700E5C2B6 /* PeerInputActivity.swift in Sources */,
|
||||
D0C50E321E93A85E00F62E39 /* CallSession.swift in Sources */,
|
||||
D0B844311DAB91E0005F29E1 /* NBPhoneMetaData.m in Sources */,
|
||||
C22EE61C1E67418000334C38 /* ToggleChannelSignatures.swift in Sources */,
|
||||
D0B418AC1D7E0597004562A4 /* Network.swift in Sources */,
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
@ -9,6 +9,18 @@ import Foundation
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public enum CallSessionError {
|
||||
case generic
|
||||
case privacyRestricted
|
||||
case notSupportedByPeer
|
||||
case serverProvided(String)
|
||||
}
|
||||
|
||||
public enum CallSessionTerminationReason {
|
||||
case ended
|
||||
case error(CallSessionError)
|
||||
}
|
||||
|
||||
enum CallSessionInternalState {
|
||||
case ringing(id: Int64, accessHash: Int64, gAHash: Data, b: Data)
|
||||
case accepting(id: Int64, accessHash: Int64, gAHash: Data, b: Data, disposable: Disposable)
|
||||
@ -18,7 +30,7 @@ enum CallSessionInternalState {
|
||||
case confirming(id: Int64, accessHash: Int64, key: Data, keyId: Int64, keyVisualHash: Data, disposable: Disposable)
|
||||
case active(id: Int64, accessHash: Int64, beginTimestamp: Int32, key: Data, keyId: Int64, keyVisualHash: Data, connections: CallSessionConnectionSet)
|
||||
case dropping(Disposable)
|
||||
case terminated
|
||||
case terminated(CallSessionTerminationReason)
|
||||
}
|
||||
|
||||
public typealias CallSessionInternalId = Int64
|
||||
@ -35,7 +47,7 @@ public enum CallSessionState {
|
||||
case requesting(ringing: Bool)
|
||||
case active(key: Data, keyVisualHash: Data, connections: CallSessionConnectionSet)
|
||||
case dropping
|
||||
case terminated
|
||||
case terminated(CallSessionTerminationReason)
|
||||
|
||||
fileprivate init(_ context: CallSessionContext) {
|
||||
switch context.state {
|
||||
@ -51,8 +63,8 @@ public enum CallSessionState {
|
||||
self = .active(key: key, keyVisualHash: keyVisualHash, connections: connections)
|
||||
case .dropping:
|
||||
self = .dropping
|
||||
case .terminated:
|
||||
self = .terminated
|
||||
case let .terminated(reason):
|
||||
self = .terminated(reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -250,7 +262,7 @@ private final class CallSessionManagerContext {
|
||||
dropData = (id, accessHash, .abort)
|
||||
case let .requesting(_, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated
|
||||
context.state = .terminated(.ended)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
if context.isEmpty {
|
||||
self.contexts.removeValue(forKey: internalId)
|
||||
@ -262,7 +274,7 @@ private final class CallSessionManagerContext {
|
||||
context.state = .dropping((dropCallSession(network: self.network, addUpdates: self.addUpdates, stableId: id, accessHash: accessHash, reason: reason) |> deliverOn(self.queue)).start(completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if let context = strongSelf.contexts[internalId] {
|
||||
context.state = .terminated
|
||||
context.state = .terminated(.ended)
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
if context.isEmpty {
|
||||
strongSelf.contexts.removeValue(forKey: internalId)
|
||||
@ -324,94 +336,103 @@ private final class CallSessionManagerContext {
|
||||
switch call {
|
||||
case .phoneCallEmpty:
|
||||
break
|
||||
case let .phoneCallAccepted(id, _, date, _, _, gB, `protocol`):
|
||||
case let .phoneCallAccepted(id, _, _, _, _, gB, _):
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
let context = self.contexts[internalId]!
|
||||
switch context.state {
|
||||
case let .requested(_, accessHash, a, gA, config, _):
|
||||
var key = MTExp(gB.makeData(), a, config.p.makeData())!
|
||||
|
||||
if key.count > 256 {
|
||||
key.count = 256
|
||||
} else {
|
||||
while key.count < 256 {
|
||||
key.insert(0, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
let keyHash = MTSha1(key)!
|
||||
|
||||
var keyId: Int64 = 0
|
||||
keyHash.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
|
||||
memcpy(&keyId, bytes.advanced(by: keyHash.count - 8), 8)
|
||||
}
|
||||
|
||||
let keyVisualHash = MTSha256(key + gA)!
|
||||
|
||||
context.state = .confirming(id: id, accessHash: accessHash, key: key, keyId: keyId, keyVisualHash: keyVisualHash, disposable: (confirmCallSession(network: self.network, stableId: id, accessHash: accessHash, gA: gA, keyFingerprint: keyId) |> deliverOnMainQueue).start(next: { [weak self] updatedCall in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId], case .confirming = context.state {
|
||||
if let updatedCall = updatedCall {
|
||||
strongSelf.updateSession(updatedCall)
|
||||
} else {
|
||||
strongSelf.drop(internalId: internalId)
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .requested(_, accessHash, a, gA, config, _):
|
||||
var key = MTExp(gB.makeData(), a, config.p.makeData())!
|
||||
|
||||
if key.count > 256 {
|
||||
key.count = 256
|
||||
} else {
|
||||
while key.count < 256 {
|
||||
key.insert(0, at: 0)
|
||||
}
|
||||
}
|
||||
}))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
default:
|
||||
self.drop(internalId: internalId)
|
||||
|
||||
let keyHash = MTSha1(key)!
|
||||
|
||||
var keyId: Int64 = 0
|
||||
keyHash.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
|
||||
memcpy(&keyId, bytes.advanced(by: keyHash.count - 8), 8)
|
||||
}
|
||||
|
||||
let keyVisualHash = MTSha256(key + gA)!
|
||||
|
||||
context.state = .confirming(id: id, accessHash: accessHash, key: key, keyId: keyId, keyVisualHash: keyVisualHash, disposable: (confirmCallSession(network: self.network, stableId: id, accessHash: accessHash, gA: gA, keyFingerprint: keyId) |> deliverOnMainQueue).start(next: { [weak self] updatedCall in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId], case .confirming = context.state {
|
||||
if let updatedCall = updatedCall {
|
||||
strongSelf.updateSession(updatedCall)
|
||||
} else {
|
||||
strongSelf.drop(internalId: internalId)
|
||||
}
|
||||
}
|
||||
}))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
default:
|
||||
self.drop(internalId: internalId)
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .phoneCallDiscarded(_, id, reason, duration):
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
let context = self.contexts[internalId]!
|
||||
switch context.state {
|
||||
case let .accepting(_, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .active:
|
||||
context.state = .terminated
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .awaitingConfirmation, .requested:
|
||||
context.state = .terminated
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .confirming(_, _, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .requesting(_, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .ringing:
|
||||
context.state = .terminated
|
||||
self.ringingStatesUpdated()
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .dropping, .terminated:
|
||||
break
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .accepting(_, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(.ended)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .active:
|
||||
context.state = .terminated(.ended)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .awaitingConfirmation, .requested:
|
||||
context.state = .terminated(.ended)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .confirming(_, _, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(.ended)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .requesting(_, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(.ended)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .ringing:
|
||||
context.state = .terminated(.ended)
|
||||
self.ringingStatesUpdated()
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .dropping, .terminated:
|
||||
break
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .phoneCall(id, _, _, _, _, gAOrB, keyFingerprint, _, connection, alternativeConnections, startDate):
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
let context = self.contexts[internalId]!
|
||||
switch context.state {
|
||||
case .accepting, .active, .dropping, .requesting, .ringing, .terminated, .requested:
|
||||
break
|
||||
case let .awaitingConfirmation(_, accessHash, gAHash, b, config):
|
||||
if let (key, calculatedKeyId, keyVisualHash) = self.makeSessionEncryptionKey(config: config, gAHash: gAHash, b: b, gA: gAOrB.makeData()) {
|
||||
if keyFingerprint == calculatedKeyId {
|
||||
context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: calculatedKeyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connection, alternative: alternativeConnections))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case .accepting, .active, .dropping, .requesting, .ringing, .terminated, .requested:
|
||||
break
|
||||
case let .awaitingConfirmation(_, accessHash, gAHash, b, config):
|
||||
if let (key, calculatedKeyId, keyVisualHash) = self.makeSessionEncryptionKey(config: config, gAHash: gAHash, b: b, gA: gAOrB.makeData()) {
|
||||
if keyFingerprint == calculatedKeyId {
|
||||
context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: calculatedKeyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connection, alternative: alternativeConnections))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
} else {
|
||||
self.drop(internalId: internalId)
|
||||
}
|
||||
} else {
|
||||
self.drop(internalId: internalId)
|
||||
}
|
||||
} else {
|
||||
self.drop(internalId: internalId)
|
||||
}
|
||||
case let .confirming(id, accessHash, key, keyId, keyVisualHash, _):
|
||||
context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: keyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connection, alternative: alternativeConnections))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .confirming(id, accessHash, key, keyId, keyVisualHash, _):
|
||||
context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: keyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connection, alternative: alternativeConnections))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .phoneCallRequested(id, accessHash, date, adminId, _, gAHash, _):
|
||||
@ -420,15 +441,18 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
case let .phoneCallWaiting(_, id, _, _, _, _, _, receiveDate):
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
let context = self.contexts[internalId]!
|
||||
switch context.state {
|
||||
case let .requested(id, accessHash, a, gA, config, remoteConfirmationTimestamp):
|
||||
if let receiveDate = receiveDate, remoteConfirmationTimestamp == nil {
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: receiveDate)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
}
|
||||
default:
|
||||
break
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .requested(id, accessHash, a, gA, config, remoteConfirmationTimestamp):
|
||||
if let receiveDate = receiveDate, remoteConfirmationTimestamp == nil {
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: receiveDate)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -473,12 +497,12 @@ private final class CallSessionManagerContext {
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
if case .requesting = context.state {
|
||||
switch result {
|
||||
case let .success(id, accessHash, config, gA):
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: nil)
|
||||
case let .success(id, accessHash, config, gA, remoteConfirmationTimestamp):
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: remoteConfirmationTimestamp)
|
||||
strongSelf.contextIdByStableId[id] = internalId
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
case .failed:
|
||||
context.state = .terminated
|
||||
case let .failed(error):
|
||||
context.state = .terminated(.error(error))
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
if context.isEmpty {
|
||||
strongSelf.contexts.removeValue(forKey: internalId)
|
||||
@ -651,8 +675,8 @@ private func acceptCallSession(postbox: Postbox, network: Network, stableId: Cal
|
||||
}
|
||||
|
||||
private enum RequestCallSessionResult {
|
||||
case success(id: CallSessionStableId, accessHash: Int64, config: SecretChatEncryptionConfig, gA: Data)
|
||||
case failed
|
||||
case success(id: CallSessionStableId, accessHash: Int64, config: SecretChatEncryptionConfig, gA: Data, remoteConfirmationTimestamp: Int32?)
|
||||
case failed(CallSessionError)
|
||||
}
|
||||
|
||||
private func requestCallSession(postbox: Postbox, network: Network, peerId: PeerId, a: Data) -> Signal<RequestCallSessionResult, NoError> {
|
||||
@ -669,29 +693,35 @@ private func requestCallSession(postbox: Postbox, network: Network, peerId: Peer
|
||||
let gAHash = MTSha256(ga)!
|
||||
|
||||
return network.request(Api.functions.phone.requestCall(userId: inputUser, randomId: Int32(bitPattern: arc4random()), gAHash: Buffer(data: gAHash), protocol: .phoneCallProtocol(flags: (1 << 0) | (1 << 1), minLayer: 65, maxLayer: 66)))
|
||||
|> map { Optional($0) }
|
||||
|> `catch` { _ -> Signal<Api.phone.PhoneCall?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> RequestCallSessionResult in
|
||||
if let result = result {
|
||||
switch result {
|
||||
case let .phoneCall(phoneCall, _):
|
||||
switch phoneCall {
|
||||
case let .phoneCallRequested(id, accessHash, _, _, _, _, _):
|
||||
return .success(id: id, accessHash: accessHash, config: config, gA: ga)
|
||||
case let .phoneCallWaiting(_, id, accessHash, date, _, _, _, receiveDate):
|
||||
return .success(id: id, accessHash: accessHash, config: config, gA: ga)
|
||||
default:
|
||||
return .failed
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .failed
|
||||
switch result {
|
||||
case let .phoneCall(phoneCall, _):
|
||||
switch phoneCall {
|
||||
case let .phoneCallRequested(id, accessHash, _, _, _, _, _):
|
||||
return .success(id: id, accessHash: accessHash, config: config, gA: ga, remoteConfirmationTimestamp: nil)
|
||||
case let .phoneCallWaiting(_, id, accessHash, _, _, _, _, receiveDate):
|
||||
return .success(id: id, accessHash: accessHash, config: config, gA: ga, remoteConfirmationTimestamp: receiveDate)
|
||||
default:
|
||||
return .failed(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|> `catch` { error -> Signal<RequestCallSessionResult, NoError> in
|
||||
switch error.errorDescription {
|
||||
case "PARTICIPANT_VERSION_OUTDATED":
|
||||
return .single(.failed(.notSupportedByPeer))
|
||||
case "USER_PRIVACY_RESTRICTED":
|
||||
return .single(.failed(.privacyRestricted))
|
||||
default:
|
||||
if error.errorCode == 406 {
|
||||
return .single(.failed(.serverProvided(error.errorDescription)))
|
||||
} else {
|
||||
return .single(.failed(.generic))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .single(.failed)
|
||||
return .single(.failed(.generic))
|
||||
}
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
66
TelegramCore/RecentCalls.swift
Normal file
66
TelegramCore/RecentCalls.swift
Normal file
@ -0,0 +1,66 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import MtProtoKitMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import MtProtoKitDynamic
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public func recentCalls(account: Account, limit: Int) -> Signal<[Message], NoError> {
|
||||
let filter: Api.MessagesFilter = .inputMessagesFilterPhoneCalls(flags: 0)
|
||||
|
||||
let searchResult = account.network.request(Api.functions.messages.search(flags: 0, peer: .inputPeerEmpty, q: "", filter: filter, minDate: 0, maxDate: Int32.max, offset: 0, maxId: Int32.max, limit: Int32(limit)))
|
||||
|> retryRequest
|
||||
|
||||
let processedSearchResult = searchResult
|
||||
|> mapToSignal { result -> Signal<[Message], NoError> in
|
||||
let messages: [Api.Message]
|
||||
let chats: [Api.Chat]
|
||||
let users: [Api.User]
|
||||
switch result {
|
||||
case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messages(apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let.messagesSlice(_, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
}
|
||||
|
||||
return account.postbox.modify { modifier -> [Message] in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(modifier.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers[user.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
|
||||
var renderedMessages: [Message] = []
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
|
||||
renderedMessages.append(renderedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
return renderedMessages
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return processedSearchResult
|
||||
}
|
||||
@ -9,8 +9,7 @@ import Foundation
|
||||
import MtProtoKitDynamic
|
||||
#endif
|
||||
|
||||
|
||||
public func searchMessages(account: Account, peerId: PeerId?, query: String, tagMask:MessageTags? = nil) -> Signal<[Message], NoError> {
|
||||
public func searchMessages(account: Account, peerId: PeerId?, query: String, tagMask: MessageTags? = nil) -> Signal<[Message], NoError> {
|
||||
let searchResult: Signal<Api.messages.Messages, NoError>
|
||||
|
||||
let filter:Api.MessagesFilter
|
||||
@ -105,7 +104,6 @@ public func downloadMessage(account: Account, message: MessageId) -> Signal<Mess
|
||||
return signal
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<Message?, NoError> in
|
||||
NSLog("TGNT download message3 \(result)")
|
||||
let messages: [Api.Message]
|
||||
let chats: [Api.Chat]
|
||||
let users: [Api.User]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user