Removed (un)secure channel subclasses

pull/4985/head
Kristopher Wuollett 9 years ago
parent 85bf574106
commit 2c6d2bd327
  1. 45
      src/objective-c/GRPCClient/private/GRPCChannel.h
  2. 153
      src/objective-c/GRPCClient/private/GRPCChannel.m
  3. 22
      src/objective-c/GRPCClient/private/GRPCHost.m
  4. 60
      src/objective-c/GRPCClient/private/GRPCSecureChannel.h
  5. 113
      src/objective-c/GRPCClient/private/GRPCSecureChannel.m
  6. 42
      src/objective-c/GRPCClient/private/GRPCUnsecuredChannel.h
  7. 60
      src/objective-c/GRPCClient/private/GRPCUnsecuredChannel.m
  8. 29
      src/objective-c/GRPCClient/private/GRPCWrappedChannelArgs.h
  9. 188
      src/objective-c/GRPCClient/private/GRPCWrappedChannelArgs.m

@ -33,18 +33,51 @@
#import <Foundation/Foundation.h>
struct grpc_channel;
#include <grpc/grpc.h>
struct grpc_channel_credentials;
/**
* Each separate instance of this class represents at least one TCP connection to the provided host.
* Create them using one of the subclasses |GRPCSecureChannel| and |GRPCUnsecuredChannel|.
*/
@interface GRPCChannel : NSObject
@property(nonatomic, readonly) struct grpc_channel *unmanagedChannel;
@property(nonatomic, readonly, nonnull) struct grpc_channel *unmanagedChannel;
@property(nonatomic, readonly, getter=isSecure) BOOL secure;
- (nullable instancetype)init NS_UNAVAILABLE;
/**
* Creates a secure channel to the specified @c host using default credentials and channel
* arguments. If certificates could not be found to create a secure channel, then @c nil is
* returned.
*/
+ (nullable GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host;
/**
* Creates a secure channel to the specified @c host using the specified @c pathToCertificates and
* @c channelArgs. Only in tests should @c pathToCertificates be nil or
* @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg be set. Passing nil for @c pathToCertificates
* results in using the default root certificates distributed with the library. If certificates
* could not be found in any case, then @c nil is returned.
*/
+ (nullable GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host
pathToCertificates:(nullable NSString *)pathToCertificates
channelArgs:(nullable NSDictionary *)channelArgs;
/**
* This initializer takes ownership of the passed channel, and will destroy it when this object is
* deallocated. It's illegal to pass the same grpc_channel to two different GRPCChannel objects.
* Creates a secure channel to the specified @c host using the specified @c credentials and
* @c channelArgs. Only in tests should @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg be set.
*/
- (instancetype)initWithChannel:(struct grpc_channel *)unmanagedChannel NS_DESIGNATED_INITIALIZER;
+ (nonnull GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host
credentials:(nonnull struct grpc_channel_credentials *)credentials
channelArgs:(nullable NSDictionary *)channelArgs;
/**
* Creates an insecure channel to the specified @c host using the specified @c channelArgs.
*/
+ (nonnull GRPCChannel *)insecureChannelWithHost:(nonnull NSString *)host
channelArgs:(nullable NSDictionary *)channelArgs;
@end

@ -33,22 +33,101 @@
#import "GRPCChannel.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@implementation GRPCChannel
/**
* Returns @c grpc_channel_credentials from the specifie @c path. If the file at the path could not
* be read then NULL is returned. If NULL is returned, @c errorPtr may not be NULL if there are
* details available describing what went wrong.
*/
static grpc_channel_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr) {
// Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the
// issuer). Load them as UTF8 and produce an ASCII equivalent.
NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:errorPtr];
NSData *contentInASCII = [contentInUTF8 dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
if (!contentInASCII.bytes) {
// Passing NULL to grpc_ssl_credentials_create produces behavior we don't want, so return.
return NULL;
}
return grpc_ssl_credentials_create(contentInASCII.bytes, NULL, NULL);
}
/**
* Allocates a @c grpc_channel_args and populates it with the options specified in the
* @c dictionary. Keys must be @c NSString. If the value responds to @c @selector(UTF8String) then
* it will be mapped to @c GRPC_ARG_STRING. If not, it will be mapped to @c GRPC_ARG_INTEGER if the
* value responds to @c @selector(intValue). Otherwise, an exception will be raised.
*/
grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
if (!dictionary) {
return NULL;
}
NSUInteger argCount = [dictionary count];
// Allocate memory for both the individual args and their container
grpc_channel_args *channelArgs = gpr_malloc(sizeof(grpc_channel_args)
+ argCount * sizeof(grpc_arg));
channelArgs->num_args = argCount;
channelArgs->args = (grpc_arg *) (channelArgs + sizeof(grpc_channel_args));
- (instancetype)init {
return [self initWithChannel:NULL];
__block NSUInteger argIndex = 0;
[dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj,
BOOL * _Nonnull stop) {
// use of UTF8String assumes that grpc won't modify the pointers
grpc_arg *arg = &channelArgs->args[argIndex++];
arg->key = (char *) [key UTF8String]; // allow exception to be raised if not supported
if ([obj respondsToSelector:@selector(UTF8String)]) {
arg->type = GRPC_ARG_STRING;
arg->value.string = (char *) [obj UTF8String];
} else if ([obj respondsToSelector:@selector(intValue)]) {
arg->type = GRPC_ARG_INTEGER;
arg->value.integer = [obj intValue];
} else {
[NSException raise:NSInvalidArgumentException format:@"Invalid value type: %@", [obj class]];
}
}];
return channelArgs;
}
@implementation GRPCChannel {
// Retain arguments to channel_create because they may not be used on the thread that invoked
// the channel_create function.
NSString *_host;
grpc_channel_args *_channelArgs;
}
// Designated initializer
- (instancetype)initWithChannel:(grpc_channel *)unmanagedChannel {
if (!unmanagedChannel) {
- (instancetype)initWithHost:(NSString *)host
secure:(BOOL)secure
credentials:(struct grpc_channel_credentials *)credentials
channelArgs:(NSDictionary *)channelArgs {
if (!host) {
[NSException raise:NSInvalidArgumentException format:@"host argument missing"];
}
if (secure && !credentials) {
return nil;
}
if ((self = [super init])) {
_unmanagedChannel = unmanagedChannel;
if (self = [super init]) {
_channelArgs = buildChannelArgs(channelArgs);
_host = [host copy];
if (secure) {
_unmanagedChannel = grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs,
NULL);
} else {
_unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, _channelArgs, NULL);
}
}
return self;
}
@ -56,5 +135,61 @@
// TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely,
// as in the past that made this call to crash.
grpc_channel_destroy(_unmanagedChannel);
gpr_free(_channelArgs);
}
+ (GRPCChannel *)secureChannelWithHost:(NSString *)host {
return [[GRPCChannel alloc] initWithHost:host secure:YES credentials:NULL channelArgs:NULL];
}
+ (GRPCChannel *)secureChannelWithHost:(NSString *)host
pathToCertificates:(NSString *)path
channelArgs:(NSDictionary *)channelArgs {
// Load default SSL certificates once.
static grpc_channel_credentials *kDefaultCertificates;
static dispatch_once_t loading;
dispatch_once(&loading, ^{
NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem
// Do not use NSBundle.mainBundle, as it's nil for tests of library projects.
NSBundle *bundle = [NSBundle bundleForClass:self.class];
NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"];
NSError *error;
kDefaultCertificates = CertificatesAtPath(path, &error);
NSAssert(kDefaultCertificates, @"Could not read %@/%@.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 that the library "
"wasn't configured correctly for your project. Error: %@",
bundle.bundlePath, defaultPath, error);
});
//TODO(jcanizales): Add NSError** parameter to the initializer.
grpc_channel_credentials *certificates = path
? CertificatesAtPath(path, NULL)
: kDefaultCertificates;
return [[GRPCChannel alloc] initWithHost:host
secure:YES
credentials:certificates
channelArgs:channelArgs];
}
+ (GRPCChannel *)secureChannelWithHost:(NSString *)host
credentials:(struct grpc_channel_credentials *)credentials
channelArgs:(NSDictionary *)channelArgs {
return [[GRPCChannel alloc] initWithHost:host
secure:YES
credentials:credentials
channelArgs:channelArgs];
}
+ (GRPCChannel *)insecureChannelWithHost:(NSString *)host
channelArgs:(NSDictionary *)channelArgs {
return [[GRPCChannel alloc] initWithHost:host
secure:NO
credentials:NULL
channelArgs:channelArgs];
}
@end

@ -37,9 +37,7 @@
#import "GRPCChannel.h"
#import "GRPCCompletionQueue.h"
#import "GRPCSecureChannel.h"
#import "GRPCUnsecuredChannel.h"
#import "GRPCWrappedChannelArgs.h"
#import "NSDictionary+GRPC.h"
@interface GRPCHost ()
// TODO(mlumish): Investigate whether caching channels with strong links is a good idea.
@ -107,26 +105,26 @@
- (GRPCChannel *)channel {
// Create it lazily, because we don't want to open a connection just because someone is
// configuring a host.
if (!_channel) {
GRPCWrappedChannelArgsBuilder *argsBuilder = [[GRPCWrappedChannelArgsBuilder alloc] init];
NSMutableDictionary *args = [NSMutableDictionary dictionary];
if (_primaryUserAgent) {
[argsBuilder addKey:@GRPC_ARG_PRIMARY_USER_AGENT_STRING stringValue:_primaryUserAgent];
args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = _primaryUserAgent;
}
if (_secondaryUserAgent) {
[argsBuilder addKey:@GRPC_ARG_SECONDARY_USER_AGENT_STRING stringValue:_secondaryUserAgent];
args[@GRPC_ARG_SECONDARY_USER_AGENT_STRING] = _secondaryUserAgent;
}
if (_secure) {
if (_hostNameOverride) {
[argsBuilder addKey:@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG stringValue:_hostNameOverride];
args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride;
}
_channel = [[GRPCSecureChannel alloc] initWithHost:_address
pathToCertificates:_pathToCertificates
channelArgs:[argsBuilder build]];
_channel = [GRPCChannel secureChannelWithHost:_address
pathToCertificates:_pathToCertificates
channelArgs:args];
} else {
_channel = [[GRPCUnsecuredChannel alloc] initWithHost:_address
channelArgs:[argsBuilder build]];
_channel = [GRPCChannel insecureChannelWithHost:_address channelArgs:args];
}
}
return _channel;

@ -1,60 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/grpc.h>
#import "GRPCChannel.h"
@class GRPCWrappedChannelArgs;
struct grpc_channel_credentials;
@interface GRPCSecureChannel : GRPCChannel
- (instancetype)initWithHost:(NSString *)host;
/**
* Only in tests should pathToCertificates or @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG arg be set.
* Passing nil for pathToCertificates results in using the default root certificates distributed
* with the library.
*/
- (instancetype)initWithHost:(NSString *)host
pathToCertificates:(NSString *)path
channelArgs:(GRPCWrappedChannelArgs *)channelArgs;
/**
* The passed arguments are copied and no longer needed after the invocation of this initializer.
*/
- (instancetype)initWithHost:(NSString *)host
credentials:(struct grpc_channel_credentials *)credentials
channelArgs:(GRPCWrappedChannelArgs *)channelArgs NS_DESIGNATED_INITIALIZER;
@end

@ -1,113 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "GRPCSecureChannel.h"
#include <grpc/grpc_security.h>
#import "GRPCWrappedChannelArgs.h"
// Returns NULL if the file at path couldn't be read. In that case, if errorPtr isn't NULL,
// *errorPtr will be an object describing what went wrong.
static grpc_channel_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr) {
// Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the
// issuer). Load them as UTF8 and produce an ASCII equivalent.
NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:errorPtr];
NSData *contentInASCII = [contentInUTF8 dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
if (!contentInASCII.bytes) {
// Passing NULL to grpc_ssl_credentials_create produces behavior we don't want, so return.
return NULL;
}
return grpc_ssl_credentials_create(contentInASCII.bytes, NULL, NULL);
}
@implementation GRPCSecureChannel
- (instancetype)initWithHost:(NSString *)host {
return [self initWithHost:host pathToCertificates:nil channelArgs:nil];
}
- (instancetype)initWithHost:(NSString *)host
pathToCertificates:(NSString *)path
channelArgs:(GRPCWrappedChannelArgs *)channelArgs {
// Load default SSL certificates once.
static grpc_channel_credentials *kDefaultCertificates;
static dispatch_once_t loading;
dispatch_once(&loading, ^{
NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem
// Do not use NSBundle.mainBundle, as it's nil for tests of library projects.
NSBundle *bundle = [NSBundle bundleForClass:self.class];
NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"];
NSError *error;
kDefaultCertificates = CertificatesAtPath(path, &error);
NSAssert(kDefaultCertificates, @"Could not read %@/%@.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 that the library "
"wasn't configured correctly for your project. Error: %@",
bundle.bundlePath, defaultPath, error);
});
//TODO(jcanizales): Add NSError** parameter to the initializer.
grpc_channel_credentials *certificates = path
? CertificatesAtPath(path, NULL)
: kDefaultCertificates;
if (!certificates) {
return nil;
}
return [self initWithHost:host credentials:certificates channelArgs:channelArgs];
}
- (instancetype)initWithHost:(NSString *)host
credentials:(grpc_channel_credentials *)credentials
channelArgs:(GRPCWrappedChannelArgs *)channelArgs {
grpc_channel_args args = (grpc_channel_args) { .num_args = 0, .args = NULL };
if (channelArgs) {
args = channelArgs.channelArgs;
}
return (self = [super
initWithChannel:grpc_secure_channel_create(
credentials, host.UTF8String, &args, NULL)]);
}
// TODO(jcanizales): GRPCSecureChannel and GRPCUnsecuredChannel are just convenience initializers
// for GRPCChannel. Move them into GRPCChannel, which will make the following unnecessary.
- (instancetype)initWithChannel:(grpc_channel *)unmanagedChannel {
[NSException raise:NSInternalInconsistencyException format:@"use another initializer"];
return [self initWithHost:nil]; // silence warnings
}
@end

@ -1,42 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "GRPCChannel.h"
@class GRPCWrappedChannelArgs;
@interface GRPCUnsecuredChannel : GRPCChannel
- (instancetype)initWithHost:(NSString *)host;
- (instancetype)initWithHost:(NSString *)host
channelArgs:(GRPCWrappedChannelArgs *)channelArgs NS_DESIGNATED_INITIALIZER;
@end

@ -1,60 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "GRPCUnsecuredChannel.h"
#include <grpc/grpc.h>
#import "GRPCWrappedChannelArgs.h"
@implementation GRPCUnsecuredChannel
- (instancetype)initWithHost:(NSString *)host {
return [self initWithHost:host channelArgs:nil];
}
- (instancetype)initWithHost:(NSString *)host channelArgs:(GRPCWrappedChannelArgs *)channelArgs {
grpc_channel_args args = (grpc_channel_args) { .num_args = 0, .args = NULL };
if (channelArgs) {
args = channelArgs.channelArgs;
}
return (self = [super
initWithChannel:grpc_insecure_channel_create(host.UTF8String, &args, NULL)]);
}
// TODO(jcanizales): GRPCSecureChannel and GRPCUnsecuredChannel are just convenience initializers
// for GRPCChannel. Move them into GRPCChannel, which will make the following unnecessary.
- (instancetype)initWithChannel:(grpc_channel *)unmanagedChannel {
[NSException raise:NSInternalInconsistencyException format:@"use the other initializer"];
return [self initWithHost:nil]; // silence warnings
}
@end

@ -1,29 +0,0 @@
#import <grpc/grpc.h>
#pragma mark - Wrapped Channel Arguments
/**
* A wrapper @c grpc_channel_args that frees allocated memory used to copy key / value pairs by the
* @c GRPCWrappedChannelArgsBuilder.
*/
@interface GRPCWrappedChannelArgs : NSObject
@property(nonatomic, readonly) grpc_channel_args channelArgs;
- (instancetype)init NS_UNAVAILABLE;
@end
#pragma mark - Wrapped Channel Arguments Builder
/**
* A builder that simplifies construction and usage of @c grpc_channel_args by building a
* @c GRPCWrappedChannelArgs.
*/
@interface GRPCWrappedChannelArgsBuilder : NSObject
- (instancetype)addKey:(NSString *)key stringValue:(NSString *)value;
- (instancetype)addKey:(NSString *)key integerValue:(int)value;
- (GRPCWrappedChannelArgs *)build;
@end

@ -1,188 +0,0 @@
#import "GRPCWrappedChannelArgs.h"
#import <grpc/support/log.h>
#pragma mark - Argument Types
@interface GRPCWrappedChannelArg : NSObject
@property(nonatomic, readonly) NSString *grpc_key;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithKey:(NSString *)key NS_DESIGNATED_INITIALIZER;
@end
@implementation GRPCWrappedChannelArg {
NSString *grpc_key_;
}
- (instancetype)initWithKey:(NSString *)key {
GPR_ASSERT(key);
if (self = [super init]) {
grpc_key_ = [key copy];
}
return self;
}
- (NSString *)grpc_key {
return grpc_key_;
}
@end
#pragma mark String Argument Type
@interface GRPCWrappedChannelStringArg : GRPCWrappedChannelArg
@property(nonatomic, readonly) NSString *grpc_string;
- (instancetype)initWithKey:(NSString *)key NS_UNAVAILABLE;
- (instancetype)initWithKey:(NSString *)key value:(NSString *)value NS_DESIGNATED_INITIALIZER;
@end
@implementation GRPCWrappedChannelStringArg {
NSString *grpc_value_;
}
- (instancetype)initWithKey:(NSString *)key value:(NSString *)value {
GPR_ASSERT(value);
if (self = [super initWithKey:key]) {
grpc_value_ = [value copy];
}
return self;
}
- (NSString *)grpc_string {
return grpc_value_;
}
@end
#pragma mark Integer Argument Type
@interface GRPCWrappedChannelIntegerArg : GRPCWrappedChannelArg
@property(nonatomic, readonly) int grpc_integer;
- (instancetype)initWithKey:(NSString *)key NS_UNAVAILABLE;
- (instancetype)initWithKey:(NSString *)key value:(int)value NS_DESIGNATED_INITIALIZER;
@end
@implementation GRPCWrappedChannelIntegerArg {
int grpc_value_;
}
- (instancetype)initWithKey:(NSString *)key value:(int)value {
if (self = [super initWithKey:key]) {
grpc_value_ = value;
}
return self;
}
- (int)grpc_integer {
return grpc_value_;
}
@end
#pragma mark - Wrapped Channel Arguments
@interface GRPCWrappedChannelArgs ()
- (instancetype)initWithChannelArgs:(grpc_channel_args)channelArgs;
@end
@implementation GRPCWrappedChannelArgs {
grpc_channel_args channelArgs_;
}
- (instancetype)initWithChannelArgs:(grpc_channel_args)channelArgs {
if (self = [super init]) {
channelArgs_ = channelArgs;
}
return self;
}
- (grpc_channel_args)channelArgs {
return channelArgs_;
}
- (void)dealloc {
for (size_t i = 0; i < channelArgs_.num_args; ++i) {
grpc_arg *arg = &channelArgs_.args[i];
free(arg->key);
if (arg->type == GRPC_ARG_STRING) {
free(arg->value.string);
}
}
free(channelArgs_.args);
}
@end
#pragma mark - Wrapped Channel Arguments Builder
@implementation GRPCWrappedChannelArgsBuilder {
NSMutableArray *args_;
}
- (instancetype)init {
if (self = [super init]) {
args_ = [NSMutableArray array];
}
return self;
}
- (instancetype)addKey:(NSString *)key stringValue:(NSString *)value {
GRPCWrappedChannelStringArg *arg = [[GRPCWrappedChannelStringArg alloc] initWithKey:key value:value];
[args_ addObject:arg];
return self;
}
- (instancetype)addKey:(NSString *)key integerValue:(int)value {
GRPCWrappedChannelIntegerArg *arg = [[GRPCWrappedChannelIntegerArg alloc] initWithKey:key value:value];
[args_ addObject:arg];
return self;
}
- (GRPCWrappedChannelArgs *)build {
grpc_channel_args channelArgs;
// channelArgs.args and contents is freed by GRPCWrappedChannelArgs::dealloc
channelArgs.num_args = args_.count;
channelArgs.args = (grpc_arg *) calloc(args_.count, sizeof(grpc_arg));
for (NSInteger i = 0; i < args_.count; ++i) {
if ([args_[i] respondsToSelector:@selector(grpc_string)]) {
GRPCWrappedChannelStringArg *arg = (GRPCWrappedChannelStringArg *)args_[i];
grpc_arg *wrappedArg = &channelArgs.args[i];
wrappedArg->key = strdup(arg.grpc_key.UTF8String);
wrappedArg->type = GRPC_ARG_STRING;
wrappedArg->value.string = strdup(arg.grpc_string.UTF8String);
GPR_ASSERT(wrappedArg->key);
GPR_ASSERT(wrappedArg->value.string);
} else if ([args_[i] respondsToSelector:@selector(grpc_integer)]) {
GRPCWrappedChannelIntegerArg *arg = (GRPCWrappedChannelIntegerArg *)args_[i];
grpc_arg *wrappedArg = &channelArgs.args[i];
wrappedArg->key = strdup(arg.grpc_key.UTF8String);
wrappedArg->type = GRPC_ARG_INTEGER;
wrappedArg->value.integer = arg.grpc_integer;
GPR_ASSERT(wrappedArg->key);
} else {
GPR_ASSERT(0); // Argument type not recognized
}
}
return [[GRPCWrappedChannelArgs alloc] initWithChannelArgs:channelArgs];
}
@end
Loading…
Cancel
Save