diff --git a/.gitignore b/.gitignore index 541965de2..827bedd6f 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,13 @@ Icon? ehthumbs.db Thumbs.db .idea/ + +# Removed because it has some weird file names that Windows can't handle # +########################################################################## +iOS/tests/* + +# Android # +########### +**/*.approj/configuration.json +**/*.approj/Headers +**/*.approj/targets diff --git a/PubNub/Core/PubNub+Core.m b/PubNub/Core/PubNub+Core.m index f9db95101..eacd53682 100644 --- a/PubNub/Core/PubNub+Core.m +++ b/PubNub/Core/PubNub+Core.m @@ -16,6 +16,9 @@ #import "PNNetwork.h" #import "PNHelpers.h" +#ifdef PGDROID +#import +#endif #pragma mark Static @@ -70,6 +73,8 @@ @interface PubNub () */ @property (nonatomic, strong) PNNetwork *serviceNetwork; +@property (nonatomic, strong) PNNetwork *historyNetwork; + /** @brief Stores reference on reachability helper. @discussion Helper used by client to know about when something happened with network and when it is @@ -206,7 +211,7 @@ - (instancetype)initWithConfiguration:(PNConfiguration *)configuration _heartbeatManager = [PNHeartbeat heartbeatForClient:self]; [self addListener:self]; [self prepareReachability]; -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(handleContextTransition:) name:UIApplicationWillEnterForegroundNotification object:nil]; @@ -293,7 +298,6 @@ - (void)setRecentClientStatus:(PNStatusCategory)recentClientStatus { // Check whether previous client state reported unexpected disconnection from remote data // objects live feed or not. - PNStatusCategory previousState = self.recentClientStatus; PNStatusCategory currentState = recentClientStatus; // In case if client disconnected only from one of it's channels it should keep 'connected' @@ -308,25 +312,23 @@ - (void)setRecentClientStatus:(PNStatusCategory)recentClientStatus { // Check whether client reported unexpected disconnection. if (currentState == PNUnexpectedDisconnectCategory) { - // Check whether client unexpectedly disconnected while tried to subscribe or not. - if (previousState != PNDisconnectedCategory) { - - // Dispatching check block with small delay, which will allow to fire reachability - // change event. - __weak __typeof(self) weakSelf = self; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), - dispatch_get_main_queue(), ^{ - - // Silence static analyzer warnings. - // Code is aware about this case and at the end will simply call on 'nil' object - // method. In most cases if referenced object become 'nil' it mean what there is no - // more need in it and probably whole client instance has been deallocated. - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wreceiver-is-weak" - [weakSelf.reachability startServicePing]; - #pragma clang diagnostic pop - }); - } + // Dispatching check block with small delay, which will allow to fire reachability + // change event. + __weak __typeof(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + + // Silence static analyzer warnings. + // Code is aware about this case and at the end will simply call on 'nil' object + // method. In most cases if referenced object become 'nil' it mean what there is no + // more need in it and probably whole client instance has been deallocated. + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wreceiver-is-weak" + [weakSelf.reachability startServicePing]; + #pragma clang diagnostic pop + }); + } else { + [self.reachability stopServicePing]; } } @@ -348,7 +350,6 @@ - (void)prepareReachability { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" #pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" - [weakSelf.reachability stopServicePing]; [weakSelf.subscriberManager restoreSubscriptionCycleIfRequiredWithCompletion:nil]; #pragma clang diagnostic pop } @@ -362,10 +363,14 @@ - (void)prepareNetworkManagers { _subscriptionNetwork = [PNNetwork networkForClient:self requestTimeout:_configuration.subscribeMaximumIdleTime - maximumConnections:1 longPoll:YES]; + maximumConnections:2 longPoll:YES]; _serviceNetwork = [PNNetwork networkForClient:self requestTimeout:_configuration.nonSubscribeRequestTimeout maximumConnections:3 longPoll:NO]; + _historyNetwork = [PNNetwork networkForClient:self + requestTimeout:_configuration.historyRequestTimeout + maximumConnections:1 + longPoll:NO]; } @@ -387,6 +392,12 @@ - (void)processOperation:(PNOperationType)operationType [self.subscriptionNetwork processOperation:operationType withParameters:parameters data:data completionBlock:block]; } + else if (operationType == PNHistoryOperation) { + [self.historyNetwork processOperation:operationType + withParameters:parameters + data:data + completionBlock:block]; + } else { [self.serviceNetwork processOperation:operationType withParameters:parameters @@ -464,7 +475,7 @@ - (void)callBlock:(id)block status:(BOOL)callingStatusBlock withResult:(PNResult - (void)client:(PubNub *)__unused client didReceiveStatus:(PNSubscribeStatus *)status { if (status.category == PNConnectedCategory || status.category == PNDisconnectedCategory || - status.category == PNUnexpectedDisconnectCategory) { + status.category == PNUnexpectedDisconnectCategory || status.category == PNReconnectedCategory) { self.recentClientStatus = status.category; } @@ -475,7 +486,7 @@ - (void)client:(PubNub *)__unused client didReceiveStatus:(PNSubscribeStatus *)s - (void)handleContextTransition:(NSNotification *)notification { -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) if ([notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification]) { DDLogClientInfo([[self class] ddLogLevel], @" Did enter background execution context."); @@ -503,7 +514,7 @@ - (void)handleContextTransition:(NSNotification *)notification { - (void)dealloc { -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; diff --git a/PubNub/Core/PubNub+Publish.m b/PubNub/Core/PubNub+Publish.m index 5cf5f5712..3c7130861 100644 --- a/PubNub/Core/PubNub+Publish.m +++ b/PubNub/Core/PubNub+Publish.m @@ -179,8 +179,7 @@ - (void) publish:(id)message toChannel:(NSString *)channel DDLogAPICall([[self class] ddLogLevel], @" Publish%@ message to '%@' channel%@%@", (compressed ? @" compressed" : @""), (channel?: @""), (!shouldStore ? @" which won't be saved in hisotry" : @""), - (!compressed ? [NSString stringWithFormat:@": %@", - (messageForPublish?: @"")] : @".")); + ([NSString stringWithFormat:@": %@", (messageForPublish?: @"")])); [self processOperation:PNPublishOperation withParameters:parameters data:publishData completionBlock:^(PNStatus *status) { diff --git a/PubNub/Data/Managers/PNSubscriber.m b/PubNub/Data/Managers/PNSubscriber.m index 7e89454c1..20c8738b6 100644 --- a/PubNub/Data/Managers/PNSubscriber.m +++ b/PubNub/Data/Managers/PNSubscriber.m @@ -15,6 +15,10 @@ #import #import "PNHelpers.h" +#ifdef PGDROID +#import +#endif + #pragma mark Static @@ -566,7 +570,7 @@ - (void)updateStateTo:(PNSubscriberState)state withStatus:(PNSubscribeStatus *)s currentState == PNConnectedSubscriberState); category = ((targetState == PNDisconnectedSubscriberState) ? PNDisconnectedCategory : PNUnexpectedDisconnectCategory); - self.mayRequireSubscriptionRestore = shouldHandleTransition; + self.mayRequireSubscriptionRestore = YES; } // Check whether transit to 'access denied' state. else if (targetState == PNAccessRightsErrorSubscriberState) { @@ -628,6 +632,10 @@ - (instancetype)initForClient:(PubNub *)client { _presenceChannelsSet = [NSMutableSet new]; _resourceAccessQueue = dispatch_queue_create("com.pubnub.subscriber", DISPATCH_QUEUE_CONCURRENT); + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didEnterBackground) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; } return self; @@ -718,25 +726,31 @@ - (void)restoreSubscriptionCycleIfRequiredWithCompletion:(PNSubscriberCompletion __block BOOL shouldRestore; __block BOOL ableToRestore; + DDLogAPICall([[self class] ddLogLevel], @"Called restore subscription cycle with block: %@", block); + + __weak __typeof(self) weakSelf = self; dispatch_sync(self.resourceAccessQueue, ^{ - + __strong __typeof(self) self = weakSelf; + DDLogAPICall([[self class] ddLogLevel], @"Checking if should and able to restore subscription cycle with block: %@", block); shouldRestore = (self.currentState == PNDisconnectedUnexpectedlySubscriberState && self.mayRequireSubscriptionRestore); ableToRestore = ([self.channelsSet count] || [self.channelGroupsSet count] || [self.presenceChannelsSet count]); }); if (shouldRestore && ableToRestore) { - + DDLogAPICall([[self class] ddLogLevel], @"Restoring subscription cycle with block: %@", block); [self subscribe:YES withState:nil completion:block]; - } - else if (block) { - - block(nil); + } else { + DDLogAPICall([[self class] ddLogLevel], @"Not restoring subscription cycle with block (%d, %d): %@", shouldRestore, ableToRestore, block); + if (block) { + block(nil); + } } } - (void)continueSubscriptionCycleIfRequiredWithCompletion:(PNSubscriberCompletionBlock)block { + DDLogAPICall([[self class] ddLogLevel], @"Continuing subscription cycle with block: %@", block); [self subscribe:NO withState:nil completion:block]; } @@ -894,7 +908,6 @@ - (void)handleSuccessSubscriptionStatus:(PNSubscribeStatus *)status { } - (void)handleFailedSubscriptionStatus:(PNSubscribeStatus *)status { - // Silence static analyzer warnings. // Code is aware about this case and at the end will simply call on 'nil' object method. // In most cases if referenced object become 'nil' it mean what there is no more need in @@ -1051,6 +1064,7 @@ - (void)handleLiveFeedEvents:(PNSubscribeStatus *)status { // it and probably whole client instance has been deallocated. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" + PNSubscribeStatus *copiedStatus = [status copy]; [self.client.listenersManager notifyWithBlock:^{ // Iterate through array with notifications and report back using callback blocks to the @@ -1078,7 +1092,7 @@ - (void)handleLiveFeedEvents:(PNSubscribeStatus *)status { } } - id eventResultObject = [status copyWithMutatedData:event]; + id eventResultObject = [copiedStatus copyWithMutatedData:event]; if (isPresenceEvent) { object_setClass(eventResultObject, [PNPresenceEventResult class]); @@ -1212,7 +1226,11 @@ - (void)appendSubscriberInformation:(PNStatus *)status { status.subscribedChannelGroups = [_channelGroupsSet allObjects]; } -#pragma mark - +#pragma mark - Internal +- (void)didEnterBackground { + [self.client.heartbeatManager stopHeartbeatIfPossible]; + [self stopRetryTimer]; +} @end diff --git a/PubNub/Data/PNAES.m b/PubNub/Data/PNAES.m index 4042ceb99..ae37a725d 100644 --- a/PubNub/Data/PNAES.m +++ b/PubNub/Data/PNAES.m @@ -356,8 +356,12 @@ + (NSError *)errorFor:(CCCryptorStatus)status { errorCode = kPNAESInsufficientMemoryError; break; case kCCDecodeError: +#ifdef PGDROID +# warning HC SVNT DRACONES! : CommonCrypto is not fully implemented on PGDroid ... +#else case kCCOverflow: case kCCRNGFailure: +#endif description = @"Provided data can't be processed (data can be not encryped)."; errorCode = kPNAESDecryptionError; diff --git a/PubNub/Data/PNConfiguration.h b/PubNub/Data/PNConfiguration.h index 3b0d5b05f..b2a6a93f2 100644 --- a/PubNub/Data/PNConfiguration.h +++ b/PubNub/Data/PNConfiguration.h @@ -111,6 +111,8 @@ */ @property (nonatomic, assign) NSTimeInterval nonSubscribeRequestTimeout; +@property (nonatomic, assign) NSTimeInterval historyRequestTimeout; + /** @brief Reference on number of seconds which is used by server to track whether client still subscribed on remote data objects live feed or not. diff --git a/PubNub/Data/PNConfiguration.m b/PubNub/Data/PNConfiguration.m index 4caf09887..b600f6f8f 100644 --- a/PubNub/Data/PNConfiguration.m +++ b/PubNub/Data/PNConfiguration.m @@ -3,7 +3,7 @@ @since 4.0 @copyright © 2009-2015 PubNub, Inc. */ -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) #import #elif __MAC_OS_X_VERSION_MIN_REQUIRED #import @@ -112,6 +112,7 @@ - (instancetype)initWithPublishKey:(NSString *)publishKey subscribeKey:(NSString _uuid = [[[NSUUID UUID] UUIDString] copy]; _subscribeMaximumIdleTime = kPNDefaultSubscribeMaximumIdleTime; _nonSubscribeRequestTimeout = kPNDefaultNonSubscribeRequestTimeout; + _historyRequestTimeout = kPNDefaultNonSubscribeRequestTimeout; _TLSEnabled = kPNDefaultIsTLSEnabled; _keepTimeTokenOnListChange = kPNDefaultShouldKeepTimeTokenOnListChange; _restoreSubscription = kPNDefaultShouldRestoreSubscription; @@ -133,6 +134,7 @@ - (id)copyWithZone:(NSZone *)zone { configuration.cipherKey = self.cipherKey; configuration.subscribeMaximumIdleTime = self.subscribeMaximumIdleTime; configuration.nonSubscribeRequestTimeout = self.nonSubscribeRequestTimeout; + configuration.historyRequestTimeout = self.historyRequestTimeout; configuration.presenceHeartbeatValue = self.presenceHeartbeatValue; configuration.presenceHeartbeatInterval = self.presenceHeartbeatInterval; configuration.TLSEnabled = self.isTLSEnabled; @@ -147,7 +149,7 @@ - (id)copyWithZone:(NSZone *)zone { #pragma mark - Misc - (NSString *)uniqueDeviceIdentifier { -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) return [[[UIDevice currentDevice] identifierForVendor] UUIDString]; #elif __MAC_OS_X_VERSION_MIN_REQUIRED return ([self serialNumber]?: [self macAddress]); diff --git a/PubNub/Data/Service Objects/PNErrorStatus.m b/PubNub/Data/Service Objects/PNErrorStatus.m index b205d9659..9b33cf711 100644 --- a/PubNub/Data/Service Objects/PNErrorStatus.m +++ b/PubNub/Data/Service Objects/PNErrorStatus.m @@ -23,8 +23,14 @@ - (NSArray *)channelGroups { } - (NSString *)information { - - return self.serviceData[@"information"]; + + if ([self.serviceData isKindOfClass:[NSDictionary class]]) { + return self.serviceData[@"information"]; + } else if ([self.serviceData isKindOfClass:[NSString class]]) { + return (NSString *)self.serviceData; + } else { + return [self.serviceData description]; + } } - (id)data { diff --git a/PubNub/Data/Service Objects/PNResult.m b/PubNub/Data/Service Objects/PNResult.m index 586f55721..8daf49cf6 100644 --- a/PubNub/Data/Service Objects/PNResult.m +++ b/PubNub/Data/Service Objects/PNResult.m @@ -67,15 +67,28 @@ - (instancetype)initForOperation:(PNOperationType)operation processedData = [dataForUpdate copy]; _statusCode = (([statusCode integerValue] > 200) ? [statusCode integerValue] : _statusCode); } - _serviceData = [processedData copy]; + _serviceData = [PNResult normalizeServiceData:processedData]; } return self; } - (id)copyWithZone:(NSZone *)zone { - PNResult *result = [[[self class] allocWithZone:zone] init]; + [self fillCopy:result shouldCopyServiceData:YES]; + return result; +} + +- (instancetype)copyWithMutatedData:(id)data { + + PNResult *result = [[[self class] alloc] init]; + [self fillCopy:result shouldCopyServiceData:NO]; + [result updateData:data]; + + return result; +} + +- (void)fillCopy:(PNResult *)result shouldCopyServiceData:(BOOL)shouldCopyServiceData { result.statusCode = self.statusCode; result.operation = self.operation; result.TLSEnabled = self.isTLSEnabled; @@ -83,22 +96,28 @@ - (id)copyWithZone:(NSZone *)zone { result.authKey = self.authKey; result.origin = self.origin; result.clientRequest = self.clientRequest; - result.serviceData = self.serviceData; - - return result; + + if (shouldCopyServiceData) { + [result updateData:self.serviceData]; + } } -- (instancetype)copyWithMutatedData:(id)data { - - PNResult *result = [self copy]; - result->_serviceData = [data copy]; - - return result; ++ (NSDictionary *)normalizeServiceData:(id)serviceData { + if (serviceData && ![serviceData isKindOfClass:[NSDictionary class]]) { + id copyableServiceData; + if ([serviceData respondsToSelector:@selector(copy)]) { + copyableServiceData = serviceData; + } else { + copyableServiceData = [serviceData description]; + } + return @{@"information": [copyableServiceData copy]}; + } + return [serviceData copy]; } - (void)updateData:(id)data { - _serviceData = [data copy]; + _serviceData = [PNResult normalizeServiceData:data]; } diff --git a/PubNub/Misc/Helpers/PNClass.m b/PubNub/Misc/Helpers/PNClass.m index 66d0a8efa..0d9046e37 100644 --- a/PubNub/Misc/Helpers/PNClass.m +++ b/PubNub/Misc/Helpers/PNClass.m @@ -69,19 +69,24 @@ + (NSArray *)classesRespondingToSelector:(SEL)selector { + (NSArray *)classes { - NSMutableArray *classesList = [NSMutableArray new]; - unsigned int visibleClassesCount; - Class *classes = objc_copyClassList(&visibleClassesCount); - for (unsigned int classIdx = 0; classIdx < visibleClassesCount; classIdx++) { - - if ([NSStringFromClass(classes[classIdx]) hasPrefix:@"PN"] || - [NSStringFromClass(classes[classIdx]) isEqualToString:@"PubNub"]) { - - [classesList addObject:classes[classIdx]]; + static NSMutableArray *classesList; + static dispatch_once_t dispatchToken; + dispatch_once(&dispatchToken, ^{ + + classesList = [NSMutableArray new]; + unsigned int visibleClassesCount; + Class *classes = objc_copyClassList(&visibleClassesCount); + for (unsigned int classIdx = 0; classIdx < visibleClassesCount; classIdx++) { + + if ([NSStringFromClass(classes[classIdx]) hasPrefix:@"PN"] || + [NSStringFromClass(classes[classIdx]) isEqualToString:@"PubNub"]) { + + [classesList addObject:classes[classIdx]]; + } } - } - free(classes); - + free(classes); + }); + return ([classesList count] ? [classesList copy] : nil); } diff --git a/PubNub/Misc/Logger/PNLog.h b/PubNub/Misc/Logger/PNLog.h index c1feab169..ada3a5094 100644 --- a/PubNub/Misc/Logger/PNLog.h +++ b/PubNub/Misc/Logger/PNLog.h @@ -121,6 +121,9 @@ */ + (BOOL)isDumpingToFile; ++ (void)rollLogFileWithCompletion:(void (^)(void))completionBlock; ++ (NSString *)currentLogFilePath; + #pragma mark - diff --git a/PubNub/Misc/Logger/PNLog.m b/PubNub/Misc/Logger/PNLog.m index 790a80bc4..99a35c423 100644 --- a/PubNub/Misc/Logger/PNLog.m +++ b/PubNub/Misc/Logger/PNLog.m @@ -140,8 +140,8 @@ - (void)prepare { // Adding file logger for messages sent by PubNub client. self.fileLogger = [[DDFileLogger alloc] initWithLogFileManager:[PNLogFileManager new]]; self.fileLogger.maximumFileSize = (5 * 1024 * 1024); - self.fileLogger.logFileManager.maximumNumberOfLogFiles = 5; - self.fileLogger.logFileManager.logFilesDiskQuota = (50 * 1024 * 1024); + self.fileLogger.logFileManager.maximumNumberOfLogFiles = 0; + self.fileLogger.logFileManager.logFilesDiskQuota = 0; } + (void)enabled:(BOOL)isLoggingEnabled { @@ -227,6 +227,30 @@ + (BOOL)isDumpingToFile { return [self sharedInstance].isFileLoggerActive; } +- (void)rollLogFileWithCompletion:(void (^)(void))completionBlock { + if (self.isFileLoggerActive) { + [self.fileLogger rollLogFileWithCompletionBlock:completionBlock]; + } +} + ++ (void)rollLogFileWithCompletion:(void (^)(void))completionBlock { + [[self sharedInstance] rollLogFileWithCompletion:completionBlock]; +} + +- (NSString *)currentLogFilePath { + if (self.isFileLoggerActive) { + DDLogFileInfo *fileInfo = [self.fileLogger currentLogFileInfo]; + if (fileInfo) { + return fileInfo.filePath; + } + } + return nil; +} + ++ (NSString *)currentLogFilePath { + return [[self sharedInstance] currentLogFilePath]; +} + #pragma mark - diff --git a/PubNub/Misc/Logger/PNLogFileManager.m b/PubNub/Misc/Logger/PNLogFileManager.m index 59d197b1a..e6d417d73 100644 --- a/PubNub/Misc/Logger/PNLogFileManager.m +++ b/PubNub/Misc/Logger/PNLogFileManager.m @@ -5,31 +5,38 @@ */ #import "PNLogFileManager.h" +@interface PNLogFileManager() + +@property (nonatomic, readwrite, strong) NSDateFormatter *dateFormatter; + +@end #pragma mark Interface implementation @implementation PNLogFileManager - (instancetype)init { - // Configure file manager with default storage in application's Documents folder. NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - return [self initWithLogsDirectory:[documents lastObject]]; + if (self = [self initWithLogsDirectory:[documents lastObject]]) { + NSString *dateFormat = @"yyyy'-'MM'-'dd'T'HH'-'mm'-'ss'"; + _dateFormatter = [[NSDateFormatter alloc] init]; + [_dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + [_dateFormatter setDateFormat:dateFormat]; + [_dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; + } + return self; } - (NSString *)newLogFileName { - - return [[super newLogFileName] stringByReplacingOccurrencesOfString:@".log" - withString:@".txt"]; + NSString *formattedDate = [self.dateFormatter stringFromDate:[NSDate date]]; + return [[NSString alloc] initWithFormat:@"pubnub-console-dump-%@.log", formattedDate]; } - (BOOL)isLogFile:(NSString *)fileName { - - NSString *originalName = [fileName stringByReplacingOccurrencesOfString:@".txt" - withString:@".log"]; - - return [super isLogFile:originalName]; + return [fileName hasPrefix:@"pubnub-console-dump-"] + && [fileName hasSuffix:@".log"]; } #pragma mark - diff --git a/PubNub/Misc/PNConstants.h b/PubNub/Misc/PNConstants.h index c511e78b2..a3b964070 100644 --- a/PubNub/Misc/PNConstants.h +++ b/PubNub/Misc/PNConstants.h @@ -20,7 +20,7 @@ static NSString * const kPNLibraryVersion = @"4.0.3"; static NSString * const kPNBranchName = @"master"; static NSString * const kPNCommit = @"a9c8c4648958b86cac4b59f7092cc6ed06dd7626"; -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) static NSString * const kPNClientName = @"ObjC-iOS"; #elif __MAC_OS_X_VERSION_MIN_REQUIRED static NSString * const kPNClientName = @"ObjC-MacOS"; diff --git a/PubNub/Network/PNNetwork.m b/PubNub/Network/PNNetwork.m index 83a8c14cb..3454bf338 100644 --- a/PubNub/Network/PNNetwork.m +++ b/PubNub/Network/PNNetwork.m @@ -18,6 +18,9 @@ #import "PNConstants.h" #import "PNHelpers.h" +#ifdef PGDROID + #import +#endif #pragma mark CocoaLumberjack logging support @@ -813,6 +816,7 @@ - (NSURLSessionConfiguration *)configurationWithRequestTimeout:(NSTimeInterval)t // Prepare base configuration with predefined timeout values and maximum connections // to same host (basically how many requests can be handled at once). NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + configuration.URLCache = nil; configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; configuration.HTTPShouldUsePipelining = !self.forLongPollRequests; configuration.HTTPAdditionalHeaders = _additionalHeaders; @@ -848,7 +852,7 @@ - (NSURL *)requestBaseURL { - (NSDictionary *)defaultHeaders { NSString *device = @"iPhone"; -#if __IPHONE_OS_VERSION_MIN_REQUIRED +#if __IPHONE_OS_VERSION_MIN_REQUIRED || defined(PGDROID) device = [[UIDevice currentDevice] model]; NSString *osVersion = [[UIDevice currentDevice] systemVersion]; #elif __MAC_OS_X_VERSION_MIN_REQUIRED diff --git a/PubNub/Network/PNReachability.m b/PubNub/Network/PNReachability.m index 116beb6be..0c6a6f5ba 100644 --- a/PubNub/Network/PNReachability.m +++ b/PubNub/Network/PNReachability.m @@ -168,9 +168,13 @@ - (void)setPingRemoteService:(BOOL)pingRemoteService { - (void)startServicePing { if (!self.pingingRemoteService) { - self.pingRemoteService = YES; - + [self performServicePing]; + } +} + +- (void)performServicePing { + if (self.pingingRemoteService) { // Silence static analyzer warnings. // Code is aware about this case and at the end will simply call on 'nil' object method. // In most cases if referenced object become 'nil' it mean what there is no more need in @@ -181,6 +185,9 @@ - (void)startServicePing { // Try to request 'time' API to ensure what network really available. __weak __typeof(self) weakSelf = self; [self.client timeWithCompletion:^(PNTimeResult *result, __unused PNErrorStatus *status) { + if (!self.pingingRemoteService) { + return; + } __strong __typeof(self) strongSelf = weakSelf; BOOL successfulPing = (result.data != nil); @@ -201,9 +208,7 @@ - (void)startServicePing { NSTimeInterval delay = ((strongSelf.reachable && !successfulPing) ? 1.f : 10.0f); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - - strongSelf.pingRemoteService = NO; - [strongSelf startServicePing]; + [strongSelf performServicePing]; }); } strongSelf.reachable = successfulPing; diff --git a/PubNub/SConscript b/PubNub/SConscript new file mode 100644 index 000000000..0f1cff994 --- /dev/null +++ b/PubNub/SConscript @@ -0,0 +1,117 @@ +header_paths = [ + # Lumberingjack stuff + '../../Pods/CocoaLumberjack/Classes/', + '../../Pods/Headers/Public/', + + # PubNub + './Core', + './Data', + './Data/Managers', + './Data/Service Objects', + './Misc', + './Misc/Helpers', + './Misc/Logger', + './Misc/Protocols', + './Network', + './Network/Parsers', + './PubNub', + '.', +] + +defines = { + 'PGDROID' : 1, +} + +flags = [ + '-fobjc-arc', + '-Wall', + #'-Werror', ... sigh ... maybe someday +] + +deps = [ +] + +sources = [ + # Lumberingjack stuff + '../../Pods/CocoaLumberjack/Classes/DDASLLogCapture.m', + '../../Pods/CocoaLumberjack/Classes/DDASLLogger.m', + '../../Pods/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.m', + '../../Pods/CocoaLumberjack/Classes/DDFileLogger.m', + '../../Pods/CocoaLumberjack/Classes/DDLog.m', + '../../Pods/CocoaLumberjack/Classes/DDTTYLogger.m', + + # PubNub stuffs + './Core/PubNub+APNS.m', + './Core/PubNub+ChannelGroup.m', + './Core/PubNub+Core.m', + './Core/PubNub+History.m', + './Core/PubNub+Presence.m', + './Core/PubNub+Publish.m', + './Core/PubNub+State.m', + './Core/PubNub+Subscribe.m', + './Core/PubNub+Time.m', + './Data/Managers/PNClientState.m', + './Data/Managers/PNHeartbeat.m', + './Data/Managers/PNStateListener.m', + './Data/Managers/PNSubscriber.m', + './Data/PNAES.m', + './Data/PNConfiguration.m', + './Data/Service Objects/PNAcknowledgmentStatus.m', + './Data/Service Objects/PNAPNSEnabledChannelsResult.m', + './Data/Service Objects/PNChannelClientStateResult.m', + './Data/Service Objects/PNChannelGroupChannelsResult.m', + './Data/Service Objects/PNChannelGroupClientStateResult.m', + './Data/Service Objects/PNChannelGroupsResult.m', + './Data/Service Objects/PNClientStateUpdateStatus.m', + './Data/Service Objects/PNErrorStatus.m', + './Data/Service Objects/PNHistoryResult.m', + './Data/Service Objects/PNPresenceChannelGroupHereNowResult.m', + './Data/Service Objects/PNPresenceChannelHereNowResult.m', + './Data/Service Objects/PNPresenceGlobalHereNowResult.m', + './Data/Service Objects/PNPresenceWhereNowResult.m', + './Data/Service Objects/PNPublishStatus.m', + './Data/Service Objects/PNResult.m', + './Data/Service Objects/PNServiceData.m', + './Data/Service Objects/PNStatus.m', + './Data/Service Objects/PNSubscriberResults.m', + './Data/Service Objects/PNSubscribeStatus.m', + './Data/Service Objects/PNTimeResult.m', + './Misc/Helpers/PNArray.m', + './Misc/Helpers/PNChannel.m', + './Misc/Helpers/PNClass.m', + './Misc/Helpers/PNData.m', + './Misc/Helpers/PNDictionary.m', + './Misc/Helpers/PNGZIP.m', + './Misc/Helpers/PNJSON.m', + './Misc/Helpers/PNString.m', + './Misc/Helpers/PNURLRequest.m', + './Misc/Logger/PNLog.m', + './Misc/Logger/PNLogFileManager.m', + './Misc/Logger/PNLogger.m', + './Network/Parsers/PNChannelGroupAuditionParser.m', + './Network/Parsers/PNChannelGroupModificationParser.m', + './Network/Parsers/PNClientStateParser.m', + './Network/Parsers/PNErrorParser.m', + './Network/Parsers/PNHeartbeatParser.m', + './Network/Parsers/PNHistoryParser.m', + './Network/Parsers/PNLeaveParser.m', + './Network/Parsers/PNMessagePublishParser.m', + './Network/Parsers/PNPresenceHereNowParser.m', + './Network/Parsers/PNPresenceWhereNowParser.m', + './Network/Parsers/PNPushNotificationsAuditParser.m', + './Network/Parsers/PNPushNotificationsStateModificationParser.m', + './Network/Parsers/PNRemoveDeviceFromAPNSResponseParser.m', + './Network/Parsers/PNSubscribeParser.m', + './Network/Parsers/PNTimeParser.m', + './Network/PNNetwork.m', + './Network/PNNetworkResponseSerializer.m', + './Network/PNReachability.m', + './Network/PNRequestParameters.m', + './Network/PNURLBuilder.m', +] + +features = [ +] + +Import('env') +env.BuildLibrary('PubNub', sources, header_paths=header_paths, static=True, flags=flags, defines=defines, deps=deps, features=features) diff --git a/src b/src new file mode 120000 index 000000000..bb49dac7b --- /dev/null +++ b/src @@ -0,0 +1 @@ +PubNub \ No newline at end of file