xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/GRPCClient/private/GRPCCore/GRPCHost.mm (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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  if (![address hasPrefix:@"dns:"] && ![address hasPrefix:@"unix:"] &&
60      ![address hasPrefix:@"ipv4:"] && ![address hasPrefix:@"ipv6:"]) {
61    NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]];
62    if (hostURL.host && hostURL.port == nil) {
63      address = [hostURL.host stringByAppendingString:@":443"];
64    }
65  }
66
67  // Look up the GRPCHost in the cache.
68  static dispatch_once_t cacheInitialization;
69  dispatch_once(&cacheInitialization, ^{
70    gHostCache = [NSMutableDictionary dictionary];
71  });
72  @synchronized(gHostCache) {
73    GRPCHost *cachedHost = gHostCache[address];
74    if (cachedHost) {
75      return cachedHost;
76    }
77
78    if ((self = [super init])) {
79      _address = [address copy];
80      _retryEnabled = YES;
81      gHostCache[address] = self;
82    }
83  }
84  return self;
85}
86
87+ (void)resetAllHostSettings {
88  @synchronized(gHostCache) {
89    gHostCache = [NSMutableDictionary dictionary];
90  }
91}
92
93- (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts
94            withPrivateKey:(nullable NSString *)pemPrivateKey
95             withCertChain:(nullable NSString *)pemCertChain
96                     error:(NSError **)errorPtr {
97  _PEMRootCertificates = [pemRootCerts copy];
98  _PEMPrivateKey = [pemPrivateKey copy];
99  _PEMCertificateChain = [pemCertChain copy];
100  return YES;
101}
102
103- (GRPCCallOptions *)callOptions {
104  GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
105  options.userAgentPrefix = _userAgentPrefix;
106  options.userAgentSuffix = _userAgentSuffix;
107  options.responseSizeLimit = _responseSizeLimitOverride;
108  options.compressionAlgorithm = (GRPCCompressionAlgorithm)_compressAlgorithm;
109  options.retryEnabled = _retryEnabled;
110  options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000;
111  options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000;
112  options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000;
113  options.connectInitialBackoff = (NSTimeInterval)_initialConnectBackoff / 1000;
114  options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000;
115  options.PEMRootCertificates = _PEMRootCertificates;
116  options.PEMPrivateKey = _PEMPrivateKey;
117  options.PEMCertificateChain = _PEMCertificateChain;
118  options.hostNameOverride = _hostNameOverride;
119  if (_transportType == GRPCTransportTypeInsecure) {
120    options.transport = GRPCDefaultTransportImplList.core_insecure;
121  } else if ([GRPCCall isUsingCronet]) {
122    options.transport = gGRPCCoreCronetID;
123  } else {
124    options.transport = GRPCDefaultTransportImplList.core_secure;
125  }
126  options.logContext = _logContext;
127
128  return options;
129}
130
131+ (GRPCCallOptions *)callOptionsForHost:(NSString *)host {
132  // TODO (mxyan): Remove when old API is deprecated
133  GRPCCallOptions *callOptions = nil;
134  @synchronized(gHostCache) {
135    GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
136    callOptions = [hostConfig callOptions];
137  }
138  NSAssert(callOptions != nil, @"Unable to create call options object");
139  if (callOptions == nil) {
140    NSLog(@"Unable to create call options object");
141    callOptions = [[GRPCCallOptions alloc] init];
142  }
143  return callOptions;
144}
145
146@end
147
148NS_ASSUME_NONNULL_END
149