diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTBindKeyMessageService.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTBindKeyMessageService.h new file mode 100644 index 0000000000..9e5771a203 --- /dev/null +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTBindKeyMessageService.h @@ -0,0 +1,9 @@ +#import +#import +#import + +@interface MTBindKeyMessageService : NSObject + +- (instancetype)initWithPersistentKey:(MTDatacenterAuthKey *)persistentKey ephemeralKey:(MTDatacenterAuthKey *)ephemeralKey completion:(void (^)(bool))completion; + +@end diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h index 1f01237c4c..1b78afc778 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h @@ -49,6 +49,7 @@ @property (nonatomic, strong, readonly) MTApiEnvironment *apiEnvironment; @property (nonatomic, readonly) bool isTestingEnvironment; @property (nonatomic, readonly) bool useTempAuthKeys; +@property (nonatomic, readonly) int32_t tempKeyExpiration; + (int32_t)fixedTimeDifference; + (void)setFixedTimeDifference:(int32_t)fixedTimeDifference; diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthAction.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthAction.h index 8d2beeeda9..df67730fc7 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthAction.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthAction.h @@ -4,23 +4,12 @@ @class MTContext; -@class MTDatacenterAuthAction; - -@protocol MTDatacenterAuthActionDelegate - -- (void)datacenterAuthActionCompleted:(MTDatacenterAuthAction *)action; - -@end @interface MTDatacenterAuthAction : NSObject -@property (nonatomic, readonly) bool tempAuth; -@property (nonatomic, weak) id delegate; -@property (nonatomic, copy) void (^completedWithResult)(bool); +- (instancetype)initWithAuthKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector isCdn:(bool)isCdn completion:(void (^)(MTDatacenterAuthAction *, bool))completion; -- (instancetype)initWithTempAuth:(bool)tempAuth authKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector bindKey:(MTDatacenterAuthKey *)bindKey; - -- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId isCdn:(bool)isCdn; +- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId; - (void)cancel; @end diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h index d16a96bb73..761ed3029e 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h @@ -7,6 +7,7 @@ @class MTIncomingMessage; @class MTMessageTransaction; @class MTApiEnvironment; +@class MTSessionInfo; @protocol MTMessageService @@ -16,7 +17,7 @@ - (void)mtProtoDidAddService:(MTProto *)mtProto; - (void)mtProtoDidRemoveService:(MTProto *)mtProto; - (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray *)publicKeys; -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector; +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo; - (void)mtProtoDidChangeSession:(MTProto *)mtProto; - (void)mtProtoServerDidChangeSession:(MTProto *)mtProto firstValidMessageId:(int64_t)firstValidMessageId otherValidMessageIds:(NSArray *)otherValidMessageIds; - (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector; diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProto.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProto.h index 231d1b4a26..3405a7060b 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProto.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProto.h @@ -71,4 +71,6 @@ - (void)_messageResendRequestFailed:(int64_t)messageId; ++ (NSData *)_manuallyEncryptedMessage:(NSData *)preparedData messageId:(int64_t)messageId authKey:(MTDatacenterAuthKey *)authKey; + @end diff --git a/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m b/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m new file mode 100644 index 0000000000..6a9b69723b --- /dev/null +++ b/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m @@ -0,0 +1,156 @@ +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import "MTInternalMessageParser.h" +#import "MTRpcResultMessage.h" +#import "MTBuffer.h" + +@interface MTBindKeyMessageService () { + MTDatacenterAuthKey *_persistentKey; + MTDatacenterAuthKey *_ephemeralKey; + void (^_completion)(bool); + + int64_t _currentMessageId; + id _currentTransactionId; +} + +@end + +@implementation MTBindKeyMessageService + +- (instancetype)initWithPersistentKey:(MTDatacenterAuthKey *)persistentKey ephemeralKey:(MTDatacenterAuthKey *)ephemeralKey completion:(void (^)(bool))completion { + self = [super init]; + if (self != nil) { + _persistentKey = persistentKey; + _ephemeralKey = ephemeralKey; + _completion = [completion copy]; + } + return self; +} + +- (void)mtProtoDidAddService:(MTProto *)mtProto +{ + [mtProto requestTransportTransaction]; +} + +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo +{ + if (_currentTransactionId != nil) { + return nil; + } + + int64_t bindingMessageId = [sessionInfo generateClientMessageId:NULL]; + int32_t bindingSeqNo = [sessionInfo takeSeqNo:true]; + + int32_t expiresAt = (int32_t)([mtProto.context globalTime] + mtProto.context.tempKeyExpiration); + + int64_t randomId = 0; + arc4random_buf(&randomId, 8); + + int64_t nonce = 0; + arc4random_buf(&nonce, 8); + + MTBuffer *decryptedMessage = [[MTBuffer alloc] init]; + //bind_auth_key_inner#75a3f765 nonce:long temp_auth_key_id:long perm_auth_key_id:long temp_session_id:long expires_at:int = BindAuthKeyInner; + [decryptedMessage appendInt32:(int32_t)0x75a3f765]; + [decryptedMessage appendInt64:nonce]; + [decryptedMessage appendInt64:_ephemeralKey.authKeyId]; + [decryptedMessage appendInt64:_persistentKey.authKeyId]; + [decryptedMessage appendInt64:sessionInfo.sessionId]; + [decryptedMessage appendInt32:expiresAt]; + + NSData *encryptedMessage = [MTProto _manuallyEncryptedMessage:[decryptedMessage data] messageId:bindingMessageId authKey:_persistentKey]; + + MTBuffer *bindRequestData = [[MTBuffer alloc] init]; + + //auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool; + + [bindRequestData appendInt32:(int32_t)0xcdd42a05]; + [bindRequestData appendInt64:_persistentKey.authKeyId]; + [bindRequestData appendInt64:nonce]; + [bindRequestData appendInt32:expiresAt]; + [bindRequestData appendTLBytes:encryptedMessage]; + + MTOutgoingMessage *outgoingMessage = [[MTOutgoingMessage alloc] initWithData:bindRequestData.data metadata:[NSString stringWithFormat:@"auth.bindTempAuthKey"] additionalDebugDescription:nil shortMetadata:@"auth.bindTempAuthKey" messageId:bindingMessageId messageSeqNo:bindingSeqNo]; + + return [[MTMessageTransaction alloc] initWithMessagePayload:@[outgoingMessage] prepared:nil failed:nil completion:^(NSDictionary *messageInternalIdToTransactionId, NSDictionary *messageInternalIdToPreparedMessage, __unused NSDictionary *messageInternalIdToQuickAckId) { + MTPreparedMessage *preparedMessage = messageInternalIdToPreparedMessage[outgoingMessage.internalId]; + if (preparedMessage != nil && messageInternalIdToTransactionId[outgoingMessage.internalId] != nil) { + _currentMessageId = preparedMessage.messageId; + _currentTransactionId = messageInternalIdToTransactionId[outgoingMessage.internalId]; + } + }]; + + return nil; +} + +- (void)mtProto:(MTProto *)__unused mtProto messageDeliveryFailed:(int64_t)messageId { + if (messageId == _currentMessageId) { + _currentMessageId = 0; + _currentTransactionId = nil; + + [mtProto requestTransportTransaction]; + } +} + +- (void)mtProto:(MTProto *)mtProto transactionsMayHaveFailed:(NSArray *)transactionIds { + if (_currentTransactionId != nil && [transactionIds containsObject:_currentTransactionId]) { + _currentTransactionId = nil; + + [mtProto requestTransportTransaction]; + } +} + +- (void)mtProtoAllTransactionsMayHaveFailed:(MTProto *)mtProto { + if (_currentTransactionId != nil) { + _currentTransactionId = nil; + + [mtProto requestTransportTransaction]; + } +} + +- (void)mtProtoDidChangeSession:(MTProto *)mtProto { + _currentMessageId = 0; + _currentTransactionId = nil; + + [mtProto requestTransportTransaction]; +} + +- (void)mtProtoServerDidChangeSession:(MTProto *)mtProto firstValidMessageId:(int64_t)firstValidMessageId messageIdsInFirstValidContainer:(NSArray *)messageIdsInFirstValidContainer { + if (_currentMessageId != 0 && _currentMessageId < firstValidMessageId && ![messageIdsInFirstValidContainer containsObject:@(_currentMessageId)]) { + _currentMessageId = 0; + _currentTransactionId = nil; + + [mtProto requestTransportTransaction]; + } +} + +- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { + if ([message.body isKindOfClass:[MTRpcResultMessage class]]) { + MTRpcResultMessage *rpcResultMessage = message.body; + if (rpcResultMessage.requestMessageId == _currentMessageId) { + bool success = false; + if (rpcResultMessage.data.length >= 4) { + uint32_t signature = 0; + [rpcResultMessage.data getBytes:&signature range:NSMakeRange(0, 4)]; + + //boolTrue#997275b5 = Bool; + if (signature == 0x997275b5U) { + success = true; + } + } + _completion(success); + } + } +} + +@end diff --git a/submodules/MtProtoKit/Sources/MTContext.m b/submodules/MtProtoKit/Sources/MTContext.m index d9507e0923..07958aba96 100644 --- a/submodules/MtProtoKit/Sources/MTContext.m +++ b/submodules/MtProtoKit/Sources/MTContext.m @@ -141,7 +141,7 @@ static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKeyInteger(NSNumber *key return parseAuthInfoMapKey([key longLongValue]); } -@interface MTContext () +@interface MTContext () { int64_t _uniqueId; @@ -165,8 +165,7 @@ static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKeyInteger(NSNumber *key MTSignal *_discoverBackupAddressListSignal; NSMutableDictionary *_discoverDatacenterAddressActions; - NSMutableDictionary *_datacenterAuthActions; - NSMutableDictionary *_datacenterTempAuthActions; + NSMutableDictionary *_datacenterAuthActions; NSMutableDictionary *_datacenterTransferAuthActions; NSMutableDictionary *_datacenterCheckKeyRemovedActionTimestamps; @@ -228,6 +227,11 @@ static int32_t fixedTimeDifferenceValue = 0; _apiEnvironment = apiEnvironment; _isTestingEnvironment = isTestingEnvironment; _useTempAuthKeys = useTempAuthKeys; +#if DEBUG + _tempKeyExpiration = 1 * 60 * 60; +#else + _tempKeyExpiration = 1 * 60 * 60; +#endif _datacenterSeedAddressSetById = [[NSMutableDictionary alloc] init]; @@ -245,7 +249,6 @@ static int32_t fixedTimeDifferenceValue = 0; _discoverDatacenterAddressActions = [[NSMutableDictionary alloc] init]; _datacenterAuthActions = [[NSMutableDictionary alloc] init]; - _datacenterTempAuthActions = [[NSMutableDictionary alloc] init]; _datacenterTransferAuthActions = [[NSMutableDictionary alloc] init]; _datacenterCheckKeyRemovedActionTimestamps = [[NSMutableDictionary alloc] init]; _datacenterCheckKeyRemovedActions = [[NSMutableDictionary alloc] init]; @@ -285,9 +288,6 @@ static int32_t fixedTimeDifferenceValue = 0; NSDictionary *datacenterAuthActions = _datacenterAuthActions; _datacenterAuthActions = nil; - NSDictionary *datacenterTempAuthActions = _datacenterTempAuthActions; - _datacenterTempAuthActions = nil; - NSDictionary *discoverDatacenterAddressActions = _discoverDatacenterAddressActions; _discoverDatacenterAddressActions = nil; @@ -311,17 +311,9 @@ static int32_t fixedTimeDifferenceValue = 0; [action cancel]; } - for (NSNumber *nDatacenterId in datacenterAuthActions) + for (NSNumber *key in datacenterAuthActions) { - MTDatacenterAuthAction *action = datacenterAuthActions[nDatacenterId]; - action.delegate = nil; - [action cancel]; - } - - for (NSNumber *nDatacenterId in datacenterTempAuthActions) - { - MTDatacenterAuthAction *action = datacenterTempAuthActions[nDatacenterId]; - action.delegate = nil; + MTDatacenterAuthAction *action = datacenterAuthActions[key]; [action cancel]; } @@ -387,6 +379,14 @@ static int32_t fixedTimeDifferenceValue = 0; NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"]; if (datacenterAuthInfoById != nil) { _datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById]; +#if DEBUG + NSArray *keys = [_datacenterAuthInfoById allKeys]; + for (NSNumber *key in keys) { + if (parseAuthInfoMapKeyInteger(key).selector != MTDatacenterAuthInfoSelectorPersistent) { + [_datacenterAuthInfoById removeObjectForKey:key]; + } + } +#endif } NSDictionary *datacenterPublicKeysById = [keychain objectForKey:@"datacenterPublicKeysById" group:@"ephemeral"]; @@ -617,6 +617,8 @@ static int32_t fixedTimeDifferenceValue = 0; { NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector); + bool wasNil = _datacenterAuthInfoById[infoKey] == nil; + if (authInfo != nil) { _datacenterAuthInfoById[infoKey] = authInfo; } else { @@ -627,7 +629,7 @@ static int32_t fixedTimeDifferenceValue = 0; } if (MTLogEnabled()) { - MTLog(@"[MTContext#%x: auth info updated for %d to %@]", (int)self, datacenterId, authInfo); + MTLog(@"[MTContext#%x: auth info updated for %d selector %d to %@]", (int)self, datacenterId, selector, authInfo); } [_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"]; @@ -639,6 +641,15 @@ static int32_t fixedTimeDifferenceValue = 0; if ([listener respondsToSelector:@selector(contextDatacenterAuthInfoUpdated:datacenterId:authInfo:selector:)]) [listener contextDatacenterAuthInfoUpdated:self datacenterId:datacenterId authInfo:authInfo selector:selector]; } + + if (wasNil && authInfo != nil && selector == MTDatacenterAuthInfoSelectorPersistent) { + for (NSNumber *key in _datacenterAuthActions) { + MTDatacenterAuthInfoMapKeyStruct parsedKey = parseAuthInfoMapKeyInteger(key); + if (parsedKey.datacenterId == datacenterId && parsedKey.selector != MTDatacenterAuthInfoSelectorPersistent) { + [_datacenterAuthActions[key] execute:self datacenterId:datacenterId]; + } + } + } } }]; } @@ -1289,33 +1300,40 @@ static int32_t fixedTimeDifferenceValue = 0; { [[MTContext contextQueue] dispatchOnQueue:^ { - if (_datacenterAuthActions[@(datacenterId)] == nil) + NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector); + + if (_datacenterAuthActions[infoKey] == nil) { - MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithTempAuth:false authKeyInfoSelector:selector bindKey:nil]; - authAction.delegate = self; - _datacenterAuthActions[@(datacenterId)] = authAction; - [authAction execute:self datacenterId:datacenterId isCdn:isCdn]; - } - }]; -} - -- (void)datacenterAuthActionCompleted:(MTDatacenterAuthAction *)action -{ - [[MTContext contextQueue] dispatchOnQueue:^ - { - if (action.tempAuth) { - for (NSNumber *nDatacenterId in _datacenterTempAuthActions) { - if (_datacenterTempAuthActions[nDatacenterId] == action) { - [_datacenterTempAuthActions removeObjectForKey:nDatacenterId]; + __weak MTContext *weakSelf = self; + MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithAuthKeyInfoSelector:selector isCdn:isCdn completion:^(MTDatacenterAuthAction *action, __unused bool success) { + [[MTContext contextQueue] dispatchOnQueue:^{ + __strong MTContext *strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + for (NSNumber *key in _datacenterAuthActions) { + if (_datacenterAuthActions[key] == action) { + [_datacenterAuthActions removeObjectForKey:key]; + break; + } + } + }]; + }]; + _datacenterAuthActions[infoKey] = authAction; + + switch (selector) { + case MTDatacenterAuthInfoSelectorEphemeralMain: + case MTDatacenterAuthInfoSelectorEphemeralMedia: { + if ([self authInfoForDatacenterWithId:datacenterId selector:MTDatacenterAuthInfoSelectorPersistent] == nil) { + [self authInfoForDatacenterWithIdRequired:datacenterId isCdn:false selector:MTDatacenterAuthInfoSelectorPersistent]; + } else { + [authAction execute:self datacenterId:datacenterId]; + } break; } - } - } else { - for (NSNumber *nDatacenterId in _datacenterAuthActions) { - if (_datacenterAuthActions[nDatacenterId] == action) { - [_datacenterAuthActions removeObjectForKey:nDatacenterId]; - + default: { + [authAction execute:self datacenterId:datacenterId]; break; } } @@ -1395,7 +1413,7 @@ static int32_t fixedTimeDifferenceValue = 0; _datacenterCheckKeyRemovedActionTimestamps[@(datacenterId)] = currentTimestamp; [_datacenterCheckKeyRemovedActions[@(datacenterId)] dispose]; __weak MTContext *weakSelf = self; - _datacenterCheckKeyRemovedActions[@(datacenterId)] = [[MTDiscoverConnectionSignals checkIfAuthKeyRemovedWithContext:self datacenterId:datacenterId authKey:[[MTDatacenterAuthKey alloc] initWithAuthKey:authInfo.authKey authKeyId:authInfo.authKeyId notBound:false]] startWithNext:^(NSNumber *isRemoved) { + _datacenterCheckKeyRemovedActions[@(datacenterId)] = [[MTDiscoverConnectionSignals checkIfAuthKeyRemovedWithContext:self datacenterId:datacenterId authKey:[[MTDatacenterAuthKey alloc] initWithAuthKey:authInfo.authKey authKeyId:authInfo.authKeyId notBound:false]] startWithNext:^(NSNumber* isRemoved) { [[MTContext contextQueue] dispatchOnQueue:^{ __strong MTContext *strongSelf = weakSelf; if (strongSelf == nil) { diff --git a/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m index 9ca4736340..736b69f546 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m @@ -12,13 +12,15 @@ #import #import #import +#import #import "MTBuffer.h" @interface MTDatacenterAuthAction () { + void (^_completion)(MTDatacenterAuthAction *, bool); + bool _isCdn; MTDatacenterAuthInfoSelector _authKeyInfoSelector; - MTDatacenterAuthKey *_bindKey; NSInteger _datacenterId; __weak MTContext *_context; @@ -26,42 +28,36 @@ bool _awaitingAddresSetUpdate; MTProto *_authMtProto; MTProto *_bindMtProto; - - MTMetaDisposable *_verifyDisposable; } @end @implementation MTDatacenterAuthAction -- (instancetype)initWithTempAuth:(bool)tempAuth authKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector bindKey:(MTDatacenterAuthKey *)bindKey { +- (instancetype)initWithAuthKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector isCdn:(bool)isCdn completion:(void (^)(MTDatacenterAuthAction *, bool))completion { self = [super init]; if (self != nil) { - _tempAuth = tempAuth; _authKeyInfoSelector = authKeyInfoSelector; - _bindKey = bindKey; - _verifyDisposable = [[MTMetaDisposable alloc] init]; + _isCdn = isCdn; + _completion = [completion copy]; } return self; } -- (void)dealloc -{ +- (void)dealloc { [self cleanup]; } -- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId isCdn:(bool)isCdn -{ +- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId { _datacenterId = datacenterId; _context = context; - _isCdn = isCdn; if (_datacenterId != 0 && context != nil) { bool alreadyCompleted = false; MTDatacenterAuthInfo *currentAuthInfo = [context authInfoForDatacenterWithId:_datacenterId selector:_authKeyInfoSelector]; - if (currentAuthInfo != nil && _bindKey == nil) { + if (currentAuthInfo != nil) { alreadyCompleted = true; } @@ -69,23 +65,24 @@ [self complete]; } else { _authMtProto = [[MTProto alloc] initWithContext:context datacenterId:_datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0]; - _authMtProto.cdn = isCdn; + _authMtProto.cdn = _isCdn; _authMtProto.useUnauthorizedMode = true; - if (_tempAuth) { - switch (_authKeyInfoSelector) { - case MTDatacenterAuthInfoSelectorEphemeralMain: - _authMtProto.media = false; - break; - case MTDatacenterAuthInfoSelectorEphemeralMedia: - _authMtProto.media = true; - _authMtProto.enforceMedia = true; - break; - default: - break; - } + bool tempAuth = false; + switch (_authKeyInfoSelector) { + case MTDatacenterAuthInfoSelectorEphemeralMain: + tempAuth = true; + _authMtProto.media = false; + break; + case MTDatacenterAuthInfoSelectorEphemeralMedia: + tempAuth = true; + _authMtProto.media = true; + _authMtProto.enforceMedia = true; + break; + default: + break; } - MTDatacenterAuthMessageService *authService = [[MTDatacenterAuthMessageService alloc] initWithContext:context tempAuth:_tempAuth]; + MTDatacenterAuthMessageService *authService = [[MTDatacenterAuthMessageService alloc] initWithContext:context tempAuth:tempAuth]; authService.delegate = self; [_authMtProto addMessageService:authService]; } @@ -99,44 +96,71 @@ } - (void)completeWithAuthKey:(MTDatacenterAuthKey *)authKey timestamp:(int64_t)timestamp { - if (_tempAuth) { - MTContext *mainContext = _context; - if (mainContext != nil) { - if (_bindKey != nil) { - _bindMtProto = [[MTProto alloc] initWithContext:mainContext datacenterId:_datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0]; - _bindMtProto.cdn = false; - _bindMtProto.useUnauthorizedMode = false; - _bindMtProto.useTempAuthKeys = true; - __weak MTDatacenterAuthAction *weakSelf = self; - _bindMtProto.tempAuthKeyBindingResultUpdated = ^(bool success) { - __strong MTDatacenterAuthAction *strongSelf = weakSelf; - if (strongSelf == nil) { - return; + if (MTLogEnabled()) { + MTLog(@"[MTDatacenterAuthAction#%p@%p: completeWithAuthKey %lld selector %d]", self, _context, authKey.authKeyId, _authKeyInfoSelector); + } + + switch (_authKeyInfoSelector) { + case MTDatacenterAuthInfoSelectorPersistent: { + MTDatacenterAuthInfo *authInfo = [[MTDatacenterAuthInfo alloc] initWithAuthKey:authKey.authKey authKeyId:authKey.authKeyId saltSet:@[[[MTDatacenterSaltInfo alloc] initWithSalt:0 firstValidMessageId:timestamp lastValidMessageId:timestamp + (29.0 * 60.0) * 4294967296]] authKeyAttributes:nil]; + + MTContext *context = _context; + [context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo selector:_authKeyInfoSelector]; + [self complete]; + } + break; + + case MTDatacenterAuthInfoSelectorEphemeralMain: + case MTDatacenterAuthInfoSelectorEphemeralMedia: { + MTContext *mainContext = _context; + if (mainContext != nil) { + MTDatacenterAuthInfo *persistentAuthInfo = [mainContext authInfoForDatacenterWithId:_datacenterId selector:MTDatacenterAuthInfoSelectorPersistent]; + if (persistentAuthInfo != nil) { + _bindMtProto = [[MTProto alloc] initWithContext:mainContext datacenterId:_datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0]; + _bindMtProto.cdn = false; + _bindMtProto.useUnauthorizedMode = false; + _bindMtProto.useTempAuthKeys = true; + _bindMtProto.useExplicitAuthKey = authKey; + + switch (_authKeyInfoSelector) { + case MTDatacenterAuthInfoSelectorEphemeralMain: + _bindMtProto.media = false; + break; + case MTDatacenterAuthInfoSelectorEphemeralMedia: + _bindMtProto.media = true; + _bindMtProto.enforceMedia = true; + break; + default: + break; } - [strongSelf->_bindMtProto stop]; - if (strongSelf->_completedWithResult) { - strongSelf->_completedWithResult(success); - } - }; - _bindMtProto.useExplicitAuthKey = authKey; - [_bindMtProto resume]; - } else { - MTContext *context = _context; - [context performBatchUpdates:^{ - MTDatacenterAuthInfo *authInfo = [context authInfoForDatacenterWithId:_datacenterId selector:_authKeyInfoSelector]; - if (authInfo != nil) { - [context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo selector:_authKeyInfoSelector]; - } - }]; - [self complete]; + + __weak MTDatacenterAuthAction *weakSelf = self; + [_bindMtProto addMessageService:[[MTBindKeyMessageService alloc] initWithPersistentKey:[[MTDatacenterAuthKey alloc] initWithAuthKey:persistentAuthInfo.authKey authKeyId:persistentAuthInfo.authKeyId notBound:false] ephemeralKey:authKey completion:^(bool success) { + __strong MTDatacenterAuthAction *strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + [strongSelf->_bindMtProto stop]; + + if (success) { + MTDatacenterAuthInfo *authInfo = [[MTDatacenterAuthInfo alloc] initWithAuthKey:authKey.authKey authKeyId:authKey.authKeyId saltSet:@[[[MTDatacenterSaltInfo alloc] initWithSalt:0 firstValidMessageId:timestamp lastValidMessageId:timestamp + (29.0 * 60.0) * 4294967296]] authKeyAttributes:nil]; + + [strongSelf->_context updateAuthInfoForDatacenterWithId:strongSelf->_datacenterId authInfo:authInfo selector:strongSelf->_authKeyInfoSelector]; + + [strongSelf complete]; + } else { + [strongSelf fail]; + } + }]]; + [_bindMtProto resume]; + } } } - } else { - MTDatacenterAuthInfo *authInfo = [[MTDatacenterAuthInfo alloc] initWithAuthKey:authKey.authKey authKeyId:authKey.authKeyId saltSet:@[[[MTDatacenterSaltInfo alloc] initWithSalt:0 firstValidMessageId:timestamp lastValidMessageId:timestamp + (29.0 * 60.0) * 4294967296]] authKeyAttributes:nil]; - - MTContext *context = _context; - [context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo selector:_authKeyInfoSelector]; - [self complete]; + break; + + default: + assert(false); + break; } } @@ -147,7 +171,10 @@ [authMtProto stop]; - [_verifyDisposable dispose]; + MTProto *bindMtProto = _bindMtProto; + _bindMtProto = nil; + + [bindMtProto stop]; } - (void)cancel @@ -156,18 +183,17 @@ [self fail]; } -- (void)complete -{ - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(datacenterAuthActionCompleted:)]) - [delegate datacenterAuthActionCompleted:self]; +- (void)complete { + if (_completion) { + _completion(self, true); + } } - (void)fail { - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(datacenterAuthActionCompleted:)]) - [delegate datacenterAuthActionCompleted:self]; + if (_completion) { + _completion(self, false); + } } @end diff --git a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m index 01f4e320d5..e9d94c678b 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m @@ -222,7 +222,7 @@ typedef enum { } } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { if (_currentStageTransactionId == nil) { @@ -389,7 +389,7 @@ typedef enum { [innerDataBuffer appendBytes:_nonce.bytes length:_nonce.length]; [innerDataBuffer appendBytes:_serverNonce.bytes length:_serverNonce.length]; [innerDataBuffer appendBytes:_newNonce.bytes length:_newNonce.length]; - [innerDataBuffer appendInt32:60 * 60 * 32]; + [innerDataBuffer appendInt32:mtProto.context.tempKeyExpiration]; NSData *innerDataBytes = innerDataBuffer.data; diff --git a/submodules/MtProtoKit/Sources/MTDiscoverConnectionSignals.m b/submodules/MtProtoKit/Sources/MTDiscoverConnectionSignals.m index d4446e9204..429ff755af 100644 --- a/submodules/MtProtoKit/Sources/MTDiscoverConnectionSignals.m +++ b/submodules/MtProtoKit/Sources/MTDiscoverConnectionSignals.m @@ -249,12 +249,11 @@ MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init]; [[MTContext contextQueue] dispatchOnQueue:^{ - MTDatacenterAuthAction *action = [[MTDatacenterAuthAction alloc] initWithTempAuth:true authKeyInfoSelector:MTDatacenterAuthInfoSelectorEphemeralMain bindKey:authKey]; - action.completedWithResult = ^(bool success) { + MTDatacenterAuthAction *action = [[MTDatacenterAuthAction alloc] initWithAuthKeyInfoSelector:MTDatacenterAuthInfoSelectorEphemeralMain isCdn:false completion:^(__unused MTDatacenterAuthAction *action, bool success) { [subscriber putNext:@(!success)]; [subscriber putCompletion]; - }; - [action execute:context datacenterId:datacenterId isCdn:false]; + }]; + [action execute:context datacenterId:datacenterId]; [disposable setDisposable:[[MTBlockDisposable alloc] initWithBlock:^{ [action cancel]; diff --git a/submodules/MtProtoKit/Sources/MTProto.m b/submodules/MtProtoKit/Sources/MTProto.m index 7aa4bf30dd..b872c91085 100644 --- a/submodules/MtProtoKit/Sources/MTProto.m +++ b/submodules/MtProtoKit/Sources/MTProto.m @@ -828,42 +828,60 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; } - (MTDatacenterAuthKey *)getAuthKeyForCurrentScheme:(MTTransportScheme *)scheme createIfNeeded:(bool)createIfNeeded authInfoSelector:(MTDatacenterAuthInfoSelector *)authInfoSelector { - MTDatacenterAuthInfoSelector selector = MTDatacenterAuthInfoSelectorPersistent; - - if (_cdn) { - selector = MTDatacenterAuthInfoSelectorPersistent; - } else { - if (_useTempAuthKeys) { - if (scheme.address.preferForMedia) { - selector = MTDatacenterAuthInfoSelectorEphemeralMedia; - } else { - selector = MTDatacenterAuthInfoSelectorEphemeralMain; - } - } else { - selector = MTDatacenterAuthInfoSelectorPersistent; + if (_useExplicitAuthKey) { + MTDatacenterAuthInfoSelector selector = MTDatacenterAuthInfoSelectorEphemeralMain; + if (authInfoSelector != nil) { + *authInfoSelector = selector; } - } - - if (authInfoSelector != nil) { - *authInfoSelector = selector; - } - - if (_validAuthInfo != nil && _validAuthInfo.selector == selector) { + + if (_validAuthInfo != nil && _validAuthInfo.selector == selector) { + return [[MTDatacenterAuthKey alloc] initWithAuthKey:_validAuthInfo.authInfo.authKey authKeyId:_validAuthInfo.authInfo.authKeyId notBound:false]; + } + + MTDatacenterAuthInfo *authInfo = [[MTDatacenterAuthInfo alloc] initWithAuthKey:_useExplicitAuthKey.authKey authKeyId:_useExplicitAuthKey.authKeyId saltSet:@[[[MTDatacenterSaltInfo alloc] initWithSalt:0 firstValidMessageId:0 lastValidMessageId:0]] authKeyAttributes:nil]; + + _validAuthInfo = [[MTProtoValidAuthInfo alloc] initWithAuthInfo:authInfo selector:selector]; return [[MTDatacenterAuthKey alloc] initWithAuthKey:_validAuthInfo.authInfo.authKey authKeyId:_validAuthInfo.authInfo.authKeyId notBound:false]; } else { - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId selector:selector]; - if (authInfo != nil) { - _validAuthInfo = [[MTProtoValidAuthInfo alloc] initWithAuthInfo:authInfo selector:selector]; + MTDatacenterAuthInfoSelector selector = MTDatacenterAuthInfoSelectorPersistent; + + if (_cdn) { + selector = MTDatacenterAuthInfoSelectorPersistent; + } else { + if (_useTempAuthKeys) { + if (scheme.address.preferForMedia) { + selector = MTDatacenterAuthInfoSelectorEphemeralMedia; + } else { + selector = MTDatacenterAuthInfoSelectorEphemeralMain; + } + } else { + selector = MTDatacenterAuthInfoSelectorPersistent; + } + } + + if (authInfoSelector != nil) { + *authInfoSelector = selector; + } + + if (_validAuthInfo != nil && _validAuthInfo.selector == selector) { return [[MTDatacenterAuthKey alloc] initWithAuthKey:_validAuthInfo.authInfo.authKey authKeyId:_validAuthInfo.authInfo.authKeyId notBound:false]; } else { - [_context performBatchUpdates:^{ - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil selector:selector]; - [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:_cdn selector:selector]; - }]; - _mtState |= MTProtoStateAwaitingDatacenterAuthorization; - _awaitingAuthInfoForSelector = @(selector); - - return nil; + MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId selector:selector]; + if (authInfo != nil) { + _validAuthInfo = [[MTProtoValidAuthInfo alloc] initWithAuthInfo:authInfo selector:selector]; + return [[MTDatacenterAuthKey alloc] initWithAuthKey:_validAuthInfo.authInfo.authKey authKeyId:_validAuthInfo.authInfo.authKeyId notBound:false]; + } else { + if (createIfNeeded) { + [_context performBatchUpdates:^{ + [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil selector:selector]; + [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:_cdn selector:selector]; + }]; + _mtState |= MTProtoStateAwaitingDatacenterAuthorization; + _awaitingAuthInfoForSelector = @(selector); + } + + return nil; + } } } } @@ -924,9 +942,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; NSMutableArray *messageServiceTransactions = [[NSMutableArray alloc] init]; for (id messageService in _messageServices) { - if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:authInfoSelector:)]) + if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:authInfoSelector:sessionInfo:)]) { - MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self authInfoSelector:authInfoSelector]; + MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self authInfoSelector:authInfoSelector sessionInfo:transactionSessionInfo]; if (messageTransaction != nil) { for (MTOutgoingMessage *message in messageTransaction.messagePayload) @@ -1496,7 +1514,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return messageData; } -- (NSData *)paddedDataV1:(NSData *)data { ++ (NSData *)paddedDataV1:(NSData *)data { NSMutableData *padded = [[NSMutableData alloc] initWithData:data]; uint8_t randomBytes[128]; arc4random_buf(randomBytes, 128); @@ -1543,7 +1561,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return padded; } -- (NSData *)_manuallyEncryptedMessage:(NSData *)preparedData messageId:(int64_t)messageId authKey:(MTDatacenterAuthKey *)authKey { ++ (NSData *)_manuallyEncryptedMessage:(NSData *)preparedData messageId:(int64_t)messageId authKey:(MTDatacenterAuthKey *)authKey { MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; int64_t random1 = 0; @@ -1559,7 +1577,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; [decryptedOs writeInt32:(int32_t)preparedData.length]; [decryptedOs writeData:preparedData]; - NSData *decryptedData = [self paddedDataV1:[decryptedOs currentBytes]]; + NSData *decryptedData = [MTProto paddedDataV1:[decryptedOs currentBytes]]; NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + preparedData.length); NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; @@ -2013,6 +2031,10 @@ static NSString *dumpHexString(NSData *data, int maxLength) { MTDatacenterAuthInfoSelector authInfoSelector; [self getAuthKeyForCurrentScheme:scheme createIfNeeded:false authInfoSelector:&authInfoSelector]; + if (MTLogEnabled()) { + MTLog(@"[MTProto#%p@%p missing key %lld selector]", self, _context, _validAuthInfo.authInfo.authKeyId, authInfoSelector); + } + if (_useExplicitAuthKey != nil) { } else if (_cdn) { _validAuthInfo = nil; @@ -2047,7 +2069,23 @@ static NSString *dumpHexString(NSData *data, int maxLength) { _mtState |= MTProtoStateAwaitingDatacenterAuthorization; _awaitingAuthInfoForSelector = @(authInfoSelector); } else { - [_context checkIfLoggedOut:_datacenterId]; + switch (authInfoSelector) { + case MTDatacenterAuthInfoSelectorEphemeralMain: + case MTDatacenterAuthInfoSelectorEphemeralMedia: { + _validAuthInfo = nil; + + [_context performBatchUpdates:^{ + [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil selector:authInfoSelector]; + [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:false selector:authInfoSelector]; + }]; + _mtState |= MTProtoStateAwaitingDatacenterAuthorization; + _awaitingAuthInfoForSelector = @(authInfoSelector); + break; + } + default: + [_context checkIfLoggedOut:_datacenterId]; + break; + } } } } @@ -2497,6 +2535,8 @@ static NSString *dumpHexString(NSData *data, int maxLength) { } else if (_awaitingAuthInfoForSelector != nil) { if ([_awaitingAuthInfoForSelector intValue] != selector) { return; + } else if (authInfo != nil) { + _awaitingAuthInfoForSelector = nil; } } else { return; @@ -2566,14 +2606,21 @@ static NSString *dumpHexString(NSData *data, int maxLength) { if (saltList != nil) { - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId selector:authInfoSelector]; - if (authInfo != nil) - { - MTDatacenterAuthInfo *updatedAuthInfo = [authInfo mergeSaltSet:saltList forTimestamp:[_context globalTime]]; - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:updatedAuthInfo selector:authInfoSelector]; + if (_useExplicitAuthKey) { if (_validAuthInfo != nil && _validAuthInfo.selector == authInfoSelector) { + MTDatacenterAuthInfo *updatedAuthInfo = [_validAuthInfo.authInfo mergeSaltSet:saltList forTimestamp:[_context globalTime]]; _validAuthInfo = [[MTProtoValidAuthInfo alloc] initWithAuthInfo:updatedAuthInfo selector:authInfoSelector]; } + } else { + MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId selector:authInfoSelector]; + if (authInfo != nil) + { + MTDatacenterAuthInfo *updatedAuthInfo = [authInfo mergeSaltSet:saltList forTimestamp:[_context globalTime]]; + [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:updatedAuthInfo selector:authInfoSelector]; + if (_validAuthInfo != nil && _validAuthInfo.selector == authInfoSelector) { + _validAuthInfo = [[MTProtoValidAuthInfo alloc] initWithAuthInfo:updatedAuthInfo selector:authInfoSelector]; + } + } } } diff --git a/submodules/MtProtoKit/Sources/MTRequestMessageService.m b/submodules/MtProtoKit/Sources/MTRequestMessageService.m index b37bd8d6d0..fb85f6ff47 100644 --- a/submodules/MtProtoKit/Sources/MTRequestMessageService.m +++ b/submodules/MtProtoKit/Sources/MTRequestMessageService.m @@ -391,7 +391,7 @@ return currentData; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { NSMutableArray *messages = nil; NSMutableDictionary *requestInternalIdToMessageInternalId = nil; diff --git a/submodules/MtProtoKit/Sources/MTResendMessageService.m b/submodules/MtProtoKit/Sources/MTResendMessageService.m index 16f7b7f4f6..585ec29599 100644 --- a/submodules/MtProtoKit/Sources/MTResendMessageService.m +++ b/submodules/MtProtoKit/Sources/MTResendMessageService.m @@ -41,7 +41,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { if (_currentRequestMessageId == 0 || _currentRequestTransactionId == nil) { diff --git a/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m b/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m index 9504df24f0..8672ed541d 100644 --- a/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m +++ b/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m @@ -45,7 +45,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { if (_currentTransactionId == nil) { diff --git a/submodules/TelegramCore/Sources/Account.swift b/submodules/TelegramCore/Sources/Account.swift index 195f72ae0e..cad791bbc4 100644 --- a/submodules/TelegramCore/Sources/Account.swift +++ b/submodules/TelegramCore/Sources/Account.swift @@ -104,7 +104,7 @@ public class UnauthorizedAccount { } for id in datacenterIds { if network.context.authInfoForDatacenter(withId: id, selector: .persistent) == nil { - network.context.authInfoForDatacenter(withIdRequired: id, isCdn: false, selector: .persistent) + network.context.authInfoForDatacenter(withIdRequired: id, isCdn: false, selector: .ephemeralMain) } } network.context.beginExplicitBackupAddressDiscovery() @@ -128,7 +128,7 @@ public class UnauthorizedAccount { } } |> mapToSignal { (localizationSettings, proxySettings, networkSettings) -> Signal in - return initializedNetwork(arguments: self.networkArguments, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) + return initializedNetwork(accountId: self.id, arguments: self.networkArguments, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) |> map { network in let updated = UnauthorizedAccount(networkArguments: self.networkArguments, id: self.id, rootPath: self.rootPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network) updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get()) @@ -257,7 +257,7 @@ public func accountWithId(accountManager: AccountManager, networkArguments: Netw if let accountState = accountState { switch accountState { case let unauthorizedState as UnauthorizedAccountState: - return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) + return initializedNetwork(accountId: id, arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) |> map { network -> AccountResult in return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) } @@ -266,7 +266,7 @@ public func accountWithId(accountManager: AccountManager, networkArguments: Netw return (transaction.getPeer(authorizedState.peerId) as? TelegramUser)?.phone } |> mapToSignal { phoneNumber in - return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: phoneNumber) + return initializedNetwork(accountId: id, arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: phoneNumber) |> map { network -> AccountResult in return .authorized(Account(accountManager: accountManager, id: id, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, postbox: postbox, network: network, networkArguments: networkArguments, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods, supplementary: supplementary)) } @@ -276,7 +276,7 @@ public func accountWithId(accountManager: AccountManager, networkArguments: Netw } } - return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) + return initializedNetwork(accountId: id, arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) |> map { network -> AccountResult in return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: beginWithTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) } diff --git a/submodules/TelegramCore/Sources/Network.swift b/submodules/TelegramCore/Sources/Network.swift index 7d0313466e..4e7a4a2c60 100644 --- a/submodules/TelegramCore/Sources/Network.swift +++ b/submodules/TelegramCore/Sources/Network.swift @@ -424,7 +424,17 @@ public struct NetworkInitializationArguments { private let cloudDataContext = Atomic(value: nil) #endif -func initializedNetwork(arguments: NetworkInitializationArguments, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool, languageCode: String?, proxySettings: ProxySettings?, networkSettings: NetworkSettings?, phoneNumber: String?) -> Signal { +private final class SharedContextStore { + struct Key: Hashable { + var accountId: AccountRecordId + } + + var contexts: [Key: MTContext] = [:] +} + +private let sharedContexts = Atomic(value: SharedContextStore()) + +func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializationArguments, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool, languageCode: String?, proxySettings: ProxySettings?, networkSettings: NetworkSettings?, phoneNumber: String?) -> Signal { return Signal { subscriber in let queue = Queue() queue.async { @@ -464,7 +474,22 @@ func initializedNetwork(arguments: NetworkInitializationArguments, supplementary } } - let context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: false)! + var contextValue: MTContext? + sharedContexts.with { store in + let key = SharedContextStore.Key(accountId: accountId) + + let context: MTContext + if let current = store.contexts[key] { + context = current + context.updateApiEnvironment({ _ in return apiEnvironment}) + } else { + context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: true)! + store.contexts[key] = context + } + contextValue = context + } + + let context = contextValue! let seedAddressList: [Int: [String]] diff --git a/submodules/TelegramCore/Sources/UnauthorizedAccountStateManager.swift b/submodules/TelegramCore/Sources/UnauthorizedAccountStateManager.swift index 19a87d91f3..b9993cf1f9 100644 --- a/submodules/TelegramCore/Sources/UnauthorizedAccountStateManager.swift +++ b/submodules/TelegramCore/Sources/UnauthorizedAccountStateManager.swift @@ -27,7 +27,7 @@ private final class UnauthorizedUpdateMessageService: NSObject, MTMessageService self.pipe.putNext(updates) } - func mtProto(_ mtProto: MTProto!, receivedMessage message: MTIncomingMessage!) { + func mtProto(_ mtProto: MTProto!, receivedMessage message: MTIncomingMessage!, authInfoSelector: MTDatacenterAuthInfoSelector) { if let updates = (message.body as? BoxedMessage)?.body as? Api.Updates { self.addUpdates(updates) } diff --git a/submodules/TelegramCore/Sources/UpdateMessageService.swift b/submodules/TelegramCore/Sources/UpdateMessageService.swift index 80369b330c..bca8a5a76e 100644 --- a/submodules/TelegramCore/Sources/UpdateMessageService.swift +++ b/submodules/TelegramCore/Sources/UpdateMessageService.swift @@ -34,7 +34,7 @@ class UpdateMessageService: NSObject, MTMessageService { self.pipe.putNext(groups) } - func mtProto(_ mtProto: MTProto!, receivedMessage message: MTIncomingMessage!) { + func mtProto(_ mtProto: MTProto!, receivedMessage message: MTIncomingMessage!, authInfoSelector: MTDatacenterAuthInfoSelector) { if let updates = (message.body as? BoxedMessage)?.body as? Api.Updates { self.addUpdates(updates) }