From 096fd07a065751a1fd4928e9696ab32216b6bd11 Mon Sep 17 00:00:00 2001 From: Keeyou Date: Thu, 9 May 2024 10:38:37 +0800 Subject: [PATCH] ios: use NetworkPathMonitor SCNetworkReachabilityCreateWithAddress is deprecated for some time. --- src/ios/YassAppDelegate.mm | 1 + src/ios/utils.cpp | 26 -------------- src/ios/utils.h | 4 +++ src/ios/utils.mm | 69 +++++++++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/ios/YassAppDelegate.mm b/src/ios/YassAppDelegate.mm index 6bae7ca19..561208851 100644 --- a/src/ios/YassAppDelegate.mm +++ b/src/ios/YassAppDelegate.mm @@ -52,6 +52,7 @@ @implementation YassAppDelegate { - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { state_ = STOPPED; + initNetworkPathMonitor(); [self didDefaultsChanged:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didDefaultsChanged:) diff --git a/src/ios/utils.cpp b/src/ios/utils.cpp index b0ee29d5f..e1ffd7097 100644 --- a/src/ios/utils.cpp +++ b/src/ios/utils.cpp @@ -3,7 +3,6 @@ #include "ios/utils.h" -#include #include #include #include @@ -14,31 +13,6 @@ using json = nlohmann::json; -bool connectedToNetwork() { - // Create zero addy - struct sockaddr_in zeroAddress; - bzero(&zeroAddress, sizeof(zeroAddress)); - zeroAddress.sin_len = sizeof(zeroAddress); - zeroAddress.sin_family = AF_INET; - - // Recover reachability flags - SCNetworkReachabilityRef defaultRouteReachability = - SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr*)&zeroAddress); - SCNetworkReachabilityFlags flags; - - Boolean didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); - CFRelease(defaultRouteReachability); - - if (!didRetrieveFlags) { - return false; - } - - Boolean isReachable = flags & kSCNetworkFlagsReachable; - Boolean needsConnection = flags & kSCNetworkFlagsConnectionRequired; - - return (isReachable && !needsConnection) ? true : false; -} - std::string serializeTelemetryJson(uint64_t total_rx_bytes, uint64_t total_tx_bytes) { json j; j["total_rx_bytes"] = total_rx_bytes; diff --git a/src/ios/utils.h b/src/ios/utils.h index 1e1675fe7..d931791ca 100644 --- a/src/ios/utils.h +++ b/src/ios/utils.h @@ -7,7 +7,11 @@ #include #include +void initNetworkPathMonitor(); +void deinitNetworkPathMonitor(); + bool connectedToNetwork(); + std::string serializeTelemetryJson(uint64_t total_rx_bytes, uint64_t total_tx_bytes); bool parseTelemetryJson(std::string_view resp, uint64_t* total_rx_bytes, uint64_t* total_tx_bytes); diff --git a/src/ios/utils.mm b/src/ios/utils.mm index aeff9d508..3b24703b5 100644 --- a/src/ios/utils.mm +++ b/src/ios/utils.mm @@ -3,4 +3,71 @@ #include "ios/utils.h" -// PLACE HOLDER FOR Objective-C++ Code +#include +#include + +#include + +#include "core/logging.hpp" + +static std::atomic connectedNetwork; +static dispatch_queue_t monitorQueue; +static nw_path_monitor_t monitor; +static std::once_flag initFlag; + +// https://forums.developer.apple.com/forums/thread/105822 +void initNetworkPathMonitor() { + DCHECK(!monitor); + + std::call_once(initFlag, []() { + dispatch_queue_attr_t attrs = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, + DISPATCH_QUEUE_PRIORITY_DEFAULT); + monitorQueue = dispatch_queue_create("it.gui.yass.network-monitor", attrs); + }); + + // monitor = nw_path_monitor_create_with_type(nw_interface_type_wifi); + monitor = nw_path_monitor_create(); + nw_path_monitor_set_queue(monitor, monitorQueue); + if (@available(iOS 14, *)) { + nw_path_monitor_prohibit_interface_type(monitor, nw_interface_type_loopback); + } + nw_path_monitor_set_update_handler(monitor, ^(nw_path_t _Nonnull path) { + nw_path_status_t status = nw_path_get_status(path); + // Determine the active interface, but how? + switch (status) { + case nw_path_status_invalid: { + // Network path is invalid + connectedNetwork = false; + break; + } + case nw_path_status_satisfied: { + // Network is usable + connectedNetwork = true; + break; + } + case nw_path_status_satisfiable: { + // Network may be usable + connectedNetwork = false; + break; + } + case nw_path_status_unsatisfied: { + // Network is not usable + connectedNetwork = false; + break; + } + } + }); + + nw_path_monitor_start(monitor); +} + +void deinitNetworkPathMonitor() { + DCHECK(monitor); + + nw_path_monitor_cancel(monitor); + monitor = nw_path_monitor_t(); +} + +bool connectedToNetwork() { + return connectedNetwork; +}