Updated Reachability to handle an IP Address or a Host name
Note this does not fix the issue with the status not being correctly reported for a 3G connection.
This commit is contained in:
parent
ac20e02af3
commit
d96f8f3fde
1 changed files with 81 additions and 30 deletions
|
|
@ -208,6 +208,8 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
||||||
#ifdef _SYSTEMCONFIGURATION_H
|
#ifdef _SYSTEMCONFIGURATION_H
|
||||||
- (void)startMonitoringNetworkReachability;
|
- (void)startMonitoringNetworkReachability;
|
||||||
- (void)stopMonitoringNetworkReachability;
|
- (void)stopMonitoringNetworkReachability;
|
||||||
|
+ (AFNetworkReachabilityStatus)reachabilityStatusForFlags:(SCNetworkReachabilityFlags)flags;
|
||||||
|
+ (BOOL)addressFromString:(NSString *)IPAddress address:(struct sockaddr_in *)address;
|
||||||
#endif
|
#endif
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
@ -290,38 +292,14 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
||||||
|
|
||||||
#ifdef _SYSTEMCONFIGURATION_H
|
#ifdef _SYSTEMCONFIGURATION_H
|
||||||
static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
|
static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
|
||||||
BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
|
AFNetworkReachabilityStatus status = [AFHTTPClient reachabilityStatusForFlags:flags];
|
||||||
BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
|
|
||||||
BOOL isNetworkReachable = (isReachable && !needsConnection);
|
|
||||||
|
|
||||||
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusNotReachable;
|
|
||||||
if(isNetworkReachable == NO) {
|
|
||||||
status = AFNetworkReachabilityStatusNotReachable;
|
|
||||||
} else {
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
if((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0){
|
|
||||||
status = AFNetworkReachabilityStatusReachableViaWWAN;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sockaddr_in localWiFiAddress;
|
|
||||||
memset(&localWiFiAddress, '\0', sizeof(localWiFiAddress));
|
|
||||||
localWiFiAddress.sin_len = sizeof(localWiFiAddress);
|
|
||||||
localWiFiAddress.sin_family = AF_INET;
|
|
||||||
localWiFiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
|
|
||||||
|
|
||||||
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&localWiFiAddress);
|
|
||||||
if (reachability != NULL) {
|
|
||||||
status = AFNetworkReachabilityStatusReachableViaWiFi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;
|
AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;
|
||||||
if (block) {
|
if (block) {
|
||||||
block(status);
|
block(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithBool:status]];
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithInt:status]];
|
||||||
}
|
}
|
||||||
|
|
||||||
static const void * AFReachabilityRetainCallback(const void *info) {
|
static const void * AFReachabilityRetainCallback(const void *info) {
|
||||||
|
|
@ -334,7 +312,23 @@ static void AFReachabilityReleaseCallback(const void *info) {
|
||||||
|
|
||||||
- (void)startMonitoringNetworkReachability {
|
- (void)startMonitoringNetworkReachability {
|
||||||
[self stopMonitoringNetworkReachability];
|
[self stopMonitoringNetworkReachability];
|
||||||
|
|
||||||
|
//In order to handle all Reachability cases, we must determine if the Host URL is an IP Address
|
||||||
|
//or a Host Name. We must then use the appropriate SCNetworkReachabilityCreateWith... function
|
||||||
|
//based on the result.
|
||||||
|
NSString * ipMatch = @"^[0-9]{1,3}(.[0-9]{1,3}){3}$";
|
||||||
|
NSRegularExpression *ipRegex = [NSRegularExpression regularExpressionWithPattern:ipMatch options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
|
||||||
|
BOOL isIPAddress = [ipRegex numberOfMatchesInString:[self.baseURL host] options:NSMatchingReportProgress range:NSMakeRange(0, [[self.baseURL host] length])];
|
||||||
|
|
||||||
|
if(isIPAddress == YES){
|
||||||
|
struct sockaddr_in address;
|
||||||
|
[AFHTTPClient addressFromString:[self.baseURL host] address:&address];
|
||||||
|
self.networkReachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&address);
|
||||||
|
}
|
||||||
|
else {
|
||||||
self.networkReachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [[self.baseURL host] UTF8String]);
|
self.networkReachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [[self.baseURL host] UTF8String]);
|
||||||
|
}
|
||||||
|
|
||||||
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status){
|
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status){
|
||||||
self.networkReachabilityStatus = status;
|
self.networkReachabilityStatus = status;
|
||||||
|
|
@ -342,9 +336,22 @@ static void AFReachabilityReleaseCallback(const void *info) {
|
||||||
self.networkReachabilityStatusBlock(status);
|
self.networkReachabilityStatusBlock(status);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SCNetworkReachabilityContext context = {0, callback, AFReachabilityRetainCallback, AFReachabilityReleaseCallback, NULL};
|
SCNetworkReachabilityContext context = {0, callback, AFReachabilityRetainCallback, AFReachabilityReleaseCallback, NULL};
|
||||||
SCNetworkReachabilitySetCallback(self.networkReachability, AFReachabilityCallback, &context);
|
SCNetworkReachabilitySetCallback(self.networkReachability, AFReachabilityCallback, &context);
|
||||||
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
|
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
|
||||||
|
|
||||||
|
if(isIPAddress == YES){
|
||||||
|
//For SCNetworkReachabilityCreateWithAddress, the callback block is not immediately called.
|
||||||
|
//In order to duplicate the immediate callback behavior of SCNetworkReachabilityCreateWithName,
|
||||||
|
//we must pull the current status, and then manually call the block
|
||||||
|
SCNetworkReachabilityFlags flags;
|
||||||
|
SCNetworkReachabilityGetFlags(self.networkReachability, &flags);
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
AFNetworkReachabilityStatus status = [AFHTTPClient reachabilityStatusForFlags:flags];
|
||||||
|
callback(status);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stopMonitoringNetworkReachability {
|
- (void)stopMonitoringNetworkReachability {
|
||||||
|
|
@ -354,9 +361,53 @@ static void AFReachabilityReleaseCallback(const void *info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (AFNetworkReachabilityStatus)reachabilityStatusForFlags:(SCNetworkReachabilityFlags)flags{
|
||||||
|
BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
|
||||||
|
BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
|
||||||
|
BOOL isNetworkReachable = (isReachable && !needsConnection);
|
||||||
|
|
||||||
|
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusNotReachable;
|
||||||
|
if(isNetworkReachable == NO) {
|
||||||
|
status = AFNetworkReachabilityStatusNotReachable;
|
||||||
|
} else {
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
if((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0){
|
||||||
|
status = AFNetworkReachabilityStatusReachableViaWWAN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sockaddr_in localWiFiAddress;
|
||||||
|
memset(&localWiFiAddress, '\0', sizeof(localWiFiAddress));
|
||||||
|
localWiFiAddress.sin_len = sizeof(localWiFiAddress);
|
||||||
|
localWiFiAddress.sin_family = AF_INET;
|
||||||
|
localWiFiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
|
||||||
|
|
||||||
|
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&localWiFiAddress);
|
||||||
|
if (reachability != NULL) {
|
||||||
|
status = AFNetworkReachabilityStatusReachableViaWiFi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)addressFromString:(NSString *)IPAddress address:(struct sockaddr_in *)address{
|
||||||
|
if (!IPAddress || ![IPAddress length]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((char *) address, sizeof(struct sockaddr_in), 0);
|
||||||
|
address->sin_family = AF_INET;
|
||||||
|
address->sin_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
int conversionResult = inet_aton([IPAddress UTF8String], &address->sin_addr);
|
||||||
|
if (conversionResult == 0) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block {
|
- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block {
|
||||||
self.networkReachabilityStatusBlock = block;
|
self.networkReachabilityStatusBlock = block;
|
||||||
[self startMonitoringNetworkReachability];
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue