no message

This commit is contained in:
Peter 2017-02-02 18:58:11 +03:00
parent 57a9c196b9
commit dbba320020
131 changed files with 5910 additions and 846 deletions

11
MTAes.h Normal file
View File

@ -0,0 +1,11 @@
#import <Foundation/Foundation.h>
void MyAesIgeEncrypt(const void *inBytes, int length, void *outBytes, const void *key, int keyLength, void *iv);
void MyAesIgeDecrypt(const void *inBytes, int length, void *outBytes, const void *key, int keyLength, void *iv);
@interface MTAesCtr : NSObject
- (instancetype)initWithKey:(const void *)key keyLength:(int)keyLength iv:(const void *)iv;
- (void)encryptIn:(const unsigned char *)in out:(unsigned char *)out len:(size_t)len;
@end

288
MTAes.m Normal file
View File

@ -0,0 +1,288 @@
#import "MTAes.h"
#import <CommonCrypto/CommonCrypto.h>
# define AES_MAXNR 14
# define AES_BLOCK_SIZE 16
#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
typedef struct {
unsigned long data[N_WORDS];
} aes_block_t;
/* XXX: probably some better way to do this */
#if defined(__i386__) || defined(__x86_64__)
# define UNALIGNED_MEMOPS_ARE_FAST 1
#else
# define UNALIGNED_MEMOPS_ARE_FAST 0
#endif
#if UNALIGNED_MEMOPS_ARE_FAST
# define load_block(d, s) (d) = *(const aes_block_t *)(s)
# define store_block(d, s) *(aes_block_t *)(d) = (s)
#else
# define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE)
# define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE)
#endif
void MyAesIgeEncrypt(const void *inBytes, int length, void *outBytes, const void *key, int keyLength, void *iv) {
int len;
size_t n;
void const *inB;
void *outB;
unsigned char aesIv[AES_BLOCK_SIZE];
memcpy(aesIv, iv, AES_BLOCK_SIZE);
unsigned char ccIv[AES_BLOCK_SIZE];
memcpy(ccIv, iv + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
assert(((size_t)inBytes | (size_t)outBytes | (size_t)aesIv | (size_t)ccIv) % sizeof(long) ==
0);
void *tmpInBytes = malloc(length);
len = length / AES_BLOCK_SIZE;
inB = inBytes;
outB = tmpInBytes;
aes_block_t *inp = (aes_block_t *)inB;
aes_block_t *outp = (aes_block_t *)outB;
for (n = 0; n < N_WORDS; ++n) {
outp->data[n] = inp->data[n];
}
--len;
inB += AES_BLOCK_SIZE;
outB += AES_BLOCK_SIZE;
void const *inBCC = inBytes;
aes_block_t const *iv3p = (aes_block_t *)ccIv;
if (len > 0) {
while (len) {
aes_block_t *inp = (aes_block_t *)inB;
aes_block_t *outp = (aes_block_t *)outB;
for (n = 0; n < N_WORDS; ++n) {
outp->data[n] = inp->data[n] ^ iv3p->data[n];
}
iv3p = inBCC;
--len;
inBCC += AES_BLOCK_SIZE;
inB += AES_BLOCK_SIZE;
outB += AES_BLOCK_SIZE;
}
}
size_t realOutLength = 0;
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0, key, keyLength, aesIv, tmpInBytes, length, outBytes, length, &realOutLength);
free(tmpInBytes);
assert(result == kCCSuccess);
len = length / AES_BLOCK_SIZE;
aes_block_t const *ivp = inB;
aes_block_t *iv2p = (aes_block_t *)ccIv;
inB = inBytes;
outB = outBytes;
while (len) {
aes_block_t *inp = (aes_block_t *)inB;
aes_block_t *outp = (aes_block_t *)outB;
for (n = 0; n < N_WORDS; ++n) {
outp->data[n] ^= iv2p->data[n];
}
ivp = outp;
iv2p = inp;
--len;
inB += AES_BLOCK_SIZE;
outB += AES_BLOCK_SIZE;
}
memcpy(iv, ivp->data, AES_BLOCK_SIZE);
memcpy(iv + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
}
void MyAesIgeDecrypt(const void *inBytes, int length, void *outBytes, const void *key, int keyLength, void *iv) {
unsigned char aesIv[AES_BLOCK_SIZE];
memcpy(aesIv, iv, AES_BLOCK_SIZE);
unsigned char ccIv[AES_BLOCK_SIZE];
memcpy(ccIv, iv + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
assert(((size_t)inBytes | (size_t)outBytes | (size_t)aesIv | (size_t)ccIv) % sizeof(long) ==
0);
CCCryptorRef decryptor = NULL;
CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode, key, keyLength, nil, &decryptor);
if (decryptor != NULL) {
int len;
size_t n;
len = length / AES_BLOCK_SIZE;
aes_block_t *ivp = (aes_block_t *)(aesIv);
aes_block_t *iv2p = (aes_block_t *)(ccIv);
while (len) {
aes_block_t tmp;
aes_block_t *inp = (aes_block_t *)inBytes;
aes_block_t *outp = (aes_block_t *)outBytes;
for (n = 0; n < N_WORDS; ++n)
tmp.data[n] = inp->data[n] ^ iv2p->data[n];
size_t dataOutMoved = 0;
CCCryptorStatus result = CCCryptorUpdate(decryptor, &tmp, AES_BLOCK_SIZE, outBytes, AES_BLOCK_SIZE, &dataOutMoved);
assert(result == kCCSuccess);
assert(dataOutMoved == AES_BLOCK_SIZE);
for (n = 0; n < N_WORDS; ++n)
outp->data[n] ^= ivp->data[n];
ivp = inp;
iv2p = outp;
inBytes += AES_BLOCK_SIZE;
outBytes += AES_BLOCK_SIZE;
--len;
}
memcpy(iv, ivp->data, AES_BLOCK_SIZE);
memcpy(iv + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
CCCryptorRelease(decryptor);
}
}
static void ctr128_inc(unsigned char *counter)
{
uint32_t n = 16, c = 1;
do {
--n;
c += counter[n];
counter[n] = (uint8_t)c;
c >>= 8;
} while (n);
}
static void ctr128_inc_aligned(unsigned char *counter)
{
size_t *data, c, d, n;
const union {
long one;
char little;
} is_endian = {
1
};
if (is_endian.little || ((size_t)counter % sizeof(size_t)) != 0) {
ctr128_inc(counter);
return;
}
data = (size_t *)counter;
c = 1;
n = 16 / sizeof(size_t);
do {
--n;
d = data[n] += c;
/* did addition carry? */
c = ((d - c) ^ d) >> (sizeof(size_t) * 8 - 1);
} while (n);
}
@interface MTAesCtr () {
CCCryptorRef _cryptor;
unsigned char _ivec[16];
unsigned int _num;
unsigned char _ecount[16];
}
@end
@implementation MTAesCtr
- (instancetype)initWithKey:(const void *)key keyLength:(int)keyLength iv:(const void *)iv {
self = [super init];
if (self != nil) {
_num = 0;
memset(_ecount, 0, 16);
memcpy(_ivec, iv, 16);
CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode, key, keyLength, nil, &_cryptor);
}
return self;
}
- (void)dealloc {
if (_cryptor) {
CCCryptorRelease(_cryptor);
}
}
- (void)encryptIn:(const unsigned char *)in out:(unsigned char *)out len:(size_t)len {
unsigned int n;
size_t l = 0;
assert(in && out);
assert(_num < 16);
n = _num;
if (16 % sizeof(size_t) == 0) { /* always true actually */
do {
while (n && len) {
*(out++) = *(in++) ^ _ecount[n];
--len;
n = (n + 1) % 16;
}
while (len >= 16) {
size_t dataOutMoved;
CCCryptorUpdate(_cryptor, _ivec, 16, _ecount, 16, &dataOutMoved);
ctr128_inc_aligned(_ivec);
for (n = 0; n < 16; n += sizeof(size_t))
*(size_t *)(out + n) =
*(size_t *)(in + n) ^ *(size_t *)(_ecount + n);
len -= 16;
out += 16;
in += 16;
n = 0;
}
if (len) {
size_t dataOutMoved;
CCCryptorUpdate(_cryptor, _ivec, 16, _ecount, 16, &dataOutMoved);
ctr128_inc_aligned(_ivec);
while (len--) {
out[n] = in[n] ^ _ecount[n];
++n;
}
}
_num = n;
return;
} while (0);
}
/* the rest would be commonly eliminated by x86* compiler */
while (l < len) {
if (n == 0) {
size_t dataOutMoved;
CCCryptorUpdate(_cryptor, _ivec, 16, _ecount, 16, &dataOutMoved);
ctr128_inc(_ivec);
}
out[l] = in[l] ^ _ecount[n];
++l;
n = (n + 1) % 16;
}
_num = n;
}
@end

11
MTAtomic.h Normal file
View File

@ -0,0 +1,11 @@
#import <Foundation/Foundation.h>
@interface MTAtomic : NSObject
- (instancetype)initWithValue:(id)value;
- (id)swap:(id)newValue;
- (id)value;
- (id)modify:(id (^)(id))f;
- (id)with:(id (^)(id))f;
@end

64
MTAtomic.m Normal file
View File

@ -0,0 +1,64 @@
#import "MTAtomic.h"
#import <libkern/OSAtomic.h>
@interface MTAtomic ()
{
volatile OSSpinLock _lock;
id _value;
}
@end
@implementation MTAtomic
- (instancetype)initWithValue:(id)value
{
self = [super init];
if (self != nil)
{
_value = value;
}
return self;
}
- (id)swap:(id)newValue
{
id previousValue = nil;
OSSpinLockLock(&_lock);
previousValue = _value;
_value = newValue;
OSSpinLockUnlock(&_lock);
return previousValue;
}
- (id)value
{
id previousValue = nil;
OSSpinLockLock(&_lock);
previousValue = _value;
OSSpinLockUnlock(&_lock);
return previousValue;
}
- (id)modify:(id (^)(id))f
{
id newValue = nil;
OSSpinLockLock(&_lock);
newValue = f(_value);
_value = newValue;
OSSpinLockUnlock(&_lock);
return newValue;
}
- (id)with:(id (^)(id))f
{
id result = nil;
OSSpinLockLock(&_lock);
result = f(_value);
OSSpinLockUnlock(&_lock);
return result;
}
@end

11
MTBag.h Normal file
View File

@ -0,0 +1,11 @@
#import <Foundation/Foundation.h>
@interface MTBag : NSObject
- (NSInteger)addItem:(id)item;
- (void)enumerateItems:(void (^)(id))block;
- (void)removeItem:(NSInteger)key;
- (bool)isEmpty;
- (NSArray *)copyItems;
@end

74
MTBag.m Normal file
View File

@ -0,0 +1,74 @@
#import "MTBag.h"
@interface MTBag ()
{
NSInteger _nextKey;
NSMutableArray *_items;
NSMutableArray *_itemKeys;
}
@end
@implementation MTBag
- (instancetype)init
{
self = [super init];
if (self != nil)
{
_items = [[NSMutableArray alloc] init];
_itemKeys = [[NSMutableArray alloc] init];
}
return self;
}
- (NSInteger)addItem:(id)item
{
if (item == nil)
return -1;
NSInteger key = _nextKey;
[_items addObject:item];
[_itemKeys addObject:@(key)];
_nextKey++;
return key;
}
- (void)enumerateItems:(void (^)(id))block
{
if (block)
{
for (id item in _items)
{
block(item);
}
}
}
- (void)removeItem:(NSInteger)key
{
NSUInteger index = 0;
for (NSNumber *itemKey in _itemKeys)
{
if ([itemKey integerValue] == key)
{
[_items removeObjectAtIndex:index];
[_itemKeys removeObjectAtIndex:index];
break;
}
index++;
}
}
- (bool)isEmpty
{
return _items.count == 0;
}
- (NSArray *)copyItems
{
return [[NSArray alloc] initWithArray:_items];
}
@end

View File

@ -1,10 +1,10 @@
#import <Foundation/Foundation.h>
#import <SSignalKit/SSignalKit.h>
#import <MTProtoKit/MTContext.h>
@class MTContext;
@class MTSignal;
@interface MTDiscoverConnectionSignals : NSObject
+ (SSignal *)discoverSchemeWithContext:(MTContext *)context addressList:(NSArray *)addressList media:(bool)media;
+ (MTSignal *)discoverSchemeWithContext:(MTContext *)context addressList:(NSArray *)addressList media:(bool)media;
@end

View File

@ -2,9 +2,39 @@
#import "MTTcpConnection.h"
#import "MTHttpWorker.h"
#import "MTTransportScheme.h"
#import "MTTcpTransport.h"
#import "MTHttpTransport.h"
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTTransportScheme.h>
# import <MTProtoKitDynamic/MTTcpTransport.h>
# import <MTProtoKitDynamic/MTHttpTransport.h>
# import <MTProtoKitDynamic/MTQueue.h>
# import <MTProtoKitDynamic/MTProtoKitDynamic.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTTransportScheme.h>
# import <MTProtoKitMac/MTTcpTransport.h>
# import <MTProtoKitMac/MTHttpTransport.h>
# import <MTProtoKitMac/MTQueue.h>
# import <MTProtoKitMac/MTProtoKitMac.h>
#else
# import <MTProtoKit/MTTransportScheme.h>
# import <MTProtoKit/MTTcpTransport.h>
# import <MTProtoKit/MTHttpTransport.h>
# import <MTProtoKit/MTQueue.h>
# import <MTProtoKit/MTProtoKit.h>
#endif
#import "MTDatacenterAddress.h"
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTDisposable.h>
# import <MTProtoKitDynamic/MTSignal.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTDisposable.h>
# import <MTProtoKitMac/MTSignal.h>
#else
# import <MTProtoKit/MTDisposable.h>
# import <MTProtoKit/MTSignal.h>
#endif
#import <netinet/in.h>
#import <arpa/inet.h>
@ -63,14 +93,14 @@ typedef struct {
return success == 1;
}
+ (SSignal *)tcpConnectionWithContext:(MTContext *)context datacenterId:(NSUInteger)datacenterId address:(MTDatacenterAddress *)address;
+ (MTSignal *)tcpConnectionWithContext:(MTContext *)context datacenterId:(NSUInteger)datacenterId address:(MTDatacenterAddress *)address;
{
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
MTPayloadData payloadData;
NSData *data = [self payloadData:&payloadData];
MTTcpConnection *connection = [[MTTcpConnection alloc] initWithContext:context datacenterId:datacenterId address:address interface:nil];
MTTcpConnection *connection = [[MTTcpConnection alloc] initWithContext:context datacenterId:datacenterId address:address interface:nil usageCalculationInfo:nil];
__weak MTTcpConnection *weakConnection = connection;
connection.connectionOpened = ^
{
@ -84,34 +114,43 @@ typedef struct {
received = true;
if ([self isResponseValid:data payloadData:payloadData])
{
MTLog(@"success tcp://%@:%d", address.ip, (int)address.port);
if (MTLogEnabled()) {
MTLog(@"success tcp://%@:%d", address.ip, (int)address.port);
}
[subscriber putCompletion];
}
else
{
MTLog(@"failed tcp://%@:%d", address.ip, (int)address.port);
if (MTLogEnabled()) {
MTLog(@"failed tcp://%@:%d", address.ip, (int)address.port);
}
[subscriber putError:nil];
}
};
connection.connectionClosed = ^
{
if (!received)
MTLog(@"failed tcp://%@:%d", address.ip, (int)address.port);
if (!received) {
if (MTLogEnabled()) {
MTLog(@"failed tcp://%@:%d", address.ip, (int)address.port);
}
}
[subscriber putError:nil];
};
MTLog(@"trying tcp://%@:%d", address.ip, (int)address.port);
if (MTLogEnabled()) {
MTLog(@"trying tcp://%@:%d", address.ip, (int)address.port);
}
[connection start];
return [[SBlockDisposable alloc] initWithBlock:^
return [[MTBlockDisposable alloc] initWithBlock:^
{
[connection stop];
}];
}];
}
+ (SSignal *)httpConnectionWithAddress:(MTDatacenterAddress *)address
+ (MTSignal *)httpConnectionWithAddress:(MTDatacenterAddress *)address
{
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
MTPayloadData payloadData;
NSData *data = [self payloadData:&payloadData];
@ -130,10 +169,12 @@ typedef struct {
[subscriber putError:nil];
};
MTLog(@"trying http://%@:%d", address.ip, (int)address.port);
if (MTLogEnabled()) {
MTLog(@"trying http://%@:%d", address.ip, (int)address.port);
}
MTHttpWorker *httpWorker = [[MTHttpWorker alloc] initWithDelegate:delegate address:address payloadData:data performsLongPolling:false];
return [[SBlockDisposable alloc] initWithBlock:^
return [[MTBlockDisposable alloc] initWithBlock:^
{
[delegate description]; // keep reference
[httpWorker stop];
@ -141,7 +182,7 @@ typedef struct {
}];
}
+ (SSignal *)discoverSchemeWithContext:(MTContext *)context addressList:(NSArray *)addressList media:(bool)media
+ (MTSignal *)discoverSchemeWithContext:(MTContext *)context addressList:(NSArray *)addressList media:(bool)media
{
NSMutableArray *bestAddressList = [[NSMutableArray alloc] init];
@ -165,52 +206,52 @@ typedef struct {
if ([self isIpv6:address.ip])
{
SSignal *signal = [[[[self tcpConnectionWithContext:context datacenterId:0 address:address] then:[SSignal single:tcpTransportScheme]] timeout:5.0 onQueue:[SQueue concurrentDefaultQueue] orSignal:[SSignal fail:nil]] catch:^SSignal *(__unused id error)
MTSignal *signal = [[[[self tcpConnectionWithContext:context datacenterId:0 address:address] then:[MTSignal single:tcpTransportScheme]] timeout:5.0 onQueue:[MTQueue concurrentDefaultQueue] orSignal:[MTSignal fail:nil]] catch:^MTSignal *(__unused id error)
{
return [SSignal complete];
return [MTSignal complete];
}];
[bestTcp6Signals addObject:signal];
}
else
{
SSignal *tcpConnectionWithTimeout = [[[self tcpConnectionWithContext:context datacenterId:0 address:address] then:[SSignal single:tcpTransportScheme]] timeout:5.0 onQueue:[SQueue concurrentDefaultQueue] orSignal:[SSignal fail:nil]];
SSignal *signal = [tcpConnectionWithTimeout catch:^SSignal *(__unused id error)
MTSignal *tcpConnectionWithTimeout = [[[self tcpConnectionWithContext:context datacenterId:0 address:address] then:[MTSignal single:tcpTransportScheme]] timeout:5.0 onQueue:[MTQueue concurrentDefaultQueue] orSignal:[MTSignal fail:nil]];
MTSignal *signal = [tcpConnectionWithTimeout catch:^MTSignal *(__unused id error)
{
return [SSignal complete];
return [MTSignal complete];
}];
[bestTcp4Signals addObject:signal];
}
if (!address.restrictToTcp) {
SSignal *signal = [[[[self httpConnectionWithAddress:address] then:[SSignal single:httpTransportScheme]] timeout:5.0 onQueue:[SQueue concurrentDefaultQueue] orSignal:[SSignal fail:nil]] catch:^SSignal *(__unused id error)
MTSignal *signal = [[[[self httpConnectionWithAddress:address] then:[MTSignal single:httpTransportScheme]] timeout:5.0 onQueue:[MTQueue concurrentDefaultQueue] orSignal:[MTSignal fail:nil]] catch:^MTSignal *(__unused id error)
{
return [SSignal complete];
return [MTSignal complete];
}];
[bestHttpSignals addObject:signal];
}
}
SSignal *repeatDelaySignal = [[SSignal complete] delay:1.0 onQueue:[SQueue concurrentDefaultQueue]];
SSignal *optimalDelaySignal = [[SSignal complete] delay:30.0 onQueue:[SQueue concurrentDefaultQueue]];
MTSignal *repeatDelaySignal = [[MTSignal complete] delay:1.0 onQueue:[MTQueue concurrentDefaultQueue]];
MTSignal *optimalDelaySignal = [[MTSignal complete] delay:30.0 onQueue:[MTQueue concurrentDefaultQueue]];
SSignal *firstTcp4Match = [[[[SSignal mergeSignals:bestTcp4Signals] then:repeatDelaySignal] restart] take:1];
SSignal *firstTcp6Match = [[[[SSignal mergeSignals:bestTcp6Signals] then:repeatDelaySignal] restart] take:1];
SSignal *firstHttpMatch = [[[[SSignal mergeSignals:bestHttpSignals] then:repeatDelaySignal] restart] take:1];
MTSignal *firstTcp4Match = [[[[MTSignal mergeSignals:bestTcp4Signals] then:repeatDelaySignal] restart] take:1];
MTSignal *firstTcp6Match = [[[[MTSignal mergeSignals:bestTcp6Signals] then:repeatDelaySignal] restart] take:1];
MTSignal *firstHttpMatch = [[[[MTSignal mergeSignals:bestHttpSignals] then:repeatDelaySignal] restart] take:1];
SSignal *optimalTcp4Match = [[[[SSignal mergeSignals:bestTcp4Signals] then:optimalDelaySignal] restart] take:1];
SSignal *optimalTcp6Match = [[[[SSignal mergeSignals:bestTcp6Signals] then:optimalDelaySignal] restart] take:1];
MTSignal *optimalTcp4Match = [[[[MTSignal mergeSignals:bestTcp4Signals] then:optimalDelaySignal] restart] take:1];
MTSignal *optimalTcp6Match = [[[[MTSignal mergeSignals:bestTcp6Signals] then:optimalDelaySignal] restart] take:1];
SSignal *anySignal = [[SSignal mergeSignals:@[firstTcp4Match, firstTcp6Match, firstHttpMatch]] take:1];
SSignal *optimalSignal = [[SSignal mergeSignals:@[optimalTcp4Match, optimalTcp6Match]] take:1];
MTSignal *anySignal = [[MTSignal mergeSignals:@[firstTcp4Match, firstTcp6Match, firstHttpMatch]] take:1];
MTSignal *optimalSignal = [[MTSignal mergeSignals:@[optimalTcp4Match, optimalTcp6Match]] take:1];
SSignal *signal = [anySignal mapToSignal:^SSignal *(MTTransportScheme *scheme)
MTSignal *signal = [anySignal mapToSignal:^MTSignal *(MTTransportScheme *scheme)
{
if (![scheme isOptimal])
{
return [[SSignal single:scheme] then:[optimalSignal delay:5.0 onQueue:[SQueue concurrentDefaultQueue]]];
return [[MTSignal single:scheme] then:[optimalSignal delay:5.0 onQueue:[MTQueue concurrentDefaultQueue]]];
}
else
return [SSignal single:scheme];
return [MTSignal single:scheme];
}];
return signal;

26
MTDisposable.h Normal file
View File

@ -0,0 +1,26 @@
#import <Foundation/Foundation.h>
@protocol MTDisposable <NSObject>
- (void)dispose;
@end
@interface MTBlockDisposable : NSObject <MTDisposable>
- (instancetype)initWithBlock:(void (^)())block;
@end
@interface MTMetaDisposable : NSObject <MTDisposable>
- (void)setDisposable:(id<MTDisposable>)disposable;
@end
@interface MTDisposableSet : NSObject <MTDisposable>
- (void)add:(id<MTDisposable>)disposable;
- (void)remove:(id<MTDisposable>)disposable;
@end

198
MTDisposable.m Normal file
View File

@ -0,0 +1,198 @@
#import "MTDisposable.h"
#import <libkern/OSAtomic.h>
#import <objc/runtime.h>
@interface MTBlockDisposable ()
{
void *_block;
}
@end
@implementation MTBlockDisposable
- (instancetype)initWithBlock:(void (^)())block
{
self = [super init];
if (self != nil)
{
_block = (__bridge_retained void *)[block copy];
}
return self;
}
- (void)dealloc
{
void *block = _block;
if (block != NULL)
{
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
{
if (block != nil)
{
__strong id strongBlock = (__bridge_transfer id)block;
strongBlock = nil;
}
}
}
}
- (void)dispose
{
void *block = _block;
if (block != NULL)
{
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
{
if (block != nil)
{
__strong id strongBlock = (__bridge_transfer id)block;
((dispatch_block_t)strongBlock)();
strongBlock = nil;
}
}
}
}
@end
@interface MTMetaDisposable ()
{
OSSpinLock _lock;
bool _disposed;
id<MTDisposable> _disposable;
}
@end
@implementation MTMetaDisposable
- (void)setDisposable:(id<MTDisposable>)disposable
{
id<MTDisposable> previousDisposable = nil;
bool dispose = false;
OSSpinLockLock(&_lock);
dispose = _disposed;
if (!dispose)
{
previousDisposable = _disposable;
_disposable = disposable;
}
OSSpinLockUnlock(&_lock);
if (previousDisposable != nil)
[previousDisposable dispose];
if (dispose)
[disposable dispose];
}
- (void)dispose
{
id<MTDisposable> disposable = nil;
OSSpinLockLock(&_lock);
if (!_disposed)
{
disposable = _disposable;
_disposed = true;
}
OSSpinLockUnlock(&_lock);
if (disposable != nil)
[disposable dispose];
}
@end
@interface MTDisposableSet ()
{
OSSpinLock _lock;
bool _disposed;
id<MTDisposable> _singleDisposable;
NSArray *_multipleDisposables;
}
@end
@implementation MTDisposableSet
- (void)add:(id<MTDisposable>)disposable
{
if (disposable == nil)
return;
bool dispose = false;
OSSpinLockLock(&_lock);
dispose = _disposed;
if (!dispose)
{
if (_multipleDisposables != nil)
{
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
[multipleDisposables addObject:disposable];
_multipleDisposables = multipleDisposables;
}
else if (_singleDisposable != nil)
{
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithObjects:_singleDisposable, disposable, nil];
_multipleDisposables = multipleDisposables;
_singleDisposable = nil;
}
else
{
_singleDisposable = disposable;
}
}
OSSpinLockUnlock(&_lock);
if (dispose)
[disposable dispose];
}
- (void)remove:(id<MTDisposable>)disposable {
OSSpinLockLock(&_lock);
if (_multipleDisposables != nil)
{
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
[multipleDisposables removeObject:disposable];
_multipleDisposables = multipleDisposables;
}
else if (_singleDisposable == disposable)
{
_singleDisposable = nil;
}
OSSpinLockUnlock(&_lock);
}
- (void)dispose
{
id<MTDisposable> singleDisposable = nil;
NSArray *multipleDisposables = nil;
OSSpinLockLock(&_lock);
if (!_disposed)
{
_disposed = true;
singleDisposable = _singleDisposable;
multipleDisposables = _multipleDisposables;
_singleDisposable = nil;
_multipleDisposables = nil;
}
OSSpinLockUnlock(&_lock);
if (singleDisposable != nil)
[singleDisposable dispose];
if (multipleDisposables != nil)
{
for (id<MTDisposable> disposable in multipleDisposables)
{
[disposable dispose];
}
}
}
@end

View File

@ -0,0 +1,15 @@
#import <Foundation/Foundation.h>
@class MTQueue;
@interface MTNetworkUsageCalculationInfo : NSObject
@property (nonatomic, strong, readonly) NSString *filePath;
@property (nonatomic, readonly) int32_t incomingWWANKey;
@property (nonatomic, readonly) int32_t outgoingWWANKey;
@property (nonatomic, readonly) int32_t incomingOtherKey;
@property (nonatomic, readonly) int32_t outgoingOtherKey;
- (instancetype)initWithFilePath:(NSString *)filePath incomingWWANKey:(int32_t)incomingWWANKey outgoingWWANKey:(int32_t)outgoingWWANKey incomingOtherKey:(int32_t)incomingOtherKey outgoingOtherKey:(int32_t)outgoingOtherKey;
@end

View File

@ -0,0 +1,17 @@
#import "MTNetworkUsageCalculationInfo.h"
@implementation MTNetworkUsageCalculationInfo
- (instancetype)initWithFilePath:(NSString *)filePath incomingWWANKey:(int32_t)incomingWWANKey outgoingWWANKey:(int32_t)outgoingWWANKey incomingOtherKey:(int32_t)incomingOtherKey outgoingOtherKey:(int32_t)outgoingOtherKey {
self = [super init];
if (self != nil) {
_filePath = filePath;
_incomingWWANKey = incomingWWANKey;
_outgoingWWANKey = outgoingWWANKey;
_incomingOtherKey = incomingOtherKey;
_outgoingOtherKey = outgoingOtherKey;
}
return self;
}
@end

26
MTNetworkUsageManager.h Normal file
View File

@ -0,0 +1,26 @@
#import <Foundation/Foundation.h>
@class MTSignal;
@class MTNetworkUsageCalculationInfo;
typedef enum {
MTNetworkUsageManagerInterfaceWWAN,
MTNetworkUsageManagerInterfaceOther
} MTNetworkUsageManagerInterface;
typedef struct {
NSUInteger incomingBytes;
NSUInteger outgoingBytes;
} MTNetworkUsageManagerInterfaceStats;
@interface MTNetworkUsageManager : NSObject
- (instancetype)initWithInfo:(MTNetworkUsageCalculationInfo *)info;
- (void)addIncomingBytes:(NSUInteger)incomingBytes interface:(MTNetworkUsageManagerInterface)interface;
- (void)addOutgoingBytes:(NSUInteger)outgoingBytes interface:(MTNetworkUsageManagerInterface)interface;
- (void)resetKeys:(NSArray<NSNumber *> *)keys completion:(void (^)())completion;
- (MTSignal *)currentStatsForKeys:(NSArray<NSNumber *> *)keys;
@end

140
MTNetworkUsageManager.m Normal file
View File

@ -0,0 +1,140 @@
#import "MTNetworkUsageManager.h"
#include <sys/mman.h>
#import <libkern/OSAtomic.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTNetworkUsageCalculationInfo.h>
# import <MTProtoKitDynamic/MTSignal.h>
# import <MTProtoKitDynamic/MTTimer.h>
# import <MTProtoKitDynamic/MTQueue.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTNetworkUsageCalculationInfo.h>
# import <MTProtoKitMac/MTSignal.h>
# import <MTProtoKitMac/MTTimer.h>
# import <MTProtoKitMac/MTQueue.h>
#else
# import <MTProtoKit/MTNetworkUsageCalculationInfo.h>
# import <MTProtoKit/MTSignal.h>
# import <MTProtoKit/MTTimer.h>
# import <MTProtoKit/MTQueue.h>
#endif
@interface MTNetworkUsageManager () {
MTQueue *_queue;
MTNetworkUsageCalculationInfo *_info;
NSUInteger _pendingIncomingBytes;
NSUInteger _pendingOutgoingBytes;
int _fd;
void *_map;
}
@end
@implementation MTNetworkUsageManager
- (instancetype)initWithInfo:(MTNetworkUsageCalculationInfo *)info {
self = [super init];
if (self != nil) {
_queue = [[MTQueue alloc] init];
_info = info;
NSString *path = info.filePath;
int32_t fd = open([path UTF8String], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd >= 0) {
_fd = fd;
ftruncate(fd, 4096);
void *map = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map != MAP_FAILED) {
_map = map;
}
}
}
return self;
}
- (void)dealloc {
void *map = _map;
int32_t fd = _fd;
[_queue dispatchOnQueue:^{
if (map) {
munmap(map, 4096);
}
if (fd > 0) {
close(fd);
}
}];
}
static int offsetForInterface(MTNetworkUsageCalculationInfo *info, MTNetworkUsageManagerInterface interface, bool incoming) {
switch (interface) {
case MTNetworkUsageManagerInterfaceWWAN:
if (incoming) {
return info.incomingWWANKey * 8;
} else {
return info.outgoingWWANKey * 8;
}
case MTNetworkUsageManagerInterfaceOther:
if (incoming) {
return info.incomingOtherKey * 8;
} else {
return info.outgoingOtherKey * 8;
}
}
}
- (void)addIncomingBytes:(NSUInteger)incomingBytes interface:(MTNetworkUsageManagerInterface)interface {
[_queue dispatchOnQueue:^{
if (_map) {
int64_t *ptr = (int64_t *)(_map + offsetForInterface(_info, interface, true));
OSAtomicAdd64((int64_t)incomingBytes, ptr);
}
}];
}
- (void)addOutgoingBytes:(NSUInteger)outgoingBytes interface:(MTNetworkUsageManagerInterface)interface {
[_queue dispatchOnQueue:^{
if (_map) {
int64_t *ptr = (int64_t *)(_map + offsetForInterface(_info, interface, false));
OSAtomicAdd64((int64_t)outgoingBytes, ptr);
}
}];
}
- (void)resetKeys:(NSArray<NSNumber *> *)keys completion:(void (^)())completion {
[_queue dispatchOnQueue:^{
if (_map) {
for (NSNumber *key in keys) {
int64_t *ptr = (int64_t *)(_map + [key intValue] * 8);
*ptr = 0;
}
if (completion) {
completion();
}
}
}];
}
- (MTSignal *)currentStatsForKeys:(NSArray<NSNumber *> *)keys {
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
[_queue dispatchOnQueue:^{
if (_map) {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
for (NSNumber *key in keys) {
int64_t *ptr = (int64_t *)(_map + [key intValue] * 8);
result[key] = @(*ptr);
}
[subscriber putNext:result];
} else {
[subscriber putNext:nil];
}
[subscriber putCompletion];
}];
return nil;
}];
}
@end

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.telegram.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTApiEnvironment.h>
#import "MTApiEnvironment.h"
#if TARGET_OS_IPHONE
# import <UIKit/UIKit.h>
@ -31,6 +31,8 @@
#define IPHONE_6Plus_NAMESTRING @"iPhone 6 Plus"
#define IPHONE_6S_NAMESTRING @"iPhone 6S"
#define IPHONE_6SPlus_NAMESTRING @"iPhone 6S Plus"
#define IPHONE_7_NAMESTRING @"iPhone 7"
#define IPHONE_7Plus_NAMESTRING @"iPhone 7 Plus"
#define IPHONE_UNKNOWN_NAMESTRING @"Unknown iPhone"
#define IPOD_1G_NAMESTRING @"iPod touch 1G"
@ -79,6 +81,8 @@ typedef enum {
UIDevice6PlusiPhone,
UIDevice6siPhone,
UIDevice6SPlusiPhone,
UIDevice7iPhone,
UIDevice7PlusiPhone,
UIDevice1GiPod,
UIDevice2GiPod,
@ -136,11 +140,27 @@ typedef enum {
_langCode = [[NSLocale preferredLanguages] objectAtIndex:0];
_apiInitializationHash = [[NSString alloc] initWithFormat:@"apiId=%" PRId32 "&deviceModel=%@&systemVersion=%@&appVersion=%@&langCode=%@&layer=%@", _apiId, _deviceModel, _systemVersion, _appVersion, _langCode, _layer];
[self _updateApiInitializationHash];
}
return self;
}
- (void)_updateApiInitializationHash {
_apiInitializationHash = [[NSString alloc] initWithFormat:@"apiId=%" PRId32 "&deviceModel=%@&systemVersion=%@&appVersion=%@&langCode=%@&layer=%@", _apiId, _deviceModel, _systemVersion, _appVersion, _langCode, _layer];
}
- (void)setLayer:(NSNumber *)layer {
_layer = layer;
[self _updateApiInitializationHash];
}
- (void)setAppVersion:(NSString *)appVersion {
_appVersion = appVersion;
[self _updateApiInitializationHash];
}
- (NSString *)platformString
{
switch ([self platformType])
@ -156,6 +176,8 @@ typedef enum {
case UIDevice6PlusiPhone: return IPHONE_6Plus_NAMESTRING;
case UIDevice6siPhone: return IPHONE_6S_NAMESTRING;
case UIDevice6SPlusiPhone: return IPHONE_6SPlus_NAMESTRING;
case UIDevice7iPhone: return IPHONE_7_NAMESTRING;
case UIDevice7PlusiPhone: return IPHONE_7Plus_NAMESTRING;
case UIDeviceUnknowniPhone: return IPHONE_UNKNOWN_NAMESTRING;
case UIDevice1GiPod: return IPOD_1G_NAMESTRING;
@ -212,6 +234,8 @@ typedef enum {
if ([platform isEqualToString:@"iPhone7,2"]) return UIDevice6iPhone;
if ([platform isEqualToString:@"iPhone8,1"]) return UIDevice6siPhone;
if ([platform isEqualToString:@"iPhone8,2"]) return UIDevice6SPlusiPhone;
if ([platform isEqualToString:@"iPhone9,3"]) return UIDevice7iPhone;
if ([platform isEqualToString:@"iPhone9,2"]) return UIDevice7PlusiPhone;
// iPod
if ([platform hasPrefix:@"iPod1"]) return UIDevice1GiPod;
@ -240,8 +264,7 @@ typedef enum {
// Simulator thanks Jordan Breeding
if ([platform hasSuffix:@"86"] || [platform isEqual:@"x86_64"])
{
BOOL smallerScreen = [[UIScreen mainScreen] bounds].size.width < 768;
return smallerScreen ? UIDeviceSimulatoriPhone : UIDeviceSimulatoriPad;
return UIDeviceSimulatoriPhone;
}
#else
return UIDeviceOSX;

View File

@ -6,33 +6,45 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTContext.h>
#import "MTContext.h"
#import <inttypes.h>
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTTimer.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTKeychain.h>
#import "MTLogging.h"
#import "MTTimer.h"
#import "MTQueue.h"
#import "MTKeychain.h"
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import <MTProtoKit/MTDatacenterAuthInfo.h>
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import <MTProtoKit/MTSessionInfo.h>
#import "MTDatacenterAddressSet.h"
#import "MTDatacenterAddress.h"
#import "MTDatacenterAuthInfo.h"
#import "MTDatacenterSaltInfo.h"
#import "MTSessionInfo.h"
#import <MTProtoKit/MTDiscoverDatacenterAddressAction.h>
#import <MTProtoKit/MTDatacenterAuthAction.h>
#import <MTProtoKit/MTDatacenterTransferAuthAction.h>
#import "MTDiscoverDatacenterAddressAction.h"
#import "MTDatacenterAuthAction.h"
#import "MTDatacenterTransferAuthAction.h"
#import <MTProtoKit/MTTransportScheme.h>
#import <MTProtoKit/MTTcpTransport.h>
#import "MTTransportScheme.h"
#import "MTTcpTransport.h"
#import <MTProtoKit/MTApiEnvironment.h>
#import "MTApiEnvironment.h"
#import <libkern/OSAtomic.h>
#import "MTDiscoverConnectionSignals.h"
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTDisposable.h>
# import <MTProtoKitDynamic/MTSignal.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTDisposable.h>
# import <MTProtoKitMac/MTSignal.h>
#else
# import <MTProtoKit/MTDisposable.h>
# import <MTProtoKit/MTSignal.h>
#endif
@implementation MTContextBlockChangeListener
- (void)contextIsPasswordRequiredUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId
@ -63,7 +75,6 @@
NSMutableArray *_changeListeners;
NSMutableDictionary *_discoverDatacenterAddressActions;
NSMutableDictionary *_discoverDatacenterTransportSchemeActions;
NSMutableDictionary *_datacenterAuthActions;
NSMutableDictionary *_datacenterTransferAuthActions;
@ -121,7 +132,6 @@
_changeListeners = [[NSMutableArray alloc] init];
_discoverDatacenterAddressActions = [[NSMutableDictionary alloc] init];
_discoverDatacenterTransportSchemeActions = [[NSMutableDictionary alloc] init];
_datacenterAuthActions = [[NSMutableDictionary alloc] init];
_datacenterTransferAuthActions = [[NSMutableDictionary alloc] init];
@ -159,9 +169,6 @@
NSDictionary *discoverDatacenterAddressActions = _discoverDatacenterAddressActions;
_discoverDatacenterAddressActions = nil;
NSDictionary *discoverDatacenterTransportSchemeActions = _discoverDatacenterTransportSchemeActions;
_discoverDatacenterTransportSchemeActions = nil;
NSDictionary *datacenterTransferAuthActions = _datacenterTransferAuthActions;
_datacenterTransferAuthActions = nil;
@ -288,7 +295,9 @@
{
_globalTimeDifference = globalTimeDifference;
MTLog(@"[MTContext#%x: global time difference changed: %.1fs]", (int)self, globalTimeDifference);
if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: global time difference changed: %.1fs]", (int)self, globalTimeDifference);
}
[_keychain setObject:@(_globalTimeDifference) forKey:@"globalTimeDifference" group:@"temp"];
}];
@ -308,7 +317,9 @@
{
if (addressSet != nil && datacenterId != 0)
{
MTLog(@"[MTContext#%x: address set updated for %d]", (int)self, datacenterId);
if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: address set updated for %d]", (int)self, datacenterId);
}
bool previousAddressSetWasEmpty = ((MTDatacenterAddressSet *)_datacenterAddressSetById[@(datacenterId)]).addressList.count == 0;
@ -359,7 +370,9 @@
if (updated)
{
MTLog(@"[MTContext#%x: added address %@ for datacenter %d]", (int)self, address, datacenterId);
if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: added address %@ for datacenter %d]", (int)self, address, datacenterId);
}
_datacenterAddressSetById[@(datacenterId)] = addressSet;
[_keychain setObject:_datacenterAddressSetById forKey:@"datacenterAddressSetById" group:@"persistent"];
@ -381,7 +394,9 @@
{
if (authInfo != nil && datacenterId != 0)
{
MTLog(@"[MTContext#%x: auth info updated for %d]", (int)self, datacenterId);
if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: auth info updated for %d]", (int)self, datacenterId);
}
_datacenterAuthInfoById[@(datacenterId)] = authInfo;
[_keychain setObject:_datacenterAuthInfoById forKey:@"datacenterAuthInfoById" group:@"persistent"];
@ -461,7 +476,9 @@
if (currentScheme != nil && (previousScheme == nil || ![previousScheme isEqualToScheme:currentScheme]))
{
MTLog(@"[MTContext#%x: %@ transport scheme updated for %d: %@]", (int)self, media ? @"media" : @"generic", datacenterId, transportScheme);
if (MTLogEnabled()) {
MTLog(@"[MTContext#%x: %@ transport scheme updated for %d: %@]", (int)self, media ? @"media" : @"generic", datacenterId, transportScheme);
}
for (id<MTContextChangeListener> listener in currentListeners)
{
@ -748,7 +765,7 @@
{
if (_transportSchemeDisposableByDatacenterId == nil)
_transportSchemeDisposableByDatacenterId = [[NSMutableDictionary alloc] init];
id<SDisposable> disposable = _transportSchemeDisposableByDatacenterId[@(datacenterId)];
id<MTDisposable> disposable = _transportSchemeDisposableByDatacenterId[@(datacenterId)];
if (disposable == nil)
{
__weak MTContext *weakSelf = self;
@ -765,7 +782,9 @@
}
}] startWithNext:^(id next)
{
MTLog(@"scheme: %@", next);
if (MTLogEnabled()) {
MTLog(@"scheme: %@", next);
}
__strong MTContext *strongSelf = weakSelf;
if (strongSelf != nil)
{
@ -801,7 +820,7 @@
{
if (_transportSchemeDisposableByDatacenterId == nil)
_transportSchemeDisposableByDatacenterId = [[NSMutableDictionary alloc] init];
id<SDisposable> disposable = _transportSchemeDisposableByDatacenterId[@(datacenterId)];
id<MTDisposable> disposable = _transportSchemeDisposableByDatacenterId[@(datacenterId)];
[disposable dispose];
[_transportSchemeDisposableByDatacenterId removeObjectForKey:@(datacenterId)];
}

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAddress.h>
#import "MTDatacenterAddress.h"
#import <netinet/in.h>
#import <arpa/inet.h>

View File

@ -6,7 +6,9 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAddress.h>
#import <Foundation/Foundation.h>
@class MTDatacenterAddress;
@interface MTDatacenterAddressSet : NSObject <NSCoding>

View File

@ -6,7 +6,9 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import "MTDatacenterAddressSet.h"
#import "MTDatacenterAddress.h"
@implementation MTDatacenterAddressSet

View File

@ -6,14 +6,14 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAuthAction.h>
#import "MTDatacenterAuthAction.h"
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTRequest.h>
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import "MTContext.h"
#import "MTProto.h"
#import "MTRequest.h"
#import "MTDatacenterSaltInfo.h"
#import <MTProtoKit/MTDatacenterAuthMessageService.h>
#import "MTDatacenterAuthMessageService.h"
@interface MTDatacenterAuthAction () <MTDatacenterAuthMessageServiceDelegate>
{
@ -44,7 +44,7 @@
[self complete];
else
{
_authMtProto = [[MTProto alloc] initWithContext:context datacenterId:_datacenterId];
_authMtProto = [[MTProto alloc] initWithContext:context datacenterId:_datacenterId usageCalculationInfo:nil];
_authMtProto.useUnauthorizedMode = true;
MTDatacenterAuthMessageService *authService = [[MTDatacenterAuthMessageService alloc] initWithContext:context];

View File

@ -6,9 +6,8 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAuthInfo.h>
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import "MTDatacenterAuthInfo.h"
#import "MTDatacenterSaltInfo.h"
@implementation MTDatacenterAuthInfo

View File

@ -6,7 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTMessageService.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTMessageService.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTMessageService.h>
#else
# import <MTProtoKit/MTMessageService.h>
#endif
@class MTContext;
@class MTDatacenterAuthMessageService;

View File

@ -6,27 +6,27 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAuthMessageService.h>
#import "MTDatacenterAuthMessageService.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTSessionInfo.h>
#import <MTProtoKit/MTIncomingMessage.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTPreparedMessage.h>
#import <MTProtoKit/MTDatacenterAuthInfo.h>
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import <MTProtoKit/MTBuffer.h>
#import <MTProtoKit/MTEncryption.h>
#import "MTLogging.h"
#import "MTContext.h"
#import "MTProto.h"
#import "MTSerialization.h"
#import "MTSessionInfo.h"
#import "MTIncomingMessage.h"
#import "MTOutgoingMessage.h"
#import "MTMessageTransaction.h"
#import "MTPreparedMessage.h"
#import "MTDatacenterAuthInfo.h"
#import "MTDatacenterSaltInfo.h"
#import "MTBuffer.h"
#import "MTEncryption.h"
#import <MTProtoKit/MTInternalMessageParser.h>
#import <MTProtoKit/MTServerDhInnerDataMessage.h>
#import <MTProtoKit/MTResPqMessage.h>
#import <MTProtoKit/MTServerDhParamsMessage.h>
#import <MTProtoKit/MTSetClientDhParamsResponseMessage.h>
#import "MTInternalMessageParser.h"
#import "MTServerDhInnerDataMessage.h"
#import "MTResPqMessage.h"
#import "MTServerDhParamsMessage.h"
#import "MTSetClientDhParamsResponseMessage.h"
static NSDictionary *selectPublicKey(NSArray *fingerprints)
{
@ -178,7 +178,7 @@ typedef enum {
if (_nonce == nil)
{
uint8_t nonceBytes[16];
SecRandomCopyBytes(kSecRandomDefault, 16, nonceBytes);
__unused int result = SecRandomCopyBytes(kSecRandomDefault, 16, nonceBytes);
_nonce = [[NSData alloc] initWithBytes:nonceBytes length:16];
}
@ -260,7 +260,9 @@ typedef enum {
NSDictionary *publicKey = selectPublicKey(resPqMessage.serverPublicKeyFingerprints);
if (publicKey == nil)
{
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't find valid server public key]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't find valid server public key]", self);
}
[self reset:mtProto];
}
else
@ -306,7 +308,7 @@ typedef enum {
_dhPublicKeyFingerprint = [[publicKey objectForKey:@"fingerprint"] longLongValue];
uint8_t nonceBytes[32];
SecRandomCopyBytes(kSecRandomDefault, 32, nonceBytes);
__unused int result = SecRandomCopyBytes(kSecRandomDefault, 32, nonceBytes);
_newNonce = [[NSData alloc] initWithBytes:nonceBytes length:32];
MTBuffer *innerDataBuffer = [[MTBuffer alloc] init];
@ -414,7 +416,9 @@ typedef enum {
if (!hashVerified)
{
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't decode DH params]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't decode DH params]", self);
}
[self reset:mtProto];
return;
@ -424,7 +428,9 @@ typedef enum {
if (![dhInnerData isKindOfClass:[MTServerDhInnerDataMessage class]])
{
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't parse decoded DH params]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't parse decoded DH params]", self);
}
[self reset:mtProto];
return;
@ -432,7 +438,9 @@ typedef enum {
if (![_nonce isEqualToData:dhInnerData.nonce])
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH nonce]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH nonce]", self);
}
[self reset:mtProto];
return;
@ -440,7 +448,9 @@ typedef enum {
if (![_serverNonce isEqualToData:dhInnerData.serverNonce])
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH server nonce]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH server nonce]", self);
}
[self reset:mtProto];
return;
@ -449,7 +459,9 @@ typedef enum {
int32_t innerDataG = dhInnerData.g;
if (innerDataG < 0 || !MTCheckIsSafeG((unsigned int)innerDataG))
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH g]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH g]", self);
}
[self reset:mtProto];
return;
@ -459,7 +471,9 @@ typedef enum {
NSData *innerDataDhPrime = dhInnerData.dhPrime;
if (!MTCheckIsSafeGAOrB(innerDataGA, innerDataDhPrime))
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH g_a]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH g_a]", self);
}
[self reset:mtProto];
return;
@ -467,7 +481,9 @@ typedef enum {
if (!MTCheckMod(innerDataDhPrime, (unsigned int)innerDataG, mtProto.context.keychain))
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH g (2)]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH g (2)]", self);
}
[self reset:mtProto];
return;
@ -475,14 +491,16 @@ typedef enum {
if (!MTCheckIsSafePrime(innerDataDhPrime, mtProto.context.keychain))
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH prime]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH prime]", self);
}
[self reset:mtProto];
return;
}
uint8_t bBytes[256];
SecRandomCopyBytes(kSecRandomDefault, 256, bBytes);
__unused int result = SecRandomCopyBytes(kSecRandomDefault, 256, bBytes);
NSData *b = [[NSData alloc] initWithBytes:bBytes length:256];
int32_t tmpG = innerDataG;
@ -536,7 +554,9 @@ typedef enum {
}
else
{
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't set DH params]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p couldn't set DH params]", self);
}
[self reset:mtProto];
}
}
@ -578,7 +598,9 @@ typedef enum {
{
if (![newNonceHash1 isEqualToData:((MTSetClientDhParamsResponseOkMessage *)setClientDhParamsResponseMessage).nextNonceHash1])
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH answer nonce hash 1]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH answer nonce hash 1]", self);
}
[self reset:mtProto];
}
else
@ -597,12 +619,16 @@ typedef enum {
{
if (![newNonceHash2 isEqualToData:((MTSetClientDhParamsResponseRetryMessage *)setClientDhParamsResponseMessage).nextNonceHash2])
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH answer nonce hash 2]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH answer nonce hash 2]", self);
}
[self reset:mtProto];
}
else
{
MTLog(@"[MTDatacenterAuthMessageService#%p retry DH]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p retry DH]", self);
}
[self reset:mtProto];
}
}
@ -610,18 +636,24 @@ typedef enum {
{
if (![newNonceHash3 isEqualToData:((MTSetClientDhParamsResponseFailMessage *)setClientDhParamsResponseMessage).nextNonceHash3])
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH answer nonce hash 3]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH answer nonce hash 3]", self);
}
[self reset:mtProto];
}
else
{
MTLog(@"[MTDatacenterAuthMessageService#%p server rejected DH params]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p server rejected DH params]", self);
}
[self reset:mtProto];
}
}
else
{
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH params response]", self);
if (MTLogEnabled()) {
MTLog(@"[MTDatacenterAuthMessageService#%p invalid DH params response]", self);
}
[self reset:mtProto];
}
}

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import "MTDatacenterSaltInfo.h"
@implementation MTDatacenterSaltInfo

View File

@ -6,14 +6,14 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterTransferAuthAction.h>
#import "MTDatacenterTransferAuthAction.h"
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTRequestMessageService.h>
#import <MTProtoKit/MTRequest.h>
#import <MTProtoKit/MTBuffer.h>
#import "MTContext.h"
#import "MTSerialization.h"
#import "MTProto.h"
#import "MTRequestMessageService.h"
#import "MTRequest.h"
#import "MTBuffer.h"
@interface MTDatacenterTransferAuthAction () <MTContextChangeListener>
{
@ -90,7 +90,7 @@
return;
}
_sourceDatacenterMtProto = [[MTProto alloc] initWithContext:context datacenterId:sourceDatacenterId];
_sourceDatacenterMtProto = [[MTProto alloc] initWithContext:context datacenterId:sourceDatacenterId usageCalculationInfo:nil];
MTRequestMessageService *requestService = [[MTRequestMessageService alloc] initWithContext:context];
[_sourceDatacenterMtProto addMessageService:requestService];
@ -126,7 +126,7 @@
_sourceDatacenterMtProto = nil;
MTContext *context = _context;
_destinationDatacenterMtProto = [[MTProto alloc] initWithContext:context datacenterId:_destinationDatacenterId];
_destinationDatacenterMtProto = [[MTProto alloc] initWithContext:context datacenterId:_destinationDatacenterId usageCalculationInfo:nil];
MTRequestMessageService *requestService = [[MTRequestMessageService alloc] initWithContext:context];
[_destinationDatacenterMtProto addMessageService:requestService];

