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

Fix dereference issue on ARTOSReachability #1452

Closed
wants to merge 12 commits into from
55 changes: 42 additions & 13 deletions Source/Private/ARTOSReachability.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@
NSNotificationName const kARTOSReachabilityNetworkIsDownNotification = @"ARTOSReachabilityNetworkIsDownNotification";

/// Global callback for network state changes
static void ARTOSReachability_Callback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
static void ARTOSReachability_Callback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *_Nullable info) {
// Post a notification to notify the instance that the network reachability changed.
BOOL reachable = flags & kSCNetworkReachabilityFlagsReachable;
if (reachable) {
[NSNotificationCenter.defaultCenter postNotificationName:kARTOSReachabilityNetworkIsReachableNotification object:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:kARTOSReachabilityNetworkIsReachableNotification object:nil];
});
}
else {
[NSNotificationCenter.defaultCenter postNotificationName:kARTOSReachabilityNetworkIsDownNotification object:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:kARTOSReachabilityNetworkIsDownNotification object:nil];
});
}
}

Expand All @@ -44,36 +48,56 @@ - (void)listenForHost:(NSString *)host callback:(void (^)(BOOL))callback {
_host = host;
_callback = callback;

_reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [host UTF8String]);
if(_queue == nil) {
dispatch_queue_attr_t attrs = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, DISPATCH_QUEUE_PRIORITY_DEFAULT);
_queue = dispatch_queue_create("com.ably.reachability-monitor", attrs);
}

_reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [host UTF8String]);

SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};

[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(networkIsReachable) name:kARTOSReachabilityNetworkIsReachableNotification object:nil];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(networkIsDown) name:kARTOSReachabilityNetworkIsDownNotification object:nil];
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ARTOSReachability_Callback, &context)) {
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
[_logger info:@"Reachability: started listening for host %@", _host];

if(SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _queue)){
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ARTOSReachability_Callback, &context)) {
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
[_logger info:@"Reachability: started listening for host %@", _host];
}
else {
[_logger warn:@"Reachability: failed starting listener for host %@", _host];
}
}
else {
[_logger warn:@"Reachability: failed starting listener for host %@", _host];
[_logger warn:@"Reachability: failed setting callback for %@", _host];
[self removeAllObservers];
}
}
else {
[NSNotificationCenter.defaultCenter removeObserver:self name:kARTOSReachabilityNetworkIsReachableNotification object:nil];
[NSNotificationCenter.defaultCenter removeObserver:self name:kARTOSReachabilityNetworkIsDownNotification object:nil];
[_logger info:@"Reachability: failed setting dispatch queue for %@", _host];
[self removeAllObservers];
}
}

- (void)off {
if (_reachabilityRef != NULL) {
[NSNotificationCenter.defaultCenter removeObserver:self name:kARTOSReachabilityNetworkIsReachableNotification object:nil];
[NSNotificationCenter.defaultCenter removeObserver:self name:kARTOSReachabilityNetworkIsDownNotification object:nil];
[self removeAllObservers];

SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, NULL);
SCNetworkReachabilitySetCallback(_reachabilityRef, NULL, NULL);
[_logger info:@"Reachability: stopped listening for host %@", _host];
}
_callback = nil;
_host = nil;
}

- (void)removeAllObservers {
[NSNotificationCenter.defaultCenter removeObserver:self name:kARTOSReachabilityNetworkIsReachableNotification object:nil];
[NSNotificationCenter.defaultCenter removeObserver:self name:kARTOSReachabilityNetworkIsDownNotification object:nil];
}

- (void)networkIsReachable {
[self internalCallback:true];
}
Expand All @@ -85,14 +109,19 @@ - (void)networkIsDown {
- (void)internalCallback:(BOOL)reachable {
[_logger info:@"Reachability: host %@ is reachable: %@", _host, reachable ? @"true" : @"false"];
dispatch_async(_queue, ^{
if (self->_callback) self->_callback(reachable);
if (self->_callback)
dispatch_async(dispatch_get_main_queue(), ^{
self->_callback(reachable);
});

});
}

- (void)dealloc {
[self off];
if (_reachabilityRef != NULL) {
CFRelease(_reachabilityRef);
_reachabilityRef = NULL;
}
}

Expand Down