This commit is contained in:
Ali
2020-09-10 12:49:15 +01:00
parent c17cedf494
commit 56affdf64f
27 changed files with 510 additions and 617 deletions

View File

@@ -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",

View File

@@ -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",

View File

@@ -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;
@@ -73,7 +73,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 +95,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<NSDictionary *> *)publicKeysForDatacenterWithId:(NSInteger)datacenterId;
- (void)updatePublicKeysForDatacenterWithId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys;
@@ -107,8 +107,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;

View File

@@ -18,7 +18,7 @@
@property (nonatomic, weak) id<MTDatacenterAuthActionDelegate> delegate;
@property (nonatomic, copy) void (^completedWithResult)(bool);
- (instancetype)initWithTempAuth:(bool)tempAuth tempAuthKeyType:(MTDatacenterAuthTempKeyType)tempAuthKeyType bindKey:(MTDatacenterAuthKey *)bindKey;
- (instancetype)initWithTempAuth:(bool)tempAuth authKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector bindKey:(MTDatacenterAuthKey *)bindKey;
- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId isCdn:(bool)isCdn;
- (void)cancel;

View File

@@ -1,10 +1,5 @@
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, MTDatacenterAuthTempKeyType) {
MTDatacenterAuthTempKeyTypeMain,
MTDatacenterAuthTempKeyTypeMedia
};
@interface MTDatacenterAuthKey: NSObject <NSCoding>
@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 <NSCoding>
@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

View File

