From 8a0ef6a5b03f5e3c4636baf6d8b7e5df9cc36ea7 Mon Sep 17 00:00:00 2001 From: nsingh-branch Date: Tue, 23 Jul 2024 11:11:36 -0700 Subject: [PATCH 1/2] Created branchVPNBlockingError method --- Sources/BranchSDK/BNCServerInterface.m | 2 ++ Sources/BranchSDK/BNCURLFilter.m | 2 ++ Sources/BranchSDK/BranchQRCode.m | 2 ++ Sources/BranchSDK/NSError+Branch.m | 34 ++++++++++++++++++++++ Sources/BranchSDK/Private/NSError+Branch.h | 3 ++ 5 files changed, 43 insertions(+) diff --git a/Sources/BranchSDK/BNCServerInterface.m b/Sources/BranchSDK/BNCServerInterface.m index 63559c3a8..ef7ab058a 100644 --- a/Sources/BranchSDK/BNCServerInterface.m +++ b/Sources/BranchSDK/BNCServerInterface.m @@ -124,6 +124,8 @@ - (void)genericHTTPRequest:(NSURLRequest *)request retryNumber:(NSInteger)retryN if (status != 200) { if ([NSError branchDNSBlockingError:underlyingError]) { [[BranchLogger shared] logWarning:[NSString stringWithFormat:@"Possible DNS Ad Blocker. Giving up on request with HTTP status code %ld", (long)status] error:underlyingError]; + } else if ([NSError branchVPNBlockingError:underlyingError]) { + [[BranchLogger shared] logWarning:[NSString stringWithFormat:@"Possible VPN Ad Blocker. Giving up on request with HTTP status code %ld", (long)status] error:underlyingError]; } else { [[BranchLogger shared] logWarning: [NSString stringWithFormat:@"Giving up on request with HTTP status code %ld", (long)status] error:underlyingError]; } diff --git a/Sources/BranchSDK/BNCURLFilter.m b/Sources/BranchSDK/BNCURLFilter.m index 65cf25ff5..d60ff3827 100644 --- a/Sources/BranchSDK/BNCURLFilter.m +++ b/Sources/BranchSDK/BNCURLFilter.m @@ -133,6 +133,8 @@ - (BOOL)foundUpdatedURLList:(id)operation { } else if (statusCode != 200 || error != nil || jsonString == nil) { if ([NSError branchDNSBlockingError:error]) { [[BranchLogger shared] logWarning:@"Possible DNS Ad Blocker" error:error]; + } else if ([NSError branchVPNBlockingError:error]) { + [[BranchLogger shared] logWarning:@"Possible VPN Ad Blocker" error:error]; } else { [[BranchLogger shared] logWarning:@"Failed to update URL ignore list" error:operation.error]; } diff --git a/Sources/BranchSDK/BranchQRCode.m b/Sources/BranchSDK/BranchQRCode.m index b88bfe068..00dfc850b 100644 --- a/Sources/BranchSDK/BranchQRCode.m +++ b/Sources/BranchSDK/BranchQRCode.m @@ -145,6 +145,8 @@ - (void)callQRCodeAPI:(nullable NSDictionary *)params if (error) { if ([NSError branchDNSBlockingError:error]) { [[BranchLogger shared] logWarning:@"Possible DNS Ad Blocker" error:error]; + } else if ([NSError branchVPNBlockingError:error]) { + [[BranchLogger shared] logWarning:@"Possible VPN Ad Blocker" error:error]; } else { [[BranchLogger shared] logError:@"QR Code request failed" error:error]; completion(nil, error); diff --git a/Sources/BranchSDK/NSError+Branch.m b/Sources/BranchSDK/NSError+Branch.m index 5e06a6987..93f66166c 100644 --- a/Sources/BranchSDK/NSError+Branch.m +++ b/Sources/BranchSDK/NSError+Branch.m @@ -115,4 +115,38 @@ + (BOOL)branchDNSBlockingError:(NSError *)error { return NO; } ++ (BOOL)branchVPNBlockingError:(NSError *)error { + if (error) { + NSError *underlyingError = error.userInfo[@"NSUnderlyingError"]; + if (underlyingError) { + + BOOL isCouldntConnectErrorCode = [@(-1004) isEqual:@(underlyingError.code)]; + BOOL isLocalHostErrorKey = [@(61) isEqual:error.userInfo[@"_kCFStreamErrorCodeKey"]]; + + if ([self isConnectedToVPN] && isCouldntConnectErrorCode && isLocalHostErrorKey) { + return YES; + } + } + } + return NO; +} + ++ (BOOL)isConnectedToVPN { + NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings()); + if (proxySettings) { + NSDictionary *scopedSettings = proxySettings[@"__SCOPED__"]; + if (scopedSettings) { + for (NSString *key in scopedSettings) { + if ([key containsString:@"tap"] || + [key containsString:@"tun"] || + [key containsString:@"ppp"] || + [key containsString:@"ipsec"]) { + return YES; + } + } + } + } + return NO; +} + @end diff --git a/Sources/BranchSDK/Private/NSError+Branch.h b/Sources/BranchSDK/Private/NSError+Branch.h index 07e36c969..5cf6d0087 100644 --- a/Sources/BranchSDK/Private/NSError+Branch.h +++ b/Sources/BranchSDK/Private/NSError+Branch.h @@ -46,6 +46,9 @@ typedef NS_ENUM(NSInteger, BNCErrorCode) { // Checks if an NSError looks like a DNS blocking error + (BOOL)branchDNSBlockingError:(NSError *)error; +// Checks if an NSError looks like a VPN blocking error ++ (BOOL)branchVPNBlockingError:(NSError *)error; + @end NS_ASSUME_NONNULL_END From 25254ce5cfb06b2c45432136b3ac975191f756b2 Mon Sep 17 00:00:00 2001 From: nsingh-branch Date: Tue, 23 Jul 2024 12:10:43 -0700 Subject: [PATCH 2/2] Added documentation --- Sources/BranchSDK/NSError+Branch.m | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Sources/BranchSDK/NSError+Branch.m b/Sources/BranchSDK/NSError+Branch.m index 93f66166c..67d6fa738 100644 --- a/Sources/BranchSDK/NSError+Branch.m +++ b/Sources/BranchSDK/NSError+Branch.m @@ -120,6 +120,14 @@ + (BOOL)branchVPNBlockingError:(NSError *)error { NSError *underlyingError = error.userInfo[@"NSUnderlyingError"]; if (underlyingError) { + /** + `Domain=kCFErrorDomainCFNetwork Code=-1004` indicates that the connection failed because a connection can't be made to the host. + Reference: https://developer.apple.com/documentation/cfnetwork/cfnetworkerrors/kcfurlerrorcannotconnecttohost?language=objc + + `_kCFStreamErrorCodeKey=61` indicates that the connection was refused. + Reference: https://opensource.apple.com/source/xnu/xnu-792/bsd/sys/errno.h.auto.html + */ + BOOL isCouldntConnectErrorCode = [@(-1004) isEqual:@(underlyingError.code)]; BOOL isLocalHostErrorKey = [@(61) isEqual:error.userInfo[@"_kCFStreamErrorCodeKey"]]; @@ -131,6 +139,10 @@ + (BOOL)branchVPNBlockingError:(NSError *)error { return NO; } +/** + Helper method to which checks the device's internet proxy settings for common VPN protocol and interface substrings to determine if a VPN enabled. + https://developer.apple.com/documentation/cfnetwork/cfnetworkcopysystemproxysettings() + */ + (BOOL)isConnectedToVPN { NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings()); if (proxySettings) {