From d7a235a65e829223521738d675148c64a7de577e Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Wed, 6 Oct 2010 19:55:06 -0700 Subject: [PATCH] Apple's Reachability code is ludicrously complex (and APSL). --- Cydia.mm | 26 +++-- Reachability.h | 88 ---------------- Reachability.mm | 273 ------------------------------------------------ makefile | 2 +- 4 files changed, 21 insertions(+), 368 deletions(-) delete mode 100644 Reachability.h delete mode 100644 Reachability.mm diff --git a/Cydia.mm b/Cydia.mm index 8f42c6de..090823dd 100644 --- a/Cydia.mm +++ b/Cydia.mm @@ -59,6 +59,8 @@ #include #include +#include + #include #include "iPhonePrivate.h" @@ -121,9 +123,6 @@ extern "C" { #include "UICaboodle/BrowserView.h" #include "substrate.h" - -// Apple's sample Reachability code, ASPL licensed. -#include "Reachability.h" /* }}} */ /* Profiler {{{ */ @@ -7972,10 +7971,25 @@ static _finline void _setHomePage(Cydia *self) { - (void) _refreshIfPossible { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - Reachability* reachability = [Reachability reachabilityWithHostName:@"cydia.saurik.com"]; - NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus]; + SCNetworkReachabilityFlags flags; { + SCNetworkReachabilityRef reachability(SCNetworkReachabilityCreateWithName(NULL, "cydia.saurik.com")); + SCNetworkReachabilityGetFlags(reachability, &flags); + CFRelease(reachability); + } + + // XXX: this elaborate mess is what Apple is using to determine this? :( + // XXX: do we care if the user has to intervene? maybe that's ok? + bool reachable( + (flags & kSCNetworkReachabilityFlagsReachable) != 0 && ( + (flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0 || ( + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0 || + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0 + ) && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0 || + (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0 + ) + ); - if (loaded_ || ManualRefresh || remoteHostStatus == NotReachable) loaded: + if (loaded_ || ManualRefresh || !reachable) loaded: [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO]; else { loaded_ = true; diff --git a/Reachability.h b/Reachability.h deleted file mode 100644 index 317982fb..00000000 --- a/Reachability.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - - File: Reachability.h - Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. - - Version: 2.2 - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. - ("Apple") in consideration of your agreement to the following terms, and your - use, installation, modification or redistribution of this Apple software - constitutes acceptance of these terms. If you do not agree with these terms, - please do not use, install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject - to these terms, Apple grants you a personal, non-exclusive license, under - Apple's copyrights in this original Apple software (the "Apple Software"), to - use, reproduce, modify and redistribute the Apple Software, with or without - modifications, in source and/or binary forms; provided that if you redistribute - the Apple Software in its entirety and without modifications, you must retain - this notice and the following text and disclaimers in all such redistributions - of the Apple Software. - Neither the name, trademarks, service marks or logos of Apple Inc. may be used - to endorse or promote products derived from the Apple Software without specific - prior written permission from Apple. Except as expressly stated in this notice, - no other rights or licenses, express or implied, are granted by Apple herein, - including but not limited to any patent rights that may be infringed by your - derivative works or by other works in which the Apple Software may be - incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR - DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF - CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF - APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Copyright (C) 2010 Apple Inc. All Rights Reserved. - -*/ - - -#import -#import - -typedef enum { - NotReachable = 0, - ReachableViaWiFi, - ReachableViaWWAN -} NetworkStatus; -#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" - -@interface Reachability: NSObject -{ - BOOL localWiFiRef; - SCNetworkReachabilityRef reachabilityRef; -} - -//reachabilityWithHostName- Use to check the reachability of a particular host name. -+ (Reachability*) reachabilityWithHostName: (NSString*) hostName; - -//reachabilityWithAddress- Use to check the reachability of a particular IP address. -+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; - -//reachabilityForInternetConnection- checks whether the default route is available. -// Should be used by applications that do not connect to a particular host -+ (Reachability*) reachabilityForInternetConnection; - -//reachabilityForLocalWiFi- checks whether a local wifi connection is available. -+ (Reachability*) reachabilityForLocalWiFi; - -//Start listening for reachability notifications on the current run loop -- (BOOL) startNotifier; -- (void) stopNotifier; - -- (NetworkStatus) currentReachabilityStatus; -//WWAN may be available, but not active until a connection has been established. -//WiFi may require a connection for VPN on Demand. -- (BOOL) connectionRequired; -@end - - diff --git a/Reachability.mm b/Reachability.mm deleted file mode 100644 index 31c0ed0b..00000000 --- a/Reachability.mm +++ /dev/null @@ -1,273 +0,0 @@ -/* - - File: Reachability.m - Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. - - Version: 2.2 - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. - ("Apple") in consideration of your agreement to the following terms, and your - use, installation, modification or redistribution of this Apple software - constitutes acceptance of these terms. If you do not agree with these terms, - please do not use, install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject - to these terms, Apple grants you a personal, non-exclusive license, under - Apple's copyrights in this original Apple software (the "Apple Software"), to - use, reproduce, modify and redistribute the Apple Software, with or without - modifications, in source and/or binary forms; provided that if you redistribute - the Apple Software in its entirety and without modifications, you must retain - this notice and the following text and disclaimers in all such redistributions - of the Apple Software. - Neither the name, trademarks, service marks or logos of Apple Inc. may be used - to endorse or promote products derived from the Apple Software without specific - prior written permission from Apple. Except as expressly stated in this notice, - no other rights or licenses, express or implied, are granted by Apple herein, - including but not limited to any patent rights that may be infringed by your - derivative works or by other works in which the Apple Software may be - incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR - DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF - CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF - APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Copyright (C) 2010 Apple Inc. All Rights Reserved. - -*/ - -#import -#import -#import -#import -#import -#import - -#import - -#import "Reachability.h" - -#define kShouldPrintReachabilityFlags 1 - -static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) -{ -#if kShouldPrintReachabilityFlags - - NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", - (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', - (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', - - (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', - (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', - (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', - (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', - comment - ); -#endif -} - - -@implementation Reachability -static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) -{ - #pragma unused (target, flags) - NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); - NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); - - //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively - // in case someon uses the Reachablity object in a different thread. - NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init]; - - Reachability* noteObject = (Reachability*) info; - // Post a notification to notify the client that the network reachability changed. - [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; - - [myPool release]; -} - -- (BOOL) startNotifier -{ - BOOL retVal = NO; - SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL}; - if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) - { - if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) - { - retVal = YES; - } - } - return retVal; -} - -- (void) stopNotifier -{ - if(reachabilityRef!= NULL) - { - SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - } -} - -- (void) dealloc -{ - [self stopNotifier]; - if(reachabilityRef!= NULL) - { - CFRelease(reachabilityRef); - } - [super dealloc]; -} - -+ (Reachability*) reachabilityWithHostName: (NSString*) hostName; -{ - Reachability* retVal = NULL; - SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); - if(reachability!= NULL) - { - retVal= [[[self alloc] init] autorelease]; - if(retVal!= NULL) - { - retVal->reachabilityRef = reachability; - retVal->localWiFiRef = NO; - } - } - return retVal; -} - -+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; -{ - SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); - Reachability* retVal = NULL; - if(reachability!= NULL) - { - retVal= [[[self alloc] init] autorelease]; - if(retVal!= NULL) - { - retVal->reachabilityRef = reachability; - retVal->localWiFiRef = NO; - } - } - return retVal; -} - -+ (Reachability*) reachabilityForInternetConnection; -{ - struct sockaddr_in zeroAddress; - bzero(&zeroAddress, sizeof(zeroAddress)); - zeroAddress.sin_len = sizeof(zeroAddress); - zeroAddress.sin_family = AF_INET; - return [self reachabilityWithAddress: &zeroAddress]; -} - -+ (Reachability*) reachabilityForLocalWiFi; -{ - struct sockaddr_in localWifiAddress; - bzero(&localWifiAddress, sizeof(localWifiAddress)); - localWifiAddress.sin_len = sizeof(localWifiAddress); - localWifiAddress.sin_family = AF_INET; - // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 - localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); - Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; - if(retVal!= NULL) - { - retVal->localWiFiRef = YES; - } - return retVal; -} - -#pragma mark Network Flag Handling - -- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags -{ - PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); - - NetworkStatus retVal = NotReachable; - if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) - { - retVal = ReachableViaWiFi; - } - return retVal; -} - -- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags -{ - PrintReachabilityFlags(flags, "networkStatusForFlags"); - if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) - { - // if target host is not reachable - return NotReachable; - } - - NetworkStatus retVal = NotReachable; - - if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) - { - // if target host is reachable and no connection is required - // then we'll assume (for now) that your on Wi-Fi - retVal = ReachableViaWiFi; - } - - - if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || - (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) - { - // ... and the connection is on-demand (or on-traffic) if the - // calling application is using the CFSocketStream or higher APIs - - if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) - { - // ... and no [user] intervention is needed - retVal = ReachableViaWiFi; - } - } - - if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) - { - // ... but WWAN connections are OK if the calling application - // is using the CFNetwork (CFSocketStream?) APIs. - retVal = ReachableViaWWAN; - } - return retVal; -} - -- (BOOL) connectionRequired; -{ - NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); - SCNetworkReachabilityFlags flags; - if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) - { - return (flags & kSCNetworkReachabilityFlagsConnectionRequired); - } - return NO; -} - -- (NetworkStatus) currentReachabilityStatus -{ - NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); - NetworkStatus retVal = NotReachable; - SCNetworkReachabilityFlags flags; - if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) - { - if(localWiFiRef) - { - retVal = [self localWiFiStatusForFlags: flags]; - } - else - { - retVal = [self networkStatusForFlags: flags]; - } - } - return retVal; -} -@end diff --git a/makefile b/makefile index 52a91b61..1d189f0a 100644 --- a/makefile +++ b/makefile @@ -42,7 +42,7 @@ all: Cydia clean: rm -f Cydia -Cydia: Cydia.mm Reachability.mm UICaboodle/*.mm iPhonePrivate.h +Cydia: Cydia.mm UICaboodle/*.mm iPhonePrivate.h $(cycc) $(filter %.mm,$^) $(flags) $(link) ldid -Slaunch.xml $@ -- 2.45.2