@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <MtProtoKit/MTDatacenterAuthInfo.h>
@class MTProto;
@class MTIncomingMessage;
@@ -15,10 +16,10 @@
- (void)mtProtoDidAddService:(MTProto *)mtProto;
- (void)mtProtoDidRemoveService:(MTProto *)mtProto;
- (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray<NSDictionary *> *)publicKeys;
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto;
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector;
- (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;

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

@@ -114,6 +114,33 @@
@end
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, MTDatacenterAuthActionDelegate, MTDatacenterTransferAuthActionDelegate>
{
int64_t _uniqueId;
@@ -127,7 +154,7 @@
NSMutableDictionary<NSNumber *, NSMutableDictionary<MTDatacenterAddress *, MTTransportSchemeStats *> *> *_transportSchemeStats;
MTTimer *_schemeStatsSyncTimer;
NSMutableDictionary *_datacenterAuthInfoById;
NSMutableDictionary<NSNumber *, MTDatacenterAuthInfo *> *_datacenterAuthInfoById;
NSMutableDictionary *_datacenterPublicKeysById;
@@ -582,29 +609,35 @@ 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)
{
NSNumber *infoKey = authInfoMapIntegerKey((int32_t)datacenterId, selector);
if (authInfo != nil) {
_datacenterAuthInfoById[infoKey] = authInfo;
} else {
if (_datacenterAuthInfoById[infoKey] == nil) {
return;
}
[_datacenterAuthInfoById removeObjectForKey:infoKey];
}
if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: auth info updated for %d to %@]", (int)self, datacenterId, authInfo);
}
if (authInfo != nil) {
_datacenterAuthInfoById[@(datacenterId)] = authInfo;
} else {
[_datacenterAuthInfoById removeObjectForKey:@(datacenterId)];
}
[_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"];
NSArray *currentListeners = [[NSArray alloc] initWithArray:_changeListeners];
for (id<MTContextChangeListener> 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];
}
}
}];
@@ -864,10 +897,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,13 +1285,13 @@ 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)
{
MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithTempAuth:false tempAuthKeyType:MTDatacenterAuthTempKeyTypeMain bindKey:nil];
MTDatacenterAuthAction *authAction = [[MTDatacenterAuthAction alloc] initWithTempAuth:false authKeyInfoSelector:selector bindKey:nil];
authAction.delegate = self;
_datacenterAuthActions[@(datacenterId)] = authAction;
[authAction execute:self datacenterId:datacenterId isCdn:isCdn];
@@ -1265,17 +1299,6 @@ static int32_t fixedTimeDifferenceValue = 0;
}];
}
- (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:^
@@ -1357,21 +1380,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 +1395,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) {

View File

@@ -17,7 +17,7 @@
@interface MTDatacenterAuthAction () <MTDatacenterAuthMessageServiceDelegate>
{
bool _isCdn;
MTDatacenterAuthTempKeyType _tempAuthKeyType;
MTDatacenterAuthInfoSelector _authKeyInfoSelector;
MTDatacenterAuthKey *_bindKey;
NSInteger _datacenterId;
@@ -34,11 +34,11 @@
@implementation MTDatacenterAuthAction
- (instancetype)initWithTempAuth:(bool)tempAuth tempAuthKeyType:(MTDatacenterAuthTempKeyType)tempAuthKeyType bindKey:(MTDatacenterAuthKey *)bindKey {
- (instancetype)initWithTempAuth:(bool)tempAuth authKeyInfoSelector:(MTDatacenterAuthInfoSelector)authKeyInfoSelector bindKey:(MTDatacenterAuthKey *)bindKey {
self = [super init];
if (self != nil) {
_tempAuth = tempAuth;
_tempAuthKeyType = tempAuthKeyType;
_authKeyInfoSelector = authKeyInfoSelector;
_bindKey = bindKey;
_verifyDisposable = [[MTMetaDisposable alloc] init];
}
@@ -59,15 +59,10 @@
if (_datacenterId != 0 && context != nil)
{
bool alreadyCompleted = false;
MTDatacenterAuthInfo *currentAuthInfo = [context authInfoForDatacenterWithId:_datacenterId];
MTDatacenterAuthInfo *currentAuthInfo = [context authInfoForDatacenterWithId:_datacenterId selector:_authKeyInfoSelector];
if (currentAuthInfo != nil && _bindKey == nil) {
if (_tempAuth) {
if ([currentAuthInfo tempAuthKeyWithType:_tempAuthKeyType] != nil) {
alreadyCompleted = true;
}
} else {
alreadyCompleted = true;
}
alreadyCompleted = true;
}
if (alreadyCompleted) {
@@ -77,11 +72,11 @@
_authMtProto.cdn = isCdn;
_authMtProto.useUnauthorizedMode = true;
if (_tempAuth) {
switch (_tempAuthKeyType) {
case MTDatacenterAuthTempKeyTypeMain:
switch (_authKeyInfoSelector) {
case MTDatacenterAuthInfoSelectorEphemeralMain:
_authMtProto.media = false;
break;
case MTDatacenterAuthTempKeyTypeMedia:
case MTDatacenterAuthInfoSelectorEphemeralMedia:
_authMtProto.media = true;
_authMtProto.enforceMedia = true;
break;
@@ -128,20 +123,19 @@
} else {
MTContext *context = _context;
[context performBatchUpdates:^{
MTDatacenterAuthInfo *authInfo = [context authInfoForDatacenterWithId:_datacenterId];
MTDatacenterAuthInfo *authInfo = [context authInfoForDatacenterWithId:_datacenterId selector:_authKeyInfoSelector];
if (authInfo != nil) {
authInfo = [authInfo withUpdatedTempAuthKeyWithType:_tempAuthKeyType key:authKey];
[context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo];
[context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo selector:_authKeyInfoSelector];
}
}];
[self complete];
}
}
} 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];
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];
[context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo selector:_authKeyInfoSelector];
[self complete];
}
}

View File

@@ -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 {

View File

@@ -222,7 +222,7 @@ typedef enum {
}
}
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector
{
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]])
{

View File

@@ -249,7 +249,7 @@
MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init];
[[MTContext contextQueue] dispatchOnQueue:^{
MTDatacenterAuthAction *action = [[MTDatacenterAuthAction alloc] initWithTempAuth:true tempAuthKeyType:MTDatacenterAuthTempKeyTypeMain bindKey:authKey];
MTDatacenterAuthAction *action = [[MTDatacenterAuthAction alloc] initWithTempAuth:true authKeyInfoSelector:MTDatacenterAuthInfoSelectorEphemeralMain bindKey:authKey];
action.completedWithResult = ^(bool success) {
[subscriber putNext:@(!success)];
[subscriber putCompletion];

View File

@@ -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;

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;
}
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector
{
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) {

View File

@@ -41,7 +41,7 @@
[mtProto requestTransportTransaction];
}
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector
{
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)
{

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]])
{

View File

@@ -45,7 +45,7 @@
[mtProto requestTransportTransaction];
}
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto
- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector
{
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)
{

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])
}
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: .persistent)
}
}
network.context.beginExplicitBackupAddressDiscovery()
@@ -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")

View File

@@ -34,12 +34,18 @@ private func inputSecretChat(postbox: Postbox, peerId: PeerId) -> Signal<Api.Inp
|> 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<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]
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<Never, PeerReadStateValidationError> {
let readStateWithInitialState = dialogReadState(network: network, postbox: postbox, peerId: peerId)
|> map { ($0.0, $0.1) }
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
if let currentReadState = transaction.getCombinedPeerReadState(peerId) {
loop: for (namespace, currentState) in currentReadState.states {

View File

@@ -22,7 +22,7 @@ private func accountInfo(account: Account) -> Signal<StoredAccountInfo, NoError>
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 {