no message

This commit is contained in:
Peter Iakovlev 2018-04-20 23:33:41 +04:00
parent a73820f6d3
commit 0e8f3be0e4
11 changed files with 365 additions and 4 deletions

View File

@ -207,6 +207,8 @@
NSDictionary *fetchPublicKeysActions = _fetchPublicKeysActions;
_fetchPublicKeysActions = nil;
id<MTDisposable> cleanupSessionInfoDisposables = _cleanupSessionInfoDisposables;
[[MTContext contextQueue] dispatchOnQueue:^
{
for (NSNumber *nDatacenterId in discoverDatacenterAddressActions)
@ -223,6 +225,13 @@
[action cancel];
}
for (NSNumber *nDatacenterId in datacenterTempAuthActions)
{
MTDatacenterAuthAction *action = datacenterTempAuthActions[nDatacenterId];
action.delegate = nil;
[action cancel];
}
for (NSNumber *nDatacenterId in datacenterTransferAuthActions)
{
MTDatacenterTransferAuthAction *action = datacenterTransferAuthActions[nDatacenterId];
@ -236,7 +245,7 @@
[disposable dispose];
}
[_cleanupSessionInfoDisposables dispose];
[cleanupSessionInfoDisposables dispose];
}];
}

View File

@ -273,6 +273,20 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
_transport = transport;
[previousTransport stop];
if (_transport != nil && _useTempAuthKeys) {
MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain;
if (_transport.address.preferForMedia) {
tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia;
}
MTDatacenterAuthKey *effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType];
if (effectiveAuthKey == nil) {
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p setTransport temp auth key missing]", self);
}
}
}
if (_transport != nil)
[self addMessageService:_transport];
@ -2068,7 +2082,6 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}
effectiveAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType];
NSAssert(effectiveAuthKey != nil, @"effectiveAuthKey == nil");
} else {
effectiveAuthKey = [[MTDatacenterAuthKey alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId notBound:false];
}

View File

@ -73,3 +73,4 @@ FOUNDATION_EXPORT const unsigned char MtProtoKitVersionString[];
#import <MTProtoKit/MTBackupAddressSignals.h>
#import <MTProtoKit/AFURLConnectionOperation.h>
#import <MTProtoKit/AFHTTPRequestOperation.h>
#import <MTProtoKit/MTProxyConnectivity.h>

View File

@ -613,7 +613,7 @@ struct ctr_state {
if (resp.Reply != 0x00) {
if (MTLogEnabled()) {
MTLog(@"***** %s: socks5 connect failed, error 0x%02x", __PRETTY_FUNCTION__, resp.Reply);
MTLog(@"***** %x %s: socks5 connect failed, error 0x%02x", (int)self, __PRETTY_FUNCTION__, resp.Reply);
}
[self closeAndNotify];
return;

18
MTProxyConnectivity.h Normal file
View File

@ -0,0 +1,18 @@
#import <Foundation/Foundation.h>
@class MTSignal;
@class MTContext;
@class MTSocksProxySettings;
@interface MTProxyConnectivityStatus : NSObject
@property (nonatomic, readonly) bool reachable;
@property (nonatomic, readonly) NSTimeInterval roundTripTime;
@end
@interface MTProxyConnectivity : NSObject
+ (MTSignal *)pingProxyWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId settings:(MTSocksProxySettings *)settings;
@end

176
MTProxyConnectivity.m Normal file
View File

@ -0,0 +1,176 @@
#import "MTProxyConnectivity.h"
#import "MTSignal.h"
#import "MTQueue.h"
#import "MTContext.h"
#import "MTApiEnvironment.h"
#import "MTDatacenterAddressSet.h"
#import "MTDatacenterAddress.h"
#import "MTTcpConnection.h"
#import "MTTransportScheme.h"
@implementation MTProxyConnectivityStatus
- (instancetype)initWithReachable:(bool)reachable roundTripTime:(NSTimeInterval)roundTripTime {
self = [super init];
if (self != nil) {
_reachable = reachable;
_roundTripTime = roundTripTime;
}
return self;
}
- (BOOL)isEqual:(id)object {
if (![object isKindOfClass:[MTProxyConnectivityStatus class]]) {
return false;
}
MTProxyConnectivityStatus *other = object;
if (_reachable != other.reachable) {
return false;
}
if (_roundTripTime != other.roundTripTime) {
return false;
}
return true;
}
@end
typedef struct {
uint8_t nonce[16];
} MTPayloadData;
@implementation MTProxyConnectivity
+ (NSData *)payloadData:(MTPayloadData *)outPayloadData;
{
uint8_t reqPqBytes[] = {
0, 0, 0, 0, 0, 0, 0, 0, // zero * 8
0, 0, 0, 0, 0, 0, 0, 0, // message id
20, 0, 0, 0, // message length
0x78, 0x97, 0x46, 0x60, // req_pq
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // nonce
};
MTPayloadData payloadData;
arc4random_buf(&payloadData.nonce, 16);
if (outPayloadData)
*outPayloadData = payloadData;
arc4random_buf(reqPqBytes + 8, 8);
memcpy(reqPqBytes + 8 + 8 + 4 + 4, payloadData.nonce, 16);
return [[NSData alloc] initWithBytes:reqPqBytes length:sizeof(reqPqBytes)];
}
+ (bool)isResponseValid:(NSData *)data payloadData:(MTPayloadData)payloadData
{
if (data.length >= 84)
{
uint8_t zero[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t resPq[] = { 0x63, 0x24, 0x16, 0x05 };
if (memcmp((uint8_t * const)data.bytes, zero, 8) == 0 && memcmp(((uint8_t * const)data.bytes) + 20, resPq, 4) == 0 && memcmp(((uint8_t * const)data.bytes) + 24, payloadData.nonce, 16) == 0)
{
return true;
}
}
return false;
}
+ (MTSignal *)pingWithAddress:(MTDatacenterAddress *)address datacenterId:(NSUInteger)datacenterId settings:(MTSocksProxySettings *)settings context:(MTContext *)context {
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
MTQueue *queue = [[MTQueue alloc] init];
MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init];
[queue dispatchOnQueue:^{
[subscriber putNext:[NSNull null]];
MTPayloadData payloadData;
NSData *data = [self payloadData:&payloadData];
MTContext *proxyContext = [[MTContext alloc] initWithSerialization:context.serialization apiEnvironment:[[context apiEnvironment] withUpdatedSocksProxySettings:settings]];
MTTcpConnection *connection = [[MTTcpConnection alloc] initWithContext:proxyContext datacenterId:datacenterId address:address interface:nil usageCalculationInfo:nil];
__weak MTTcpConnection *weakConnection = connection;
__block NSTimeInterval startTime = CFAbsoluteTimeGetCurrent();
connection.connectionOpened = ^ {
__strong MTTcpConnection *strongConnection = weakConnection;
if (strongConnection != nil) {
startTime = CFAbsoluteTimeGetCurrent();
[strongConnection sendDatas:@[data] completion:nil requestQuickAck:false expectDataInResponse:true];
}
};
__block bool received = false;
connection.connectionReceivedData = ^(NSData *data) {
received = true;
if ([self isResponseValid:data payloadData:payloadData]) {
NSTimeInterval roundTripTime = CFAbsoluteTimeGetCurrent() - startTime;
[subscriber putNext:[[MTProxyConnectivityStatus alloc] initWithReachable:true roundTripTime:roundTripTime]];
} else {
[subscriber putNext:[[MTProxyConnectivityStatus alloc] initWithReachable:false roundTripTime:0.0]];
}
[subscriber putCompletion];
};
connection.connectionClosed = ^
{
if (!received) {
[subscriber putNext:[[MTProxyConnectivityStatus alloc] initWithReachable:false roundTripTime:0.0]];
[subscriber putCompletion];
}
};
[connection start];
[disposable setDisposable:[[MTBlockDisposable alloc] initWithBlock:^{
[queue dispatchOnQueue:^{
[connection stop];
__unused id desc = [proxyContext description];
}];
}]];
}];
return disposable;
}];
}
+ (MTSignal *)pingProxyWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId settings:(MTSocksProxySettings *)settings {
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
MTTransportScheme *transportScheme = [context transportSchemeForDatacenterWithId:datacenterId media:false isProxy:true];
MTDatacenterAddressSet *addressSet = [context addressSetForDatacenterWithId:datacenterId];
NSMutableArray *signals = [[NSMutableArray alloc] init];
for (MTDatacenterAddress *address in addressSet.addressList) {
if (!address.isIpv6) {
[signals addObject:[self pingWithAddress:address datacenterId:datacenterId settings:settings context:context]];
}
if (address.isIpv6) {
[signals addObject:[self pingWithAddress:address datacenterId:datacenterId settings:settings context:context]];
}
}
if (signals.count == 0) {
[subscriber putNext:[[MTProxyConnectivityStatus alloc] initWithReachable:false roundTripTime:0.0]];
[subscriber putCompletion];
return nil;
}
return [[MTSignal combineSignals:signals] startWithNext:^(NSArray *results) {
bool allStatusesAreValid = true;
for (MTProxyConnectivityStatus *status in results) {
if ([status isKindOfClass:[MTProxyConnectivityStatus class]]) {
if (status.reachable) {
[subscriber putNext:status];
[subscriber putCompletion];
return;
}
} else {
allStatusesAreValid = false;
}
}
if (allStatusesAreValid) {
[subscriber putNext:[[MTProxyConnectivityStatus alloc] initWithReachable:false roundTripTime:0.0]];
[subscriber putCompletion];
}
}];
}];
}
@end

