adium-1.4 2636:f8d77bb2192d: Add an observer for both AF_INET (I...

commits at adium.im commits at adium.im
Sat Oct 24 15:33:00 UTC 2009


details:	http://hg.adium.im/adium-1.4/rev/f8d77bb2192d
revision:	2636:f8d77bb2192d
author:		Zachary West <zacw at adium.im>
date:		Sat Oct 24 11:32:51 2009 -0400

Add an observer for both AF_INET (IPv4) and AF_INET6 (IPv6) DNS records for connection hosts. Fixes #12632.

When we're determining reachability, we consult all entries for a host, instead of the one that changed. We only add one observer for each record type.

diffs (144 lines):

diff -r 08e3f43120bb -r f8d77bb2192d Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m
--- a/Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m	Tue Oct 20 23:07:17 2009 -0400
+++ b/Frameworks/AIUtilities Framework/Source/AIHostReachabilityMonitor.m	Sat Oct 24 11:32:51 2009 -0400
@@ -198,7 +198,7 @@
  * @param reachability The SCNetworkReachabilityRef for the host which changed
  * @param isReachable YES if the host is now reachable; NO if it is not reachable
  */
-- (void)reachability:(SCNetworkReachabilityRef)reachability changedToReachable:(BOOL)isReachable
+- (void)reachabilityChanged:(SCNetworkReachabilityRef)reachability
 {
 	[hostAndObserverListLock lock];
 
@@ -207,7 +207,26 @@
 		NSString *host = [hosts objectAtIndex:i];
 		id <AIHostReachabilityObserver> observer = [observers objectAtIndex:i];
 		
-		if (isReachable) {
+		BOOL anyHostsReachable = NO;
+		
+		// If we have multiple host <-> IP links (AAAA record and an A record), we need to check agreement.
+		for (NSUInteger index = 0; index < hosts.count; index++) {
+			if (![host isEqualToString:[hosts objectAtIndex:index]])
+				continue;
+			
+			SCNetworkReachabilityRef otherReachability = (SCNetworkReachabilityRef)[reachabilities objectAtIndex:index];
+			SCNetworkConnectionFlags flags;
+
+			if (SCNetworkReachabilityGetFlags(otherReachability, &flags)
+				&& (flags & kSCNetworkFlagsReachable)
+				&& !(flags & kSCNetworkFlagsConnectionRequired)) {
+				anyHostsReachable = YES;
+				break;
+			}
+		}
+		
+		// Return reachability based on any reachability response.
+		if (anyHostsReachable) {
 			[observer hostReachabilityMonitor:self hostIsReachable:host];
 		} else {
 			[observer hostReachabilityMonitor:self hostIsNotReachable:host];
@@ -224,9 +243,6 @@
  */
 static void hostReachabilityChangedCallback(SCNetworkReachabilityRef target, SCNetworkConnectionFlags flags, void *info)
 {
-	BOOL reachable =  (flags & kSCNetworkFlagsReachable)			&&
-					 !(flags & kSCNetworkFlagsConnectionRequired);
-
 #if CONNECTIVITY_DEBUG
 	NSLog(@"*** hostReachabilityChangedCallback got flags: %c%c%c%c%c%c%c \n",  
  	      (flags & kSCNetworkFlagsTransientConnection)  ? 't' : '-',  
@@ -237,9 +253,9 @@
  	      (flags & kSCNetworkFlagsIsLocalAddress)       ? 'l' : '-',  
  	      (flags & kSCNetworkFlagsIsDirect)             ? 'd' : '-');
 #endif
-
+	
 	AIHostReachabilityMonitor *self = info;
-	[self reachability:target changedToReachable:reachable];
+	[self reachabilityChanged:target];
 }
 
 /*
@@ -255,8 +271,34 @@
 	NSString					*host = [infoDict objectForKey:@"host"];
 
 	if (typeInfo == kCFHostAddresses) {
+		//CFHostGetAddressing returns a CFArrayRef of CFDataRefs which wrap struct sockaddr
 		CFArrayRef addresses = CFHostGetAddressing(theHost, NULL);
-		if (addresses && CFArrayGetCount(addresses)) {
+		
+		if (!CFArrayGetCount(addresses)) {
+			/* We were not able to resolve the host name to an IP address.  This is most likely because we have no
+			 * Internet connection or because the user is attempting to connect to MSN.
+			 *
+			 * Add to unconfiguredHostsAndObservers so we can try configuring again later.
+			 */
+			[self addUnconfiguredHost:host
+							 observer:observer];
+		}
+		
+		// Only add 1 observer for IPv6 and one for IPv4.
+		BOOL addedIPv4 = NO, addedIPv6 = NO;
+		
+		for (NSData *saData in (NSArray *)addresses) {
+			struct sockaddr							*remoteAddr = (struct sockaddr *)saData.bytes;
+			
+			if ((remoteAddr->sa_family == AF_INET && addedIPv4) || (remoteAddr->sa_family == AF_INET6 && addedIPv6)) {
+				continue;
+			}
+			
+			if (remoteAddr->sa_family == AF_INET)
+				addedIPv4 = YES;
+			if (remoteAddr->sa_family == AF_INET6)
+				addedIPv6 = YES;
+						
 			SCNetworkReachabilityRef		reachabilityRef;
 			SCNetworkReachabilityContext	reachabilityContext = {
 				.version         = 0,
@@ -267,7 +309,6 @@
 			};
 			SCNetworkConnectionFlags				flags;
 			struct sockaddr_in						localAddr;
-			struct sockaddr							*remoteAddr;
 			
 			/* Create a reachability reference pair with localhost and the remote host */
 			
@@ -277,10 +318,6 @@
 			localAddr.sin_family = AF_INET;
 			inet_aton("127.0.0.1", &localAddr.sin_addr);
 			
-			//CFHostGetAddressing returns a CFArrayRef of CFDataRefs which wrap struct sockaddr
-			CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, 0);
-			remoteAddr = (struct sockaddr *)CFDataGetBytePtr(saData);
-			
 			//Create the pair
 			reachabilityRef = SCNetworkReachabilityCreateWithAddressPair(NULL, 
 																		 (struct sockaddr *)&localAddr, 
@@ -303,9 +340,9 @@
 
 			if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {
 				//We already have valid flags for the reachabilityRef
-#if CONNECTIVITY_DEBUG
+		#if CONNECTIVITY_DEBUG
 				NSLog(@"Immediate reachability info for %@", reachabilityRef);
-#endif
+		#endif
 				hostReachabilityChangedCallback(reachabilityRef,
 												flags,
 												self);
@@ -335,14 +372,6 @@
 										  NULL);
 			}
 
-		} else {
-			/* We were not able to resolve the host name to an IP address.  This is most likely because we have no
-			* Internet connection or because the user is attempting to connect to MSN.
-			*
-			* Add to unconfiguredHostsAndObservers so we can try configuring again later.
-			*/
-			[self addUnconfiguredHost:host
-							 observer:observer];
 		}
 		
 	} else if (typeInfo == kCFHostReachability) {




More information about the commits mailing list