// // TGDownloadWorker.m // Telegraph // // Created by Peter on 14/02/14. // // #import "TGNetworkWorker.h" #import "ASQueue.h" #import "ActionStage.h" #import "TGTelegraph.h" #import "TGTimer.h" #import #import #import #import static int workerCount = 0; @interface TGNetworkWorker () { MTContext *_context; MTProto *_mtProto; MTRequestMessageService *_requestService; TGTimer *_timeoutTimer; bool _isReadyToBeRemoved; bool _isBusy; } @end @implementation TGNetworkWorker - (instancetype)initWithContext:(MTContext *)context datacenterId:(NSInteger)datacenterId masterDatacenterId:(NSInteger)masterDatacenterId { self = [super init]; if (self != nil) { workerCount++; TGLog(@"[TGNetworkWorker#%x/%d start (%d)]", (int)self, (int)datacenterId, workerCount); _context = context; _datacenterId = datacenterId; _mtProto = [[MTProto alloc] initWithContext:_context datacenterId:_datacenterId]; _mtProto.requiredAuthToken = @(TGTelegraphInstance.clientUserId); _mtProto.authTokenMasterDatacenterId = masterDatacenterId; _requestService = [[MTRequestMessageService alloc] initWithContext:_context]; _requestService.delegate = self; [_mtProto addMessageService:_requestService]; [self startTimer]; } return self; } - (void)dealloc { workerCount--; TGLog(@"[TGNetworkWorker#%x stop (%d)]", (int)self, workerCount); if (_timeoutTimer != nil) { [_timeoutTimer invalidate]; _timeoutTimer = nil; } [_mtProto stop]; _requestService.delegate = nil; } - (void)startTimer { [ActionStageInstance() dispatchOnStageQueue:^ { [self clearTimer]; __weak TGNetworkWorker *weakSelf = self; _timeoutTimer = [[TGTimer alloc] initWithTimeout:30 repeat:false completion:^ { __strong TGNetworkWorker *strongSelf = weakSelf; [strongSelf timerTimeout]; } queue:[ActionStageInstance() globalStageDispatchQueue]]; [_timeoutTimer start]; }]; } - (void)clearTimer { [ActionStageInstance() dispatchOnStageQueue:^ { if (_timeoutTimer != nil) { [_timeoutTimer invalidate]; _timeoutTimer = nil; } }]; } - (void)timerTimeout { [ActionStageInstance() dispatchOnStageQueue:^ { _isReadyToBeRemoved = true; id delegate = _delegate; if ([delegate respondsToSelector:@selector(networkWorkerReadyToBeRemoved:)]) [delegate networkWorkerReadyToBeRemoved:self]; }]; } - (bool)isBusy { return _isBusy; } - (void)setIsBusy:(bool)isBusy { [ActionStageInstance() dispatchOnStageQueue:^ { if (_isBusy != isBusy) { _isBusy = isBusy; if (isBusy) [self clearTimer]; else [self startTimer]; if (!_isBusy) { id delegate = _delegate; if ([delegate respondsToSelector:@selector(networkWorkerDidBecomeAvailable:)]) [delegate networkWorkerDidBecomeAvailable:self]; } } }]; } - (void)updateReadyToBeRemoved { [ActionStageInstance() dispatchOnStageQueue:^ { if (_isReadyToBeRemoved) { id delegate = _delegate; if ([delegate respondsToSelector:@selector(networkWorkerReadyToBeRemoved:)]) [delegate networkWorkerReadyToBeRemoved:self]; } }]; } - (void)addRequest:(MTRequest *)request { [ActionStageInstance() dispatchOnStageQueue:^ { [_requestService addRequest:request]; }]; } - (void)cancelRequestById:(id)requestId { [_requestService removeRequestByInternalId:requestId askForReconnectionOnDrop:true]; } - (void)cancelRequestByIdSoft:(id)requestId { [_requestService removeRequestByInternalId:requestId askForReconnectionOnDrop:false]; } - (void)ensureConnection { [_mtProto requestTransportTransaction]; } - (void)requestMessageServiceDidCompleteAllRequests:(MTRequestMessageService *)__unused requestMessageService { } - (void)requestMessageServiceAuthorizationRequired:(MTRequestMessageService *)__unused requestMessageService { [_context updateAuthTokenForDatacenterWithId:_datacenterId authToken:nil]; [_context authTokenForDatacenterWithIdRequired:_datacenterId authToken:_mtProto.requiredAuthToken masterDatacenterId:_mtProto.authTokenMasterDatacenterId]; } @end @implementation TGNetworkWorkerGuard - (instancetype)initWithWorker:(TGNetworkWorker *)worker { self = [super init]; if (self != nil) { _worker = worker; } return self; } - (void)dealloc { [self releaseWorker]; } - (TGNetworkWorker *)strongWorker { return _worker; } - (void)releaseWorker { TGNetworkWorker *worker = _worker; _worker = nil; [worker setIsBusy:false]; worker = nil; } @end