Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: Upgrade from SCNetworkReachability -> nw_path_monitor #1406

Merged
merged 4 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Source/santasyncservice/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ objc_library(
name = "FCM_lib",
srcs = ["SNTSyncFCM.m"],
hdrs = ["SNTSyncFCM.h"],
sdk_frameworks = ["SystemConfiguration"],
sdk_frameworks = ["Network"],
deps = [
"@MOLAuthenticatingURLSession",
],
Expand Down Expand Up @@ -55,6 +55,7 @@ objc_library(
],
hdrs = ["SNTSyncManager.h"],
sdk_dylibs = ["libz"],
sdk_frameworks = ["Network"],
deps = [
":FCM_lib",
":broadcaster_lib",
Expand Down
53 changes: 18 additions & 35 deletions Source/santasyncservice/SNTSyncFCM.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#import "Source/santasyncservice/SNTSyncFCM.h"

#import <SystemConfiguration/SystemConfiguration.h>
#import <Network/Network.h>

#import <MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.h>

Expand Down Expand Up @@ -80,7 +80,7 @@ @interface SNTSyncFCM () {
@property(copy, nonatomic) SNTSyncFCMMessageHandler messageHandler;

/** Is used throughout the class to reconnect to FCM after a connection loss. */
@property SCNetworkReachabilityRef reachability;
@property nw_path_monitor_t pathMonitor;

/** FCM client identities. */
@property(nonatomic, readonly) NSString *project;
Expand All @@ -97,21 +97,6 @@ - (void)reachabilityRestored;

@end

#pragma mark SCNetworkReachabilityCallBack

/** Called when the network state changes. */
static void reachabilityHandler(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,
void *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if (flags & kSCNetworkReachabilityFlagsReachable) {
SNTSyncFCM *FCMClient = (__bridge SNTSyncFCM *)info;
SEL s = @selector(reachabilityRestored);
[NSObject cancelPreviousPerformRequestsWithTarget:FCMClient selector:s object:nil];
[FCMClient performSelector:s withObject:nil afterDelay:1];
}
});
}

@implementation SNTSyncFCM

#pragma mark init/dealloc methods
Expand Down Expand Up @@ -184,11 +169,6 @@ - (instancetype)initWithProject:(NSString *)project
messageHandler:messageHandler];
}

/** Before this object is released ensure reachability release. */
- (void)dealloc {
[self stopReachability];
}

#pragma mark property methods

