From 1b32f70d51c1f841b9a6dba12df3dd814440b471 Mon Sep 17 00:00:00 2001 From: Peter Iakovlev Date: Mon, 15 Dec 2014 21:29:49 +0300 Subject: [PATCH] Ready state --- MTProtoKit/MTContext.h | 2 + MTProtoKit/MTContext.m | 2 +- MTProtoKit/MTDatacenterAuthMessageService.m | 1 + MTProtoKit/MTDiscoverTransportSchemeAction.m | 1 + MTProtoKit/MTEncryption.m | 1 + MTProtoKit/MTHttpTransport.m | 1 + MTProtoKit/MTInputStream.m | 2 + MTProtoKit/MTKeychain.m | 1 + MTProtoKit/MTMessageService.h | 2 + MTProtoKit/MTNetworkAvailability.m | 1 + ...MacBook Pro's conflicted copy 2014-02-18).mm | 1900 ----------------- MTProtoKit/MTProto.h | 2 + MTProtoKit/{MTProto.mm => MTProto.m} | 1 + MTProtoKit/MTRequestErrorContext.h | 1 + MTProtoKit/MTRequestMessageService.m | 1 + MTProtoKit/MTResendMessageService.m | 2 + .../{MTSessionInfo.mm => MTSessionInfo.m} | 33 +- MTProtoKit/MTTcpConnection.m | 1 + MTProtoKit/MTTcpConnectionBehaviour.h | 2 + MTProtoKit/MTTcpConnectionBehaviour.m | 2 + MTProtoKit/MTTcpTransport.m | 1 + MTProtoKit/MTTimeFixContext.h | 1 + MtProtoKit.xcodeproj/project.pbxproj | 28 +- thirdparty/AsyncSocket/GCDAsyncSocket.m | 2 + 24 files changed, 56 insertions(+), 1935 deletions(-) delete mode 100644 MTProtoKit/MTProto (Peter’s MacBook Pro's conflicted copy 2014-02-18).mm rename MTProtoKit/{MTProto.mm => MTProto.m} (99%) rename MTProtoKit/{MTSessionInfo.mm => MTSessionInfo.m} (87%) diff --git a/MTProtoKit/MTContext.h b/MTProtoKit/MTContext.h index 7b9bce867f..a005aa0a43 100644 --- a/MTProtoKit/MTContext.h +++ b/MTProtoKit/MTContext.h @@ -6,6 +6,8 @@ * Copyright Peter Iakovlev, 2013. */ +#import + @class MTDatacenterAddress; @class MTDatacenterAddressSet; @class MTDatacenterAuthInfo; diff --git a/MTProtoKit/MTContext.m b/MTProtoKit/MTContext.m index 58ac63feff..596d04324f 100644 --- a/MTProtoKit/MTContext.m +++ b/MTProtoKit/MTContext.m @@ -10,8 +10,8 @@ #import +#import #import - #import #import diff --git a/MTProtoKit/MTDatacenterAuthMessageService.m b/MTProtoKit/MTDatacenterAuthMessageService.m index 3387f985b1..e93228acd4 100644 --- a/MTProtoKit/MTDatacenterAuthMessageService.m +++ b/MTProtoKit/MTDatacenterAuthMessageService.m @@ -8,6 +8,7 @@ #import +#import #import #import #import diff --git a/MTProtoKit/MTDiscoverTransportSchemeAction.m b/MTProtoKit/MTDiscoverTransportSchemeAction.m index 1f2531c1c1..23b89fc835 100644 --- a/MTProtoKit/MTDiscoverTransportSchemeAction.m +++ b/MTProtoKit/MTDiscoverTransportSchemeAction.m @@ -8,6 +8,7 @@ #import "MTDiscoverTransportSchemeAction.h" +#import #import #import #import diff --git a/MTProtoKit/MTEncryption.m b/MTProtoKit/MTEncryption.m index f97ded4da6..39e853ccf0 100644 --- a/MTProtoKit/MTEncryption.m +++ b/MTProtoKit/MTEncryption.m @@ -8,6 +8,7 @@ #import +#import #import #import diff --git a/MTProtoKit/MTHttpTransport.m b/MTProtoKit/MTHttpTransport.m index 0cbe163514..bbaa82960f 100644 --- a/MTProtoKit/MTHttpTransport.m +++ b/MTProtoKit/MTHttpTransport.m @@ -8,6 +8,7 @@ #import +#import #import #import diff --git a/MTProtoKit/MTInputStream.m b/MTProtoKit/MTInputStream.m index 5ac3ab2b4e..5b183201ab 100644 --- a/MTProtoKit/MTInputStream.m +++ b/MTProtoKit/MTInputStream.m @@ -6,6 +6,8 @@ * Copyright Peter Iakovlev, 2013. */ +#import +#import #import #if TARGET_OS_IPHONE diff --git a/MTProtoKit/MTKeychain.m b/MTProtoKit/MTKeychain.m index ae43150081..103b6e7e83 100644 --- a/MTProtoKit/MTKeychain.m +++ b/MTProtoKit/MTKeychain.m @@ -7,6 +7,7 @@ */ #import +#import #import diff --git a/MTProtoKit/MTMessageService.h b/MTProtoKit/MTMessageService.h index 03fc44e8eb..e840fb6a3b 100644 --- a/MTProtoKit/MTMessageService.h +++ b/MTProtoKit/MTMessageService.h @@ -6,6 +6,8 @@ * Copyright Peter Iakovlev, 2013. */ +#import + @class MTProto; @class MTIncomingMessage; @class MTMessageTransaction; diff --git a/MTProtoKit/MTNetworkAvailability.m b/MTProtoKit/MTNetworkAvailability.m index b14789c5d6..e803f3a3b8 100644 --- a/MTProtoKit/MTNetworkAvailability.m +++ b/MTProtoKit/MTNetworkAvailability.m @@ -8,6 +8,7 @@ #import +#import #import #import diff --git a/MTProtoKit/MTProto (Peter’s MacBook Pro's conflicted copy 2014-02-18).mm b/MTProtoKit/MTProto (Peter’s MacBook Pro's conflicted copy 2014-02-18).mm deleted file mode 100644 index 9197c4da10..0000000000 --- a/MTProtoKit/MTProto (Peter’s MacBook Pro's conflicted copy 2014-02-18).mm +++ /dev/null @@ -1,1900 +0,0 @@ -/* - * This is the source code of Telegram for iOS v. 1.1 - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Peter Iakovlev, 2013. - */ - -#import - -#import - -#import -#import -#import - -#import -#import -#import -#import -#import - -#import -#import -#import -#import - -#import -#import -#import -#import - -#import -#import - -#import -#import - -#import -#import - -typedef enum { - MTProtoStateAwaitingDatacenterAddress = 1, - MTProtoStateAwaitingDatacenterAuthorization = 2, - MTProtoStateAwaitingDatacenterAuthToken = 4, - MTProtoStateAwaitingTimeFixAndSalts = 8, - MTProtoStateStopped = 16 -} MTProtoState; - -static const NSUInteger MTMaxContainerSize = 3 * 1024; -static const NSUInteger MTMaxUnacknowledgedMessageSize = 1 * 1024 * 1024; -static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; - -@interface MTProto () -{ - NSMutableArray *_messageServices; - - MTDatacenterAuthInfo *_authInfo; - MTSessionInfo *_sessionInfo; - MTTimeFixContext *_timeFixContext; - - MTTransport *_transport; - - int _mtState; - - bool _willRequestTransactionOnNextQueuePass; -} - -@end - -@implementation MTProto - -+ (MTQueue *)managerQueue -{ - static MTQueue *queue = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - queue = [[MTQueue alloc] initWithName:"org.mtproto.managerQueue"]; - }); - return queue; -} - -- (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId -{ -#ifdef DEBUG - NSAssert(context != nil, @"context should not be nil"); - NSAssert(context.serialization != nil, @"context serialization should not be nil"); - NSAssert(datacenterId != 0, @"datacenterId should not be 0"); -#endif - - self = [super init]; - if (self != nil) - { - _context = context; - _datacenterId = datacenterId; - - [_context addChangeListener:self]; - - _messageServices = [[NSMutableArray alloc] init]; - - _sessionInfo = [[MTSessionInfo alloc] initWithRandomSessionIdAndContext:_context]; - _authInfo = [_context authInfoForDatacenterWithId:_datacenterId]; - - _shouldStayConnected = true; - } - return self; -} - -- (void)dealloc -{ - MTTransport *transport = _transport; - _transport.delegate = nil; - _transport = nil; - - [[MTProto managerQueue] dispatchOnQueue:^ - { - [transport stop]; - }]; -} - -- (void)stop -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if ((_mtState & MTProtoStateStopped) == 0) - { - [self setMtState:_mtState | MTProtoStateStopped]; - - if (_transport != nil) - { - _transport.delegate = nil; - [_transport stop]; - [self setTransport:nil]; - } - } - }]; -} - -- (void)updateConnectionState -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (_transport != nil) - [_transport updateConnectionState]; - else - { - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoNetworkAvailabilityChanged:isNetworkAvailable:)]) - [delegate mtProtoNetworkAvailabilityChanged:self isNetworkAvailable:false]; - if ([delegate respondsToSelector:@selector(mtProtoConnectionStateChanged:isConnected:)]) - [delegate mtProtoConnectionStateChanged:self isConnected:false]; - if ([delegate respondsToSelector:@selector(mtProtoConnectionContextUpdateStateChanged:isUpdatingConnectionContext:)]) - [delegate mtProtoConnectionContextUpdateStateChanged:self isUpdatingConnectionContext:false]; - } - }]; -} - -- (void)setTransport:(MTTransport *)transport -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (_transport != nil) - [self removeMessageService:_transport]; - - _transport = transport; - - if (_transport != nil) - [self addMessageService:_transport]; - - [self updateConnectionState]; - }]; -} - -- (void)resetTransport -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (_mtState & MTProtoStateStopped) - return; - - if (_transport != nil) - { - _transport.delegate = nil; - [_transport stop]; - [self setTransport:nil]; - } - - if ([[_context addressSetForDatacenterWithId:_datacenterId] firstAddress] == nil) - { - if ((_mtState & MTProtoStateAwaitingDatacenterAddress) == 0) - { - [self setMtState:_mtState | MTProtoStateAwaitingDatacenterAddress]; - - [_context addressSetForDatacenterWithIdRequired:_datacenterId]; - } - } - else if (!_useUnauthorizedMode && [_context authInfoForDatacenterWithId:_datacenterId] == nil) - { - if ((_mtState & MTProtoStateAwaitingDatacenterAuthorization) == 0) - { - [self setMtState:_mtState | MTProtoStateAwaitingDatacenterAuthorization]; - - [_context authInfoForDatacenterWithIdRequired:_datacenterId]; - } - } - else if (_requiredAuthToken != nil && !_useUnauthorizedMode && ![_requiredAuthToken isEqual:[_context authTokenForDatacenterWithId:_datacenterId]]) - { - if ((_mtState & MTProtoStateAwaitingDatacenterAuthToken) == 0) - { - [self setMtState:_mtState | MTProtoStateAwaitingDatacenterAuthToken]; - - [_context authTokenForDatacenterWithIdRequired:_datacenterId authToken:_requiredAuthToken masterDatacenterId:_authTokenMasterDatacenterId]; - } - } - else - { - [self setTransport:[[MTTcpTransport alloc] initWithDelegate:self context:_context datacenterId:_datacenterId]]; - //[self setTransport:[[MTHttpTransport alloc] initWithDelegate:self context:_context datacenterId:_datacenterId]]; - } - }]; -} - -- (void)resetSessionInfo -{ - MTLog(@"[MTProto#%p resetting session]", self); - - _sessionInfo = [[MTSessionInfo alloc] initWithRandomSessionIdAndContext:_context]; - _timeFixContext = nil; - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - if ([messageService respondsToSelector:@selector(mtProtoDidChangeSession:)]) - [messageService mtProtoDidChangeSession:self]; - } - - [self resetTransport]; - [self requestTransportTransaction]; -} - -- (void)setMtState:(int)mtState -{ - bool wasPerformingServiceTasks = _mtState & MTProtoStateAwaitingTimeFixAndSalts; - - _mtState = mtState; - - bool performingServiceTasks = _mtState & MTProtoStateAwaitingTimeFixAndSalts; - - if (performingServiceTasks != wasPerformingServiceTasks) - { - bool haveResendMessagesPending = false; - for (id messageService in _messageServices) - { - if ([messageService isKindOfClass:[MTResendMessageService class]]) - { - haveResendMessagesPending = true; - - break; - } - } - - MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, haveResendMessagesPending ? "yes" : "no"); - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoServiceTasksStateChanged:isPerformingServiceTasks:)]) - [messageService mtProtoServiceTasksStateChanged:self isPerformingServiceTasks:performingServiceTasks || haveResendMessagesPending]; - } - - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoServiceTasksStateChanged:isPerformingServiceTasks:)]) - [delegate mtProtoServiceTasksStateChanged:self isPerformingServiceTasks:performingServiceTasks || haveResendMessagesPending]; - } -} - -- (void)addMessageService:(id)messageService -{ - if ([messageService respondsToSelector:@selector(mtProtoWillAddService:)]) - [messageService mtProtoWillAddService:self]; - - [[MTProto managerQueue] dispatchOnQueue:^ - { - bool notifyAboutServiceTask = false; - - if ([messageService isKindOfClass:[MTResendMessageService class]]) - { - notifyAboutServiceTask = true; - - for (id currentService in _messageServices) - { - if ([currentService isKindOfClass:[MTResendMessageService class]]) - { - notifyAboutServiceTask = false; - - break; - } - } - } - - if (![_messageServices containsObject:messageService]) - { - [_messageServices addObject:messageService]; - - if ([messageService respondsToSelector:@selector(mtProtoDidAddService:)]) - [messageService mtProtoDidAddService:self]; - } - - if (notifyAboutServiceTask) - { - MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, true ? "yes" : "no"); - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoServiceTasksStateChanged:isPerformingServiceTasks:)]) - [messageService mtProtoServiceTasksStateChanged:self isPerformingServiceTasks:true]; - } - - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoServiceTasksStateChanged:isPerformingServiceTasks:)]) - [delegate mtProtoServiceTasksStateChanged:self isPerformingServiceTasks:true]; - } - }]; -} - -- (void)removeMessageService:(id)messageService -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if ([_messageServices containsObject:messageService]) - { - [_messageServices removeObject:messageService]; - - if ([messageService respondsToSelector:@selector(mtProtoDidRemoveService:)]) - [messageService mtProtoDidRemoveService:self]; - - bool notifyAboutServiceTask = false; - if ([messageService isKindOfClass:[MTResendMessageService class]]) - { - notifyAboutServiceTask = true; - - for (id currentService in _messageServices) - { - if ([currentService isKindOfClass:[MTResendMessageService class]]) - { - notifyAboutServiceTask = false; - - break; - } - } - } - - if (notifyAboutServiceTask) - { - bool performingServiceTasks = _mtState & MTProtoStateAwaitingTimeFixAndSalts; - if (!performingServiceTasks) - { - MTLog(@"[MTProto#%p service tasks state: %d, resend: %s]", self, _mtState, false ? "yes" : "no"); - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoServiceTasksStateChanged:isPerformingServiceTasks:)]) - [messageService mtProtoServiceTasksStateChanged:self isPerformingServiceTasks:false]; - } - - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoServiceTasksStateChanged:isPerformingServiceTasks:)]) - [delegate mtProtoServiceTasksStateChanged:self isPerformingServiceTasks:false]; - } - } - } - }]; -} - -- (MTQueue *)messageServiceQueue -{ - return [MTProto managerQueue]; -} - -- (void)initiateTimeSync -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if ((_mtState & MTProtoStateAwaitingTimeFixAndSalts) == 0) - { - [self setMtState:_mtState | MTProtoStateAwaitingTimeFixAndSalts]; - - MTTimeSyncMessageService *timeSyncService = [[MTTimeSyncMessageService alloc] init]; - timeSyncService.delegate = self; - [self addMessageService:timeSyncService]; - } - }]; -} - -- (void)completeTimeSync -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if ((_mtState & MTProtoStateAwaitingTimeFixAndSalts) != 0) - { - [self setMtState:_mtState & (~MTProtoStateAwaitingTimeFixAndSalts)]; - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService isKindOfClass:[MTTimeSyncMessageService class]]) - { - ((MTTimeSyncMessageService *)messageService).delegate = nil; - [self removeMessageService:messageService]; - } - } - } - }]; -} - -- (void)requestMessageWithId:(int64_t)messageId -{ - bool alreadyRequestingThisMessage = false; - - for (id messageService in _messageServices) - { - if ([messageService isKindOfClass:[MTResendMessageService class]]) - { - if (((MTResendMessageService *)messageService).messageId == messageId) - { - alreadyRequestingThisMessage = true; - - break; - } - } - } - - if (!alreadyRequestingThisMessage) - { - MTResendMessageService *resendService = [[MTResendMessageService alloc] initWithMessageId:messageId]; - resendService.delegate = self; - [self addMessageService:resendService]; - } -} - -- (void)resendMessageServiceCompleted:(MTResendMessageService *)resendService -{ - resendService.delegate = nil; - [self removeMessageService:resendService]; -} - -- (void)requestTransportTransaction -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (!_willRequestTransactionOnNextQueuePass) - { - _willRequestTransactionOnNextQueuePass = true; - - dispatch_async([MTProto managerQueue].nativeQueue, ^ - { - _willRequestTransactionOnNextQueuePass = false; - - if ([self isStopped]) - return; - - if (_transport == nil) - [self resetTransport]; - - [_transport setDelegateNeedsTransaction]; - }); - } - }]; -} - -- (void)requestSecureTransportReset -{ - if ([self isStopped]) - return; - - if (_transport != nil) - [self resetTransport]; -} - -- (bool)canAskForTransactions -{ - return (_mtState & (MTProtoStateAwaitingDatacenterAddress | MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterAuthToken | MTProtoStateAwaitingTimeFixAndSalts | MTProtoStateStopped)) == 0; -} - -- (bool)canAskForServiceTransactions -{ - return (_mtState & (MTProtoStateAwaitingDatacenterAddress | MTProtoStateAwaitingDatacenterAuthorization | MTProtoStateAwaitingDatacenterAuthToken | MTProtoStateStopped)) == 0; -} - -- (bool)timeFixOrSaltsMissing -{ - return _mtState & MTProtoStateAwaitingTimeFixAndSalts; -} - -- (bool)isStopped -{ - return (_mtState & MTProtoStateStopped) != 0; -} - -- (void)transportNetworkAvailabilityChanged:(MTTransport *)transport isNetworkAvailable:(bool)isNetworkAvailable -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (transport != _transport) - return; - - MTLog(@"[MTProto#%p network state: %s]", self, isNetworkAvailable ? "available" : "waiting"); - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoNetworkAvailabilityChanged:isNetworkAvailable:)]) - [messageService mtProtoNetworkAvailabilityChanged:self isNetworkAvailable:isNetworkAvailable]; - } - - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoNetworkAvailabilityChanged:isNetworkAvailable:)]) - [delegate mtProtoNetworkAvailabilityChanged:self isNetworkAvailable:isNetworkAvailable]; - }]; -} - -- (void)transportConnectionStateChanged:(MTTransport *)transport isConnected:(bool)isConnected -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (transport != _transport) - return; - - MTLog(@"[MTProto#%p connection state: %s]", self, isConnected ? "connected" : "connecting"); - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoConnectionStateChanged:isConnected:)]) - [messageService mtProtoConnectionStateChanged:self isConnected:isConnected]; - } - - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoConnectionStateChanged:isConnected:)]) - [delegate mtProtoConnectionStateChanged:self isConnected:isConnected]; - }]; -} - -- (void)transportConnectionContextUpdateStateChanged:(MTTransport *)transport isUpdatingConnectionContext:(bool)isUpdatingConnectionContext -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (transport != _transport) - return; - - MTLog(@"[MTProto#%p connection context update state: %s]", self, isUpdatingConnectionContext ? "updating" : "up to date"); - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoConnectionContextUpdateStateChanged:isUpdatingConnectionContext:)]) - [messageService mtProtoConnectionContextUpdateStateChanged:self isUpdatingConnectionContext:isUpdatingConnectionContext]; - } - - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(mtProtoConnectionContextUpdateStateChanged:isUpdatingConnectionContext:)]) - [delegate mtProtoConnectionContextUpdateStateChanged:self isUpdatingConnectionContext:isUpdatingConnectionContext]; - }]; -} - -- (void)transportReadyForTransaction:(MTTransport *)transport transportSpecificTransaction:(MTMessageTransaction *)transportSpecificTransaction forceConfirmations:(bool)forceConfirmations transactionReady:(void (^)(NSArray *))transactionReady -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - // debug - /*static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - _authInfo = [[MTDatacenterAuthInfo alloc] initWithAuthKey:_authInfo.authKey authKeyId:_authInfo.authKeyId saltSet:@[] authKeyAttributes:_authInfo.authKeyAttributes]; - });*/ - - if (_authInfo.authKey != nil && !_sessionInfo.scheduledForCleanup) - { - _sessionInfo.scheduledForCleanup = true; - [_context scheduleSessionCleanupForAuthKeyId:_authInfo.authKeyId sessionInfo:_sessionInfo]; - } - - if (_transport != transport) - { - if (transactionReady) - transactionReady(nil); - } - else if ([self canAskForTransactions]) - { - MTSessionInfo *transactionSessionInfo = _sessionInfo; - - NSMutableArray *messageTransactions = [[NSMutableArray alloc] init]; - - if (transportSpecificTransaction != nil) - { - if (!(transportSpecificTransaction.requiresEncryption && _useUnauthorizedMode) && (!transportSpecificTransaction.requiresEncryption || _authInfo != nil)) - { - [messageTransactions addObject:transportSpecificTransaction]; - } - } - - bool anyTransactionHasHighPriorityMessages = false; - - NSMutableArray *messageServiceTransactions = [[NSMutableArray alloc] init]; - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:)]) - { - MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self]; - if (messageTransaction != nil) - { - for (MTOutgoingMessage *message in messageTransaction.messagePayload) - { - if (message.hasHighPriority) - { - anyTransactionHasHighPriorityMessages = true; - break; - } - } - - [messageServiceTransactions addObject:messageTransaction]; - } - } - } - - if (forceConfirmations || !anyTransactionHasHighPriorityMessages || [transactionSessionInfo scheduledMessageConfirmationsExceedSize:MTMaxUnacknowledgedMessageSize orCount:MTMaxUnacknowledgedMessageCount]) - { - NSArray *scheduledMessageConfirmations = [transactionSessionInfo scheduledMessageConfirmations]; - if (scheduledMessageConfirmations.count != 0) - { - MTOutgoingMessage *outgoingMessage = [[MTOutgoingMessage alloc] initWithBody:[_context.serialization msgsAck:scheduledMessageConfirmations]]; - outgoingMessage.requiresConfirmation = false; - - [messageTransactions addObject:[[MTMessageTransaction alloc] initWithMessagePayload:@[outgoingMessage] completion:^(__unused NSDictionary *messageInternalIdToTransactionId, NSDictionary *messageInternalIdToPreparedMessage, __unused NSDictionary *messageInternalIdToQuickAckId) - { - if (messageInternalIdToTransactionId[outgoingMessage.internalId] != nil && messageInternalIdToPreparedMessage[outgoingMessage.internalId] != nil) - { - [transactionSessionInfo assignTransactionId:messageInternalIdToTransactionId[outgoingMessage.internalId] toScheduledMessageConfirmationsWithIds:scheduledMessageConfirmations]; - } - }]]; - } - } - - [messageTransactions addObjectsFromArray:messageServiceTransactions]; - - NSMutableArray *transactionMessageList = [[NSMutableArray alloc] init]; - NSMutableDictionary *messageInternalIdToPreparedMessage = [[NSMutableDictionary alloc] init]; - NSMutableDictionary *preparedMessageInternalIdToMessageInternalId = [[NSMutableDictionary alloc] init]; - - bool monotonityViolated = false; - bool saltSetEmpty = false; - - int64_t messageSalt = 0; - if (!_useUnauthorizedMode) - { - messageSalt = [_authInfo authSaltForMessageId:[transactionSessionInfo actualClientMessagId]]; - if (messageSalt == 0) - saltSetEmpty = true; - } - - bool transactionNeedsQuickAck = false; - bool transactionExpectsDataInResponse = false; - - for (MTMessageTransaction *messageTransaction in messageTransactions) - { - for (MTOutgoingMessage *outgoingMessage in messageTransaction.messagePayload) - { - id messageBody = outgoingMessage.body; - - if (outgoingMessage.dynamicDecorator != nil) - { - id decoratedBody = outgoingMessage.dynamicDecorator(messageBody, messageInternalIdToPreparedMessage); - if (decoratedBody != nil) - messageBody = decoratedBody; - } - - NSData *data = [_context.serialization serializeMessage:messageBody]; - - int64_t messageId = 0; - int32_t messageSeqNo = 0; - if (outgoingMessage.messageId == 0) - { - messageId = [transactionSessionInfo generateClientMessageId:&monotonityViolated]; - messageSeqNo = [transactionSessionInfo takeSeqNo:outgoingMessage.requiresConfirmation]; - } - else - { - messageId = outgoingMessage.messageId; - messageSeqNo = outgoingMessage.messageSeqNo; - } - - MTLog(@"[MTProto#%p preparing %@]", self, [_context.serialization messageDescription:messageBody messageId:messageId messageSeqNo:messageSeqNo]); - - if (!monotonityViolated || _useUnauthorizedMode) - { - MTPreparedMessage *preparedMessage = [[MTPreparedMessage alloc] initWithData:data messageId:messageId seqNo:messageSeqNo salt:messageSalt requiresConfirmation:outgoingMessage.requiresConfirmation hasHighPriority:outgoingMessage.hasHighPriority inResponseToMessageId:outgoingMessage.inResponseToMessageId]; - - if (outgoingMessage.needsQuickAck) - transactionNeedsQuickAck = true; - if (outgoingMessage.requiresConfirmation) - transactionExpectsDataInResponse = true; - - messageInternalIdToPreparedMessage[outgoingMessage.internalId] = preparedMessage; - preparedMessageInternalIdToMessageInternalId[preparedMessage.internalId] = outgoingMessage.internalId; - - [transactionMessageList addObject:preparedMessage]; - } - } - - if ([transport needsParityCorrection] && !transactionExpectsDataInResponse) - transactionNeedsQuickAck = true; - } - - if (monotonityViolated || saltSetEmpty) - { - for (MTMessageTransaction *messageTransaction in messageTransactions) - { - if (messageTransaction.completion) - messageTransaction.completion(nil, nil, nil); - } - - if (transactionReady != nil) - transactionReady(nil); - - if (monotonityViolated) - { - MTLog(@"[MTProto#%p client message id monotonity violated]", self); - - [self resetSessionInfo]; - } - else if (saltSetEmpty) - [self initiateTimeSync]; - } - else if (transactionReady != nil) - { - if (transactionMessageList.count != 0) - { - if (transactionMessageList.count != 1) - { - [transactionMessageList sortUsingComparator:^NSComparisonResult(MTPreparedMessage *message1, MTPreparedMessage *message2) - { - return message1.messageId < message2.messageId ? NSOrderedAscending : NSOrderedDescending; - }]; - - if (!forceConfirmations) - { - NSMutableArray *highPriorityMessages = nil; - for (NSInteger i = 0; i < (NSInteger)transactionMessageList.count; i++) - { - MTPreparedMessage *preparedMessage = transactionMessageList[(NSUInteger)i]; - if (preparedMessage.hasHighPriority) - { - if (highPriorityMessages == nil) - highPriorityMessages = [[NSMutableArray alloc] init]; - - [highPriorityMessages addObject:preparedMessage]; - [transactionMessageList removeObjectAtIndex:(NSUInteger)i]; - i--; - } - } - - if (highPriorityMessages != nil) - { - [highPriorityMessages addObjectsFromArray:transactionMessageList]; - transactionMessageList = highPriorityMessages; - } - } - } - - NSMutableArray *transactionPayloadList = [[NSMutableArray alloc] init]; - NSMutableArray *messageInternalIdsByPayload = [[NSMutableArray alloc] init]; - NSMutableArray *quickAckIdsByPayload = [[NSMutableArray alloc] init]; - - bool currentlyProcessingHighPriority = false; - for (NSUInteger i = 0; i < transactionMessageList.count; ) - { - if (!_useUnauthorizedMode) - { - NSMutableArray *currentContainerMessages = [[NSMutableArray alloc] init]; - NSUInteger currentContainerSize = 0; - - for (NSUInteger j = i; j < transactionMessageList.count; j++, i++) - { - MTPreparedMessage *preparedMessage = transactionMessageList[j]; - - bool breakContainer = false; - - if (!forceConfirmations) - { - if (preparedMessage.hasHighPriority) - currentlyProcessingHighPriority = true; - else if (currentlyProcessingHighPriority) - { - currentlyProcessingHighPriority = false; - breakContainer = true; - } - } - - if (currentContainerSize + preparedMessage.data.length > MTMaxContainerSize || (breakContainer && currentContainerSize != 0)) - { - if (currentContainerSize == 0) - { - [currentContainerMessages addObject:preparedMessage]; - currentContainerSize += preparedMessage.data.length; - i++; - } - - break; - } - else - { - [currentContainerMessages addObject:preparedMessage]; - currentContainerSize += preparedMessage.data.length; - } - } - - if (currentContainerMessages.count == 1) - { - int32_t quickAckId = 0; - NSData *messageData = [self _dataForEncryptedMessage:currentContainerMessages[0] sessionInfo:transactionSessionInfo quickAckId:&quickAckId]; - if (messageData != nil) - { - [transactionPayloadList addObject:messageData]; - [messageInternalIdsByPayload addObject:@[preparedMessageInternalIdToMessageInternalId[((MTPreparedMessage *)currentContainerMessages[0]).internalId]]]; - [quickAckIdsByPayload addObject:@(quickAckId)]; - } - } - else if (currentContainerMessages.count != 0) - { - int32_t quickAckId = 0; - NSData *containerData = [self _dataForEncryptedContainerWithMessages:currentContainerMessages sessionInfo:transactionSessionInfo quickAckId:&quickAckId]; - if (containerData != nil) - { - [transactionPayloadList addObject:containerData]; - - NSMutableArray *messageInternalIds = [[NSMutableArray alloc] initWithCapacity:currentContainerMessages.count]; - for (MTPreparedMessage *preparedMessage in currentContainerMessages) - { - [messageInternalIds addObject:preparedMessageInternalIdToMessageInternalId[preparedMessage.internalId]]; - } - [messageInternalIdsByPayload addObject:messageInternalIds]; - [quickAckIdsByPayload addObject:@(quickAckId)]; - } - } - } - else - { - MTPreparedMessage *preparedMessage = transactionMessageList[i]; - NSData *messageData = [self _dataForPlainMessage:preparedMessage]; - i++; - if (messageData != nil) - { - [transactionPayloadList addObject:messageData]; - [messageInternalIdsByPayload addObject:@[preparedMessageInternalIdToMessageInternalId[preparedMessage.internalId]]]; - [quickAckIdsByPayload addObject:@(0)]; - } - } - } - - if (transactionPayloadList.count != 0) - { - NSMutableArray *transportTransactions = [[NSMutableArray alloc] initWithCapacity:transactionPayloadList.count]; - - for (NSUInteger i = 0; i < transactionPayloadList.count; i++) - { - [transportTransactions addObject:[[MTTransportTransaction alloc] initWithPayload:transactionPayloadList[i] completion:^(bool success, id transactionId) - { - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (success) - { - NSMutableDictionary *messageInternalIdToTransactionId = [[NSMutableDictionary alloc] init]; - NSMutableDictionary *messageInternalIdToQuickAckId = [[NSMutableDictionary alloc] init]; - NSMutableDictionary *transactionMessageInternalIdToPreparedMessage = [[NSMutableDictionary alloc] init]; - for (id messageInternalId in messageInternalIdsByPayload[i]) - { - messageInternalIdToTransactionId[messageInternalId] = transactionId; - messageInternalIdToQuickAckId[messageInternalId] = quickAckIdsByPayload[i]; - - MTPreparedMessage *preparedMessage = messageInternalIdToPreparedMessage[messageInternalId]; - if (preparedMessage != nil) - transactionMessageInternalIdToPreparedMessage[messageInternalId] = preparedMessage; - } - - for (MTMessageTransaction *messageTransaction in messageTransactions) - { - if (messageTransaction.completion) - messageTransaction.completion(messageInternalIdToTransactionId, transactionMessageInternalIdToPreparedMessage, messageInternalIdToQuickAckId); - } - } - else - { - NSMutableString *idsString = [[NSMutableString alloc] init]; - for (id messageInternalId in messageInternalIdsByPayload[i]) - { - MTOutgoingMessage *outgoingMessage = messageInternalIdToPreparedMessage[messageInternalId]; - if (outgoingMessage != nil) - { - if (idsString.length != 0) - [idsString appendString:@", "]; - [idsString appendFormat:@"%" PRId64 "", outgoingMessage.messageId]; - } - } - - MTLog(@"[MTProto#%p transport did not accept transactions with messages (%@)]", self, idsString); - } - }]; - } needsQuickAck:transactionNeedsQuickAck expectsDataInResponse:transactionExpectsDataInResponse]]; - } - - transactionReady(transportTransactions); - } - else - { - for (MTMessageTransaction *messageTransaction in messageTransactions) - { - if (messageTransaction.completion) - messageTransaction.completion(nil, nil, nil); - } - - transactionReady(nil); - } - } - else - transactionReady(nil); - } - } - else if ([self timeFixOrSaltsMissing] && [self canAskForServiceTransactions] && (_timeFixContext == nil || _timeFixContext.transactionId == nil)) - { - int64_t timeFixMessageId = [_sessionInfo generateClientMessageId:NULL]; - int32_t timeFixSeqNo = [_sessionInfo takeSeqNo:false]; - - int64_t randomId = 0; - arc4random_buf(&randomId, 8); - - id ping = [_context.serialization ping:randomId]; - NSData *messageData = [_context.serialization serializeMessage:ping]; - - MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; - - MTLog(@"[MTProto#%x sending time fix %@ (%" PRId64 "/%" PRId32 ")]", self, NSStringFromClass([ping class]), timeFixMessageId, timeFixSeqNo); - - [decryptedOs writeInt64:[_authInfo authSaltForMessageId:timeFixMessageId]]; // salt - [decryptedOs writeInt64:_sessionInfo.sessionId]; - [decryptedOs writeInt64:timeFixMessageId]; - [decryptedOs writeInt32:timeFixSeqNo]; - - [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 = [decryptedOs currentBytes]; - - NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + messageData.length); - NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; - - NSData *transactionData = nil; - - MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; - if (encryptionKey != nil) - { - NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length]; - [encryptedData appendData:decryptedData]; - MTAesEncryptInplace(encryptedData, encryptionKey.key, encryptionKey.iv); - - int64_t authKeyId = _authInfo.authKeyId; - [encryptedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&authKeyId length:8]; - [encryptedData replaceBytesInRange:NSMakeRange(8, 0) withBytes:messageKey.bytes length:messageKey.length]; - - transactionData = encryptedData; - } - - if (transactionReady != nil) - { - if (transactionData != nil) - { - __weak MTProto *weakSelf = self; - transactionReady(@[[[MTTransportTransaction alloc] initWithPayload:transactionData completion:^(bool success, id transactionId) - { - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (success) - { - if (transactionId != nil) - { - _timeFixContext = [[MTTimeFixContext alloc] initWithMessageId:timeFixMessageId messageSeqNo:timeFixSeqNo transactionId:transactionId timeFixAbsoluteStartTime:MTAbsoluteSystemTime()]; - } - } - else - { - __strong MTProto *strongSelf = weakSelf; - [strongSelf requestTransportTransaction]; - } - }]; - }]]); - } - else - transactionReady(nil); - } - } - else if (transactionReady != nil) - transactionReady(nil); - }]; -} - -- (NSData *)_dataForEncryptedContainerWithMessages:(NSArray *)preparedMessages sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId -{ - NSMutableArray *containerMessageIds = [[NSMutableArray alloc] init]; - - MTOutputStream *containerOs = [[MTOutputStream alloc] init]; - - [containerOs writeInt32:0x73f1f8dc]; // msg_container - [containerOs writeInt32:(int32_t)preparedMessages.count]; - - int64_t salt = 0; - for (MTPreparedMessage *preparedMessage in preparedMessages) - { - salt = preparedMessage.salt; - - [containerOs writeInt64:preparedMessage.messageId]; - [containerOs writeInt32:preparedMessage.seqNo]; - [containerOs writeInt32:(int32_t)preparedMessage.data.length]; - [containerOs writeData:preparedMessage.data]; - - if (preparedMessage.requiresConfirmation) - [containerMessageIds addObject:@(preparedMessage.messageId)]; - } - - NSData *containerData = [containerOs currentBytes]; - - MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; - - int64_t containerMessageId = [sessionInfo generateClientMessageId:NULL]; - if (containerMessageIds.count != 0) - { - [sessionInfo addContainerMessageIdMapping:containerMessageId childMessageIds:containerMessageIds]; - -#ifdef DEBUG - NSMutableString *idsString = [[NSMutableString alloc] init]; - for (NSNumber *nMessageId in containerMessageIds) - { - if (idsString.length != 0) - [idsString appendString:@","]; - [idsString appendFormat:@"%lld", [nMessageId longLongValue]]; - } - MTLog(@" container (%" PRId64 ") of (%@)", containerMessageId, idsString); -#endif - } - - [decryptedOs writeInt64:salt]; - [decryptedOs writeInt64:sessionInfo.sessionId]; - [decryptedOs writeInt64:containerMessageId]; - [decryptedOs writeInt32:[sessionInfo takeSeqNo:false]]; - - [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 = [decryptedOs currentBytes]; - - NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + containerData.length); - NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; - - int32_t nQuickAckId = *((int32_t *)(messageKeyFull.bytes)); - 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]; - [encryptedData appendData:decryptedData]; - MTAesEncryptInplace(encryptedData, encryptionKey.key, encryptionKey.iv); - - int64_t authKeyId = _authInfo.authKeyId; - [encryptedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&authKeyId length:8]; - [encryptedData replaceBytesInRange:NSMakeRange(8, 0) withBytes:messageKey.bytes length:messageKey.length]; - - return encryptedData; - } - - return nil; -} - -- (NSData *)_dataForPlainMessage:(MTPreparedMessage *)preparedMessage -{ - MTOutputStream *os = [[MTOutputStream alloc] init]; - - [os writeInt64:0]; - [os writeInt64:preparedMessage.messageId]; - [os writeInt32:(int32_t)preparedMessage.data.length]; - [os writeData:preparedMessage.data]; - - NSData *messageData = [os currentBytes]; - - return messageData; -} - -- (NSData *)_dataForEncryptedMessage:(MTPreparedMessage *)preparedMessage sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId -{ - MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; - - [decryptedOs writeInt64:preparedMessage.salt]; - [decryptedOs writeInt64:sessionInfo.sessionId]; - [decryptedOs writeInt64:preparedMessage.messageId]; - [decryptedOs writeInt32:preparedMessage.seqNo]; - - [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 = [decryptedOs currentBytes]; - - NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + preparedMessage.data.length); - NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; - - int32_t nQuickAckId = *((int32_t *)(messageKeyFull.bytes)); - 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]; - [encryptedData appendData:decryptedData]; - MTAesEncryptInplace(encryptedData, encryptionKey.key, encryptionKey.iv); - - int64_t authKeyId = _authInfo.authKeyId; - [encryptedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&authKeyId length:8]; - [encryptedData replaceBytesInRange:NSMakeRange(8, 0) withBytes:messageKey.bytes length:messageKey.length]; - - return encryptedData; - } - else - return nil; -} - -- (void)transportTransactionsMayHaveFailed:(MTTransport *)__unused transport transactionIds:(NSArray *)transactionIds -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if ([self isStopped]) - return; - - bool requestTransaction = false; - - if (_timeFixContext != nil && _timeFixContext.transactionId != nil && [transactionIds containsObject:_timeFixContext.transactionId]) - { - _timeFixContext = nil; - requestTransaction = true; - } - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProto:transactionsMayHaveFailed:)]) - [messageService mtProto:self transactionsMayHaveFailed:transactionIds]; - } - - if (requestTransaction) - [self requestTransportTransaction]; - }]; -} - -- (void)transportReceivedQuickAck:(MTTransport *)transport quickAckId:(int32_t)quickAckId -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (_transport != transport || [self isStopped]) - return; - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProto:receivedQuickAck:)]) - [messageService mtProto:self receivedQuickAck:quickAckId]; - } - }]; -} - -- (void)transportDecodeProgressToken:(MTTransport *)transport data:(NSData *)data token:(int64_t)token completion:(void (^)(int64_t token, id progressToken))completion -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (transport != _transport || completion == nil) - return; - - MTInputStream *is = [[MTInputStream alloc] initWithData:data]; - - int64_t keyId = [is readInt64]; - - if (keyId != 0 && _authInfo != nil) - { - NSData *messageKey = [is readData:16]; - MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:true]; - - NSMutableData *messageData = [is readMutableData:(data.length - 24)]; - while (messageData.length % 16 != 0) - [messageData setLength:messageData.length - 1]; - if (messageData.length != 0) - { - MTAesDecryptInplace(messageData, encryptionKey.key, encryptionKey.iv); - - MTInputStream *messageIs = [[MTInputStream alloc] initWithData:messageData]; - [messageIs readInt64]; - [messageIs readInt64]; - - [messageIs readInt64]; - [messageIs readInt32]; - [messageIs readInt32]; - - bool stop = false; - int64_t reqMsgId = 0; - - if (true) - { - while (!stop && reqMsgId == 0) - { - int32_t signature = [messageIs readInt32:&stop]; - [self findReqMsgId:messageIs signature:signature reqMsgId:&reqMsgId failed:&stop]; - } - } - else - { - int32_t signature = [messageIs readInt32]; - if (signature == (int)0xf35c6d01) - reqMsgId = [messageIs readInt64]; - else if (signature == (int)0x73f1f8dc) - { - int count = [messageIs readInt32]; - if (count != 0) - { - [messageIs readInt64]; - [messageIs readInt32]; - [messageIs readInt32]; - - signature = [messageIs readInt32]; - if (signature == (int)0xf35c6d01) - reqMsgId = [messageIs readInt64]; - } - } - } - - if (reqMsgId != 0) - completion(token, @(reqMsgId)); - } - } - }]; -} - -- (void)findReqMsgId:(MTInputStream *)is signature:(int32_t)signature reqMsgId:(int64_t *)reqMsgId failed:(bool *)failed -{ - if (signature == (int)0x73f1f8dc) //msg_container - { - int count = [is readInt32:failed]; - if (*failed) - return; - - for (int i = 0; i < count; i++) - { - [is readInt64:failed]; - [is readInt32:failed]; - [is readInt32:failed]; - if (*failed) - return; - - int innerSignature = [is readInt32:failed]; - if (*failed) - return; - - [self findReqMsgId:is signature:innerSignature reqMsgId:reqMsgId failed:failed]; - if (*failed || *reqMsgId != 0) - return; - } - } - else if (signature == (int)0xf35c6d01) //rpc_result - { - int64_t value = [is readInt64:failed]; - if (*failed) - return; - - *reqMsgId = value; - } - else if (signature == (int)0x62d6b459) // msgs_ack - { - [is readInt32:failed]; - if (*failed) - return; - - int count = [is readInt32:failed]; - if (*failed) - return; - - for (int i = 0; i < count; i++) - { - [is readInt32:failed]; - if (*failed) - return; - } - } - else if (signature == (int)0x347773c5) // pong - { - [is readInt64:failed]; - [is readInt64:failed]; - if (*failed) - return; - } -} - -- (void)transportUpdatedDataReceiveProgress:(MTTransport *)transport progressToken:(id)progressToken packetLength:(NSInteger)packetLength progress:(float)progress -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (transport != _transport) - return; - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProto:updateReceiveProgressForToken:progress:packetLength:)]) - [messageService mtProto:self updateReceiveProgressForToken:progressToken progress:progress packetLength:packetLength]; - } - }]; -} - -- (void)transportTransactionsSucceeded:(NSArray *)transactionIds -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - [_sessionInfo removeScheduledMessageConfirmationsWithTransactionIds:transactionIds]; - }]; -} - -- (void)transportHasIncomingData:(MTTransport *)transport data:(NSData *)data transactionId:(id)transactionId requestTransactionAfterProcessing:(bool)requestTransactionAfterProcessing decodeResult:(void (^)(id transactionId, bool success))decodeResult -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (_transport != transport || [self isStopped]) - return; - - _transport.simultaneousTransactionsEnabled = true; - - if (data.length == 4) - { - int32_t protocolErrorCode = 0; - [data getBytes:&protocolErrorCode range:NSMakeRange(0, 4)]; - - MTLog(@"[MTProto#%p protocol error %" PRId32 "", self, protocolErrorCode); - - if (decodeResult != nil) - decodeResult(transactionId, false); - - id currentTransport = _transport; - - [self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]]; - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProto:protocolErrorReceived:)]) - [messageService mtProto:self protocolErrorReceived:protocolErrorCode]; - } - - if (currentTransport == _transport) - [self requestSecureTransportReset]; - - return; - } - - NSData *decryptedData = nil; - - if (_useUnauthorizedMode) - decryptedData = data; - else - decryptedData = [self _decryptIncomingTransportData:data]; - - if (decryptedData != nil) - { - if (decodeResult != nil) - decodeResult(transactionId, true); - - int64_t dataMessageId = 0; - bool parseError = false; - NSArray *parsedMessages = [self _parseIncomingMessages:decryptedData dataMessageId:&dataMessageId parseError:&parseError]; - if (parseError) - { - [self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]]; - - [self resetTransport]; - } - else - { - [self transportTransactionsSucceeded:@[transactionId]]; - - for (MTIncomingMessage *incomingMessage in parsedMessages) - { - [self _processIncomingMessage:incomingMessage withTransactionId:transactionId]; - } - - if (requestTransactionAfterProcessing) - [self requestTransportTransaction]; - } - } - else - { - if (decodeResult != nil) - decodeResult(transactionId, false); - - [self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]]; - - [self resetTransport]; - } - }]; -} - -- (NSData *)_decryptIncomingTransportData:(NSData *)data -{ - if (_authInfo == nil) - return nil; - - if (data.length < 24 + 36) - return nil; - - int64_t authKeyId = 0; - [data getBytes:&authKeyId range:NSMakeRange(0, 8)]; - if (authKeyId != _authInfo.authKeyId) - return nil; - - NSData *embeddedMessageKey = [data subdataWithRange:NSMakeRange(8, 16)]; - MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:embeddedMessageKey toClient:true]; - if (encryptionKey == nil) - return nil; - - NSData *decryptedData = MTAesDecrypt([data subdataWithRange:NSMakeRange(24, data.length - 24)], encryptionKey.key, encryptionKey.iv); - - 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) - return nil; - - NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + messageDataLength); - NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; - if (![messageKey isEqualToData:embeddedMessageKey]) - return nil; - - return decryptedData; -} - -- (NSArray *)_parseIncomingMessages:(NSData *)data dataMessageId:(out int64_t *)dataMessageId parseError:(out bool *)parseError -{ - MTInputStream *is = [[MTInputStream alloc] initWithData:data]; - - bool readError = false; - - int64_t embeddedMessageId = 0; - int32_t embeddedSeqNo = 0; - int64_t embeddedSalt = 0; - int32_t topMessageSize = 0; - - if (_useUnauthorizedMode) - { - int64_t authKeyId = [is readInt64]; - if (authKeyId != 0) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - embeddedMessageId = [is readInt64:&readError]; - if (readError) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - topMessageSize = [is readInt32:&readError]; - if (readError || topMessageSize < 4) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - if (dataMessageId != 0) - *dataMessageId = embeddedMessageId; - } - else - { - embeddedSalt = [is readInt64:&readError]; - if (readError) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - int64_t embeddedSessionId = [is readInt64:&readError]; - if (readError) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - if (embeddedSessionId != _sessionInfo.sessionId) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - embeddedMessageId = [is readInt64:&readError]; - if (readError) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - embeddedSeqNo = [is readInt32:&readError]; - if (readError) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - - [is readInt32:&readError]; - if (readError) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - } - - id topObject = [_context.serialization parseMessage:[is wrappedInputStream] responseParsingBlock:^int32_t (int64_t requestMessageId, bool *requestFound) - { - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(possibleSignatureForResult:found:)]) - { - bool found = false; - int32_t possibleSignature = [messageService possibleSignatureForResult:requestMessageId found:&found]; - if (found) - { - if (requestFound != NULL) - *requestFound = true; - return possibleSignature; - } - } - } - - return nil; - }]; - - if (topObject == nil) - { - if (parseError != NULL) - *parseError = true; - return nil; - } - -#warning check message id - - NSMutableArray *messages = [[NSMutableArray alloc] init]; - NSTimeInterval timestamp = embeddedMessageId / 4294967296.0; - - if ([_context.serialization isMessageContainer:topObject]) - { - for (id subObject in [_context.serialization containerMessages:topObject]) - { - if ([_context.serialization isMessageProtoMessage:subObject]) - { - int64_t subMessageId = 0; - int32_t subMessageSeqNo = 0; - int32_t subMessageLength = 0; - id subMessageBody = [_context.serialization protoMessageBody:subObject messageId:&subMessageId seqNo:&subMessageSeqNo length:&subMessageLength]; - [messages addObject:[[MTIncomingMessage alloc] initWithMessageId:subMessageId seqNo:subMessageSeqNo salt:embeddedSalt timestamp:timestamp size:subMessageLength body:subMessageBody]]; - } - if ([_context.serialization isMessageProtoCopyMessage:subObject]) - { - int64_t subMessageId = 0; - int32_t subMessageSeqNo = 0; - int32_t subMessageLength = 0; - id subMessageBody = [_context.serialization protoCopyMessageBody:subObject messageId:&subMessageId seqNo:&subMessageSeqNo length:&subMessageLength]; - [messages addObject:[[MTIncomingMessage alloc] initWithMessageId:subMessageId seqNo:subMessageSeqNo salt:embeddedSalt timestamp:timestamp size:subMessageLength body:subMessageBody]]; - } - } - } - else if ([_context.serialization isMessageProtoCopyMessage:topObject]) - { - int64_t subMessageId = 0; - int32_t subMessageSeqNo = 0; - int32_t subMessageLength = 0; - id subMessageBody = [_context.serialization protoCopyMessageBody:topObject messageId:&subMessageId seqNo:&subMessageSeqNo length:&subMessageLength]; - [messages addObject:[[MTIncomingMessage alloc] initWithMessageId:subMessageId seqNo:subMessageSeqNo salt:embeddedSalt timestamp:timestamp size:subMessageLength body:subMessageBody]]; - } - else - [messages addObject:[[MTIncomingMessage alloc] initWithMessageId:embeddedMessageId seqNo:embeddedSeqNo salt:embeddedSalt timestamp:timestamp size:topMessageSize body:topObject]]; - - return messages; -} - -- (void)_processIncomingMessage:(MTIncomingMessage *)incomingMessage withTransactionId:(id)transactionId -{ - if ([_sessionInfo messageProcessed:incomingMessage.messageId]) - { - MTLog(@"[MTProto#%p received duplicate message %" PRId64 "]", self, incomingMessage.messageId); - [_sessionInfo scheduleMessageConfirmation:incomingMessage.messageId size:incomingMessage.size]; - - if ([_sessionInfo scheduledMessageConfirmationsExceedSize:MTMaxUnacknowledgedMessageSize orCount:MTMaxUnacknowledgedMessageCount]) - [self requestTransportTransaction]; - - return; - } - - MTLog(@"[MTProto#%p received %@]", self, [_context.serialization messageDescription:incomingMessage.body messageId:incomingMessage.messageId messageSeqNo:incomingMessage.seqNo]); - - [_sessionInfo setMessageProcessed:incomingMessage.messageId]; - if (!_useUnauthorizedMode && incomingMessage.seqNo % 2 != 0) - { - [_sessionInfo scheduleMessageConfirmation:incomingMessage.messageId size:incomingMessage.size]; - - if ([_sessionInfo scheduledMessageConfirmationsExceedSize:MTMaxUnacknowledgedMessageSize orCount:MTMaxUnacknowledgedMessageCount]) - [self requestTransportTransaction]; - } - - if (!_useUnauthorizedMode && [_context.serialization isMessageBadMsgNotification:incomingMessage.body]) - { - int64_t badMessageId = [_context.serialization badMessageBadMessageId:incomingMessage.body]; - - NSArray *containerMessageIds = [_sessionInfo messageIdsInContainer:badMessageId]; - - if ([_context.serialization isMessageBadServerSaltNotification:incomingMessage.body]) - { - if (_timeFixContext != nil && badMessageId == _timeFixContext.messageId) - { - MTAbsoluteTime timeFixAbsoluteStartTime = _timeFixContext.timeFixAbsoluteStartTime; - _timeFixContext = nil; - - __block bool test = false; -#if TARGET_IPHONE_SIMULATOR - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - test = true; - }); -#endif - int64_t validSalt = [_context.serialization badMessageNewServerSalt:incomingMessage.body]; - NSTimeInterval timeDifference = incomingMessage.messageId / 4294967296.0 - [[NSDate date] timeIntervalSince1970]; - [self timeSyncInfoChanged:timeDifference saltList:@[[[MTDatacenterSaltInfo alloc] initWithSalt:validSalt firstValidMessageId:incomingMessage.messageId lastValidMessageId:incomingMessage.messageId + (4294967296 * 30 * 60)]]]; - - MTAbsoluteTime absoluteDifference = ABS(MTAbsoluteSystemTime() - timeFixAbsoluteStartTime); - if (absoluteDifference > 5.0 || test) - { - MTLog(@"[MTProto#%p time fix needs more precision: %f s]", self, absoluteDifference); - [self initiateTimeSync]; - } - else - [self completeTimeSync]; - } - else - [self initiateTimeSync]; - } - else - { - switch ([_context.serialization badMessageErrorCode:incomingMessage.body]) - { - case 16: - case 17: - { - if (_timeFixContext != nil && badMessageId == _timeFixContext.messageId) - { - _timeFixContext = nil; - - NSTimeInterval timeDifference = incomingMessage.messageId / 4294967296.0 - [[NSDate date] timeIntervalSince1970]; - [self completeTimeSync]; - [self timeSyncInfoChanged:timeDifference saltList:nil]; - } - else - [self initiateTimeSync]; - - break; - } - case 32: - case 33: - { - [self resetSessionInfo]; - [self initiateTimeSync]; - - break; - } - case 48: - { - [self initiateTimeSync]; - - break; - } - default: - break; - } - } - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProto:messageDeliveryFailed:)]) - { - [messageService mtProto:self messageDeliveryFailed:badMessageId]; - - if (containerMessageIds != nil) - { - for (NSNumber *nMessageId in containerMessageIds) - [messageService mtProto:self messageDeliveryFailed:(int64_t)[nMessageId longLongValue]]; - } - } - } - - if ([self canAskForTransactions] || [self canAskForServiceTransactions]) - [self requestTransportTransaction]; - } - else if ([_context.serialization isMessageMsgsAck:incomingMessage.body]) - { - NSArray *messageIds = [_context.serialization msgsAckMessageIds:incomingMessage.body]; - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProto:messageDeliveryConfirmed:)]) - [messageService mtProto:self messageDeliveryConfirmed:messageIds]; - } - } - else if ([_context.serialization isMessageDetailedInfo:incomingMessage.body]) - { - bool shouldRequest = false; - - if ([_context.serialization isMessageDetailedResponseInfo:incomingMessage.body]) - { - int64_t requestMessageId = [_context.serialization detailedInfoResponseRequestMessageId:incomingMessage.body]; - - for (id messageService in _messageServices) - { - if ([messageService respondsToSelector:@selector(mtProto:shouldRequestMessageInResponseToMessageId:currentTransactionId:)]) - { - if ([messageService mtProto:self shouldRequestMessageInResponseToMessageId:requestMessageId currentTransactionId:transactionId]) - { - shouldRequest = true; - break; - } - } - } - } - else - shouldRequest = true; - - if (shouldRequest) - [self requestMessageWithId:[_context.serialization detailedInfoResponseMessageId:incomingMessage.body]]; - else - { - [_sessionInfo scheduleMessageConfirmation:[_context.serialization detailedInfoResponseMessageId:incomingMessage.body] size:(NSInteger)[_context.serialization detailedInfoResponseMessageLength:incomingMessage.body]]; - [self requestTransportTransaction]; - } - } - else if ([_context.serialization isMessageNewSession:incomingMessage.body]) - { - int64_t firstValidMessageId = [_context.serialization messageNewSessionFirstValidMessageId:incomingMessage.body]; - - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProtoServerDidChangeSession:firstValidMessageId:otherValidMessageIds:)]) - [messageService mtProtoServerDidChangeSession:self firstValidMessageId:firstValidMessageId otherValidMessageIds:[_sessionInfo messageIdsInContainersAfterMessageId:firstValidMessageId]]; - } - } - else - { - for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--) - { - id messageService = _messageServices[(NSUInteger)i]; - - if ([messageService respondsToSelector:@selector(mtProto:receivedMessage:)]) - [messageService mtProto:self receivedMessage:incomingMessage]; - } - - if (_timeFixContext != nil && [_context.serialization isMessagePong:incomingMessage.body] && [_context.serialization pongMessageId:incomingMessage.body] == _timeFixContext.messageId) - { - _timeFixContext = nil; - [self completeTimeSync]; - - if ([self canAskForTransactions] || [self canAskForServiceTransactions]) - [self requestTransportTransaction]; - } - } -} - -- (void)contextDatacenterAddressSetUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId addressSet:(MTDatacenterAddressSet *)__unused addressSet -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (context == _context && datacenterId == _datacenterId && (_mtState & MTProtoStateAwaitingDatacenterAddress)) - { - [self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterAddress)]; - - [self resetTransport]; - [self requestTransportTransaction]; - } - }]; -} - -- (void)contextDatacenterAuthInfoUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authInfo:(MTDatacenterAuthInfo *)authInfo -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (!_useUnauthorizedMode && context == _context && datacenterId == _datacenterId && authInfo != nil) - { - _authInfo = authInfo; - - if (_mtState & MTProtoStateAwaitingDatacenterAuthorization) - { - [self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterAuthorization)]; - - [self resetTransport]; - [self requestTransportTransaction]; - } - } - }]; -} - -- (void)contextDatacenterAuthTokenUpdated:(MTContext *)context datacenterId:(NSInteger)datacenterId authToken:(id)authToken -{ - [[MTProto managerQueue] dispatchOnQueue:^ - { - if (!_useUnauthorizedMode && context == _context && datacenterId == _datacenterId && _requiredAuthToken != nil && [_requiredAuthToken isEqual:authToken]) - { - if (_mtState & MTProtoStateAwaitingDatacenterAuthToken) - { - [self setMtState:_mtState & (~MTProtoStateAwaitingDatacenterAuthToken)]; - - [self resetTransport]; - [self requestTransportTransaction]; - } - } - }]; -} - -- (void)timeSyncServiceCompleted:(MTTimeSyncMessageService *)timeSyncService timeDifference:(NSTimeInterval)timeDifference saltList:(NSArray *)saltList -{ - if ([_messageServices containsObject:timeSyncService]) - { - [self completeTimeSync]; - [self timeSyncInfoChanged:timeDifference saltList:saltList]; - } -} - -- (void)timeSyncInfoChanged:(NSTimeInterval)timeDifference saltList:(NSArray *)saltList -{ - [_context setGlobalTimeDifference:timeDifference]; - - if (saltList != nil) - { - MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId]; - if (authInfo != nil) - { - MTDatacenterAuthInfo *updatedAuthInfo = [[MTDatacenterAuthInfo alloc] initWithAuthKey:authInfo.authKey authKeyId:authInfo.authKeyId saltSet:saltList authKeyAttributes:authInfo.authKeyAttributes]; - [_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:updatedAuthInfo]; - } - } - - if ([self canAskForTransactions] || [self canAskForServiceTransactions]) - [self requestTransportTransaction]; -} - -@end diff --git a/MTProtoKit/MTProto.h b/MTProtoKit/MTProto.h index b0f04ad4a0..9365c6af65 100644 --- a/MTProtoKit/MTProto.h +++ b/MTProtoKit/MTProto.h @@ -6,6 +6,8 @@ * Copyright Peter Iakovlev, 2013. */ +#import + @protocol MTMessageService; @class MTQueue; @class MTContext; diff --git a/MTProtoKit/MTProto.mm b/MTProtoKit/MTProto.m similarity index 99% rename from MTProtoKit/MTProto.mm rename to MTProtoKit/MTProto.m index 1609f8f702..4782a959f6 100644 --- a/MTProtoKit/MTProto.mm +++ b/MTProtoKit/MTProto.m @@ -10,6 +10,7 @@ #import +#import #import #import #import diff --git a/MTProtoKit/MTRequestErrorContext.h b/MTProtoKit/MTRequestErrorContext.h index 9057679f07..c223c7bbe7 100644 --- a/MTProtoKit/MTRequestErrorContext.h +++ b/MTProtoKit/MTRequestErrorContext.h @@ -6,6 +6,7 @@ * Copyright Peter Iakovlev, 2013. */ +#import #import @interface MTRequestErrorContext : NSObject diff --git a/MTProtoKit/MTRequestMessageService.m b/MTProtoKit/MTRequestMessageService.m index 1294dbe3d6..52374dccc8 100644 --- a/MTProtoKit/MTRequestMessageService.m +++ b/MTProtoKit/MTRequestMessageService.m @@ -8,6 +8,7 @@ #import +#import #import #import #import diff --git a/MTProtoKit/MTResendMessageService.m b/MTProtoKit/MTResendMessageService.m index b3528d64ce..776b313787 100644 --- a/MTProtoKit/MTResendMessageService.m +++ b/MTProtoKit/MTResendMessageService.m @@ -6,6 +6,8 @@ * Copyright Peter Iakovlev, 2013. */ +#import +#import #import #import diff --git a/MTProtoKit/MTSessionInfo.mm b/MTProtoKit/MTSessionInfo.m similarity index 87% rename from MTProtoKit/MTSessionInfo.mm rename to MTProtoKit/MTSessionInfo.m index 3749a6d752..070b167b2d 100644 --- a/MTProtoKit/MTSessionInfo.mm +++ b/MTProtoKit/MTSessionInfo.m @@ -8,12 +8,9 @@ #import +#import #import -#import -#import -#import - @interface MTScheduledMessageConfirmation : NSObject @property (nonatomic) int64_t messageId; @@ -60,9 +57,9 @@ int64_t _lastServerMessageId; - std::set _processedMessageIds; + NSMutableSet *_processedMessageIdsSet; NSMutableArray *_scheduledMessageConfirmations; - std::map _containerMessagesMapping; + NSMutableDictionary *_containerMessagesMappingDict; } @end @@ -85,6 +82,9 @@ _context = context; _scheduledMessageConfirmations = [[NSMutableArray alloc] init]; + + _processedMessageIdsSet = [[NSMutableSet alloc] init]; + _containerMessagesMappingDict = [[NSMutableDictionary alloc] init]; } return self; } @@ -138,12 +138,12 @@ - (bool)messageProcessed:(int64_t)messageId { - return _processedMessageIds.find(messageId) != _processedMessageIds.end(); + return [_processedMessageIdsSet containsObject:@(messageId)]; } - (void)setMessageProcessed:(int64_t)messageId { - _processedMessageIds.insert(messageId); + [_processedMessageIdsSet addObject:@(messageId)]; } - (void)scheduleMessageConfirmation:(int64_t)messageId size:(NSInteger)size @@ -246,32 +246,29 @@ - (void)addContainerMessageIdMapping:(int64_t)containerMessageId childMessageIds:(NSArray *)childMessageIds { - _containerMessagesMapping[containerMessageId] = childMessageIds; + _containerMessagesMappingDict[@(containerMessageId)] = childMessageIds; } - (NSArray *)messageIdsInContainer:(int64_t)containerMessageId { - auto it = _containerMessagesMapping.find(containerMessageId); - if (it != _containerMessagesMapping.end()) - return it->second; - - return nil; + return _containerMessagesMappingDict[@(containerMessageId)]; } - (NSArray *)messageIdsInContainersAfterMessageId:(int64_t)firstMessageId { NSMutableArray *array = [[NSMutableArray alloc] init]; - for (auto it = _containerMessagesMapping.begin(); it != _containerMessagesMapping.end(); it++) + [_containerMessagesMappingDict enumerateKeysAndObjectsUsingBlock:^(NSNumber *nContainerMessageId, NSArray *messageIds, __unused BOOL *stop) { - for (NSNumber *nMessageId in it->second) + int64_t containerMessageId = (int64_t)[nContainerMessageId longLongValue]; + for (NSNumber *nMessageId in messageIds) { - if (it->first >= firstMessageId || ((int64_t)[nMessageId longLongValue]) >= firstMessageId) + if (containerMessageId >= firstMessageId || ((int64_t)[nMessageId longLongValue]) >= firstMessageId) { [array addObject:nMessageId]; } } - } + }]; return array; } diff --git a/MTProtoKit/MTTcpConnection.m b/MTProtoKit/MTTcpConnection.m index a76007765e..7f74a2bd8a 100644 --- a/MTProtoKit/MTTcpConnection.m +++ b/MTProtoKit/MTTcpConnection.m @@ -8,6 +8,7 @@ #import +#import #import #import diff --git a/MTProtoKit/MTTcpConnectionBehaviour.h b/MTProtoKit/MTTcpConnectionBehaviour.h index 5e2f8218a8..a79c4df6d5 100644 --- a/MTProtoKit/MTTcpConnectionBehaviour.h +++ b/MTProtoKit/MTTcpConnectionBehaviour.h @@ -9,6 +9,8 @@ @class MTQueue; @class MTTcpConnectionBehaviour; +#import + @protocol MTTcpConnectionBehaviourDelegate @optional diff --git a/MTProtoKit/MTTcpConnectionBehaviour.m b/MTProtoKit/MTTcpConnectionBehaviour.m index 3a2d712d11..5364bf9cf2 100644 --- a/MTProtoKit/MTTcpConnectionBehaviour.m +++ b/MTProtoKit/MTTcpConnectionBehaviour.m @@ -6,6 +6,8 @@ * Copyright Peter Iakovlev, 2013. */ +#import + #import #import diff --git a/MTProtoKit/MTTcpTransport.m b/MTProtoKit/MTTcpTransport.m index 0669697dda..41888681fc 100644 --- a/MTProtoKit/MTTcpTransport.m +++ b/MTProtoKit/MTTcpTransport.m @@ -8,6 +8,7 @@ #import +#import #import #import #import diff --git a/MTProtoKit/MTTimeFixContext.h b/MTProtoKit/MTTimeFixContext.h index a3da8af9b7..0b0615e571 100644 --- a/MTProtoKit/MTTimeFixContext.h +++ b/MTProtoKit/MTTimeFixContext.h @@ -6,6 +6,7 @@ * Copyright Peter Iakovlev, 2013. */ +#import #import @interface MTTimeFixContext : NSObject diff --git a/MtProtoKit.xcodeproj/project.pbxproj b/MtProtoKit.xcodeproj/project.pbxproj index b06fb4f12c..ce2d547bd5 100644 --- a/MtProtoKit.xcodeproj/project.pbxproj +++ b/MtProtoKit.xcodeproj/project.pbxproj @@ -148,6 +148,8 @@ D04AC07E1A3E881700869014 /* MTExportedAuthorizationData.m in Sources */ = {isa = PBXBuildFile; fileRef = D04AC07C1A3E881700869014 /* MTExportedAuthorizationData.m */; }; D04AC0811A3F45AD00869014 /* MTDatacenterAddressListData.h in Headers */ = {isa = PBXBuildFile; fileRef = D04AC07F1A3F45AD00869014 /* MTDatacenterAddressListData.h */; }; D04AC0821A3F45AD00869014 /* MTDatacenterAddressListData.m in Sources */ = {isa = PBXBuildFile; fileRef = D04AC0801A3F45AD00869014 /* MTDatacenterAddressListData.m */; }; + D04AC08E1A3F5FA700869014 /* MTProto.m in Sources */ = {isa = PBXBuildFile; fileRef = D04AC08D1A3F5FA700869014 /* MTProto.m */; }; + D04AC0901A3F5FE600869014 /* MTSessionInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = D04AC08F1A3F5FE600869014 /* MTSessionInfo.m */; }; D0503ADA18B027F80074C3FE /* MTOutputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = D0503AD818B027F80074C3FE /* MTOutputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; D0503ADB18B027F80074C3FE /* MTOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = D0503AD918B027F80074C3FE /* MTOutputStream.m */; }; D0503ADE18B029480074C3FE /* MTInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = D0503ADC18B029480074C3FE /* MTInputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -261,9 +263,7 @@ D063A32C18B1618D00C65116 /* MTPreparedMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32218B1618D00C65116 /* MTPreparedMessage.h */; settings = {ATTRIBUTES = (Public, ); }; }; D063A32D18B1618D00C65116 /* MTPreparedMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = D063A32318B1618D00C65116 /* MTPreparedMessage.m */; }; D063A32E18B1618D00C65116 /* MTProto.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32418B1618D00C65116 /* MTProto.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D063A32F18B1618D00C65116 /* MTProto.mm in Sources */ = {isa = PBXBuildFile; fileRef = D063A32518B1618D00C65116 /* MTProto.mm */; }; D063A33018B1618D00C65116 /* MTSessionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32618B1618D00C65116 /* MTSessionInfo.h */; }; - D063A33118B1618D00C65116 /* MTSessionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = D063A32718B1618D00C65116 /* MTSessionInfo.mm */; }; D063A33218B1618D00C65116 /* MTTimeFixContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32818B1618D00C65116 /* MTTimeFixContext.h */; }; D063A33318B1618D00C65116 /* MTTimeFixContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D063A32918B1618D00C65116 /* MTTimeFixContext.m */; }; D063A33A18B161B600C65116 /* MTTransportScheme.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A33418B161B600C65116 /* MTTransportScheme.h */; }; @@ -273,9 +273,7 @@ D063A33E18B161B600C65116 /* MTMessageEncryptionKey.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A33818B161B600C65116 /* MTMessageEncryptionKey.h */; }; D063A33F18B161B600C65116 /* MTMessageEncryptionKey.m in Sources */ = {isa = PBXBuildFile; fileRef = D063A33918B161B600C65116 /* MTMessageEncryptionKey.m */; }; D063A34018B161C400C65116 /* MTProto.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32418B1618D00C65116 /* MTProto.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D063A34118B161C400C65116 /* MTProto.mm in Sources */ = {isa = PBXBuildFile; fileRef = D063A32518B1618D00C65116 /* MTProto.mm */; }; D063A34218B161C400C65116 /* MTSessionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32618B1618D00C65116 /* MTSessionInfo.h */; }; - D063A34318B161C400C65116 /* MTSessionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = D063A32718B1618D00C65116 /* MTSessionInfo.mm */; }; D063A34418B161C400C65116 /* MTTimeFixContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32818B1618D00C65116 /* MTTimeFixContext.h */; }; D063A34518B161C400C65116 /* MTTimeFixContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D063A32918B1618D00C65116 /* MTTimeFixContext.m */; }; D063A34618B161C400C65116 /* MTPreparedMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = D063A32218B1618D00C65116 /* MTPreparedMessage.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -520,6 +518,8 @@ D04AC07C1A3E881700869014 /* MTExportedAuthorizationData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTExportedAuthorizationData.m; path = MTProtoKit/MTExportedAuthorizationData.m; sourceTree = ""; }; D04AC07F1A3F45AD00869014 /* MTDatacenterAddressListData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTDatacenterAddressListData.h; path = MTProtoKit/MTDatacenterAddressListData.h; sourceTree = ""; }; D04AC0801A3F45AD00869014 /* MTDatacenterAddressListData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTDatacenterAddressListData.m; path = MTProtoKit/MTDatacenterAddressListData.m; sourceTree = ""; }; + D04AC08D1A3F5FA700869014 /* MTProto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTProto.m; path = MTProtoKit/MTProto.m; sourceTree = ""; }; + D04AC08F1A3F5FE600869014 /* MTSessionInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTSessionInfo.m; path = MTProtoKit/MTSessionInfo.m; sourceTree = ""; }; D0503AD818B027F80074C3FE /* MTOutputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTOutputStream.h; path = MTProtoKit/MTOutputStream.h; sourceTree = ""; }; D0503AD918B027F80074C3FE /* MTOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTOutputStream.m; path = MTProtoKit/MTOutputStream.m; sourceTree = ""; }; D0503ADC18B029480074C3FE /* MTInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTInputStream.h; path = MTProtoKit/MTInputStream.h; sourceTree = ""; }; @@ -592,9 +592,7 @@ D063A32218B1618D00C65116 /* MTPreparedMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTPreparedMessage.h; path = MTProtoKit/MTPreparedMessage.h; sourceTree = ""; }; D063A32318B1618D00C65116 /* MTPreparedMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTPreparedMessage.m; path = MTProtoKit/MTPreparedMessage.m; sourceTree = ""; }; D063A32418B1618D00C65116 /* MTProto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTProto.h; path = MTProtoKit/MTProto.h; sourceTree = ""; }; - D063A32518B1618D00C65116 /* MTProto.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MTProto.mm; path = MTProtoKit/MTProto.mm; sourceTree = ""; }; D063A32618B1618D00C65116 /* MTSessionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTSessionInfo.h; path = MTProtoKit/MTSessionInfo.h; sourceTree = ""; }; - D063A32718B1618D00C65116 /* MTSessionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MTSessionInfo.mm; path = MTProtoKit/MTSessionInfo.mm; sourceTree = ""; }; D063A32818B1618D00C65116 /* MTTimeFixContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTTimeFixContext.h; path = MTProtoKit/MTTimeFixContext.h; sourceTree = ""; }; D063A32918B1618D00C65116 /* MTTimeFixContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MTTimeFixContext.m; path = MTProtoKit/MTTimeFixContext.m; sourceTree = ""; }; D063A33418B161B600C65116 /* MTTransportScheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MTTransportScheme.h; path = MTProtoKit/MTTransportScheme.h; sourceTree = ""; }; @@ -994,9 +992,9 @@ children = ( D04AC00A1A3D28D500869014 /* Internal Messages */, D063A32418B1618D00C65116 /* MTProto.h */, - D063A32518B1618D00C65116 /* MTProto.mm */, + D04AC08D1A3F5FA700869014 /* MTProto.m */, D063A32618B1618D00C65116 /* MTSessionInfo.h */, - D063A32718B1618D00C65116 /* MTSessionInfo.mm */, + D04AC08F1A3F5FE600869014 /* MTSessionInfo.m */, D063A32818B1618D00C65116 /* MTTimeFixContext.h */, D063A32918B1618D00C65116 /* MTTimeFixContext.m */, D063A32218B1618D00C65116 /* MTPreparedMessage.h */, @@ -1647,11 +1645,11 @@ D063A37B18B164D600C65116 /* MTRequestMessageService.m in Sources */, D05A84A318AFCF8E007F1076 /* MTQueue.m in Sources */, D04AC0721A3E6EAB00869014 /* MTServerDhInnerDataMessage.m in Sources */, + D04AC08E1A3F5FA700869014 /* MTProto.m in Sources */, D04AC0821A3F45AD00869014 /* MTDatacenterAddressListData.m in Sources */, D04AC0521A3E2C3700869014 /* MTBadMsgNotificationMessage.m in Sources */, D063A3A518B1650400C65116 /* MTTcpTransport.m in Sources */, D063A33F18B161B600C65116 /* MTMessageEncryptionKey.m in Sources */, - D063A33118B1618D00C65116 /* MTSessionInfo.mm in Sources */, D063A33B18B161B600C65116 /* MTTransportScheme.m in Sources */, D0503ADF18B029480074C3FE /* MTInputStream.m in Sources */, D04AC0261A3D2F9600869014 /* MTBufferReader.m in Sources */, @@ -1693,6 +1691,7 @@ D063A3B318B1650F00C65116 /* MTHttpWorker.m in Sources */, D063A3AF18B1650F00C65116 /* MTHttpTransport.m in Sources */, D04AC0361A3D367C00869014 /* MTMsgDetailedInfoMessage.m in Sources */, + D04AC0901A3F5FE600869014 /* MTSessionInfo.m in Sources */, D04AC06A1A3E3D7600869014 /* MTMsgContainerMessage.m in Sources */, D063A33318B1618D00C65116 /* MTTimeFixContext.m in Sources */, D05A851118AFF259007F1076 /* AFURLConnectionOperation.m in Sources */, @@ -1701,7 +1700,6 @@ D063A39318B164F800C65116 /* MTTransportTransaction.m in Sources */, D05A84E518AFE81D007F1076 /* MTEncryption.m in Sources */, D05A84E318AFE81D007F1076 /* MTLogging.m in Sources */, - D063A32F18B1618D00C65116 /* MTProto.mm in Sources */, D05A851518AFF259007F1076 /* GCDAsyncSocket.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1726,7 +1724,6 @@ D063A34D18B161C400C65116 /* MTIncomingMessage.m in Sources */, D05A845118AFC7DC007F1076 /* MTKeychain.m in Sources */, 93DBD23818B2DA5800631ADC /* MTTime.m in Sources */, - D063A34118B161C400C65116 /* MTProto.mm in Sources */, D063A35818B1631900C65116 /* MTMessageTransaction.m in Sources */, D063A3B818B1650F00C65116 /* MTHttpWorkerBehaviour.m in Sources */, D05A846118AFC7DC007F1076 /* MTDatacenterAuthInfo.m in Sources */, @@ -1738,7 +1735,6 @@ D063A2E118B143EA00C65116 /* MTTimer.m in Sources */, D05A845F18AFC7DC007F1076 /* MTDatacenterAddressSet.m in Sources */, D063A34918B161C400C65116 /* MTOutgoingMessage.m in Sources */, - D063A34318B161C400C65116 /* MTSessionInfo.mm in Sources */, D063A38218B164E600C65116 /* MTResendMessageService.m in Sources */, D05A845718AFC7DC007F1076 /* MTDatacenterTransferAuthAction.m in Sources */, D063A34518B161C400C65116 /* MTTimeFixContext.m in Sources */, @@ -1901,7 +1897,7 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "MtProtoKitiOS/MtProtoKit-Prefix.pch"; + GCC_PREFIX_HEADER = ""; HEADER_SEARCH_PATHS = ( "$(inherited)", "/Applications/Xcode51-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", @@ -1929,7 +1925,7 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "MtProtoKitiOS/MtProtoKit-Prefix.pch"; + GCC_PREFIX_HEADER = ""; HEADER_SEARCH_PATHS = ( "$(inherited)", "/Applications/Xcode51-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", @@ -1959,7 +1955,7 @@ "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "MtProtoKit/MtProtoKit-Prefix.pch"; + GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -1981,7 +1977,7 @@ "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "MtProtoKit/MtProtoKit-Prefix.pch"; + GCC_PREFIX_HEADER = ""; INFOPLIST_FILE = "MtProtoKitTests/MtProtoKitTests-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; diff --git a/thirdparty/AsyncSocket/GCDAsyncSocket.m b/thirdparty/AsyncSocket/GCDAsyncSocket.m index 3b7e7f3246..1e39ebce3e 100755 --- a/thirdparty/AsyncSocket/GCDAsyncSocket.m +++ b/thirdparty/AsyncSocket/GCDAsyncSocket.m @@ -10,6 +10,8 @@ #import "GCDAsyncSocket.h" +#import + #if TARGET_OS_IPHONE #import #endif