diff --git a/submodules/MtProtoKit/BUCK b/submodules/MtProtoKit/BUCK index 215e91f784..e7c782ef4e 100644 --- a/submodules/MtProtoKit/BUCK +++ b/submodules/MtProtoKit/BUCK @@ -3,10 +3,10 @@ load("//Config:buck_rule_macros.bzl", "static_library", "framework", "glob_map", framework( name = "MtProtoKit", srcs = glob([ - "Sources/*.m", + "Sources/**/*.m", ]), headers = glob([ - "Sources/*.h", + "Sources/**/*.h", ]), exported_headers = glob([ "PublicHeaders/**/*.h", diff --git a/submodules/MtProtoKit/BUILD b/submodules/MtProtoKit/BUILD index cdc4b42171..c316d024a3 100644 --- a/submodules/MtProtoKit/BUILD +++ b/submodules/MtProtoKit/BUILD @@ -4,8 +4,8 @@ objc_library( enable_modules = True, module_name = "MtProtoKit", srcs = glob([ - "Sources/*.m", - "Sources/*.h", + "Sources/**/*.m", + "Sources/**/*.h", ]), hdrs = glob([ "PublicHeaders/**/*.h", 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 c4cff82ef3..1b78afc778 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h @@ -20,7 +20,7 @@ @optional - (void)contextDatacenterAddressSetUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet; -- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo; +- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo selector:(MTDatacenterAuthInfoSelector)selector; - (void)contextDatacenterAuthTokenUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authToken:(id)authToken; - (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId shouldReset:(bool)shouldReset; - (void)contextIsPasswordRequiredUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId; @@ -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; @@ -73,7 +74,7 @@ - (void)updateAddressSetForDatacenterWithId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet forceUpdateSchemes:(bool)forceUpdateSchemes; - (void)addAddressForDatacenterWithId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address; - (void)updateTransportSchemeForDatacenterWithId:(NSInteger)datacenterId transportScheme:(MTTransportScheme *)transportScheme media:(bool)media isProxy:(bool)isProxy; -- (void)updateAuthInfoForDatacenterWithId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo; +- (void)updateAuthInfoForDatacenterWithId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo selector:(MTDatacenterAuthInfoSelector)selector; - (bool)isPasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId; - (bool)updatePasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId required:(bool)required; @@ -95,7 +96,7 @@ - (void)transportSchemeForDatacenterWithIdRequired:(NSInteger)datacenterId media:(bool)media; - (void)invalidateTransportSchemeForDatacenterId:(NSInteger)datacenterId transportScheme:(MTTransportScheme *)transportScheme isProbablyHttp:(bool)isProbablyHttp media:(bool)media; - (void)revalidateTransportSchemeForDatacenterId:(NSInteger)datacenterId transportScheme:(MTTransportScheme *)transportScheme media:(bool)media; -- (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId; +- (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId selector:(MTDatacenterAuthInfoSelector)selector; - (NSArray *)publicKeysForDatacenterWithId:(NSInteger)datacenterId; - (void)updatePublicKeysForDatacenterWithId:(NSInteger)datacenterId publicKeys:(NSArray *)publicKeys; @@ -107,8 +108,7 @@ - (void)updateAuthTokenForDatacenterWithId:(NSInteger)datacenterId authToken:(id)authToken; - (void)addressSetForDatacenterWithIdRequired:(NSInteger)datacenterId; -- (void)authInfoForDatacenterWithIdRequired:(NSInteger)datacenterId isCdn:(bool)isCdn; -- (void)tempAuthKeyForDatacenterWithIdRequired:(NSInteger)datacenterId keyType:(MTDatacenterAuthTempKeyType)keyType; +- (void)authInfoForDatacenterWithIdRequired:(NSInteger)datacenterId isCdn:(bool)isCdn selector:(MTDatacenterAuthInfoSelector)selector; - (void)authTokenForDatacenterWithIdRequired:(NSInteger)datacenterId authToken:(id)authToken masterDatacenterId:(NSInteger)masterDatacenterId; - (void)reportProblemsWithDatacenterAddressForId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address; diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthAction.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthAction.h index c9643cdaf3..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 tempAuthKeyType:(MTDatacenterAuthTempKeyType)tempAuthKeyType 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/MTDatacenterAuthInfo.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthInfo.h index ae73123a64..26c7c7ea3f 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthInfo.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTDatacenterAuthInfo.h @@ -1,10 +1,5 @@ #import -typedef NS_ENUM(NSUInteger, MTDatacenterAuthTempKeyType) { - MTDatacenterAuthTempKeyTypeMain, - MTDatacenterAuthTempKeyTypeMedia -}; - @interface MTDatacenterAuthKey: NSObject @property (nonatomic, strong, readonly) NSData *authKey; @@ -15,24 +10,24 @@ typedef NS_ENUM(NSUInteger, MTDatacenterAuthTempKeyType) { @end +typedef NS_ENUM(int64_t, MTDatacenterAuthInfoSelector) { + MTDatacenterAuthInfoSelectorPersistent = 0, + MTDatacenterAuthInfoSelectorEphemeralMain, + MTDatacenterAuthInfoSelectorEphemeralMedia +}; + @interface MTDatacenterAuthInfo : NSObject @property (nonatomic, strong, readonly) NSData *authKey; @property (nonatomic, readonly) int64_t authKeyId; @property (nonatomic, strong, readonly) NSArray *saltSet; @property (nonatomic, strong, readonly) NSDictionary *authKeyAttributes; -@property (nonatomic, strong, readonly) MTDatacenterAuthKey *mainTempAuthKey; -@property (nonatomic, strong, readonly) MTDatacenterAuthKey *mediaTempAuthKey; -@property (nonatomic, strong, readonly) MTDatacenterAuthKey *persistentAuthKey; - -- (instancetype)initWithAuthKey:(NSData *)authKey authKeyId:(int64_t)authKeyId saltSet:(NSArray *)saltSet authKeyAttributes:(NSDictionary *)authKeyAttributes mainTempAuthKey:(MTDatacenterAuthKey *)mainTempAuthKey mediaTempAuthKey:(MTDatacenterAuthKey *)mediaTempAuthKey; +- (instancetype)initWithAuthKey:(NSData *)authKey authKeyId:(int64_t)authKeyId saltSet:(NSArray *)saltSet authKeyAttributes:(NSDictionary *)authKeyAttributes; - (int64_t)authSaltForMessageId:(int64_t)messageId; - (MTDatacenterAuthInfo *)mergeSaltSet:(NSArray *)updatedSaltSet forTimestamp:(NSTimeInterval)timestamp; - (MTDatacenterAuthInfo *)withUpdatedAuthKeyAttributes:(NSDictionary *)authKeyAttributes; -- (MTDatacenterAuthKey *)tempAuthKeyWithType:(MTDatacenterAuthTempKeyType)type; -- (MTDatacenterAuthInfo *)withUpdatedTempAuthKeyWithType:(MTDatacenterAuthTempKeyType)type key:(MTDatacenterAuthKey *)key; @end diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h index 2b89f85ecf..761ed3029e 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h @@ -1,11 +1,13 @@ #import +#import @class MTProto; @class MTIncomingMessage; @class MTMessageTransaction; @class MTApiEnvironment; +@class MTSessionInfo; @protocol MTMessageService @@ -15,10 +17,10 @@ - (void)mtProtoDidAddService:(MTProto *)mtProto; - (void)mtProtoDidRemoveService:(MTProto *)mtProto; - (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray *)publicKeys; -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto; +- (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; +- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector; - (void)mtProto:(MTProto *)mtProto receivedQuickAck:(int32_t)quickAckId; - (void)mtProto:(MTProto *)mtProto transactionsMayHaveFailed:(NSArray *)transactionIds; - (void)mtProtoAllTransactionsMayHaveFailed:(MTProto *)mtProto; 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/PublicHeaders/MtProtoKit/MTProtoEngine.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoEngine.h new file mode 100644 index 0000000000..a5e507e8de --- /dev/null +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoEngine.h @@ -0,0 +1,13 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MTProtoEngine : NSObject + +- (instancetype)initWithPersistenceInterface:(id)persistenceInterface; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoInstance.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoInstance.h new file mode 100644 index 0000000000..91a58939e5 --- /dev/null +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoInstance.h @@ -0,0 +1,12 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MTProtoInstance : NSObject + +- (instancetype)initWithEngine:(MTProtoEngine *)engine; + +@end + +NS_ASSUME_NONNULL_END diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoPersistenceInterface.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoPersistenceInterface.h new file mode 100644 index 0000000000..ecabfee72f --- /dev/null +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTProtoPersistenceInterface.h @@ -0,0 +1,14 @@ +#import + +@class MTSignal; + +NS_ASSUME_NONNULL_BEGIN + +@protocol MTProtoPersistenceInterface + +- (MTSignal *)get:(NSData *)key; +- (void)set:(NSData *)key value:(NSData *)value; + +@end + +NS_ASSUME_NONNULL_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 506a954d98..059f974907 100644 --- a/submodules/MtProtoKit/Sources/MTContext.m +++ b/submodules/MtProtoKit/Sources/MTContext.m @@ -114,7 +114,34 @@ @end -@interface MTContext () +typedef int64_t MTDatacenterAuthInfoMapKey; + +typedef struct { + int32_t datacenterId; + MTDatacenterAuthInfoSelector selector; +} MTDatacenterAuthInfoMapKeyStruct; + +static MTDatacenterAuthInfoMapKey authInfoMapKey(int32_t datacenterId, MTDatacenterAuthInfoSelector selector) { + int64_t result = (((int64_t)(selector)) << 32) | ((int64_t)(datacenterId)); + return result; +} + +static NSNumber *authInfoMapIntegerKey(int32_t datacenterId, MTDatacenterAuthInfoSelector selector) { + return [NSNumber numberWithLongLong:authInfoMapKey(datacenterId, selector)]; +} + +static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKey(int64_t key) { + MTDatacenterAuthInfoMapKeyStruct result; + result.datacenterId = (int32_t)(key & 0x7fffffff); + result.selector = (int32_t)(((key >> 32) & 0x7fffffff)); + return result; +} + +static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKeyInteger(NSNumber *key) { + return parseAuthInfoMapKey([key longLongValue]); +} + +@interface MTContext () { int64_t _uniqueId; @@ -127,7 +154,7 @@ NSMutableDictionary *> *_transportSchemeStats; MTTimer *_schemeStatsSyncTimer; - NSMutableDictionary *_datacenterAuthInfoById; + NSMutableDictionary *_datacenterAuthInfoById; NSMutableDictionary *_datacenterPublicKeysById; @@ -138,8 +165,7 @@ MTSignal *_discoverBackupAddressListSignal; NSMutableDictionary *_discoverDatacenterAddressActions; - NSMutableDictionary *_datacenterAuthActions; - NSMutableDictionary *_datacenterTempAuthActions; + NSMutableDictionary *_datacenterAuthActions; NSMutableDictionary *_datacenterTransferAuthActions; NSMutableDictionary *_datacenterCheckKeyRemovedActionTimestamps; @@ -201,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]; @@ -218,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]; @@ -258,9 +288,6 @@ static int32_t fixedTimeDifferenceValue = 0; NSDictionary *datacenterAuthActions = _datacenterAuthActions; _datacenterAuthActions = nil; - NSDictionary *datacenterTempAuthActions = _datacenterTempAuthActions; - _datacenterTempAuthActions = nil; - NSDictionary *discoverDatacenterAddressActions = _discoverDatacenterAddressActions; _discoverDatacenterAddressActions = nil; @@ -284,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]; } @@ -360,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"]; @@ -582,29 +609,46 @@ static int32_t fixedTimeDifferenceValue = 0; }]; } -- (void)updateAuthInfoForDatacenterWithId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo +- (void)updateAuthInfoForDatacenterWithId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo selector:(MTDatacenterAuthInfoSelector)selector { [[MTContext contextQueue] dispatchOnQueue:^ { if (datacenterId != 0) { - if (MTLogEnabled()) { - MTLog(@"[MTContext#%x: auth info updated for %d to %@]", (int)self, datacenterId, authInfo); - } + NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector); + + bool wasNil = _datacenterAuthInfoById[infoKey] == nil; if (authInfo != nil) { - _datacenterAuthInfoById[@(datacenterId)] = authInfo; + _datacenterAuthInfoById[infoKey] = authInfo; } else { - [_datacenterAuthInfoById removeObjectForKey:@(datacenterId)]; + if (_datacenterAuthInfoById[infoKey] == nil) { + return; + } + [_datacenterAuthInfoById removeObjectForKey:infoKey]; } + + if (MTLogEnabled()) { + MTLog(@"[MTContext#%x: auth info updated for %d selector %d to %@]", (int)self, datacenterId, selector, authInfo); + } + [_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"]; NSArray *currentListeners = [[NSArray alloc] initWithArray:_changeListeners]; for (id listener in currentListeners) { - if ([listener respondsToSelector:@selector(contextDatacenterAuthInfoUpdated:datacenterId:authInfo:)]) - [listener contextDatacenterAuthInfoUpdated:self datacenterId:datacenterId authInfo:authInfo]; + 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]; + } + } } } }]; @@ -864,10 +908,11 @@ static int32_t fixedTimeDifferenceValue = 0; return results; } -- (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId { +- (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId selector:(MTDatacenterAuthInfoSelector)selector { __block MTDatacenterAuthInfo *result = nil; [[MTContext contextQueue] dispatchOnQueue:^{ - result = _datacenterAuthInfoById[@(datacenterId)]; + NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector); + result = _datacenterAuthInfoById[infoKey]; } synchronous:true]; return result; @@ -1251,48 +1296,44 @@ static int32_t fixedTimeDifferenceValue = 0; }]; } -- (void)authInfoForDatacenterWithIdRequired:(NSInteger)datacenterId isCdn:(bool)isCdn +- (void)authInfoForDatacenterWithIdRequired:(NSInteger)datacenterId isCdn:(bool)isCdn selector:(MTDatacenterAuthInfoSelector)selector { [[MTContext contextQueue] dispatchOnQueue:^ { - if (_datacenterAuthActions[@(datacenterId)] == nil) + NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector); + + if (_datacenterAuthActions[infoKey] == nil) { - MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithTempAuth:false tempAuthKeyType:MTDatacenterAuthTempKeyTypeMain bindKey:nil]; - authAction.delegate = self; - _datacenterAuthActions[@(datacenterId)] = authAction; - [authAction execute:self datacenterId:datacenterId isCdn:isCdn]; - } - }]; -} - -- (void)tempAuthKeyForDatacenterWithIdRequired:(NSInteger)datacenterId keyType:(MTDatacenterAuthTempKeyType)keyType { - [[MTContext contextQueue] dispatchOnQueue:^{ - if (_datacenterTempAuthActions[@(datacenterId)] == nil) { - MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithTempAuth:true tempAuthKeyType:keyType bindKey:nil]; - authAction.delegate = self; - _datacenterTempAuthActions[@(datacenterId)] = authAction; - [authAction execute:self datacenterId:datacenterId isCdn:false]; - } - }]; -} - -- (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; } } @@ -1357,21 +1398,11 @@ static int32_t fixedTimeDifferenceValue = 0; - (void)updatePeriodicTasks { - [[MTContext contextQueue] dispatchOnQueue:^ - { - int64_t saltsRequiredAtLeastUntilMessageId = (int64_t)(([self globalTime] + 24 * 60.0 * 60.0) * 4294967296); - - [_datacenterAuthInfoById enumerateKeysAndObjectsUsingBlock:^(NSNumber *nDatacenterId, MTDatacenterAuthInfo *authInfo, __unused BOOL *stop) - { - if ([authInfo authSaltForMessageId:saltsRequiredAtLeastUntilMessageId == 0]) { - } - }]; - }]; } - (void)checkIfLoggedOut:(NSInteger)datacenterId { [[MTContext contextQueue] dispatchOnQueue:^{ - MTDatacenterAuthInfo *authInfo = [self authInfoForDatacenterWithId:datacenterId]; + MTDatacenterAuthInfo *authInfo = [self authInfoForDatacenterWithId:datacenterId selector:MTDatacenterAuthInfoSelectorPersistent]; if (authInfo == nil || authInfo.authKey == nil) { return; } @@ -1382,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:authInfo.authKey] 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 3896afcd51..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; - MTDatacenterAuthTempKeyType _tempAuthKeyType; - MTDatacenterAuthKey *_bindKey; + MTDatacenterAuthInfoSelector _authKeyInfoSelector; NSInteger _datacenterId; __weak MTContext *_context; @@ -26,71 +28,61 @@ bool _awaitingAddresSetUpdate; MTProto *_authMtProto; MTProto *_bindMtProto; - - MTMetaDisposable *_verifyDisposable; } @end @implementation MTDatacenterAuthAction -- (instancetype)initWithTempAuth:(bool)tempAuth tempAuthKeyType:(MTDatacenterAuthTempKeyType)tempAuthKeyType bindKey:(MTDatacenterAuthKey *)bindKey { +- (instancetype)initWithAuthKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector isCdn:(bool)isCdn completion:(void (^)(MTDatacenterAuthAction *, bool))completion { self = [super init]; if (self != nil) { - _tempAuth = tempAuth; - _tempAuthKeyType = tempAuthKeyType; - _bindKey = bindKey; - _verifyDisposable = [[MTMetaDisposable alloc] init]; + _authKeyInfoSelector = authKeyInfoSelector; + _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]; - if (currentAuthInfo != nil && _bindKey == nil) { - if (_tempAuth) { - if ([currentAuthInfo tempAuthKeyWithType:_tempAuthKeyType] != nil) { - alreadyCompleted = true; - } - } else { - alreadyCompleted = true; - } + + MTDatacenterAuthInfo *currentAuthInfo = [context authInfoForDatacenterWithId:_datacenterId selector:_authKeyInfoSelector]; + if (currentAuthInfo != nil) { + alreadyCompleted = true; } if (alreadyCompleted) { [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 (_tempAuthKeyType) { - case MTDatacenterAuthTempKeyTypeMain: - _authMtProto.media = false; - break; - case MTDatacenterAuthTempKeyTypeMedia: - _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]; } @@ -104,45 +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]; - if (authInfo != nil) { - authInfo = [authInfo withUpdatedTempAuthKeyWithType:_tempAuthKeyType key:authKey]; - [context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo]; - } - }]; - [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 mainTempAuthKey:nil mediaTempAuthKey:nil]; - - MTContext *context = _context; - [context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo]; - [self complete]; + break; + + default: + assert(false); + break; } } @@ -153,7 +171,10 @@ [authMtProto stop]; - [_verifyDisposable dispose]; + MTProto *bindMtProto = _bindMtProto; + _bindMtProto = nil; + + [bindMtProto stop]; } - (void)cancel @@ -162,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/MTDatacenterAuthInfo.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthInfo.m index f9959626a9..d6b783dfcd 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthInfo.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthInfo.m @@ -27,7 +27,7 @@ @implementation MTDatacenterAuthInfo -- (instancetype)initWithAuthKey:(NSData *)authKey authKeyId:(int64_t)authKeyId saltSet:(NSArray *)saltSet authKeyAttributes:(NSDictionary *)authKeyAttributes mainTempAuthKey:(MTDatacenterAuthKey *)mainTempAuthKey mediaTempAuthKey:(MTDatacenterAuthKey *)mediaTempAuthKey +- (instancetype)initWithAuthKey:(NSData *)authKey authKeyId:(int64_t)authKeyId saltSet:(NSArray *)saltSet authKeyAttributes:(NSDictionary *)authKeyAttributes { self = [super init]; if (self != nil) @@ -36,8 +36,6 @@ _authKeyId = authKeyId; _saltSet = saltSet; _authKeyAttributes = authKeyAttributes; - _mainTempAuthKey = mainTempAuthKey; - _mediaTempAuthKey = mediaTempAuthKey; } return self; } @@ -51,8 +49,6 @@ _authKeyId = [aDecoder decodeInt64ForKey:@"authKeyId"]; _saltSet = [aDecoder decodeObjectForKey:@"saltSet"]; _authKeyAttributes = [aDecoder decodeObjectForKey:@"authKeyAttributes"]; - _mainTempAuthKey = [aDecoder decodeObjectForKey:@"tempAuthKey"]; - _mediaTempAuthKey = [aDecoder decodeObjectForKey:@"mediaTempAuthKey"]; } return self; } @@ -63,8 +59,6 @@ [aCoder encodeInt64:_authKeyId forKey:@"authKeyId"]; [aCoder encodeObject:_saltSet forKey:@"saltSet"]; [aCoder encodeObject:_authKeyAttributes forKey:@"authKeyAttributes"]; - [aCoder encodeObject:_mainTempAuthKey forKey:@"tempAuthKey"]; - [aCoder encodeObject:_mediaTempAuthKey forKey:@"mediaTempAuthKey"]; } - (int64_t)authSaltForMessageId:(int64_t)messageId @@ -113,35 +107,11 @@ } } - return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:mergedSaltSet authKeyAttributes:_authKeyAttributes mainTempAuthKey:_mainTempAuthKey mediaTempAuthKey:_mediaTempAuthKey]; + return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:mergedSaltSet authKeyAttributes:_authKeyAttributes]; } - (MTDatacenterAuthInfo *)withUpdatedAuthKeyAttributes:(NSDictionary *)authKeyAttributes { - return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:_saltSet authKeyAttributes:authKeyAttributes mainTempAuthKey:_mainTempAuthKey mediaTempAuthKey:_mediaTempAuthKey]; -} - -- (MTDatacenterAuthKey *)tempAuthKeyWithType:(MTDatacenterAuthTempKeyType)type { - switch (type) { - case MTDatacenterAuthTempKeyTypeMain: - return _mainTempAuthKey; - case MTDatacenterAuthTempKeyTypeMedia: - return _mediaTempAuthKey; - default: - NSAssert(false, @"unknown MTDatacenterAuthTempKeyType"); - return nil; - } -} - -- (MTDatacenterAuthInfo *)withUpdatedTempAuthKeyWithType:(MTDatacenterAuthTempKeyType)type key:(MTDatacenterAuthKey *)key { - switch (type) { - case MTDatacenterAuthTempKeyTypeMain: - return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:_saltSet authKeyAttributes:_authKeyAttributes mainTempAuthKey:key mediaTempAuthKey:_mediaTempAuthKey]; - case MTDatacenterAuthTempKeyTypeMedia: - return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:_saltSet authKeyAttributes:_authKeyAttributes mainTempAuthKey:_mainTempAuthKey mediaTempAuthKey:key]; - default: - NSAssert(false, @"unknown MTDatacenterAuthTempKeyType"); - return self; - } + return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:_saltSet authKeyAttributes:authKeyAttributes]; } - (MTDatacenterAuthKey *)persistentAuthKey { diff --git a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m index a72758f2a0..e9d94c678b 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m @@ -222,7 +222,7 @@ typedef enum { } } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { if (_currentStageTransactionId == nil) { @@ -308,7 +308,7 @@ typedef enum { return nil; } -- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message +- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if (_stage == MTDatacenterAuthStagePQ && [message.body isKindOfClass:[MTResPqMessage class]]) { @@ -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 6ad6cc0976..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 tempAuthKeyType:MTDatacenterAuthTempKeyTypeMain 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/MTDiscoverDatacenterAddressAction.m b/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m index 940d8eb942..bfd5b5292d 100644 --- a/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m +++ b/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m @@ -88,7 +88,7 @@ [self fail]; else { - if ([context authInfoForDatacenterWithId:_targetDatacenterId] != nil) + if ([context authInfoForDatacenterWithId:_targetDatacenterId selector:MTDatacenterAuthInfoSelectorPersistent] != nil) { _mtProto = [[MTProto alloc] initWithContext:context datacenterId:_targetDatacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0]; _mtProto.useTempAuthKeys = useTempAuthKeys; @@ -118,11 +118,11 @@ [_requestService addRequest:request]; } else - [context authInfoForDatacenterWithIdRequired:_targetDatacenterId isCdn:false]; + [context authInfoForDatacenterWithIdRequired:_targetDatacenterId isCdn:false selector:MTDatacenterAuthInfoSelectorPersistent]; } } -- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)__unused authInfo +- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)__unused authInfo selector:(MTDatacenterAuthInfoSelector)selector { if (_context != context || !_awaitingAddresSetUpdate) return; diff --git a/submodules/MtProtoKit/Sources/MTProto.m b/submodules/MtProtoKit/Sources/MTProto.m index 7c96b4930f..b872c91085 100644 --- a/submodules/MtProtoKit/Sources/MTProto.m +++ b/submodules/MtProtoKit/Sources/MTProto.m @@ -14,7 +14,6 @@ #import #import #import -#import "MTBindingTempAuthKeyContext.h" #import #import @@ -58,13 +57,11 @@ typedef enum { MTProtoStateAwaitingDatacenterScheme = 1, MTProtoStateAwaitingDatacenterAuthorization = 2, - MTProtoStateAwaitingDatacenterTempAuthKey = 4, MTProtoStateAwaitingDatacenterAuthToken = 8, MTProtoStateAwaitingTimeFixAndSalts = 16, MTProtoStateAwaitingLostMessages = 32, MTProtoStateStopped = 64, - MTProtoStatePaused = 128, - MTProtoStateBindingTempAuthKey = 256 + MTProtoStatePaused = 128 } MTProtoState; static const NSUInteger MTMaxContainerSize = 3 * 1024; @@ -85,17 +82,36 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; @end +@interface MTProtoValidAuthInfo : NSObject + +@property (nonatomic, strong, readonly) MTDatacenterAuthInfo *authInfo; +@property (nonatomic, readonly) MTDatacenterAuthInfoSelector selector; + +@end + +@implementation MTProtoValidAuthInfo + +- (instancetype)initWithAuthInfo:(MTDatacenterAuthInfo *)authInfo selector:(MTDatacenterAuthInfoSelector)selector { + self = [super init]; + if (self != nil) { + _authInfo = authInfo; + _selector = selector; + } + return self; +} + +@end + @interface MTProto () { NSMutableArray *_messageServices; - MTDatacenterAuthInfo *_authInfo; + MTProtoValidAuthInfo *_validAuthInfo; + NSNumber *_awaitingAuthInfoForSelector; + MTSessionInfo *_sessionInfo; MTTimeFixContext *_timeFixContext; - int64_t _bindingTempAuthKeyId; - MTBindingTempAuthKeyContext *_bindingTempAuthKeyContext; - MTTransport *_transport; int _mtState; @@ -149,7 +165,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; _messageServices = [[NSMutableArray alloc] init]; _sessionInfo = [[MTSessionInfo alloc] initWithRandomSessionIdAndContext:_context]; - _authInfo = [_context authInfoForDatacenterWithId:_datacenterId]; + + _shouldStayConnected = true; } @@ -170,15 +187,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; }]; } -- (void)setUseExplicitAuthKey:(MTDatacenterAuthKey *)useExplicitAuthKey { - _useExplicitAuthKey = useExplicitAuthKey; - if (_useExplicitAuthKey != nil) { - _authInfo = [_authInfo withUpdatedTempAuthKeyWithType:MTDatacenterAuthTempKeyTypeMain key:useExplicitAuthKey]; - [self setMtState:_mtState | MTProtoStateBindingTempAuthKey]; - [self requestTransportTransaction]; - } -} - - (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo { [[MTProto managerQueue] dispatchOnQueue:^{ _usageCalculationInfo = usageCalculationInfo; @@ -278,7 +286,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; }]; _timeFixContext = nil; - _bindingTempAuthKeyContext = nil; if (_transport != nil) [self removeMessageService:_transport]; @@ -286,20 +293,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; _transport = transport; [previousTransport stop]; - if (_transport != nil && _useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - /*if (_transport.scheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - }*/ - - MTDatacenterAuthKey *effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - if (effectiveAuthKey == nil) { - if (MTLogEnabled()) { - MTLog(@"[MTProto#%p setTransport temp auth key missing]", self); - } - } - } - if (_transport != nil) [self addMessageService:_transport]; @@ -323,38 +316,13 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; NSArray *transportSchemes = [_context transportSchemesForDatacenterWithId:_datacenterId media:_media enforceMedia:_enforceMedia isProxy:_apiEnvironment.socksProxySettings != nil]; - /*MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (_transportScheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - }*/ - if (transportSchemes.count == 0) { if ((_mtState & MTProtoStateAwaitingDatacenterScheme) == 0) { [self setMtState:_mtState | MTProtoStateAwaitingDatacenterScheme]; [_context transportSchemeForDatacenterWithIdRequired:_datacenterId media:_media]; } - } else if (!_useUnauthorizedMode && [_context authInfoForDatacenterWithId:_datacenterId] == nil) { - if (MTLogEnabled()) { - MTLog(@"[MTProto#%p@%p authInfoForDatacenterWithId:%d is nil]", self, _context, _datacenterId); - } - MTShortLog(@"[MTProto#%p@%p authInfoForDatacenterWithId:%d is nil]", self, _context, _datacenterId); - if ((_mtState & MTProtoStateAwaitingDatacenterAuthorization) == 0) { - [self setMtState:_mtState | MTProtoStateAwaitingDatacenterAuthorization]; - - if (MTLogEnabled()) { - MTLog(@"[MTProto#%p@%p requesting authInfo for %d]", self, _context, _datacenterId); - } - MTShortLog(@"[MTProto#%p@%p requesting authInfo for %d]", self, _context, _datacenterId); - [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:_cdn]; - } - }/* else if (!_useUnauthorizedMode && _useTempAuthKeys && [[_context authInfoForDatacenterWithId:_datacenterId] tempAuthKeyWithType:tempAuthKeyType] == nil) { - if ((_mtState & MTProtoStateAwaitingDatacenterTempAuthKey) == 0) { - [self setMtState:_mtState | MTProtoStateAwaitingDatacenterTempAuthKey]; - - [_context tempAuthKeyForDatacenterWithIdRequired:_datacenterId keyType:tempAuthKeyType]; - } - }*/ + } else if (_requiredAuthToken != nil && !_useUnauthorizedMode && ![_requiredAuthToken isEqual:[_context authTokenForDatacenterWithId:_datacenterId]]) { if ((_mtState & MTProtoStateAwaitingDatacenterAuthToken) == 0) { [self setMtState:_mtState | MTProtoStateAwaitingDatacenterAuthToken]; @@ -366,8 +334,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; MTTransport *transport = [[MTTcpTransport alloc] initWithDelegate:self context:_context datacenterId:_datacenterId schemes:transportSchemes proxySettings:_context.apiEnvironment.socksProxySettings usageCalculationInfo:_usageCalculationInfo]; [self setTransport:transport]; - - //[self checkTempAuthKeyBinding:transport.scheme.address]; } }]; } @@ -381,13 +347,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; } MTShortLog(@"[MTProto#%p@%p resetting session]", self, _context); - if (_authInfo.authKeyId != 0 && !self.cdn) { - [_context scheduleSessionCleanupForAuthKeyId:_authInfo.authKeyId sessionInfo:_sessionInfo]; - } - _sessionInfo = [[MTSessionInfo alloc] initWithRandomSessionIdAndContext:_context]; _timeFixContext = nil; - _bindingTempAuthKeyContext = nil; for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) { @@ -402,11 +363,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; } - (void)finalizeSession { - [[MTProto managerQueue] dispatchOnQueue:^{ - if (_authInfo.authKeyId != 0 && !self.cdn) { - [_context scheduleSessionCleanupForAuthKeyId:_authInfo.authKeyId sessionInfo:_sessionInfo]; - } - }]; } - (void)requestTimeResync @@ -695,12 +651,12 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; - (bool)canAskForTransactions { - return (_mtState & (MTProtoStateAwaitingDatacenterScheme | MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterTempAuthKey | MTProtoStateAwaitingDatacenterAuthToken | MTProtoStateAwaitingTimeFixAndSalts | MTProtoStateBindingTempAuthKey | MTProtoStateStopped)) == 0; + return (_mtState & (MTProtoStateAwaitingDatacenterScheme | MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterAuthToken | MTProtoStateAwaitingTimeFixAndSalts | MTProtoStateStopped)) == 0; } - (bool)canAskForServiceTransactions { - return (_mtState & (MTProtoStateAwaitingDatacenterScheme | MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterTempAuthKey | MTProtoStateAwaitingDatacenterAuthToken | MTProtoStateStopped)) == 0; + return (_mtState & (MTProtoStateAwaitingDatacenterScheme | MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterAuthToken | MTProtoStateStopped)) == 0; } - (bool)timeFixOrSaltsMissing @@ -708,11 +664,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return _mtState & MTProtoStateAwaitingTimeFixAndSalts; } -- (bool)bindingTempAuthKey -{ - return _mtState & MTProtoStateBindingTempAuthKey; -} - - (bool)isStopped { return (_mtState & MTProtoStateStopped) != 0; @@ -876,6 +827,65 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return [[NSString alloc] initWithFormat:@"%@ (%" PRId64", %" PRId64"/%" PRId64")", message.body, message.messageId, message.authKeyId, message.sessionId]; } +- (MTDatacenterAuthKey *)getAuthKeyForCurrentScheme:(MTTransportScheme *)scheme createIfNeeded:(bool)createIfNeeded authInfoSelector:(MTDatacenterAuthInfoSelector *)authInfoSelector { + if (_useExplicitAuthKey) { + MTDatacenterAuthInfoSelector selector = MTDatacenterAuthInfoSelectorEphemeralMain; + if (authInfoSelector != nil) { + *authInfoSelector = 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 { + 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 { + 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; + } + } + } +} + - (void)transportReadyForTransaction:(MTTransport *)transport scheme:(MTTransportScheme *)scheme transportSpecificTransaction:(MTMessageTransaction *)transportSpecificTransaction forceConfirmations:(bool)forceConfirmations transactionReady:(void (^)(NSArray *))transactionReady { [[MTProto managerQueue] dispatchOnQueue:^ @@ -887,6 +897,19 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return; } + MTDatacenterAuthKey *authKey = nil; + MTDatacenterAuthInfoSelector authInfoSelector = MTDatacenterAuthInfoSelectorPersistent; + if (!_useUnauthorizedMode) { + authKey = [self getAuthKeyForCurrentScheme:scheme createIfNeeded:true authInfoSelector:&authInfoSelector]; + + if (authKey == nil) { + if (transactionReady) { + transactionReady(nil); + } + return; + } + } + bool extendedPadding = false; if (transport.proxySettings != nil && transport.proxySettings.secret != nil) { MTProxySecret *parsedSecret = [MTProxySecret parseData:transport.proxySettings.secret]; @@ -908,7 +931,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; if (transportSpecificTransaction != nil) { - if (!(transportSpecificTransaction.requiresEncryption && _useUnauthorizedMode) && (!transportSpecificTransaction.requiresEncryption || _authInfo != nil)) + if (!(transportSpecificTransaction.requiresEncryption && _useUnauthorizedMode) && (!transportSpecificTransaction.requiresEncryption || authKey != nil)) { [messageTransactions addObject:transportSpecificTransaction]; } @@ -919,9 +942,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; NSMutableArray *messageServiceTransactions = [[NSMutableArray alloc] init]; for (id messageService in _messageServices) { - if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:)]) + if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:authInfoSelector:sessionInfo:)]) { - MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self]; + MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self authInfoSelector:authInfoSelector sessionInfo:transactionSessionInfo]; if (messageTransaction != nil) { for (MTOutgoingMessage *message in messageTransaction.messagePayload) @@ -977,7 +1000,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; int64_t messageSalt = 0; if (!_useUnauthorizedMode) { - messageSalt = [_authInfo authSaltForMessageId:[transactionSessionInfo actualClientMessagId]]; + messageSalt = [_validAuthInfo.authInfo authSaltForMessageId:[transactionSessionInfo actualClientMessagId]]; if (messageSalt == 0) saltSetEmpty = true; } @@ -1156,7 +1179,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; if (currentContainerMessages.count == 1) { int32_t quickAckId = 0; - NSData *messageData = [self _dataForEncryptedMessage:currentContainerMessages[0] sessionInfo:transactionSessionInfo quickAckId:&quickAckId address:scheme.address extendedPadding:extendedPadding]; + NSData *messageData = [self _dataForEncryptedMessage:currentContainerMessages[0] authKey:authKey sessionInfo:transactionSessionInfo quickAckId:&quickAckId address:scheme.address extendedPadding:extendedPadding]; if (messageData != nil) { [transactionPayloadList addObject:messageData]; @@ -1167,7 +1190,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; else if (currentContainerMessages.count != 0) { int32_t quickAckId = 0; - NSData *containerData = [self _dataForEncryptedContainerWithMessages:currentContainerMessages sessionInfo:transactionSessionInfo quickAckId:&quickAckId address:scheme.address extendedPadding:extendedPadding]; + NSData *containerData = [self _dataForEncryptedContainerWithMessages:currentContainerMessages authKey:authKey sessionInfo:transactionSessionInfo quickAckId:&quickAckId address:scheme.address extendedPadding:extendedPadding]; if (containerData != nil) { [transactionPayloadList addObject:containerData]; @@ -1309,7 +1332,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; } MTShortLog(@"[MTProto#%p@%p sending time fix ping (%" PRId64 "/%" PRId32 ", %" PRId64 ")]", self, _context, timeFixMessageId, timeFixSeqNo, _sessionInfo.sessionId); - [decryptedOs writeInt64:[_authInfo authSaltForMessageId:timeFixMessageId]]; // salt + [decryptedOs writeInt64:[_validAuthInfo.authInfo authSaltForMessageId:timeFixMessageId]]; // salt [decryptedOs writeInt64:_sessionInfo.sessionId]; [decryptedOs writeInt64:timeFixMessageId]; [decryptedOs writeInt32:timeFixSeqNo]; @@ -1319,18 +1342,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; NSData *decryptedData = [self paddedData:[decryptedOs currentBytes] extendedPadding:extendedPadding]; - MTDatacenterAuthKey *effectiveAuthKey; - if (_useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (scheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - - effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - NSAssert(effectiveAuthKey != nil, @"effectiveAuthKey == nil"); - } else { - effectiveAuthKey = [[MTDatacenterAuthKey alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId notBound:false]; - } + MTDatacenterAuthKey *effectiveAuthKey = authKey; int xValue = 0; NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init]; @@ -1384,115 +1396,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; transactionReady(nil); } } - else if (![self timeFixOrSaltsMissing] && [self bindingTempAuthKey] && [self canAskForServiceTransactions] && (_bindingTempAuthKeyContext == nil || _bindingTempAuthKeyContext.transactionId == nil)) - { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (scheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - - MTDatacenterAuthKey *effectiveTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - NSAssert(effectiveTempAuthKey != nil, @"effectiveAuthKey == nil"); - - int64_t bindingMessageId = [_sessionInfo generateClientMessageId:NULL]; - int32_t bindingSeqNo = [_sessionInfo takeSeqNo:true]; - - int32_t expiresAt = (int32_t)([_context globalTime] + 60 * 60 * 32); - - 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:effectiveTempAuthKey.authKeyId]; - [decryptedMessage appendInt64:_authInfo.authKeyId]; - [decryptedMessage appendInt64:_sessionInfo.sessionId]; - [decryptedMessage appendInt32:expiresAt]; - - NSData *encryptedMessage = [self _manuallyEncryptedMessage:[decryptedMessage data] messageId:bindingMessageId authKey:_authInfo.persistentAuthKey]; - - 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:_authInfo.persistentAuthKey.authKeyId]; - [bindRequestData appendInt64:nonce]; - [bindRequestData appendInt32:expiresAt]; - [bindRequestData appendTLBytes:encryptedMessage]; - - NSData *messageData = bindRequestData.data; - - MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; - - if (MTLogEnabled()) { - MTLog(@"[MTProto#%p@%p sending temp key binding message (%" PRId64 "/%" PRId32 ") for %lld (%d)]", self, _context, bindingMessageId, bindingSeqNo, effectiveTempAuthKey.authKeyId, (int)tempAuthKeyType); - } - MTShortLog(@"[MTProto#%p@%p sending temp key binding message (%" PRId64 "/%" PRId32 ") for %lld (%d)]", self, _context, bindingMessageId, bindingSeqNo, effectiveTempAuthKey.authKeyId, (int)tempAuthKeyType); - - [decryptedOs writeInt64:[_authInfo authSaltForMessageId:bindingMessageId]]; - [decryptedOs writeInt64:_sessionInfo.sessionId]; - [decryptedOs writeInt64:bindingMessageId]; - [decryptedOs writeInt32:bindingSeqNo]; - - [decryptedOs writeInt32:(int32_t)messageData.length]; - [decryptedOs writeData:messageData]; - - NSData *decryptedData = [self paddedData:[decryptedOs currentBytes] extendedPadding:extendedPadding]; - - int xValue = 0; - NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init]; - [msgKeyLargeData appendBytes:effectiveTempAuthKey.authKey.bytes + 88 + xValue length:32]; - [msgKeyLargeData appendData:decryptedData]; - - NSData *msgKeyLarge = MTSha256(msgKeyLargeData); - NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)]; - MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:effectiveTempAuthKey.authKey messageKey:messageKey toClient:false]; - - NSData *transactionData = nil; - - if (encryptionKey != nil) - { - NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length]; - [encryptedData appendData:decryptedData]; - MTAesEncryptInplace(encryptedData, encryptionKey.key, encryptionKey.iv); - - int64_t authKeyId = effectiveTempAuthKey.authKeyId; - [encryptedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&authKeyId length:8]; - [encryptedData replaceBytesInRange:NSMakeRange(8, 0) withBytes:messageKey.bytes length:messageKey.length]; - - transactionData = encryptedData; - } - - if (transactionReady != nil) - { - if (transactionData != nil) - { - __weak MTProto *weakSelf = self; - transactionReady(@[[[MTTransportTransaction alloc] initWithPayload:transactionData completion:^(bool success, id transactionId) { - [[MTProto managerQueue] dispatchOnQueue:^{ - if (success) { - if (transactionId != nil) { - _bindingTempAuthKeyContext = [[MTBindingTempAuthKeyContext alloc] initWithMessageId:bindingMessageId messageSeqNo:bindingSeqNo transactionId:transactionId]; - } - } - else - { - __strong MTProto *strongSelf = weakSelf; - [strongSelf requestTransportTransaction]; - } - }]; - } needsQuickAck:false expectsDataInResponse:true]]); - } - else - transactionReady(nil); - } - } else if (transactionReady != nil) transactionReady(nil); @@ -1503,19 +1406,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; }]; } -- (NSData *)_dataForEncryptedContainerWithMessages:(NSArray *)preparedMessages sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId address:(MTDatacenterAddress *)address extendedPadding:(bool)extendedPadding { - MTDatacenterAuthKey *effectiveAuthKey; - if (_useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - - NSAssert(effectiveAuthKey != nil, @"effectiveAuthKey == nil"); - } else { - effectiveAuthKey = [[MTDatacenterAuthKey alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId notBound:false]; - } +- (NSData *)_dataForEncryptedContainerWithMessages:(NSArray *)preparedMessages authKey:(MTDatacenterAuthKey *)authKey sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId address:(MTDatacenterAddress *)address extendedPadding:(bool)extendedPadding { + MTDatacenterAuthKey *effectiveAuthKey = authKey; NSMutableArray *containerMessageIds = [[NSMutableArray alloc] init]; @@ -1622,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); @@ -1669,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; @@ -1685,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]; @@ -1708,19 +1600,10 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return nil; } -- (NSData *)_dataForEncryptedMessage:(MTPreparedMessage *)preparedMessage sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId address:(MTDatacenterAddress *)address extendedPadding:(bool)extendedPadding +- (NSData *)_dataForEncryptedMessage:(MTPreparedMessage *)preparedMessage authKey:(MTDatacenterAuthKey *)authKey sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId address:(MTDatacenterAddress *)address extendedPadding:(bool)extendedPadding { - MTDatacenterAuthKey *effectiveAuthKey; - if (_useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - NSAssert(effectiveAuthKey != nil, @"effectiveAuthKey == nil"); - } else { - effectiveAuthKey = [[MTDatacenterAuthKey alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId notBound:false]; - } + MTDatacenterAuthKey *effectiveAuthKey = authKey; + NSAssert(effectiveAuthKey != nil, @"effectiveAuthKey == nil"); MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; @@ -1774,12 +1657,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; requestTransaction = true; } - if (_bindingTempAuthKeyContext != nil && _bindingTempAuthKeyContext.transactionId != nil && [transactionIds containsObject:_bindingTempAuthKeyContext.transactionId]) - { - _bindingTempAuthKeyContext = nil; - requestTransaction = true; - } - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) { id messageService = _messageServices[(NSUInteger)i]; @@ -1806,12 +1683,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; requestTransaction = true; } - if (_bindingTempAuthKeyContext != nil && _bindingTempAuthKeyContext.transactionId != nil) - { - _bindingTempAuthKeyContext = nil; - requestTransaction = true; - } - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) { id messageService = _messageServices[(NSUInteger)i]; @@ -1848,24 +1719,18 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; if (transport != _transport || completion == nil) return; - MTDatacenterAuthKey *effectiveAuthKey; - if (_useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (scheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - - effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - NSAssert(effectiveAuthKey != nil, @"effectiveAuthKey == nil"); - } else { - effectiveAuthKey = [[MTDatacenterAuthKey alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId notBound:false]; + MTDatacenterAuthKey *authKey = [self getAuthKeyForCurrentScheme:scheme createIfNeeded:false authInfoSelector:nil]; + if (authKey == nil) { + return; } + MTDatacenterAuthKey *effectiveAuthKey = authKey; + MTInputStream *is = [[MTInputStream alloc] initWithData:data]; int64_t keyId = [is readInt64]; - if (keyId != 0 && _authInfo != nil) + if (keyId == authKey.authKeyId) { NSData *messageKey = [is readData:16]; @@ -2070,7 +1935,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { } if (protocolErrorCode == -404) { - [self handleMissingKey:scheme.address]; + [self handleMissingKey:scheme]; } if (currentTransport == _transport) @@ -2081,10 +1946,17 @@ static NSString *dumpHexString(NSData *data, int maxLength) { NSData *decryptedData = nil; - if (_useUnauthorizedMode) + int64_t embeddedAuthKeyId = 0; + MTDatacenterAuthInfoSelector authInfoSelector = MTDatacenterAuthInfoSelectorPersistent; + if (_useUnauthorizedMode) { decryptedData = data; - else - decryptedData = [self _decryptIncomingTransportData:data address:scheme.address]; + } else { + MTDatacenterAuthKey *authKey = [self getAuthKeyForCurrentScheme:scheme createIfNeeded:false authInfoSelector:&authInfoSelector]; + if (authKey != nil) { + embeddedAuthKeyId = authKey.authKeyId; + decryptedData = [self _decryptIncomingTransportData:data address:scheme.address authKey:authKey]; + } + } if (decryptedData != nil) { @@ -2093,9 +1965,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { int64_t dataMessageId = 0; bool parseError = false; - NSArray *parsedMessages = [self _parseIncomingMessages:decryptedData dataMessageId:&dataMessageId parseError:&parseError]; - - + NSArray *parsedMessages = [self _parseIncomingMessages:decryptedData dataMessageId:&dataMessageId embeddedAuthKeyId:embeddedAuthKeyId parseError:&parseError]; for (MTIncomingMessage *message in parsedMessages) { if ([message.body isKindOfClass:[MTRpcResultMessage class]]) { @@ -2108,7 +1978,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { MTLog(@"[MTProto#%p@%p received AUTH_KEY_PERM_EMPTY]", self, _context); } MTShortLog(@"[MTProto#%p@%p received AUTH_KEY_PERM_EMPTY]", self, _context); - [self handleMissingKey:scheme.address]; + [self handleMissingKey:scheme]; [self requestSecureTransportReset]; return; @@ -2132,7 +2002,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { for (MTIncomingMessage *incomingMessage in parsedMessages) { - [self _processIncomingMessage:incomingMessage totalSize:(int)data.length withTransactionId:transactionId address:scheme.address]; + [self _processIncomingMessage:incomingMessage totalSize:(int)data.length withTransactionId:transactionId address:scheme.address authInfoSelector:authInfoSelector]; } if (requestTransactionAfterProcessing) @@ -2155,71 +2025,74 @@ static NSString *dumpHexString(NSData *data, int maxLength) { }]; } -- (void)handleMissingKey:(MTDatacenterAddress *)address { +- (void)handleMissingKey:(MTTransportScheme *)scheme { NSAssert([[MTProto managerQueue] isCurrentQueue], @"invalid queue"); + 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) { - _authInfo = nil; + _validAuthInfo = nil; + [_context performBatchUpdates:^{ - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil]; - [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:true]; + [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil selector:authInfoSelector]; + [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:true selector:authInfoSelector]; }]; _mtState |= MTProtoStateAwaitingDatacenterAuthorization; - } else if (_useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - - MTDatacenterAuthKey *currentTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - - _authInfo = [_authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:nil]; - _mtState |= MTProtoStateAwaitingDatacenterTempAuthKey; - - [_context performBatchUpdates:^{ - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId]; - if ([authInfo tempAuthKeyWithType:tempAuthKeyType].authKeyId == currentTempAuthKey.authKeyId) { - authInfo = [authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:nil]; - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo]; - [_context tempAuthKeyForDatacenterWithIdRequired:_datacenterId keyType:tempAuthKeyType]; - } - }]; + _awaitingAuthInfoForSelector = @(authInfoSelector); } else { + MTDatacenterAuthInfoSelector authInfoSelector; + [self getAuthKeyForCurrentScheme:scheme createIfNeeded:false authInfoSelector:&authInfoSelector]; + if (_requiredAuthToken != nil && _authTokenMasterDatacenterId != _datacenterId) { - _authInfo = nil; + _validAuthInfo = nil; + [_context removeTokenForDatacenterWithId:_datacenterId]; [_context performBatchUpdates:^{ - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil]; - [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:false]; + [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil selector:authInfoSelector]; + [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:false selector:authInfoSelector]; }]; _mtState |= MTProtoStateAwaitingDatacenterAuthorization; + _awaitingAuthInfoForSelector = @(authInfoSelector); } else if (_canResetAuthData) { - _authInfo = nil; + _validAuthInfo = nil; + [_context performBatchUpdates:^{ - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil]; - [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:false]; + [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil selector:authInfoSelector]; + [_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:false selector:authInfoSelector]; }]; _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; + } } } } -- (NSData *)_decryptIncomingTransportData:(NSData *)transportData address:(MTDatacenterAddress *)address +- (NSData *)_decryptIncomingTransportData:(NSData *)transportData address:(MTDatacenterAddress *)address authKey:(MTDatacenterAuthKey *)authKey { - MTDatacenterAuthKey *effectiveAuthKey; - if (_useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - - effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - } else { - effectiveAuthKey = [[MTDatacenterAuthKey alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId notBound:false]; - } + MTDatacenterAuthKey *effectiveAuthKey = authKey; if (effectiveAuthKey == nil) return nil; @@ -2281,13 +2154,12 @@ static NSString *dumpHexString(NSData *data, int maxLength) { return [_context.serialization parseMessage:unwrappedData]; } -- (NSArray *)_parseIncomingMessages:(NSData *)data dataMessageId:(out int64_t *)dataMessageId parseError:(out bool *)parseError +- (NSArray *)_parseIncomingMessages:(NSData *)data dataMessageId:(out int64_t *)dataMessageId embeddedAuthKeyId:(int64_t)embeddedAuthKeyId parseError:(out bool *)parseError { MTInputStream *is = [[MTInputStream alloc] initWithData:data]; bool readError = false; - int64_t embeddedAuthKeyId = 0; int64_t embeddedSessionId = 0; int64_t embeddedMessageId = 0; int32_t embeddedSeqNo = 0; @@ -2303,7 +2175,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) { *parseError = true; return nil; } - embeddedAuthKeyId = authKeyId; embeddedMessageId = [is readInt64:&readError]; if (readError) @@ -2326,7 +2197,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) { } else { - embeddedAuthKeyId = _authInfo.authKeyId; embeddedSalt = [is readInt64:&readError]; if (readError) { @@ -2436,7 +2306,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { return messages; } -- (void)_processIncomingMessage:(MTIncomingMessage *)incomingMessage totalSize:(int)totalSize withTransactionId:(id)transactionId address:(MTDatacenterAddress *)address +- (void)_processIncomingMessage:(MTIncomingMessage *)incomingMessage totalSize:(int)totalSize withTransactionId:(id)transactionId address:(MTDatacenterAddress *)address authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if ([_sessionInfo messageProcessed:incomingMessage.messageId]) { @@ -2482,7 +2352,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { int64_t validSalt = ((MTBadServerSaltNotificationMessage *)badMsgNotification).nextServerSalt; NSTimeInterval timeDifference = incomingMessage.messageId / 4294967296.0 - [[NSDate date] timeIntervalSince1970]; [self completeTimeSync]; - [self timeSyncInfoChanged:timeDifference saltList:@[[[MTDatacenterSaltInfo alloc] initWithSalt:validSalt firstValidMessageId:incomingMessage.messageId lastValidMessageId:incomingMessage.messageId + (4294967296 * 30 * 60)]]]; + [self timeSyncInfoChanged:timeDifference saltList:@[[[MTDatacenterSaltInfo alloc] initWithSalt:validSalt firstValidMessageId:incomingMessage.messageId lastValidMessageId:incomingMessage.messageId + (4294967296 * 30 * 60)]] authInfoSelector:authInfoSelector]; } else [self initiateTimeSync]; @@ -2500,7 +2370,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) { NSTimeInterval timeDifference = incomingMessage.messageId / 4294967296.0 - [[NSDate date] timeIntervalSince1970]; [self completeTimeSync]; - [self timeSyncInfoChanged:timeDifference saltList:nil]; + [self timeSyncInfoChanged:timeDifference saltList:nil authInfoSelector:authInfoSelector]; } else [self initiateTimeSync]; @@ -2542,11 +2412,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) { } } - if (_bindingTempAuthKeyContext != nil && badMessageId == _bindingTempAuthKeyContext.messageId) - { - _bindingTempAuthKeyContext = nil; - } - if ([self canAskForTransactions] || [self canAskForServiceTransactions]) [self requestTransportTransaction]; } @@ -2624,8 +2489,8 @@ static NSString *dumpHexString(NSData *data, int maxLength) { { id messageService = _messageServices[(NSUInteger)i]; - if ([messageService respondsToSelector:@selector(mtProto:receivedMessage:)]) - [messageService mtProto:self receivedMessage:incomingMessage]; + if ([messageService respondsToSelector:@selector(mtProto:receivedMessage:authInfoSelector:)]) + [messageService mtProto:self receivedMessage:incomingMessage authInfoSelector:authInfoSelector]; } if (_timeFixContext != nil && [incomingMessage.body isKindOfClass:[MTPongMessage class]] && ((MTPongMessage *)incomingMessage.body).messageId == _timeFixContext.messageId) @@ -2636,71 +2501,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) { if ([self canAskForTransactions] || [self canAskForServiceTransactions]) [self requestTransportTransaction]; } - - if (_bindingTempAuthKeyContext != nil && [incomingMessage.body isKindOfClass:[MTRpcResultMessage class]] && ((MTRpcResultMessage *)incomingMessage.body).requestMessageId == _bindingTempAuthKeyContext.messageId) { - MTRpcResultMessage *rpcResultMessage = (MTRpcResultMessage *)incomingMessage.body; - - _bindingTempAuthKeyContext = nil; - - id maybeInternalMessage = [MTInternalMessageParser parseMessage:rpcResultMessage.data]; - - id rpcResult = nil; - MTRpcError *rpcError = nil; - - if ([maybeInternalMessage isKindOfClass:[MTRpcError class]]) - rpcError = maybeInternalMessage; - else - { - if (rpcResultMessage.data.length >= 4) { - int32_t signature = 0; - [rpcResultMessage.data getBytes:&signature range:NSMakeRange(0, 4)]; - if (signature == (int32_t)0xbc799737) { - rpcResult = @true; - } else if (signature == (int32_t)0x997275b5) { - rpcResult = @false; - } - } - if (rpcResult == nil) { - rpcError = [[MTRpcError alloc] initWithErrorCode:500 errorDescription:@"TL_PARSING_ERROR"]; - } - } - - if ([rpcResult respondsToSelector:@selector(boolValue)]) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - MTDatacenterAuthKey *effectiveTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - if (effectiveTempAuthKey != nil) { - _authInfo = [_authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:[[MTDatacenterAuthKey alloc] initWithAuthKey:effectiveTempAuthKey.authKey authKeyId:effectiveTempAuthKey.authKeyId notBound:false]]; - NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:_authInfo.authKeyAttributes]; - [authKeyAttributes removeObjectForKey:@"apiInitializationHash"]; - _authInfo = [_authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; - if (_useExplicitAuthKey == nil) { - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:_authInfo]; - } - if (_tempAuthKeyBindingResultUpdated) { - _tempAuthKeyBindingResultUpdated(true); - } - } - _bindingTempAuthKeyId = 0; - if ((_mtState & MTProtoStateBindingTempAuthKey) != 0) { - [self setMtState:_mtState & (~MTProtoStateBindingTempAuthKey)]; - [self requestTransportTransaction]; - } - } else { - if (MTLogEnabled()) { - MTLog(@"[MTProto#%p@%p bindTempAuthKey error %@]", self, _context, rpcError); - } - MTShortLog(@"[MTProto#%p@%p bindTempAuthKey error %@]", self, _context, rpcError); - - [self requestTransportTransaction]; - - if (_tempAuthKeyBindingResultUpdated) { - _tempAuthKeyBindingResultUpdated(false); - } - } - } } } @@ -2722,18 +2522,27 @@ static NSString *dumpHexString(NSData *data, int maxLength) { }]; } -- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo +- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo selector:(MTDatacenterAuthInfoSelector)selector { [[MTProto managerQueue] dispatchOnQueue:^ { if (!_useUnauthorizedMode && context == _context && datacenterId == _datacenterId) { - _authInfo = authInfo; - if (_useExplicitAuthKey != nil) { - _authInfo = [_authInfo withUpdatedTempAuthKeyWithType:MTDatacenterAuthTempKeyTypeMain key:_useExplicitAuthKey]; + if (_validAuthInfo != nil) { + if (_validAuthInfo.selector != selector) { + return; + } + } else if (_awaitingAuthInfoForSelector != nil) { + if ([_awaitingAuthInfoForSelector intValue] != selector) { + return; + } else if (authInfo != nil) { + _awaitingAuthInfoForSelector = nil; + } + } else { + return; } - bool wasSuspended = _mtState & (MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterTempAuthKey); + bool wasSuspended = _mtState & (MTProtoStateAwaitingDatacenterAuthorization); if (authInfo != nil) { if (_mtState & MTProtoStateAwaitingDatacenterAuthorization) { @@ -2741,38 +2550,8 @@ static NSString *dumpHexString(NSData *data, int maxLength) { } } - /*if (_transportScheme != nil && _useTempAuthKeys) { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (_transportScheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - if ([[_context authInfoForDatacenterWithId:_datacenterId] tempAuthKeyWithType:tempAuthKeyType] == nil) { - if ((_mtState & MTProtoStateAwaitingDatacenterTempAuthKey) == 0) { - [self setMtState:_mtState | MTProtoStateAwaitingDatacenterTempAuthKey]; - - [_context tempAuthKeyForDatacenterWithIdRequired:_datacenterId keyType:tempAuthKeyType]; - } - } - } - - if (_transportScheme != nil && (_mtState & MTProtoStateAwaitingDatacenterTempAuthKey)) - { - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (_transportScheme.address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - - if ([_authInfo tempAuthKeyWithType:tempAuthKeyType] != nil) { - [self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterTempAuthKey)]; - } - } - - if (_transportScheme != nil) { - [self checkTempAuthKeyBinding:_transportScheme.address]; - }*/ - if (authInfo != nil) { - if ((_mtState & (MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterTempAuthKey)) == 0) { + if ((_mtState & (MTProtoStateAwaitingDatacenterAuthorization)) == 0) { if (wasSuspended) { [self resetTransport]; [self requestTransportTransaction]; @@ -2785,38 +2564,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) { }]; } -- (void)checkTempAuthKeyBinding:(MTDatacenterAddress *)address { - NSAssert([[MTProto managerQueue] isCurrentQueue], @"invalid queue"); - - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - MTDatacenterAuthKey *effectiveTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - - if (_useTempAuthKeys && effectiveTempAuthKey != nil && effectiveTempAuthKey.notBound) { - bool isAlreadyBinding = false; - if (_bindingTempAuthKeyId != 0) { - if (_bindingTempAuthKeyId == effectiveTempAuthKey.authKeyId) { - isAlreadyBinding = true; - } else { - _bindingTempAuthKeyId = 0; - _bindingTempAuthKeyContext = nil; - } - } - if (!isAlreadyBinding && (_mtState & MTProtoStateBindingTempAuthKey) == 0) { - [self bindToPersistentKey:address]; - } - } else { - _bindingTempAuthKeyId = 0; - _bindingTempAuthKeyContext = nil; - if ((_mtState & MTProtoStateBindingTempAuthKey) != 0) { - [self setMtState:_mtState & (~MTProtoStateBindingTempAuthKey)]; - [self requestTransportTransaction]; - } - } -} - - (void)contextDatacenterAuthTokenUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authToken:(id)authToken { [[MTProto managerQueue] dispatchOnQueue:^ @@ -2842,28 +2589,38 @@ static NSString *dumpHexString(NSData *data, int maxLength) { }]; } -- (void)timeSyncServiceCompleted:(MTTimeSyncMessageService *)timeSyncService timeDifference:(NSTimeInterval)timeDifference saltList:(NSArray *)saltList +- (void)timeSyncServiceCompleted:(MTTimeSyncMessageService *)timeSyncService timeDifference:(NSTimeInterval)timeDifference saltList:(NSArray *)saltList authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if ([_messageServices containsObject:timeSyncService]) { [self completeTimeSync]; [_messageServices removeObject:timeSyncService]; - [self timeSyncInfoChanged:timeDifference saltList:saltList]; + [self timeSyncInfoChanged:timeDifference saltList:saltList authInfoSelector:authInfoSelector]; } } -- (void)timeSyncInfoChanged:(NSTimeInterval)timeDifference saltList:(NSArray *)saltList +- (void)timeSyncInfoChanged:(NSTimeInterval)timeDifference saltList:(NSArray *)saltList authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { [_context setGlobalTimeDifference:timeDifference]; if (saltList != nil) { - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId]; - if (authInfo != nil) - { - MTDatacenterAuthInfo *updatedAuthInfo = [authInfo mergeSaltSet:saltList forTimestamp:[_context globalTime]]; - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:updatedAuthInfo]; + 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]; + } + } } } @@ -2925,18 +2682,4 @@ static NSString *dumpHexString(NSData *data, int maxLength) { }]; } -- (void)bindToPersistentKey:(MTDatacenterAddress *)address { - [[MTProto managerQueue] dispatchOnQueue:^{ - MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain; - if (address.preferForMedia) { - tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia; - } - MTDatacenterAuthKey *effectiveTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType]; - - _bindingTempAuthKeyId = effectiveTempAuthKey.authKeyId; - _bindingTempAuthKeyContext = nil; - _mtState |= MTProtoStateBindingTempAuthKey; - }]; -} - @end diff --git a/submodules/MtProtoKit/Sources/MTProtoEngine.m b/submodules/MtProtoKit/Sources/MTProtoEngine.m new file mode 100644 index 0000000000..f48cc993cd --- /dev/null +++ b/submodules/MtProtoKit/Sources/MTProtoEngine.m @@ -0,0 +1,52 @@ +#import + +#import "Utils/MTQueueLocalObject.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MTProtoEngineImpl : NSObject { + MTQueue *_queue; + id _persistenceInterface; +} + +@end + +@implementation MTProtoEngineImpl + +- (instancetype)initWithQueue:(MTQueue *)queue persistenceInterface:(id)persistenceInterface { + self = [super init]; + if (self != nil) { + _queue = queue; + _persistenceInterface = persistenceInterface; + } + return self; +} + +@end + +@interface MTProtoEngine () { + MTQueue *_queue; + MTQueueLocalObject *_impl; +} + +@end + +@implementation MTProtoEngine + +- (instancetype)initWithPersistenceInterface:(id)persistenceInterface { + self = [super init]; + if (self != nil) { + _queue = [[MTQueue alloc] init]; + __auto_type queue = _queue; + _impl = [[MTQueueLocalObject alloc] initWithQueue:queue generator:^MTProtoEngineImpl *{ + return [[MTProtoEngineImpl alloc] initWithQueue:queue persistenceInterface:persistenceInterface]; + }]; + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/submodules/MtProtoKit/Sources/MTProtoInstance.m b/submodules/MtProtoKit/Sources/MTProtoInstance.m new file mode 100644 index 0000000000..ba5da46abf --- /dev/null +++ b/submodules/MtProtoKit/Sources/MTProtoInstance.m @@ -0,0 +1,48 @@ +#import + +#import +#import "Utils/MTQueueLocalObject.h" + +@interface MTProtoInstanceImpl : NSObject { + MTQueue *_queue; + MTProtoEngine *_engine; +} + +@end + +@implementation MTProtoInstanceImpl + +- (instancetype)initWithQueue:(MTQueue *)queue engine:(MTProtoEngine *)engine { + self = [super init]; + if (self != nil) { + _queue = queue; + _engine = engine; + } + return self; +} + +@end + +@interface MTProtoInstance () { + MTQueue *_queue; + MTQueueLocalObject *_impl; +} + +@end + +@implementation MTProtoInstance + +- (instancetype)initWithEngine:(MTProtoEngine *)engine { + self = [super init]; + if (self != nil) { + _queue = [[MTQueue alloc] init]; + __auto_type queue = _queue; + _impl = [[MTQueueLocalObject alloc] initWithQueue:queue generator:^MTProtoInstanceImpl *{ + return [[MTProtoInstanceImpl alloc] initWithQueue:queue engine:engine]; + }]; + } + return self; +} + +@end diff --git a/submodules/MtProtoKit/Sources/MTRequestMessageService.m b/submodules/MtProtoKit/Sources/MTRequestMessageService.m index 23f12dc625..fb85f6ff47 100644 --- a/submodules/MtProtoKit/Sources/MTRequestMessageService.m +++ b/submodules/MtProtoKit/Sources/MTRequestMessageService.m @@ -391,12 +391,12 @@ return currentData; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { NSMutableArray *messages = nil; NSMutableDictionary *requestInternalIdToMessageInternalId = nil; - bool requestsWillInitializeApi = _apiEnvironment != nil && ![_apiEnvironment.apiInitializationHash isEqualToString:[_context authInfoForDatacenterWithId:mtProto.datacenterId].authKeyAttributes[@"apiInitializationHash"]]; + bool requestsWillInitializeApi = _apiEnvironment != nil && ![_apiEnvironment.apiInitializationHash isEqualToString:[_context authInfoForDatacenterWithId:mtProto.datacenterId selector:authInfoSelector].authKeyAttributes[@"apiInitializationHash"]]; CFAbsoluteTime currentTime = MTAbsoluteSystemTime(); @@ -561,7 +561,7 @@ return nil; } -- (void)mtProto:(MTProto *)__unused mtProto receivedMessage:(MTIncomingMessage *)message +- (void)mtProto:(MTProto *)__unused mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if ([message.body isKindOfClass:[MTRpcResultMessage class]]) { @@ -610,13 +610,13 @@ { rpcError = [[MTRpcError alloc] initWithErrorCode:500 errorDescription:@"TL_PARSING_ERROR"]; [_context performBatchUpdates:^{ - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId]; + MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId selector:authInfoSelector]; NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:authInfo.authKeyAttributes]; authKeyAttributes[@"apiInitializationHash"] = @""; authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; - [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo]; + [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo selector:authInfoSelector]; }]; } } @@ -636,7 +636,7 @@ if (rpcResult != nil && request.requestContext.willInitializeApi) { - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId]; + MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId selector:authInfoSelector]; if (![_apiEnvironment.apiInitializationHash isEqualToString:authInfo.authKeyAttributes[@"apiInitializationHash"]]) { @@ -644,7 +644,7 @@ authKeyAttributes[@"apiInitializationHash"] = _apiEnvironment.apiInitializationHash; authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; - [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo]; + [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo selector:authInfoSelector]; } } @@ -726,13 +726,13 @@ { [_context performBatchUpdates:^ { - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId]; + MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId selector:authInfoSelector]; NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:authInfo.authKeyAttributes]; [authKeyAttributes removeObjectForKey:@"apiInitializationHash"]; authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; - [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo]; + [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo selector:authInfoSelector]; }]; } else if (rpcError.errorCode == 406) { if (_didReceiveSoftAuthResetError) { diff --git a/submodules/MtProtoKit/Sources/MTResendMessageService.m b/submodules/MtProtoKit/Sources/MTResendMessageService.m index 4e515ba39f..585ec29599 100644 --- a/submodules/MtProtoKit/Sources/MTResendMessageService.m +++ b/submodules/MtProtoKit/Sources/MTResendMessageService.m @@ -41,7 +41,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { if (_currentRequestMessageId == 0 || _currentRequestTransactionId == nil) { @@ -121,7 +121,7 @@ } } -- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message +- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if (message.messageId == _messageId) { diff --git a/submodules/MtProtoKit/Sources/MTTcpTransport.m b/submodules/MtProtoKit/Sources/MTTcpTransport.m index 6b4cc265f1..3b0883b3aa 100644 --- a/submodules/MtProtoKit/Sources/MTTcpTransport.m +++ b/submodules/MtProtoKit/Sources/MTTcpTransport.m @@ -747,7 +747,7 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0; }]; } -- (void)mtProto:(MTProto *)__unused mtProto receivedMessage:(MTIncomingMessage *)incomingMessage +- (void)mtProto:(MTProto *)__unused mtProto receivedMessage:(MTIncomingMessage *)incomingMessage authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if ([incomingMessage.body isKindOfClass:[MTPongMessage class]]) { diff --git a/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m b/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m index 6d8919c176..8672ed541d 100644 --- a/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m +++ b/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m @@ -45,7 +45,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo { if (_currentTransactionId == nil) { @@ -127,7 +127,7 @@ } } -- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message +- (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector { if ([message.body isKindOfClass:[MTFutureSaltsMessage class]] && ((MTFutureSaltsMessage *)message.body).requestMessageId == _currentMessageId) { diff --git a/submodules/MtProtoKit/Sources/Utils/MTQueueLocalObject.h b/submodules/MtProtoKit/Sources/Utils/MTQueueLocalObject.h new file mode 100644 index 0000000000..63165bd89f --- /dev/null +++ b/submodules/MtProtoKit/Sources/Utils/MTQueueLocalObject.h @@ -0,0 +1,14 @@ +#import + +@class MTQueue; + +NS_ASSUME_NONNULL_BEGIN + +@interface MTQueueLocalObject<__covariant T> : NSObject + +- (instancetype)initWithQueue:(MTQueue *)queue generator:(T(^)())generator; +- (void)with:(void (^)(T))f; + +@end + +NS_ASSUME_NONNULL_END diff --git a/submodules/MtProtoKit/Sources/Utils/MTQueueLocalObject.m b/submodules/MtProtoKit/Sources/Utils/MTQueueLocalObject.m new file mode 100644 index 0000000000..a84da57845 --- /dev/null +++ b/submodules/MtProtoKit/Sources/Utils/MTQueueLocalObject.m @@ -0,0 +1,56 @@ +#import "MTQueueLocalObject.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MTQueueLocalObjectHolder : NSObject + +@property (nonatomic, assign) CFTypeRef impl; + +@end + +@implementation MTQueueLocalObjectHolder + +@end + +@interface MTQueueLocalObject () { + MTQueue *_queue; + MTQueueLocalObjectHolder *_holder; +} + +@end + +@implementation MTQueueLocalObject + +- (instancetype)initWithQueue:(MTQueue *)queue generator:(id(^)())generator { + self = [super init]; + if (self != nil) { + _queue = queue; + _holder = [[MTQueueLocalObjectHolder alloc] init]; + __auto_type holder = _holder; + [queue dispatchOnQueue:^{ + id value = generator(); + holder.impl = CFBridgingRetain(value); + } synchronous:false]; + } + return self; +} + +- (void)dealloc { + __auto_type holder = _holder; + [_queue dispatchOnQueue:^{ + CFBridgingRelease(holder.impl); + } synchronous:false]; +} + +- (void)with:(void (^)(id))f { + __auto_type holder = _holder; + [_queue dispatchOnQueue:^{ + id value = (__bridge id)holder.impl; + f(value); + } synchronous:false]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/submodules/TelegramCore/Sources/Account.swift b/submodules/TelegramCore/Sources/Account.swift index 24194959ca..cad791bbc4 100644 --- a/submodules/TelegramCore/Sources/Account.swift +++ b/submodules/TelegramCore/Sources/Account.swift @@ -103,8 +103,8 @@ public class UnauthorizedAccount { datacenterIds.append(contentsOf: [4]) } for id in datacenterIds { - if network.context.authInfoForDatacenter(withId: id) == nil { - network.context.authInfoForDatacenter(withIdRequired: id, isCdn: false) + if network.context.authInfoForDatacenter(withId: id, selector: .persistent) == nil { + 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()) @@ -243,7 +243,7 @@ public func accountWithId(accountManager: AccountManager, networkArguments: Netw let backupState = AuthorizedAccountState(isTestingEnvironment: beginWithTestingEnvironment, masterDatacenterId: backupData.masterDatacenterId, peerId: PeerId(backupData.peerId), state: nil) state = backupState let dict = NSMutableDictionary() - dict.setObject(MTDatacenterAuthInfo(authKey: backupData.masterDatacenterKey, authKeyId: backupData.masterDatacenterKeyId, saltSet: [], authKeyAttributes: [:], mainTempAuthKey: nil, mediaTempAuthKey: nil), forKey: backupData.masterDatacenterId as NSNumber) + dict.setObject(MTDatacenterAuthInfo(authKey: backupData.masterDatacenterKey, authKeyId: backupData.masterDatacenterKeyId, saltSet: [], authKeyAttributes: [:]), forKey: backupData.masterDatacenterId as NSNumber) let data = NSKeyedArchiver.archivedData(withRootObject: dict) transaction.setState(backupState) transaction.setKeychainEntry(data, forKey: "persistent:datacenterAuthInfoById") @@ -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/SynchronizePeerReadState.swift b/submodules/TelegramCore/Sources/SynchronizePeerReadState.swift index 5f55a1bce3..9817e3c28b 100644 --- a/submodules/TelegramCore/Sources/SynchronizePeerReadState.swift +++ b/submodules/TelegramCore/Sources/SynchronizePeerReadState.swift @@ -34,12 +34,18 @@ private func inputSecretChat(postbox: Postbox, peerId: PeerId) -> Signal take(1) } -private func dialogTopMessage(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<(Int32, Int32), PeerReadStateValidationError> { +private func dialogTopMessage(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<(Int32, Int32)?, PeerReadStateValidationError> { return inputPeer(postbox: postbox, peerId: peerId) - |> mapToSignal { inputPeer -> Signal<(Int32, Int32), PeerReadStateValidationError> in + |> mapToSignal { inputPeer -> Signal<(Int32, Int32)?, PeerReadStateValidationError> in return network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: Int32.max, offsetDate: Int32.max, addOffset: 0, limit: 1, maxId: Int32.max, minId: 1, hash: 0)) - |> retryRequest - |> mapToSignalPromotingError { result -> Signal<(Int32, Int32), PeerReadStateValidationError> in + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignalPromotingError { result -> Signal<(Int32, Int32)?, PeerReadStateValidationError> in + guard let result = result else { + return .single(nil) + } let apiMessages: [Api.Message] switch result { case let .channelMessages(_, _, _, messages, _, _): @@ -60,14 +66,18 @@ private func dialogTopMessage(network: Network, postbox: Postbox, peerId: PeerId } } -private func dialogReadState(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> { +private func dialogReadState(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<(PeerReadState, PeerReadStateMarker)?, PeerReadStateValidationError> { return dialogTopMessage(network: network, postbox: postbox, peerId: peerId) - |> mapToSignal { topMessage -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> in + |> mapToSignal { topMessage -> Signal<(PeerReadState, PeerReadStateMarker)?, PeerReadStateValidationError> in + guard let _ = topMessage else { + return .single(nil) + } + return inputPeer(postbox: postbox, peerId: peerId) - |> mapToSignal { inputPeer -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> in + |> mapToSignal { inputPeer -> Signal<(PeerReadState, PeerReadStateMarker)?, PeerReadStateValidationError> in return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(peer: inputPeer)])) |> retryRequest - |> mapToSignalPromotingError { result -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> in + |> mapToSignalPromotingError { result -> Signal<(PeerReadState, PeerReadStateMarker)?, PeerReadStateValidationError> in switch result { case let .peerDialogs(dialogs, _, _, _, state): if let dialog = dialogs.filter({ $0.peerId == peerId }).first { @@ -150,10 +160,16 @@ enum PeerReadStateValidationError { private func validatePeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Signal { let readStateWithInitialState = dialogReadState(network: network, postbox: postbox, peerId: peerId) - |> map { ($0.0, $0.1) } let maybeAppliedReadState = readStateWithInitialState - |> mapToSignal { (readState, finalMarker) -> Signal in + |> mapToSignal { data -> Signal in + guard let (readState, _) = data else { + return postbox.transaction { transaction -> Void in + transaction.confirmSynchronizedIncomingReadState(peerId) + } + |> castError(PeerReadStateValidationError.self) + |> ignoreValues + } return stateManager.addCustomOperation(postbox.transaction { transaction -> PeerReadStateValidationError? in if let currentReadState = transaction.getCombinedPeerReadState(peerId) { loop: for (namespace, currentState) in currentReadState.states { 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) } diff --git a/submodules/TelegramUI/Sources/ManageSharedAccountInfo.swift b/submodules/TelegramUI/Sources/ManageSharedAccountInfo.swift index 49ee068a3a..396a494187 100644 --- a/submodules/TelegramUI/Sources/ManageSharedAccountInfo.swift +++ b/submodules/TelegramUI/Sources/ManageSharedAccountInfo.swift @@ -22,7 +22,7 @@ private func accountInfo(account: Account) -> Signal var datacenters: [Int32: AccountDatacenterInfo] = [:] for nId in context.knownDatacenterIds() { if let id = nId as? Int { - if let authInfo = context.authInfoForDatacenter(withId: id), let authKey = authInfo.authKey { + if let authInfo = context.authInfoForDatacenter(withId: id, selector: .persistent), let authKey = authInfo.authKey { let transportScheme = context.chooseTransportSchemeForConnection(toDatacenterId: id, schemes: context.transportSchemesForDatacenter(withId: id, media: true, enforceMedia: false, isProxy: false)) var addressList: [AccountDatacenterAddress] = [] if let transportScheme = transportScheme, let address = transportScheme.address, let host = address.host {