• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19#import "GRPCHost.h"
20
21#import <GRPCClient/GRPCCall+Cronet.h>
22#import <GRPCClient/GRPCCall.h>
23#import <GRPCClient/GRPCCallOptions.h>
24#import <GRPCClient/GRPCTransport.h>
25
26#include <grpc/grpc.h>
27#include <grpc/grpc_security.h>
28
29#import "../../internal/GRPCCallOptions+Internal.h"
30#import "GRPCChannelFactory.h"
31#import "GRPCCompletionQueue.h"
32#import "GRPCSecureChannelFactory.h"
33#import "NSDictionary+GRPC.h"
34
35NS_ASSUME_NONNULL_BEGIN
36
37static NSMutableDictionary *gHostCache;
38
39@implementation GRPCHost {
40  NSString *_PEMRootCertificates;
41  NSString *_PEMPrivateKey;
42  NSString *_PEMCertificateChain;
43}
44
45+ (nullable instancetype)hostWithAddress:(NSString *)address {
46  return [[self alloc] initWithAddress:address];
47}
48
49// Default initializer.
50- (nullable instancetype)initWithAddress:(NSString *)address {
51  if (!address) {
52    return nil;
53  }
54
55  // To provide a default port, we try to interpret the address. If it's just a host name without
56  // scheme and without port, we'll use port 443. If it has a scheme, we pass it untouched to the C
57  // gRPC library.
58  // TODO(jcanizales): Add unit tests for the types of addresses we want to let pass untouched.
59  NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]];
60  if (hostURL.host && hostURL.port == nil) {
61    address = [hostURL.host stringByAppendingString:@":443"];
62  }
63
64  // Look up the GRPCHost in the cache.
65  static dispatch_once_t cacheInitialization;
66  dispatch_once(&cacheInitialization, ^{
67    gHostCache = [NSMutableDictionary dictionary];
68  });
69  @synchronized(gHostCache) {
70    GRPCHost *cachedHost = gHostCache[address];
71    if (cachedHost) {
72      return cachedHost;
73    }
74
75    if ((self = [super init])) {
76      _address = [address copy];
77      _retryEnabled = YES;
78      gHostCache[address] = self;
79    }
80  }
81  return self;
82}
83
84+ (void)resetAllHostSettings {
85  @synchronized(gHostCache) {
86    gHostCache = [NSMutableDictionary dictionary];
87  }
88}
89
90- (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts
91            withPrivateKey:(nullable NSString *)pemPrivateKey
92             withCertChain:(nullable NSString *)pemCertChain
93                     error:(NSError **)errorPtr {
94  _PEMRootCertificates = [pemRootCerts copy];
95  _PEMPrivateKey = [pemPrivateKey copy];
96  _PEMCertificateChain = [pemCertChain copy];
97  return YES;
98}
99
100- (GRPCCallOptions *)callOptions {
101  GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
102  options.userAgentPrefix = _userAgentPrefix;
103  options.responseSizeLimit = _responseSizeLimitOverride;
104  options.compressionAlgorithm = (GRPCCompressionAlgorithm)_compressAlgorithm;
105  options.retryEnabled = _retryEnabled;
106  options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000;
107  options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000;
108  options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000;
109  options.connectInitialBackoff = (NSTimeInterval)_initialConnectBackoff / 1000;
110  options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000;
111  options.PEMRootCertificates = _PEMRootCertificates;
112  options.PEMPrivateKey = _PEMPrivateKey;
113  options.PEMCertificateChain = _PEMCertificateChain;
114  options.hostNameOverride = _hostNameOverride;
115  if (_transportType == GRPCTransportTypeInsecure) {
116    options.transport = GRPCDefaultTransportImplList.core_insecure;
117  } else if ([GRPCCall isUsingCronet]) {
118    options.transport = gGRPCCoreCronetID;
119  } else {
120    options.transport = GRPCDefaultTransportImplList.core_secure;
121  }
122  options.logContext = _logContext;
123
124  return options;
125}
126
127+ (GRPCCallOptions *)callOptionsForHost:(NSString *)host {
128  // TODO (mxyan): Remove when old API is deprecated
129  GRPCCallOptions *callOptions = nil;
130  @synchronized(gHostCache) {
131    GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
132    callOptions = [hostConfig callOptions];
133  }
134  NSAssert(callOptions != nil, @"Unable to create call options object");
135  if (callOptions == nil) {
136    NSLog(@"Unable to create call options object");
137    callOptions = [[GRPCCallOptions alloc] init];
138  }
139  return callOptions;
140}
141
142@end
143
144NS_ASSUME_NONNULL_END
145