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 1 commit
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
50 changes: 15 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 @@ -151,6 +136,17 @@ - (instancetype)initWithProject:(NSString *)project
_connectDelayMaxSeconds = connectDelayMax ?: kDefaultConnectDelayMaxSeconds;
_backoffMaxSeconds = backoffMax ?: kDefaultBackoffMaxSeconds;
_fatalHTTPStatusCodes = fatalCodes ?: @[ @302, @400, @401, @403, @404 ];

_pathMonitor = nw_path_monitor_create();
nw_path_monitor_set_update_handler(_pathMonitor, ^(nw_path_t path) {
dispatch_async(dispatch_get_main_queue(), ^{
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];
}
});
});
}
return self;
}
Expand Down Expand Up @@ -184,11 +180,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 +203,13 @@ - (void)reachabilityRestored {

/** Start listening for network state changes on a background thread. */
- (void)startReachability {
if (self.reachability) return;
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));
}
nw_path_monitor_start(self.pathMonitor);
russellhancox marked this conversation as resolved.
Show resolved Hide resolved
}

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

#pragma mark message methods
Expand Down
67 changes: 20 additions & 47 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 All @@ -98,15 +81,25 @@ - (instancetype)initWithDaemonConnection:(MOLXPCConnection *)daemonConn {
_syncLimiter = dispatch_semaphore_create(kMaxEnqueuedSyncs);

_eventBatchSize = kDefaultEventBatchSize;

_pathMonitor = nw_path_monitor_create();
nw_path_monitor_set_update_handler(_pathMonitor, ^(nw_path_t path) {
// Put this check and set on the main thread to ensure serial access.
dispatch_async(dispatch_get_main_queue(), ^{
// 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_queue(self.pathMonitor,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
}
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 @@ -415,32 +408,12 @@ - (void)setReachable:(BOOL)reachable {

// Start listening for network state changes on a background thread
- (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];
}
});
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;
}
});
nw_path_monitor_cancel(self.pathMonitor);
}

@end
Loading