mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-02 02:43:07 +00:00
no message
This commit is contained in:
parent
57a9c196b9
commit
dbba320020
11
MTAes.h
Normal file
11
MTAes.h
Normal 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
288
MTAes.m
Normal 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
11
MTAtomic.h
Normal 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
64
MTAtomic.m
Normal 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
11
MTBag.h
Normal 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
74
MTBag.m
Normal 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
|
@ -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
|
||||
|
@ -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
26
MTDisposable.h
Normal 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
198
MTDisposable.m
Normal 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
|
15
MTNetworkUsageCalculationInfo.h
Normal file
15
MTNetworkUsageCalculationInfo.h
Normal 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
|
17
MTNetworkUsageCalculationInfo.m
Normal file
17
MTNetworkUsageCalculationInfo.m
Normal 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
26
MTNetworkUsageManager.h
Normal 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
140
MTNetworkUsageManager.m
Normal 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
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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)];
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTDatacenterAddress.h>
|
||||
#import "MTDatacenterAddress.h"
|
||||
|
||||
#import <netinet/in.h>
|
||||
#import <arpa/inet.h>
|
||||
|
@ -6,7 +6,9 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTDatacenterAddress.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class MTDatacenterAddress;
|
||||
|
||||
@interface MTDatacenterAddressSet : NSObject <NSCoding>
|
||||
|
||||
|
@ -6,7 +6,9 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTDatacenterAddressSet.h>
|
||||
#import "MTDatacenterAddressSet.h"
|
||||
|
||||
#import "MTDatacenterAddress.h"
|
||||
|
||||
@implementation MTDatacenterAddressSet
|
||||
|
||||
|
@ -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];
|
||||
|
@ -6,9 +6,8 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTDatacenterAuthInfo.h>
|
||||
|
||||
#import <MTProtoKit/MTDatacenterSaltInfo.h>
|
||||
#import "MTDatacenterAuthInfo.h"
|
||||
#import "MTDatacenterSaltInfo.h"
|
||||
|
||||
@implementation MTDatacenterAuthInfo
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTDatacenterSaltInfo.h>
|
||||
#import "MTDatacenterSaltInfo.h"
|
||||
|
||||
@implementation MTDatacenterSaltInfo
|
||||
|
||||
|
@ -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];
|
||||
|
@ -24,4 +24,4 @@
|
||||
- (void)execute:(MTContext *)context datacenterId:(NSInteger)datacenterId;
|
||||
- (void)cancel;
|
||||
|
||||
@end
|
||||
@end
|
||||
|
@ -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];
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTDropResponseContext.h>
|
||||
#import "MTDropResponseContext.h"
|
||||
|
||||
@implementation MTDropResponseContext
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
9
MTProtoKit/MTHttpRequestOperation.h
Normal file
9
MTProtoKit/MTHttpRequestOperation.h
Normal file
@ -0,0 +1,9 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class MTSignal;
|
||||
|
||||
@interface MTHttpRequestOperation : NSObject
|
||||
|
||||
+ (MTSignal *)dataForHttpUrl:(NSURL *)url;
|
||||
|
||||
@end
|
46
MTProtoKit/MTHttpRequestOperation.m
Normal file
46
MTProtoKit/MTHttpRequestOperation.m
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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]];
|
||||
|
@ -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 ()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTIncomingMessage.h>
|
||||
#import "MTIncomingMessage.h"
|
||||
|
||||
@implementation MTIncomingMessage
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -6,4 +6,4 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTKeychain.h>
|
||||
#import "MTKeychain.h"
|
||||
|
@ -15,6 +15,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool MTLogEnabled();
|
||||
void MTLog(NSString *format, ...);
|
||||
void MTLogSetLoggingFunction(void (*function)(NSString *, va_list args));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -6,9 +6,9 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTMessageTransaction.h>
|
||||
#import "MTMessageTransaction.h"
|
||||
|
||||
#import <MTProtoKit/MTInternalId.h>
|
||||
#import "MTInternalId.h"
|
||||
|
||||
MTInternalIdClass(MTMessageTransaction)
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTOutgoingMessage.h>
|
||||
#import "MTOutgoingMessage.h"
|
||||
|
||||
@interface MTOutgoingMessageInternalId : NSObject <NSCopying>
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTOutputStream.h>
|
||||
#import "MTOutputStream.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
# import <endian.h>
|
||||
|
@ -6,9 +6,9 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTPreparedMessage.h>
|
||||
#import "MTPreparedMessage.h"
|
||||
|
||||
#import <MTProtoKit/MTInternalId.h>
|
||||
#import "MTInternalId.h"
|
||||
|
||||
MTInternalIdClass(MTPreparedMessage)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -13,6 +13,8 @@
|
||||
- (instancetype)initWithName:(const char *)name;
|
||||
|
||||
+ (MTQueue *)mainQueue;
|
||||
+ (MTQueue *)concurrentDefaultQueue;
|
||||
+ (MTQueue *)concurrentLowQueue;
|
||||
|
||||
- (dispatch_queue_t)nativeQueue;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -6,7 +6,9 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTRequest.h>
|
||||
#import "MTRequest.h"
|
||||
|
||||
#import "MTRpcError.h"
|
||||
|
||||
@interface MTRequestInternalId : NSObject <NSCopying>
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTRequestContext.h>
|
||||
#import "MTRequestContext.h"
|
||||
|
||||
@implementation MTRequestContext
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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 ()
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTTimer.h>
|
||||
#import "MTTimer.h"
|
||||
|
||||
@interface MTTimer ()
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright Peter Iakovlev, 2013.
|
||||
*/
|
||||
|
||||
#import <MTProtoKit/MTTransportTransaction.h>
|
||||
#import "MTTransportTransaction.h"
|
||||
|
||||
@implementation MTTransportTransaction
|
||||
|
||||
|
21
MTRsa.h
Normal file
21
MTRsa.h
Normal 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
448
MTRsa.m
Normal 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
62
MTSignal.h
Normal 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
817
MTSignal.m
Normal 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
18
MTSubscriber.h
Normal 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
144
MTSubscriber.m
Normal 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
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -8,4 +8,3 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
|
||||
#import <MTProtoKit/MTLogging.h>
|
||||
|
@ -8,4 +8,3 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
#import <MTProtoKit/MTLogging.h>
|
||||
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user