View File

@ -24,4 +24,4 @@
- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId;
- (void)cancel;
@end
@end

View File

@ -6,14 +6,14 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDiscoverDatacenterAddressAction.h>
#import "MTDiscoverDatacenterAddressAction.h"
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import <MTProtoKit/MTRequestMessageService.h>
#import <MTProtoKit/MTRequest.h>
#import "MTContext.h"
#import "MTSerialization.h"
#import "MTProto.h"
#import "MTDatacenterAddressSet.h"
#import "MTRequestMessageService.h"
#import "MTRequest.h"
@interface MTDiscoverDatacenterAddressAction () <MTContextChangeListener>
{
@ -98,7 +98,7 @@
{
if ([context authInfoForDatacenterWithId:_targetDatacenterId] != nil)
{
_mtProto = [[MTProto alloc] initWithContext:context datacenterId:_targetDatacenterId];
_mtProto = [[MTProto alloc] initWithContext:context datacenterId:_targetDatacenterId usageCalculationInfo:nil];
_requestService = [[MTRequestMessageService alloc] initWithContext:_context];
[_mtProto addMessageService:_requestService];

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDropResponseContext.h>
#import "MTDropResponseContext.h"
@implementation MTDropResponseContext

View File

@ -24,7 +24,6 @@ int32_t MTMurMurHash32(const void *bytes, int length);
void MTAesEncryptInplace(NSMutableData *data, NSData *key, NSData *iv);
void MTAesEncryptInplaceAndModifyIv(NSMutableData *data, NSData *key, NSMutableData *iv);
void MTAesDecryptInplace(NSMutableData *data, NSData *key, NSData *iv);
void MTAesDecryptInplaceAndModifyIv(NSMutableData *data, NSData *key, NSMutableData *iv);
NSData *MTAesEncrypt(NSData *data, NSData *key, NSData *iv);
NSData *MTAesDecrypt(NSData *data, NSData *key, NSData *iv);

View File

@ -6,23 +6,24 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTEncryption.h>
#import "MTEncryption.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTKeychain.h>
#import "MTLogging.h"
#import "MTKeychain.h"
#import <CommonCrypto/CommonCrypto.h>
#import <CommonCrypto/CommonDigest.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#import "MTAes.h"
#import "MTRsa.h"
#if TARGET_OS_IOS
#else
# include <openssl/pem.h>
#endif
NSData *MTSha1(NSData *data)
{
@ -166,78 +167,89 @@ int32_t MTMurMurHash32(const void *bytes, int length)
void MTAesEncryptInplace(NSMutableData *data, NSData *key, NSData *iv)
{
AES_KEY aesKey;
AES_set_encrypt_key(key.bytes, 256, &aesKey);
unsigned char aesIv[AES_BLOCK_SIZE * 2];
unsigned char aesIv[16 * 2];
memcpy(aesIv, iv.bytes, iv.length);
AES_ige_encrypt(data.bytes, (void *)data.bytes, data.length, &aesKey, aesIv, true);
void *outData = malloc(data.length);
MyAesIgeEncrypt(data.bytes, (int)data.length, outData, key.bytes, (int)key.length, aesIv);
memcpy(data.mutableBytes, outData, data.length);
free(outData);
}
void MTAesEncryptInplaceAndModifyIv(NSMutableData *data, NSData *key, NSMutableData *iv)
{
AES_KEY aesKey;
AES_set_encrypt_key(key.bytes, 256, &aesKey);
AES_ige_encrypt(data.bytes, (void *)data.bytes, data.length, &aesKey, iv.mutableBytes, true);
}
void MTAesDecryptInplace(NSMutableData *data, NSData *key, NSData *iv)
{
AES_KEY aesKey;
AES_set_decrypt_key(key.bytes, 256, &aesKey);
unsigned char aesIv[AES_BLOCK_SIZE * 2];
unsigned char aesIv[16 * 2];
memcpy(aesIv, iv.bytes, iv.length);
AES_ige_encrypt(data.bytes, (void *)data.bytes, data.length, &aesKey, aesIv, false);
void *outData = malloc(data.length);
MyAesIgeEncrypt(data.bytes, (int)data.length, outData, key.bytes, (int)key.length, aesIv);
memcpy(data.mutableBytes, outData, data.length);
free(outData);
memcpy(iv.mutableBytes, aesIv, 16 * 2);
}
void MTAesDecryptInplaceAndModifyIv(NSMutableData *data, NSData *key, NSMutableData *iv)
{
AES_KEY aesKey;
AES_set_decrypt_key(key.bytes, 256, &aesKey);
unsigned char aesIv[16 * 2];
memcpy(aesIv, iv.bytes, iv.length);
AES_ige_encrypt(data.bytes, (void *)data.bytes, data.length, &aesKey, iv.mutableBytes, false);
void *outData = malloc(data.length);
MyAesIgeDecrypt(data.bytes, (int)data.length, outData, key.bytes, (int)key.length, aesIv);
memcpy(data.mutableBytes, outData, data.length);
free(outData);
memcpy(iv.mutableBytes, aesIv, 16 * 2);
}
NSData *MTAesEncrypt(NSData *data, NSData *key, NSData *iv)
{
if (key == nil || iv == nil)
{
MTLog(@"***** MTAesEncrypt: empty key or iv");
if (MTLogEnabled()) {
MTLog(@"***** MTAesEncrypt: empty key or iv");
}
return nil;
}
AES_KEY aesKey;
AES_set_encrypt_key(key.bytes, 256, &aesKey);
unsigned char aesIv[AES_BLOCK_SIZE * 2];
unsigned char aesIv[16 * 2];
memcpy(aesIv, iv.bytes, iv.length);
uint8_t *resultBytes = malloc(data.length);
AES_ige_encrypt(data.bytes, resultBytes, data.length, &aesKey, aesIv, true);
return [[NSData alloc] initWithBytesNoCopy:resultBytes length:data.length freeWhenDone:true];
void *outData = malloc(data.length);
MyAesIgeEncrypt(data.bytes, (int)data.length, outData, key.bytes, (int)key.length, aesIv);
return [[NSData alloc] initWithBytesNoCopy:outData length:data.length freeWhenDone:true];
}
NSData *MTAesDecrypt(NSData *data, NSData *key, NSData *iv)
{
if (key == nil || iv == nil)
{
MTLog(@"***** MTAesEncrypt: empty key or iv");
if (MTLogEnabled()) {
MTLog(@"***** MTAesEncrypt: empty key or iv");
}
return nil;
}
AES_KEY aesKey;
AES_set_decrypt_key(key.bytes, 256, &aesKey);
unsigned char aesIv[AES_BLOCK_SIZE * 2];
NSMutableData *resultData = [[NSMutableData alloc] initWithLength:data.length];
unsigned char aesIv[16 * 2];
memcpy(aesIv, iv.bytes, iv.length);
MyAesIgeDecrypt(data.bytes, (int)data.length, resultData.mutableBytes, key.bytes, (int)key.length, aesIv);
uint8_t *resultBytes = malloc(data.length);
AES_ige_encrypt(data.bytes, resultBytes, data.length, &aesKey, aesIv, false);
return [[NSData alloc] initWithBytesNoCopy:resultBytes length:data.length freeWhenDone:true];
return resultData;
}
NSData *MTRsaEncrypt(NSString *publicKey, NSData *data)
{
#if TARGET_OS_IOS
NSMutableData *updatedData = [[NSMutableData alloc] initWithData:data];
while (updatedData.length < 256) {
uint8_t zero = 0;
[updatedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&zero length:1];
}
return [MTRsa encryptData:updatedData publicKey:publicKey];
#else
BIO *keyBio = BIO_new(BIO_s_mem());
const char *keyData = [publicKey UTF8String];
BIO_write(keyBio, keyData, (int)publicKey.length);
@ -262,6 +274,7 @@ NSData *MTRsaEncrypt(NSString *publicKey, NSData *data)
NSData *result = [[NSData alloc] initWithBytesNoCopy:res length:(NSUInteger)resLen freeWhenDone:true];
return result;
#endif
}
NSData *MTExp(NSData *base, NSData *exp, NSData *modulus)
@ -380,7 +393,9 @@ bool MTFactorize(uint64_t what, uint64_t *resA, uint64_t *resB)
}
else
{
MTLog(@"Factorization failed for %lld", (long long int)what);
if (MTLogEnabled()) {
MTLog(@"Factorization failed for %lld", (long long int)what);
}
return false;
}

View File

@ -1,6 +1,12 @@
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTKeychain.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTKeychain.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTKeychain.h>
#else
# import <MTProtoKit/MTKeychain.h>
#endif
@interface MTFileBasedKeychain : NSObject <MTKeychain>

View File

@ -1,6 +1,6 @@
#import "MTFileBasedKeychain.h"
#import <MTProtoKit/MTLogging.h>
#import "MTLogging.h"
#import <pthread.h>
@ -10,7 +10,7 @@
#define TG_SYNCHRONIZED_END(lock) pthread_mutex_unlock(&_TG_SYNCHRONIZED_##lock);
#import <CommonCrypto/CommonCrypto.h>
#import <MTProtoKit/MTEncryption.h>
#import "MTEncryption.h"
static TG_SYNCHRONIZED_DEFINE(_keychains) = PTHREAD_MUTEX_INITIALIZER;
static NSMutableDictionary *keychains()
@ -136,10 +136,11 @@ static NSMutableDictionary *keychains()
{
uint8_t buf[32];
SecRandomCopyBytes(kSecRandomDefault, 32, buf);
int result = 0;
result = SecRandomCopyBytes(kSecRandomDefault, 32, buf);
_aesKey = [[NSData alloc] initWithBytes:buf length:32];
SecRandomCopyBytes(kSecRandomDefault, 32, buf);
result = SecRandomCopyBytes(kSecRandomDefault, 32, buf);
_aesIv = [[NSData alloc] initWithBytes:buf length:32];
}
@ -192,8 +193,11 @@ static NSMutableDictionary *keychains()
__autoreleasing NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:dataDirectory withIntermediateDirectories:true attributes:nil error:&error];
if (error != nil)
MTLog(@"[MTKeychain error creating keychain directory: %@]", error);
if (error != nil) {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error creating keychain directory: %@]", error);
}
}
});
return [dataDirectory stringByAppendingPathComponent:[[NSString alloc] initWithFormat:@"%@_%@.bin", name, group]];
@ -219,10 +223,16 @@ static NSMutableDictionary *keychains()
if (data.length == 4 + paddedLength || data.length == 4 + paddedLength + 4)
{
NSMutableData *decryptedData = [[NSMutableData alloc] init];
[decryptedData appendData:[data subdataWithRange:NSMakeRange(4, paddedLength)]];
if (_encrypted)
MTAesDecryptInplace(decryptedData, _aesKey, _aesIv);
NSMutableData *encryptedData = [[NSMutableData alloc] init];
[encryptedData appendData:[data subdataWithRange:NSMakeRange(4, paddedLength)]];
NSMutableData *decryptedData = nil;
if (_encrypted) {
decryptedData = [[NSMutableData alloc] initWithData:MTAesDecrypt(encryptedData, _aesKey, _aesIv)];
} else {
decryptedData = encryptedData;
}
[decryptedData setLength:length];
bool hashVerified = true;
@ -235,7 +245,9 @@ static NSMutableDictionary *keychains()
int32_t decryptedHash = MTMurMurHash32(decryptedData.bytes, (int)decryptedData.length);
if (hash != decryptedHash)
{
MTLog(@"[MTKeychain invalid decrypted hash]");
if (MTLogEnabled()) {
MTLog(@"[MTKeychain invalid decrypted hash]");
}
hashVerified = false;
}
}
@ -247,17 +259,25 @@ static NSMutableDictionary *keychains()
id object = [NSKeyedUnarchiver unarchiveObjectWithData:decryptedData];
if ([object respondsToSelector:@selector(objectForKey:)] && [object respondsToSelector:@selector(setObject:forKey:)])
_dictByGroup[group] = object;
else
MTLog(@"[MTKeychain invalid root object %@]", object);
else {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain invalid root object %@]", object);
}
}
}
@catch (NSException *e)
{
MTLog(@"[MTKeychain error parsing keychain: %@]", e);
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error parsing keychain: %@]", e);
}
}
}
}
else
MTLog(@"[MTKeychain error loading keychain: expected data length %d, got %d]", 4 + (int)paddedLength, (int)data.length);
else {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error loading keychain: expected data length %d, got %d]", 4 + (int)paddedLength, (int)data.length);
}
}
}
}
@ -291,20 +311,29 @@ static NSMutableDictionary *keychains()
[encryptedData appendBytes:&hash length:4];
NSString *filePath = [self filePathForName:_name group:group];
if (![encryptedData writeToFile:filePath atomically:true])
MTLog(@"[MTKeychain error writing keychain to file]");
if (![encryptedData writeToFile:filePath atomically:true]) {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error writing keychain to file]");
}
}
else
{
#if TARGET_OS_IPHONE
__autoreleasing NSError *error = nil;
[[NSURL fileURLWithPath:filePath] setResourceValue:[NSNumber numberWithBool:true] forKey:NSURLIsExcludedFromBackupKey error:&error];
if (error != nil)
MTLog(@"[MTKeychain error setting \"exclude from backup\" flag]");
if (error != nil) {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error setting \"exclude from backup\" flag]");
}
}
#endif
}
}
else
MTLog(@"[MTKeychain error serializing keychain]");
else {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error serializing keychain]");
}
}
}
}

View File

@ -0,0 +1,9 @@
#import <Foundation/Foundation.h>
@class MTSignal;
@interface MTHttpRequestOperation : NSObject
+ (MTSignal *)dataForHttpUrl:(NSURL *)url;
@end

View File

@ -0,0 +1,46 @@
#import "MTHttpRequestOperation.h"
#import "../thirdparty/AFNetworking/AFHTTPRequestOperation.h"
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTDisposable.h>
# import <MTProtoKitDynamic/MTSignal.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTDisposable.h>
# import <MTProtoKitMac/MTSignal.h>
#else
# import <MTProtoKit/MTDisposable.h>
# import <MTProtoKit/MTSignal.h>
#endif
@implementation MTHttpRequestOperation
+ (MTSignal *)dataForHttpUrl:(NSURL *)url {
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setSuccessCallbackQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
[operation setFailureCallbackQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
[operation setCompletionBlockWithSuccess:^(__unused AFHTTPRequestOperation *operation, __unused id responseObject)
{
[subscriber putNext:[operation responseData]];
[subscriber putCompletion];
} failure:^(__unused AFHTTPRequestOperation *operation, __unused NSError *error)
{
[subscriber putError:nil];
}];
[operation start];
__weak AFHTTPRequestOperation *weakOperation = operation;
return [[MTBlockDisposable alloc] initWithBlock:^
{
__strong AFHTTPRequestOperation *strongOperation = weakOperation;
[strongOperation cancel];
}];
}];
}
@end