View File

@ -29,6 +29,7 @@
- (MTSignal *)catch:(MTSignal *(^)(id error))f;
+ (MTSignal *)mergeSignals:(NSArray *)signals;
+ (MTSignal *)combineSignals:(NSArray *)signals;
- (MTSignal *)restart;
@ -45,7 +46,6 @@
- (MTSignal *)deliverOn:(MTQueue *)queue;
- (MTSignal *)startOn:(MTQueue *)queue;
- (MTSignal *)take:(NSUInteger)count;
- (MTSignal *)takeLast;
- (MTSignal *)reduceLeft:(id)value with:(id (^)(id, id))f;

View File

@ -195,6 +195,30 @@
@end
@interface MTSignalCombineState : NSObject
@property (nonatomic, strong, readonly) NSDictionary *latestValues;
@property (nonatomic, strong, readonly) NSArray *completedStatuses;
@property (nonatomic) bool error;
@end
@implementation MTSignalCombineState
- (instancetype)initWithLatestValues:(NSDictionary *)latestValues completedStatuses:(NSArray *)completedStatuses error:(bool)error
{
self = [super init];
if (self != nil)
{
_latestValues = latestValues;
_completedStatuses = completedStatuses;
_error = error;
}
return self;
}
@end
@implementation MTSignal
- (instancetype)initWithGenerator:(id<MTDisposable> (^)(MTSubscriber *))generator
@ -401,6 +425,108 @@
}];
}
+ (MTSignal *)combineSignals:(NSArray *)signals
{
if (signals.count == 0)
return [MTSignal single:@[]];
else
return [self combineSignals:signals withInitialStates:nil];
}
+ (MTSignal *)combineSignals:(NSArray *)signals withInitialStates:(NSArray *)initialStates
{
return [[MTSignal alloc] initWithGenerator:^(MTSubscriber *subscriber)
{
NSMutableArray *completedStatuses = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < signals.count; i++) {
[completedStatuses addObject:@false];
}
NSMutableDictionary *initialLatestValues = [[NSMutableDictionary alloc] init];
for (NSUInteger i = 0; i < initialStates.count; i++) {
initialLatestValues[@(i)] = initialStates[i];
}
MTAtomic *combineState = [[MTAtomic alloc] initWithValue:[[MTSignalCombineState alloc] initWithLatestValues:initialLatestValues completedStatuses:completedStatuses error:false]];
MTDisposableSet *compositeDisposable = [[MTDisposableSet alloc] init];
NSUInteger index = 0;
NSUInteger count = signals.count;
for (MTSignal *signal in signals) {
id<MTDisposable> disposable = [signal startWithNext:^(id next)
{
MTSignalCombineState *currentState = [combineState modify:^id(MTSignalCombineState *state)
{
NSMutableDictionary *latestValues = [[NSMutableDictionary alloc] initWithDictionary:state.latestValues];
latestValues[@(index)] = next;
return [[MTSignalCombineState alloc] initWithLatestValues:latestValues completedStatuses:state.completedStatuses error:state.error];
}];
NSMutableArray *latestValues = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < count; i++)
{
id value = currentState.latestValues[@(i)];
if (value == nil)
{
latestValues = nil;
break;
}
latestValues[i] = value;
}
if (latestValues != nil)
[subscriber putNext:latestValues];
}
error:^(id error)
{
__block bool hadError = false;
[combineState modify:^id(MTSignalCombineState *state)
{
hadError = state.error;
return [[MTSignalCombineState alloc] initWithLatestValues:state.latestValues completedStatuses:state.completedStatuses error:true];
}];
if (!hadError)
[subscriber putError:error];
} completed:^
{
__block bool wasCompleted = false;
__block bool isCompleted = false;
[combineState modify:^id(MTSignalCombineState *state)
{
NSMutableArray *completedStatuses = [[NSMutableArray alloc] initWithArray:state.completedStatuses];
bool everyStatusWasCompleted = true;
for (NSNumber *nStatus in completedStatuses)
{
if (![nStatus boolValue])
{
everyStatusWasCompleted = false;
break;
}
}
completedStatuses[index] = @true;
bool everyStatusIsCompleted = true;
for (NSNumber *nStatus in completedStatuses)
{
if (![nStatus boolValue])
{
everyStatusIsCompleted = false;
break;
}
}
wasCompleted = everyStatusWasCompleted;
isCompleted = everyStatusIsCompleted;
return [[MTSignalCombineState alloc] initWithLatestValues:state.latestValues completedStatuses:completedStatuses error:state.error];
}];
if (!wasCompleted && isCompleted)
[subscriber putCompletion];
}];
[compositeDisposable add:disposable];
index++;
}
return compositeDisposable;
}];
}
+ (MTSignal *)mergeSignals:(NSArray *)signals
{
if (signals.count == 0)

View File

@ -16,6 +16,12 @@
D010DB7E1D70ABEE0012AD96 /* MTRsa.m in Sources */ = {isa = PBXBuildFile; fileRef = D010DB7C1D70ABEE0012AD96 /* MTRsa.m */; };
D010DB811D70B3B90012AD96 /* MTAes.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DB7F1D70B3B90012AD96 /* MTAes.h */; };
D010DB821D70B3B90012AD96 /* MTAes.m in Sources */ = {isa = PBXBuildFile; fileRef = D010DB801D70B3B90012AD96 /* MTAes.m */; };
D0185E722089D265005E1A6C /* MTProxyConnectivity.h in Headers */ = {isa = PBXBuildFile; fileRef = D0185E702089D265005E1A6C /* MTProxyConnectivity.h */; settings = {ATTRIBUTES = (Public, ); }; };
D0185E732089D265005E1A6C /* MTProxyConnectivity.h in Headers */ = {isa = PBXBuildFile; fileRef = D0185E702089D265005E1A6C /* MTProxyConnectivity.h */; settings = {ATTRIBUTES = (Public, ); }; };
D0185E742089D265005E1A6C /* MTProxyConnectivity.h in Headers */ = {isa = PBXBuildFile; fileRef = D0185E702089D265005E1A6C /* MTProxyConnectivity.h */; settings = {ATTRIBUTES = (Public, ); }; };
D0185E752089D265005E1A6C /* MTProxyConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = D0185E712089D265005E1A6C /* MTProxyConnectivity.m */; };
D0185E762089D265005E1A6C /* MTProxyConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = D0185E712089D265005E1A6C /* MTProxyConnectivity.m */; };
D0185E772089D265005E1A6C /* MTProxyConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = D0185E712089D265005E1A6C /* MTProxyConnectivity.m */; };
D020FAFA1D994E3100F279AA /* MTHttpRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D020FAF81D994E3100F279AA /* MTHttpRequestOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
D020FAFB1D994E3100F279AA /* MTHttpRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D020FAF81D994E3100F279AA /* MTHttpRequestOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
D020FAFC1D994E3100F279AA /* MTHttpRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D020FAF81D994E3100F279AA /* MTHttpRequestOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -595,6 +601,8 @@
D010DB7C1D70ABEE0012AD96 /* MTRsa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRsa.m; sourceTree = "<group>"; };
D010DB7F1D70B3B90012AD96 /* MTAes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTAes.h; sourceTree = "<group>"; };
D010DB801D70B3B90012AD96 /* MTAes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTAes.m; sourceTree = "<group>"; };
D0185E702089D265005E1A6C /* MTProxyConnectivity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTProxyConnectivity.h; sourceTree = "<group>"; };
D0185E712089D265005E1A6C /* MTProxyConnectivity.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTProxyConnectivity.m; sourceTree = "<group>"; };
D020FAF81D994E3100F279AA /* MTHttpRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTHttpRequestOperation.h; path = MTProtoKit/MTHttpRequestOperation.h; sourceTree = "<group>"; };
D020FAF91D994E3100F279AA /* MTHttpRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTHttpRequestOperation.m; path = MTProtoKit/MTHttpRequestOperation.m; sourceTree = "<group>"; };
D0254CC518B10404009452AA /* MTEncryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTEncryption.h; path = MTProtoKit/MTEncryption.h; sourceTree = "<group>"; };
@ -1053,6 +1061,8 @@
D0E9B9EC1F0176DA00F079A4 /* MTBackupAddressSignals.m */,
D0E2E17520866780005737E8 /* MTDNS.h */,
D0E2E17620866780005737E8 /* MTDNS.m */,
D0185E702089D265005E1A6C /* MTProxyConnectivity.h */,
D0185E712089D265005E1A6C /* MTProxyConnectivity.m */,
);
name = Utils;
sourceTree = "<group>";
@ -1505,6 +1515,7 @@
D0CD98681D74B9E200F41187 /* MTContext.h in Headers */,
D0CD985B1D74B9BF00F41187 /* MTSetClientDhParamsResponseMessage.h in Headers */,
D0CD98741D74BA0100F41187 /* MTDiscoverDatacenterAddressAction.h in Headers */,
D0185E732089D265005E1A6C /* MTProxyConnectivity.h in Headers */,
D0CD98EA1D75C0C100F41187 /* MTMessageTransaction.h in Headers */,
D0CD98B41D74BA7500F41187 /* MTNetworkAvailability.h in Headers */,
D0E9B9EE1F0176DA00F079A4 /* MTBackupAddressSignals.h in Headers */,
@ -1639,6 +1650,7 @@
D0CB06251ADC4562005E298F /* MTTransportScheme.h in Headers */,
D0D1A05C1ADD983C007D9ED6 /* MTResPqMessage.h in Headers */,
D0D1A03E1ADD983C007D9ED6 /* MTDropRpcResultMessage.h in Headers */,
D0185E722089D265005E1A6C /* MTProxyConnectivity.h in Headers */,
D0D1A05E1ADD983C007D9ED6 /* MTRpcError.h in Headers */,
D0E2E17720866780005737E8 /* MTDNS.h in Headers */,
D0C9322B1E095E280074F044 /* MTNetworkUsageManager.h in Headers */,
@ -1699,6 +1711,7 @@
D0CD98691D74B9E300F41187 /* MTContext.h in Headers */,
D0CD985F1D74B9BF00F41187 /* MTSetClientDhParamsResponseMessage.h in Headers */,
D0CD98751D74BA0100F41187 /* MTDiscoverDatacenterAddressAction.h in Headers */,
D0185E742089D265005E1A6C /* MTProxyConnectivity.h in Headers */,
D0CD98EB1D75C0C100F41187 /* MTMessageTransaction.h in Headers */,
D0CD98B71D74BA7500F41187 /* MTNetworkAvailability.h in Headers */,
D0E9B9EF1F0176DA00F079A4 /* MTBackupAddressSignals.h in Headers */,
@ -2033,6 +2046,7 @@
D0CD98BC1D74BA7C00F41187 /* MTTransportTransaction.m in Sources */,
D0CD98F41D75C0DD00F41187 /* MTRequestMessageService.m in Sources */,
D0CD98A81D74BA6E00F41187 /* MTTimeFixContext.m in Sources */,
D0185E762089D265005E1A6C /* MTProxyConnectivity.m in Sources */,
D0CD98721D74B9F900F41187 /* MTDiscoverConnectionSignals.m in Sources */,
D0CD98061D74B96C00F41187 /* MTBadMsgNotificationMessage.m in Sources */,
D0CD98311D74B9AA00F41187 /* MTMessage.m in Sources */,
@ -2129,6 +2143,7 @@
D0CB06521ADC45BA005E298F /* MTRequest.m in Sources */,
D0CB06481ADC45A6005E298F /* MTMessageTransaction.m in Sources */,
D0CB06221ADC4551005E298F /* MTKeychain.m in Sources */,
D0185E752089D265005E1A6C /* MTProxyConnectivity.m in Sources */,
D0D1A0471ADD983C007D9ED6 /* MTMessage.m in Sources */,
D0CB06121ADC44B7005E298F /* MTLogging.m in Sources */,
D0CB063F1ADC4599005E298F /* MTProto.m in Sources */,
@ -2225,6 +2240,7 @@
D0CD98BF1D74BA7C00F41187 /* MTTransportTransaction.m in Sources */,
D0CD98F51D75C0DD00F41187 /* MTRequestMessageService.m in Sources */,
D0CD98AF1D74BA6F00F41187 /* MTTimeFixContext.m in Sources */,
D0185E772089D265005E1A6C /* MTProxyConnectivity.m in Sources */,
D0CD98731D74B9F900F41187 /* MTDiscoverConnectionSignals.m in Sources */,
D0CD980B1D74B96C00F41187 /* MTBadMsgNotificationMessage.m in Sources */,
D0CD98401D74B9AA00F41187 /* MTMessage.m in Sources */,

View File

@ -74,3 +74,4 @@ FOUNDATION_EXPORT const unsigned char MtProtoKitDynamicVersionString[];
#import <MTProtoKitDynamic/MTBackupAddressSignals.h>
#import <MTProtoKitDynamic/AFURLConnectionOperation.h>
#import <MTProtoKitDynamic/AFHTTPRequestOperation.h>
#import <MTProtoKitDynamic/MTProxyConnectivity.h>

View File

@ -74,3 +74,4 @@ FOUNDATION_EXPORT const unsigned char MtProtoKitMacVersionString[];
#import <MtProtoKitMac/MTBackupAddressSignals.h>
#import <MtProtoKitMac/AFURLConnectionOperation.h>
#import <MtProtoKitMac/AFHTTPRequestOperation.h>
#import <MTProtoKitMac/MTProxyConnectivity.h>