48 #import <sys/socket.h>
49 #import <netinet/in.h>
50 #import <netinet6/in6.h>
55 #import <CoreFoundation/CoreFoundation.h>
57 #import "Reachability.h"
59 #define kShouldPrintReachabilityFlags 1
61 static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags,
const char *comment)
63 #if kShouldPrintReachabilityFlags
65 NSLog(
@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
66 (flags & kSCNetworkReachabilityFlagsIsWWAN) ?
'W' :
'-',
67 (flags & kSCNetworkReachabilityFlagsReachable) ?
'R' :
'-',
69 (flags & kSCNetworkReachabilityFlagsTransientConnection) ?
't' :
'-',
70 (flags & kSCNetworkReachabilityFlagsConnectionRequired) ?
'c' :
'-',
71 (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ?
'C' :
'-',
72 (flags & kSCNetworkReachabilityFlagsInterventionRequired) ?
'i' :
'-',
73 (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ?
'D' :
'-',
74 (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ?
'l' :
'-',
75 (flags & kSCNetworkReachabilityFlagsIsDirect) ?
'd' :
'-', comment);
80 static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,
83 #pragma unused(target, flags)
84 NSCAssert(info != NULL,
@"info was NULL in ReachabilityCallback");
85 NSCAssert([(NSObject *)info isKindOfClass:[
Reachability class]],
86 @"info was wrong class in ReachabilityCallback");
90 NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
94 [[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
100 - (BOOL)startNotifier
103 SCNetworkReachabilityContext context = { 0,
self, NULL, NULL, NULL };
104 if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
106 if (SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(),
107 kCFRunLoopDefaultMode))
117 if (reachabilityRef != NULL)
119 SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(),
120 kCFRunLoopDefaultMode);
127 if (reachabilityRef != NULL)
129 CFRelease(reachabilityRef);
134 + (
Reachability *)reachabilityWithHostName:(NSString *)hostName;
137 SCNetworkReachabilityRef reachability =
138 SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
139 if (reachability != NULL)
141 retVal = [[[
self alloc] init] autorelease];
144 retVal->reachabilityRef = reachability;
145 retVal->localWiFiRef = NO;
151 + (
Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
153 SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(
154 kCFAllocatorDefault, (
const struct sockaddr *)hostAddress);
156 if (reachability != NULL)
158 retVal = [[[
self alloc] init] autorelease];
161 retVal->reachabilityRef = reachability;
162 retVal->localWiFiRef = NO;
170 struct sockaddr_in zeroAddress;
171 bzero(&zeroAddress,
sizeof(zeroAddress));
172 zeroAddress.sin_len =
sizeof(zeroAddress);
173 zeroAddress.sin_family = AF_INET;
174 return [
self reachabilityWithAddress:&zeroAddress];
179 struct sockaddr_in localWifiAddress;
180 bzero(&localWifiAddress,
sizeof(localWifiAddress));
181 localWifiAddress.sin_len =
sizeof(localWifiAddress);
182 localWifiAddress.sin_family = AF_INET;
184 localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
185 Reachability *retVal = [
self reachabilityWithAddress:&localWifiAddress];
188 retVal->localWiFiRef = YES;
193 #pragma mark Network Flag Handling
195 - (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
197 PrintReachabilityFlags(flags,
"localWiFiStatusForFlags");
199 BOOL retVal = NotReachable;
200 if ((flags & kSCNetworkReachabilityFlagsReachable) &&
201 (flags & kSCNetworkReachabilityFlagsIsDirect))
203 retVal = ReachableViaWiFi;
208 - (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
210 PrintReachabilityFlags(flags,
"networkStatusForFlags");
211 if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
217 BOOL retVal = NotReachable;
219 if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
223 retVal = ReachableViaWiFi;
226 if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0) ||
227 (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
232 if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
235 retVal = ReachableViaWiFi;
239 if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
243 retVal = ReachableViaWWAN;
248 - (BOOL)connectionRequired;
250 NSAssert(reachabilityRef != NULL,
@"connectionRequired called with NULL reachabilityRef");
251 SCNetworkReachabilityFlags flags;
252 if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
254 return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
259 - (NetworkStatus)currentReachabilityStatus
261 NSAssert(reachabilityRef != NULL,
@"currentNetworkStatus called with NULL reachabilityRef");
262 NetworkStatus retVal = NotReachable;
263 SCNetworkReachabilityFlags flags;
264 if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
268 retVal = [
self localWiFiStatusForFlags:flags];
272 retVal = [
self networkStatusForFlags:flags];