Merge branch 'modern-networking'

This commit is contained in:
Ali 2020-09-10 21:10:39 +01:00
commit ec8519c25e
33 changed files with 916 additions and 750 deletions

View File

@ -3,10 +3,10 @@ load("//Config:buck_rule_macros.bzl", "static_library", "framework", "glob_map",
framework( framework(
name = "MtProtoKit", name = "MtProtoKit",
srcs = glob([ srcs = glob([
"Sources/*.m", "Sources/**/*.m",
]), ]),
headers = glob([ headers = glob([
"Sources/*.h", "Sources/**/*.h",
]), ]),
exported_headers = glob([ exported_headers = glob([
"PublicHeaders/**/*.h", "PublicHeaders/**/*.h",

View File

@ -4,8 +4,8 @@ objc_library(
enable_modules = True, enable_modules = True,
module_name = "MtProtoKit", module_name = "MtProtoKit",
srcs = glob([ srcs = glob([
"Sources/*.m", "Sources/**/*.m",
"Sources/*.h", "Sources/**/*.h",
]), ]),
hdrs = glob([ hdrs = glob([
"PublicHeaders/**/*.h", "PublicHeaders/**/*.h",

View File

@ -0,0 +1,9 @@
#import <Foundation/Foundation.h>
#import <MtProtoKit/MTMessageService.h>
#import <MtProtoKit/MTDatacenterAuthInfo.h>
@interface MTBindKeyMessageService : NSObject <MTMessageService>
- (instancetype)initWithPersistentKey:(MTDatacenterAuthKey *)persistentKey ephemeralKey:(MTDatacenterAuthKey *)ephemeralKey completion:(void (^)(bool))completion;
@end

View File

@ -20,7 +20,7 @@
@optional @optional
- (void)contextDatacenterAddressSetUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet; - (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)contextDatacenterAuthTokenUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authToken:(id)authToken;
- (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId shouldReset:(bool)shouldReset; - (void)contextDatacenterTransportSchemesUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId shouldReset:(bool)shouldReset;
- (void)contextIsPasswordRequiredUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId; - (void)contextIsPasswordRequiredUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId;
@ -49,6 +49,7 @@
@property (nonatomic, strong, readonly) MTApiEnvironment *apiEnvironment; @property (nonatomic, strong, readonly) MTApiEnvironment *apiEnvironment;
@property (nonatomic, readonly) bool isTestingEnvironment; @property (nonatomic, readonly) bool isTestingEnvironment;
@property (nonatomic, readonly) bool useTempAuthKeys; @property (nonatomic, readonly) bool useTempAuthKeys;
@property (nonatomic, readonly) int32_t tempKeyExpiration;
+ (int32_t)fixedTimeDifference; + (int32_t)fixedTimeDifference;
+ (void)setFixedTimeDifference:(int32_t)fixedTimeDifference; + (void)setFixedTimeDifference:(int32_t)fixedTimeDifference;
@ -73,7 +74,7 @@
- (void)updateAddressSetForDatacenterWithId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet forceUpdateSchemes:(bool)forceUpdateSchemes; - (void)updateAddressSetForDatacenterWithId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)addressSet forceUpdateSchemes:(bool)forceUpdateSchemes;
- (void)addAddressForDatacenterWithId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address; - (void)addAddressForDatacenterWithId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address;
- (void)updateTransportSchemeForDatacenterWithId:(NSInteger)datacenterId transportScheme:(MTTransportScheme *)transportScheme media:(bool)media isProxy:(bool)isProxy; - (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)isPasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId;
- (bool)updatePasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId required:(bool)required; - (bool)updatePasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId required:(bool)required;
@ -95,7 +96,7 @@
- (void)transportSchemeForDatacenterWithIdRequired:(NSInteger)datacenterId media:(bool)media; - (void)transportSchemeForDatacenterWithIdRequired:(NSInteger)datacenterId media:(bool)media;
- (void)invalidateTransportSchemeForDatacenterId:(NSInteger)datacenterId transportScheme:(MTTransportScheme *)transportScheme isProbablyHttp:(bool)isProbablyHttp 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; - (void)revalidateTransportSchemeForDatacenterId:(NSInteger)datacenterId transportScheme:(MTTransportScheme *)transportScheme media:(bool)media;
- (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId; - (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId selector:(MTDatacenterAuthInfoSelector)selector;
- (NSArray<NSDictionary *> *)publicKeysForDatacenterWithId:(NSInteger)datacenterId; - (NSArray<NSDictionary *> *)publicKeysForDatacenterWithId:(NSInteger)datacenterId;
- (void)updatePublicKeysForDatacenterWithId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys; - (void)updatePublicKeysForDatacenterWithId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys;
@ -107,8 +108,7 @@
- (void)updateAuthTokenForDatacenterWithId:(NSInteger)datacenterId authToken:(id)authToken; - (void)updateAuthTokenForDatacenterWithId:(NSInteger)datacenterId authToken:(id)authToken;
- (void)addressSetForDatacenterWithIdRequired:(NSInteger)datacenterId; - (void)addressSetForDatacenterWithIdRequired:(NSInteger)datacenterId;
- (void)authInfoForDatacenterWithIdRequired:(NSInteger)datacenterId isCdn:(bool)isCdn; - (void)authInfoForDatacenterWithIdRequired:(NSInteger)datacenterId isCdn:(bool)isCdn selector:(MTDatacenterAuthInfoSelector)selector;
- (void)tempAuthKeyForDatacenterWithIdRequired:(NSInteger)datacenterId keyType:(MTDatacenterAuthTempKeyType)keyType;
- (void)authTokenForDatacenterWithIdRequired:(NSInteger)datacenterId authToken:(id)authToken masterDatacenterId:(NSInteger)masterDatacenterId; - (void)authTokenForDatacenterWithIdRequired:(NSInteger)datacenterId authToken:(id)authToken masterDatacenterId:(NSInteger)masterDatacenterId;
- (void)reportProblemsWithDatacenterAddressForId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address; - (void)reportProblemsWithDatacenterAddressForId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address;

View File

@ -4,23 +4,12 @@
@class MTContext; @class MTContext;
@class MTDatacenterAuthAction;
@protocol MTDatacenterAuthActionDelegate <NSObject>
- (void)datacenterAuthActionCompleted:(MTDatacenterAuthAction *)action;
@end
@interface MTDatacenterAuthAction : NSObject @interface MTDatacenterAuthAction : NSObject
@property (nonatomic, readonly) bool tempAuth; - (instancetype)initWithAuthKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector isCdn:(bool)isCdn completion:(void (^)(MTDatacenterAuthAction *, bool))completion;
@property (nonatomic, weak) id<MTDatacenterAuthActionDelegate> delegate;
@property (nonatomic, copy) void (^completedWithResult)(bool);
- (instancetype)initWithTempAuth:(bool)tempAuth tempAuthKeyType:(MTDatacenterAuthTempKeyType)tempAuthKeyType bindKey:(MTDatacenterAuthKey *)bindKey; - (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId;
- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId isCdn:(bool)isCdn;
- (void)cancel; - (void)cancel;
@end @end

View File

@ -1,10 +1,5 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, MTDatacenterAuthTempKeyType) {
MTDatacenterAuthTempKeyTypeMain,
MTDatacenterAuthTempKeyTypeMedia
};
@interface MTDatacenterAuthKey: NSObject <NSCoding> @interface MTDatacenterAuthKey: NSObject <NSCoding>
@property (nonatomic, strong, readonly) NSData *authKey; @property (nonatomic, strong, readonly) NSData *authKey;
@ -15,24 +10,24 @@ typedef NS_ENUM(NSUInteger, MTDatacenterAuthTempKeyType) {
@end @end
typedef NS_ENUM(int64_t, MTDatacenterAuthInfoSelector) {
MTDatacenterAuthInfoSelectorPersistent = 0,
MTDatacenterAuthInfoSelectorEphemeralMain,
MTDatacenterAuthInfoSelectorEphemeralMedia
};
@interface MTDatacenterAuthInfo : NSObject <NSCoding> @interface MTDatacenterAuthInfo : NSObject <NSCoding>
@property (nonatomic, strong, readonly) NSData *authKey; @property (nonatomic, strong, readonly) NSData *authKey;
@property (nonatomic, readonly) int64_t authKeyId; @property (nonatomic, readonly) int64_t authKeyId;
@property (nonatomic, strong, readonly) NSArray *saltSet; @property (nonatomic, strong, readonly) NSArray *saltSet;
@property (nonatomic, strong, readonly) NSDictionary *authKeyAttributes; @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;
- (instancetype)initWithAuthKey:(NSData *)authKey authKeyId:(int64_t)authKeyId saltSet:(NSArray *)saltSet authKeyAttributes:(NSDictionary *)authKeyAttributes mainTempAuthKey:(MTDatacenterAuthKey *)mainTempAuthKey mediaTempAuthKey:(MTDatacenterAuthKey *)mediaTempAuthKey;
- (int64_t)authSaltForMessageId:(int64_t)messageId; - (int64_t)authSaltForMessageId:(int64_t)messageId;
- (MTDatacenterAuthInfo *)mergeSaltSet:(NSArray *)updatedSaltSet forTimestamp:(NSTimeInterval)timestamp; - (MTDatacenterAuthInfo *)mergeSaltSet:(NSArray *)updatedSaltSet forTimestamp:(NSTimeInterval)timestamp;
- (MTDatacenterAuthInfo *)withUpdatedAuthKeyAttributes:(NSDictionary *)authKeyAttributes; - (MTDatacenterAuthInfo *)withUpdatedAuthKeyAttributes:(NSDictionary *)authKeyAttributes;
- (MTDatacenterAuthKey *)tempAuthKeyWithType:(MTDatacenterAuthTempKeyType)type;
- (MTDatacenterAuthInfo *)withUpdatedTempAuthKeyWithType:(MTDatacenterAuthTempKeyType)type key:(MTDatacenterAuthKey *)key;
@end @end

View File

@ -1,11 +1,13 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <MtProtoKit/MTDatacenterAuthInfo.h>
@class MTProto; @class MTProto;
@class MTIncomingMessage; @class MTIncomingMessage;
@class MTMessageTransaction; @class MTMessageTransaction;
@class MTApiEnvironment; @class MTApiEnvironment;
@class MTSessionInfo;
@protocol MTMessageService <NSObject> @protocol MTMessageService <NSObject>
@ -15,10 +17,10 @@
- (void)mtProtoDidAddService:(MTProto *)mtProto; - (void)mtProtoDidAddService:(MTProto *)mtProto;
- (void)mtProtoDidRemoveService:(MTProto *)mtProto; - (void)mtProtoDidRemoveService:(MTProto *)mtProto;
- (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys; - (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys;
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto; - (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo;
- (void)mtProtoDidChangeSession:(MTProto *)mtProto; - (void)mtProtoDidChangeSession:(MTProto *)mtProto;
- (void)mtProtoServerDidChangeSession:(MTProto *)mtProto firstValidMessageId:(int64_t)firstValidMessageId otherValidMessageIds:(NSArray *)otherValidMessageIds; - (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 receivedQuickAck:(int32_t)quickAckId;
- (void)mtProto:(MTProto *)mtProto transactionsMayHaveFailed:(NSArray *)transactionIds; - (void)mtProto:(MTProto *)mtProto transactionsMayHaveFailed:(NSArray *)transactionIds;
- (void)mtProtoAllTransactionsMayHaveFailed:(MTProto *)mtProto; - (void)mtProtoAllTransactionsMayHaveFailed:(MTProto *)mtProto;

View File

@ -71,4 +71,6 @@
- (void)_messageResendRequestFailed:(int64_t)messageId; - (void)_messageResendRequestFailed:(int64_t)messageId;
+ (NSData *)_manuallyEncryptedMessage:(NSData *)preparedData messageId:(int64_t)messageId authKey:(MTDatacenterAuthKey *)authKey;
@end @end

View File

@ -0,0 +1,13 @@
#import <Foundation/Foundation.h>
#import <MtProtoKit/MTProtoPersistenceInterface.h>
NS_ASSUME_NONNULL_BEGIN
@interface MTProtoEngine : NSObject
- (instancetype)initWithPersistenceInterface:(id<MTProtoPersistenceInterface>)persistenceInterface;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import <MtProtoKit/MTProtoEngine.h>
NS_ASSUME_NONNULL_BEGIN
@interface MTProtoInstance : NSObject
- (instancetype)initWithEngine:(MTProtoEngine *)engine;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,14 @@
#import <Foundation/Foundation.h>
@class MTSignal;
NS_ASSUME_NONNULL_BEGIN
@protocol MTProtoPersistenceInterface <NSObject>
- (MTSignal *)get:(NSData *)key;
- (void)set:(NSData *)key value:(NSData *)value;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,156 @@
#import <MtProtoKit/MTBindKeyMessageService.h>
#import <MtProtoKit/MTTime.h>
#import <MtProtoKit/MTContext.h>
#import <MtProtoKit/MTProto.h>
#import <MtProtoKit/MTSerialization.h>
#import <MtProtoKit/MTOutgoingMessage.h>
#import <MtProtoKit/MTIncomingMessage.h>
#import <MtProtoKit/MTPreparedMessage.h>
#import <MtProtoKit/MTMessageTransaction.h>
#import <MtProtoKit/MTDatacenterSaltInfo.h>
#import <MtProtoKit/MTSessionInfo.h>
#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

View File

@ -114,7 +114,34 @@
@end @end
@interface MTContext () <MTDiscoverDatacenterAddressActionDelegate, MTDatacenterAuthActionDelegate, MTDatacenterTransferAuthActionDelegate> 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 () <MTDiscoverDatacenterAddressActionDelegate, MTDatacenterTransferAuthActionDelegate>
{ {
int64_t _uniqueId; int64_t _uniqueId;
@ -127,7 +154,7 @@
NSMutableDictionary<NSNumber *, NSMutableDictionary<MTDatacenterAddress *, MTTransportSchemeStats *> *> *_transportSchemeStats; NSMutableDictionary<NSNumber *, NSMutableDictionary<MTDatacenterAddress *, MTTransportSchemeStats *> *> *_transportSchemeStats;
MTTimer *_schemeStatsSyncTimer; MTTimer *_schemeStatsSyncTimer;
NSMutableDictionary *_datacenterAuthInfoById; NSMutableDictionary<NSNumber *, MTDatacenterAuthInfo *> *_datacenterAuthInfoById;
NSMutableDictionary *_datacenterPublicKeysById; NSMutableDictionary *_datacenterPublicKeysById;
@ -138,8 +165,7 @@
MTSignal *_discoverBackupAddressListSignal; MTSignal *_discoverBackupAddressListSignal;
NSMutableDictionary *_discoverDatacenterAddressActions; NSMutableDictionary *_discoverDatacenterAddressActions;
NSMutableDictionary *_datacenterAuthActions; NSMutableDictionary<NSNumber *, MTDatacenterAuthAction *> *_datacenterAuthActions;
NSMutableDictionary *_datacenterTempAuthActions;
NSMutableDictionary *_datacenterTransferAuthActions; NSMutableDictionary *_datacenterTransferAuthActions;
NSMutableDictionary<NSNumber *, NSNumber *> *_datacenterCheckKeyRemovedActionTimestamps; NSMutableDictionary<NSNumber *, NSNumber *> *_datacenterCheckKeyRemovedActionTimestamps;
@ -201,6 +227,11 @@ static int32_t fixedTimeDifferenceValue = 0;
_apiEnvironment = apiEnvironment; _apiEnvironment = apiEnvironment;
_isTestingEnvironment = isTestingEnvironment; _isTestingEnvironment = isTestingEnvironment;
_useTempAuthKeys = useTempAuthKeys; _useTempAuthKeys = useTempAuthKeys;
#if DEBUG
_tempKeyExpiration = 1 * 60 * 60;
#else
_tempKeyExpiration = 1 * 60 * 60;
#endif
_datacenterSeedAddressSetById = [[NSMutableDictionary alloc] init]; _datacenterSeedAddressSetById = [[NSMutableDictionary alloc] init];
@ -218,7 +249,6 @@ static int32_t fixedTimeDifferenceValue = 0;
_discoverDatacenterAddressActions = [[NSMutableDictionary alloc] init]; _discoverDatacenterAddressActions = [[NSMutableDictionary alloc] init];
_datacenterAuthActions = [[NSMutableDictionary alloc] init]; _datacenterAuthActions = [[NSMutableDictionary alloc] init];
_datacenterTempAuthActions = [[NSMutableDictionary alloc] init];
_datacenterTransferAuthActions = [[NSMutableDictionary alloc] init]; _datacenterTransferAuthActions = [[NSMutableDictionary alloc] init];
_datacenterCheckKeyRemovedActionTimestamps = [[NSMutableDictionary alloc] init]; _datacenterCheckKeyRemovedActionTimestamps = [[NSMutableDictionary alloc] init];
_datacenterCheckKeyRemovedActions = [[NSMutableDictionary alloc] init]; _datacenterCheckKeyRemovedActions = [[NSMutableDictionary alloc] init];
@ -258,9 +288,6 @@ static int32_t fixedTimeDifferenceValue = 0;
NSDictionary *datacenterAuthActions = _datacenterAuthActions; NSDictionary *datacenterAuthActions = _datacenterAuthActions;
_datacenterAuthActions = nil; _datacenterAuthActions = nil;
NSDictionary *datacenterTempAuthActions = _datacenterTempAuthActions;
_datacenterTempAuthActions = nil;
NSDictionary *discoverDatacenterAddressActions = _discoverDatacenterAddressActions; NSDictionary *discoverDatacenterAddressActions = _discoverDatacenterAddressActions;
_discoverDatacenterAddressActions = nil; _discoverDatacenterAddressActions = nil;
@ -284,17 +311,9 @@ static int32_t fixedTimeDifferenceValue = 0;
[action cancel]; [action cancel];
} }
for (NSNumber *nDatacenterId in datacenterAuthActions) for (NSNumber *key in datacenterAuthActions)
{ {
MTDatacenterAuthAction *action = datacenterAuthActions[nDatacenterId]; MTDatacenterAuthAction *action = datacenterAuthActions[key];
action.delegate = nil;
[action cancel];
}
for (NSNumber *nDatacenterId in datacenterTempAuthActions)
{
MTDatacenterAuthAction *action = datacenterTempAuthActions[nDatacenterId];
action.delegate = nil;
[action cancel]; [action cancel];
} }
@ -360,6 +379,14 @@ static int32_t fixedTimeDifferenceValue = 0;
NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"]; NSDictionary *datacenterAuthInfoById = [keychain objectForKey:@"datacenterAuthInfoById" group:@"persistent"];
if (datacenterAuthInfoById != nil) { if (datacenterAuthInfoById != nil) {
_datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById]; _datacenterAuthInfoById = [[NSMutableDictionary alloc] initWithDictionary:datacenterAuthInfoById];
#if DEBUG
/*NSArray<NSNumber *> *keys = [_datacenterAuthInfoById allKeys];
for (NSNumber *key in keys) {
if (parseAuthInfoMapKeyInteger(key).selector != MTDatacenterAuthInfoSelectorPersistent) {
[_datacenterAuthInfoById removeObjectForKey:key];
}
}*/
#endif
} }
NSDictionary *datacenterPublicKeysById = [keychain objectForKey:@"datacenterPublicKeysById" group:@"ephemeral"]; 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:^ [[MTContext contextQueue] dispatchOnQueue:^
{ {
if (datacenterId != 0) if (datacenterId != 0)
{ {
if (MTLogEnabled()) { NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector);
MTLog(@"[MTContext#%x: auth info updated for %d to %@]", (int)self, datacenterId, authInfo);
} bool wasNil = _datacenterAuthInfoById[infoKey] == nil;
if (authInfo != nil) { if (authInfo != nil) {
_datacenterAuthInfoById[@(datacenterId)] = authInfo; _datacenterAuthInfoById[infoKey] = authInfo;
} else { } 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"]; [_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"];
NSArray *currentListeners = [[NSArray alloc] initWithArray:_changeListeners]; NSArray *currentListeners = [[NSArray alloc] initWithArray:_changeListeners];
for (id<MTContextChangeListener> listener in currentListeners) for (id<MTContextChangeListener> listener in currentListeners)
{ {
if ([listener respondsToSelector:@selector(contextDatacenterAuthInfoUpdated:datacenterId:authInfo:)]) if ([listener respondsToSelector:@selector(contextDatacenterAuthInfoUpdated:datacenterId:authInfo:selector:)])
[listener contextDatacenterAuthInfoUpdated:self datacenterId:datacenterId authInfo:authInfo]; [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; return results;
} }
- (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId { - (MTDatacenterAuthInfo *)authInfoForDatacenterWithId:(NSInteger)datacenterId selector:(MTDatacenterAuthInfoSelector)selector {
__block MTDatacenterAuthInfo *result = nil; __block MTDatacenterAuthInfo *result = nil;
[[MTContext contextQueue] dispatchOnQueue:^{ [[MTContext contextQueue] dispatchOnQueue:^{
result = _datacenterAuthInfoById[@(datacenterId)]; NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector);
result = _datacenterAuthInfoById[infoKey];
} synchronous:true]; } synchronous:true];
return result; 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:^ [[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]; __weak MTContext *weakSelf = self;
authAction.delegate = self; MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithAuthKeyInfoSelector:selector isCdn:isCdn completion:^(MTDatacenterAuthAction *action, __unused bool success) {
_datacenterAuthActions[@(datacenterId)] = authAction; [[MTContext contextQueue] dispatchOnQueue:^{
[authAction execute:self datacenterId:datacenterId isCdn:isCdn]; __strong MTContext *strongSelf = weakSelf;
} if (strongSelf == nil) {
}]; return;
} }
- (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];
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; break;
} }
} default: {
} else { [authAction execute:self datacenterId:datacenterId];
for (NSNumber *nDatacenterId in _datacenterAuthActions) {
if (_datacenterAuthActions[nDatacenterId] == action) {
[_datacenterAuthActions removeObjectForKey:nDatacenterId];
break; break;
} }
} }
@ -1357,21 +1398,11 @@ static int32_t fixedTimeDifferenceValue = 0;
- (void)updatePeriodicTasks - (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 { - (void)checkIfLoggedOut:(NSInteger)datacenterId {
[[MTContext contextQueue] dispatchOnQueue:^{ [[MTContext contextQueue] dispatchOnQueue:^{
MTDatacenterAuthInfo *authInfo = [self authInfoForDatacenterWithId:datacenterId]; MTDatacenterAuthInfo *authInfo = [self authInfoForDatacenterWithId:datacenterId selector:MTDatacenterAuthInfoSelectorPersistent];
if (authInfo == nil || authInfo.authKey == nil) { if (authInfo == nil || authInfo.authKey == nil) {
return; return;
} }
@ -1382,7 +1413,7 @@ static int32_t fixedTimeDifferenceValue = 0;
_datacenterCheckKeyRemovedActionTimestamps[@(datacenterId)] = currentTimestamp; _datacenterCheckKeyRemovedActionTimestamps[@(datacenterId)] = currentTimestamp;
[_datacenterCheckKeyRemovedActions[@(datacenterId)] dispose]; [_datacenterCheckKeyRemovedActions[@(datacenterId)] dispose];
__weak MTContext *weakSelf = self; __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:^{ [[MTContext contextQueue] dispatchOnQueue:^{
__strong MTContext *strongSelf = weakSelf; __strong MTContext *strongSelf = weakSelf;
if (strongSelf == nil) { if (strongSelf == nil) {

View File

@ -12,13 +12,15 @@
#import <MtProtoKit/MTSignal.h> #import <MtProtoKit/MTSignal.h>
#import <MtProtoKit/MTDatacenterAuthMessageService.h> #import <MtProtoKit/MTDatacenterAuthMessageService.h>
#import <MtProtoKit/MTRequestMessageService.h> #import <MtProtoKit/MTRequestMessageService.h>
#import <MtProtoKit/MTBindKeyMessageService.h>
#import "MTBuffer.h" #import "MTBuffer.h"
@interface MTDatacenterAuthAction () <MTDatacenterAuthMessageServiceDelegate> @interface MTDatacenterAuthAction () <MTDatacenterAuthMessageServiceDelegate>
{ {
void (^_completion)(MTDatacenterAuthAction *, bool);
bool _isCdn; bool _isCdn;
MTDatacenterAuthTempKeyType _tempAuthKeyType; MTDatacenterAuthInfoSelector _authKeyInfoSelector;
MTDatacenterAuthKey *_bindKey;
NSInteger _datacenterId; NSInteger _datacenterId;
__weak MTContext *_context; __weak MTContext *_context;
@ -26,71 +28,61 @@
bool _awaitingAddresSetUpdate; bool _awaitingAddresSetUpdate;
MTProto *_authMtProto; MTProto *_authMtProto;
MTProto *_bindMtProto; MTProto *_bindMtProto;
MTMetaDisposable *_verifyDisposable;
} }
@end @end
@implementation MTDatacenterAuthAction @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]; self = [super init];
if (self != nil) { if (self != nil) {
_tempAuth = tempAuth; _authKeyInfoSelector = authKeyInfoSelector;
_tempAuthKeyType = tempAuthKeyType; _isCdn = isCdn;
_bindKey = bindKey; _completion = [completion copy];
_verifyDisposable = [[MTMetaDisposable alloc] init];
} }
return self; return self;
} }
- (void)dealloc - (void)dealloc {
{
[self cleanup]; [self cleanup];
} }
- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId isCdn:(bool)isCdn - (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId {
{
_datacenterId = datacenterId; _datacenterId = datacenterId;
_context = context; _context = context;
_isCdn = isCdn;
if (_datacenterId != 0 && context != nil) if (_datacenterId != 0 && context != nil)
{ {
bool alreadyCompleted = false; bool alreadyCompleted = false;
MTDatacenterAuthInfo *currentAuthInfo = [context authInfoForDatacenterWithId:_datacenterId];
if (currentAuthInfo != nil && _bindKey == nil) { MTDatacenterAuthInfo *currentAuthInfo = [context authInfoForDatacenterWithId:_datacenterId selector:_authKeyInfoSelector];
if (_tempAuth) { if (currentAuthInfo != nil) {
if ([currentAuthInfo tempAuthKeyWithType:_tempAuthKeyType] != nil) { alreadyCompleted = true;
alreadyCompleted = true;
}
} else {
alreadyCompleted = true;
}
} }
if (alreadyCompleted) { if (alreadyCompleted) {
[self complete]; [self complete];
} else { } else {
_authMtProto = [[MTProto alloc] initWithContext:context datacenterId:_datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0]; _authMtProto = [[MTProto alloc] initWithContext:context datacenterId:_datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0];
_authMtProto.cdn = isCdn; _authMtProto.cdn = _isCdn;
_authMtProto.useUnauthorizedMode = true; _authMtProto.useUnauthorizedMode = true;
if (_tempAuth) { bool tempAuth = false;
switch (_tempAuthKeyType) { switch (_authKeyInfoSelector) {
case MTDatacenterAuthTempKeyTypeMain: case MTDatacenterAuthInfoSelectorEphemeralMain:
_authMtProto.media = false; tempAuth = true;
break; _authMtProto.media = false;
case MTDatacenterAuthTempKeyTypeMedia: break;
_authMtProto.media = true; case MTDatacenterAuthInfoSelectorEphemeralMedia:
_authMtProto.enforceMedia = true; tempAuth = true;
break; _authMtProto.media = true;
default: _authMtProto.enforceMedia = true;
break; break;
} default:
break;
} }
MTDatacenterAuthMessageService *authService = [[MTDatacenterAuthMessageService alloc] initWithContext:context tempAuth:_tempAuth]; MTDatacenterAuthMessageService *authService = [[MTDatacenterAuthMessageService alloc] initWithContext:context tempAuth:tempAuth];
authService.delegate = self; authService.delegate = self;
[_authMtProto addMessageService:authService]; [_authMtProto addMessageService:authService];
} }
@ -104,45 +96,71 @@
} }
- (void)completeWithAuthKey:(MTDatacenterAuthKey *)authKey timestamp:(int64_t)timestamp { - (void)completeWithAuthKey:(MTDatacenterAuthKey *)authKey timestamp:(int64_t)timestamp {
if (_tempAuth) { if (MTLogEnabled()) {
MTContext *mainContext = _context; MTLog(@"[MTDatacenterAuthAction#%p@%p: completeWithAuthKey %lld selector %d]", self, _context, authKey.authKeyId, _authKeyInfoSelector);
if (mainContext != nil) { }
if (_bindKey != nil) {
_bindMtProto = [[MTProto alloc] initWithContext:mainContext datacenterId:_datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0]; switch (_authKeyInfoSelector) {
_bindMtProto.cdn = false; case MTDatacenterAuthInfoSelectorPersistent: {
_bindMtProto.useUnauthorizedMode = false; 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];
_bindMtProto.useTempAuthKeys = true;
__weak MTDatacenterAuthAction *weakSelf = self; MTContext *context = _context;
_bindMtProto.tempAuthKeyBindingResultUpdated = ^(bool success) { [context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo selector:_authKeyInfoSelector];
__strong MTDatacenterAuthAction *strongSelf = weakSelf; [self complete];
if (strongSelf == nil) { }
return; 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) { __weak MTDatacenterAuthAction *weakSelf = self;
strongSelf->_completedWithResult(success); [_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) {
_bindMtProto.useExplicitAuthKey = authKey; return;
[_bindMtProto resume]; }
} else { [strongSelf->_bindMtProto stop];
MTContext *context = _context;
[context performBatchUpdates:^{ if (success) {
MTDatacenterAuthInfo *authInfo = [context authInfoForDatacenterWithId:_datacenterId]; 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];
if (authInfo != nil) {
authInfo = [authInfo withUpdatedTempAuthKeyWithType:_tempAuthKeyType key:authKey]; [strongSelf->_context updateAuthInfoForDatacenterWithId:strongSelf->_datacenterId authInfo:authInfo selector:strongSelf->_authKeyInfoSelector];
[context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo];
} [strongSelf complete];
}]; } else {
[self complete]; [strongSelf fail];
}
}]];
[_bindMtProto resume];
}
} }
} }
} else { break;
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];
default:
MTContext *context = _context; assert(false);
[context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo]; break;
[self complete];
} }
} }
@ -153,7 +171,10 @@
[authMtProto stop]; [authMtProto stop];
[_verifyDisposable dispose]; MTProto *bindMtProto = _bindMtProto;
_bindMtProto = nil;
[bindMtProto stop];
} }
- (void)cancel - (void)cancel
@ -162,18 +183,17 @@
[self fail]; [self fail];
} }
- (void)complete - (void)complete {
{ if (_completion) {
id<MTDatacenterAuthActionDelegate> delegate = _delegate; _completion(self, true);
if ([delegate respondsToSelector:@selector(datacenterAuthActionCompleted:)]) }
[delegate datacenterAuthActionCompleted:self];
} }
- (void)fail - (void)fail
{ {
id<MTDatacenterAuthActionDelegate> delegate = _delegate; if (_completion) {
if ([delegate respondsToSelector:@selector(datacenterAuthActionCompleted:)]) _completion(self, false);
[delegate datacenterAuthActionCompleted:self]; }
} }
@end @end

View File

@ -27,7 +27,7 @@
@implementation MTDatacenterAuthInfo @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]; self = [super init];
if (self != nil) if (self != nil)
@ -36,8 +36,6 @@
_authKeyId = authKeyId; _authKeyId = authKeyId;
_saltSet = saltSet; _saltSet = saltSet;
_authKeyAttributes = authKeyAttributes; _authKeyAttributes = authKeyAttributes;
_mainTempAuthKey = mainTempAuthKey;
_mediaTempAuthKey = mediaTempAuthKey;
} }
return self; return self;
} }
@ -51,8 +49,6 @@
_authKeyId = [aDecoder decodeInt64ForKey:@"authKeyId"]; _authKeyId = [aDecoder decodeInt64ForKey:@"authKeyId"];
_saltSet = [aDecoder decodeObjectForKey:@"saltSet"]; _saltSet = [aDecoder decodeObjectForKey:@"saltSet"];
_authKeyAttributes = [aDecoder decodeObjectForKey:@"authKeyAttributes"]; _authKeyAttributes = [aDecoder decodeObjectForKey:@"authKeyAttributes"];
_mainTempAuthKey = [aDecoder decodeObjectForKey:@"tempAuthKey"];
_mediaTempAuthKey = [aDecoder decodeObjectForKey:@"mediaTempAuthKey"];
} }
return self; return self;
} }
@ -63,8 +59,6 @@
[aCoder encodeInt64:_authKeyId forKey:@"authKeyId"]; [aCoder encodeInt64:_authKeyId forKey:@"authKeyId"];
[aCoder encodeObject:_saltSet forKey:@"saltSet"]; [aCoder encodeObject:_saltSet forKey:@"saltSet"];
[aCoder encodeObject:_authKeyAttributes forKey:@"authKeyAttributes"]; [aCoder encodeObject:_authKeyAttributes forKey:@"authKeyAttributes"];
[aCoder encodeObject:_mainTempAuthKey forKey:@"tempAuthKey"];
[aCoder encodeObject:_mediaTempAuthKey forKey:@"mediaTempAuthKey"];
} }
- (int64_t)authSaltForMessageId:(int64_t)messageId - (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 { - (MTDatacenterAuthInfo *)withUpdatedAuthKeyAttributes:(NSDictionary *)authKeyAttributes {
return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:_saltSet authKeyAttributes:authKeyAttributes mainTempAuthKey:_mainTempAuthKey mediaTempAuthKey:_mediaTempAuthKey]; return [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authKey authKeyId:_authKeyId saltSet:_saltSet authKeyAttributes:authKeyAttributes];
}
- (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;
}
} }
- (MTDatacenterAuthKey *)persistentAuthKey { - (MTDatacenterAuthKey *)persistentAuthKey {

View File

@ -222,7 +222,7 @@ typedef enum {
} }
} }
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto - (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo
{ {
if (_currentStageTransactionId == nil) if (_currentStageTransactionId == nil)
{ {
@ -308,7 +308,7 @@ typedef enum {
return nil; 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]]) if (_stage == MTDatacenterAuthStagePQ && [message.body isKindOfClass:[MTResPqMessage class]])
{ {
@ -389,7 +389,7 @@ typedef enum {
[innerDataBuffer appendBytes:_nonce.bytes length:_nonce.length]; [innerDataBuffer appendBytes:_nonce.bytes length:_nonce.length];
[innerDataBuffer appendBytes:_serverNonce.bytes length:_serverNonce.length]; [innerDataBuffer appendBytes:_serverNonce.bytes length:_serverNonce.length];
[innerDataBuffer appendBytes:_newNonce.bytes length:_newNonce.length]; [innerDataBuffer appendBytes:_newNonce.bytes length:_newNonce.length];
[innerDataBuffer appendInt32:60 * 60 * 32]; [innerDataBuffer appendInt32:mtProto.context.tempKeyExpiration];
NSData *innerDataBytes = innerDataBuffer.data; NSData *innerDataBytes = innerDataBuffer.data;

View File

@ -249,12 +249,11 @@
MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init]; MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init];
[[MTContext contextQueue] dispatchOnQueue:^{ [[MTContext contextQueue] dispatchOnQueue:^{
MTDatacenterAuthAction *action = [[MTDatacenterAuthAction alloc] initWithTempAuth:true tempAuthKeyType:MTDatacenterAuthTempKeyTypeMain bindKey:authKey]; MTDatacenterAuthAction *action = [[MTDatacenterAuthAction alloc] initWithAuthKeyInfoSelector:MTDatacenterAuthInfoSelectorEphemeralMain isCdn:false completion:^(__unused MTDatacenterAuthAction *action, bool success) {
action.completedWithResult = ^(bool success) {
[subscriber putNext:@(!success)]; [subscriber putNext:@(!success)];
[subscriber putCompletion]; [subscriber putCompletion];
}; }];
[action execute:context datacenterId:datacenterId isCdn:false]; [action execute:context datacenterId:datacenterId];
[disposable setDisposable:[[MTBlockDisposable alloc] initWithBlock:^{ [disposable setDisposable:[[MTBlockDisposable alloc] initWithBlock:^{
[action cancel]; [action cancel];

View File

@ -88,7 +88,7 @@
[self fail]; [self fail];
else 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 = [[MTProto alloc] initWithContext:context datacenterId:_targetDatacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0];
_mtProto.useTempAuthKeys = useTempAuthKeys; _mtProto.useTempAuthKeys = useTempAuthKeys;
@ -118,11 +118,11 @@
[_requestService addRequest:request]; [_requestService addRequest:request];
} }
else 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) if (_context != context || !_awaitingAddresSetUpdate)
return; return;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
#import <MtProtoKit/MTProtoEngine.h>
#import "Utils/MTQueueLocalObject.h"
#import <MtProtoKit/MTQueue.h>
NS_ASSUME_NONNULL_BEGIN
@interface MTProtoEngineImpl : NSObject {
MTQueue *_queue;
id<MTProtoPersistenceInterface> _persistenceInterface;
}
@end
@implementation MTProtoEngineImpl
- (instancetype)initWithQueue:(MTQueue *)queue persistenceInterface:(id<MTProtoPersistenceInterface>)persistenceInterface {
self = [super init];
if (self != nil) {
_queue = queue;
_persistenceInterface = persistenceInterface;
}
return self;
}
@end
@interface MTProtoEngine () {
MTQueue *_queue;
MTQueueLocalObject<MTProtoEngineImpl *> *_impl;
}
@end
@implementation MTProtoEngine
- (instancetype)initWithPersistenceInterface:(id<MTProtoPersistenceInterface>)persistenceInterface {
self = [super init];
if (self != nil) {
_queue = [[MTQueue alloc] init];
__auto_type queue = _queue;
_impl = [[MTQueueLocalObject<MTProtoEngineImpl
*> alloc] initWithQueue:queue generator:^MTProtoEngineImpl *{
return [[MTProtoEngineImpl alloc] initWithQueue:queue persistenceInterface:persistenceInterface];
}];
}
return self;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,48 @@
#import <MtProtoKit/MTProtoInstance.h>
#import <MtProtoKit/MTQueue.h>
#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<MTProtoInstanceImpl *> *_impl;
}
@end
@implementation MTProtoInstance
- (instancetype)initWithEngine:(MTProtoEngine *)engine {
self = [super init];
if (self != nil) {
_queue = [[MTQueue alloc] init];
__auto_type queue = _queue;
_impl = [[MTQueueLocalObject<MTProtoInstanceImpl
*> alloc] initWithQueue:queue generator:^MTProtoInstanceImpl *{
return [[MTProtoInstanceImpl alloc] initWithQueue:queue engine:engine];
}];
}
return self;
}
@end

View File

@ -391,12 +391,12 @@
return currentData; return currentData;
} }
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto - (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo
{ {
NSMutableArray *messages = nil; NSMutableArray *messages = nil;
NSMutableDictionary *requestInternalIdToMessageInternalId = 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(); CFAbsoluteTime currentTime = MTAbsoluteSystemTime();
@ -561,7 +561,7 @@
return nil; 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]]) if ([message.body isKindOfClass:[MTRpcResultMessage class]])
{ {
@ -610,13 +610,13 @@
{ {
rpcError = [[MTRpcError alloc] initWithErrorCode:500 errorDescription:@"TL_PARSING_ERROR"]; rpcError = [[MTRpcError alloc] initWithErrorCode:500 errorDescription:@"TL_PARSING_ERROR"];
[_context performBatchUpdates:^{ [_context performBatchUpdates:^{
MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId]; MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId selector:authInfoSelector];
NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:authInfo.authKeyAttributes]; NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:authInfo.authKeyAttributes];
authKeyAttributes[@"apiInitializationHash"] = @""; authKeyAttributes[@"apiInitializationHash"] = @"";
authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; 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) 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"]]) if (![_apiEnvironment.apiInitializationHash isEqualToString:authInfo.authKeyAttributes[@"apiInitializationHash"]])
{ {
@ -644,7 +644,7 @@
authKeyAttributes[@"apiInitializationHash"] = _apiEnvironment.apiInitializationHash; authKeyAttributes[@"apiInitializationHash"] = _apiEnvironment.apiInitializationHash;
authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes];
[_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo]; [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo selector:authInfoSelector];
} }
} }
@ -726,13 +726,13 @@
{ {
[_context performBatchUpdates:^ [_context performBatchUpdates:^
{ {
MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId]; MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:mtProto.datacenterId selector:authInfoSelector];
NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:authInfo.authKeyAttributes]; NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:authInfo.authKeyAttributes];
[authKeyAttributes removeObjectForKey:@"apiInitializationHash"]; [authKeyAttributes removeObjectForKey:@"apiInitializationHash"];
authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes]; authInfo = [authInfo withUpdatedAuthKeyAttributes:authKeyAttributes];
[_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo]; [_context updateAuthInfoForDatacenterWithId:mtProto.datacenterId authInfo:authInfo selector:authInfoSelector];
}]; }];
} else if (rpcError.errorCode == 406) { } else if (rpcError.errorCode == 406) {
if (_didReceiveSoftAuthResetError) { if (_didReceiveSoftAuthResetError) {

View File

@ -41,7 +41,7 @@
[mtProto requestTransportTransaction]; [mtProto requestTransportTransaction];
} }
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto - (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo
{ {
if (_currentRequestMessageId == 0 || _currentRequestTransactionId == nil) 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) if (message.messageId == _messageId)
{ {

View File

@ -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]]) if ([incomingMessage.body isKindOfClass:[MTPongMessage class]])
{ {

View File

@ -45,7 +45,7 @@
[mtProto requestTransportTransaction]; [mtProto requestTransportTransaction];
} }
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto - (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo
{ {
if (_currentTransactionId == nil) 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) if ([message.body isKindOfClass:[MTFutureSaltsMessage class]] && ((MTFutureSaltsMessage *)message.body).requestMessageId == _currentMessageId)
{ {

View File

@ -0,0 +1,14 @@
#import <Foundation/Foundation.h>
@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

View File

@ -0,0 +1,56 @@
#import "MTQueueLocalObject.h"
#import <MtProtoKit/MTQueue.h>
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

View File

@ -103,8 +103,8 @@ public class UnauthorizedAccount {
datacenterIds.append(contentsOf: [4]) datacenterIds.append(contentsOf: [4])
} }
for id in datacenterIds { for id in datacenterIds {
if network.context.authInfoForDatacenter(withId: id) == nil { if network.context.authInfoForDatacenter(withId: id, selector: .persistent) == nil {
network.context.authInfoForDatacenter(withIdRequired: id, isCdn: false) network.context.authInfoForDatacenter(withIdRequired: id, isCdn: false, selector: .ephemeralMain)
} }
} }
network.context.beginExplicitBackupAddressDiscovery() network.context.beginExplicitBackupAddressDiscovery()
@ -128,7 +128,7 @@ public class UnauthorizedAccount {
} }
} }
|> mapToSignal { (localizationSettings, proxySettings, networkSettings) -> Signal<UnauthorizedAccount, NoError> in |> mapToSignal { (localizationSettings, proxySettings, networkSettings) -> Signal<UnauthorizedAccount, NoError> 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 |> 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) 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()) 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) let backupState = AuthorizedAccountState(isTestingEnvironment: beginWithTestingEnvironment, masterDatacenterId: backupData.masterDatacenterId, peerId: PeerId(backupData.peerId), state: nil)
state = backupState state = backupState
let dict = NSMutableDictionary() 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) let data = NSKeyedArchiver.archivedData(withRootObject: dict)
transaction.setState(backupState) transaction.setState(backupState)
transaction.setKeychainEntry(data, forKey: "persistent:datacenterAuthInfoById") transaction.setKeychainEntry(data, forKey: "persistent:datacenterAuthInfoById")
@ -257,7 +257,7 @@ public func accountWithId(accountManager: AccountManager, networkArguments: Netw
if let accountState = accountState { if let accountState = accountState {
switch accountState { switch accountState {
case let unauthorizedState as UnauthorizedAccountState: 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 |> map { network -> AccountResult in
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) 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 return (transaction.getPeer(authorizedState.peerId) as? TelegramUser)?.phone
} }
|> mapToSignal { phoneNumber in |> 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 |> 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)) 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 |> map { network -> AccountResult in
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: beginWithTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: beginWithTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
} }

View File

@ -424,7 +424,17 @@ public struct NetworkInitializationArguments {
private let cloudDataContext = Atomic<CloudDataContext?>(value: nil) private let cloudDataContext = Atomic<CloudDataContext?>(value: nil)
#endif #endif
func initializedNetwork(arguments: NetworkInitializationArguments, supplementary: Bool, datacenterId: Int, keychain: Keychain, basePath: String, testingEnvironment: Bool, languageCode: String?, proxySettings: ProxySettings?, networkSettings: NetworkSettings?, phoneNumber: String?) -> Signal<Network, NoError> { private final class SharedContextStore {
struct Key: Hashable {
var accountId: AccountRecordId
}
var contexts: [Key: MTContext] = [:]
}
private let sharedContexts = Atomic<SharedContextStore>(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<Network, NoError> {
return Signal { subscriber in return Signal { subscriber in
let queue = Queue() let queue = Queue()
queue.async { 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]] let seedAddressList: [Int: [String]]

View File

@ -34,12 +34,18 @@ private func inputSecretChat(postbox: Postbox, peerId: PeerId) -> Signal<Api.Inp
|> take(1) |> 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) 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)) 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 |> map(Optional.init)
|> mapToSignalPromotingError { result -> Signal<(Int32, Int32), PeerReadStateValidationError> in |> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
return .single(nil)
}
|> mapToSignalPromotingError { result -> Signal<(Int32, Int32)?, PeerReadStateValidationError> in
guard let result = result else {
return .single(nil)
}
let apiMessages: [Api.Message] let apiMessages: [Api.Message]
switch result { switch result {
case let .channelMessages(_, _, _, messages, _, _): 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) 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) 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)])) return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeer(peer: inputPeer)]))
|> retryRequest |> retryRequest
|> mapToSignalPromotingError { result -> Signal<(PeerReadState, PeerReadStateMarker), PeerReadStateValidationError> in |> mapToSignalPromotingError { result -> Signal<(PeerReadState, PeerReadStateMarker)?, PeerReadStateValidationError> in
switch result { switch result {
case let .peerDialogs(dialogs, _, _, _, state): case let .peerDialogs(dialogs, _, _, _, state):
if let dialog = dialogs.filter({ $0.peerId == peerId }).first { 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<Never, PeerReadStateValidationError> { private func validatePeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Signal<Never, PeerReadStateValidationError> {
let readStateWithInitialState = dialogReadState(network: network, postbox: postbox, peerId: peerId) let readStateWithInitialState = dialogReadState(network: network, postbox: postbox, peerId: peerId)
|> map { ($0.0, $0.1) }
let maybeAppliedReadState = readStateWithInitialState let maybeAppliedReadState = readStateWithInitialState
|> mapToSignal { (readState, finalMarker) -> Signal<Never, PeerReadStateValidationError> in |> mapToSignal { data -> Signal<Never, PeerReadStateValidationError> 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 return stateManager.addCustomOperation(postbox.transaction { transaction -> PeerReadStateValidationError? in
if let currentReadState = transaction.getCombinedPeerReadState(peerId) { if let currentReadState = transaction.getCombinedPeerReadState(peerId) {
loop: for (namespace, currentState) in currentReadState.states { loop: for (namespace, currentState) in currentReadState.states {

View File

@ -27,7 +27,7 @@ private final class UnauthorizedUpdateMessageService: NSObject, MTMessageService
self.pipe.putNext(updates) 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 { if let updates = (message.body as? BoxedMessage)?.body as? Api.Updates {
self.addUpdates(updates) self.addUpdates(updates)
} }

View File

@ -34,7 +34,7 @@ class UpdateMessageService: NSObject, MTMessageService {
self.pipe.putNext(groups) 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 { if let updates = (message.body as? BoxedMessage)?.body as? Api.Updates {
self.addUpdates(updates) self.addUpdates(updates)
} }

View File

@ -22,7 +22,7 @@ private func accountInfo(account: Account) -> Signal<StoredAccountInfo, NoError>
var datacenters: [Int32: AccountDatacenterInfo] = [:] var datacenters: [Int32: AccountDatacenterInfo] = [:]
for nId in context.knownDatacenterIds() { for nId in context.knownDatacenterIds() {
if let id = nId as? Int { 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)) let transportScheme = context.chooseTransportSchemeForConnection(toDatacenterId: id, schemes: context.transportSchemesForDatacenter(withId: id, media: true, enforceMedia: false, isProxy: false))
var addressList: [AccountDatacenterAddress] = [] var addressList: [AccountDatacenterAddress] = []
if let transportScheme = transportScheme, let address = transportScheme.address, let host = address.host { if let transportScheme = transportScheme, let address = transportScheme.address, let host = address.host {