Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: ff59e564a6
Fetching contributors…

Cannot retrieve contributors at this time

273 lines (230 sloc) 8.289 kb
/*
Erica Sadun, http://ericasadun.com
iPhone Developer's Cookbook, 3.0 Edition
BSD License for anything not specifically marked as developed by a third party.
Apple's code excluded.
Use at your own risk
*/
#import <SystemConfiguration/SystemConfiguration.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <ifaddrs.h>
#import <dlfcn.h>
#import "UIDevice-Reachability.h"
@implementation UIDevice (Reachability)
SCNetworkConnectionFlags connectionFlags;
SCNetworkReachabilityRef reachability;
#pragma mark Class IP and Host Utilities
// This IP Utilities are mostly inspired by or derived from Apple code. Thank you Apple.
+ (NSString *) stringFromAddress: (const struct sockaddr *) address
{
if(address && address->sa_family == AF_INET) {
const struct sockaddr_in* sin = (struct sockaddr_in*) address;
return [NSString stringWithFormat:@"%@:%d", [NSString stringWithUTF8String:inet_ntoa(sin->sin_addr)], ntohs(sin->sin_port)];
}
return nil;
}
+ (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) {
NSAssert1(conversionResult != 1, @"Failed to convert the IP address string into a sockaddr_in: %@", IPAddress);
return NO;
}
return YES;
}
+ (NSString *) hostname
{
char baseHostName[256]; // Thanks, Gunnar Larisch
int success = gethostname(baseHostName, 255);
if (success != 0) return nil;
baseHostName[255] = '\0';
#if !TARGET_IPHONE_SIMULATOR
return [NSString stringWithFormat:@"%s.local", baseHostName];
#else
return [NSString stringWithFormat:@"%s", baseHostName];
#endif
}
+ (NSString *) getIPAddressForHost: (NSString *) theHost
{
struct hostent *host = gethostbyname([theHost UTF8String]);
if (!host) {herror("resolv"); return NULL; }
struct in_addr **list = (struct in_addr **)host->h_addr_list;
NSString *addressString = [NSString stringWithCString:inet_ntoa(*list[0]) encoding:NSUTF8StringEncoding];
return addressString;
}
+ (NSString *) localIPAddress
{
struct hostent *host = gethostbyname([[self hostname] UTF8String]);
if (!host) {herror("resolv"); return nil;}
struct in_addr **list = (struct in_addr **)host->h_addr_list;
return [NSString stringWithCString:inet_ntoa(*list[0]) encoding:NSUTF8StringEncoding];
}
// Matt Brown's get WiFi IP addy solution
// Author gave permission to use in Cookbook under cookbook license
// http://mattbsoftware.blogspot.com/2009/04/how-to-get-ip-address-of-iphone-os-v221.html
+ (NSString *) localWiFiIPAddress
{
BOOL success;
struct ifaddrs * addrs;
const struct ifaddrs * cursor;
success = getifaddrs(&addrs) == 0;
if (success) {
cursor = addrs;
while (cursor != NULL) {
// the second test keeps from picking up the loopback address
if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0)
{
NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
if ([name isEqualToString:@"en0"]) // Wi-Fi adapter
return [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)];
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return nil;
}
+ (NSString *) whatismyipdotcom
{
NSError *error;
NSURL *ipURL = [NSURL URLWithString:@"http://www.whatismyip.com/automation/n09230945.asp"];
NSString *ip = [NSString stringWithContentsOfURL:ipURL encoding:1 error:&error];
return ip ? ip : [error localizedDescription];
}
+ (BOOL) hostAvailable: (NSString *) theHost
{
NSString *addressString = [self getIPAddressForHost:theHost];
if (!addressString)
{
printf("Error recovering IP address from host name\n");
return NO;
}
struct sockaddr_in address;
BOOL gotAddress = [self addressFromString:addressString address:&address];
if (!gotAddress)
{
printf("Error recovering sockaddr address from %s\n", [addressString UTF8String]);
return NO;
}
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&address);
SCNetworkReachabilityFlags flags;
BOOL didRetrieveFlags =SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags)
{
printf("Error. Could not recover network reachability flags\n");
return NO;
}
BOOL isReachable = flags & kSCNetworkFlagsReachable;
return isReachable ? YES : NO;;
}
#pragma mark Checking Connections
+ (void) pingReachabilityInternal
{
if (!reachability)
{
BOOL ignoresAdHocWiFi = NO;
struct sockaddr_in ipAddress;
bzero(&ipAddress, sizeof(ipAddress));
ipAddress.sin_len = sizeof(ipAddress);
ipAddress.sin_family = AF_INET;
ipAddress.sin_addr.s_addr = htonl(ignoresAdHocWiFi ? INADDR_ANY : IN_LINKLOCALNETNUM);
/* Can also create zero addy
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET; */
reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&ipAddress);
CFRetain(reachability);
}
// Recover reachability flags
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(reachability, &connectionFlags);
if (!didRetrieveFlags) printf("Error. Could not recover network reachability flags\n");
}
+ (BOOL) networkAvailable
{
[self pingReachabilityInternal];
BOOL isReachable = ((connectionFlags & kSCNetworkFlagsReachable) != 0);
BOOL needsConnection = ((connectionFlags & kSCNetworkFlagsConnectionRequired) != 0);
return (isReachable && !needsConnection) ? YES : NO;
}
+ (BOOL) activeWWAN
{
if (![self networkAvailable]) return NO;
return ((connectionFlags & kSCNetworkReachabilityFlagsIsWWAN) != 0);
}
+ (BOOL) activeWLAN
{
return ([UIDevice localWiFiIPAddress] != nil);
}
#pragma mark WiFi Check and Alert
+ (void) showAlert: (id) formatstring,...
{
va_list arglist;
if (!formatstring) return;
va_start(arglist, formatstring);
id outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease];
va_end(arglist);
UIAlertView *av = [[[UIAlertView alloc] initWithTitle:outstring message:nil delegate:nil cancelButtonTitle:@"OK"otherButtonTitles:nil] autorelease];
[av show];
}
+ (BOOL) performWiFiCheck
{
if (![self networkAvailable] || ![self activeWLAN])
{
[self performSelector:@selector(showAlert:) withObject:@"This application requires WiFi. Please enable WiFi in Settings and run this application again." afterDelay:0.5f];
return NO;
}
return YES;
}
#pragma mark Monitoring reachability
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkConnectionFlags flags, void* info)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[(id)info performSelector:@selector(reachabilityChanged)];
[pool release];
}
+ (BOOL) scheduleReachabilityWatcher: (id) watcher
{
if (![watcher conformsToProtocol:@protocol(ReachabilityWatcher)])
{
NSLog(@"Watcher must conform to ReachabilityWatcher protocol. Cannot continue.");
return NO;
}
[self pingReachabilityInternal];
SCNetworkReachabilityContext context = {0, watcher, NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(reachability, ReachabilityCallback, &context))
{
if(!SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetCurrent(), kCFRunLoopCommonModes))
{
NSLog(@"Error: Could not schedule reachability");
SCNetworkReachabilitySetCallback(reachability, NULL, NULL);
return NO;
}
}
else
{
NSLog(@"Error: Could not set reachability callback");
return NO;
}
return YES;
}
+ (void) unscheduleReachabilityWatcher
{
SCNetworkReachabilitySetCallback(reachability, NULL, NULL);
if (SCNetworkReachabilityUnscheduleFromRunLoop(reachability, CFRunLoopGetCurrent(), kCFRunLoopCommonModes))
NSLog(@"Unscheduled reachability");
else
NSLog(@"Error: Could not unschedule reachability");
CFRelease(reachability);
reachability = nil;
}
@end
Jump to Line
Something went wrong with that request. Please try again.