View File

@ -6,7 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTransport.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTTransport.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTTransport.h>
#else
# import <MTProtoKit/MTTransport.h>
#endif
@interface MTHttpTransport : MTTransport

View File

@ -6,27 +6,29 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTHttpTransport.h>
#import "MTHttpTransport.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTTimer.h>
#import "MTLogging.h"
#import "MTQueue.h"
#import "MTTimer.h"
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import <MTProtoKit/MTDatacenterAddress.h>
#import "MTDatacenterAddressSet.h"
#import "MTDatacenterAddress.h"
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTTransportTransaction.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MtProtoKit/MTIncomingMessage.h>
#import <MtProtoKit/MTPreparedMessage.h>
#import "MTSerialization.h"
#import "MTTransportTransaction.h"
#import "MTMessageTransaction.h"
#import "MTOutgoingMessage.h"
#import "MTIncomingMessage.h"
#import "MTPreparedMessage.h"
#import <MTProtoKit/MTHttpWorkerBehaviour.h>
#import <MTProtoKit/MTHttpWorker.h>
#import "MTHttpWorkerBehaviour.h"
#import "MTHttpWorker.h"
#import <MTProtoKit/MTBuffer.h>
#import <MTProtoKit/MTPongMessage.h>
#import "MTBuffer.h"
#import "MTPongMessage.h"
#import "MTContext.h"
#import "MTDatacenterAuthInfo.h"
@interface MTHttpTransport () <MTHttpWorkerBehaviourDelegate, MTHttpWorkerDelegate, MTContextChangeListener>
{
@ -61,9 +63,9 @@
return queue;
}
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo
{
self = [super initWithDelegate:delegate context:context datacenterId:datacenterId address:address];
self = [super initWithDelegate:delegate context:context datacenterId:datacenterId address:address usageCalculationInfo:usageCalculationInfo];
if (self != nil)
{
_address = address;
@ -460,7 +462,9 @@
else if (transaction.payload.length != 0)
{
MTHttpWorker *worker = [[MTHttpWorker alloc] initWithDelegate:self address:_address payloadData:transaction.payload performsLongPolling:performsLongPolling && transactionIndex == 0];
MTLog(@"[MTHttpTransport#%x spawn MTHttpWorker#%x(longPolling: %s), %d active]", (int)self, (int)worker, worker.performsLongPolling ? "1" : "0", _workers.count + 1);
if (MTLogEnabled()) {
MTLog(@"[MTHttpTransport#%x spawn MTHttpWorker#%x(longPolling: %s), %d active]", (int)self, (int)worker, worker.performsLongPolling ? "1" : "0", _workers.count + 1);
}
worker.delegate = self;
if (_workers == nil)

View File

@ -6,14 +6,14 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTHttpWorker.h>
#import "MTHttpWorker.h"
#import <MTProtoKit/MTTimer.h>
#import <MTProtoKit/MTQueue.h>
#import "MTTimer.h"
#import "MTQueue.h"
#import <MTProtoKit/MTDatacenterAddress.h>
#import "MTDatacenterAddress.h"
#import <MTProtoKit/MTInternalId.h>
#import "MTInternalId.h"
MTInternalIdClass(MTHttpWorker)
@ -69,6 +69,12 @@ MTInternalIdClass(MTHttpWorker)
int32_t randomId = 0;
arc4random_buf(&randomId, 4);
/*#ifdef DEBUG
if (![address isIpv6]) {
address = [[MTDatacenterAddress alloc] initWithIp:@"127.0.0.1" port:443 preferForMedia:address.preferForMedia restrictToTcp:address.restrictToTcp];
}
#endif*/
NSString *urlString = [[NSString alloc] initWithFormat:@"http://%@:%d/api%" PRIx32 "", address.ip, (int)address.port, randomId];
self = [super initWithBaseURL:[[NSURL alloc] initWithString:urlString]];

View File

@ -6,10 +6,10 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTHttpWorkerBehaviour.h>
#import "MTHttpWorkerBehaviour.h"
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTTimer.h>
#import "MTQueue.h"
#import "MTTimer.h"
@interface MTHttpWorkerBehaviour ()
{

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTIncomingMessage.h>
#import "MTIncomingMessage.h"
@implementation MTIncomingMessage

View File

@ -7,8 +7,8 @@
*/
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTInputStream.h>
#import "MTLogging.h"
#import "MTInputStream.h"
#if TARGET_OS_IPHONE
# import <endian.h>
@ -66,7 +66,11 @@ static inline int roundUpInput(int numToRound, int multiple)
if ([_wrappedInputStream read:(uint8_t *)&value maxLength:4] != 4)
{
MTLog(@"***** Couldn't read int32");
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read int32");
@throw [[NSException alloc] initWithName:@"MTInputStreamException" reason:@"readInt32 end of stream" userInfo:@{}];
}
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -105,7 +109,9 @@ static inline int roundUpInput(int numToRound, int multiple)
if ([_wrappedInputStream read:(uint8_t *)&value maxLength:8] != 8)
{
MTLog(@"***** Couldn't read int64");
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read int64");
}
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -144,7 +150,9 @@ static inline int roundUpInput(int numToRound, int multiple)
if ([_wrappedInputStream read:(uint8_t *)&value maxLength:8] != 8)
{
MTLog(@"***** Couldn't read double");
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read double");
}
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -183,7 +191,9 @@ static inline int roundUpInput(int numToRound, int multiple)
NSInteger readLen = [_wrappedInputStream read:bytes maxLength:length];
if (readLen != length)
{
MTLog(@"***** Couldn't read %d bytes", length);
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read %d bytes", length);
}
}
NSData *data = [[NSData alloc] initWithBytesNoCopy:bytes length:length freeWhenDone:true];
return data;
@ -209,7 +219,9 @@ static inline int roundUpInput(int numToRound, int multiple)
NSInteger readLen = [_wrappedInputStream read:bytes maxLength:length];
if (readLen != length)
{
MTLog(@"***** Couldn't read %d bytes", length);
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read %d bytes", length);
}
}
NSMutableData *data = [[NSMutableData alloc] initWithBytesNoCopy:bytes length:length freeWhenDone:true];
return data;
@ -265,7 +277,9 @@ static inline int roundUpInput(int numToRound, int multiple)
NSInteger readLen = [_wrappedInputStream read:bytes maxLength:length];
if (readLen != length)
{
MTLog(@"***** Couldn't read %d bytes", length);
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read %d bytes", length);
}
}
string = [[NSString alloc] initWithBytesNoCopy:bytes length:length encoding:NSUTF8StringEncoding freeWhenDone:true];
@ -360,7 +374,9 @@ static inline int roundUpInput(int numToRound, int multiple)
NSInteger readLen = [_wrappedInputStream read:bytes maxLength:length];
if (readLen != length)
{
MTLog(@"***** Couldn't read %d bytes", length);
if (MTLogEnabled()) {
MTLog(@"***** Couldn't read %d bytes", length);
}
}
NSData *result = [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:true];

View File

@ -1,28 +1,30 @@
#import "MTInternalMessageParser.h"
#import <MTProtoKit/MTBufferReader.h>
#import "MTBufferReader.h"
#import <MTProtoKit/MTResPqMessage.h>
#import <MTProtoKit/MTRpcResultMessage.h>
#import <MTProtoKit/MTRpcError.h>
#import <MTProtoKit/MTDropRpcResultMessage.h>
#import <MTProtoKit/MTServerDhParamsMessage.h>
#import <MTProtoKit/MTServerDhInnerDataMessage.h>
#import <MTProtoKit/MTSetClientDhParamsResponseMessage.h>
#import <MTProtoKit/MTMsgsAckMessage.h>
#import <MTProtoKit/MTMsgsStateReqMessage.h>
#import <MTProtoKit/MtMsgsStateInfoMessage.h>
#import <MTProtoKit/MTMsgDetailedInfoMessage.h>
#import <MTProtoKit/MTMsgAllInfoMessage.h>
#import <MTProtoKit/MTMessage.h>
#import <MTProtoKit/MTMsgResendReqMessage.h>
#import <MTProtoKit/MTBadMsgNotificationMessage.h>
#import <MTProtoKit/MTPingMessage.h>
#import <MTProtoKit/MTPongMessage.h>
#import <MTProtoKit/MTNewSessionCreatedMessage.h>
#import <MTProtoKit/MTDestroySessionResponseMessage.h>
#import <MTProtoKit/MTMsgContainerMessage.h>
#import <MTProtoKit/MTFutureSaltsMessage.h>
#import "MTResPqMessage.h"
#import "MTRpcResultMessage.h"
#import "MTRpcError.h"
#import "MTDropRpcResultMessage.h"
#import "MTServerDhParamsMessage.h"
#import "MTServerDhInnerDataMessage.h"
#import "MTSetClientDhParamsResponseMessage.h"
#import "MTMsgsAckMessage.h"
#import "MTMsgsStateReqMessage.h"
#import "MtMsgsStateInfoMessage.h"
#import "MTMsgDetailedInfoMessage.h"
#import "MTMsgAllInfoMessage.h"
#import "MTMessage.h"
#import "MTMsgResendReqMessage.h"
#import "MTBadMsgNotificationMessage.h"
#import "MTPingMessage.h"
#import "MTPongMessage.h"
#import "MTNewSessionCreatedMessage.h"
#import "MTDestroySessionResponseMessage.h"
#import "MTMsgContainerMessage.h"
#import "MTFutureSaltsMessage.h"
#import "MTLogging.h"
#import <zlib.h>
@ -415,19 +417,25 @@
int32_t vectorSignature = 0;
if (![reader readInt32:&vectorSignature])
{
MTLog(@"[MTInternalMessageParser: msgs_ack can't read vectorSignature]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msgs_ack can't read vectorSignature]");
}
return nil;
}
else if (vectorSignature != (int32_t)0x1cb5c415)
{
MTLog(@"[MTInternalMessageParser: msgs_ack invalid vectorSignature]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msgs_ack invalid vectorSignature]");
}
return nil;
}
int32_t count = 0;
if (![reader readInt32:&count])
{
MTLog(@"[MTInternalMessageParser: msgs_ack can't read count]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msgs_ack can't read count]");
}
return nil;
}
@ -437,7 +445,9 @@
int64_t messageId = 0;
if (![reader readInt64:&messageId])
{
MTLog(@"[MTInternalMessageParser: msgs_ack can't read messageId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msgs_ack can't read messageId]");
}
return nil;
}
[messageIds addObject:@(messageId)];
@ -450,7 +460,9 @@
int64_t pingId = 0;
if (![reader readInt64:&pingId])
{
MTLog(@"[MTInternalMessageParser: ping can't read pingId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: ping can't read pingId]");
}
return nil;
}
@ -461,14 +473,18 @@
int64_t messageId = 0;
if (![reader readInt64:&messageId])
{
MTLog(@"[MTInternalMessageParser: pong can't read messageId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: pong can't read messageId]");
}
return nil;
}
int64_t pingId = 0;
if (![reader readInt64:&pingId])
{
MTLog(@"[MTInternalMessageParser: pong can't read pingId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: pong can't read pingId]");
}
return nil;
}
@ -479,21 +495,27 @@
int64_t firstMessageId = 0;
if (![reader readInt64:&firstMessageId])
{
MTLog(@"[MTInternalMessageParser: new_session_created can't read firstMessageId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: new_session_created can't read firstMessageId]");
}
return nil;
}
int64_t uniqueId = 0;
if (![reader readInt64:&uniqueId])
{
MTLog(@"[MTInternalMessageParser: new_session_created can't read uniqueId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: new_session_created can't read uniqueId]");
}
return nil;
}
int64_t serverSalt = 0;
if (![reader readInt64:&serverSalt])
{
MTLog(@"[MTInternalMessageParser: new_session_created can't read serverSalt]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: new_session_created can't read serverSalt]");
}
return nil;
}
@ -504,7 +526,9 @@
int64_t sessionId = 0;
if (![reader readInt64:&sessionId])
{
MTLog(@"[MTInternalMessageParser: destroy_session_ok can't read sessionId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: destroy_session_ok can't read sessionId]");
}
return nil;
}
@ -515,7 +539,9 @@
int64_t sessionId = 0;
if (![reader readInt64:&sessionId])
{
MTLog(@"[MTInternalMessageParser: destroy_session_none can't read sessionId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: destroy_session_none can't read sessionId]");
}
return nil;
}
@ -532,7 +558,9 @@
int32_t count = 0;
if (![reader readInt32:&count])
{
MTLog(@"[MTInternalMessageParser: msg_container can't read count]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msg_container can't read count]");
}
return nil;
}
@ -543,27 +571,35 @@
int64_t messageId = 0;
if (![reader readInt64:&messageId])
{
MTLog(@"[MTInternalMessageParser: msg_container can't read messageId]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msg_container can't read messageId]");
}
return nil;
}
int32_t seqNo = 0;
if (![reader readInt32:&seqNo])
{
MTLog(@"[MTInternalMessageParser: msg_container can't read seqNo]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msg_container can't read seqNo]");
}
return nil;
}
int32_t length = 0;
if (![reader readInt32:&length])
{
MTLog(@"[MTInternalMessageParser: msg_container can't read length]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msg_container can't read length]");
}
return nil;
}
if (length < 0 || length > 16 * 1024 * 1024)
{
MTLog(@"[MTInternalMessageParser: msg_container invalid length %d]", length);
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msg_container invalid length %d]", length);
}
return nil;
}
@ -571,7 +607,9 @@
[messageData setLength:(NSUInteger)length];
if (![reader readBytes:messageData.mutableBytes length:(NSUInteger)length])
{
MTLog(@"[MTInternalMessageParser: msg_container can't read bytes]");
if (MTLogEnabled()) {
MTLog(@"[MTInternalMessageParser: msg_container can't read bytes]");
}
return nil;
}

View File

@ -6,4 +6,4 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTKeychain.h>
#import "MTKeychain.h"

View File

