1/* 2 * 3 * Copyright 2018 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 "GRPCCallOptions.h" 20#import "GRPCTransport.h" 21#import "internal/GRPCCallOptions+Internal.h" 22 23// The default values for the call options. 24static NSString *const kDefaultServerAuthority = nil; 25static const NSTimeInterval kDefaultTimeout = 0; 26static const BOOL kDefaultFlowControlEnabled = NO; 27static NSArray<id<GRPCInterceptorFactory>> *const kDefaultInterceptorFactories = nil; 28static NSDictionary *const kDefaultInitialMetadata = nil; 29static NSString *const kDefaultUserAgentPrefix = nil; 30static const NSUInteger kDefaultResponseSizeLimit = 0; 31static const GRPCCompressionAlgorithm kDefaultCompressionAlgorithm = GRPCCompressNone; 32static const BOOL kDefaultRetryEnabled = YES; 33static const NSTimeInterval kDefaultKeepaliveInterval = 0; 34static const NSTimeInterval kDefaultKeepaliveTimeout = 0; 35static const NSTimeInterval kDefaultConnectMinTimeout = 0; 36static const NSTimeInterval kDefaultConnectInitialBackoff = 0; 37static const NSTimeInterval kDefaultConnectMaxBackoff = 0; 38static NSDictionary *const kDefaultAdditionalChannelArgs = nil; 39static NSString *const kDefaultPEMRootCertificates = nil; 40static NSString *const kDefaultPEMPrivateKey = nil; 41static NSString *const kDefaultPEMCertificateChain = nil; 42static NSString *const kDefaultOauth2AccessToken = nil; 43static const id<GRPCAuthorizationProtocol> kDefaultAuthTokenProvider = nil; 44static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeChttp2BoringSSL; 45static const GRPCTransportID kDefaultTransport = NULL; 46static NSString *const kDefaultHostNameOverride = nil; 47static const id kDefaultLogContext = nil; 48static NSString *const kDefaultChannelPoolDomain = nil; 49static const NSUInteger kDefaultChannelID = 0; 50 51// Check if two objects are equal. Returns YES if both are nil; 52static BOOL areObjectsEqual(id obj1, id obj2) { 53 if (obj1 == obj2) { 54 return YES; 55 } 56 if (obj1 == nil || obj2 == nil) { 57 return NO; 58 } 59 return [obj1 isEqual:obj2]; 60} 61 62@implementation GRPCCallOptions { 63 @protected 64 NSString *_serverAuthority; 65 NSTimeInterval _timeout; 66 BOOL _flowControlEnabled; 67 NSArray<id<GRPCInterceptorFactory>> *_interceptorFactories; 68 NSString *_oauth2AccessToken; 69 id<GRPCAuthorizationProtocol> _authTokenProvider; 70 NSDictionary *_initialMetadata; 71 NSString *_userAgentPrefix; 72 NSUInteger _responseSizeLimit; 73 GRPCCompressionAlgorithm _compressionAlgorithm; 74 BOOL _retryEnabled; 75 NSTimeInterval _keepaliveInterval; 76 NSTimeInterval _keepaliveTimeout; 77 NSTimeInterval _connectMinTimeout; 78 NSTimeInterval _connectInitialBackoff; 79 NSTimeInterval _connectMaxBackoff; 80 NSDictionary *_additionalChannelArgs; 81 NSString *_PEMRootCertificates; 82 NSString *_PEMPrivateKey; 83 NSString *_PEMCertificateChain; 84 GRPCTransportType _transportType; 85 GRPCTransportID _transport; 86 NSString *_hostNameOverride; 87 id<NSObject> _logContext; 88 NSString *_channelPoolDomain; 89 NSUInteger _channelID; 90} 91 92@synthesize serverAuthority = _serverAuthority; 93@synthesize timeout = _timeout; 94@synthesize flowControlEnabled = _flowControlEnabled; 95@synthesize interceptorFactories = _interceptorFactories; 96@synthesize oauth2AccessToken = _oauth2AccessToken; 97@synthesize authTokenProvider = _authTokenProvider; 98@synthesize initialMetadata = _initialMetadata; 99@synthesize userAgentPrefix = _userAgentPrefix; 100@synthesize responseSizeLimit = _responseSizeLimit; 101@synthesize compressionAlgorithm = _compressionAlgorithm; 102@synthesize retryEnabled = _retryEnabled; 103@synthesize keepaliveInterval = _keepaliveInterval; 104@synthesize keepaliveTimeout = _keepaliveTimeout; 105@synthesize connectMinTimeout = _connectMinTimeout; 106@synthesize connectInitialBackoff = _connectInitialBackoff; 107@synthesize connectMaxBackoff = _connectMaxBackoff; 108@synthesize additionalChannelArgs = _additionalChannelArgs; 109@synthesize PEMRootCertificates = _PEMRootCertificates; 110@synthesize PEMPrivateKey = _PEMPrivateKey; 111@synthesize PEMCertificateChain = _PEMCertificateChain; 112@synthesize transportType = _transportType; 113@synthesize transport = _transport; 114@synthesize hostNameOverride = _hostNameOverride; 115@synthesize logContext = _logContext; 116@synthesize channelPoolDomain = _channelPoolDomain; 117@synthesize channelID = _channelID; 118 119- (instancetype)init { 120 return [self initWithServerAuthority:kDefaultServerAuthority 121 timeout:kDefaultTimeout 122 flowControlEnabled:kDefaultFlowControlEnabled 123 interceptorFactories:kDefaultInterceptorFactories 124 oauth2AccessToken:kDefaultOauth2AccessToken 125 authTokenProvider:kDefaultAuthTokenProvider 126 initialMetadata:kDefaultInitialMetadata 127 userAgentPrefix:kDefaultUserAgentPrefix 128 responseSizeLimit:kDefaultResponseSizeLimit 129 compressionAlgorithm:kDefaultCompressionAlgorithm 130 retryEnabled:kDefaultRetryEnabled 131 keepaliveInterval:kDefaultKeepaliveInterval 132 keepaliveTimeout:kDefaultKeepaliveTimeout 133 connectMinTimeout:kDefaultConnectMinTimeout 134 connectInitialBackoff:kDefaultConnectInitialBackoff 135 connectMaxBackoff:kDefaultConnectMaxBackoff 136 additionalChannelArgs:kDefaultAdditionalChannelArgs 137 PEMRootCertificates:kDefaultPEMRootCertificates 138 PEMPrivateKey:kDefaultPEMPrivateKey 139 PEMCertificateChain:kDefaultPEMCertificateChain 140 transportType:kDefaultTransportType 141 transport:kDefaultTransport 142 hostNameOverride:kDefaultHostNameOverride 143 logContext:kDefaultLogContext 144 channelPoolDomain:kDefaultChannelPoolDomain 145 channelID:kDefaultChannelID]; 146} 147 148- (instancetype)initWithServerAuthority:(NSString *)serverAuthority 149 timeout:(NSTimeInterval)timeout 150 flowControlEnabled:(BOOL)flowControlEnabled 151 interceptorFactories:(NSArray<id<GRPCInterceptorFactory>> *)interceptorFactories 152 oauth2AccessToken:(NSString *)oauth2AccessToken 153 authTokenProvider:(id<GRPCAuthorizationProtocol>)authTokenProvider 154 initialMetadata:(NSDictionary *)initialMetadata 155 userAgentPrefix:(NSString *)userAgentPrefix 156 responseSizeLimit:(NSUInteger)responseSizeLimit 157 compressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm 158 retryEnabled:(BOOL)retryEnabled 159 keepaliveInterval:(NSTimeInterval)keepaliveInterval 160 keepaliveTimeout:(NSTimeInterval)keepaliveTimeout 161 connectMinTimeout:(NSTimeInterval)connectMinTimeout 162 connectInitialBackoff:(NSTimeInterval)connectInitialBackoff 163 connectMaxBackoff:(NSTimeInterval)connectMaxBackoff 164 additionalChannelArgs:(NSDictionary *)additionalChannelArgs 165 PEMRootCertificates:(NSString *)PEMRootCertificates 166 PEMPrivateKey:(NSString *)PEMPrivateKey 167 PEMCertificateChain:(NSString *)PEMCertificateChain 168 transportType:(GRPCTransportType)transportType 169 transport:(GRPCTransportID)transport 170 hostNameOverride:(NSString *)hostNameOverride 171 logContext:(id)logContext 172 channelPoolDomain:(NSString *)channelPoolDomain 173 channelID:(NSUInteger)channelID { 174 if ((self = [super init])) { 175 _serverAuthority = [serverAuthority copy]; 176 _timeout = timeout < 0 ? 0 : timeout; 177 _flowControlEnabled = flowControlEnabled; 178 _interceptorFactories = interceptorFactories; 179 _oauth2AccessToken = [oauth2AccessToken copy]; 180 _authTokenProvider = authTokenProvider; 181 _initialMetadata = initialMetadata == nil 182 ? nil 183 : [[NSDictionary alloc] initWithDictionary:initialMetadata 184 copyItems:YES]; 185 _userAgentPrefix = [userAgentPrefix copy]; 186 _responseSizeLimit = responseSizeLimit; 187 _compressionAlgorithm = compressionAlgorithm; 188 _retryEnabled = retryEnabled; 189 _keepaliveInterval = keepaliveInterval < 0 ? 0 : keepaliveInterval; 190 _keepaliveTimeout = keepaliveTimeout < 0 ? 0 : keepaliveTimeout; 191 _connectMinTimeout = connectMinTimeout < 0 ? 0 : connectMinTimeout; 192 _connectInitialBackoff = connectInitialBackoff < 0 ? 0 : connectInitialBackoff; 193 _connectMaxBackoff = connectMaxBackoff < 0 ? 0 : connectMaxBackoff; 194 _additionalChannelArgs = additionalChannelArgs == nil 195 ? nil 196 : [[NSDictionary alloc] initWithDictionary:additionalChannelArgs 197 copyItems:YES]; 198 _PEMRootCertificates = [PEMRootCertificates copy]; 199 _PEMPrivateKey = [PEMPrivateKey copy]; 200 _PEMCertificateChain = [PEMCertificateChain copy]; 201 _transportType = transportType; 202 _transport = transport; 203 _hostNameOverride = [hostNameOverride copy]; 204 _logContext = logContext; 205 _channelPoolDomain = [channelPoolDomain copy]; 206 _channelID = channelID; 207 } 208 return self; 209} 210 211- (nonnull id)copyWithZone:(NSZone *)zone { 212 GRPCCallOptions *newOptions = 213 [[GRPCCallOptions allocWithZone:zone] initWithServerAuthority:_serverAuthority 214 timeout:_timeout 215 flowControlEnabled:_flowControlEnabled 216 interceptorFactories:_interceptorFactories 217 oauth2AccessToken:_oauth2AccessToken 218 authTokenProvider:_authTokenProvider 219 initialMetadata:_initialMetadata 220 userAgentPrefix:_userAgentPrefix 221 responseSizeLimit:_responseSizeLimit 222 compressionAlgorithm:_compressionAlgorithm 223 retryEnabled:_retryEnabled 224 keepaliveInterval:_keepaliveInterval 225 keepaliveTimeout:_keepaliveTimeout 226 connectMinTimeout:_connectMinTimeout 227 connectInitialBackoff:_connectInitialBackoff 228 connectMaxBackoff:_connectMaxBackoff 229 additionalChannelArgs:_additionalChannelArgs 230 PEMRootCertificates:_PEMRootCertificates 231 PEMPrivateKey:_PEMPrivateKey 232 PEMCertificateChain:_PEMCertificateChain 233 transportType:_transportType 234 transport:_transport 235 hostNameOverride:_hostNameOverride 236 logContext:_logContext 237 channelPoolDomain:_channelPoolDomain 238 channelID:_channelID]; 239 return newOptions; 240} 241 242- (nonnull id)mutableCopyWithZone:(NSZone *)zone { 243 GRPCMutableCallOptions *newOptions = [[GRPCMutableCallOptions allocWithZone:zone] 244 initWithServerAuthority:[_serverAuthority copy] 245 timeout:_timeout 246 flowControlEnabled:_flowControlEnabled 247 interceptorFactories:_interceptorFactories 248 oauth2AccessToken:[_oauth2AccessToken copy] 249 authTokenProvider:_authTokenProvider 250 initialMetadata:[[NSDictionary alloc] initWithDictionary:_initialMetadata 251 copyItems:YES] 252 userAgentPrefix:[_userAgentPrefix copy] 253 responseSizeLimit:_responseSizeLimit 254 compressionAlgorithm:_compressionAlgorithm 255 retryEnabled:_retryEnabled 256 keepaliveInterval:_keepaliveInterval 257 keepaliveTimeout:_keepaliveTimeout 258 connectMinTimeout:_connectMinTimeout 259 connectInitialBackoff:_connectInitialBackoff 260 connectMaxBackoff:_connectMaxBackoff 261 additionalChannelArgs:[[NSDictionary alloc] initWithDictionary:_additionalChannelArgs 262 copyItems:YES] 263 PEMRootCertificates:[_PEMRootCertificates copy] 264 PEMPrivateKey:[_PEMPrivateKey copy] 265 PEMCertificateChain:[_PEMCertificateChain copy] 266 transportType:_transportType 267 transport:_transport 268 hostNameOverride:[_hostNameOverride copy] 269 logContext:_logContext 270 channelPoolDomain:[_channelPoolDomain copy] 271 channelID:_channelID]; 272 return newOptions; 273} 274 275- (BOOL)hasChannelOptionsEqualTo:(GRPCCallOptions *)callOptions { 276 if (callOptions == nil) return NO; 277 if (!areObjectsEqual(callOptions.userAgentPrefix, _userAgentPrefix)) return NO; 278 if (!(callOptions.responseSizeLimit == _responseSizeLimit)) return NO; 279 if (!(callOptions.compressionAlgorithm == _compressionAlgorithm)) return NO; 280 if (!(callOptions.retryEnabled == _retryEnabled)) return NO; 281 if (!(callOptions.keepaliveInterval == _keepaliveInterval)) return NO; 282 if (!(callOptions.keepaliveTimeout == _keepaliveTimeout)) return NO; 283 if (!(callOptions.connectMinTimeout == _connectMinTimeout)) return NO; 284 if (!(callOptions.connectInitialBackoff == _connectInitialBackoff)) return NO; 285 if (!(callOptions.connectMaxBackoff == _connectMaxBackoff)) return NO; 286 if (!areObjectsEqual(callOptions.additionalChannelArgs, _additionalChannelArgs)) return NO; 287 if (!areObjectsEqual(callOptions.PEMRootCertificates, _PEMRootCertificates)) return NO; 288 if (!areObjectsEqual(callOptions.PEMPrivateKey, _PEMPrivateKey)) return NO; 289 if (!areObjectsEqual(callOptions.PEMCertificateChain, _PEMCertificateChain)) return NO; 290 if (!areObjectsEqual(callOptions.hostNameOverride, _hostNameOverride)) return NO; 291 if (!(callOptions.transportType == _transportType)) return NO; 292 if (!(TransportIDIsEqual(callOptions.transport, _transport))) return NO; 293 if (!areObjectsEqual(callOptions.logContext, _logContext)) return NO; 294 if (!areObjectsEqual(callOptions.channelPoolDomain, _channelPoolDomain)) return NO; 295 if (!(callOptions.channelID == _channelID)) return NO; 296 297 return YES; 298} 299 300- (NSUInteger)channelOptionsHash { 301 NSUInteger result = 0; 302 result ^= _userAgentPrefix.hash; 303 result ^= _responseSizeLimit; 304 result ^= _compressionAlgorithm; 305 result ^= _retryEnabled; 306 result ^= (unsigned int)(_keepaliveInterval * 1000); 307 result ^= (unsigned int)(_keepaliveTimeout * 1000); 308 result ^= (unsigned int)(_connectMinTimeout * 1000); 309 result ^= (unsigned int)(_connectInitialBackoff * 1000); 310 result ^= (unsigned int)(_connectMaxBackoff * 1000); 311 result ^= _additionalChannelArgs.hash; 312 result ^= _PEMRootCertificates.hash; 313 result ^= _PEMPrivateKey.hash; 314 result ^= _PEMCertificateChain.hash; 315 result ^= _hostNameOverride.hash; 316 result ^= _transportType; 317 result ^= TransportIDHash(_transport); 318 result ^= _logContext.hash; 319 result ^= _channelPoolDomain.hash; 320 result ^= _channelID; 321 322 return result; 323} 324 325@end 326 327@implementation GRPCMutableCallOptions 328 329@dynamic serverAuthority; 330@dynamic timeout; 331@dynamic flowControlEnabled; 332@dynamic interceptorFactories; 333@dynamic oauth2AccessToken; 334@dynamic authTokenProvider; 335@dynamic initialMetadata; 336@dynamic userAgentPrefix; 337@dynamic responseSizeLimit; 338@dynamic compressionAlgorithm; 339@dynamic retryEnabled; 340@dynamic keepaliveInterval; 341@dynamic keepaliveTimeout; 342@dynamic connectMinTimeout; 343@dynamic connectInitialBackoff; 344@dynamic connectMaxBackoff; 345@dynamic additionalChannelArgs; 346@dynamic PEMRootCertificates; 347@dynamic PEMPrivateKey; 348@dynamic PEMCertificateChain; 349@dynamic transportType; 350@dynamic transport; 351@dynamic hostNameOverride; 352@dynamic logContext; 353@dynamic channelPoolDomain; 354@dynamic channelID; 355 356- (instancetype)init { 357 return [self initWithServerAuthority:kDefaultServerAuthority 358 timeout:kDefaultTimeout 359 flowControlEnabled:kDefaultFlowControlEnabled 360 interceptorFactories:kDefaultInterceptorFactories 361 oauth2AccessToken:kDefaultOauth2AccessToken 362 authTokenProvider:kDefaultAuthTokenProvider 363 initialMetadata:kDefaultInitialMetadata 364 userAgentPrefix:kDefaultUserAgentPrefix 365 responseSizeLimit:kDefaultResponseSizeLimit 366 compressionAlgorithm:kDefaultCompressionAlgorithm 367 retryEnabled:kDefaultRetryEnabled 368 keepaliveInterval:kDefaultKeepaliveInterval 369 keepaliveTimeout:kDefaultKeepaliveTimeout 370 connectMinTimeout:kDefaultConnectMinTimeout 371 connectInitialBackoff:kDefaultConnectInitialBackoff 372 connectMaxBackoff:kDefaultConnectMaxBackoff 373 additionalChannelArgs:kDefaultAdditionalChannelArgs 374 PEMRootCertificates:kDefaultPEMRootCertificates 375 PEMPrivateKey:kDefaultPEMPrivateKey 376 PEMCertificateChain:kDefaultPEMCertificateChain 377 transportType:kDefaultTransportType 378 transport:kDefaultTransport 379 hostNameOverride:kDefaultHostNameOverride 380 logContext:kDefaultLogContext 381 channelPoolDomain:kDefaultChannelPoolDomain 382 channelID:kDefaultChannelID]; 383} 384 385- (nonnull id)copyWithZone:(NSZone *)zone { 386 GRPCCallOptions *newOptions = 387 [[GRPCCallOptions allocWithZone:zone] initWithServerAuthority:_serverAuthority 388 timeout:_timeout 389 flowControlEnabled:_flowControlEnabled 390 interceptorFactories:_interceptorFactories 391 oauth2AccessToken:_oauth2AccessToken 392 authTokenProvider:_authTokenProvider 393 initialMetadata:_initialMetadata 394 userAgentPrefix:_userAgentPrefix 395 responseSizeLimit:_responseSizeLimit 396 compressionAlgorithm:_compressionAlgorithm 397 retryEnabled:_retryEnabled 398 keepaliveInterval:_keepaliveInterval 399 keepaliveTimeout:_keepaliveTimeout 400 connectMinTimeout:_connectMinTimeout 401 connectInitialBackoff:_connectInitialBackoff 402 connectMaxBackoff:_connectMaxBackoff 403 additionalChannelArgs:_additionalChannelArgs 404 PEMRootCertificates:_PEMRootCertificates 405 PEMPrivateKey:_PEMPrivateKey 406 PEMCertificateChain:_PEMCertificateChain 407 transportType:_transportType 408 transport:_transport 409 hostNameOverride:_hostNameOverride 410 logContext:_logContext 411 channelPoolDomain:_channelPoolDomain 412 channelID:_channelID]; 413 return newOptions; 414} 415 416- (nonnull id)mutableCopyWithZone:(NSZone *)zone { 417 GRPCMutableCallOptions *newOptions = [[GRPCMutableCallOptions allocWithZone:zone] 418 initWithServerAuthority:_serverAuthority 419 timeout:_timeout 420 flowControlEnabled:_flowControlEnabled 421 interceptorFactories:_interceptorFactories 422 oauth2AccessToken:_oauth2AccessToken 423 authTokenProvider:_authTokenProvider 424 initialMetadata:_initialMetadata 425 userAgentPrefix:_userAgentPrefix 426 responseSizeLimit:_responseSizeLimit 427 compressionAlgorithm:_compressionAlgorithm 428 retryEnabled:_retryEnabled 429 keepaliveInterval:_keepaliveInterval 430 keepaliveTimeout:_keepaliveTimeout 431 connectMinTimeout:_connectMinTimeout 432 connectInitialBackoff:_connectInitialBackoff 433 connectMaxBackoff:_connectMaxBackoff 434 additionalChannelArgs:[_additionalChannelArgs copy] 435 PEMRootCertificates:_PEMRootCertificates 436 PEMPrivateKey:_PEMPrivateKey 437 PEMCertificateChain:_PEMCertificateChain 438 transportType:_transportType 439 transport:_transport 440 hostNameOverride:_hostNameOverride 441 logContext:_logContext 442 channelPoolDomain:_channelPoolDomain 443 channelID:_channelID]; 444 return newOptions; 445} 446 447- (void)setServerAuthority:(NSString *)serverAuthority { 448 _serverAuthority = [serverAuthority copy]; 449} 450 451- (void)setTimeout:(NSTimeInterval)timeout { 452 if (timeout < 0) { 453 _timeout = 0; 454 } else { 455 _timeout = timeout; 456 } 457} 458 459- (void)setFlowControlEnabled:(BOOL)flowControlEnabled { 460 _flowControlEnabled = flowControlEnabled; 461} 462 463- (void)setInterceptorFactories:(NSArray<id<GRPCInterceptorFactory>> *)interceptorFactories { 464 _interceptorFactories = interceptorFactories; 465} 466 467- (void)setOauth2AccessToken:(NSString *)oauth2AccessToken { 468 _oauth2AccessToken = [oauth2AccessToken copy]; 469} 470 471- (void)setAuthTokenProvider:(id<GRPCAuthorizationProtocol>)authTokenProvider { 472 _authTokenProvider = authTokenProvider; 473} 474 475- (void)setInitialMetadata:(NSDictionary *)initialMetadata { 476 _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; 477} 478 479- (void)setUserAgentPrefix:(NSString *)userAgentPrefix { 480 _userAgentPrefix = [userAgentPrefix copy]; 481} 482 483- (void)setResponseSizeLimit:(NSUInteger)responseSizeLimit { 484 _responseSizeLimit = responseSizeLimit; 485} 486 487- (void)setCompressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm { 488 _compressionAlgorithm = compressionAlgorithm; 489} 490 491- (void)setRetryEnabled:(BOOL)retryEnabled { 492 _retryEnabled = retryEnabled; 493} 494 495- (void)setKeepaliveInterval:(NSTimeInterval)keepaliveInterval { 496 if (keepaliveInterval < 0) { 497 _keepaliveInterval = 0; 498 } else { 499 _keepaliveInterval = keepaliveInterval; 500 } 501} 502 503- (void)setKeepaliveTimeout:(NSTimeInterval)keepaliveTimeout { 504 if (keepaliveTimeout < 0) { 505 _keepaliveTimeout = 0; 506 } else { 507 _keepaliveTimeout = keepaliveTimeout; 508 } 509} 510 511- (void)setConnectMinTimeout:(NSTimeInterval)connectMinTimeout { 512 if (connectMinTimeout < 0) { 513 _connectMinTimeout = 0; 514 } else { 515 _connectMinTimeout = connectMinTimeout; 516 } 517} 518 519- (void)setConnectInitialBackoff:(NSTimeInterval)connectInitialBackoff { 520 if (connectInitialBackoff < 0) { 521 _connectInitialBackoff = 0; 522 } else { 523 _connectInitialBackoff = connectInitialBackoff; 524 } 525} 526 527- (void)setConnectMaxBackoff:(NSTimeInterval)connectMaxBackoff { 528 if (connectMaxBackoff < 0) { 529 _connectMaxBackoff = 0; 530 } else { 531 _connectMaxBackoff = connectMaxBackoff; 532 } 533} 534 535- (void)setAdditionalChannelArgs:(NSDictionary *)additionalChannelArgs { 536 _additionalChannelArgs = [[NSDictionary alloc] initWithDictionary:additionalChannelArgs 537 copyItems:YES]; 538} 539 540- (void)setPEMRootCertificates:(NSString *)PEMRootCertificates { 541 _PEMRootCertificates = [PEMRootCertificates copy]; 542} 543 544- (void)setPEMPrivateKey:(NSString *)PEMPrivateKey { 545 _PEMPrivateKey = [PEMPrivateKey copy]; 546} 547 548- (void)setPEMCertificateChain:(NSString *)PEMCertificateChain { 549 _PEMCertificateChain = [PEMCertificateChain copy]; 550} 551 552- (void)setTransportType:(GRPCTransportType)transportType { 553 _transportType = transportType; 554} 555 556- (void)setTransport:(GRPCTransportID)transport { 557 _transport = transport; 558} 559 560- (void)setHostNameOverride:(NSString *)hostNameOverride { 561 _hostNameOverride = [hostNameOverride copy]; 562} 563 564- (void)setLogContext:(id)logContext { 565 _logContext = logContext; 566} 567 568- (void)setChannelPoolDomain:(NSString *)channelPoolDomain { 569 _channelPoolDomain = [channelPoolDomain copy]; 570} 571 572- (void)setChannelID:(NSUInteger)channelID { 573 _channelID = channelID; 574} 575 576@end 577