• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /**
20  * The gRPC protocol is an RPC protocol on top of HTTP2.
21  *
22  * While the most common type of RPC receives only one request message and returns only one response
23  * message, the protocol also supports RPCs that return multiple individual messages in a streaming
24  * fashion, RPCs that accept a stream of request messages, or RPCs with both streaming requests and
25  * responses.
26  *
27  * Conceptually, each gRPC call consists of a bidirectional stream of binary messages, with RPCs of
28  * the "non-streaming type" sending only one message in the corresponding direction (the protocol
29  * doesn't make any distinction).
30  *
31  * Each RPC uses a different HTTP2 stream, and thus multiple simultaneous RPCs can be multiplexed
32  * transparently on the same TCP connection.
33  */
34 
35 #import <Foundation/Foundation.h>
36 #import <RxLibrary/GRXWriter.h>
37 
38 #include <AvailabilityMacros.h>
39 
40 #pragma mark gRPC errors
41 
42 /** Domain of NSError objects produced by gRPC. */
43 extern NSString *const kGRPCErrorDomain;
44 
45 /**
46  * gRPC error codes.
47  * Note that a few of these are never produced by the gRPC libraries, but are of general utility for
48  * server applications to produce.
49  */
50 typedef NS_ENUM(NSUInteger, GRPCErrorCode) {
51   /** The operation was cancelled (typically by the caller). */
52   GRPCErrorCodeCancelled = 1,
53 
54   /**
55    * Unknown error. Errors raised by APIs that do not return enough error information may be
56    * converted to this error.
57    */
58   GRPCErrorCodeUnknown = 2,
59 
60   /**
61    * The client specified an invalid argument. Note that this differs from FAILED_PRECONDITION.
62    * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the
63    * server (e.g., a malformed file name).
64    */
65   GRPCErrorCodeInvalidArgument = 3,
66 
67   /**
68    * Deadline expired before operation could complete. For operations that change the state of the
69    * server, this error may be returned even if the operation has completed successfully. For
70    * example, a successful response from the server could have been delayed long enough for the
71    * deadline to expire.
72    */
73   GRPCErrorCodeDeadlineExceeded = 4,
74 
75   /** Some requested entity (e.g., file or directory) was not found. */
76   GRPCErrorCodeNotFound = 5,
77 
78   /** Some entity that we attempted to create (e.g., file or directory) already exists. */
79   GRPCErrorCodeAlreadyExists = 6,
80 
81   /**
82    * The caller does not have permission to execute the specified operation. PERMISSION_DENIED isn't
83    * used for rejections caused by exhausting some resource (RESOURCE_EXHAUSTED is used instead for
84    * those errors). PERMISSION_DENIED doesn't indicate a failure to identify the caller
85    * (UNAUTHENTICATED is used instead for those errors).
86    */
87   GRPCErrorCodePermissionDenied = 7,
88 
89   /**
90    * The request does not have valid authentication credentials for the operation (e.g. the caller's
91    * identity can't be verified).
92    */
93   GRPCErrorCodeUnauthenticated = 16,
94 
95   /** Some resource has been exhausted, perhaps a per-user quota. */
96   GRPCErrorCodeResourceExhausted = 8,
97 
98   /**
99    * The RPC was rejected because the server is not in a state required for the procedure's
100    * execution. For example, a directory to be deleted may be non-empty, etc.
101    * The client should not retry until the server state has been explicitly fixed (e.g. by
102    * performing another RPC). The details depend on the service being called, and should be found in
103    * the NSError's userInfo.
104    */
105   GRPCErrorCodeFailedPrecondition = 9,
106 
107   /**
108    * The RPC was aborted, typically due to a concurrency issue like sequencer check failures,
109    * transaction aborts, etc. The client should retry at a higher-level (e.g., restarting a read-
110    * modify-write sequence).
111    */
112   GRPCErrorCodeAborted = 10,
113 
114   /**
115    * The RPC was attempted past the valid range. E.g., enumerating past the end of a list.
116    * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state
117    * changes. For example, an RPC to get elements of a list will generate INVALID_ARGUMENT if asked
118    * to return the element at a negative index, but it will generate OUT_OF_RANGE if asked to return
119    * the element at an index past the current size of the list.
120    */
121   GRPCErrorCodeOutOfRange = 11,
122 
123   /** The procedure is not implemented or not supported/enabled in this server. */
124   GRPCErrorCodeUnimplemented = 12,
125 
126   /**
127    * Internal error. Means some invariant expected by the server application or the gRPC library has
128    * been broken.
129    */
130   GRPCErrorCodeInternal = 13,
131 
132   /**
133    * The server is currently unavailable. This is most likely a transient condition and may be
134    * corrected by retrying with a backoff.
135    */
136   GRPCErrorCodeUnavailable = 14,
137 
138   /** Unrecoverable data loss or corruption. */
139   GRPCErrorCodeDataLoss = 15,
140 };
141 
142 /**
143  * Safety remark of a gRPC method as defined in RFC 2616 Section 9.1
144  */
145 typedef NS_ENUM(NSUInteger, GRPCCallSafety) {
146   /** Signal that there is no guarantees on how the call affects the server state. */
147   GRPCCallSafetyDefault = 0,
148   /** Signal that the call is idempotent. gRPC is free to use PUT verb. */
149   GRPCCallSafetyIdempotentRequest = 1,
150   /** Signal that the call is cacheable and will not affect server state. gRPC is free to use GET
151      verb. */
152   GRPCCallSafetyCacheableRequest = 2,
153 };
154 
155 /**
156  * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by
157  * the server.
158  */
159 extern id const kGRPCHeadersKey;
160 extern id const kGRPCTrailersKey;
161 
162 #pragma mark GRPCCall
163 
164 /** Represents a single gRPC remote call. */
165 @interface GRPCCall : GRXWriter
166 
167 /**
168  * The authority for the RPC. If nil, the default authority will be used. This property must be nil
169  * when Cronet transport is enabled.
170  */
171 @property(atomic, copy, readwrite) NSString *serverName;
172 
173 /**
174  * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to
175  * positive, the gRPC call returns with status GRPCErrorCodeDeadlineExceeded if it is not completed
176  * within \a timeout seconds. A negative value is not allowed.
177  */
178 @property NSTimeInterval timeout;
179 
180 /**
181  * The container of the request headers of an RPC conforms to this protocol, which is a subset of
182  * NSMutableDictionary's interface. It will become a NSMutableDictionary later on.
183  * The keys of this container are the header names, which per the HTTP standard are case-
184  * insensitive. They are stored in lowercase (which is how HTTP/2 mandates them on the wire), and
185  * can only consist of ASCII characters.
186  * A header value is a NSString object (with only ASCII characters), unless the header name has the
187  * suffix "-bin", in which case the value has to be a NSData object.
188  */
189 /**
190  * These HTTP headers will be passed to the server as part of this call. Each HTTP header is a
191  * name-value pair with string names and either string or binary values.
192  *
193  * The passed dictionary has to use NSString keys, corresponding to the header names. The value
194  * associated to each can be a NSString object or a NSData object. E.g.:
195  *
196  * call.requestHeaders = @{@"authorization": @"Bearer ..."};
197  *
198  * call.requestHeaders[@"my-header-bin"] = someData;
199  *
200  * After the call is started, trying to modify this property is an error.
201  *
202  * The property is initialized to an empty NSMutableDictionary.
203  */
204 @property(atomic, readonly) NSMutableDictionary *requestHeaders;
205 
206 /**
207  * This dictionary is populated with the HTTP headers received from the server. This happens before
208  * any response message is received from the server. It has the same structure as the request
209  * headers dictionary: Keys are NSString header names; names ending with the suffix "-bin" have a
210  * NSData value; the others have a NSString value.
211  *
212  * The value of this property is nil until all response headers are received, and will change before
213  * any of -writeValue: or -writesFinishedWithError: are sent to the writeable.
214  */
215 @property(atomic, readonly) NSDictionary *responseHeaders;
216 
217 /**
218  * Same as responseHeaders, but populated with the HTTP trailers received from the server before the
219  * call finishes.
220  *
221  * The value of this property is nil until all response trailers are received, and will change
222  * before -writesFinishedWithError: is sent to the writeable.
223  */
224 @property(atomic, readonly) NSDictionary *responseTrailers;
225 
226 /**
227  * The request writer has to write NSData objects into the provided Writeable. The server will
228  * receive each of those separately and in order as distinct messages.
229  * A gRPC call might not complete until the request writer finishes. On the other hand, the request
230  * finishing doesn't necessarily make the call to finish, as the server might continue sending
231  * messages to the response side of the call indefinitely (depending on the semantics of the
232  * specific remote method called).
233  * To finish a call right away, invoke cancel.
234  * host parameter should not contain the scheme (http:// or https://), only the name or IP addr
235  * and the port number, for example @"localhost:5050".
236  */
237 - (instancetype)initWithHost:(NSString *)host
238                         path:(NSString *)path
239               requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER;
240 
241 /**
242  * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and
243  * finishes the response side of the call with an error of code CANCELED.
244  */
245 - (void)cancel;
246 
247 /**
248  * Set the call flag for a specific host path.
249  *
250  * Host parameter should not contain the scheme (http:// or https://), only the name or IP addr
251  * and the port number, for example @"localhost:5050".
252  */
253 + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path;
254 
255 /**
256  * Set the dispatch queue to be used for callbacks.
257  *
258  * This configuration is only effective before the call starts.
259  */
260 - (void)setResponseDispatchQueue:(dispatch_queue_t)queue;
261 
262 // TODO(jcanizales): Let specify a deadline. As a category of GRXWriter?
263 @end
264 
265 #pragma mark Backwards compatibiity
266 
267 /** This protocol is kept for backwards compatibility with existing code. */
268 DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
269 @protocol GRPCRequestHeaders<NSObject>
270 @property(nonatomic, readonly) NSUInteger count;
271 
272 - (id)objectForKeyedSubscript:(id)key;
273 - (void)setObject:(id)obj forKeyedSubscript:(id)key;
274 
275 - (void)removeAllObjects;
276 - (void)removeObjectForKey:(id)key;
277 @end
278 
279 #pragma clang diagnostic push
280 #pragma clang diagnostic ignored "-Wdeprecated"
281 /** This is only needed for backwards-compatibility. */
282 @interface NSMutableDictionary (GRPCRequestHeaders)<GRPCRequestHeaders>
283 @end
284 #pragma clang diagnostic pop
285