@ -15,6 +15,7 @@
extern "C" {
#endif
bool MTLogEnabled();
void MTLog(NSString *format, ...);
void MTLogSetLoggingFunction(void (*function)(NSString *, va_list args));

View File

@ -6,22 +6,23 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTLogging.h>
#import "MTLogging.h"
static void (*loggingFunction)(NSString *, va_list args) = NULL;
void MTLog(NSString *format, ...)
{
bool MTLogEnabled() {
return loggingFunction != NULL;
}
void MTLog(NSString *format, ...) {
va_list L;
va_start(L, format);
if (loggingFunction == NULL)
NSLogv(format, L);
else
if (loggingFunction != NULL) {
loggingFunction(format, L);
}
va_end(L);
}
void MTLogSetLoggingFunction(void (*function)(NSString *, va_list args))
{
void MTLogSetLoggingFunction(void (*function)(NSString *, va_list args)) {
loggingFunction = function;
}
}

View File

@ -14,6 +14,8 @@
@property (nonatomic, strong, readonly) NSData *iv;
+ (instancetype)messageEncryptionKeyForAuthKey:(NSData *)authKey messageKey:(NSData *)messageKey toClient:(bool)toClient;
+ (instancetype)messageEncryptionKeyV2ForAuthKey:(NSData *)authKey messageKey:(NSData *)messageKey toClient:(bool)toClient;
- (instancetype)initWithKey:(NSData *)key iv:(NSData *)iv;
@end

View File

@ -6,9 +6,9 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTMessageEncryptionKey.h>
#import "MTMessageEncryptionKey.h"
#import <MTProtoKit/MTEncryption.h>
#import "MTEncryption.h"
@implementation MTMessageEncryptionKey
@ -19,8 +19,6 @@
NSAssert(messageKey != nil, @"message key should not be nil");
#endif
#warning TODO more precise length check
if (authKey == nil || authKey.length == 0 || messageKey == nil || messageKey.length == 0)
return nil;
@ -77,6 +75,55 @@
return result;
}
+ (instancetype)messageEncryptionKeyV2ForAuthKey:(NSData *)authKey messageKey:(NSData *)messageKey toClient:(bool)toClient {
#ifdef DEBUG
NSAssert(authKey != nil, @"authKey should not be nil");
NSAssert(messageKey != nil, @"message key should not be nil");
#endif
if (authKey == nil || authKey.length == 0 || messageKey == nil || messageKey.length == 0)
return nil;
/*
sha256_a = SHA256 (msg_key + substr (auth_key, x, 36));
sha256_b = SHA256 (substr (auth_key, 40+x, 36) + msg_key);
aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8);
aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8);
*/
int xValue = toClient ? 8 : 0;
NSMutableData *sha256_a_data = [[NSMutableData alloc] init];
[sha256_a_data appendData:messageKey];
[sha256_a_data appendBytes:authKey.bytes + xValue length:36];
NSData *sha256_a = MTSha256(sha256_a_data);
NSMutableData *sha256_b_data = [[NSMutableData alloc] init];
[sha256_b_data appendBytes:authKey.bytes + 40 + xValue length:36];
[sha256_b_data appendData:messageKey];
NSData *sha256_b = MTSha256(sha256_b_data);
NSMutableData *aesKey = [[NSMutableData alloc] init];
[aesKey appendBytes:sha256_a.bytes + 0 length:8];
[aesKey appendBytes:sha256_b.bytes + 8 length:16];
[aesKey appendBytes:sha256_a.bytes + 24 length:8];
NSMutableData *aesIv = [[NSMutableData alloc] init];
[aesIv appendBytes:sha256_b.bytes + 0 length:8];
[aesIv appendBytes:sha256_a.bytes + 8 length:16];
[aesIv appendBytes:sha256_b.bytes + 24 length:8];
MTMessageEncryptionKey *result = [[MTMessageEncryptionKey alloc] init];
result->_key = [[NSData alloc] initWithData:aesKey];
result->_iv = [[NSData alloc] initWithData:aesIv];
return result;
}
- (instancetype)initWithKey:(NSData *)key iv:(NSData *)iv
{
self = [super init];

View File

@ -13,7 +13,7 @@
@property (nonatomic, strong, readonly) id internalId;
/*
* Can be invoked multiple times in case when message transaction maps to multiple different transport transactions
* Can be invoked multiple times in case message transaction maps to multiple different transport transactions
*/
@property (nonatomic, copy) void (^completion)(NSDictionary *messageInternalIdToTransactionId, NSDictionary *messageInternalIdToPreparedMessage, NSDictionary *messageInternalIdToQuickAckId);
@property (nonatomic, copy) void (^prepared)(NSDictionary *messageInternalIdToPreparedMessage);

View File

@ -6,9 +6,9 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTMessageTransaction.h>
#import "MTMessageTransaction.h"
#import <MTProtoKit/MTInternalId.h>
#import "MTInternalId.h"
MTInternalIdClass(MTMessageTransaction)

View File

@ -6,11 +6,11 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTNetworkAvailability.h>
#import "MTNetworkAvailability.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTTimer.h>
#import "MTLogging.h"
#import "MTQueue.h"
#import "MTTimer.h"
#import <sys/socket.h>
#import <netinet/in.h>
@ -155,7 +155,9 @@ static void MTNetworkAvailabilityContextRelease(const void *info)
if (![currentReachabilityState isEqualToString:_lastReachabilityState])
{
_lastReachabilityState = currentReachabilityState;
MTLog(@"[MTNetworkAvailability#%p state: %@]", self, _lastReachabilityState);
if (MTLogEnabled()) {
MTLog(@"[MTNetworkAvailability#%p state: %@]", self, _lastReachabilityState);
}
if (notify)
{

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTOutgoingMessage.h>
#import "MTOutgoingMessage.h"
@interface MTOutgoingMessageInternalId : NSObject <NSCopying>
{

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTOutputStream.h>
#import "MTOutputStream.h"
#if TARGET_OS_IPHONE
# import <endian.h>

View File

@ -6,9 +6,9 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTPreparedMessage.h>
#import "MTPreparedMessage.h"
#import <MTProtoKit/MTInternalId.h>
#import "MTInternalId.h"
MTInternalIdClass(MTPreparedMessage)

View File

@ -11,6 +11,7 @@
@protocol MTMessageService;
@class MTQueue;
@class MTContext;
@class MTNetworkUsageCalculationInfo;
@class MTProto;
@ -38,7 +39,9 @@
@property (nonatomic) id requiredAuthToken;
@property (nonatomic) NSInteger authTokenMasterDatacenterId;
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId;
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (void)pause;
- (void)resume;

View File

@ -6,50 +6,56 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTProto.h>
#import "MTProto.h"
#import <inttypes.h>
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTOutputStream.h>
#import <MTProtoKit/MTInputStream.h>
#import "MTLogging.h"
#import "MTQueue.h"
#import "MTOutputStream.h"
#import "MTInputStream.h"
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import <MtProtoKit/MTTransportScheme.h>
#import <MTProtoKit/MTDatacenterAuthInfo.h>
#import <MTProtoKit/MTSessionInfo.h>
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import <MTProtoKit/MTTimeFixContext.h>
#import "MTContext.h"
#import <MTProtoKit/MTMessageService.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTTimeSyncMessageService.h>
#import <MTProtoKit/MTResendMessageService.h>
#import "MTDatacenterAddressSet.h"
#import "MTTransportScheme.h"
#import "MTDatacenterAuthInfo.h"
#import "MTSessionInfo.h"
#import "MTDatacenterSaltInfo.h"
#import "MTTimeFixContext.h"
#import <MTProtoKit/MTIncomingMessage.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MTProtoKit/MTPreparedMessage.h>
#import <MTProtoKit/MTMessageEncryptionKey.h>
#import "MTMessageService.h"
#import "MTMessageTransaction.h"
#import "MTTimeSyncMessageService.h"
#import "MTResendMessageService.h"
#import <MTProtoKit/MTTransport.h>
#import <MTProtoKit/MTTransportTransaction.h>
#import "MTIncomingMessage.h"
#import "MTOutgoingMessage.h"
#import "MTPreparedMessage.h"
#import "MTMessageEncryptionKey.h"
#import <MTProtoKit/MTTcpTransport.h>
#import <MTProtoKit/MTHttpTransport.h>
#import "MTTransport.h"
#import "MTTransportTransaction.h"
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTEncryption.h>
#import "MTTcpTransport.h"
#import "MTHttpTransport.h"
#import <MTProtoKit/MTBuffer.h>
#import <MTProtoKit/MTInternalMessageParser.h>
#import <MTProtoKit/MTMsgContainerMessage.h>
#import <MTProtoKit/MTMessage.h>
#import <MTProtoKit/MTBadMsgNotificationMessage.h>
#import <MTProtoKit/MTMsgsAckMessage.h>
#import <MTProtoKit/MTMsgDetailedInfoMessage.h>
#import <MTProtoKit/MTNewSessionCreatedMessage.h>
#import <MTProtoKit/MTPongMessage.h>
#import "MTSerialization.h"
#import "MTEncryption.h"
#import "MTBuffer.h"
#import "MTInternalMessageParser.h"
#import "MTMsgContainerMessage.h"
#import "MTMessage.h"
#import "MTBadMsgNotificationMessage.h"
#import "MTMsgsAckMessage.h"
#import "MTMsgDetailedInfoMessage.h"
#import "MTNewSessionCreatedMessage.h"
#import "MTPongMessage.h"
#import "MTTime.h"
#define MTProtoV2 1
typedef enum {
MTProtoStateAwaitingDatacenterScheme = 1,
@ -79,6 +85,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
int _mtState;
bool _willRequestTransactionOnNextQueuePass;
MTNetworkUsageCalculationInfo *_usageCalculationInfo;
}
@end
@ -96,7 +104,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
return queue;
}
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo
{
#ifdef DEBUG
NSAssert(context != nil, @"context should not be nil");
@ -109,6 +117,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
_context = context;
_datacenterId = datacenterId;
_usageCalculationInfo = usageCalculationInfo;
[_context addChangeListener:self];
@ -134,13 +143,22 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}];
}
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo {
[[MTProto managerQueue] dispatchOnQueue:^{
_usageCalculationInfo = usageCalculationInfo;
[_transport setUsageCalculationInfo:usageCalculationInfo];
}];
}
- (void)pause
{
[[MTProto managerQueue] dispatchOnQueue:^
{
if ((_mtState & MTProtoStatePaused) == 0)
{
MTLog(@"[MTProto#%p pause]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p pause]", self);
}
_mtState |= MTProtoStatePaused;
@ -156,7 +174,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
if (_mtState & MTProtoStatePaused)
{
MTLog(@"[MTProto#%p resume]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p resume]", self);
}
[self setMtState:_mtState & (~MTProtoStatePaused)];
@ -207,7 +227,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
[[MTProto managerQueue] dispatchOnQueue:^
{
MTLog(@"[MTProto#%p changing transport %@#%p to %@#%p]", self, [_transport class] == nil ? @"" : NSStringFromClass([_transport class]), _transport, [transport class] == nil ? @"" : NSStringFromClass([transport class]), transport);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p changing transport %@#%p to %@#%p]", self, [_transport class] == nil ? @"" : NSStringFromClass([_transport class]), _transport, [transport class] == nil ? @"" : NSStringFromClass([transport class]), transport);
}
[self allTransactionsMayHaveFailed];
@ -279,7 +301,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
MTTransport *transport = nil;
transport = [_transportScheme createTransportWithContext:_context datacenterId:_datacenterId delegate:self];
transport = [_transportScheme createTransportWithContext:_context datacenterId:_datacenterId delegate:self usageCalculationInfo:_usageCalculationInfo];
[self setTransport:transport];
}
@ -290,7 +312,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
[[MTProto managerQueue] dispatchOnQueue:^
{
MTLog(@"[MTProto#%p resetting session]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p resetting session]", self);
}
_sessionInfo = [[MTSessionInfo alloc] initWithRandomSessionIdAndContext:_context];
_timeFixContext = nil;
@ -324,7 +348,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (!alreadySyncing)
{
MTLog(@"[MTProto#%p begin time sync]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p begin time sync]", self);
}
MTTimeSyncMessageService *timeSyncService = [[MTTimeSyncMessageService alloc] init];
timeSyncService.delegate = self;
@ -354,7 +380,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}
}
MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, haveResendMessagesPending ? "yes" : "no");
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, haveResendMessagesPending ? "yes" : "no");
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -402,7 +430,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (notifyAboutServiceTask)
{
MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, true ? "yes" : "no");
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, true ? "yes" : "no");
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -452,7 +482,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
bool performingServiceTasks = _mtState & MTProtoStateAwaitingTimeFixAndSalts;
if (!performingServiceTasks)
{
MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, false ? "yes" : "no");
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, false ? "yes" : "no");
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -611,7 +643,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (transport != _transport)
return;
MTLog(@"[MTProto#%p network state: %s]", self, isNetworkAvailable ? "available" : "waiting");
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p network state: %s]", self, isNetworkAvailable ? "available" : "waiting");
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -632,7 +666,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (transport != _transport)
return;
MTLog(@"[MTProto#%p connection state: %s]", self, isConnected ? "connected" : "connecting");
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p connection state: %s]", self, isConnected ? "connected" : "connecting");
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -653,7 +689,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (transport != _transport)
return;
MTLog(@"[MTProto#%p connection context update state: %s]", self, isUpdatingConnectionContext ? "updating" : "up to date");
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p connection context update state: %s]", self, isUpdatingConnectionContext ? "updating" : "up to date");
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -823,7 +861,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
messageSeqNo = outgoingMessage.messageSeqNo;
}
MTLog(@"[MTProto#%p preparing %@]", self, [self outgoingMessageDescription:outgoingMessage messageId:messageId messageSeqNo:messageSeqNo]);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p preparing %@]", self, [self outgoingMessageDescription:outgoingMessage messageId:messageId messageSeqNo:messageSeqNo]);
}
if (!monotonityViolated || _useUnauthorizedMode)
{
@ -865,7 +905,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (monotonityViolated)
{
MTLog(@"[MTProto#%p client message id monotonity violated]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p client message id monotonity violated]", self);
}
[self resetSessionInfo];
}
@ -1050,7 +1092,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}
}
MTLog(@"[MTProto#%p transport did not accept transactions with messages (%@)]", self, idsString);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p transport did not accept transactions with messages (%@)]", self, idsString);
}
}
}];
} needsQuickAck:transactionNeedsQuickAck expectsDataInResponse:transactionExpectsDataInResponse]];
@ -1104,7 +1148,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
MTOutputStream *decryptedOs = [[MTOutputStream alloc] init];
MTLog(@"[MTProto#%x sending time fix ping (%" PRId64 "/%" PRId32 ")]", self, timeFixMessageId, timeFixSeqNo);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%x sending time fix ping (%" PRId64 "/%" PRId32 ")]", self, timeFixMessageId, timeFixSeqNo);
}
[decryptedOs writeInt64:[_authInfo authSaltForMessageId:timeFixMessageId]]; // salt
[decryptedOs writeInt64:_sessionInfo.sessionId];
@ -1114,21 +1160,25 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
[decryptedOs writeInt32:(int32_t)messageData.length];
[decryptedOs writeData:messageData];
uint8_t randomBytes[15];
arc4random_buf(randomBytes, 15);
for (int i = 0; ((int)messageData.length + i) % 16 != 0; i++)
{
[decryptedOs write:&randomBytes[i] maxLength:1];
}
NSData *decryptedData = [self paddedData:[decryptedOs currentBytes]];
NSData *decryptedData = [decryptedOs currentBytes];
#if MTProtoV2
int xValue = 0;
NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init];
[msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32];
[msgKeyLargeData appendData:decryptedData];
NSData *msgKeyLarge = MTSha256(msgKeyLargeData);
NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)];
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
#else
NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + messageData.length);
NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16];
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
#endif
NSData *transactionData = nil;
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
if (encryptionKey != nil)
{
NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length];
@ -1215,7 +1265,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
[idsString appendString:@","];
[idsString appendFormat:@"%lld", [nMessageId longLongValue]];
}
MTLog(@" container (%" PRId64 ") of (%@)", containerMessageId, idsString);
if (MTLogEnabled()) {
MTLog(@" container (%" PRId64 ") of (%@)", containerMessageId, idsString);
}
#endif
}
@ -1227,27 +1279,32 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
[decryptedOs writeInt32:(int32_t)containerData.length];
[decryptedOs writeData:containerData];
uint8_t randomBytes[15];
arc4random_buf(randomBytes, 15);
for (int i = 0; ((int)containerData.length + i) % 16 != 0; i++)
{
[decryptedOs write:&randomBytes[i] maxLength:1];
}
NSData *decryptedData = [self paddedData:[decryptedOs currentBytes]];
NSData *decryptedData = [decryptedOs currentBytes];
#if MTProtoV2
int xValue = 0;
NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init];
[msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32];
[msgKeyLargeData appendData:decryptedData];
NSData *msgKeyLarge = MTSha256(msgKeyLargeData);
NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)];
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
int32_t nQuickAckId = *((int32_t *)(msgKeyLarge.bytes));
#else
NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + containerData.length);
NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16];
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
int32_t nQuickAckId = *((int32_t *)(messageKeyFull.bytes));
#endif
nQuickAckId = nQuickAckId & 0x7fffffff;
if (quickAckId != NULL)
*quickAckId = nQuickAckId;
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
if (encryptionKey != nil)
{
NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length];
NSMutableData *encryptedData = [[NSMutableData alloc] init];
[encryptedData appendData:decryptedData];
MTAesEncryptInplace(encryptedData, encryptionKey.key, encryptionKey.iv);
@ -1275,6 +1332,39 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
return messageData;
}
- (NSData *)paddedData:(NSData *)data {
NSMutableData *padded = [[NSMutableData alloc] initWithData:data];
uint8_t randomBytes[128];
arc4random_buf(randomBytes, 128);
#if MTProtoV2
int take = 0;
while (take < 12) {
[padded appendBytes:randomBytes + take length:1];
take++;
}
while (padded.length % 16 != 0) {
[padded appendBytes:randomBytes + take length:1];
take++;
}
int remainingCount = arc4random_uniform(72 + 1 - take);
while (remainingCount % 16 != 0) {
remainingCount--;
}
for (int i = 0; i < remainingCount; i++) {
[padded appendBytes:randomBytes + take length:1];
take++;
}
#else
for (int i = 0; ((int)data.length + i) % 16 != 0; i++) {
[padded appendBytes:randomBytes + i length:1];
}
#endif
return padded;
}
- (NSData *)_dataForEncryptedMessage:(MTPreparedMessage *)preparedMessage sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId
{
MTOutputStream *decryptedOs = [[MTOutputStream alloc] init];
@ -1287,15 +1377,18 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
[decryptedOs writeInt32:(int32_t)preparedMessage.data.length];
[decryptedOs writeData:preparedMessage.data];
uint8_t randomBytes[15];
arc4random_buf(randomBytes, 15);
for (int i = 0; ((int)preparedMessage.data.length + i) % 16 != 0; i++)
{
[decryptedOs write:&randomBytes[i] maxLength:1];
}
NSData *decryptedData = [self paddedData:[decryptedOs currentBytes]];
NSData *decryptedData = [decryptedOs currentBytes];
#if MTProtoV2
int xValue = 0;
NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init];
[msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32];
[msgKeyLargeData appendData:decryptedData];
NSData *msgKeyLarge = MTSha256(msgKeyLargeData);
NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)];
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
#else
NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + preparedMessage.data.length);
NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16];
@ -1305,6 +1398,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
*quickAckId = nQuickAckId;
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false];
#endif
if (encryptionKey != nil)
{
NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length];
@ -1405,16 +1500,21 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (keyId != 0 && _authInfo != nil)
{
NSData *messageKey = [is readData:16];
#if MTProtoV2
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:true];
#else
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:true];
#endif
NSMutableData *messageData = [is readMutableData:(data.length - 24)];
while (messageData.length % 16 != 0)
[messageData setLength:messageData.length - 1];
if (messageData.length != 0)
NSMutableData *encryptedMessageData = [is readMutableData:(data.length - 24)];
while (encryptedMessageData.length % 16 != 0) {
[encryptedMessageData setLength:encryptedMessageData.length - 1];
}
if (encryptedMessageData.length != 0)
{
MTAesDecryptInplace(messageData, encryptionKey.key, encryptionKey.iv);
NSData *decryptedData = MTAesDecrypt(encryptedMessageData, encryptionKey.key, encryptionKey.iv);
MTInputStream *messageIs = [[MTInputStream alloc] initWithData:messageData];
MTInputStream *messageIs = [[MTInputStream alloc] initWithData:decryptedData];
[messageIs readInt64];
[messageIs readInt64];
@ -1557,7 +1657,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
int32_t protocolErrorCode = 0;
[data getBytes:&protocolErrorCode range:NSMakeRange(0, 4)];
MTLog(@"[MTProto#%p protocol error %" PRId32 "", self, protocolErrorCode);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p protocol error %" PRId32 "", self, protocolErrorCode);
}
if (decodeResult != nil)
decodeResult(transactionId, false);
@ -1597,7 +1699,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
NSArray *parsedMessages = [self _parseIncomingMessages:decryptedData dataMessageId:&dataMessageId parseError:&parseError];
if (parseError)
{
MTLog(@"[MTProto#%p incoming data parse error]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p incoming data parse error]", self);
}
[self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]];
@ -1618,7 +1722,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}
else
{
MTLog(@"[MTProto#%p couldn't decrypt incoming data]", self);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p couldn't decrypt incoming data]", self);
}
if (decodeResult != nil)
decodeResult(transactionId, false);
@ -1644,7 +1750,13 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
return nil;
NSData *embeddedMessageKey = [data subdataWithRange:NSMakeRange(8, 16)];
#if MTProtoV2
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:embeddedMessageKey toClient:true];
#else
MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:embeddedMessageKey toClient:true];
#endif
if (encryptionKey == nil)
return nil;
@ -1653,11 +1765,22 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
int32_t messageDataLength = 0;
[decryptedData getBytes:&messageDataLength range:NSMakeRange(28, 4)];
if (messageDataLength < 0 || messageDataLength < (int32_t)decryptedData.length - 32 - 16 || messageDataLength > (int32_t)decryptedData.length - 32)
if (messageDataLength < 0 || messageDataLength > (int32_t)decryptedData.length)
return nil;
#if MTProtoV2
int xValue = 8;
NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init];
[msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32];
[msgKeyLargeData appendData:decryptedData];
NSData *msgKeyLarge = MTSha256(msgKeyLargeData);
NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)];
#else
NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + messageDataLength);
NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16];
#endif
if (![messageKey isEqualToData:embeddedMessageKey])
return nil;
@ -1831,7 +1954,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
if ([_sessionInfo messageProcessed:incomingMessage.messageId])
{
MTLog(@"[MTProto#%p received duplicate message %" PRId64 "]", self, incomingMessage.messageId);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p received duplicate message %" PRId64 "]", self, incomingMessage.messageId);
}
[_sessionInfo scheduleMessageConfirmation:incomingMessage.messageId size:incomingMessage.size];
if ([_sessionInfo scheduledMessageConfirmationsExceedSize:MTMaxUnacknowledgedMessageSize orCount:MTMaxUnacknowledgedMessageCount])
@ -1840,7 +1965,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
return;
}
MTLog(@"[MTProto#%p received %@]", self, [self incomingMessageDescription:incomingMessage]);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p received %@]", self, [self incomingMessageDescription:incomingMessage]);
}
[_sessionInfo setMessageProcessed:incomingMessage.messageId];
if (!_useUnauthorizedMode && incomingMessage.seqNo % 2 != 0)
@ -1968,7 +2095,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
{
int64_t requestMessageId = ((MTMsgDetailedResponseInfoMessage *)detailedInfoMessage).requestMessageId;
MTLog(@"[MTProto#%p detailed info %" PRId64 " is for %" PRId64 "", self, incomingMessage.messageId, requestMessageId);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p detailed info %" PRId64 " is for %" PRId64 "", self, incomingMessage.messageId, requestMessageId);
}
for (id<MTMessageService> messageService in _messageServices)
{
@ -1988,7 +2117,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (shouldRequest)
{
[self requestMessageWithId:detailedInfoMessage.responseMessageId];
MTLog(@"[MTProto#%p will request message %" PRId64 "", self, detailedInfoMessage.responseMessageId);
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p will request message %" PRId64 "", self, detailedInfoMessage.responseMessageId);
}
}
else
{

View File

@ -17,15 +17,56 @@ FOUNDATION_EXPORT const unsigned char MtProtoKitVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <MtProtoKit/PublicHeader.h>
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTRequestMessageService.h>
#import <MTProtoKit/MTRequest.h>
#import <MTProtoKit/MTFileBasedKeychain.h>
#import <MTProtoKit/MTTime.h>
#import <MTProtoKit/MTTimer.h>
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTEncryption.h>
#import <MTProtoKit/MTInternalId.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTOutputStream.h>
#import <MTProtoKit/MTInputStream.h>
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTExportedAuthorizationData.h>
#import <MTProtoKit/MTRpcError.h>
#import <MTProtoKit/MTKeychain.h>
#import <MTProtoKit/MTFileBasedKeychain.h>
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTTransportScheme.h>
#import <MTProtoKit/MTDatacenterTransferAuthAction.h>
#import <MTProtoKit/MTDatacenterAuthAction.h>
#import <MTProtoKit/MTDatacenterAuthMessageService.h>
#import <MTProtoKit/MTDatacenterAddress.h>
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import <MTProtoKit/MTDatacenterAuthInfo.h>
#import <MTProtoKit/MTApiEnvironment.h>
#import <MTProtoKit/MTEncryption.h>
#import <MTProtoKit/MTDatacenterSaltInfo.h>
#import <MTProtoKit/MTDatacenterAddressListData.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTSessionInfo.h>
#import <MTProtoKit/MTTimeFixContext.h>
#import <MTProtoKit/MTPreparedMessage.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MTProtoKit/MTIncomingMessage.h>
#import <MTProtoKit/MTMessageEncryptionKey.h>
#import <MTProtoKit/MTMessageService.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTTimeSyncMessageService.h>
#import <MTProtoKit/MTRequestMessageService.h>
#import <MTProtoKit/MTRequest.h>
#import <MTProtoKit/MTRequestContext.h>
#import <MTProtoKit/MTRequestErrorContext.h>
#import <MTProtoKit/MTDropResponseContext.h>
#import <MTProtoKit/MTApiEnvironment.h>
#import <MTProtoKit/MTResendMessageService.h>
#import <MTProtoKit/MTNetworkAvailability.h>
#import <MTProtoKit/MTTransport.h>
#import <MTProtoKit/MTTransportTransaction.h>
#import <MTProtoKit/MTTcpTransport.h>
#import <MTProtoKit/MTHttpTransport.h>
#import <MTProtoKit/MTHttpRequestOperation.h>
#import <MTProtoKit/MTAtomic.h>
#import <MTProtoKit/MTBag.h>
#import <MTProtoKit/MTDisposable.h>
#import <MTProtoKit/MTSubscriber.h>
#import <MTProtoKit/MTSignal.h>
#import <MTProtoKit/MTNetworkUsageCalculationInfo.h>
#import <MTProtoKit/MTNetworkUsageManager.h>

View File

@ -13,6 +13,8 @@
- (instancetype)initWithName:(const char *)name;
+ (MTQueue *)mainQueue;
+ (MTQueue *)concurrentDefaultQueue;
+ (MTQueue *)concurrentLowQueue;
- (dispatch_queue_t)nativeQueue;

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTQueue.h>
#import "MTQueue.h"
@interface MTQueue ()
{
@ -20,6 +20,15 @@
@implementation MTQueue
- (instancetype)init {
self = [super init];
if (self != nil)
{
_queue = dispatch_queue_create(nil, 0);
}
return self;
}
- (instancetype)initWithName:(const char *)name
{
self = [super init];
@ -54,6 +63,27 @@
return queue;
}
+ (MTQueue *)concurrentDefaultQueue {
static MTQueue *queue = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
queue = [[MTQueue alloc] init];
queue->_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
});
return queue;
}
+ (MTQueue *)concurrentLowQueue {
static MTQueue *queue = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^ {
queue = [[MTQueue alloc] init];
queue->_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
});
return queue;
}
- (dispatch_queue_t)nativeQueue
{
return _queue;
@ -61,7 +91,7 @@
- (bool)isCurrentQueue
{
if (_queue == nil)
if (_queue == nil || _name == nil)
return false;
if (_isMainQueue)
@ -70,6 +100,10 @@
return dispatch_get_specific(_name) == _name;
}
- (void)dispatch:(dispatch_block_t)block {
[self dispatchOnQueue:block synchronous:false];
}
- (void)dispatchOnQueue:(dispatch_block_t)block
{
[self dispatchOnQueue:block synchronous:false];
@ -93,7 +127,7 @@
}
else
{
if (dispatch_get_specific(_name) == _name)
if (_name != NULL && dispatch_get_specific(_name) == _name)
block();
else if (synchronous)
dispatch_sync(_queue, block);

View File

@ -6,10 +6,11 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <Foundation/Foundation.h>
@class MTRequestContext;
@class MTRequestErrorContext;
#import <MTProtoKit/MTRpcError.h>
@class MTRpcError;
@interface MTRequest : NSObject

View File

@ -6,7 +6,9 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTRequest.h>
#import "MTRequest.h"
#import "MTRpcError.h"
@interface MTRequestInternalId : NSObject <NSCopying>
{

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTRequestContext.h>
#import "MTRequestContext.h"
@implementation MTRequestContext

View File

@ -7,11 +7,10 @@
*/
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTTime.h>
@interface MTRequestErrorContext : NSObject
@property (nonatomic) MTAbsoluteTime minimalExecuteTime;
@property (nonatomic) CFAbsoluteTime minimalExecuteTime;
@property (nonatomic) NSUInteger internalServerErrorCount;
@property (nonatomic) NSUInteger floodWaitSeconds;

View File

@ -6,7 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTMessageService.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTMessageService.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTMessageService.h>
#else
# import <MTProtoKit/MTMessageService.h>
#endif
@class MTContext;
@class MTRequest;

View File

@ -6,31 +6,31 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTRequestMessageService.h>
#import "MTRequestMessageService.h"
#import <MTProtoKit/MTLogging.h>
#import <MtProtoKit/MTTime.h>
#import <MtProtoKit/MTTimer.h>
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTIncomingMessage.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MTProtoKit/MTPreparedMessage.h>
#import <MTProtoKit/MTRequest.h>
#import <MTProtoKit/MTRequestContext.h>
#import <MtProtoKit/MTRequestErrorContext.h>
#import <MTProtoKit/MTDropResponseContext.h>
#import <MTProtoKit/MTApiEnvironment.h>
#import <MTProtoKit/MTDatacenterAuthInfo.h>
#import <MTProtoKit/MTBuffer.h>
#import "MTLogging.h"
#import "MTTime.h"
#import "MTTimer.h"
#import "MTContext.h"
#import "MTSerialization.h"
#import "MTProto.h"
#import "MTQueue.h"
#import "MTMessageTransaction.h"
#import "MTIncomingMessage.h"
#import "MTOutgoingMessage.h"
#import "MTPreparedMessage.h"
#import "MTRequest.h"
#import "MTRequestContext.h"
#import "MTRequestErrorContext.h"
#import "MTDropResponseContext.h"
#import "MTApiEnvironment.h"
#import "MTDatacenterAuthInfo.h"
#import "MTBuffer.h"
#import <MTProtoKit/MTInternalMessageParser.h>
#import <MTProtoKit/MTRpcResultMessage.h>
#import <MTProtoKit/MTRpcError.h>
#import <MTProtoKit/MTDropRpcResultMessage.h>
#import "MTInternalMessageParser.h"
#import "MTRpcResultMessage.h"
#import "MTRpcError.h"
#import "MTDropRpcResultMessage.h"
@interface MTRequestMessageService ()
{
@ -125,8 +125,11 @@
anyNewDropRequests = true;
}
if (request.requestContext.messageId != 0)
MTLog(@"[MTRequestMessageService#%x drop %" PRId64 "]", (int)self, request.requestContext.messageId);
if (request.requestContext.messageId != 0) {
if (MTLogEnabled()) {
MTLog(@"[MTRequestMessageService#%x drop %" PRId64 "]", (int)self, request.requestContext.messageId);
}
}
request.requestContext = nil;
[_requests removeObjectAtIndex:(NSUInteger)index];
@ -193,9 +196,9 @@
{
[_queue dispatchOnQueue:^
{
MTAbsoluteTime currentTime = MTAbsoluteSystemTime();
CFAbsoluteTime currentTime = MTAbsoluteSystemTime();
MTAbsoluteTime minWaitTime = DBL_MAX;
CFAbsoluteTime minWaitTime = DBL_MAX;
bool needTimer = false;
bool needTransaction = false;
@ -345,9 +348,7 @@
bool requestsWillInitializeApi = _apiEnvironment != nil && ![_apiEnvironment.apiInitializationHash isEqualToString:[_context authInfoForDatacenterWithId:mtProto.datacenterId].authKeyAttributes[@"apiInitializationHash"]];
MTAbsoluteTime currentTime = MTAbsoluteSystemTime();
static bool catchPrepare = false;
CFAbsoluteTime currentTime = MTAbsoluteSystemTime();
for (MTRequest *request in _requests)
{
@ -536,11 +537,15 @@
if (rpcResult != nil)
{
MTLog(@"[MTRequestMessageService#%p response for %" PRId64 " is %@]", self, request.requestContext.messageId, rpcResult);
if (MTLogEnabled()) {
MTLog(@"[MTRequestMessageService#%p response for %" PRId64 " is %@]", self, request.requestContext.messageId, rpcResult);
}
}
else
{
MTLog(@"[MTRequestMessageService#%p response for %" PRId64 " is error: %d: %@]", self, request.requestContext.messageId, (int)rpcError.errorCode, rpcError.errorDescription);
if (MTLogEnabled()) {
MTLog(@"[MTRequestMessageService#%p response for %" PRId64 " is error: %d: %@]", self, request.requestContext.messageId, (int)rpcError.errorCode, rpcError.errorDescription);
}
}
if (rpcResult != nil && request.requestContext.willInitializeApi)
@ -620,13 +625,13 @@
if (request.shouldContinueExecutionWithErrorContext(request.errorContext))
{
restartRequest = true;
request.errorContext.minimalExecuteTime = MAX(request.errorContext.minimalExecuteTime, MTAbsoluteSystemTime() + (MTAbsoluteTime)errorWaitTime);
request.errorContext.minimalExecuteTime = MAX(request.errorContext.minimalExecuteTime, MTAbsoluteSystemTime() + (CFAbsoluteTime)errorWaitTime);
}
}
else
{
restartRequest = true;
request.errorContext.minimalExecuteTime = MAX(request.errorContext.minimalExecuteTime, MTAbsoluteSystemTime() + (MTAbsoluteTime)errorWaitTime);
request.errorContext.minimalExecuteTime = MAX(request.errorContext.minimalExecuteTime, MTAbsoluteSystemTime() + (CFAbsoluteTime)errorWaitTime);
}
}
}
@ -645,7 +650,7 @@
}];
}
#warning TODO other service errors
//#warning TODO other service errors
}
request.requestContext = nil;
@ -656,7 +661,7 @@
}
else
{
void (^completed)(id result, NSTimeInterval completionTimestamp, id error) = request.completed;
void (^completed)(id result, NSTimeInterval completionTimestamp, id error) = [request.completed copy];
[_requests removeObjectAtIndex:(NSUInteger)index];
if (completed)
@ -667,8 +672,11 @@
}
}
if (!requestFound)
MTLog(@"[MTRequestMessageService#%p response %" PRId64 " didn't match any request]", self, message.messageId);
if (!requestFound) {
if (MTLogEnabled()) {
MTLog(@"[MTRequestMessageService#%p response %" PRId64 " didn't match any request]", self, message.messageId);
}
}
else if (_requests.count == 0)
{
id<MTRequestMessageServiceDelegate> delegate = _delegate;

View File

@ -6,7 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTMessageService.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTMessageService.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTMessageService.h>
#else
# import <MTProtoKit/MTMessageService.h>
#endif
@class MTResendMessageService;

View File

@ -7,18 +7,18 @@
*/
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTResendMessageService.h>
#import "MTLogging.h"
#import "MTResendMessageService.h"
#import <MTProtoKit/MTProto.h>
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MTProtoKit/MTPreparedMessage.h>
#import <MTProtoKit/MTIncomingMessage.h>
#import <MTProtoKit/MTBuffer.h>
#import <MTProtoKit/MTMsgsStateInfoMessage.h>
#import "MTProto.h"
#import "MTContext.h"
#import "MTSerialization.h"
#import "MTMessageTransaction.h"
#import "MTOutgoingMessage.h"
#import "MTPreparedMessage.h"
#import "MTIncomingMessage.h"
#import "MTBuffer.h"
#import "MTMsgsStateInfoMessage.h"
@interface MTResendMessageService ()
{
@ -73,7 +73,9 @@
_currentRequestMessageId = ((MTPreparedMessage *)messageInternalIdToPreparedMessage[outgoingMessage.internalId]).messageId;
_currentRequestTransactionId = messageInternalIdToTransactionId[outgoingMessage.internalId];
MTLog(@"[MTResendMessageService#%p request %" PRId64 " for %" PRId64 "]", self, _currentRequestMessageId, _messageId);
if (MTLogEnabled()) {
MTLog(@"[MTResendMessageService#%p request %" PRId64 " for %" PRId64 "]", self, _currentRequestMessageId, _messageId);
}
}
}];
}

