diff --git a/build-ios.sh b/build-ios.sh index 1fc411a7c..d316fe2fa 100755 --- a/build-ios.sh +++ b/build-ios.sh @@ -56,7 +56,7 @@ if [ "$IOS_PLAT" == "iphoneos" ] || [ "$IOS_PLAT" == "iphonesimulator" ]; then SYS_NAME="iOS" DEPLOYMENT_TARGET="$IOS_DEPLOYMENT_TARGET" if [ -z "$DEPLOYMENT_TARGET" ]; then - DEPLOYMENT_TARGET="10.0" + DEPLOYMENT_TARGET="12.0" FORCE_RESET_DEPLOYMENT_TARGET=YES fi elif [ "$IOS_PLAT" == "xros" ] || [ "$IOS_PLAT" == "xrsimulator" ]; then diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 6a8c1e32f..4b4115a37 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,7 +1,7 @@ # Honor visibility properties for all target types cmake_policy(SET CMP0063 NEW) -include_directories( . ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include/public ${CMAKE_CURRENT_SOURCE_DIR}/include/public ${CMAKE_CURRENT_SOURCE_DIR}/include/mat ${CMAKE_CURRENT_SOURCE_DIR}/pal ${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_CURRENT_SOURCE_DIR}/modules/exp ${CMAKE_CURRENT_SOURCE_DIR}/modules/dataviewer ${CMAKE_CURRENT_SOURCE_DIR}/modules/privacyguard ${CMAKE_CURRENT_SOURCE_DIR}/modules/liveeventinspector ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/Reachability ${CMAKE_CURRENT_SOURCE_DIR}/modules/cds ${CMAKE_CURRENT_SOURCE_DIR}/modules/signals ${CMAKE_CURRENT_SOURCE_DIR}/modules/sanitizer /usr/local/include ) +include_directories( . ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include/public ${CMAKE_CURRENT_SOURCE_DIR}/include/public ${CMAKE_CURRENT_SOURCE_DIR}/include/mat ${CMAKE_CURRENT_SOURCE_DIR}/pal ${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_CURRENT_SOURCE_DIR}/modules/exp ${CMAKE_CURRENT_SOURCE_DIR}/modules/dataviewer ${CMAKE_CURRENT_SOURCE_DIR}/modules/privacyguard ${CMAKE_CURRENT_SOURCE_DIR}/modules/liveeventinspector ${CMAKE_CURRENT_SOURCE_DIR}/modules/cds ${CMAKE_CURRENT_SOURCE_DIR}/modules/signals ${CMAKE_CURRENT_SOURCE_DIR}/modules/sanitizer /usr/local/include ) set(SRCS decorators/BaseDecorator.cpp packager/BondSplicer.cpp @@ -160,8 +160,6 @@ if(PAL_IMPLEMENTATION STREQUAL "CPP11") list(APPEND SRCS pal/posix/NetworkInformationImpl.mm - # TODO: this unit below needs to be deprecated and removed - ../third_party/Reachability/ODWReachability.m ) else() list(APPEND SRCS diff --git a/lib/pal/posix/NetworkInformationImpl.mm b/lib/pal/posix/NetworkInformationImpl.mm index d7ba15403..2cd8379a4 100644 --- a/lib/pal/posix/NetworkInformationImpl.mm +++ b/lib/pal/posix/NetworkInformationImpl.mm @@ -7,7 +7,6 @@ #include "pal/NetworkInformationImpl.hpp" #import -#import "ODWReachability.h" namespace PAL_NS_BEGIN { @@ -67,12 +66,7 @@ virtual NetworkCost GetNetworkCost() void UpdateCost(NetworkCost cost) noexcept; std::string m_network_provider {}; - // iOS 12 and newer nw_path_monitor_t m_monitor = nil; - - // iOS 11 and older - ODWReachability* m_reach = nil; - id m_notificationId = nil; }; NetworkInformation::NetworkInformation(IRuntimeConfig& configuration) : @@ -84,20 +78,9 @@ virtual NetworkCost GetNetworkCost() NetworkInformation::~NetworkInformation() noexcept { - if (@available(macOS 10.14, iOS 12.0, *)) - { - if (m_isNetDetectEnabled) - { - nw_path_monitor_cancel(m_monitor); - } - } - else + if (m_isNetDetectEnabled) { - if (m_isNetDetectEnabled) - { - [[NSNotificationCenter defaultCenter] removeObserver:m_notificationId]; - [m_reach stopNotifier]; - } + nw_path_monitor_cancel(m_monitor); } } @@ -105,8 +88,9 @@ virtual NetworkCost GetNetworkCost() { auto weak_this = std::weak_ptr(shared_from_this()); - m_reach = [ODWReachability reachabilityForInternetConnection]; - void (^block)(NSNotification*) = ^(NSNotification*) + m_monitor = nw_path_monitor_create(); + nw_path_monitor_set_queue(m_monitor, dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)); + nw_path_monitor_set_update_handler(m_monitor, ^(nw_path_t path) { auto strong_this = weak_this.lock(); if (!strong_this) @@ -114,87 +98,44 @@ virtual NetworkCost GetNetworkCost() return; } - // NetworkCost information is not available until iOS 12. - // Just make the best guess here. - switch (m_reach.currentReachabilityStatus) - { - case NotReachable: - strong_this->UpdateType(NetworkType_Unknown); - strong_this->UpdateCost(NetworkCost_Unknown); - break; - case ReachableViaWiFi: - strong_this->UpdateType(NetworkType_Wifi); - strong_this->UpdateCost(NetworkCost_Unmetered); - break; - case ReachableViaWWAN: - strong_this->UpdateType(NetworkType_WWAN); - strong_this->UpdateCost(NetworkCost_Metered); - break; - } - }; - block(nil); // Update the initial status. - - if (@available(macOS 10.14, iOS 12.0, *)) - { - m_monitor = nw_path_monitor_create(); - nw_path_monitor_set_queue(m_monitor, dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)); - nw_path_monitor_set_update_handler(m_monitor, ^(nw_path_t path) + NetworkType type = NetworkType_Unknown; + NetworkCost cost = NetworkCost_Unknown; + nw_path_status_t status = nw_path_get_status(path); + bool connected = status == nw_path_status_satisfied || status == nw_path_status_satisfiable; + if (connected) { - auto strong_this = weak_this.lock(); - if (!strong_this) + if (nw_path_uses_interface_type(path, nw_interface_type_wifi)) { - return; + type = NetworkType_Wifi; } - - NetworkType type = NetworkType_Unknown; - NetworkCost cost = NetworkCost_Unknown; - nw_path_status_t status = nw_path_get_status(path); - bool connected = status == nw_path_status_satisfied || status == nw_path_status_satisfiable; - if (connected) + else if (nw_path_uses_interface_type(path, nw_interface_type_cellular)) { - if (nw_path_uses_interface_type(path, nw_interface_type_wifi)) - { - type = NetworkType_Wifi; - } - else if (nw_path_uses_interface_type(path, nw_interface_type_cellular)) - { - type = NetworkType_WWAN; - } - else if (nw_path_uses_interface_type(path, nw_interface_type_wired)) - { - type = NetworkType_Wired; - } - cost = nw_path_is_expensive(path) ? NetworkCost_Metered : NetworkCost_Unmetered; - if (@available(macOS 10.15, iOS 13.0, *)) + type = NetworkType_WWAN; + } + else if (nw_path_uses_interface_type(path, nw_interface_type_wired)) + { + type = NetworkType_Wired; + } + cost = nw_path_is_expensive(path) ? NetworkCost_Metered : NetworkCost_Unmetered; + if (@available(macOS 10.15, iOS 13.0, *)) + { + if (nw_path_is_constrained(path)) { - if (nw_path_is_constrained(path)) - { - cost = NetworkCost_Roaming; - } + cost = NetworkCost_Roaming; } } - strong_this->UpdateType(type); - strong_this->UpdateCost(cost); - }); - nw_path_monitor_start(m_monitor); - - // nw_path_monitor_start will invoke the callback for once. So if - // we don't want to listen for changes, we can just start the - // monitor and stop it right away. - if (!m_isNetDetectEnabled) - { - nw_path_monitor_cancel(m_monitor); } - } - else if (m_isNetDetectEnabled) + strong_this->UpdateType(type); + strong_this->UpdateCost(cost); + }); + nw_path_monitor_start(m_monitor); + + // nw_path_monitor_start will invoke the callback for once. So if + // we don't want to listen for changes, we can just start the + // monitor and stop it right away. + if (!m_isNetDetectEnabled) { - m_notificationId = - [[NSNotificationCenter defaultCenter] - addObserverForName: kNetworkReachabilityChangedNotification - object: nil - queue: nil - usingBlock: block]; - [m_reach startNotifier]; + nw_path_monitor_cancel(m_monitor); } } diff --git a/tests/unittests/obj-c/ODWReachabilityTests.mm b/tests/unittests/obj-c/ODWReachabilityTests.mm deleted file mode 100644 index 501a3be7a..000000000 --- a/tests/unittests/obj-c/ODWReachabilityTests.mm +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// ODWReachabilityTests.mm -// Tests -// -// Created by Abu Sayem on 13/12/2024. -// - -#import -#import "ODWReachability.h" - -#import -#import -#import -#import -#import -#import -#import - -@interface ODWReachabilityTests : XCTestCase -@end - -@implementation ODWReachabilityTests - -- (void)testReachabilityWithHostname -{ - NSString *hostname = @"www.microsoft.com"; - ODWReachability *reachability = [ODWReachability reachabilityWithHostname:hostname]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Reachability check"]; - NSString *hostUrl = [NSString stringWithFormat:@"https://%@", hostname]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - XCTAssertNotNil(reachability); - XCTAssertEqualObjects(reachability.url.absoluteString, hostUrl); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:10.0 handler:nil]; -} - -- (void)testReachabilityWithInvalidHostname -{ - NSString *hostname = @"invalid.hostname"; - ODWReachability *reachability = [ODWReachability reachabilityWithHostname:hostname]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Reachability check"]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - XCTAssertNil(reachability); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:10.0 handler:nil]; -} - -- (void)testReachabilityWithAddress -{ - struct sockaddr_in address; - address.sin_family = AF_INET; - address.sin_addr.s_addr = inet_addr("8.8.8.8"); - ODWReachability *reachability = [ODWReachability reachabilityWithAddress:&address]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Reachability check"]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - XCTAssertNotNil(reachability); - XCTAssertEqualObjects(reachability.url.absoluteString, @"https://8.8.8.8"); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:10.0 handler:nil]; -} - -- (void)testReachabilityWithInvalidAddress -{ - struct sockaddr_in address; - address.sin_family = AF_INET; - address.sin_addr.s_addr = inet_addr("0.0.0.0"); - ODWReachability *reachability = [ODWReachability reachabilityWithAddress:&address]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Reachability check"]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - XCTAssertNil(reachability); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:10.0 handler:nil]; -} - -- (void)testReachabilityForInternetConnection -{ - ODWReachability *reachability = [ODWReachability reachabilityForInternetConnection]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Reachability check"]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - XCTAssertNotNil(reachability); - XCTAssertEqual(reachability.currentReachabilityStatus, ReachableViaWiFi); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:10.0 handler:nil]; -} - -- (void)testReachabilityForLocalWiFi -{ - ODWReachability *reachability = [ODWReachability reachabilityForLocalWiFi]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Reachability check"]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - XCTAssertNotNil(reachability); - XCTAssertEqual(reachability.currentReachabilityStatus, ReachableViaWiFi); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:10.0 handler:nil]; -} - -@end - diff --git a/tests/unittests/unittests-ios.xcodeproj/project.pbxproj b/tests/unittests/unittests-ios.xcodeproj/project.pbxproj index 5511210d4..b17cd878a 100644 --- a/tests/unittests/unittests-ios.xcodeproj/project.pbxproj +++ b/tests/unittests/unittests-ios.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 16CC10702D4D58DA00C03295 /* ODWReachabilityTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16CC106F2D4D58DA00C03295 /* ODWReachabilityTests.mm */; }; 430102E5235E660F00836D50 /* iOSWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 430102E4235E660F00836D50 /* iOSWrapper.mm */; }; 431EFE50233EBE54002FCC18 /* HttpClientTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 431EFE2A233EBE53002FCC18 /* HttpClientTests.cpp */; }; 431EFE51233EBE54002FCC18 /* LoggerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 431EFE2B233EBE53002FCC18 /* LoggerTests.cpp */; }; @@ -117,7 +116,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 16CC106F2D4D58DA00C03295 /* ODWReachabilityTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = ODWReachabilityTests.mm; path = "obj-c/ODWReachabilityTests.mm"; sourceTree = ""; }; 430102E4235E660F00836D50 /* iOSWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = iOSWrapper.mm; path = ../../common/iOSWrapper.mm; sourceTree = ""; }; 431EFE1E233EBDF2002FCC18 /* libunittests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libunittests.a; sourceTree = BUILT_PRODUCTS_DIR; }; 431EFE2A233EBE53002FCC18 /* HttpClientTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpClientTests.cpp; sourceTree = ""; }; @@ -203,7 +201,6 @@ 431EFE15233EBDF2002FCC18 = { isa = PBXGroup; children = ( - 16CC106F2D4D58DA00C03295 /* ODWReachabilityTests.mm */, 43BD496F26B8B0C300EC3C0C /* EventPropertiesDecoratorTests.cpp */, 437C72F024D2286F0046F545 /* ODWLogConfigurationTests.mm */, 437C72EE24D21ACE0046F545 /* ODWSemanticContextTests.mm */, @@ -436,7 +433,6 @@ 431EFEA7233EC590002FCC18 /* HttpDeflateCompressionTests.cpp in Sources */, 431EFEB3233EC590002FCC18 /* OfflineStorageTests.cpp in Sources */, 431EFEB8233EC590002FCC18 /* TaskDispatcherCAPITests.cpp in Sources */, - 16CC10712D4D58DA00C03295 /* ODWReachabilityTests.mm in Sources */, 437C72ED24D0C5D70046F545 /* ODWEventPropertiesTests.mm in Sources */, 431EFEB6233EC590002FCC18 /* RouteTests.cpp in Sources */, 431EFEA8233EC590002FCC18 /* HttpRequestEncoderTests.cpp in Sources */, diff --git a/third_party/Reachability/ODWReachability.h b/third_party/Reachability/ODWReachability.h deleted file mode 100644 index b2d218417..000000000 --- a/third_party/Reachability/ODWReachability.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (c) 2011, Tony Million. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#import -#import - - -/** - * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X. - * - * @see http://nshipster.com/ns_enum-ns_options/ - **/ -#ifndef NS_ENUM -#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type -#endif - -extern NSString* const kNetworkReachabilityChangedNotification; - -typedef NS_ENUM(NSInteger, ODWNetworkStatus) { - // Apple NetworkStatus Compatible Names. - NotReachable = 0, - ReachableViaWiFi = 2, - ReachableViaWWAN = 1 -}; - -@class ODWReachability; - -typedef void (^NetworkReachable)(ODWReachability * reachability); -typedef void (^NetworkUnreachable)(ODWReachability * reachability); - - -@interface ODWReachability : NSObject - -@property (nonatomic, copy) NetworkReachable reachableBlock; -@property (nonatomic, copy) NetworkUnreachable unreachableBlock; - -@property (nonatomic, assign) BOOL reachableOnWWAN; - -@property (nonatomic, strong) NSURL *url; - -+(ODWReachability*)reachabilityWithHostname:(NSString*)hostname; -// This is identical to the function above, but is here to maintain -//compatibility with Apples original code. (see .m) -+(ODWReachability*)reachabilityWithHostName:(NSString*)hostname; -+(ODWReachability*)reachabilityForInternetConnection; -+(ODWReachability*)reachabilityWithAddress:(void *)hostAddress; -+(ODWReachability*)reachabilityForLocalWiFi; -+(void)setTimeoutDurationInSeconds:(int)timeoutDuration; - --(ODWReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; - --(BOOL)startNotifier; --(void)stopNotifier; - --(BOOL)isReachable; --(BOOL)isReachableViaWWAN; --(BOOL)isReachableViaWiFi; - -// WWAN may be available, but not active until a connection has been established. -// WiFi may require a connection for VPN on Demand. --(BOOL)isConnectionRequired; // Identical DDG variant. --(BOOL)connectionRequired; // Apple's routine. -// Dynamic, on demand connection? --(BOOL)isConnectionOnDemand; -// Is user intervention required? --(BOOL)isInterventionRequired; - --(ODWNetworkStatus)currentReachabilityStatus; --(SCNetworkReachabilityFlags)reachabilityFlags; --(NSString*)currentReachabilityString; --(NSString*)currentReachabilityFlags; - -@end diff --git a/third_party/Reachability/ODWReachability.m b/third_party/Reachability/ODWReachability.m deleted file mode 100644 index 0e13591d5..000000000 --- a/third_party/Reachability/ODWReachability.m +++ /dev/null @@ -1,700 +0,0 @@ -/* - Copyright (c) 2011, Tony Million. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#import "ODWReachability.h" - -#import -#import -#import -#import -#import -#import -#import - - -NSString *const kNetworkReachabilityChangedNotification = @"NetworkReachabilityChangedNotification"; - - -@interface ODWReachability () - -@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; -@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; -@property (nonatomic, strong) id reachabilityObject; - --(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; --(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; - -@end - - -static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) -{ - return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", -#if TARGET_OS_IPHONE - (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', -#else - 'X', -#endif - (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', - (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', - (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', - (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', - (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', - (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; -} - -// Start listening for reachability notifications on the current run loop -static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) -{ -#pragma unused (target) - - ODWReachability *reachability = ((__bridge ODWReachability*)info); - - // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, - // but what the heck eh? - @autoreleasepool - { - [reachability reachabilityChanged:flags]; - } -} - - -@implementation ODWReachability - -static int kTimeoutDurationInSeconds = 10; - -#pragma mark - Class Constructor Methods - -+(ODWReachability*)reachabilityWithHostName:(NSString*)hostname -{ - if (hostname == nil || [hostname length] == 0) - { - NSLog(@"Invalid hostname"); - return nil; - } - return [ODWReachability reachabilityWithHostname:hostname]; -} - -+(instancetype)reachabilityWithHostname:(NSString*)hostname -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - // Use URLSession for macOS 10.14 or higher - NSString *formattedHostname = hostname; - if (![formattedHostname hasPrefix:@"https://"] && ![formattedHostname hasPrefix:@"http://"]) { - formattedHostname = [NSString stringWithFormat:@"https://%@", hostname]; - } - NSURL *url = [NSURL URLWithString:formattedHostname]; - - NSURLSession *session = [NSURLSession sharedSession]; - __block ODWReachability *reachabilityInstance = [[self alloc] init]; - reachabilityInstance.url = url; - NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - reachabilityInstance = [self handleReachabilityResponse:response error:error url:reachabilityInstance.url]; - }]; - [dataTask resume]; - return reachabilityInstance; - } - - // Use SCNetworkReachability for macOS 10.14 or lower -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); -#pragma clang diagnostic pop - if (ref) - { - id reachability = [[self alloc] initWithReachabilityRef:ref]; - - return reachability; - } - - return nil; -} - -+(ODWReachability *)reachabilityWithAddress:(void *)hostAddress -{ - if (hostAddress == NULL) { - NSLog(@"Invalid address"); - return nil; - } - - if (@available(macOS 10.14, iOS 12.0, *)) - { - // Use URLSession for macOS 10.14 or higher - NSString *addressString = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)hostAddress)->sin_addr)]; - NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", addressString]]; - NSURLSession *session = [NSURLSession sharedSession]; - __block ODWReachability *reachabilityInstance = [[self alloc] init]; - reachabilityInstance.url = url; - NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - reachabilityInstance = [self handleReachabilityResponse:response error:error url:reachabilityInstance.url]; - }]; - [dataTask resume]; - return reachabilityInstance; // Return the instance after resuming the data task - } - - // Use SCNetworkReachability for macOS 10.14 or lower -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); -#pragma clang diagnostic pop - if (ref) - { - id reachability = [[self alloc] initWithReachabilityRef:ref]; - - return reachability; - } - - return nil; -} - -+(ODWReachability *)handleReachabilityResponse:(NSURLResponse *)response error:(NSError *)error url:(NSURL *)url -{ - __block ODWReachability *reachabilityInstance = nil; - - if (error == nil) { - // Handle successful reachability - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - if (httpResponse.statusCode == 200) - { - NSLog(@"Reachability success: %@", url); - reachabilityInstance = [[self alloc] init]; - reachabilityInstance.url = url; - } - else - { - NSLog(@"Reachability failed with status code: %ld", (long)httpResponse.statusCode); - } - return reachabilityInstance; - } - - // Handle reachability failure - NSLog(@"Reachability error: %@", error.localizedDescription); - - return nil; -} - - -+(ODWReachability *)reachabilityForInternetConnection -{ - struct sockaddr_in zeroAddress; - bzero(&zeroAddress, sizeof(zeroAddress)); - zeroAddress.sin_len = sizeof(zeroAddress); - zeroAddress.sin_family = AF_INET; - - return [self reachabilityWithAddress:&zeroAddress]; -} - -+(ODWReachability*)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); - - return [self reachabilityWithAddress:&localWifiAddress]; -} - - -// Initialization methods - --(ODWReachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref -{ - self = [super init]; - if (self != nil) - { - self.reachableOnWWAN = YES; - self.reachabilityRef = ref; - - // We need to create a serial queue. - // We allocate this once for the lifetime of the notifier. - - self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); - } - - return self; -} - -+(void)setTimeoutDurationInSeconds:(int)timeoutDuration -{ - if (timeoutDuration >= kTimeoutDurationInSeconds) - { - kTimeoutDurationInSeconds = timeoutDuration; - } - else - { - NSLog(@"Timeout duration must be at least 10."); - } -} - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" // Not fixing third_party components. -#endif - --(void)dealloc -{ - [self stopNotifier]; - - if(self.reachabilityRef) - { - CFRelease(self.reachabilityRef); - self.reachabilityRef = nil; - } - - self.reachableBlock = nil; - self.unreachableBlock = nil; - self.reachabilitySerialQueue = nil; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#pragma mark - Notifier Methods - -// Notifier -// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD -// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. -// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) - --(BOOL)startNotifier -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - // Use URLSession for macOS 10.14 or higher - NSURLSession *session = [NSURLSession sharedSession]; - NSURLSessionDataTask *task = [session dataTaskWithURL:[self url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if (error) { - NSLog(@"URLSession failed: %@", error.localizedDescription); - self.reachabilityObject = nil; - } else { - self.reachabilityObject = self; - [[NSNotificationCenter defaultCenter] postNotificationName:kNetworkReachabilityChangedNotification object:self]; - } - }]; - if (task) { - [task resume]; - return YES; - } else { - NSLog(@"Failed to create URLSessionDataTask"); - return NO; - } - } - - // Use SCNetworkReachability for macOS 10.14 or lower - // allow start notifier to be called multiple times - if (self.reachabilityObject && (self.reachabilityObject == self)) - { - return YES; - } - - SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; - context.info = (__bridge void *)self; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) - { - if (SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) -#pragma clang diagnostic pop - { - self.reachabilityObject = self; - return YES; - } else { -#ifdef DEBUG - NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); -#endif - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - // UH OH - FAILURE - stop any callbacks! - SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); -#pragma clang diagnostic pop - } - } - else - { -#ifdef DEBUG - NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); -#endif - } - - // if we get here we fail at the internet - self.reachabilityObject = nil; - return NO; -} - --(void)stopNotifier -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - // Use URLSession for macOS 10.14 or higher, no specific action is needed for URLSession - self.reachabilityObject = nil; - } - - // Use SCNetworkReachability for macOS 10.14 or lower -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - // First stop, any callbacks! - SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); - - // Unregister target from the GCD serial dispatch queue. - SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); -#pragma clang diagnostic pop - self.reachabilityObject = nil; -} - - -#pragma mark - reachability tests - -// This is for the case where you flick the airplane mode; -// you end up getting something like this: -//Reachability: WR ct----- -//Reachability: -- ------- -//Reachability: WR ct----- -//Reachability: -- ------- -// We treat this as 4 UNREACHABLE triggers - really apple should do better than this - -#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) - --(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags -{ - BOOL connectionUP = YES; - - if(!(flags & kSCNetworkReachabilityFlagsReachable)) - connectionUP = NO; - - if( (flags & testcase) == testcase ) - connectionUP = NO; - -#if TARGET_OS_IPHONE - if(flags & kSCNetworkReachabilityFlagsIsWWAN) - { - // We're on 3G. - if(!self.reachableOnWWAN) - { - // We don't want to connect when on 3G. - connectionUP = NO; - } - } -#endif - - return connectionUP; -} - --(BOOL)isReachable -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - return [self checkNetworkReachability:true]; - } - - // for macOS 10.14 or lower - SCNetworkReachabilityFlags flags; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - return NO; -#pragma clang diagnostic pop - - return [self isReachableWithFlags:flags]; -} - - --(BOOL)isReachableViaWWAN -{ -#if TARGET_OS_IPHONE - - SCNetworkReachabilityFlags flags = 0; - - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) - { - // Check we're REACHABLE - if(flags & kSCNetworkReachabilityFlagsReachable) - { - // Now, check we're on WWAN - if(flags & kSCNetworkReachabilityFlagsIsWWAN) - { - return YES; - } - } - } -#endif - - return NO; -} - --(BOOL)isReachableViaWiFi -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - return [self checkNetworkReachability:true]; - } - - // for macOS 10.14 or lower - SCNetworkReachabilityFlags flags = 0; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) -#pragma clang diagnostic pop - { - // Check we're reachable - if((flags & kSCNetworkReachabilityFlagsReachable)) - { -#if TARGET_OS_IPHONE - // Check we're NOT on WWAN - if((flags & kSCNetworkReachabilityFlagsIsWWAN)) - { - return NO; - } -#endif - return YES; - } - } - - return NO; -} - - -// WWAN may be available, but not active until a connection has been established. -// WiFi may require a connection for VPN on Demand. --(BOOL)isConnectionRequired -{ - return [self connectionRequired]; -} - --(BOOL)connectionRequired -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - return [self checkNetworkReachability:false]; - } - - // for macOS 10.14 or lower - SCNetworkReachabilityFlags flags; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) -#pragma clang diagnostic pop - { - return (flags & kSCNetworkReachabilityFlagsConnectionRequired); - } - - return NO; -} - - -// Dynamic, on demand connection? --(BOOL)isConnectionOnDemand -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - return [self checkNetworkReachability:true]; - } - - // for macOS 10.14 or lower - SCNetworkReachabilityFlags flags; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) -#pragma clang diagnostic pop - { - return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && - (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); - } - - return NO; -} - - -// Is user intervention required? --(BOOL)isInterventionRequired -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - return [self checkNetworkReachability:false]; - } - - // for macOS 10.14 or lower - SCNetworkReachabilityFlags flags; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) -#pragma clang diagnostic pop - { - return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && - (flags & kSCNetworkReachabilityFlagsInterventionRequired)); - } - - return NO; -} - - - -#pragma mark - reachability status stuff - --(ODWNetworkStatus)currentReachabilityStatus -{ - if([self isReachable]) - { - if([self isReachableViaWiFi]) - return ReachableViaWiFi; - -#if TARGET_OS_IPHONE - return ReachableViaWWAN; -#endif - } - - return NotReachable; -} - --(SCNetworkReachabilityFlags)reachabilityFlags -{ - if (@available(macOS 10.14, iOS 12.0, *)) - { - __block SCNetworkReachabilityFlags flags = 0; - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - - NSURLSession *session = [NSURLSession sharedSession]; - NSURLSessionDataTask *task = [session dataTaskWithURL:[self url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if (error == nil && data != nil) { - flags = kSCNetworkReachabilityFlagsReachable; - } - dispatch_semaphore_signal(semaphore); - }]; - - [task resume]; - dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, kTimeoutDurationInSeconds * NSEC_PER_SEC)); - - return flags; - } - - // for macOS 10.14 or lower - SCNetworkReachabilityFlags flags = 0; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) -#pragma clang diagnostic pop - { - return flags; - } - - return 0; -} - --(NSString*)currentReachabilityString -{ - ODWNetworkStatus temp = [self currentReachabilityStatus]; - - if(temp == ReachableViaWWAN) - { - // Updated for the fact that we have CDMA phones now! - return NSLocalizedString(@"Cellular", @""); - } - if (temp == ReachableViaWiFi) - { - return NSLocalizedString(@"WiFi", @""); - } - - return NSLocalizedString(@"No Connection", @""); -} - --(NSString*)currentReachabilityFlags -{ - return reachabilityFlags([self reachabilityFlags]); -} - -- (SCNetworkReachabilityFlags)checkNetworkReachability:(BOOL)checkData -{ - __block BOOL connection = NO; - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - - NSURLSession *session = [NSURLSession sharedSession]; - NSURLSessionDataTask *task = [session dataTaskWithURL:[self url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if (error == nil && !checkData) - { - connection = YES; - } - else if (error == nil && checkData && data != nil) - { - connection = YES; - } - dispatch_semaphore_signal(semaphore); - }]; - - [task resume]; - dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, kTimeoutDurationInSeconds * NSEC_PER_SEC)); - - return connection; -} - -#pragma mark - Callback function calls this method - --(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags -{ - if([self isReachableWithFlags:flags]) - { - if(self.reachableBlock) - { - self.reachableBlock(self); - } - } - else - { - if(self.unreachableBlock) - { - self.unreachableBlock(self); - } - } - - // this makes sure the change notification happens on the MAIN THREAD - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:kNetworkReachabilityChangedNotification - object:self]; - }); -} - -#pragma mark - Debug Description - -- (NSString *) description -{ - NSString *description = [NSString stringWithFormat:@"<%@: %p (%@)>", - NSStringFromClass([self class]), self, [self currentReachabilityFlags]]; - return description; -} - -@end diff --git a/third_party/Reachability/README.md b/third_party/Reachability/README.md deleted file mode 100644 index 5feefa7ab..000000000 --- a/third_party/Reachability/README.md +++ /dev/null @@ -1,28 +0,0 @@ -This code has been obtained from https://github.com/tonymillion/Reachability - -LICENSE: https://github.com/tonymillion/Reachability/blob/master/LICENCE.txt - -Copyright (c) 2011-2013, Tony Million. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE.