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