Add protocol and corresponding changes in GRPCClient
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index 8723624..3b937ac 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -40,10 +40,14 @@
 NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
 static NSMutableDictionary *callFlags;
 
+static NSString * const kAuthorizationHeader = @"authorization";
+static NSString * const kBearerPrefix = @"Bearer ";
+
 @interface GRPCCall () <GRXWriteable>
 // Make them read-write.
 @property(atomic, strong) NSDictionary *responseHeaders;
 @property(atomic, strong) NSDictionary *responseTrailers;
+@property(atomic) BOOL isWaitingForToken;
 @end
 
 // The following methods of a C gRPC call object aren't reentrant, and thus
@@ -211,7 +215,11 @@
   [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
                                             code:GRPCErrorCodeCancelled
                                         userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]];
-  [self cancelCall];
+  if (!self.isWaitingForToken) {
+    [self cancelCall];
+  } else {
+    self.isWaitingForToken = NO;
+  }
 }
 
 - (void)dealloc {
@@ -422,33 +430,55 @@
   // that the life of the instance is determined by this retain cycle.
   _retainSelf = self;
 
-  _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable
-                                                           dispatchQueue:_responseQueue];
-
-  _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host serverName:_serverName 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) {
-    // TODO(jcanizales): Check this on init.
-    [NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", _host];
-  }
   __weak typeof(self) weakSelf = self;
-  _connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host];
-  void (^handler)() = ^{
+  void (^performCall)() = ^{
     typeof(self) strongSelf = weakSelf;
     if (strongSelf) {
-      [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
-                                                      code:GRPCErrorCodeUnavailable
-                                                  userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]];
+      strongSelf->_responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable
+                                                                           dispatchQueue:strongSelf->_responseQueue];
+
+      strongSelf->_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:strongSelf->_host
+                                                            serverName:strongSelf->_serverName
+                                                                  path:strongSelf->_path];
+      NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
+
+      [strongSelf sendHeaders:_requestHeaders];
+      [strongSelf invokeCall];
+
+      // TODO(jcanizales): Extract this logic somewhere common.
+      NSString *host = [NSURL URLWithString:[@"https://" stringByAppendingString:strongSelf->_host]].host;
+      if (!host) {
+        // TODO(jcanizales): Check this on init.
+        [NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", strongSelf->_host];
+      }
+      strongSelf->_connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host];
+      void (^handler)() = ^{
+        typeof(self) strongSelf = weakSelf;
+        [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+                                                        code:GRPCErrorCodeUnavailable
+                                                    userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]];
+      };
+      [_connectivityMonitor handleLossWithHandler:handler
+                          wifiStatusChangeHandler:nil];
     }
   };
-  [_connectivityMonitor handleLossWithHandler:handler
-                      wifiStatusChangeHandler:nil];
+
+  if (self.oauthToken != nil) {
+    self.isWaitingForToken = YES;
+    [self.oauthToken getTokenWithHandler:^(NSString *token){
+      typeof(self) strongSelf = weakSelf;
+      if (strongSelf && strongSelf.isWaitingForToken) {
+        if (token) {
+          NSString *t = [kBearerPrefix stringByAppendingString:token];
+          strongSelf.requestHeaders[kAuthorizationHeader] = t;
+        }
+        performCall();
+        strongSelf.isWaitingForToken = NO;
+      }
+    }];
+  } else {
+    performCall();
+  }
 }
 
 - (void)setState:(GRXWriterState)newState {