View File

@ -8,8 +8,16 @@
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTExportedAuthorizationData.h>
#import <MTProtoKit/MTDatacenterAddressListData.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTExportedAuthorizationData.h>
# import <MTProtoKitDynamic/MTDatacenterAddressListData.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTExportedAuthorizationData.h>
# import <MTProtoKitMac/MTDatacenterAddressListData.h>
#else
# import <MTProtoKit/MTExportedAuthorizationData.h>
# import <MTProtoKit/MTDatacenterAddressListData.h>
#endif
typedef MTExportedAuthorizationData *(^MTExportAuthorizationResponseParser)(NSData *);
typedef MTDatacenterAddressListData *(^MTRequestDatacenterAddressListParser)(NSData *);

View File

@ -6,10 +6,10 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTSessionInfo.h>
#import "MTSessionInfo.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTContext.h>
#import "MTLogging.h"
#import "MTContext.h"
@interface MTScheduledMessageConfirmation : NSObject

View File

@ -6,11 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTDatacenterAddress.h>
#import <Foundation/Foundation.h>
@class MTDatacenterAddress;
@class MTContext;
@class MTQueue;
@class MTTcpConnection;
@class MTNetworkUsageCalculationInfo;
/*!
MTTcpConnection delegate protocol
@ -45,7 +47,9 @@
+ (MTQueue *)tcpQueue;
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address interface:(NSString *)interface;
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address interface:(NSString *)interface usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (void)start;
- (void)stop;

View File

@ -6,19 +6,22 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTcpConnection.h>
#import "MTTcpConnection.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTTimer.h>
#import "MTLogging.h"
#import "MTQueue.h"
#import "MTTimer.h"
#import "GCDAsyncSocket.h"
#import <sys/socket.h>
#import <MTProtoKit/MTInternalId.h>
#import "MTInternalId.h"
#import <MTProtoKit/MTContext.h>
#import <MTProtoKit/MTApiEnvironment.h>
#import "MTContext.h"
#import "MTApiEnvironment.h"
#import "MTDatacenterAddress.h"
#import "MTAes.h"
MTInternalIdClass(MTTcpConnection)
@ -32,6 +35,20 @@ typedef enum {
static const NSTimeInterval MTMinTcpResponseTimeout = 12.0;
static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
static const bool useEncryption = true;
struct ctr_state {
unsigned char ivec[16]; /* ivec[0..7] is the IV, ivec[8..15] is the big-endian counter */
unsigned int num;
unsigned char ecount[16];
};
static void init_ctr(struct ctr_state *state, const unsigned char *iv)
{
state->num = 0;
memset(state->ecount, 0, 16);
memcpy(state->ivec, iv, 16);
}
@interface MTTcpConnection () <GCDAsyncSocketDelegate>
{
@ -51,6 +68,11 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
NSData *_firstPacketControlByte;
bool _addedControlHeader;
MTAesCtr *_outgoingAesCtr;
MTAesCtr *_incomingAesCtr;
MTNetworkUsageCalculationInfo *_usageCalculationInfo;
}
@property (nonatomic) int64_t packetHeadDecodeToken;
@ -71,7 +93,7 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
return queue;
}
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address interface:(NSString *)interface
- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address interface:(NSString *)interface usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo
{
#ifdef DEBUG
NSAssert(address != nil, @"address should not be nil");
@ -82,8 +104,16 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
{
_internalId = [[MTInternalId(MTTcpConnection) alloc] init];
/*#ifdef DEBUG
if (![address isIpv6]) {
address = [[MTDatacenterAddress alloc] initWithIp:@"127.0.0.1" port:443 preferForMedia:address.preferForMedia restrictToTcp:address.restrictToTcp];
}
#endif*/
_address = address;
_interface = interface;
_usageCalculationInfo = usageCalculationInfo;
if (context.apiEnvironment.datacenterAddressOverrides[@(datacenterId)] != nil) {
_firstPacketControlByte = [context.apiEnvironment tcpPayloadPrefix];
@ -108,6 +138,13 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
}];
}
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo {
[[MTTcpConnection tcpQueue] dispatchOnQueue:^{
_usageCalculationInfo = usageCalculationInfo;
_socket.usageCalculationInfo = usageCalculationInfo;
}];
}
- (void)setDelegate:(id<MTTcpConnectionDelegate>)delegate
{
_delegate = delegate;
@ -122,8 +159,11 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
if (_socket == nil)
{
_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[[MTTcpConnection tcpQueue] nativeQueue]];
_socket.usageCalculationInfo = _usageCalculationInfo;
MTLog(@"[MTTcpConnection#%x connecting to %@:%d]", (int)self, _address.ip, (int)_address.port);
if (MTLogEnabled()) {
MTLog(@"[MTTcpConnection#%x connecting to %@:%d]", (int)self, _address.ip, (int)_address.port);
}
NSString *ip = _address.ip;
@ -221,21 +261,52 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
uint8_t controlBytes[64];
arc4random_buf(controlBytes, 64);
int32_t *firstByte = (int32_t *)controlBytes;
while (*firstByte == 0x44414548 || *firstByte == 0x54534f50 || *firstByte == 0x20544547 || *firstByte == 0x4954504f || *firstByte == 0xeeeeeeee) {
arc4random_buf(controlBytes, 4);
if (useEncryption) {
int32_t controlVersion = 0xefefefef;
memcpy(controlBytes + 56, &controlVersion, 4);
uint8_t controlBytesReversed[64];
for (int i = 0; i < 64; i++) {
controlBytesReversed[i] = controlBytes[64 - 1 - i];
}
_outgoingAesCtr = [[MTAesCtr alloc] initWithKey:controlBytes + 8 keyLength:32 iv:controlBytes + 8 + 32];
_incomingAesCtr = [[MTAesCtr alloc] initWithKey:controlBytesReversed + 8 keyLength:32 iv:controlBytesReversed + 8 + 32];
uint8_t encryptedControlBytes[64];
[_outgoingAesCtr encryptIn:controlBytes out:encryptedControlBytes len:64];
NSMutableData *outData = [[NSMutableData alloc] initWithLength:64 + packetData.length];
memcpy(outData.mutableBytes, controlBytes, 56);
memcpy(outData.mutableBytes + 56, encryptedControlBytes + 56, 8);
[_outgoingAesCtr encryptIn:packetData.bytes out:outData.mutableBytes + 64 len:packetData.length];
[_socket writeData:outData withTimeout:-1 tag:0];
} else {
int32_t *firstByte = (int32_t *)controlBytes;
while (*firstByte == 0x44414548 || *firstByte == 0x54534f50 || *firstByte == 0x20544547 || *firstByte == 0x4954504f || *firstByte == 0xeeeeeeee) {
arc4random_buf(controlBytes, 4);
}
while (controlBytes[0] == 0xef) {
arc4random_buf(controlBytes, 1);
}
NSMutableData *controlData = [[NSMutableData alloc] init];
[controlData appendBytes:controlBytes length:64];
[controlData appendData:packetData];
[_socket writeData:controlData withTimeout:-1 tag:0];
}
while (controlBytes[0] == 0xef) {
arc4random_buf(controlBytes, 1);
}
NSMutableData *controlData = [[NSMutableData alloc] init];
[controlData appendBytes:controlBytes length:64];
[controlData appendData:packetData];
[_socket writeData:controlData withTimeout:-1 tag:0];
} else {
[_socket writeData:packetData withTimeout:-1 tag:0];
if (useEncryption) {
NSMutableData *encryptedData = [[NSMutableData alloc] initWithLength:packetData.length];
[_outgoingAesCtr encryptIn:packetData.bytes out:encryptedData.mutableBytes len:packetData.length];
[_socket writeData:encryptedData withTimeout:-1 tag:0];
} else {
[_socket writeData:packetData withTimeout:-1 tag:0];
}
}
}
@ -255,7 +326,9 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
}
else
{
MTLog(@"***** %s: can't send data: connection is not opened", __PRETTY_FUNCTION__);
if (MTLogEnabled()) {
MTLog(@"***** %s: can't send data: connection is not opened", __PRETTY_FUNCTION__);
}
if (completion)
completion(false);
@ -274,7 +347,9 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
[_responseTimeoutTimer invalidate];
_responseTimeoutTimer = nil;
MTLog(@"[MTTcpConnection#%x response timeout]", (int)self);
if (MTLogEnabled()) {
MTLog(@"[MTTcpConnection#%x response timeout]", (int)self);
}
[self stop];
}
@ -299,11 +374,21 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
}
}
- (void)socket:(GCDAsyncSocket *)__unused socket didReadData:(NSData *)data withTag:(long)tag
- (void)socket:(GCDAsyncSocket *)__unused socket didReadData:(NSData *)rawData withTag:(long)tag
{
if (_closed)
return;
NSData *data = nil;
if (useEncryption) {
NSMutableData *decryptedData = [[NSMutableData alloc] initWithLength:rawData.length];
[_incomingAesCtr encryptIn:rawData.bytes out:decryptedData.mutableBytes len:rawData.length];
data = decryptedData;
} else {
data = rawData;
}
if (tag == MTTcpReadTagPacketShortLength)
{
#ifdef DEBUG
@ -336,7 +421,9 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
[_socket readDataToLength:3 withTimeout:-1 tag:MTTcpReadTagPacketLongLength];
else
{
MTLog(@"***** %s: invalid quarter length marker (%" PRIu8 ")", __PRETTY_FUNCTION__, quarterLengthMarker);
if (MTLogEnabled()) {
MTLog(@"***** %s: invalid quarter length marker (%" PRIu8 ")", __PRETTY_FUNCTION__, quarterLengthMarker);
}
[self closeAndNotify];
}
}
@ -352,7 +439,9 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
if (quarterLength <= 0 || quarterLength > (4 * 1024 * 1024) / 4)
{
MTLog(@"***** %s: invalid quarter length (%" PRIu32 ")", __PRETTY_FUNCTION__, quarterLength);
if (MTLogEnabled()) {
MTLog(@"***** %s: invalid quarter length (%" PRIu32 ")", __PRETTY_FUNCTION__, quarterLength);
}
[self closeAndNotify];
}
else
@ -447,10 +536,16 @@ static const NSUInteger MTTcpProgressCalculationThreshold = 4096;
- (void)socketDidDisconnect:(GCDAsyncSocket *)__unused socket withError:(NSError *)error
{
if (error != nil)
MTLog(@"[MTTcpConnection#%x disconnected from %@ (%@)]", (int)self, _address.ip, error);
else
MTLog(@"[MTTcpConnection#%x disconnected from %@]", (int)self, _address.ip);
if (error != nil) {
if (MTLogEnabled()) {
MTLog(@"[MTTcpConnection#%x disconnected from %@ (%@)]", (int)self, _address.ip, error);
}
}
else {
if (MTLogEnabled()) {
MTLog(@"[MTTcpConnection#%x disconnected from %@]", (int)self, _address.ip);
}
}
[self closeAndNotify];
}

View File

@ -8,10 +8,10 @@
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTTcpConnectionBehaviour.h>
#import "MTTcpConnectionBehaviour.h"
#import <MTProtoKit/MTTimer.h>
#import <MTProtoKit/MTQueue.h>
#import "MTTimer.h"
#import "MTQueue.h"
@interface MTTcpConnectionBehaviour ()
{

View File

@ -6,7 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTransport.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTTransport.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTTransport.h>
#else
# import <MTProtoKit/MTTransport.h>
#endif
@interface MTTcpTransport : MTTransport

View File

@ -6,27 +6,27 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTcpTransport.h>
#import "MTTcpTransport.h"
#import <MTProtoKit/MTLogging.h>
#import <MTProtoKit/MTQueue.h>
#import <MTProtoKit/MTTimer.h>
#import <MTProtoKit/MTTime.h>
#import "MTLogging.h"
#import "MTQueue.h"
#import "MTTimer.h"
#import "MTTime.h"
#import <MTProtoKit/MTDatacenterAddressSet.h>
#import "MTDatacenterAddressSet.h"
#import <MTProtoKit/MTTransportTransaction.h>
#import <MTProtoKit/MTOutgoingMessage.h>
#import <MTProtoKit/MTIncomingMessage.h>
#import <MTProtoKit/MTMessageTransaction.h>
#import <MTProtoKit/MTPreparedMessage.h>
#import "MTTransportTransaction.h"
#import "MTOutgoingMessage.h"
#import "MTIncomingMessage.h"
#import "MTMessageTransaction.h"
#import "MTPreparedMessage.h"
#import <MTProtoKit/MTTcpConnection.h>
#import <MTProtoKit/MTTcpConnectionBehaviour.h>
#import "MTTcpConnection.h"
#import "MTTcpConnectionBehaviour.h"
#import <MTProtoKit/MTSerialization.h>
#import <MTProtoKit/MTBuffer.h>
#import <MTProtoKit/MTPongMessage.h>
#import "MTSerialization.h"
#import "MTBuffer.h"
#import "MTPongMessage.h"
static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
@ -69,6 +69,7 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
MTTcpTransportContext *_transportContext;
__weak MTContext *_context;
NSInteger _datacenterId;
MTNetworkUsageCalculationInfo *_usageCalculationInfo;
}
@end
@ -86,7 +87,7 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
return queue;
}
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo
{
#ifdef DEBUG
NSAssert(context != nil, @"context should not be nil");
@ -94,11 +95,12 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
NSAssert(address != nil, @"address should not be nil");
#endif
self = [super initWithDelegate:delegate context:context datacenterId:datacenterId address:address];
self = [super initWithDelegate:delegate context:context datacenterId:datacenterId address:address usageCalculationInfo:usageCalculationInfo];
if (self != nil)
{
_context = context;
_datacenterId = datacenterId;
_usageCalculationInfo = usageCalculationInfo;
MTTcpTransportContext *transportContext = [[MTTcpTransportContext alloc] init];
_transportContext = transportContext;
@ -135,6 +137,13 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
}];
}
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo {
[[MTTcpTransport tcpTransportQueue] dispatchOnQueue:^{
_usageCalculationInfo = usageCalculationInfo;
[_transportContext.connection setUsageCalculationInfo:usageCalculationInfo];
}];
}
- (bool)needsParityCorrection
{
return true;
@ -188,7 +197,7 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
[self startSleepWatchdogTimer];
MTContext *context = _context;
transportContext.connection = [[MTTcpConnection alloc] initWithContext:context datacenterId:_datacenterId address:transportContext.address interface:nil];
transportContext.connection = [[MTTcpConnection alloc] initWithContext:context datacenterId:_datacenterId address:transportContext.address interface:nil usageCalculationInfo:_usageCalculationInfo];
transportContext.connection.delegate = self;
[transportContext.connection start];
}
@ -258,7 +267,9 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
{
if (ABS(currentTime - strongSelf->_transportContext.sleepWatchdogTimerLastTime) > MTTcpTransportSleepWatchdogTimeout * 2.0)
{
MTLog(@"[MTTcpTransport#%p system sleep detected, resetting connection]", strongSelf);
if (MTLogEnabled()) {
MTLog(@"[MTTcpTransport#%p system sleep detected, resetting connection]", strongSelf);
}
[strongSelf reset];
}
strongSelf->_transportContext.sleepWatchdogTimerLastTime = currentTime;
@ -544,19 +555,25 @@ static const NSTimeInterval MTTcpTransportSleepWatchdogTimeout = 60.0;
{
if (!transportContext.didSendActualizationPingAfterConnection)
{
MTLog(@"[MTTcpTransport#%x unlocking transaction processing due to connection context update task]", (int)self);
if (MTLogEnabled()) {
MTLog(@"[MTTcpTransport#%x unlocking transaction processing due to connection context update task]", (int)self);
}
transportContext.isWaitingForTransactionToBecomeReady = false;
transportContext.transactionLockTime = 0.0;
}
else if (CFAbsoluteTimeGetCurrent() > transportContext.transactionLockTime + 1.0)
{
MTLog(@"[MTTcpTransport#%x unlocking transaction processing due to timeout]", (int)self);
if (MTLogEnabled()) {
MTLog(@"[MTTcpTransport#%x unlocking transaction processing due to timeout]", (int)self);
}
transportContext.isWaitingForTransactionToBecomeReady = false;
transportContext.transactionLockTime = 0.0;
}
else
{
MTLog(@"[MTTcpTransport#%x skipping transaction request]", (int)self);
if (MTLogEnabled()) {
MTLog(@"[MTTcpTransport#%x skipping transaction request]", (int)self);
}
transportContext.requestAnotherTransactionWhenReady = true;
return;

View File

@ -9,13 +9,13 @@
#ifndef MtProtoKit_MTTime_h
#define MtProtoKit_MTTime_h
typedef double MTAbsoluteTime;
#ifdef __cplusplus
extern "C" {
#endif
#import <Foundation/Foundation.h>
MTAbsoluteTime MTAbsoluteSystemTime();
CFAbsoluteTime MTAbsoluteSystemTime();
#ifdef __cplusplus
}

View File

@ -6,15 +6,15 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTime.h>
#import "MTTime.h"
#import <mach/mach_time.h>
MTAbsoluteTime MTAbsoluteSystemTime()
CFAbsoluteTime MTAbsoluteSystemTime()
{
static mach_timebase_info_data_t s_timebase_info;
if (s_timebase_info.denom == 0)
mach_timebase_info(&s_timebase_info);
return ((MTAbsoluteTime)(mach_absolute_time() * s_timebase_info.numer)) / (s_timebase_info.denom * NSEC_PER_SEC);
return ((CFAbsoluteTime)(mach_absolute_time() * s_timebase_info.numer)) / (s_timebase_info.denom * NSEC_PER_SEC);
}

View File

@ -7,15 +7,14 @@
*/
#import <Foundation/Foundation.h>
#import <MTProtoKit/MTTime.h>
@interface MTTimeFixContext : NSObject
@property (nonatomic, readonly) int64_t messageId;
@property (nonatomic, readonly) int32_t messageSeqNo;
@property (nonatomic, strong, readonly) id transactionId;
@property (nonatomic, readonly) MTAbsoluteTime timeFixAbsoluteStartTime;
@property (nonatomic, readonly) CFAbsoluteTime timeFixAbsoluteStartTime;
- (instancetype)initWithMessageId:(int64_t)messageId messageSeqNo:(int32_t)messageSeqNo transactionId:(id)transactionId timeFixAbsoluteStartTime:(MTAbsoluteTime)timeFixAbsoluteStartTime;
- (instancetype)initWithMessageId:(int64_t)messageId messageSeqNo:(int32_t)messageSeqNo transactionId:(id)transactionId timeFixAbsoluteStartTime:(CFAbsoluteTime)timeFixAbsoluteStartTime;
@end

View File

@ -6,11 +6,11 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTimeFixContext.h>
#import "MTTimeFixContext.h"
@implementation MTTimeFixContext
- (instancetype)initWithMessageId:(int64_t)messageId messageSeqNo:(int32_t)messageSeqNo transactionId:(id)transactionId timeFixAbsoluteStartTime:(MTAbsoluteTime)timeFixAbsoluteStartTime
- (instancetype)initWithMessageId:(int64_t)messageId messageSeqNo:(int32_t)messageSeqNo transactionId:(id)transactionId timeFixAbsoluteStartTime:(CFAbsoluteTime)timeFixAbsoluteStartTime
{
self = [super init];
if (self != nil)

View File

@ -6,7 +6,13 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTMessageService.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTMessageService.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTMessageService.h>
#else
# import <MTProtoKit/MTMessageService.h>
#endif
@class MTTimeSyncMessageService;

View File

@ -6,25 +6,25 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTimeSyncMessageService.h>
#import "MTTimeSyncMessageService.h"
#import <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/MTBuffer.h>
#import <MTProtoKit/MTFutureSaltsMessage.h>
#import "MTTime.h"
#import "MTContext.h"
#import "MTProto.h"
#import "MTSerialization.h"
#import "MTOutgoingMessage.h"
#import "MTIncomingMessage.h"
#import "MTPreparedMessage.h"
#import "MTMessageTransaction.h"
#import "MTDatacenterSaltInfo.h"
#import "MTBuffer.h"
#import "MTFutureSaltsMessage.h"
@interface MTTimeSyncMessageService ()
{
int64_t _currentMessageId;
id _currentTransactionId;
MTAbsoluteTime _currentSampleAbsoluteStartTime;
CFAbsoluteTime _currentSampleAbsoluteStartTime;
NSUInteger _takenSampleCount;
NSUInteger _requiredSampleCount;

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTimer.h>
#import "MTTimer.h"
@interface MTTimer ()

View File

@ -6,16 +6,24 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTContext.h>
#import <Foundation/Foundation.h>
@class MTContext;
@class MTDatacenterAddress;
@class MTTransport;
@class MTTransportTransaction;
@class MTOutgoingMessage;
@class MTIncomingMessage;
@class MTMessageTransaction;
@class MTNetworkUsageCalculationInfo;
#import <MTProtoKit/MTMessageService.h>
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTMessageService.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTMessageService.h>
#else
# import <MTProtoKit/MTMessageService.h>
#endif
@protocol MTTransportDelegate <NSObject>
@ -44,7 +52,9 @@
@property (nonatomic) bool simultaneousTransactionsEnabled;
@property (nonatomic) bool reportTransportConnectionContextUpdateStates;
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address;
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (bool)needsParityCorrection;

View File

@ -6,9 +6,10 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTransport.h>
#import "MTTransport.h"
#import <MTProtoKit/MTNetworkAvailability.h>
#import "MTContext.h"
#import "MTNetworkAvailability.h"
@interface MTTransport () <MTNetworkAvailabilityDelegate>
{
@ -19,7 +20,7 @@
@implementation MTTransport
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address
- (instancetype)initWithDelegate:(id<MTTransportDelegate>)delegate context:(MTContext *)context datacenterId:(NSInteger)datacenterId address:(MTDatacenterAddress *)address usageCalculationInfo:(MTNetworkUsageCalculationInfo *)__unused usageCalculationInfo
{
#ifdef DEBUG
NSAssert(context != nil, @"context should not be nil");
@ -40,6 +41,9 @@
return self;
}
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)__unused usageCalculationInfo {
}
- (bool)needsParityCorrection
{
return false;

View File

@ -12,6 +12,7 @@
@class MTTransport;
@class MTDatacenterAddress;
@protocol MTTransportDelegate;
@class MTNetworkUsageCalculationInfo;
@interface MTTransportScheme : NSObject <NSCoding>
@ -25,6 +26,6 @@
- (BOOL)isOptimal;
- (NSComparisonResult)compareToScheme:(MTTransportScheme *)other;
- (MTTransport *)createTransportWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId delegate:(id<MTTransportDelegate>)delegate;
- (MTTransport *)createTransportWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId delegate:(id<MTTransportDelegate>)delegate usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
@end

View File

@ -6,12 +6,12 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTransportScheme.h>
#import "MTTransportScheme.h"
#import <MtProtoKit/MTTransport.h>
#import <MtProtoKit/MTDatacenterAddress.h>
#import "MTTransport.h"
#import "MTDatacenterAddress.h"
#import <MTProtoKit/MTTcpTransport.h>
#import "MTTcpTransport.h"
@interface MTTransportScheme ()
{
@ -87,9 +87,9 @@
return NSOrderedSame;
}
- (MTTransport *)createTransportWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId delegate:(id<MTTransportDelegate>)delegate
- (MTTransport *)createTransportWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId delegate:(id<MTTransportDelegate>)delegate usageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo
{
return [(MTTransport *)[_transportClass alloc] initWithDelegate:delegate context:context datacenterId:datacenterId address:_address];
return [(MTTransport *)[_transportClass alloc] initWithDelegate:delegate context:context datacenterId:datacenterId address:_address usageCalculationInfo:usageCalculationInfo];
}
- (NSString *)description

View File

@ -6,7 +6,7 @@
* Copyright Peter Iakovlev, 2013.
*/
#import <MTProtoKit/MTTransportTransaction.h>
#import "MTTransportTransaction.h"
@implementation MTTransportTransaction

21
MTRsa.h Normal file
View File

@ -0,0 +1,21 @@
#import <Foundation/Foundation.h>
@interface MTRsa : NSObject
// return base64 encoded string
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;
// return base64 encoded string
// enc with private key NOT working YET!
//+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey;
// return raw data
//+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey;
// decrypt base64 encoded string, convert result to string(not base64 encoded)
+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey;
+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;
+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey;
@end

448
MTRsa.m Normal file
View File

@ -0,0 +1,448 @@
#import "MTRsa.h"
/*
@author: ideawu
@link: https://github.com/ideawu/Objective-C-RSA
*/
#import <Security/Security.h>
@implementation MTRsa
/*
static NSString *base64_encode(NSString *str){
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
if(!data){
return nil;
}
return base64_encode_data(data);
}
*/
NSString *MTStringByEncodingInBase64(NSData *data) {
NSUInteger length = [data length];
NSMutableData *mutableData = [[NSMutableData alloc] initWithLength:((length + 2) / 3) * 4];
uint8_t *input = (uint8_t *)[data bytes];
uint8_t *output = (uint8_t *)[mutableData mutableBytes];
for (NSUInteger i = 0; i < length; i += 3)
{
NSUInteger value = 0;
for (NSUInteger j = i; j < (i + 3); j++)
{
value <<= 8;
if (j < length)
{
value |= (0xFF & input[j]);
}
}
static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
NSUInteger idx = (i / 3) * 4;
output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
}
static NSString *base64_encode_data(NSData *data) {
if ([data respondsToSelector:@selector(base64EncodedDataWithOptions:)]) {
data = [data base64EncodedDataWithOptions:0];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return ret;
} else {
return MTStringByEncodingInBase64(data);
}
}
static NSData *base64_decode(NSString *str) {
if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
return data;
} else {
return [[NSData alloc] initWithBase64Encoding:[str stringByReplacingOccurrencesOfString:@"[^A-Za-z0-9+/=]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [str length])]];
}
}
+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{
// Skip ASN.1 public key header
if (d_key == nil) return(nil);
unsigned long len = [d_key length];
if (!len) return(nil);
unsigned char *c_key = (unsigned char *)[d_key bytes];
unsigned int idx = 0;
if (c_key[idx++] != 0x30) return(nil);
if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
else idx++;
// PKCS #1 rsaEncryption szOID_RSA_RSA
static unsigned char seqiod[] =
{ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x01, 0x05, 0x00 };
if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
idx += 15;
if (c_key[idx++] != 0x03) return(nil);
if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
else idx++;
if (c_key[idx++] != '\0') return(nil);
// Now make a new NSData from this buffer
return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}
//credit: http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036
+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
// Skip ASN.1 private key header
if (d_key == nil) return(nil);
unsigned long len = [d_key length];
if (!len) return(nil);
unsigned char *c_key = (unsigned char *)[d_key bytes];
unsigned int idx = 22; //magic byte at offset 22
if (0x04 != c_key[idx++]) return nil;
//calculate length of the key
unsigned int c_len = c_key[idx++];
int det = c_len & 0x80;
if (!det) {
c_len = c_len & 0x7f;
} else {
int byteCount = c_len & 0x7f;
if (byteCount + idx > len) {
//rsa length field longer than buffer
return nil;
}
unsigned int accum = 0;
unsigned char *ptr = &c_key[idx];
idx += byteCount;
while (byteCount) {
accum = (accum << 8) + *ptr;
ptr++;
byteCount--;
}
c_len = accum;
}
// Now make a new NSData from this buffer
return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
}
+ (SecKeyRef)addPublicKey:(NSString *)key_s {
NSString *key = [[key_s stringByReplacingOccurrencesOfString:@"-----BEGIN RSA PUBLIC KEY-----\n" withString:@"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A"] stringByReplacingOccurrencesOfString:@"-----END RSA PUBLIC KEY-----" withString:@"-----END PUBLIC KEY-----"];
NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
if(spos.location != NSNotFound && epos.location != NSNotFound){
NSUInteger s = spos.location + spos.length;
NSUInteger e = epos.location;
NSRange range = NSMakeRange(s, e-s);
key = [key substringWithRange:range];
}
key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];
// This will be base64 encoded, decode it.
NSData *data = base64_decode(key);
data = [MTRsa stripPublicKeyHeader:data];
if(!data){
return nil;
}
//a tag to read/write keychain storage
NSString *tag = @"RSAUtil_PubKey";
NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
// Delete any old lingering key with the same tag
NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
[publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
SecItemDelete((__bridge CFDictionaryRef)publicKey);
// Add persistent version of the key to system keychain
[publicKey setObject:data forKey:(__bridge id)kSecValueData];
[publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
kSecAttrKeyClass];
[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
kSecReturnPersistentRef];
CFTypeRef persistKey = nil;
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
if (persistKey != nil){
CFRelease(persistKey);
}
if ((status != noErr) && (status != errSecDuplicateItem)) {
return nil;
}
[publicKey removeObjectForKey:(__bridge id)kSecValueData];
[publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
// Now fetch the SecKeyRef version of the key
SecKeyRef keyRef = nil;
status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
if(status != noErr){
return nil;
}
return keyRef;
}
+ (SecKeyRef)addPrivateKey:(NSString *)key{
NSRange spos;
NSRange epos;
spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
if(spos.length > 0){
epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
}else{
spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];
epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];
}
if(spos.location != NSNotFound && epos.location != NSNotFound){
NSUInteger s = spos.location + spos.length;
NSUInteger e = epos.location;
NSRange range = NSMakeRange(s, e-s);
key = [key substringWithRange:range];
}
key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];
// This will be base64 encoded, decode it.
NSData *data = base64_decode(key);
data = [MTRsa stripPrivateKeyHeader:data];
if(!data){
return nil;
}
//a tag to read/write keychain storage
NSString *tag = @"RSAUtil_PrivKey";
NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
// Delete any old lingering key with the same tag
NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
[privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
[privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
SecItemDelete((__bridge CFDictionaryRef)privateKey);
// Add persistent version of the key to system keychain
[privateKey setObject:data forKey:(__bridge id)kSecValueData];
[privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
kSecAttrKeyClass];
[privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
kSecReturnPersistentRef];
CFTypeRef persistKey = nil;
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
if (persistKey != nil){
CFRelease(persistKey);
}
if ((status != noErr) && (status != errSecDuplicateItem)) {
return nil;
}
[privateKey removeObjectForKey:(__bridge id)kSecValueData];
[privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
[privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
[privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
// Now fetch the SecKeyRef version of the key
SecKeyRef keyRef = nil;
status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
if(status != noErr){
return nil;
}
return keyRef;
}
/* START: Encryption & Decryption with RSA private key */
+ (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length;
size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
void *outbuf = malloc(block_size);
size_t src_block_size = block_size;
NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=0; idx<srclen; idx+=src_block_size){
//NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
}
size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyEncrypt(keyRef,
kSecPaddingNone,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != 0) {
NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
ret = nil;
break;
}else{
[ret appendBytes:outbuf length:outlen];
}
}
free(outbuf);
CFRelease(keyRef);
return ret;
}
+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{
NSData *data = [MTRsa encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];
NSString *ret = base64_encode_data(data);
return ret;
}
+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{
if(!data || !privKey){
return nil;
}
SecKeyRef keyRef = [MTRsa addPrivateKey:privKey];
if(!keyRef){
return nil;
}
return [MTRsa encryptData:data withKeyRef:keyRef];
}
+ (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length;
size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
UInt8 *outbuf = malloc(block_size);
size_t src_block_size = block_size;
NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=0; idx<srclen; idx+=src_block_size){
//NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
}
size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyDecrypt(keyRef,
kSecPaddingNone,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != 0) {
NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
ret = nil;
break;
}else{
//the actual decrypted data is in the middle, locate it!
int idxFirstZero = -1;
int idxNextZero = (int)outlen;
for ( int i = 0; i < outlen; i++ ) {
if ( outbuf[i] == 0 ) {
if ( idxFirstZero < 0 ) {
idxFirstZero = i;
} else {
idxNextZero = i;
break;
}
}
}
[ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
}
}
free(outbuf);
CFRelease(keyRef);
return ret;
}
+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
data = [MTRsa decryptData:data privateKey:privKey];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return ret;
}
+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
if(!data || !privKey){
return nil;
}
SecKeyRef keyRef = [MTRsa addPrivateKey:privKey];
if(!keyRef){
return nil;
}
return [MTRsa decryptData:data withKeyRef:keyRef];
}
/* END: Encryption & Decryption with RSA private key */
/* START: Encryption & Decryption with RSA public key */
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
NSData *data = [MTRsa encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
NSString *ret = base64_encode_data(data);
return ret;
}
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
if(!data || !pubKey){
return nil;
}
SecKeyRef keyRef = [MTRsa addPublicKey:pubKey];
if(!keyRef){
return nil;
}
return [MTRsa encryptData:data withKeyRef:keyRef];
}
+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
data = [MTRsa decryptData:data publicKey:pubKey];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return ret;
}
+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{
if(!data || !pubKey){
return nil;
}
SecKeyRef keyRef = [MTRsa addPublicKey:pubKey];
if(!keyRef){
return nil;
}
return [MTRsa decryptData:data withKeyRef:keyRef];
}
/* END: Encryption & Decryption with RSA public key */
@end

62
MTSignal.h Normal file
View File

@ -0,0 +1,62 @@
#import <Foundation/Foundation.h>
#import "MTSubscriber.h"
@class MTQueue;
@interface MTSignal : NSObject
{
@public
id<MTDisposable> (^_generator)(MTSubscriber *);
}
- (instancetype)initWithGenerator:(id<MTDisposable> (^)(MTSubscriber *))generator;
- (id<MTDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed;
- (id<MTDisposable>)startWithNext:(void (^)(id next))next;
- (id<MTDisposable>)startWithNext:(void (^)(id next))next completed:(void (^)())completed;
+ (MTSignal *)single:(id)next;
+ (MTSignal *)fail:(id)error;
+ (MTSignal *)never;
+ (MTSignal *)complete;
- (MTSignal *)then:(MTSignal *)signal;
- (MTSignal *)delay:(NSTimeInterval)seconds onQueue:(MTQueue *)queue;
- (MTSignal *)timeout:(NSTimeInterval)seconds onQueue:(MTQueue *)queue orSignal:(MTSignal *)signal;
- (MTSignal *)catch:(MTSignal *(^)(id error))f;
+ (MTSignal *)mergeSignals:(NSArray *)signals;
- (MTSignal *)restart;
- (MTSignal *)take:(NSUInteger)count;
- (MTSignal *)switchToLatest;
- (MTSignal *)map:(id (^)(id))f;
- (MTSignal *)filter:(bool (^)(id))f;
- (MTSignal *)mapToSignal:(MTSignal *(^)(id))f;
- (MTSignal *)onDispose:(void (^)())f;
- (MTSignal *)deliverOn:(MTQueue *)queue;
- (MTSignal *)startOn:(MTQueue *)queue;
- (MTSignal *)take:(NSUInteger)count;
- (MTSignal *)takeLast;
- (MTSignal *)reduceLeft:(id)value with:(id (^)(id, id))f;
@end
@interface MTPipe : NSObject
@property (nonatomic, copy, readonly) MTSignal *(^signalProducer)();
@property (nonatomic, copy, readonly) void (^sink)(id);
- (instancetype)initWithReplay:(bool)replay;
@end

817
MTSignal.m Normal file
View File

@ -0,0 +1,817 @@
#import "MTSignal.h"
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTProtoKitDynamic.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTProtoKitMac.h>
#else
# import <MTProtoKit/MTProtoKit.h>
#endif
#import <libkern/OSAtomic.h>
@interface MTSubscriberDisposable : NSObject <MTDisposable>
{
MTSubscriber *_subscriber;
id<MTDisposable> _disposable;
}
@end
@implementation MTSubscriberDisposable
- (instancetype)initWithSubscriber:(MTSubscriber *)subscriber disposable:(id<MTDisposable>)disposable
{
self = [super init];
if (self != nil)
{
_subscriber = subscriber;
_disposable = disposable;
}
return self;
}
- (void)dispose
{
[_subscriber _markTerminatedWithoutDisposal];
[_disposable dispose];
}
@end
@interface MTSignal_ValueContainer : NSObject
@property (nonatomic, strong, readonly) id value;
@end
@implementation MTSignal_ValueContainer
- (instancetype)initWithValue:(id)value {
self = [super init];
if (self != nil) {
_value = value;
}
return self;
}
@end
@interface MTSignalQueueState : NSObject <MTDisposable>
{
OSSpinLock _lock;
bool _executingSignal;
bool _terminated;
id<MTDisposable> _disposable;
MTMetaDisposable *_currentDisposable;
MTSubscriber *_subscriber;
NSMutableArray *_queuedSignals;
bool _queueMode;
}
@end
@implementation MTSignalQueueState
- (instancetype)initWithSubscriber:(MTSubscriber *)subscriber queueMode:(bool)queueMode
{
self = [super init];
if (self != nil)
{
_subscriber = subscriber;
_currentDisposable = [[MTMetaDisposable alloc] init];
_queuedSignals = queueMode ? [[NSMutableArray alloc] init] : nil;
_queueMode = queueMode;
}
return self;
}
- (void)beginWithDisposable:(id<MTDisposable>)disposable
{
_disposable = disposable;
}
- (void)enqueueSignal:(MTSignal *)signal
{
bool startSignal = false;
OSSpinLockLock(&_lock);
if (_queueMode && _executingSignal)
{
[_queuedSignals addObject:signal];
}
else
{
_executingSignal = true;
startSignal = true;
}
OSSpinLockUnlock(&_lock);
if (startSignal)
{
__weak MTSignalQueueState *weakSelf = self;
id<MTDisposable> disposable = [signal startWithNext:^(id next)
{
[_subscriber putNext:next];
} error:^(id error)
{
[_subscriber putError:error];
} completed:^
{
__strong MTSignalQueueState *strongSelf = weakSelf;
if (strongSelf != nil) {
[strongSelf headCompleted];
}
}];
[_currentDisposable setDisposable:disposable];
}
}
- (void)headCompleted
{
MTSignal *nextSignal = nil;
bool terminated = false;
OSSpinLockLock(&_lock);
_executingSignal = false;
if (_queueMode)
{
if (_queuedSignals.count != 0)
{
nextSignal = _queuedSignals[0];
[_queuedSignals removeObjectAtIndex:0];
_executingSignal = true;
}
else
terminated = _terminated;
}
else
terminated = _terminated;
OSSpinLockUnlock(&_lock);
if (terminated)
[_subscriber putCompletion];
else if (nextSignal != nil)
{
__weak MTSignalQueueState *weakSelf = self;
id<MTDisposable> disposable = [nextSignal startWithNext:^(id next)
{
[_subscriber putNext:next];
} error:^(id error)
{
[_subscriber putError:error];
} completed:^
{
__strong MTSignalQueueState *strongSelf = weakSelf;
if (strongSelf != nil) {
[strongSelf headCompleted];
}
}];
[_currentDisposable setDisposable:disposable];
}
}
- (void)beginCompletion
{
bool executingSignal = false;
OSSpinLockLock(&_lock);
executingSignal = _executingSignal;
_terminated = true;
OSSpinLockUnlock(&_lock);
if (!executingSignal)
[_subscriber putCompletion];
}
- (void)dispose
{
[_currentDisposable dispose];
[_disposable dispose];
}
@end
@implementation MTSignal
- (instancetype)initWithGenerator:(id<MTDisposable> (^)(MTSubscriber *))generator
{
self = [super init];
if (self != nil)
{
_generator = [generator copy];
}
return self;
}
- (id<MTDisposable>)startWithNext:(void (^)(id next))next error:(void (^)(id error))error completed:(void (^)())completed
{
MTSubscriber *subscriber = [[MTSubscriber alloc] initWithNext:next error:error completed:completed];
id<MTDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[MTSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
- (id<MTDisposable>)startWithNext:(void (^)(id next))next
{
MTSubscriber *subscriber = [[MTSubscriber alloc] initWithNext:next error:nil completed:nil];
id<MTDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[MTSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
- (id<MTDisposable>)startWithNext:(void (^)(id next))next completed:(void (^)())completed
{
MTSubscriber *subscriber = [[MTSubscriber alloc] initWithNext:next error:nil completed:completed];
id<MTDisposable> disposable = _generator(subscriber);
[subscriber _assignDisposable:disposable];
return [[MTSubscriberDisposable alloc] initWithSubscriber:subscriber disposable:disposable];
}
+ (MTSignal *)single:(id)next
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
[subscriber putNext:next];
[subscriber putCompletion];
return nil;
}];
}
+ (MTSignal *)fail:(id)error
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
[subscriber putError:error];
return nil;
}];
}
+ (MTSignal *)never
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (__unused MTSubscriber *subscriber)
{
return nil;
}];
}
+ (MTSignal *)complete
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
[subscriber putCompletion];
return nil;
}];
}
- (MTSignal *)then:(MTSignal *)signal
{
return [[MTSignal alloc] initWithGenerator:^(MTSubscriber *subscriber)
{
MTDisposableSet *compositeDisposable = [[MTDisposableSet alloc] init];
MTMetaDisposable *currentDisposable = [[MTMetaDisposable alloc] init];
[compositeDisposable add:currentDisposable];
[currentDisposable setDisposable:[self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[compositeDisposable add:[signal startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}]];
}]];
return compositeDisposable;
}];
}
- (MTSignal *)delay:(NSTimeInterval)seconds onQueue:(MTQueue *)queue
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init];
MTTimer *timer = [[MTTimer alloc] initWithTimeout:seconds repeat:false completion:^
{
[disposable setDisposable:[self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}]];
} queue:queue.nativeQueue];
[timer start];
[disposable setDisposable:[[MTBlockDisposable alloc] initWithBlock:^
{
[timer invalidate];
}]];
return disposable;
}];
}
- (MTSignal *)timeout:(NSTimeInterval)seconds onQueue:(MTQueue *)queue orSignal:(MTSignal *)signal
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init];
MTTimer *timer = [[MTTimer alloc] initWithTimeout:seconds repeat:false completion:^
{
[disposable setDisposable:[signal startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}]];
} queue:queue.nativeQueue];
[timer start];
[disposable setDisposable:[self startWithNext:^(id next)
{
[timer invalidate];
[subscriber putNext:next];
} error:^(id error)
{
[timer invalidate];
[subscriber putError:error];
} completed:^
{
[timer invalidate];
[subscriber putCompletion];
}]];
return disposable;
}];
}
- (MTSignal *)catch:(MTSignal *(^)(id error))f
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
MTDisposableSet *disposable = [[MTDisposableSet alloc] init];
[disposable add:[self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
MTSignal *signal = f(error);
[disposable add:[signal startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}]];
} completed:^
{
[subscriber putCompletion];
}]];
return disposable;
}];
}
+ (MTSignal *)mergeSignals:(NSArray *)signals
{
if (signals.count == 0)
return [MTSignal complete];
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
MTDisposableSet *disposables = [[MTDisposableSet alloc] init];
MTAtomic *completedStates = [[MTAtomic alloc] initWithValue:[[NSSet alloc] init]];
NSInteger index = -1;
NSUInteger count = signals.count;
for (MTSignal *signal in signals)
{
index++;
id<MTDisposable> disposable = [signal startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
NSSet *set = [completedStates modify:^id(NSSet *set)
{
return [set setByAddingObject:@(index)];
}];
if (set.count == count)
[subscriber putCompletion];
}];
[disposables add:disposable];
}
return disposables;
}];
};
static dispatch_block_t recursiveBlock(void (^block)(dispatch_block_t recurse))
{
return ^
{
block(recursiveBlock(block));
};
}
- (MTSignal *)restart
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
MTAtomic *shouldRestart = [[MTAtomic alloc] initWithValue:@true];
MTMetaDisposable *currentDisposable = [[MTMetaDisposable alloc] init];
void (^start)() = recursiveBlock(^(dispatch_block_t recurse)
{
NSNumber *currentShouldRestart = [shouldRestart with:^id(NSNumber *current)
{
return current;
}];
if ([currentShouldRestart boolValue])
{
id<MTDisposable> disposable = [self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
recurse();
}];
[currentDisposable setDisposable:disposable];
}
});
start();
return [[MTBlockDisposable alloc] initWithBlock:^
{
[currentDisposable dispose];
[shouldRestart modify:^id(__unused id current)
{
return @false;
}];
}];
}];
}
- (MTSignal *)take:(NSUInteger)count
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
MTAtomic *counter = [[MTAtomic alloc] initWithValue:@(0)];
return [self startWithNext:^(id next)
{
__block bool passthrough = false;
__block bool complete = false;
[counter modify:^id(NSNumber *currentCount)
{
NSUInteger updatedCount = [currentCount unsignedIntegerValue] + 1;
if (updatedCount <= count)
passthrough = true;
if (updatedCount == count)
complete = true;
return @(updatedCount);
}];
if (passthrough)
[subscriber putNext:next];
if (complete)
[subscriber putCompletion];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}];
}];
}
- (MTSignal *)switchToLatest
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
MTSignalQueueState *state = [[MTSignalQueueState alloc] initWithSubscriber:subscriber queueMode:false];
[state beginWithDisposable:[self startWithNext:^(id next)
{
[state enqueueSignal:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[state beginCompletion];
}]];
return state;
}];
}
- (MTSignal *)map:(id (^)(id))f {
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
return [self startWithNext:^(id next)
{
[subscriber putNext:f(next)];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}];
}];
}
- (MTSignal *)filter:(bool (^)(id))f
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
return [self startWithNext:^(id next)
{
if (f(next))
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}];
}];
}
- (MTSignal *)mapToSignal:(MTSignal *(^)(id))f
{
return [[self map:f] switchToLatest];
}
- (MTSignal *)onDispose:(void (^)())f
{
return [[MTSignal alloc] initWithGenerator:^(MTSubscriber *subscriber)
{
MTDisposableSet *compositeDisposable = [[MTDisposableSet alloc] init];
[compositeDisposable add:[self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}]];
[compositeDisposable add:[[MTBlockDisposable alloc] initWithBlock:^
{
f();
}]];
return compositeDisposable;
}];
}
- (MTSignal *)deliverOn:(MTQueue *)queue
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
return [self startWithNext:^(id next)
{
[queue dispatchOnQueue:^
{
[subscriber putNext:next];
}];
} error:^(id error)
{
[queue dispatchOnQueue:^
{
[subscriber putError:error];
}];
} completed:^
{
[queue dispatchOnQueue:^
{
[subscriber putCompletion];
}];
}];
}];
}
- (MTSignal *)startOn:(MTQueue *)queue
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable> (MTSubscriber *subscriber)
{
__block bool isCancelled = false;
MTMetaDisposable *disposable = [[MTMetaDisposable alloc] init];
[disposable setDisposable:[[MTBlockDisposable alloc] initWithBlock:^
{
isCancelled = true;
}]];
[queue dispatchOnQueue:^
{
if (!isCancelled)
{
[disposable setDisposable:[self startWithNext:^(id next)
{
[subscriber putNext:next];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
[subscriber putCompletion];
}]];
}
}];
return disposable;
}];
}
- (MTSignal *)takeLast
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
MTAtomic *last = [[MTAtomic alloc] initWithValue:nil];
return [self startWithNext:^(id next)
{
[last swap:[[MTSignal_ValueContainer alloc] initWithValue:next]];
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
MTSignal_ValueContainer *value = [last with:^id(id value) {
return value;
}];
if (value != nil)
{
[subscriber putNext:value.value];
}
[subscriber putCompletion];
}];
}];
}
- (MTSignal *)reduceLeft:(id)value with:(id (^)(id, id))f
{
return [[MTSignal alloc] initWithGenerator:^(MTSubscriber *subscriber)
{
__block id intermediateResult = value;
return [self startWithNext:^(id next)
{
intermediateResult = f(intermediateResult, next);
} error:^(id error)
{
[subscriber putError:error];
} completed:^
{
if (intermediateResult != nil)
[subscriber putNext:intermediateResult];
[subscriber putCompletion];
}];
}];
}
@end
@interface MTPipeReplayState : NSObject
@property (nonatomic, readonly) bool hasReceivedValue;
@property (nonatomic, strong, readonly) id recentValue;
@end
@implementation MTPipeReplayState
- (instancetype)initWithReceivedValue:(bool)receivedValue recentValue:(id)recentValue
{
self = [super init];
if (self != nil)
{
_hasReceivedValue = receivedValue;
_recentValue = recentValue;
}
return self;
}
@end
@implementation MTPipe
- (instancetype)init
{
return [self initWithReplay:false];
}
- (instancetype)initWithReplay:(bool)replay
{
self = [super init];
if (self != nil)
{
MTAtomic *subscribers = [[MTAtomic alloc] initWithValue:[[MTBag alloc] init]];
MTAtomic *replayState = replay ? [[MTAtomic alloc] initWithValue:[[MTPipeReplayState alloc] initWithReceivedValue:false recentValue:nil]] : nil;
_signalProducer = [^MTSignal *
{
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber)
{
__block NSUInteger index = 0;
[subscribers with:^id(MTBag *bag)
{
index = [bag addItem:[^(id next)
{
[subscriber putNext:next];
} copy]];
return nil;
}];
if (replay)
{
[replayState with:^id(MTPipeReplayState *state)
{
if (state.hasReceivedValue)
[subscriber putNext:state.recentValue];
return nil;
}];
}
return [[MTBlockDisposable alloc] initWithBlock:^
{
[subscribers with:^id(MTBag *bag)
{
[bag removeItem:index];
return nil;
}];
}];
}];
} copy];
_sink = [^(id next)
{
NSArray *items = [subscribers with:^id(MTBag *bag)
{
return [bag copyItems];
}];
for (void (^item)(id) in items)
{
item(next);
}
if (replay)
{
[replayState modify:^id(__unused MTPipeReplayState *state)
{
return [[MTPipeReplayState alloc] initWithReceivedValue:true recentValue:next];
}];
}
} copy];
}
return self;
}
@end

