1.1 --- a/Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m Tue May 12 17:50:21 2009 -0700
1.2 +++ b/Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m Sat Oct 24 11:32:51 2009 -0400
1.3 @@ -198,7 +198,7 @@
1.4 * @param reachability The SCNetworkReachabilityRef for the host which changed
1.5 * @param isReachable YES if the host is now reachable; NO if it is not reachable
1.6 */
1.7 -- (void)reachability:(SCNetworkReachabilityRef)reachability changedToReachable:(BOOL)isReachable
1.8 +- (void)reachabilityChanged:(SCNetworkReachabilityRef)reachability
1.9 {
1.10 [hostAndObserverListLock lock];
1.11
1.12 @@ -207,7 +207,26 @@
1.13 NSString *host = [hosts objectAtIndex:i];
1.14 id <AIHostReachabilityObserver> observer = [observers objectAtIndex:i];
1.15
1.16 - if (isReachable) {
1.17 + BOOL anyHostsReachable = NO;
1.18 +
1.19 + // If we have multiple host <-> IP links (AAAA record and an A record), we need to check agreement.
1.20 + for (NSUInteger index = 0; index < hosts.count; index++) {
1.21 + if (![host isEqualToString:[hosts objectAtIndex:index]])
1.22 + continue;
1.23 +
1.24 + SCNetworkReachabilityRef otherReachability = (SCNetworkReachabilityRef)[reachabilities objectAtIndex:index];
1.25 + SCNetworkConnectionFlags flags;
1.26 +
1.27 + if (SCNetworkReachabilityGetFlags(otherReachability, &flags)
1.28 + && (flags & kSCNetworkFlagsReachable)
1.29 + && !(flags & kSCNetworkFlagsConnectionRequired)) {
1.30 + anyHostsReachable = YES;
1.31 + break;
1.32 + }
1.33 + }
1.34 +
1.35 + // Return reachability based on any reachability response.
1.36 + if (anyHostsReachable) {
1.37 [observer hostReachabilityMonitor:self hostIsReachable:host];
1.38 } else {
1.39 [observer hostReachabilityMonitor:self hostIsNotReachable:host];
1.40 @@ -224,9 +243,6 @@
1.41 */
1.42 static void hostReachabilityChangedCallback(SCNetworkReachabilityRef target, SCNetworkConnectionFlags flags, void *info)
1.43 {
1.44 - BOOL reachable = (flags & kSCNetworkFlagsReachable) &&
1.45 - !(flags & kSCNetworkFlagsConnectionRequired);
1.46 -
1.47 #if CONNECTIVITY_DEBUG
1.48 NSLog(@"*** hostReachabilityChangedCallback got flags: %c%c%c%c%c%c%c \n",
1.49 (flags & kSCNetworkFlagsTransientConnection) ? 't' : '-',
1.50 @@ -237,9 +253,9 @@
1.51 (flags & kSCNetworkFlagsIsLocalAddress) ? 'l' : '-',
1.52 (flags & kSCNetworkFlagsIsDirect) ? 'd' : '-');
1.53 #endif
1.54 -
1.55 +
1.56 AIHostReachabilityMonitor *self = info;
1.57 - [self reachability:target changedToReachable:reachable];
1.58 + [self reachabilityChanged:target];
1.59 }
1.60
1.61 /*
1.62 @@ -255,8 +271,34 @@
1.63 NSString *host = [infoDict objectForKey:@"host"];
1.64
1.65 if (typeInfo == kCFHostAddresses) {
1.66 + //CFHostGetAddressing returns a CFArrayRef of CFDataRefs which wrap struct sockaddr
1.67 CFArrayRef addresses = CFHostGetAddressing(theHost, NULL);
1.68 - if (addresses && CFArrayGetCount(addresses)) {
1.69 +
1.70 + if (!CFArrayGetCount(addresses)) {
1.71 + /* We were not able to resolve the host name to an IP address. This is most likely because we have no
1.72 + * Internet connection or because the user is attempting to connect to MSN.
1.73 + *
1.74 + * Add to unconfiguredHostsAndObservers so we can try configuring again later.
1.75 + */
1.76 + [self addUnconfiguredHost:host
1.77 + observer:observer];
1.78 + }
1.79 +
1.80 + // Only add 1 observer for IPv6 and one for IPv4.
1.81 + BOOL addedIPv4 = NO, addedIPv6 = NO;
1.82 +
1.83 + for (NSData *saData in (NSArray *)addresses) {
1.84 + struct sockaddr *remoteAddr = (struct sockaddr *)saData.bytes;
1.85 +
1.86 + if ((remoteAddr->sa_family == AF_INET && addedIPv4) || (remoteAddr->sa_family == AF_INET6 && addedIPv6)) {
1.87 + continue;
1.88 + }
1.89 +
1.90 + if (remoteAddr->sa_family == AF_INET)
1.91 + addedIPv4 = YES;
1.92 + if (remoteAddr->sa_family == AF_INET6)
1.93 + addedIPv6 = YES;
1.94 +
1.95 SCNetworkReachabilityRef reachabilityRef;
1.96 SCNetworkReachabilityContext reachabilityContext = {
1.97 .version = 0,
1.98 @@ -267,7 +309,6 @@
1.99 };
1.100 SCNetworkConnectionFlags flags;
1.101 struct sockaddr_in localAddr;
1.102 - struct sockaddr *remoteAddr;
1.103
1.104 /* Create a reachability reference pair with localhost and the remote host */
1.105
1.106 @@ -277,10 +318,6 @@
1.107 localAddr.sin_family = AF_INET;
1.108 inet_aton("127.0.0.1", &localAddr.sin_addr);
1.109
1.110 - //CFHostGetAddressing returns a CFArrayRef of CFDataRefs which wrap struct sockaddr
1.111 - CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, 0);
1.112 - remoteAddr = (struct sockaddr *)CFDataGetBytePtr(saData);
1.113 -
1.114 //Create the pair
1.115 reachabilityRef = SCNetworkReachabilityCreateWithAddressPair(NULL,
1.116 (struct sockaddr *)&localAddr,
1.117 @@ -303,9 +340,9 @@
1.118
1.119 if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {
1.120 //We already have valid flags for the reachabilityRef
1.121 -#if CONNECTIVITY_DEBUG
1.122 + #if CONNECTIVITY_DEBUG
1.123 NSLog(@"Immediate reachability info for %@", reachabilityRef);
1.124 -#endif
1.125 + #endif
1.126 hostReachabilityChangedCallback(reachabilityRef,
1.127 flags,
1.128 self);
1.129 @@ -335,14 +372,6 @@
1.130 NULL);
1.131 }
1.132
1.133 - } else {
1.134 - /* We were not able to resolve the host name to an IP address. This is most likely because we have no
1.135 - * Internet connection or because the user is attempting to connect to MSN.
1.136 - *
1.137 - * Add to unconfiguredHostsAndObservers so we can try configuring again later.
1.138 - */
1.139 - [self addUnconfiguredHost:host
1.140 - observer:observer];
1.141 }
1.142
1.143 } else if (typeInfo == kCFHostReachability) {