diff options
Diffstat (limited to 'src/objective-c/GRPCClient/private')
7 files changed, 110 insertions, 220 deletions
diff --git a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m index 7d5ecb56d9..59c0565494 100644 --- a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m +++ b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m @@ -33,7 +33,7 @@ #import "GRPCDelegateWrapper.h" -#import <gRPC/GRXWriteable.h> +#import <RxLibrary/GRXWriteable.h> @interface GRPCDelegateWrapper () // These are atomic so that cancellation can nillify them from any thread. diff --git a/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h b/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h deleted file mode 100644 index 28c7374517..0000000000 --- a/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h +++ /dev/null @@ -1,40 +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 <Foundation/Foundation.h> - -#import "GRPCMethodName.h" - -@interface GRPCMethodName (HTTP2Encoding) -- (NSString *)HTTP2Path; -@end diff --git a/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m b/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m deleted file mode 100644 index 3ad757fb29..0000000000 --- a/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m +++ /dev/null @@ -1,44 +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 "GRPCMethodName+HTTP2Encoding.h" - -@implementation GRPCMethodName (HTTP2Encoding) -- (NSString *)HTTP2Path { - if (self.package) { - return [NSString stringWithFormat:@"/%@.%@/%@", self.package, self.interface, self.method]; - } else { - return [NSString stringWithFormat:@"/%@/%@", self.interface, self.method]; - } -} -@end diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannel.m b/src/objective-c/GRPCClient/private/GRPCSecureChannel.m index 2cbc6e0f83..43a8bd539e 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannel.m @@ -38,13 +38,17 @@ @implementation GRPCSecureChannel - (instancetype)initWithHost:(NSString *)host { - static const grpc_credentials *kCredentials; + static grpc_credentials *kCredentials; static dispatch_once_t loading; dispatch_once(&loading, ^{ // Do not use NSBundle.mainBundle, as it's nil for tests of library projects. NSBundle *bundle = [NSBundle bundleForClass:self.class]; - NSString *certsPath = [bundle pathForResource:@"gRPC.bundle/roots" ofType:@"pem"]; + NSString *certsPath = [bundle pathForResource:@"gRPCCertificates.bundle/roots" ofType:@"pem"]; + NSAssert(certsPath.length, + @"gRPCCertificates.bundle/roots.pem not found under %@. This file, with the root " + "certificates, is needed to establish TLS (HTTPS) connections.", bundle.bundlePath); NSData *certsData = [NSData dataWithContentsOfFile:certsPath]; + NSAssert(certsData.length, @"No data read from %@", certsPath); NSString *certsString = [[NSString alloc] initWithData:certsData encoding:NSUTF8StringEncoding]; kCredentials = grpc_ssl_credentials_create(certsString.UTF8String, NULL); }); diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index 4deeec0475..18f8bb5531 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -33,60 +33,58 @@ #import <Foundation/Foundation.h> #include <grpc/grpc.h> -#import "GRPCChannel.h" - -typedef void(^GRPCCompletionHandler)(NSDictionary *); - -@protocol GRPCOp <NSObject> -- (void)getOp:(grpc_op *)op; +#import "GRPCChannel.h" +@interface GRPCOperation : NSObject +@property(nonatomic, readonly) grpc_op op; +// Guaranteed to be called when the operation has finished. - (void)finish; - @end -@interface GRPCOpSendMetadata : NSObject <GRPCOp> +@interface GRPCOpSendMetadata : GRPCOperation - (instancetype)initWithMetadata:(NSDictionary *)metadata - handler:(void(^)(void))handler NS_DESIGNATED_INITIALIZER; + handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end -@interface GRPCOpSendMessage : NSObject <GRPCOp> +@interface GRPCOpSendMessage : GRPCOperation - (instancetype)initWithMessage:(NSData *)message - handler:(void(^)(void))handler NS_DESIGNATED_INITIALIZER; + handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end -@interface GRPCOpSendClose : NSObject <GRPCOp> +@interface GRPCOpSendClose : GRPCOperation -- (instancetype)initWithHandler:(void(^)(void))handler NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHandler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end -@interface GRPCOpRecvMetadata : NSObject <GRPCOp> +@interface GRPCOpRecvMetadata : GRPCOperation - (instancetype)initWithHandler:(void(^)(NSDictionary *))handler NS_DESIGNATED_INITIALIZER; @end -@interface GRPCOpRecvMessage : NSObject <GRPCOp> +@interface GRPCOpRecvMessage : GRPCOperation - (instancetype)initWithHandler:(void(^)(grpc_byte_buffer *))handler NS_DESIGNATED_INITIALIZER; @end -@interface GRPCOpRecvStatus : NSObject <GRPCOp> +@interface GRPCOpRecvStatus : GRPCOperation -- (instancetype)initWithHandler:(void(^)(NSError *, NSDictionary *))handler NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHandler:(void(^)(NSError *, NSDictionary *))handler + NS_DESIGNATED_INITIALIZER; @end @interface GRPCWrappedCall : NSObject - (instancetype)initWithChannel:(GRPCChannel *)channel - method:(NSString *)method + path:(NSString *)path host:(NSString *)host NS_DESIGNATED_INITIALIZER; - (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void(^)())errorHandler; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index ea482b29ef..45f10f5d63 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -41,110 +41,85 @@ #import "NSData+GRPC.h" #import "NSError+GRPC.h" -@implementation GRPCOpSendMetadata{ - void(^_handler)(void); - grpc_metadata *_sendMetadata; - size_t _count; +@implementation GRPCOperation { +@protected + // Most operation subclasses don't set any flags in the grpc_op, and rely on the flag member being + // initialized to zero. + grpc_op _op; + void(^_handler)(); } +- (void)finish { + if (_handler) { + _handler(); + } +} +@end + +@implementation GRPCOpSendMetadata + - (instancetype)init { return [self initWithMetadata:nil handler:nil]; } -- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)(void))handler { +- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler { if (self = [super init]) { - _sendMetadata = [metadata grpc_metadataArray]; - _count = metadata.count; + _op.op = GRPC_OP_SEND_INITIAL_METADATA; + _op.data.send_initial_metadata.count = metadata.count; + _op.data.send_initial_metadata.metadata = metadata.grpc_metadataArray; _handler = handler; } return self; } -- (void)getOp:(grpc_op *)op { - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = _count; - op->data.send_initial_metadata.metadata = _sendMetadata; -} - -- (void)finish { - if (_handler) { - _handler(); - } -} - - (void)dealloc { - gpr_free(_sendMetadata); + gpr_free(_op.data.send_initial_metadata.metadata); } @end -@implementation GRPCOpSendMessage{ - void(^_handler)(void); - grpc_byte_buffer *_byteBuffer; -} +@implementation GRPCOpSendMessage - (instancetype)init { return [self initWithMessage:nil handler:nil]; } -- (instancetype)initWithMessage:(NSData *)message handler:(void (^)(void))handler { +- (instancetype)initWithMessage:(NSData *)message handler:(void (^)())handler { if (!message) { [NSException raise:NSInvalidArgumentException format:@"message cannot be nil"]; } if (self = [super init]) { - _byteBuffer = [message grpc_byteBuffer]; + _op.op = GRPC_OP_SEND_MESSAGE; + _op.data.send_message = message.grpc_byteBuffer; _handler = handler; } return self; } -- (void)getOp:(grpc_op *)op { - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message = _byteBuffer; -} - -- (void)finish { - if (_handler) { - _handler(); - } -} - - (void)dealloc { - gpr_free(_byteBuffer); + gpr_free(_op.data.send_message); } @end -@implementation GRPCOpSendClose{ - void(^_handler)(void); -} +@implementation GRPCOpSendClose - (instancetype)init { return [self initWithHandler:nil]; } -- (instancetype)initWithHandler:(void (^)(void))handler { +- (instancetype)initWithHandler:(void (^)())handler { if (self = [super init]) { + _op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; _handler = handler; } return self; } -- (void)getOp:(grpc_op *)op { - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; -} - -- (void)finish { - if (_handler) { - _handler(); - } -} - @end -@implementation GRPCOpRecvMetadata{ - void(^_handler)(NSDictionary *); - grpc_metadata_array _recvInitialMetadata; +@implementation GRPCOpRecvMetadata { + grpc_metadata_array _headers; } - (instancetype) init { @@ -153,33 +128,31 @@ - (instancetype) initWithHandler:(void (^)(NSDictionary *))handler { if (self = [super init]) { - _handler = handler; - grpc_metadata_array_init(&_recvInitialMetadata); + _op.op = GRPC_OP_RECV_INITIAL_METADATA; + grpc_metadata_array_init(&_headers); + _op.data.recv_initial_metadata = &_headers; + if (handler) { + // Prevent reference cycle with _handler + __weak typeof(self) weakSelf = self; + _handler = ^{ + __strong typeof(self) strongSelf = weakSelf; + NSDictionary *metadata = [NSDictionary + grpc_dictionaryFromMetadataArray:strongSelf->_headers]; + handler(metadata); + }; + } } return self; } -- (void)getOp:(grpc_op *)op { - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata = &_recvInitialMetadata; -} - -- (void)finish { - NSDictionary *metadata = [NSDictionary grpc_dictionaryFromMetadataArray:_recvInitialMetadata]; - if (_handler) { - _handler(metadata); - } -} - - (void)dealloc { - grpc_metadata_array_destroy(&_recvInitialMetadata); + grpc_metadata_array_destroy(&_headers); } @end @implementation GRPCOpRecvMessage{ - void(^_handler)(grpc_byte_buffer *); - grpc_byte_buffer *_recvMessage; + grpc_byte_buffer *_receivedMessage; } - (instancetype)init { @@ -188,30 +161,27 @@ - (instancetype)initWithHandler:(void (^)(grpc_byte_buffer *))handler { if (self = [super init]) { - _handler = handler; + _op.op = GRPC_OP_RECV_MESSAGE; + _op.data.recv_message = &_receivedMessage; + if (handler) { + // Prevent reference cycle with _handler + __weak typeof(self) weakSelf = self; + _handler = ^{ + __strong typeof(self) strongSelf = weakSelf; + handler(strongSelf->_receivedMessage); + }; + } } return self; } -- (void)getOp:(grpc_op *)op { - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message = &_recvMessage; -} - -- (void)finish { - if (_handler) { - _handler(_recvMessage); - } -} - @end @implementation GRPCOpRecvStatus{ - void(^_handler)(NSError *, NSDictionary *); grpc_status_code _statusCode; char *_details; size_t _detailsCapacity; - grpc_metadata_array _metadata; + grpc_metadata_array _trailers; } - (instancetype) init { @@ -220,30 +190,30 @@ - (instancetype) initWithHandler:(void (^)(NSError *, NSDictionary *))handler { if (self = [super init]) { - _handler = handler; - grpc_metadata_array_init(&_metadata); + _op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; + _op.data.recv_status_on_client.status = &_statusCode; + _op.data.recv_status_on_client.status_details = &_details; + _op.data.recv_status_on_client.status_details_capacity = &_detailsCapacity; + grpc_metadata_array_init(&_trailers); + _op.data.recv_status_on_client.trailing_metadata = &_trailers; + if (handler) { + // Prevent reference cycle with _handler + __weak typeof(self) weakSelf = self; + _handler = ^{ + __strong typeof(self) strongSelf = weakSelf; + NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode + details:strongSelf->_details]; + NSDictionary *trailers = [NSDictionary + grpc_dictionaryFromMetadataArray:strongSelf->_trailers]; + handler(error, trailers); + }; + } } return self; } -- (void)getOp:(grpc_op *)op { - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.status = &_statusCode; - op->data.recv_status_on_client.status_details = &_details; - op->data.recv_status_on_client.status_details_capacity = &_detailsCapacity; - op->data.recv_status_on_client.trailing_metadata = &_metadata; -} - -- (void)finish { - if (_handler) { - NSError *error = [NSError grpc_errorFromStatusCode:_statusCode details:_details]; - NSDictionary *trailers = [NSDictionary grpc_dictionaryFromMetadataArray:_metadata]; - _handler(error, trailers); - } -} - - (void)dealloc { - grpc_metadata_array_destroy(&_metadata); + grpc_metadata_array_destroy(&_trailers); gpr_free(_details); } @@ -255,13 +225,13 @@ } - (instancetype)init { - return [self initWithChannel:nil method:nil host:nil]; + return [self initWithChannel:nil path:nil host:nil]; } - (instancetype)initWithChannel:(GRPCChannel *)channel - method:(NSString *)method + path:(NSString *)path host:(NSString *)host { - if (!channel || !method || !host) { + if (!channel || !path || !host) { [NSException raise:NSInvalidArgumentException format:@"channel, method, and host cannot be nil."]; } @@ -277,7 +247,7 @@ return nil; } _call = grpc_channel_create_call(channel.unmanagedChannel, _queue.unmanagedQueue, - method.UTF8String, host.UTF8String, gpr_inf_future); + path.UTF8String, host.UTF8String, gpr_inf_future); if (_call == NULL) { return nil; } @@ -293,8 +263,8 @@ size_t nops = operations.count; grpc_op *ops_array = gpr_malloc(nops * sizeof(grpc_op)); size_t i = 0; - for (id op in operations) { - [op getOp:&ops_array[i++]]; + for (GRPCOperation *operation in operations) { + ops_array[i++] = operation.op; } grpc_call_error error = grpc_call_start_batch(_call, ops_array, nops, (__bridge_retained void *)(^(bool success){ @@ -305,14 +275,16 @@ return; } } - for (id<GRPCOp> operation in operations) { + for (GRPCOperation *operation in operations) { [operation finish]; } })); - + gpr_free(ops_array); + if (error != GRPC_CALL_OK) { [NSException raise:NSInternalInconsistencyException - format:@"A precondition for calling grpc_call_start_batch wasn't met"]; + format:@"A precondition for calling grpc_call_start_batch wasn't met. Error %i", + error]; } } diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m index f7390476d9..638f41cb11 100644 --- a/src/objective-c/GRPCClient/private/NSError+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m @@ -33,7 +33,7 @@ #import "NSError+GRPC.h" -#include <grpc.h> +#include <grpc/grpc.h> NSString * const kGRPCErrorDomain = @"io.grpc"; |