From a0a32c4dbf98259906346468ef47cdb89fc19d6f Mon Sep 17 00:00:00 2001 From: Alexander Dodatko Date: Fri, 27 Jul 2018 16:07:44 +0300 Subject: [PATCH] [#3] refactoring * assert() ==> NSParameterAssert() * using _cmd instead of selector literals where appropriate * JAHPQNSURLSessionDemuxTaskInfo extracted to a separate file * a few typedefs introduced for convenience * a few local variables extracted --- .../JAHPQNSURLSessionDemux.m | 354 ++++++++++-------- 1 file changed, 204 insertions(+), 150 deletions(-) diff --git a/Source/JiveAuthenticatingHTTPProtocol/JAHPQNSURLSessionDemux.m b/Source/JiveAuthenticatingHTTPProtocol/JAHPQNSURLSessionDemux.m index ce49371..122a8a8 100644 --- a/Source/JiveAuthenticatingHTTPProtocol/JAHPQNSURLSessionDemux.m +++ b/Source/JiveAuthenticatingHTTPProtocol/JAHPQNSURLSessionDemux.m @@ -46,72 +46,13 @@ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ #import "JAHPQNSURLSessionDemux.h" - -@interface JAHPQNSURLSessionDemuxTaskInfo : NSObject - -- (instancetype)initWithTask:(NSURLSessionDataTask *)task delegate:(id)delegate modes:(NSArray *)modes; - -@property (atomic, strong, readonly ) NSURLSessionDataTask * task; -@property (atomic, strong, readonly ) id delegate; -@property (atomic, strong, readonly ) NSThread * thread; -@property (atomic, copy, readonly ) NSArray * modes; - -- (void)performBlock:(dispatch_block_t)block; - -- (void)invalidate; - -@end - -@interface JAHPQNSURLSessionDemuxTaskInfo () - -@property (atomic, strong, readwrite) id delegate; -@property (atomic, strong, readwrite) NSThread * thread; - -@end - -@implementation JAHPQNSURLSessionDemuxTaskInfo - -- (instancetype)initWithTask:(NSURLSessionDataTask *)task delegate:(id)delegate modes:(NSArray *)modes -{ - assert(task != nil); - assert(delegate != nil); - assert(modes != nil); - - self = [super init]; - if (self != nil) { - self->_task = task; - self->_delegate = delegate; - self->_thread = [NSThread currentThread]; - self->_modes = [modes copy]; - } - return self; -} - -- (void)performBlock:(dispatch_block_t)block -{ - assert(self.delegate != nil); - assert(self.thread != nil); - [self performSelector:@selector(performBlockOnClientThread:) onThread:self.thread withObject:[block copy] waitUntilDone:NO modes:self.modes]; -} - -- (void)performBlockOnClientThread:(dispatch_block_t)block -{ - assert([NSThread currentThread] == self.thread); - block(); -} - -- (void)invalidate -{ - self.delegate = nil; - self.thread = nil; -} - -@end +#import "JAHPQNSURLSessionDemuxTaskInfo.h" @interface JAHPQNSURLSessionDemux () -@property (atomic, strong, readonly ) NSMutableDictionary * taskInfoByTaskID; // keys NSURLSessionTask taskIdentifier, values are SessionManager -@property (atomic, strong, readonly ) NSOperationQueue * sessionDelegateQueue; +// keys NSURLSessionTask taskIdentifier, values are SessionManager +@property (atomic, strong, readonly ) NSMutableDictionary* taskInfoByTaskID; +@property (atomic, strong, readonly ) NSOperationQueue* sessionDelegateQueue; @end @@ -126,43 +67,61 @@ - (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration { // configuration may be nil self = [super init]; - if (self != nil) { - if (configuration == nil) { - configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - } - self->_configuration = [configuration copy]; - - self->_taskInfoByTaskID = [[NSMutableDictionary alloc] init]; - - self->_sessionDelegateQueue = [[NSOperationQueue alloc] init]; - [self->_sessionDelegateQueue setMaxConcurrentOperationCount:1]; - [self->_sessionDelegateQueue setName:@"JAHPQNSURLSessionDemux"]; + + if (self == nil) + { + return nil; + } - self->_session = [NSURLSession sessionWithConfiguration:self->_configuration delegate:self delegateQueue:self->_sessionDelegateQueue]; - self->_session.sessionDescription = @"JAHPQNSURLSessionDemux"; + if (configuration == nil) + { + configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; } + self->_configuration = [configuration copy]; + + self->_taskInfoByTaskID = [[NSMutableDictionary alloc] init]; + + self->_sessionDelegateQueue = [[NSOperationQueue alloc] init]; + [self->_sessionDelegateQueue setMaxConcurrentOperationCount:1]; + [self->_sessionDelegateQueue setName:@"JAHPQNSURLSessionDemux"]; + + self->_session = + [NSURLSession sessionWithConfiguration:self->_configuration + delegate:self + delegateQueue:self->_sessionDelegateQueue]; + + self->_session.sessionDescription = @"JAHPQNSURLSessionDemux"; + + return self; } -- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request delegate:(id)delegate modes:(NSArray *)modes +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request + delegate:(id)delegate + modes:(NSArray *)modes { - NSURLSessionDataTask * task; - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + NSURLSessionDataTask* task ; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo; - assert(request != nil); - assert(delegate != nil); + NSParameterAssert(request != nil); + NSParameterAssert(delegate != nil); // modes may be nil - if ([modes count] == 0) { + if ([modes count] == 0) + { modes = @[ NSDefaultRunLoopMode ]; } task = [self.session dataTaskWithRequest:request]; - assert(task != nil); + NSParameterAssert(task != nil); - taskInfo = [[JAHPQNSURLSessionDemuxTaskInfo alloc] initWithTask:task delegate:delegate modes:modes]; + taskInfo = + [[JAHPQNSURLSessionDemuxTaskInfo alloc] initWithTask: task + delegate: delegate + modes: modes]; - @synchronized (self) { + @synchronized (self) + { self.taskInfoByTaskID[@(task.taskIdentifier)] = taskInfo; } @@ -171,80 +130,126 @@ - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request delegate:( - (JAHPQNSURLSessionDemuxTaskInfo *)taskInfoForTask:(NSURLSessionTask *)task { - JAHPQNSURLSessionDemuxTaskInfo * result; + JAHPQNSURLSessionDemuxTaskInfo* result; - assert(task != nil); + NSParameterAssert(task != nil); - @synchronized (self) { + @synchronized (self) + { result = self.taskInfoByTaskID[@(task.taskIdentifier)]; - assert(result != nil); + NSParameterAssert(result != nil); } + return result; } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *))completionHandler +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)newRequest + completionHandler:(void (^)(NSURLRequest *))completionHandler { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = nil; taskInfo = [self taskInfoForTask:task]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session task:task willPerformHTTPRedirection:response newRequest:newRequest completionHandler:completionHandler]; + if ([taskInfo.delegate respondsToSelector: _cmd]) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession:session + task:task + willPerformHTTPRedirection:response + newRequest:newRequest + completionHandler:completionHandler]; }]; - } else { + } + else + { completionHandler(newRequest); } } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler + +typedef void (^JAHUrlSessionChallengeHandler)( + NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential *credential); + + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(JAHUrlSessionChallengeHandler)completionHandler { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:task]; - taskInfo = [self taskInfoForTask:task]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler]; + if ([taskInfo.delegate respondsToSelector: _cmd]) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession:session + task:task + didReceiveChallenge:challenge + completionHandler:completionHandler]; }]; - } else { + } + else + { completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler +typedef void (^JAHUrlSessionBodyStreamHandler)(NSInputStream *bodyStream); + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + needNewBodyStream:(JAHUrlSessionBodyStreamHandler)completionHandler { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; - - taskInfo = [self taskInfoForTask:task]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:task:needNewBodyStream:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session task:task needNewBodyStream:completionHandler]; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:task]; + if ([taskInfo.delegate respondsToSelector: _cmd]) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession: session + task: task + needNewBodyStream: completionHandler]; }]; - } else { + } else + { completionHandler(nil); } } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:task]; - taskInfo = [self taskInfoForTask:task]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend]; + if ([taskInfo.delegate respondsToSelector: _cmd]) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession: session + task: task + didSendBodyData: bytesSent + totalBytesSent: totalBytesSent + totalBytesExpectedToSend: totalBytesExpectedToSend]; }]; } } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error +- (void) URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didCompleteWithError:(NSError *)error { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; - - taskInfo = [self taskInfoForTask:task]; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:task]; // This is our last delegate callback so we remove our task info record. - @synchronized (self) { + @synchronized (self) + { [self.taskInfoByTaskID removeObjectForKey:@(taskInfo.task.taskIdentifier)]; } @@ -252,64 +257,113 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didComp // after calling the delegate, otherwise the client thread side of the -performBlock: code can // find itself with an invalidated task info. - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:task:didCompleteWithError:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session task:task didCompleteWithError:error]; + if ([taskInfo.delegate respondsToSelector: _cmd]) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession:session + task:task + didCompleteWithError:error]; + [taskInfo invalidate]; }]; - } else { + } + else + { [taskInfo invalidate]; } } -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:dataTask]; - taskInfo = [self taskInfoForTask:dataTask]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler]; + BOOL canPropagateDelegateCall = + [taskInfo.delegate respondsToSelector: _cmd]; + + if (canPropagateDelegateCall) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession: session + dataTask: dataTask + didReceiveResponse: response + completionHandler: completionHandler]; }]; - } else { + } + else + { completionHandler(NSURLSessionResponseAllow); } } -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:dataTask]; - taskInfo = [self taskInfoForTask:dataTask]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:dataTask:didBecomeDownloadTask:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session dataTask:dataTask didBecomeDownloadTask:downloadTask]; + BOOL canPropagateDelegateCall = + [taskInfo.delegate respondsToSelector: _cmd]; + + if (canPropagateDelegateCall) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession: session + dataTask: dataTask + didBecomeDownloadTask: downloadTask]; }]; } } -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = [self taskInfoForTask:dataTask]; - taskInfo = [self taskInfoForTask:dataTask]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:dataTask:didReceiveData:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session dataTask:dataTask didReceiveData:data]; + BOOL canPropagateDelegateCall = + [taskInfo.delegate respondsToSelector: _cmd]; + + if (canPropagateDelegateCall) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession: session + dataTask: dataTask + didReceiveData: data]; }]; } } -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + willCacheResponse:(NSCachedURLResponse *)proposedResponse + completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler { - JAHPQNSURLSessionDemuxTaskInfo * taskInfo; + JAHPQNSURLSessionDemuxTaskInfo* taskInfo = nil; taskInfo = [self taskInfoForTask:dataTask]; - if ([taskInfo.delegate respondsToSelector:@selector(URLSession:dataTask:willCacheResponse:completionHandler:)]) { - [taskInfo performBlock:^{ - [taskInfo.delegate URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler]; + + BOOL canPropagateDelegateCall = + ([taskInfo.delegate respondsToSelector: _cmd]); + + if (canPropagateDelegateCall) + { + [taskInfo performBlock:^void() + { + [taskInfo.delegate URLSession: session + dataTask: dataTask + willCacheResponse: proposedResponse + completionHandler: completionHandler]; }]; - } else { + } + else + { completionHandler(proposedResponse); } }