Author: gavincornwell
Date: Thu May 22 15:04:26 2014
New Revision: 1596896

URL: http://svn.apache.org/r1596896
Log:
CMIS-805: Detect when no network is available and return error immediately.

Added:
    chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.h
    chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.m
Modified:
    chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj
    chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.h
    chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.m
    chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISHttpRequest.m

Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj
URL: 
http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj?rev=1596896&r1=1596895&r2=1596896&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj 
(original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj Thu 
May 22 15:04:26 2014
@@ -140,6 +140,10 @@
                5892CC15192CB91300C7734A /* CMISNSDictionary+CMISUtil.h in 
Headers */ = {isa = PBXBuildFile; fileRef = 5892CC11192CB91300C7734A /* 
CMISNSDictionary+CMISUtil.h */; };
                5892CC16192CB91300C7734A /* CMISNSDictionary+CMISUtil.m in 
Sources */ = {isa = PBXBuildFile; fileRef = 5892CC12192CB91300C7734A /* 
CMISNSDictionary+CMISUtil.m */; };
                5892CC17192CB93E00C7734A /* CMISNSDictionary+CMISUtil.m in 
Sources */ = {isa = PBXBuildFile; fileRef = 5892CC12192CB91300C7734A /* 
CMISNSDictionary+CMISUtil.m */; };
+               5892CC1A192CE23F00C7734A /* CMISReachability.h in Headers */ = 
{isa = PBXBuildFile; fileRef = 5892CC18192CE23F00C7734A /* CMISReachability.h 
*/; settings = {ATTRIBUTES = (Public, ); }; };
+               5892CC1B192CE23F00C7734A /* CMISReachability.m in Sources */ = 
{isa = PBXBuildFile; fileRef = 5892CC19192CE23F00C7734A /* CMISReachability.m 
*/; };
+               5892CC20192CEE3E00C7734A /* SystemConfiguration.framework in 
Frameworks */ = {isa = PBXBuildFile; fileRef = 5892CC1F192CEE3E00C7734A /* 
SystemConfiguration.framework */; };
+               5892CC21192CEE4B00C7734A /* SystemConfiguration.framework in 
Frameworks */ = {isa = PBXBuildFile; fileRef = 5892CC1F192CEE3E00C7734A /* 
SystemConfiguration.framework */; };
                750CB2BE159C56A5004576F7 /* AllowableActions.xml in Resources 
*/ = {isa = PBXBuildFile; fileRef = 750CB2BB159C56A5004576F7 /* 
AllowableActions.xml */; };
                750CB2BF159C56A5004576F7 /* FolderChildren-webscripts.xml in 
Resources */ = {isa = PBXBuildFile; fileRef = 750CB2BC159C56A5004576F7 /* 
FolderChildren-webscripts.xml */; };
                750CB2C0159C56A5004576F7 /* FolderChildren-opencmis.xml in 
Resources */ = {isa = PBXBuildFile; fileRef = 750CB2BD159C56A5004576F7 /* 
FolderChildren-opencmis.xml */; };
@@ -386,6 +390,10 @@
                5892CC10192CB91300C7734A /* CMISMimeHelper.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name 
= CMISMimeHelper.m; path = Utils/CMISMimeHelper.m; sourceTree = "<group>"; };
                5892CC11192CB91300C7734A /* CMISNSDictionary+CMISUtil.h */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; 
name = "CMISNSDictionary+CMISUtil.h"; path = 
"Utils/CMISNSDictionary+CMISUtil.h"; sourceTree = "<group>"; };
                5892CC12192CB91300C7734A /* CMISNSDictionary+CMISUtil.m */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.objc; name = "CMISNSDictionary+CMISUtil.m"; path = 
"Utils/CMISNSDictionary+CMISUtil.m"; sourceTree = "<group>"; };
+               5892CC18192CE23F00C7734A /* CMISReachability.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = 
CMISReachability.h; path = Utils/CMISReachability.h; sourceTree = "<group>"; };
+               5892CC19192CE23F00C7734A /* CMISReachability.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name 
= CMISReachability.m; path = Utils/CMISReachability.m; sourceTree = "<group>"; 
};
+               5892CC1C192CE2F700C7734A /* Security.framework */ = {isa = 
PBXFileReference; lastKnownFileType = wrapper.framework; name = 
Security.framework; path = System/Library/Frameworks/Security.framework; 
sourceTree = SDKROOT; };
+               5892CC1F192CEE3E00C7734A /* SystemConfiguration.framework */ = 
{isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = 
SystemConfiguration.framework; path = 
System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; 
};
                750CB2BB159C56A5004576F7 /* AllowableActions.xml */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = 
