aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/objective-c
diff options
context:
space:
mode:
Diffstat (limited to 'src/objective-c')
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m40
-rw-r--r--src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h3
-rw-r--r--src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m17
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.m13
-rw-r--r--src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h1
-rw-r--r--src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.pbxproj2
6 files changed, 55 insertions, 21 deletions
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index 43204345f5..bbfb5aa45f 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -375,20 +375,6 @@ static NSMutableDictionary *callFlags;
_state = GRXWriterStateStarted;
}
- // Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled).
- // This makes RPCs in which the call isn't externally retained possible (as long as it is started
- // before being autoreleased).
- // Care is taken not to retain self strongly in any of the blocks used in this implementation, so
- // that the life of the instance is determined by this retain cycle.
- _retainSelf = self;
-
- _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable];
-
- _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path];
- NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
-
- [self sendHeaders:_requestHeaders];
- [self invokeCall];
// TODO(jcanizales): Extract this logic somewhere common.
NSString *host = [NSURL URLWithString:[@"https://" stringByAppendingString:_host]].host;
if (!host) {
@@ -397,15 +383,35 @@ static NSMutableDictionary *callFlags;
}
__weak typeof(self) weakSelf = self;
_connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host];
- [_connectivityMonitor handleLossWithHandler:^{
+ void (^handler)() = ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeUnavailable
userInfo:@{NSLocalizedDescriptionKey: @"Connectivity lost."}]];
- [[GRPCHost hostWithAddress:strongSelf->_host] disconnect];
}
- }];
+ };
+ [_connectivityMonitor handleLossWithHandler:handler
+ wifiStatusChangeHandler:handler];
+
+ // Create a retain cycle so that this instance lives until the RPC finishes
+ // (or is cancelled).
+ // This makes RPCs in which the call isn't externally retained possible (as
+ // long as it is started
+ // before being autoreleased).
+ // Care is taken not to retain self strongly in any of the blocks used in this
+ // implementation, so
+ // that the life of the instance is determined by this retain cycle.
+ _retainSelf = self;
+
+ _responseWriteable =
+ [[GRXConcurrentWriteable alloc] initWithWriteable:writeable];
+
+ _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path];
+ NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
+
+ [self sendHeaders:_requestHeaders];
+ [self invokeCall];
}
- (void)setState:(GRXWriterState)newState {
diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
index 2fae410331..8d5c1b3e68 100644
--- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
+++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
@@ -73,5 +73,6 @@
* Only one handler is active at a time, so if this method is called again before the previous
* handler has been called, it might never be called at all (or yes, if it has already been queued).
*/
-- (void)handleLossWithHandler:(nonnull void (^)())handler;
+- (void)handleLossWithHandler:(void (^)())handler
+ wifiStatusChangeHandler:(void (^)())wifiStatusChangeHandler;
@end
diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
index b4061bd5ef..d736c5e6b0 100644
--- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
+++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
@@ -120,6 +120,7 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
@implementation GRPCConnectivityMonitor {
SCNetworkReachabilityRef _reachabilityRef;
+ GRPCReachabilityFlags *_previousReachabilityFlags;
}
- (nullable instancetype)initWithReachability:(nullable SCNetworkReachabilityRef)reachability {
@@ -129,6 +130,13 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
if ((self = [super init])) {
_reachabilityRef = CFRetain(reachability);
_queue = dispatch_get_main_queue();
+ SCNetworkReachabilityFlags flags;
+ if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) {
+ _previousReachabilityFlags =
+ [[GRPCReachabilityFlags alloc] initWithFlags:flags];
+ } else {
+ _previousReachabilityFlags = 0;
+ }
}
return self;
}
@@ -149,11 +157,16 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
return returnValue;
}
-- (void)handleLossWithHandler:(void (^)())handler {
+- (void)handleLossWithHandler:(void (^)())handler
+ wifiStatusChangeHandler:(nonnull void (^)())wifiStatusChangeHandler {
[self startListeningWithHandler:^(GRPCReachabilityFlags *flags) {
- if (!flags.isHostReachable) {
+ if (!flags.reachable && handler) {
handler();
+ } else if (flags.isWWAN ^ _previousReachabilityFlags.isWWAN &&
+ wifiStatusChangeHandler) {
+ wifiStatusChangeHandler();
}
+ _previousReachabilityFlags = flags;
}];
}
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index f8634b448e..ee6045653e 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -43,6 +43,7 @@
#import "GRPCChannel.h"
#import "GRPCCompletionQueue.h"
+#import "GRPCConnectivityMonitor.h"
#import "NSDictionary+GRPC.h"
NS_ASSUME_NONNULL_BEGIN
@@ -52,6 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
#define GRPC_OBJC_VERSION_STRING @"1.0.0"
static NSMutableDictionary *kHostCache;
+static GRPCConnectivityMonitor *connectivityMonitor = nil;
@implementation GRPCHost {
// TODO(mlumish): Investigate whether caching channels with strong links is a good idea.
@@ -98,6 +100,16 @@ static NSMutableDictionary *kHostCache;
_address = address;
_secure = YES;
kHostCache[address] = self;
+
+ if (!connectivityMonitor) {
+ connectivityMonitor =
+ [GRPCConnectivityMonitor monitorWithHost:hostURL.host];
+ void (^handler)() = ^{
+ [GRPCHost flushChannelCache];
+ };
+ [connectivityMonitor handleLossWithHandler:handler
+ wifiStatusChangeHandler:handler];
+ }
}
}
return self;
@@ -110,6 +122,7 @@ static NSMutableDictionary *kHostCache;
BOOL * _Nonnull stop) {
[host disconnect];
}];
+ connectivityMonitor = nil;
}
}
diff --git a/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h b/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
index 4b92504b55..1c907877a0 100644
--- a/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
+++ b/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
@@ -65,3 +65,4 @@ GRPC_XMACRO_ITEM(interventionRequired, InterventionRequired)
GRPC_XMACRO_ITEM(connectionOnDemand, ConnectionOnDemand)
GRPC_XMACRO_ITEM(isLocalAddress, IsLocalAddress)
GRPC_XMACRO_ITEM(isDirect, IsDirect)
+GRPC_XMACRO_ITEM(isWWAN, IsWWAN)
diff --git a/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.pbxproj b/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.pbxproj
index 2a9466c03f..3f26c98564 100644
--- a/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.pbxproj
+++ b/src/objective-c/tests/Connectivity/ConnectivityTestingApp.xcodeproj/project.pbxproj
@@ -156,7 +156,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
+ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
5347BF6C41E7888C1C05CD88 /* [CP] Copy Pods Resources */ = {