-
-
Save darkseed/1182373 to your computer and use it in GitHub Desktop.
/* | |
File: Reachability.h | |
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. | |
Version: 2.2 - ARCified | |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. | |
("Apple") in consideration of your agreement to the following terms, and your | |
use, installation, modification or redistribution of this Apple software | |
constitutes acceptance of these terms. If you do not agree with these terms, | |
please do not use, install, modify or redistribute this Apple software. | |
In consideration of your agreement to abide by the following terms, and subject | |
to these terms, Apple grants you a personal, non-exclusive license, under | |
Apple's copyrights in this original Apple software (the "Apple Software"), to | |
use, reproduce, modify and redistribute the Apple Software, with or without | |
modifications, in source and/or binary forms; provided that if you redistribute | |
the Apple Software in its entirety and without modifications, you must retain | |
this notice and the following text and disclaimers in all such redistributions | |
of the Apple Software. | |
Neither the name, trademarks, service marks or logos of Apple Inc. may be used | |
to endorse or promote products derived from the Apple Software without specific | |
prior written permission from Apple. Except as expressly stated in this notice, | |
no other rights or licenses, express or implied, are granted by Apple herein, | |
including but not limited to any patent rights that may be infringed by your | |
derivative works or by other works in which the Apple Software may be | |
incorporated. | |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | |
COMBINATION WITH YOUR PRODUCTS. | |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR | |
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF | |
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF | |
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
Copyright (C) 2010 Apple Inc. All Rights Reserved. | |
*/ | |
#import <Foundation/Foundation.h> | |
#import <SystemConfiguration/SystemConfiguration.h> | |
struct sockaddr_in; | |
typedef enum { | |
NotReachable = 0, | |
ReachableViaWiFi, | |
ReachableViaWWAN | |
} NetworkStatus; | |
#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" | |
@interface Reachability: NSObject | |
//reachabilityWithHostName- Use to check the reachability of a particular host name. | |
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName; | |
//reachabilityWithAddress- Use to check the reachability of a particular IP address. | |
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; | |
//reachabilityForInternetConnection- checks whether the default route is available. | |
// Should be used by applications that do not connect to a particular host | |
+ (Reachability*) reachabilityForInternetConnection; | |
//reachabilityForLocalWiFi- checks whether a local wifi connection is available. | |
+ (Reachability*) reachabilityForLocalWiFi; | |
//Start listening for reachability notifications on the current run loop | |
- (BOOL) startNotifier; | |
- (void) stopNotifier; | |
- (NetworkStatus) currentReachabilityStatus; | |
//WWAN may be available, but not active until a connection has been established. | |
//WiFi may require a connection for VPN on Demand. | |
- (BOOL) connectionRequired; | |
@end | |
/* | |
File: Reachability.m | |
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. | |
Version: 2.2 - ARCified | |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. | |
("Apple") in consideration of your agreement to the following terms, and your | |
use, installation, modification or redistribution of this Apple software | |
constitutes acceptance of these terms. If you do not agree with these terms, | |
please do not use, install, modify or redistribute this Apple software. | |
In consideration of your agreement to abide by the following terms, and subject | |
to these terms, Apple grants you a personal, non-exclusive license, under | |
Apple's copyrights in this original Apple software (the "Apple Software"), to | |
use, reproduce, modify and redistribute the Apple Software, with or without | |
modifications, in source and/or binary forms; provided that if you redistribute | |
the Apple Software in its entirety and without modifications, you must retain | |
this notice and the following text and disclaimers in all such redistributions | |
of the Apple Software. | |
Neither the name, trademarks, service marks or logos of Apple Inc. may be used | |
to endorse or promote products derived from the Apple Software without specific | |
prior written permission from Apple. Except as expressly stated in this notice, | |
no other rights or licenses, express or implied, are granted by Apple herein, | |
including but not limited to any patent rights that may be infringed by your | |
derivative works or by other works in which the Apple Software may be | |
incorporated. | |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | |
COMBINATION WITH YOUR PRODUCTS. | |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR | |
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF | |
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF | |
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
Copyright (C) 2010 Apple Inc. All Rights Reserved. | |
*/ | |
#import <sys/socket.h> | |
#import <netinet/in.h> | |
#import <netinet6/in6.h> | |
#import <arpa/inet.h> | |
#import <ifaddrs.h> | |
#import <netdb.h> | |
#import <CoreFoundation/CoreFoundation.h> | |
#import "Reachability.h" | |
//#define kShouldPrintReachabilityFlags 1 | |
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) | |
{ | |
#if kShouldPrintReachabilityFlags | |
NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", | |
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', | |
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', | |
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', | |
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', | |
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', | |
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', | |
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', | |
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', | |
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', | |
comment | |
); | |
#endif | |
} | |
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) | |
{ | |
#pragma unused (target, flags) | |
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); | |
NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); | |
//We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively | |
// in case someon uses the Reachablity object in a different thread. | |
@autoreleasepool { | |
Reachability* noteObject = (__bridge Reachability*) info; | |
// Post a notification to notify the client that the network reachability changed. | |
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; | |
} | |
} | |
@implementation Reachability | |
{ | |
BOOL localWiFiRef; | |
SCNetworkReachabilityRef reachabilityRef; | |
} | |
- (BOOL)startNotifier | |
{ | |
BOOL retVal = NO; | |
SCNetworkReachabilityContext context = {0, (__bridge void *)self, NULL, NULL, NULL}; | |
if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) | |
{ | |
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode)) // DFH CFRunLoopGetCurrent() | |
{ | |
retVal = YES; | |
} | |
} | |
return retVal; | |
} | |
- (void)stopNotifier | |
{ | |
if(reachabilityRef != NULL) | |
{ | |
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode); // CFRunLoopGetCurrent() | |
} | |
} | |
- (void) dealloc | |
{ | |
[self stopNotifier]; | |
if(reachabilityRef!= NULL) | |
{ | |
CFRelease(reachabilityRef); | |
} | |
} | |
+ (Reachability*)reachabilityWithHostName: (NSString*) hostName; | |
{ | |
Reachability* retVal = NULL; | |
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); | |
if(reachability!= NULL) | |
{ | |
retVal= [[self alloc] init]; | |
if(retVal!= NULL) | |
{ | |
retVal->reachabilityRef = reachability; | |
retVal->localWiFiRef = NO; | |
} | |
} | |
return retVal; | |
} | |
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; | |
{ | |
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); | |
Reachability* retVal = NULL; | |
if(reachability!= NULL) | |
{ | |
retVal= [[self alloc] init]; | |
if(retVal!= NULL) | |
{ | |
retVal->reachabilityRef = reachability; | |
retVal->localWiFiRef = NO; | |
} | |
} | |
return retVal; | |
} | |
+ (Reachability*) reachabilityForInternetConnection; | |
{ | |
struct sockaddr_in zeroAddress; | |
bzero(&zeroAddress, sizeof(zeroAddress)); | |
zeroAddress.sin_len = sizeof(zeroAddress); | |
zeroAddress.sin_family = AF_INET; | |
return [self reachabilityWithAddress: &zeroAddress]; | |
} | |
+ (Reachability*) reachabilityForLocalWiFi; | |
{ | |
struct sockaddr_in localWifiAddress; | |
bzero(&localWifiAddress, sizeof(localWifiAddress)); | |
localWifiAddress.sin_len = sizeof(localWifiAddress); | |
localWifiAddress.sin_family = AF_INET; | |
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 | |
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); | |
Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; | |
if(retVal!= NULL) | |
{ | |
retVal->localWiFiRef = YES; | |
} | |
return retVal; | |
} | |
#pragma mark Network Flag Handling | |
- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags | |
{ | |
PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); | |
BOOL retVal = NotReachable; | |
if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) | |
{ | |
retVal = ReachableViaWiFi; | |
} | |
return retVal; | |
} | |
- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags | |
{ | |
PrintReachabilityFlags(flags, "networkStatusForFlags"); | |
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) | |
{ | |
// if target host is not reachable | |
return NotReachable; | |
} | |
BOOL retVal = NotReachable; | |
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) | |
{ | |
// if target host is reachable and no connection is required | |
// then we'll assume (for now) that your on Wi-Fi | |
retVal = ReachableViaWiFi; | |
} | |
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || | |
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) | |
{ | |
// ... and the connection is on-demand (or on-traffic) if the | |
// calling application is using the CFSocketStream or higher APIs | |
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) | |
{ | |
// ... and no [user] intervention is needed | |
retVal = ReachableViaWiFi; | |
} | |
} | |
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) | |
{ | |
// ... but WWAN connections are OK if the calling application | |
// is using the CFNetwork (CFSocketStream?) APIs. | |
retVal = ReachableViaWWAN; | |
} | |
return retVal; | |
} | |
- (BOOL)connectionRequired; | |
{ | |
NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); | |
SCNetworkReachabilityFlags flags; | |
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) | |
{ | |
return (flags & kSCNetworkReachabilityFlagsConnectionRequired); | |
} | |
return NO; | |
} | |
- (NetworkStatus)currentReachabilityStatus | |
{ | |
NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); | |
NetworkStatus retVal = NotReachable; | |
SCNetworkReachabilityFlags flags; | |
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) | |
{ | |
if(localWiFiRef) | |
{ | |
retVal = [self localWiFiStatusForFlags: flags]; | |
} | |
else | |
{ | |
retVal = [self networkStatusForFlags: flags]; | |
} | |
} | |
return retVal; | |
} | |
@end |
Thanks a lot for your work! I was disappointed with iOS5 & Reachability :s
Just a little remark:
When you write that: retVal= [[self alloc] init];
(lines 139 & 155)
there are potential leaks, no?
Corrected with an autorelease for example.
It's meant to be used with ARC. ARC will automatically release retVal.
Sorry, I was passed over the ARCified, tired... :)
No worries!
Thanks!
This one looks great too: https://github.com/tonymillion/Reachability
In the callback method,
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info),
why aren't the flags used? Can't we just stuff it into the Reachability object instead of doing another call SCNetworkReachabilityGetFlags when we wish to determine the network status?
Thanks :)
Thanks! Great!
Good Work!
Thanks!
Thanks, it saved time
Thanks, It saved me.... ;)
Thanks, It saved me.... ;)
Has anyone encountered SIGPIPE terminations caused by this code?
Thanks loads for this!!!!!!!