AllowableActions.xml; sourceTree = "<group>"; };
                750CB2BC159C56A5004576F7 /* FolderChildren-webscripts.xml */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = 
"FolderChildren-webscripts.xml"; sourceTree = "<group>"; };
                750CB2BD159C56A5004576F7 /* FolderChildren-opencmis.xml */ = 
{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = 
"FolderChildren-opencmis.xml"; sourceTree = "<group>"; };
@@ -516,6 +524,7 @@
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               5892CC20192CEE3E00C7734A /* 
SystemConfiguration.framework in Frameworks */,
                                828072A715153DE800EF635C /* 
Foundation.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
@@ -524,6 +533,7 @@
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               5892CC21192CEE4B00C7734A /* 
SystemConfiguration.framework in Frameworks */,
                                828073DE15154F9400EF635C /* 
MobileCoreServices.framework in Frameworks */,
                                828072B815153DE900EF635C /* 
Foundation.framework in Frameworks */,
                                828072BB15153DE900EF635C /* libObjectiveCMIS.a 
in Frameworks */,
@@ -611,6 +621,8 @@
                828072A515153DE800EF635C /* Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               5892CC1F192CEE3E00C7734A /* 
SystemConfiguration.framework */,
+                               5892CC1C192CE2F700C7734A /* Security.framework 
*/,
                                82807383151542F400EF635C /* 
MobileCoreServices.framework */,
                                828072A615153DE800EF635C /* 
Foundation.framework */,
                        );
@@ -818,6 +830,8 @@
                                5892CC12192CB91300C7734A /* 
CMISNSDictionary+CMISUtil.m */,
                                828073291515407000EF635C /* 
CMISObjectConverter.h */,
                                8280732A1515407000EF635C /* 
CMISObjectConverter.m */,
+                               5892CC18192CE23F00C7734A /* CMISReachability.h 
*/,
+                               5892CC19192CE23F00C7734A /* CMISReachability.m 
*/,
                                4EA61BD31564F70C00C759E4 /* 
CMISStringInOutParameter.h */,
                                4EA61BD41564F70C00C759E4 /* 
CMISStringInOutParameter.m */,
                                4EA61BD51564F70C00C759E4 /* CMISURLUtil.h */,
@@ -984,6 +998,7 @@
                                FE417D5715761A0C009056AA /* 
CMISOperationContext.h in Headers */,
                                5892CB80192CB65D00C7734A /* 
CMISFolderTypeDefinition.h in Headers */,
                                FE417D5915761A0C009056AA /* CMISPagedResult.h 
in Headers */,
+                               5892CC1A192CE23F00C7734A /* CMISReachability.h 
in Headers */,
                                FE417D6315761A34009056AA /* CMISLinkCache.h in 
Headers */,
                                FE417D6515761A34009056AA /* 
CMISPropertyDefinition.h in Headers */,
                                FE417D6715761A34009056AA /* 
CMISTypeDefinition.h in Headers */,
@@ -1208,6 +1223,7 @@
                                5892CBBC192CB7D900C7734A /* 
CMISAtomEntryParser.m in Sources */,
                                4EA61BEA1564F75000C759E4 /* CMISErrors.m in 
Sources */,
                                5892CB75192CB5DF00C7734A /* CMISLinkRelations.m 
in Sources */,
+                               5892CC1B192CE23F00C7734A /* CMISReachability.m 
in Sources */,
                                752067F6156AC06300231A5D /* CMISExtensionData.m 
in Sources */,
                                5892CBF9192CB83800C7734A /* 
CMISBroswerFormDataWriter.m in Sources */,
                                752067FB156AC0FE00231A5D /* 
CMISExtensionElement.m in Sources */,
@@ -1367,6 +1383,7 @@
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+                               CLANG_ENABLE_MODULES = YES;
                                DSTROOT = /tmp/ObjectiveCMIS.dst;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = 
"ObjectiveCMIS/ObjectiveCMIS-Prefix.pch";
@@ -1383,6 +1400,7 @@
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+                               CLANG_ENABLE_MODULES = YES;
                                DSTROOT = /tmp/ObjectiveCMIS.dst;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = 