18
MTSubscriber.h Normal file
View File

@ -0,0 +1,18 @@
#import <Foundation/Foundation.h>
#import "MTDisposable.h"
@interface MTSubscriber : NSObject <MTDisposable>
{
}
- (instancetype)initWithNext:(void (^)(id))next error:(void (^)(id))error completed:(void (^)())completed;
- (void)_assignDisposable:(id<MTDisposable>)disposable;
- (void)_markTerminatedWithoutDisposal;
- (void)putNext:(id)next;
- (void)putError:(id)error;
- (void)putCompletion;
@end

144
MTSubscriber.m Normal file
View File

@ -0,0 +1,144 @@
#import "MTSubscriber.h"
#import <libkern/OSAtomic.h>
@interface MTSubscriberBlocks : NSObject {
@public
void (^_next)(id);
void (^_error)(id);
void (^_completed)();
}
@end
@implementation MTSubscriberBlocks
- (instancetype)initWithNext:(void (^)(id))next error:(void (^)(id))error completed:(void (^)())completed {
self = [super init];
if (self != nil) {
_next = [next copy];
_error = [error copy];
_completed = [completed copy];
}
return self;
}
@end
@interface MTSubscriber ()
{
@protected
OSSpinLock _lock;
bool _terminated;
id<MTDisposable> _disposable;
MTSubscriberBlocks *_blocks;
}
@end
@implementation MTSubscriber
- (instancetype)initWithNext:(void (^)(id))next error:(void (^)(id))error completed:(void (^)())completed
{
self = [super init];
if (self != nil)
{
_blocks = [[MTSubscriberBlocks alloc] initWithNext:next error:error completed:completed];
}
return self;
}
- (void)_assignDisposable:(id<MTDisposable>)disposable
{
if (_terminated)
[disposable dispose];
else
_disposable = disposable;
}
- (void)_markTerminatedWithoutDisposal
{
OSSpinLockLock(&_lock);
MTSubscriberBlocks *blocks = nil;
if (!_terminated)
{
blocks = _blocks;
_blocks = nil;
_terminated = true;
}
OSSpinLockUnlock(&_lock);
if (blocks) {
blocks = nil;
}
}
- (void)putNext:(id)next
{
MTSubscriberBlocks *blocks = nil;
OSSpinLockLock(&_lock);
if (!_terminated) {
blocks = _blocks;
}
OSSpinLockUnlock(&_lock);
if (blocks && blocks->_next) {
blocks->_next(next);
}
}
- (void)putError:(id)error
{
bool shouldDispose = false;
MTSubscriberBlocks *blocks = nil;
OSSpinLockLock(&_lock);
if (!_terminated)
{
blocks = _blocks;
_blocks = nil;
shouldDispose = true;
_terminated = true;
}
OSSpinLockUnlock(&_lock);
if (blocks && blocks->_error) {
blocks->_error(error);
}
if (shouldDispose)
[self->_disposable dispose];
}
- (void)putCompletion
{
bool shouldDispose = false;
MTSubscriberBlocks *blocks = nil;
OSSpinLockLock(&_lock);
if (!_terminated)
{
blocks = _blocks;
_blocks = nil;
shouldDispose = true;
_terminated = true;
}
OSSpinLockUnlock(&_lock);
if (blocks && blocks->_completed)
blocks->_completed();
if (shouldDispose)
[self->_disposable dispose];
}
- (void)dispose
{
[self->_disposable dispose];
}
@end

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.telegram.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -14,6 +14,60 @@ FOUNDATION_EXPORT double MtProtoKitDynamicVersionNumber;
//! Project version string for MtProtoKitDynamic.
FOUNDATION_EXPORT const unsigned char MtProtoKitDynamicVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <MtProtoKitDynamic/PublicHeader.h>
#ifndef MtProtoKitDynamicFramework
# define MtProtoKitDynamicFramework 1
#endif
#import <MTProtoKitDynamic/MTTime.h>
#import <MTProtoKitDynamic/MTTimer.h>
#import <MTProtoKitDynamic/MTLogging.h>
#import <MTProtoKitDynamic/MTEncryption.h>
#import <MTProtoKitDynamic/MTInternalId.h>
#import <MTProtoKitDynamic/MTQueue.h>
#import <MTProtoKitDynamic/MTOutputStream.h>
#import <MTProtoKitDynamic/MTInputStream.h>
#import <MTProtoKitDynamic/MTSerialization.h>
#import <MTProtoKitDynamic/MTExportedAuthorizationData.h>
#import <MTProtoKitDynamic/MTRpcError.h>
#import <MTProtoKitDynamic/MTKeychain.h>
#import <MTProtoKitDynamic/MTFileBasedKeychain.h>
#import <MTProtoKitDynamic/MTContext.h>
#import <MTProtoKitDynamic/MTTransportScheme.h>
#import <MTProtoKitDynamic/MTDatacenterTransferAuthAction.h>
#import <MTProtoKitDynamic/MTDatacenterAuthAction.h>
#import <MTProtoKitDynamic/MTDatacenterAuthMessageService.h>
#import <MTProtoKitDynamic/MTDatacenterAddress.h>
#import <MTProtoKitDynamic/MTDatacenterAddressSet.h>
#import <MTProtoKitDynamic/MTDatacenterAuthInfo.h>
#import <MTProtoKitDynamic/MTDatacenterSaltInfo.h>
#import <MTProtoKitDynamic/MTDatacenterAddressListData.h>
#import <MTProtoKitDynamic/MTProto.h>
#import <MTProtoKitDynamic/MTSessionInfo.h>
#import <MTProtoKitDynamic/MTTimeFixContext.h>
#import <MTProtoKitDynamic/MTPreparedMessage.h>
#import <MTProtoKitDynamic/MTOutgoingMessage.h>
#import <MTProtoKitDynamic/MTIncomingMessage.h>
#import <MTProtoKitDynamic/MTMessageEncryptionKey.h>
#import <MTProtoKitDynamic/MTMessageService.h>
#import <MTProtoKitDynamic/MTMessageTransaction.h>
#import <MTProtoKitDynamic/MTTimeSyncMessageService.h>
#import <MTProtoKitDynamic/MTRequestMessageService.h>
#import <MTProtoKitDynamic/MTRequest.h>
#import <MTProtoKitDynamic/MTRequestContext.h>
#import <MTProtoKitDynamic/MTRequestErrorContext.h>
#import <MTProtoKitDynamic/MTDropResponseContext.h>
#import <MTProtoKitDynamic/MTApiEnvironment.h>
#import <MTProtoKitDynamic/MTResendMessageService.h>
#import <MTProtoKitDynamic/MTNetworkAvailability.h>
#import <MTProtoKitDynamic/MTTransport.h>
#import <MTProtoKitDynamic/MTTransportTransaction.h>
#import <MTProtoKitDynamic/MTTcpTransport.h>
#import <MTProtoKitDynamic/MTHttpTransport.h>
#import <MTProtoKitDynamic/MTHttpRequestOperation.h>
#import <MTProtoKitDynamic/MTAtomic.h>
#import <MTProtoKitDynamic/MTBag.h>
#import <MTProtoKitDynamic/MTDisposable.h>
#import <MTProtoKitDynamic/MTSubscriber.h>
#import <MTProtoKitDynamic/MTSignal.h>
#import <MTProtoKitDynamic/MTNetworkUsageCalculationInfo.h>
#import <MTProtoKitDynamic/MTNetworkUsageManager.h>

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.telegram.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.telegram.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -14,6 +14,60 @@ FOUNDATION_EXPORT double MtProtoKitMacVersionNumber;
//! Project version string for MtProtoKitMac.
FOUNDATION_EXPORT const unsigned char MtProtoKitMacVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <MtProtoKitMac/PublicHeader.h>
#ifndef MtProtoKitMacFramework
# define MtProtoKitMacFramework 1
#endif
#import <MtProtoKitMac/MTTime.h>
#import <MtProtoKitMac/MTTimer.h>
#import <MtProtoKitMac/MTLogging.h>
#import <MtProtoKitMac/MTEncryption.h>
#import <MtProtoKitMac/MTInternalId.h>
#import <MtProtoKitMac/MTQueue.h>
#import <MtProtoKitMac/MTOutputStream.h>
#import <MtProtoKitMac/MTInputStream.h>
#import <MtProtoKitMac/MTSerialization.h>
#import <MtProtoKitMac/MTExportedAuthorizationData.h>
#import <MtProtoKitMac/MTRpcError.h>
#import <MtProtoKitMac/MTKeychain.h>
#import <MtProtoKitMac/MTFileBasedKeychain.h>
#import <MtProtoKitMac/MTContext.h>
#import <MtProtoKitMac/MTTransportScheme.h>
#import <MtProtoKitMac/MTDatacenterTransferAuthAction.h>
#import <MtProtoKitMac/MTDatacenterAuthAction.h>
#import <MtProtoKitMac/MTDatacenterAuthMessageService.h>
#import <MtProtoKitMac/MTDatacenterAddress.h>
#import <MtProtoKitMac/MTDatacenterAddressSet.h>
#import <MtProtoKitMac/MTDatacenterAuthInfo.h>
#import <MtProtoKitMac/MTDatacenterSaltInfo.h>
#import <MtProtoKitMac/MTDatacenterAddressListData.h>
#import <MtProtoKitMac/MTProto.h>
#import <MtProtoKitMac/MTSessionInfo.h>
#import <MtProtoKitMac/MTTimeFixContext.h>
#import <MtProtoKitMac/MTPreparedMessage.h>
#import <MtProtoKitMac/MTOutgoingMessage.h>
#import <MtProtoKitMac/MTIncomingMessage.h>
#import <MtProtoKitMac/MTMessageEncryptionKey.h>
#import <MtProtoKitMac/MTMessageService.h>
#import <MtProtoKitMac/MTMessageTransaction.h>
#import <MtProtoKitMac/MTTimeSyncMessageService.h>
#import <MtProtoKitMac/MTRequestMessageService.h>
#import <MtProtoKitMac/MTRequest.h>
#import <MtProtoKitMac/MTRequestContext.h>
#import <MtProtoKitMac/MTRequestErrorContext.h>
#import <MtProtoKitMac/MTDropResponseContext.h>
#import <MtProtoKitMac/MTApiEnvironment.h>
#import <MtProtoKitMac/MTResendMessageService.h>
#import <MtProtoKitMac/MTNetworkAvailability.h>
#import <MtProtoKitMac/MTTransport.h>
#import <MtProtoKitMac/MTTransportTransaction.h>
#import <MtProtoKitMac/MTTcpTransport.h>
#import <MtProtoKitMac/MTHttpTransport.h>
#import <MTProtoKitMac/MTHttpRequestOperation.h>
#import <MtProtoKitMac/MTAtomic.h>
#import <MtProtoKitMac/MTBag.h>
#import <MtProtoKitMac/MTDisposable.h>
#import <MtProtoKitMac/MTSubscriber.h>
#import <MtProtoKitMac/MTSignal.h>
#import <MtProtoKitMac/MTNetworkUsageCalculationInfo.h>
#import <MtProtoKitMac/MTNetworkUsageManager.h>

View File

@ -8,4 +8,3 @@
#import <Cocoa/Cocoa.h>
#endif
#import <MTProtoKit/MTLogging.h>

View File

@ -8,4 +8,3 @@
#import <Foundation/Foundation.h>
#endif
#import <MTProtoKit/MTLogging.h>

Some files were not shown because too many files have changed in this diff Show More