Revert format changes of unrelated files

pull/8561/head
Muxi Yan 8 years ago
parent e53707c481
commit 2c88b4616a
  1. 17
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
  2. 16
      src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
  3. 14
      src/objective-c/GRPCClient/GRPCCall+OAuth2.h
  4. 25
      src/objective-c/GRPCClient/GRPCCall+Tests.h
  5. 189
      src/objective-c/GRPCClient/GRPCCall.h
  6. 17
      src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
  7. 41
      src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
  8. 86
      src/objective-c/GRPCClient/private/GRPCWrappedCall.m
  9. 7
      src/objective-c/GRPCClient/private/NSError+GRPC.h

@ -40,18 +40,15 @@
@interface GRPCCall (ChannelArg) @interface GRPCCall (ChannelArg)
/** /**
* Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent * Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent string for all calls
* string for all calls to the specified @c host. * to the specified @c host.
*/ */
+ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix + (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host;
forHost:(nonnull NSString *)host;
/** The default response size limit is 4MB. Set this to override that default. /** The default response size limit is 4MB. Set this to override that default. */
*/
+ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host; + (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host;
+ (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE( + (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, "
"The API for this feature is experimental, " "and might be removed or modified at any "
"and might be removed or modified at any " "time.");
"time.");
@end @end

@ -33,26 +33,24 @@
#import "GRPCCall.h" #import "GRPCCall.h"
/** Helpers for setting TLS Trusted Roots, Client Certificates, and Private Key /** Helpers for setting TLS Trusted Roots, Client Certificates, and Private Key */
*/
@interface GRPCCall (ChannelCredentials) @interface GRPCCall (ChannelCredentials)
/** /**
* Use the provided @c pemRootCert as the set of trusted root Certificate * Use the provided @c pemRootCert as the set of trusted root Certificate Authorities for @c host.
* Authorities for @c host.
*/ */
+ (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert
forHost:(nonnull NSString *)host forHost:(nonnull NSString *)host
error:(NSError *_Nullable *_Nullable)errorPtr; error:(NSError * _Nullable * _Nullable)errorPtr;
/** /**
* Configures @c host with TLS/SSL Client Credentials and optionally trusted * Configures @c host with TLS/SSL Client Credentials and optionally trusted root Certificate
* root Certificate Authorities. If @c pemRootCerts is nil, the default CA * Authorities. If @c pemRootCerts is nil, the default CA Certificates bundled with gRPC will be
* Certificates bundled with gRPC will be used. * used.
*/ */
+ (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts
withPrivateKey:(nullable NSString *)pemPrivateKey withPrivateKey:(nullable NSString *)pemPrivateKey
withCertChain:(nullable NSString *)pemCertChain withCertChain:(nullable NSString *)pemCertChain
forHost:(nonnull NSString *)host forHost:(nonnull NSString *)host
error:(NSError *_Nullable *_Nullable)errorPtr; error:(NSError * _Nullable * _Nullable)errorPtr;
@end @end

@ -37,17 +37,15 @@
@interface GRPCCall (OAuth2) @interface GRPCCall (OAuth2)
/** /**
* Setting this property is equivalent to setting "Bearer <passed token>" as the * Setting this property is equivalent to setting "Bearer <passed token>" as the value of the
* value of the request header with key "authorization" (the authorization * request header with key "authorization" (the authorization header). Setting it to nil removes the
* header). Setting it to nil removes the authorization header from the request. * authorization header from the request.
* The value obtained by getting the property is the OAuth2 bearer token if the * The value obtained by getting the property is the OAuth2 bearer token if the authorization header
* authorization header of the request has the form "Bearer <token>", or nil * of the request has the form "Bearer <token>", or nil otherwise.
* otherwise.
*/ */
@property(atomic, copy) NSString *oauth2AccessToken; @property(atomic, copy) NSString *oauth2AccessToken;
/** Returns the value (if any) of the "www-authenticate" response header (the /** Returns the value (if any) of the "www-authenticate" response header (the challenge header). */
* challenge header). */
@property(atomic, readonly) NSString *oauth2ChallengeHeader; @property(atomic, readonly) NSString *oauth2ChallengeHeader;
@end @end

@ -34,36 +34,33 @@
#import "GRPCCall.h" #import "GRPCCall.h"
/** /**
* Methods to let tune down the security of gRPC connections for specific hosts. * Methods to let tune down the security of gRPC connections for specific hosts. These shouldn't be
* These shouldn't be used in releases, but are sometimes needed for testing. * used in releases, but are sometimes needed for testing.
*/ */
@interface GRPCCall (Tests) @interface GRPCCall (Tests)
/** /**
* Establish all SSL connections to the provided host using the passed SSL * Establish all SSL connections to the provided host using the passed SSL target name and the root
* target name and the root certificates found in the file at |certsPath|. * certificates found in the file at |certsPath|.
* *
* Must be called before any gRPC call to that host is made. It's illegal to * Must be called before any gRPC call to that host is made. It's illegal to pass the same host to
* pass the same host to more than one invocation of the methods of this * more than one invocation of the methods of this category.
* category.
*/ */
+ (void)useTestCertsPath:(NSString *)certsPath + (void)useTestCertsPath:(NSString *)certsPath
testName:(NSString *)testName testName:(NSString *)testName
forHost:(NSString *)host; forHost:(NSString *)host;
/** /**
* Establish all connections to the provided host using cleartext instead of * Establish all connections to the provided host using cleartext instead of SSL.
* SSL.
* *
* Must be called before any gRPC call to that host is made. It's illegal to * Must be called before any gRPC call to that host is made. It's illegal to pass the same host to
* pass the same host to more than one invocation of the methods of this * more than one invocation of the methods of this category.
* category.
*/ */
+ (void)useInsecureConnectionsForHost:(NSString *)host; + (void)useInsecureConnectionsForHost:(NSString *)host;
/** /**
* Resets all host configurations to their default values, and flushes all * Resets all host configurations to their default values, and flushes all connections from the
* connections from the cache. * cache.
*/ */
+ (void)resetHostSettings; + (void)resetHostSettings;
@end @end

@ -34,18 +34,17 @@
/** /**
* The gRPC protocol is an RPC protocol on top of HTTP2. * The gRPC protocol is an RPC protocol on top of HTTP2.
* *
* While the most common type of RPC receives only one request message and * While the most common type of RPC receives only one request message and returns only one response
* returns only one response message, the protocol also supports RPCs that * message, the protocol also supports RPCs that return multiple individual messages in a streaming
* return multiple individual messages in a streaming fashion, RPCs that accept * fashion, RPCs that accept a stream of request messages, or RPCs with both streaming requests and
* a stream of request messages, or RPCs with both streaming requests and
* responses. * responses.
* *
* Conceptually, each gRPC call consists of a bidirectional stream of binary * Conceptually, each gRPC call consists of a bidirectional stream of binary messages, with RPCs of
* messages, with RPCs of the "non-streaming type" sending only one message in * the "non-streaming type" sending only one message in the corresponding direction (the protocol
* the corresponding direction (the protocol doesn't make any distinction). * doesn't make any distinction).
* *
* Each RPC uses a different HTTP2 stream, and thus multiple simultaneous RPCs * Each RPC uses a different HTTP2 stream, and thus multiple simultaneous RPCs can be multiplexed
* can be multiplexed transparently on the same TCP connection. * transparently on the same TCP connection.
*/ */
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@ -60,56 +59,51 @@ extern NSString *const kGRPCErrorDomain;
/** /**
* gRPC error codes. * gRPC error codes.
* Note that a few of these are never produced by the gRPC libraries, but are of * Note that a few of these are never produced by the gRPC libraries, but are of general utility for
* general utility for server applications to produce. * server applications to produce.
*/ */
typedef NS_ENUM(NSUInteger, GRPCErrorCode) { typedef NS_ENUM(NSUInteger, GRPCErrorCode) {
/** The operation was cancelled (typically by the caller). */ /** The operation was cancelled (typically by the caller). */
GRPCErrorCodeCancelled = 1, GRPCErrorCodeCancelled = 1,
/** /**
* Unknown error. Errors raised by APIs that do not return enough error * Unknown error. Errors raised by APIs that do not return enough error information may be
* information may be
* converted to this error. * converted to this error.
*/ */
GRPCErrorCodeUnknown = 2, GRPCErrorCodeUnknown = 2,
/** /**
* The client specified an invalid argument. Note that this differs from * The client specified an invalid argument. Note that this differs from FAILED_PRECONDITION.
* FAILED_PRECONDITION. * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the
* INVALID_ARGUMENT indicates arguments that are problematic regardless of the * server (e.g., a malformed file name).
* state of the server (e.g., a malformed file name).
*/ */
GRPCErrorCodeInvalidArgument = 3, GRPCErrorCodeInvalidArgument = 3,
/** /**
* Deadline expired before operation could complete. For operations that * Deadline expired before operation could complete. For operations that change the state of the
* change the state of the server, this error may be returned even if the * server, this error may be returned even if the operation has completed successfully. For
* operation has completed successfully. For example, a successful response * example, a successful response from the server could have been delayed long enough for the
* from the server could have been delayed long enough for the deadline to * deadline to expire.
* expire.
*/ */
GRPCErrorCodeDeadlineExceeded = 4, GRPCErrorCodeDeadlineExceeded = 4,
/** Some requested entity (e.g., file or directory) was not found. */ /** Some requested entity (e.g., file or directory) was not found. */
GRPCErrorCodeNotFound = 5, GRPCErrorCodeNotFound = 5,
/** Some entity that we attempted to create (e.g., file or directory) already /** Some entity that we attempted to create (e.g., file or directory) already exists. */
exists. */
GRPCErrorCodeAlreadyExists = 6, GRPCErrorCodeAlreadyExists = 6,
/** /**
* The caller does not have permission to execute the specified operation. * The caller does not have permission to execute the specified operation. PERMISSION_DENIED isn't
* PERMISSION_DENIED isn't used for rejections caused by exhausting some * used for rejections caused by exhausting some resource (RESOURCE_EXHAUSTED is used instead for
* resource (RESOURCE_EXHAUSTED is used instead for those errors). * those errors). PERMISSION_DENIED doesn't indicate a failure to identify the caller
* PERMISSION_DENIED doesn't indicate a failure to identify the caller
* (UNAUTHENTICATED is used instead for those errors). * (UNAUTHENTICATED is used instead for those errors).
*/ */
GRPCErrorCodePermissionDenied = 7, GRPCErrorCodePermissionDenied = 7,
/** /**
* The request does not have valid authentication credentials for the * The request does not have valid authentication credentials for the operation (e.g. the caller's
* operation (e.g. the caller's identity can't be verified). * identity can't be verified).
*/ */
GRPCErrorCodeUnauthenticated = 16, GRPCErrorCodeUnauthenticated = 16,
@ -117,47 +111,42 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) {
GRPCErrorCodeResourceExhausted = 8, GRPCErrorCodeResourceExhausted = 8,
/** /**
* The RPC was rejected because the server is not in a state required for the * The RPC was rejected because the server is not in a state required for the procedure's
* procedure's
* execution. For example, a directory to be deleted may be non-empty, etc. * execution. For example, a directory to be deleted may be non-empty, etc.
* The client should not retry until the server state has been explicitly * The client should not retry until the server state has been explicitly fixed (e.g. by
* fixed (e.g. by * performing another RPC). The details depend on the service being called, and should be found in
* performing another RPC). The details depend on the service being called, * the NSError's userInfo.
* and should be found in the NSError's userInfo.
*/ */
GRPCErrorCodeFailedPrecondition = 9, GRPCErrorCodeFailedPrecondition = 9,
/** /**
* The RPC was aborted, typically due to a concurrency issue like sequencer * The RPC was aborted, typically due to a concurrency issue like sequencer check failures,
* check failures, transaction aborts, etc. The client should retry at a * transaction aborts, etc. The client should retry at a higher-level (e.g., restarting a read-
* higher-level (e.g., restarting a read-modify-write sequence). * modify-write sequence).
*/ */
GRPCErrorCodeAborted = 10, GRPCErrorCodeAborted = 10,
/** /**
* The RPC was attempted past the valid range. E.g., enumerating past the end * The RPC was attempted past the valid range. E.g., enumerating past the end of a list.
* of a list. * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state
* Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed * changes. For example, an RPC to get elements of a list will generate INVALID_ARGUMENT if asked
* if the system state changes. For example, an RPC to get elements of a list * to return the element at a negative index, but it will generate OUT_OF_RANGE if asked to return
* will generate INVALID_ARGUMENT if asked to return the element at a negative * the element at an index past the current size of the list.
* index, but it will generate OUT_OF_RANGE if asked to return the element at
* an index past the current size of the list.
*/ */
GRPCErrorCodeOutOfRange = 11, GRPCErrorCodeOutOfRange = 11,
/** The procedure is not implemented or not supported/enabled in this server. /** The procedure is not implemented or not supported/enabled in this server. */
*/
GRPCErrorCodeUnimplemented = 12, GRPCErrorCodeUnimplemented = 12,
/** /**
* Internal error. Means some invariant expected by the server application or * Internal error. Means some invariant expected by the server application or the gRPC library has
* the gRPC library has been broken. * been broken.
*/ */
GRPCErrorCodeInternal = 13, GRPCErrorCodeInternal = 13,
/** /**
* The server is currently unavailable. This is most likely a transient * The server is currently unavailable. This is most likely a transient condition and may be
* condition and may be corrected by retrying with a backoff. * corrected by retrying with a backoff.
*/ */
GRPCErrorCodeUnavailable = 14, GRPCErrorCodeUnavailable = 14,
@ -169,19 +158,17 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) {
* Safety remark of a gRPC method as defined in RFC 2616 Section 9.1 * Safety remark of a gRPC method as defined in RFC 2616 Section 9.1
*/ */
typedef NS_ENUM(NSUInteger, GRPCCallSafety) { typedef NS_ENUM(NSUInteger, GRPCCallSafety) {
/** Signal that there is no guarantees on how the call affects the server /** Signal that there is no guarantees on how the call affects the server state. */
state. */
GRPCCallSafetyDefault = 0, GRPCCallSafetyDefault = 0,
/** Signal that the call is idempotent. gRPC is free to use PUT verb. */ /** Signal that the call is idempotent. gRPC is free to use PUT verb. */
GRPCCallSafetyIdempotentRequest = 1, GRPCCallSafetyIdempotentRequest = 1,
/** Signal that the call is cacheable and will not affect server state. gRPC /** Signal that the call is cacheable and will not affect server state. gRPC is free to use GET verb. */
is free to use GET verb. */
GRPCCallSafetyCacheableRequest = 2, GRPCCallSafetyCacheableRequest = 2,
}; };
/** /**
* Keys used in |NSError|'s |userInfo| dictionary to store the response headers * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by
* and trailers sent by the server. * the server.
*/ */
extern id const kGRPCHeadersKey; extern id const kGRPCHeadersKey;
extern id const kGRPCTrailersKey; extern id const kGRPCTrailersKey;
@ -192,24 +179,20 @@ extern id const kGRPCTrailersKey;
@interface GRPCCall : GRXWriter @interface GRPCCall : GRXWriter
/** /**
* The container of the request headers of an RPC conforms to this protocol, * The container of the request headers of an RPC conforms to this protocol, which is a subset of
* which is a subset of NSMutableDictionary's interface. It will become a * NSMutableDictionary's interface. It will become a NSMutableDictionary later on.
* NSMutableDictionary later on. The keys of this container are the header * The keys of this container are the header names, which per the HTTP standard are case-
* names, which per the HTTP standard are case-insensitive. They are stored in * insensitive. They are stored in lowercase (which is how HTTP/2 mandates them on the wire), and
* lowercase (which is how HTTP/2 mandates them on the wire), and can only * can only consist of ASCII characters.
* consist of ASCII characters. * A header value is a NSString object (with only ASCII characters), unless the header name has the
* A header value is a NSString object (with only ASCII characters), unless the * suffix "-bin", in which case the value has to be a NSData object.
* header name has the suffix "-bin", in which case the value has to be a NSData
* object.
*/ */
/** /**
* These HTTP headers will be passed to the server as part of this call. Each * These HTTP headers will be passed to the server as part of this call. Each HTTP header is a
* HTTP header is a name-value pair with string names and either string or * name-value pair with string names and either string or binary values.
* binary values.
* *
* The passed dictionary has to use NSString keys, corresponding to the header * The passed dictionary has to use NSString keys, corresponding to the header names. The value
* names. The value associated to each can be a NSString object or a NSData * associated to each can be a NSString object or a NSData object. E.g.:
* object. E.g.:
* *
* call.requestHeaders = @{@"authorization": @"Bearer ..."}; * call.requestHeaders = @{@"authorization": @"Bearer ..."};
* *
@ -222,61 +205,53 @@ extern id const kGRPCTrailersKey;
@property(atomic, readonly) NSMutableDictionary *requestHeaders; @property(atomic, readonly) NSMutableDictionary *requestHeaders;
/** /**
* This dictionary is populated with the HTTP headers received from the server. * This dictionary is populated with the HTTP headers received from the server. This happens before
* This happens before any response message is received from the server. It has * any response message is received from the server. It has the same structure as the request
* the same structure as the request headers dictionary: Keys are NSString * headers dictionary: Keys are NSString header names; names ending with the suffix "-bin" have a
* header names; names ending with the suffix "-bin" have a NSData value; the * NSData value; the others have a NSString value.
* others have a NSString value.
* *
* The value of this property is nil until all response headers are received, * The value of this property is nil until all response headers are received, and will change before
* and will change before any of -writeValue: or -writesFinishedWithError: are * any of -writeValue: or -writesFinishedWithError: are sent to the writeable.
* sent to the writeable.
*/ */
@property(atomic, readonly) NSDictionary *responseHeaders; @property(atomic, readonly) NSDictionary *responseHeaders;
/** /**
* Same as responseHeaders, but populated with the HTTP trailers received from * Same as responseHeaders, but populated with the HTTP trailers received from the server before the
* the server before the call finishes. * call finishes.
* *
* The value of this property is nil until all response trailers are received, * The value of this property is nil until all response trailers are received, and will change
* and will change before -writesFinishedWithError: is sent to the writeable. * before -writesFinishedWithError: is sent to the writeable.
*/ */
@property(atomic, readonly) NSDictionary *responseTrailers; @property(atomic, readonly) NSDictionary *responseTrailers;
/** /**
* The request writer has to write NSData objects into the provided Writeable. * The request writer has to write NSData objects into the provided Writeable. The server will
* The server will receive each of those separately and in order as distinct * receive each of those separately and in order as distinct messages.
* messages. * A gRPC call might not complete until the request writer finishes. On the other hand, the request
* A gRPC call might not complete until the request writer finishes. On the * finishing doesn't necessarily make the call to finish, as the server might continue sending
* other hand, the request finishing doesn't necessarily make the call to * messages to the response side of the call indefinitely (depending on the semantics of the
* finish, as the server might continue sending messages to the response side of * specific remote method called).
* the call indefinitely (depending on the semantics of the specific remote
* method called).
* To finish a call right away, invoke cancel. * To finish a call right away, invoke cancel.
* host parameter should not contain the scheme (http:// or https://), only the * host parameter should not contain the scheme (http:// or https://), only the name or IP addr
* name or IP addr and the port number, for example @"localhost:5050". * and the port number, for example @"localhost:5050".
*/ */
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
path:(NSString *)path path:(NSString *)path
requestsWriter:(GRXWriter *)requestsWriter requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER;
NS_DESIGNATED_INITIALIZER;
/** /**
* Finishes the request side of this call, notifies the server that the RPC * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and
* should be cancelled, and finishes the response side of the call with an error * finishes the response side of the call with an error of code CANCELED.
* of code CANCELED.
*/ */
- (void)cancel; - (void)cancel;
/** /**
* Set the call flag for a specific host path. * Set the call flag for a specific host path.
* *
* Host parameter should not contain the scheme (http:// or https://), only the * Host parameter should not contain the scheme (http:// or https://), only the name or IP addr
* name or IP addr and the port number, for example @"localhost:5050". * and the port number, for example @"localhost:5050".
*/ */
+ (void)setCallSafety:(GRPCCallSafety)callSafety + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path;
host:(NSString *)host
path:(NSString *)path;
// TODO(jcanizales): Let specify a deadline. As a category of GRXWriter? // TODO(jcanizales): Let specify a deadline. As a category of GRXWriter?
@end @end
@ -285,7 +260,7 @@ extern id const kGRPCTrailersKey;
/** This protocol is kept for backwards compatibility with existing code. */ /** This protocol is kept for backwards compatibility with existing code. */
DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
@protocol GRPCRequestHeaders<NSObject> @protocol GRPCRequestHeaders <NSObject>
@property(nonatomic, readonly) NSUInteger count; @property(nonatomic, readonly) NSUInteger count;
- (id)objectForKeyedSubscript:(id)key; - (id)objectForKeyedSubscript:(id)key;
@ -298,6 +273,6 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated" #pragma clang diagnostic ignored "-Wdeprecated"
/** This is only needed for backwards-compatibility. */ /** This is only needed for backwards-compatibility. */
@interface NSMutableDictionary (GRPCRequestHeaders)<GRPCRequestHeaders> @interface NSMutableDictionary (GRPCRequestHeaders) <GRPCRequestHeaders>
@end @end
#pragma clang diagnostic pop #pragma clang diagnostic pop

@ -34,19 +34,18 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
typedef void (^GRPCQueueCompletionHandler)(bool success); typedef void(^GRPCQueueCompletionHandler)(bool success);
/** /**
* This class lets one more easily use |grpc_completion_queue|. To use it, pass * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the
* the value of the |unmanagedQueue| property of an instance of this class to * |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for
* |grpc_channel_create_call|. Then for every |grpc_call_*| method that accepts * every |grpc_call_*| method that accepts a tag, you can pass a block of type
* a tag, you can pass a block of type |GRPCQueueCompletionHandler| (remembering * |GRPCQueueCompletionHandler| (remembering to cast it using |__bridge_retained|). The block is
* to cast it using |__bridge_retained|). The block is guaranteed to eventually * guaranteed to eventually be called, by a concurrent queue, and then released. Each such block is
* be called, by a concurrent queue, and then released. Each such block is
* passed a |bool| that tells if the operation was successful. * passed a |bool| that tells if the operation was successful.
* *
* Release the GRPCCompletionQueue object only after you are not going to pass * Release the GRPCCompletionQueue object only after you are not going to pass any more blocks to
* any more blocks to the |grpc_call| that's using it. * the |grpc_call| that's using it.
*/ */
@interface GRPCCompletionQueue : NSObject @interface GRPCCompletionQueue : NSObject
@property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue; @property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue;

@ -38,10 +38,9 @@
#import "NSDictionary+GRPC.h" #import "NSDictionary+GRPC.h"
// Used by the setter. // Used by the setter.
static void CheckIsNonNilASCII(NSString *name, NSString *value) { static void CheckIsNonNilASCII(NSString *name, NSString* value) {
if (!value) { if (!value) {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException format:@"%@ cannot be nil", name];
format:@"%@ cannot be nil", name];
} }
if (![value canBeConvertedToEncoding:NSASCIIStringEncoding]) { if (![value canBeConvertedToEncoding:NSASCIIStringEncoding]) {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException
@ -53,20 +52,15 @@ static void CheckIsNonNilASCII(NSString *name, NSString *value) {
static void CheckKeyValuePairIsValid(NSString *key, id value) { static void CheckKeyValuePairIsValid(NSString *key, id value) {
if ([key hasSuffix:@"-bin"]) { if ([key hasSuffix:@"-bin"]) {
if (![value isKindOfClass:NSData.class]) { if (![value isKindOfClass:NSData.class]) {
[NSException [NSException raise:NSInvalidArgumentException
raise:NSInvalidArgumentException format:@"Expected NSData value for header %@ ending in \"-bin\", "
format:@"Expected NSData value for header %@ ending in \"-bin\", " @"instead got %@", key, value];
@"instead got %@",
key, value];
} }
} else { } else {
if (![value isKindOfClass:NSString.class]) { if (![value isKindOfClass:NSString.class]) {
[NSException [NSException raise:NSInvalidArgumentException
raise:NSInvalidArgumentException format:@"Expected NSString value for header %@ not ending in \"-bin\", "
format: @"instead got %@", key, value];
@"Expected NSString value for header %@ not ending in \"-bin\", "
@"instead got %@",
key, value];
} }
CheckIsNonNilASCII(@"Text header value", (NSString *)value); CheckIsNonNilASCII(@"Text header value", (NSString *)value);
} }
@ -74,10 +68,9 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
@implementation GRPCRequestHeaders { @implementation GRPCRequestHeaders {
__weak GRPCCall *_call; __weak GRPCCall *_call;
// The NSMutableDictionary superclass doesn't hold any storage (so that people // The NSMutableDictionary superclass doesn't hold any storage (so that people can implement their
// can implement their own in subclasses). As that's not the reason we're // own in subclasses). As that's not the reason we're subclassing, we just delegate storage to the
// subclassing, we just delegate storage to the default NSMutableDictionary // default NSMutableDictionary subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9).
// subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9).
NSMutableDictionary *_delegate; NSMutableDictionary *_delegate;
} }
@ -98,8 +91,7 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
} }
// Designated initializer // Designated initializer
- (instancetype)initWithCall:(GRPCCall *)call - (instancetype)initWithCall:(GRPCCall *)call storage:(NSMutableDictionary *)storage {
storage:(NSMutableDictionary *)storage {
// TODO(jcanizales): Throw if call or storage are nil. // TODO(jcanizales): Throw if call or storage are nil.
if ((self = [super init])) { if ((self = [super init])) {
_call = call; _call = call;
@ -108,10 +100,9 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
return self; return self;
} }
- (instancetype) - (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects
initWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys
forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt {
count:(NSUInteger)cnt {
return [self init]; return [self init];
} }
@ -143,7 +134,7 @@ initWithObjects:(const id _Nonnull __unsafe_unretained *)objects
return _delegate.count; return _delegate.count;
} }
- (NSEnumerator *_Nonnull)keyEnumerator { - (NSEnumerator * _Nonnull)keyEnumerator {
return [_delegate keyEnumerator]; return [_delegate keyEnumerator];
} }

@ -34,27 +34,27 @@
#import "GRPCWrappedCall.h" #import "GRPCWrappedCall.h"
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#import "GRPCCompletionQueue.h" #import "GRPCCompletionQueue.h"
#import "GRPCHost.h" #import "GRPCHost.h"
#import "NSData+GRPC.h"
#import "NSDictionary+GRPC.h" #import "NSDictionary+GRPC.h"
#import "NSData+GRPC.h"
#import "NSError+GRPC.h" #import "NSError+GRPC.h"
@implementation GRPCOperation { @implementation GRPCOperation {
@protected @protected
// Most operation subclasses don't set any flags in the grpc_op, and rely on // Most operation subclasses don't set any flags in the grpc_op, and rely on the flag member being
// the flag member being initialized to zero. // initialized to zero.
grpc_op _op; grpc_op _op;
void (^_handler)(); void(^_handler)();
} }
- (void)finish { - (void)finish {
if (_handler) { if (_handler) {
void (^handler)() = _handler; void(^handler)() = _handler;
_handler = nil; _handler = nil;
handler(); handler();
} }
@ -101,8 +101,7 @@
- (instancetype)initWithMessage:(NSData *)message handler:(void (^)())handler { - (instancetype)initWithMessage:(NSData *)message handler:(void (^)())handler {
if (!message) { if (!message) {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException format:@"message cannot be nil"];
format:@"message cannot be nil"];
} }
if (self = [super init]) { if (self = [super init]) {
_op.op = GRPC_OP_SEND_MESSAGE; _op.op = GRPC_OP_SEND_MESSAGE;
@ -138,11 +137,11 @@
grpc_metadata_array _headers; grpc_metadata_array _headers;
} }
- (instancetype)init { - (instancetype) init {
return [self initWithHandler:nil]; return [self initWithHandler:nil];
} }
- (instancetype)initWithHandler:(void (^)(NSDictionary *))handler { - (instancetype) initWithHandler:(void (^)(NSDictionary *))handler {
if (self = [super init]) { if (self = [super init]) {
_op.op = GRPC_OP_RECV_INITIAL_METADATA; _op.op = GRPC_OP_RECV_INITIAL_METADATA;
grpc_metadata_array_init(&_headers); grpc_metadata_array_init(&_headers);
@ -153,7 +152,7 @@
_handler = ^{ _handler = ^{
__strong typeof(self) strongSelf = weakSelf; __strong typeof(self) strongSelf = weakSelf;
NSDictionary *metadata = [NSDictionary NSDictionary *metadata = [NSDictionary
grpc_dictionaryFromMetadataArray:strongSelf->_headers]; grpc_dictionaryFromMetadataArray:strongSelf->_headers];
handler(metadata); handler(metadata);
}; };
} }
@ -167,7 +166,7 @@
@end @end
@implementation GRPCOpRecvMessage { @implementation GRPCOpRecvMessage{
grpc_byte_buffer *_receivedMessage; grpc_byte_buffer *_receivedMessage;
} }
@ -193,18 +192,18 @@
@end @end
@implementation GRPCOpRecvStatus { @implementation GRPCOpRecvStatus{
grpc_status_code _statusCode; grpc_status_code _statusCode;
char *_details; char *_details;
size_t _detailsCapacity; size_t _detailsCapacity;
grpc_metadata_array _trailers; grpc_metadata_array _trailers;
} }
- (instancetype)init { - (instancetype) init {
return [self initWithHandler:nil]; return [self initWithHandler:nil];
} }
- (instancetype)initWithHandler:(void (^)(NSError *, NSDictionary *))handler { - (instancetype) initWithHandler:(void (^)(NSError *, NSDictionary *))handler {
if (self = [super init]) { if (self = [super init]) {
_op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; _op.op = GRPC_OP_RECV_STATUS_ON_CLIENT;
_op.data.recv_status_on_client.status = &_statusCode; _op.data.recv_status_on_client.status = &_statusCode;
@ -217,11 +216,10 @@
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
_handler = ^{ _handler = ^{
__strong typeof(self) strongSelf = weakSelf; __strong typeof(self) strongSelf = weakSelf;
NSError *error = NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode
[NSError grpc_errorFromStatusCode:strongSelf->_statusCode details:strongSelf->_details];
details:strongSelf->_details];
NSDictionary *trailers = [NSDictionary NSDictionary *trailers = [NSDictionary
grpc_dictionaryFromMetadataArray:strongSelf->_trailers]; grpc_dictionaryFromMetadataArray:strongSelf->_trailers];
handler(error, trailers); handler(error, trailers);
}; };
} }
@ -247,21 +245,20 @@
return [self initWithHost:nil path:nil]; return [self initWithHost:nil path:nil];
} }
- (instancetype)initWithHost:(NSString *)host path:(NSString *)path { - (instancetype)initWithHost:(NSString *)host
path:(NSString *)path {
if (!path || !host) { if (!path || !host) {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException
format:@"path and host cannot be nil."]; format:@"path and host cannot be nil."];
} }
if (self = [super init]) { if (self = [super init]) {
// Each completion queue consumes one thread. There's a trade to be made // Each completion queue consumes one thread. There's a trade to be made between creating and
// between creating and consuming too many threads and having contention of // consuming too many threads and having contention of multiple calls in a single completion
// multiple calls in a single completion queue. Currently we use a singleton // queue. Currently we use a singleton queue.
// queue.
_queue = [GRPCCompletionQueue completionQueue]; _queue = [GRPCCompletionQueue completionQueue];
_call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path _call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path completionQueue:_queue];
completionQueue:_queue];
if (_call == NULL) { if (_call == NULL) {
return nil; return nil;
} }
@ -273,35 +270,32 @@
[self startBatchWithOperations:operations errorHandler:nil]; [self startBatchWithOperations:operations errorHandler:nil];
} }
- (void)startBatchWithOperations:(NSArray *)operations - (void)startBatchWithOperations:(NSArray *)operations errorHandler:(void (^)())errorHandler {
errorHandler:(void (^)())errorHandler {
size_t nops = operations.count; size_t nops = operations.count;
grpc_op *ops_array = gpr_malloc(nops * sizeof(grpc_op)); grpc_op *ops_array = gpr_malloc(nops * sizeof(grpc_op));
size_t i = 0; size_t i = 0;
for (GRPCOperation *operation in operations) { for (GRPCOperation *operation in operations) {
ops_array[i++] = operation.op; ops_array[i++] = operation.op;
} }
grpc_call_error error = grpc_call_start_batch( grpc_call_error error = grpc_call_start_batch(_call, ops_array, nops,
_call, ops_array, nops, (__bridge_retained void *)(^(bool success) { (__bridge_retained void *)(^(bool success){
if (!success) { if (!success) {
if (errorHandler) { if (errorHandler) {
errorHandler(); errorHandler();
} else { } else {
return; return;
} }
} }
for (GRPCOperation *operation in operations) { for (GRPCOperation *operation in operations) {
[operation finish]; [operation finish];
} }
}), }), NULL);
NULL);
gpr_free(ops_array); gpr_free(ops_array);
if (error != GRPC_CALL_OK) { if (error != GRPC_CALL_OK) {
[NSException raise:NSInternalInconsistencyException [NSException raise:NSInternalInconsistencyException
format:@"A precondition for calling grpc_call_start_batch " format:@"A precondition for calling grpc_call_start_batch wasn't met. Error %i",
@"wasn't met. Error %i", error];
error];
} }
} }

@ -36,9 +36,8 @@
@interface NSError (GRPC) @interface NSError (GRPC)
/** /**
* Returns nil if the status code is OK. Otherwise, a NSError whose code is one * Returns nil if the status code is OK. Otherwise, a NSError whose code is one of |GRPCErrorCode|
* of |GRPCErrorCode| and whose domain is |kGRPCErrorDomain|. * and whose domain is |kGRPCErrorDomain|.
*/ */
+ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode + (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode details:(char *)details;
details:(char *)details;
@end @end

Loading…
Cancel
Save