"ObjectiveCMIS/ObjectiveCMIS-Prefix.pch";
@@ -1399,6 +1417,7 @@
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+                               CLANG_ENABLE_MODULES = NO;
                                FRAMEWORK_SEARCH_PATHS = (
                                        
"$(SDKROOT)/Developer/Library/Frameworks",
                                        "$(inherited)",
@@ -1414,6 +1433,7 @@
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+                               CLANG_ENABLE_MODULES = NO;
                                FRAMEWORK_SEARCH_PATHS = (
                                        
"$(SDKROOT)/Developer/Library/Frameworks",
                                        "$(inherited)",

Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.h
URL: 
http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.h?rev=1596896&r1=1596895&r2=1596896&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.h Thu May 22 
15:04:26 2014
@@ -33,7 +33,7 @@ typedef NS_ENUM(NSInteger, CMISErrorCode
     kCMISErrorCodeBasicMaximum = 255,
 
     //basic CMIS errors
-    kCMISErrorCodeNoReturn = 0,
+    kCMISErrorCodeUnknown = 0,
     kCMISErrorCodeConnection = 1,
     kCMISErrorCodeProxyAuthentication = 2,
     kCMISErrorCodeUnauthorized = 3,
@@ -41,6 +41,7 @@ typedef NS_ENUM(NSInteger, CMISErrorCode
     kCMISErrorCodeNoRepositoryFound = 5,
     kCMISErrorCodeCancelled = 6,
     kCMISErrorCodeParsingFailed = 7,
+    kCMISErrorCodeNoNetworkConnection = 8,
     
     //error ranges for General errors
     kCMISErrorCodeGeneralMinimum = 256,
@@ -74,7 +75,7 @@ typedef NS_ENUM(NSInteger, CMISErrorCode
 extern NSString * const kCMISErrorDomainName;
 //to be used in the userInfo dictionary as Localized error description
 //Basic Errors
-extern NSString * const kCMISErrorDescriptionNoReturn;
+extern NSString * const kCMISErrorDescriptionUnknown;
 extern NSString * const kCMISErrorDescriptionConnection;
 extern NSString * const kCMISErrorDescriptionProxyAuthentication;
 extern NSString * const kCMISErrorDescriptionUnauthorized;
@@ -82,6 +83,7 @@ extern NSString * const kCMISErrorDescri
 extern NSString * const kCMISErrorDescriptionRepositoryNotFound;
 extern NSString * const kCMISErrorDescriptionCancelled;
 extern NSString * const kCMISErrorDescriptionParsingFailed;
+extern NSString * const kCMISErrorDescriptionNoNetworkConnection;
 //General errors as defined in 2.2.1.4.1 of spec
 extern NSString * const kCMISErrorDescriptionInvalidArgument;
 extern NSString * const kCMISErrorDescriptionObjectNotFound;

Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.m
URL: 
http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.m?rev=1596896&r1=1596895&r2=1596896&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Common/CMISErrors.m Thu May 22 
15:04:26 2014
@@ -30,7 +30,7 @@ NSString * const kCMISErrorDomainName = 
  */
 //Basic Errors
 
-NSString * const kCMISErrorDescriptionNoReturn = @"Unknown Error";
+NSString * const kCMISErrorDescriptionUnknown = @"Unknown Error";
 NSString * const kCMISErrorDescriptionConnection = @"Connection Error";
 NSString * const kCMISErrorDescriptionProxyAuthentication = @"Proxy 
Authentication Error";
 NSString * const kCMISErrorDescriptionUnauthorized = @"Unauthorized access 
error";
@@ -38,6 +38,7 @@ NSString * const kCMISErrorDescriptionNo
 NSString * const kCMISErrorDescriptionRepositoryNotFound =  @"Repository Not 
Found Error";
 NSString * const kCMISErrorDescriptionCancelled = @"Operation Cancelled";
 NSString * const kCMISErrorDescriptionParsingFailed = @"Parsing Failed";
+NSString * const kCMISErrorDescriptionNoNetworkConnection = @"No Network 
Connection";
 
 //General errors as defined in 2.2.1.4.1 of spec
 NSString * const kCMISErrorDescriptionInvalidArgument = @"Invalid Argument 
Error";
@@ -90,8 +91,8 @@ NSString * const kCMISErrorDescriptionVe
 + (NSString *)localizedDescriptionForCode:(CMISErrorCodes)code
 {
     switch (code) {
-        case kCMISErrorCodeNoReturn:
-            return kCMISErrorDescriptionNoReturn;
+        case kCMISErrorCodeUnknown:
+            return kCMISErrorDescriptionUnknown;
         case kCMISErrorCodeConnection:
             return kCMISErrorDescriptionConnection;
         case kCMISErrorCodeProxyAuthentication:
@@ -106,6 +107,8 @@ NSString * const kCMISErrorDescriptionVe
             return kCMISErrorDescriptionCancelled;
         case kCMISErrorCodeParsingFailed:
             return kCMISErrorDescriptionParsingFailed;
+        case kCMISErrorCodeNoNetworkConnection:
+            return kCMISErrorDescriptionNoNetworkConnection;
         case kCMISErrorCodeInvalidArgument:
             return kCMISErrorDescriptionInvalidArgument;
         case kCMISErrorCodeObjectNotFound:
@@ -133,7 +136,7 @@ NSString * const kCMISErrorDescriptionVe
         case kCMISErrorCodeVersioning:
             return kCMISErrorDescriptionVersioning;
         default:
-            return kCMISErrorDescriptionNoReturn;
+            return kCMISErrorDescriptionUnknown;
     }
     
 }

Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISHttpRequest.m
URL: 
http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISHttpRequest.m?rev=1596896&r1=1596895&r2=1596896&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISHttpRequest.m 
(original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISHttpRequest.m Thu May 
22 15:04:26 2014
@@ -21,6 +21,7 @@
 #import "CMISHttpResponse.h"
 #import "CMISErrors.h"
 #import "CMISLog.h"
+#import "CMISReachability.h"
 
 //Exception names as returned in the <!--exception> tag
 NSString * const kCMISExceptionInvalidArgument         = @"invalidArgument";
@@ -76,6 +77,8 @@ NSString * const kCMISExceptionVersionin
 
 - (BOOL)startRequest:(NSMutableURLRequest*)urlRequest
 {
+    BOOL startedRequest = NO;
+
     if (self.requestBody) {
         if ([CMISLog sharedInstance].logLevel == CMISLogLevelTrace) {
             CMISLogTrace(@"Request body: %@", [[NSString alloc] 
initWithData:self.requestBody encoding:NSUTF8StringEncoding]);
@@ -93,18 +96,25 @@ NSString * const kCMISExceptionVersionin
     }];
     
     self.connection = [[NSURLConnection alloc] initWithRequest:urlRequest 
delegate:self startImmediately:NO];
-    if (self.connection) {
+    CMISReachability *reachability = [CMISReachability networkReachability];
+    
+    if (self.connection && reachability.hasNetworkConnection) {
         [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] 
forMode:NSRunLoopCommonModes];
         [self.connection start];
-        return YES;
-    } else {
+        startedRequest = YES;
+    } else if (!reachability.hasNetworkConnection) {
+        NSError *noConnectionError = [CMISErrors 
createCMISErrorWithCode:kCMISErrorCodeNoNetworkConnection 
detailedDescription:kCMISErrorDescriptionNoNetworkConnection];
+        [self connection:self.connection didFailWithError:noConnectionError];
+    }
+    else {
         if (self.completionBlock) {
             NSString *detailedDescription = [NSString stringWithFormat:@"Could 
not create connection to %@", urlRequest.URL];
             NSError *cmisError = [CMISErrors 
createCMISErrorWithCode:kCMISErrorCodeConnection 
detailedDescription:detailedDescription];
             self.completionBlock(nil, cmisError);
         }
-        return NO;
     }
+    
+    return startedRequest;
 }
 
 - (void)cancel
@@ -163,7 +173,15 @@ NSString * const kCMISExceptionVersionin
     [self.authenticationProvider updateWithHttpURLResponse:self.response];
 
     if (self.completionBlock) {
-        CMISErrorCodes cmisErrorCode = (error.code == NSURLErrorCancelled) ? 
kCMISErrorCodeCancelled : kCMISErrorCodeConnection;
+        CMISErrorCodes cmisErrorCode = kCMISErrorCodeConnection;
+        
+        // swap error code if necessary
+        if (error.code == NSURLErrorCancelled) {
+            cmisErrorCode = kCMISErrorCodeCancelled;
+        } else if (error.code == kCMISErrorCodeNoNetworkConnection) {
+            cmisErrorCode = kCMISErrorCodeNoNetworkConnection;
+        }
+        
         NSError *cmisError = [CMISErrors cmisError:error 
cmisErrorCode:cmisErrorCode];
         self.completionBlock(nil, cmisError);
     }

Added: chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.h
URL: 
http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.h?rev=1596896&view=auto
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.h (added)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.h Thu 
May 22 15:04:26 2014
@@ -0,0 +1,28 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CMISReachability : NSObject
+
+@property (nonatomic, assign, readonly, getter = hasNetworkConnection) BOOL 
networkConnection;
+
++ (instancetype)networkReachability;
+
+@end

Added: chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.m
URL: 
http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.m?rev=1596896&view=auto
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.m (added)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Utils/CMISReachability.m Thu 
May 22 15:04:26 2014
@@ -0,0 +1,144 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CMISReachability.h"
+#import <netinet/in.h>
+#import "CMISLog.h"
+
+@import SystemConfiguration;
+
+static CMISReachability *networkReachability = NULL;
+
+@interface CMISReachability ()
+
+@property (nonatomic, assign) SCNetworkReachabilityRef networkReachabilityRef;
+
+@end
+
+@implementation CMISReachability
+
++ (instancetype)networkReachability
+{
+    if (networkReachability == NULL)
+    {
+        struct sockaddr_in zeroAddress;
+        bzero(&zeroAddress, sizeof(zeroAddress));
+        zeroAddress.sin_len = sizeof(zeroAddress);
+        zeroAddress.sin_family = AF_INET;
+        networkReachability = [self reachabilityWithAddress:&zeroAddress];
+        SCNetworkReachabilityFlags currentFlags = 0;
+        if 
(SCNetworkReachabilityGetFlags(networkReachability->_networkReachabilityRef, 
&currentFlags))
+        {
+            handleFlags(currentFlags);
+        }
+    }
+    return networkReachability;
+}
+
+- (void)dealloc
+{
+    [self stopNotifier];
+    if (self.networkReachabilityRef != NULL)
+    {
+        CFRelease(self.networkReachabilityRef);
+    }
+}
+
+#pragma mark - Private Functions
+
+static void ReachabilityChangedCallback(SCNetworkReachabilityRef target, 
SCNetworkReachabilityFlags flags, void * info)
+{
+    handleFlags(flags);
+}
+
+void handleFlags(SCNetworkReachabilityFlags flags)
+{
+    // At the moment we only care if we have network access
+#if TARGET_OS_IPHONE
+    BOOL reachable = (flags & kSCNetworkReachabilityFlagsReachable) || (flags 
& kSCNetworkReachabilityFlagsIsWWAN);
+#elif TARGET_OS_MAC
+    BOOL reachable = (flags & kSCNetworkReachabilityFlagsReachable);
+#endif
+    
+    BOOL connected = !(flags & kSCNetworkReachabilityFlagsConnectionRequired);
+    
+    if (reachable && connected)
+    {
+        networkReachability->_networkConnection = YES;
+    }
+    else
+    {
+        networkReachability->_networkConnection = NO;
+    }
+    
+    if ([CMISLog sharedInstance].logLevel == CMISLogLevelDebug)
+    {
+        CMISLogDebug(@"Network reachable: %@", (reachable && connected) ? 
@"YES" : @"NO");
+    }
+}
+
++ (instancetype)reachabilityWithAddress:(const struct sockaddr_in 
*)hostAddress;
+{
+    CMISReachability *returnReachability = NULL;
+    
+    SCNetworkReachabilityRef reachability = 
SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct 
sockaddr *)hostAddress);
+    
+    if (reachability != NULL)
+    {
+        returnReachability = [[self alloc] init];
+        if (returnReachability != NULL)
+        {
+            returnReachability.networkReachabilityRef = reachability;
+            [returnReachability startNotifier];
+        }
+    }
+    
+    return returnReachability;
+}
+
+- (BOOL)startNotifier
+{
+    BOOL started = NO;
+    
+    SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, 
NULL, NULL};
+    
+    if (SCNetworkReachabilitySetCallback(self.networkReachabilityRef, 
ReachabilityChangedCallback, &context))
+    {
+        if 
(SCNetworkReachabilityScheduleWithRunLoop(self.networkReachabilityRef, 
CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
+        {
+            started = YES;
+        }
+    }
+    
+    return started;
+}
+
+- (BOOL)stopNotifier
+{
+    BOOL stopped = NO;
+    
+    if (self.networkReachabilityRef != NULL)
+    {
+        
SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachabilityRef, 
CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+    }
+    
+    return stopped;
+}
+
+@end


Reply via email to