diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9b9b4f95471..3d06aa929bb 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -35,6 +35,7 @@ #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" +#import "private/utilities.h" // At most 6 ops can be in an op batch for a client: SEND_INITIAL_METADATA, // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT, RECV_INITIAL_METADATA, RECV_MESSAGE, @@ -67,7 +68,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @implementation GRPCRequestOptions - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { - NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); + GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, @"Host and Path cannot be empty"); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -114,15 +115,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *_Nullable)callOptions { - if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; - } - if (requestOptions.safety > GRPCCallSafetyCacheableRequest) { - [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; - } - if (responseHandler == nil) { - [NSException raise:NSInvalidArgumentException format:@"Response handler required."]; - } + GRPCAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, NSInvalidArgumentException, @"Neither host nor path can be nil."); + GRPCAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, @"Invalid call safety value."); + GRPCAssert(responseHandler != nil, NSInvalidArgumentException, @"Response handler required."); if ((self = [super init])) { _requestOptions = [requestOptions copy]; @@ -159,8 +154,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)start { dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_started, @"Call already started."); - NSAssert(!self->_canceled, @"Call already canceled."); + GRPCAssert(!self->_started, NSInternalInconsistencyException, @"Call already started."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); self->_started = YES; if (!self->_callOptions) { self->_callOptions = [[GRPCCallOptions alloc] init]; @@ -216,7 +211,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_canceled, @"Call already canceled."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); if (self->_call) { [self->_call cancel]; self->_call = nil; @@ -244,8 +239,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_canceled, @"Call arleady canceled."); - NSAssert(!self->_finished, @"Call is half-closed before sending data."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); + GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call is half-closed before sending data."); if (self->_call) { [self->_pipe writeValue:data]; } @@ -254,9 +249,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)finish { dispatch_async(_dispatchQueue, ^{ - NSAssert(self->_started, @"Call not started."); - NSAssert(!self->_canceled, @"Call arleady canceled."); - NSAssert(!self->_finished, @"Call already half-closed."); + GRPCAssert(self->_started, NSInternalInconsistencyException, @"Call not started."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); + GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call already half-closed."); if (self->_call) { [self->_pipe writesFinishedWithError:nil]; } @@ -404,16 +399,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. - if (!host || !path) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; - } - if (safety > GRPCCallSafetyCacheableRequest) { - [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; - } - if (requestWriter.state != GRXWriterStateNotStarted) { - [NSException raise:NSInvalidArgumentException - format:@"The requests writer can't be already started."]; - } + GRPCAssert(host && path, NSInvalidArgumentException, @"Neither host nor path can be nil."); + GRPCAssert(safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, @"Invalid call safety value."); + GRPCAssert(requestWriter.state == GRXWriterStateNotStarted, NSInvalidArgumentException, @"The requests writer can't be already started."); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -798,8 +786,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } - NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, - @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); + GRPCAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, NSInvalidArgumentException, @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { self.isWaitingForToken = YES; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 4f26b349b49..7d0baa91ee6 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -28,6 +28,7 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" +#import "utilities.h" #import "../internal/GRPCCallOptions+Internal.h" #import @@ -39,8 +40,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelConfiguration - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { - NSAssert(host.length, @"Host must not be empty."); - NSAssert(callOptions, @"callOptions must not be empty."); + GRPCAssert(host.length, NSInvalidArgumentException, @"Host must not be empty."); + GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); if ((self = [super init])) { _host = [host copy]; _callOptions = [callOptions copy]; @@ -192,8 +193,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay { - NSAssert(channelConfiguration, @"channelConfiguration must not be empty."); - NSAssert(destroyDelay > 0, @"destroyDelay must be greater than 0."); + GRPCAssert(channelConfiguration != nil, NSInvalidArgumentException, @"channelConfiguration must not be empty."); + GRPCAssert(destroyDelay > 0, NSInvalidArgumentException, @"destroyDelay must be greater than 0."); if ((self = [super init])) { _configuration = [channelConfiguration copy]; if (@available(iOS 8.0, *)) { @@ -206,7 +207,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; // Create gRPC core channel object. NSString *host = channelConfiguration.host; - NSAssert(host.length != 0, @"host cannot be nil"); + GRPCAssert(host.length != 0, NSInvalidArgumentException, @"host cannot be nil"); NSDictionary *channelArgs; if (channelConfiguration.callOptions.additionalChannelArgs.count != 0) { NSMutableDictionary *args = [channelConfiguration.channelArgs mutableCopy]; @@ -231,21 +232,21 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions disconnected:(BOOL *)disconnected { - NSAssert(path.length, @"path must not be empty."); - NSAssert(queue, @"completionQueue must not be empty."); - NSAssert(callOptions, @"callOptions must not be empty."); + GRPCAssert(path.length, NSInvalidArgumentException, @"path must not be empty."); + GRPCAssert(queue, NSInvalidArgumentException, @"completionQueue must not be empty."); + GRPCAssert(callOptions, NSInvalidArgumentException, @"callOptions must not be empty."); __block BOOL isDisconnected = NO; __block grpc_call *call = NULL; dispatch_sync(_dispatchQueue, ^{ if (self->_disconnected) { isDisconnected = YES; } else { - NSAssert(self->_unmanagedChannel != NULL, @"Invalid channel."); + GRPCAssert(self->_unmanagedChannel != NULL, NSInvalidArgumentException, @"Invalid channel."); NSString *serverAuthority = callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; - NSAssert(timeout >= 0, @"Invalid timeout"); + GRPCAssert(timeout >= 0, NSInvalidArgumentException, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); if (serverAuthority) { host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 98c1634bc8b..8a3b5edfa12 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -27,6 +27,7 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" +#import "utilities.h" #import #include @@ -43,9 +44,7 @@ static dispatch_once_t gInitChannelPool; + (nullable instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ gChannelPool = [[GRPCChannelPool alloc] init]; - if (gChannelPool == nil) { - [NSException raise:NSMallocException format:@"Cannot initialize global channel pool."]; - } + GRPCAssert(gChannelPool != nil, NSMallocException, @"Cannot initialize global channel pool."); }); return gChannelPool; } @@ -73,8 +72,8 @@ static dispatch_once_t gInitChannelPool; - (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions destroyDelay:(NSTimeInterval)destroyDelay { - NSAssert(host.length > 0, @"Host must not be empty."); - NSAssert(callOptions != nil, @"callOptions must not be empty."); + GRPCAssert(host.length > 0, NSInvalidArgumentException, @"Host must not be empty."); + GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); GRPCChannel *channel; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index a67162c1014..14d07e949b7 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -33,6 +33,7 @@ #import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" #import "version.h" +#import "utilities.h" NS_ASSUME_NONNULL_BEGIN @@ -121,7 +122,7 @@ static NSMutableDictionary *gHostCache; if (_transportType == GRPCTransportTypeInsecure) { options.transportType = GRPCTransportTypeInsecure; } else { - NSAssert(_transportType == GRPCTransportTypeDefault, @"Invalid transport type"); + GRPCAssert(_transportType == GRPCTransportTypeDefault, NSInvalidArgumentException, @"Invalid transport type"); options.transportType = GRPCTransportTypeCronet; } } else diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 1f6458c5247..3079394ed8a 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -22,6 +22,7 @@ #import "ChannelArgsUtil.h" #import "GRPCChannel.h" +#import "utilities.h" NS_ASSUME_NONNULL_BEGIN @@ -82,8 +83,9 @@ NS_ASSUME_NONNULL_BEGIN if (errorPtr) { *errorPtr = defaultRootsError; } - NSAssert( + GRPCAssertWithArgument( defaultRootsASCII, + NSObjectNotAvailableException, @"Could not read gRPCCertificates.bundle/roots.pem. This file, " "with the root certificates, is needed to establish secure (TLS) connections. " "Because the file is distributed with the gRPC library, this error is usually a sign " diff --git a/src/objective-c/GRPCClient/private/utilities.h b/src/objective-c/GRPCClient/private/utilities.h new file mode 100644 index 00000000000..c664e8bf9df --- /dev/null +++ b/src/objective-c/GRPCClient/private/utilities.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +/** Raise exception when condition not met. Disregard NS_BLOCK_ASSERTIONS. */ +#define GRPCAssert(condition, errorType, errorString) \ +do { \ +if (!(condition)) { \ +[NSException raise:(errorType) format:(errorString)]; \ +} \ +} while (0) + +/** The same as GRPCAssert but allows arguments to be put in the raised string. */ +#define GRPCAssertWithArgument(condition, errorType, errorFormat, ...) \ + do { \ + if (!(condition)) { \ + [NSException raise:(errorType) format:(errorFormat), __VA_ARGS__]; \ + } \ + } while (0)