- (BOOL)isConnected {
Expand All @@ -212,24 +192,27 @@ - (void)reachabilityRestored {

/** Start listening for network state changes on a background thread. */
- (void)startReachability {
if (self.reachability) return;
if (self.pathMonitor) return;
self.pathMonitor = nw_path_monitor_create();
nw_path_monitor_set_queue(self.pathMonitor, dispatch_get_main_queue());
nw_path_monitor_set_update_handler(self.pathMonitor, ^(nw_path_t path) {
if (nw_path_get_status(path) == nw_path_status_satisfied) {
SEL s = @selector(reachabilityRestored);
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:s object:nil];
[self performSelector:s withObject:nil afterDelay:1];
}
});
nw_path_monitor_set_cancel_handler(self.pathMonitor, ^{
self.pathMonitor = nil;
});
nw_path_monitor_start(self.pathMonitor);
russellhancox marked this conversation as resolved.
Show resolved Hide resolved
LOGD(@"Reachability started.");
self.reachability =
SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, _connectComponents.host.UTF8String);
SCNetworkReachabilityContext context = {.info = (__bridge void *)self};
if (SCNetworkReachabilitySetCallback(self.reachability, reachabilityHandler, &context)) {
SCNetworkReachabilitySetDispatchQueue(
self.reachability, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
}
}

/** Stop listening for network state changes. */
- (void)stopReachability {
if (self.reachability) {
SCNetworkReachabilitySetDispatchQueue(self.reachability, NULL);
if (self.reachability) CFRelease(self.reachability);
self.reachability = NULL;
}
if (!self.pathMonitor) return;
nw_path_monitor_cancel(self.pathMonitor);
russellhancox marked this conversation as resolved.
Show resolved Hide resolved
}

#pragma mark message methods
Expand Down
66 changes: 20 additions & 46 deletions Source/santasyncservice/SNTSyncManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#import <MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.h>
#import <MOLXPCConnection/MOLXPCConnection.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <Network/Network.h>

#import "Source/common/SNTCommonEnums.h"
#import "Source/common/SNTConfigurator.h"
Expand All @@ -35,9 +35,7 @@

static const uint8_t kMaxEnqueuedSyncs = 2;

@interface SNTSyncManager () <SNTPushNotificationsDelegate> {
SCNetworkReachabilityRef _reachability;
}
@interface SNTSyncManager () <SNTPushNotificationsDelegate>

@property(nonatomic) dispatch_source_t fullSyncTimer;
@property(nonatomic) dispatch_source_t ruleSyncTimer;
Expand All @@ -48,6 +46,7 @@ @interface SNTSyncManager () <SNTPushNotificationsDelegate> {
@property(nonatomic) MOLXPCConnection *daemonConn;

@property(nonatomic) BOOL reachable;
@property nw_path_monitor_t pathMonitor;

@property SNTPushNotifications *pushNotifications;

Expand All @@ -58,22 +57,6 @@ @interface SNTSyncManager () <SNTPushNotificationsDelegate> {

@end

// Called when the network state changes
static void reachabilityHandler(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,
void *info) {
// Put this check and set on the main thread to ensure serial access.
dispatch_async(dispatch_get_main_queue(), ^{
SNTSyncManager *commandSyncManager = (__bridge SNTSyncManager *)info;
// Only call the setter when there is a change. This will filter out the redundant calls to this
// callback whenever the network interface states change.
int reachable =
(flags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable;
if (commandSyncManager.reachable != reachable) {
commandSyncManager.reachable = reachable;
}
});
}

@implementation SNTSyncManager

#pragma mark init
Expand Down Expand Up @@ -102,11 +85,6 @@ - (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn {
return self;
}

- (void)dealloc {
// Ensure reachability is always stopped
[self stopReachability];
}

#pragma mark SNTSyncServiceXPC methods

- (void)postEventsToSyncServer:(NSArray<SNTStoredEvent *> *)events fromBundle:(BOOL)isFromBundle {
Expand Down Expand Up @@ -413,34 +391,30 @@ - (void)setReachable:(BOOL)reachable {
}
}

// Start listening for network state changes on a background thread
// Start listening for network state changes.
- (void)startReachability {
dispatch_async(dispatch_get_main_queue(), ^{
if (self->_reachability) return;
const char *nodename = [[SNTConfigurator configurator] syncBaseURL].host.UTF8String;
self->_reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, nodename);
SCNetworkReachabilityContext context = {
.info = (__bridge_retained void *)self,
.release = (void (*)(const void *))CFBridgingRelease,
};
if (SCNetworkReachabilitySetCallback(self->_reachability, reachabilityHandler, &context)) {
SCNetworkReachabilitySetDispatchQueue(
self->_reachability, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
} else {
[self stopReachability];
if (self.pathMonitor) return;
self.pathMonitor = nw_path_monitor_create();
russellhancox marked this conversation as resolved.
Show resolved Hide resolved
// Put the callback on the main thread to ensure serial access.
nw_path_monitor_set_queue(self.pathMonitor, dispatch_get_main_queue());
nw_path_monitor_set_update_handler(self.pathMonitor, ^(nw_path_t path) {
// Only call the setter when there is a change. This will filter out the redundant calls to
// this callback whenever the network interface states change.
int reachable = nw_path_get_status(path) == nw_path_status_satisfied;
if (self.reachable != reachable) {
self.reachable = reachable;
}
});
nw_path_monitor_set_cancel_handler(self.pathMonitor, ^{
self.pathMonitor = nil;
});
nw_path_monitor_start(self.pathMonitor);
}

// Stop listening for network state changes
- (void)stopReachability {
dispatch_async(dispatch_get_main_queue(), ^{
if (self->_reachability) {
SCNetworkReachabilitySetDispatchQueue(self->_reachability, NULL);
if (self->_reachability) CFRelease(self->_reachability);
self->_reachability = NULL;
}
});
if (!self.pathMonitor) return;
nw_path_monitor_cancel(self.pathMonitor);
}

@end
Loading