| author | Zachary West <zacw@adium.im> |
| Sat Oct 24 11:32:51 2009 -0400 (2009-10-24) | |
| changeset 2636 | f8d77bb2192d |
| parent 2635 | 08e3f43120bb |
| child 2637 | b6baa3290a42 |
| Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m | file | annotate | diff | revisions |
1.1 --- a/Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m Tue Oct 20 23:07:17 2009 -0400 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) {