3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * The gRPC protocol is an RPC protocol on top of HTTP2.
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
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).
31 * Each RPC uses a different HTTP2 stream, and thus multiple simultaneous RPCs can be multiplexed
32 * transparently on the same TCP connection.
35 #import <Foundation/Foundation.h>
36 #import <RxLibrary/GRXWriter.h>
38 #include <AvailabilityMacros.h>
40 #include "GRPCCallOptions.h"
42 NS_ASSUME_NONNULL_BEGIN
44 #pragma mark gRPC errors
46 /** Domain of NSError objects produced by gRPC. */
47 extern NSString *const kGRPCErrorDomain;
51 * Note that a few of these are never produced by the gRPC libraries, but are of general utility for
52 * server applications to produce.
54 typedef NS_ENUM(NSUInteger, GRPCErrorCode) {
55 /** The operation was cancelled (typically by the caller). */
56 GRPCErrorCodeCancelled = 1,
59 * Unknown error. Errors raised by APIs that do not return enough error information may be
60 * converted to this error.
62 GRPCErrorCodeUnknown = 2,
65 * The client specified an invalid argument. Note that this differs from FAILED_PRECONDITION.
66 * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the
67 * server (e.g., a malformed file name).
69 GRPCErrorCodeInvalidArgument = 3,
72 * Deadline expired before operation could complete. For operations that change the state of the
73 * server, this error may be returned even if the operation has completed successfully. For
74 * example, a successful response from the server could have been delayed long enough for the
77 GRPCErrorCodeDeadlineExceeded = 4,
79 /** Some requested entity (e.g., file or directory) was not found. */
80 GRPCErrorCodeNotFound = 5,
82 /** Some entity that we attempted to create (e.g., file or directory) already exists. */
83 GRPCErrorCodeAlreadyExists = 6,
86 * The caller does not have permission to execute the specified operation. PERMISSION_DENIED isn't
87 * used for rejections caused by exhausting some resource (RESOURCE_EXHAUSTED is used instead for
88 * those errors). PERMISSION_DENIED doesn't indicate a failure to identify the caller
89 * (UNAUTHENTICATED is used instead for those errors).
91 GRPCErrorCodePermissionDenied = 7,
94 * The request does not have valid authentication credentials for the operation (e.g. the caller's
95 * identity can't be verified).
97 GRPCErrorCodeUnauthenticated = 16,
99 /** Some resource has been exhausted, perhaps a per-user quota. */
100 GRPCErrorCodeResourceExhausted = 8,
103 * The RPC was rejected because the server is not in a state required for the procedure's
104 * execution. For example, a directory to be deleted may be non-empty, etc.
105 * The client should not retry until the server state has been explicitly fixed (e.g. by
106 * performing another RPC). The details depend on the service being called, and should be found in
107 * the NSError's userInfo.
109 GRPCErrorCodeFailedPrecondition = 9,
112 * The RPC was aborted, typically due to a concurrency issue like sequencer check failures,
113 * transaction aborts, etc. The client should retry at a higher-level (e.g., restarting a read-
114 * modify-write sequence).
116 GRPCErrorCodeAborted = 10,
119 * The RPC was attempted past the valid range. E.g., enumerating past the end of a list.
120 * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state
121 * changes. For example, an RPC to get elements of a list will generate INVALID_ARGUMENT if asked
122 * to return the element at a negative index, but it will generate OUT_OF_RANGE if asked to return
123 * the element at an index past the current size of the list.
125 GRPCErrorCodeOutOfRange = 11,
127 /** The procedure is not implemented or not supported/enabled in this server. */
128 GRPCErrorCodeUnimplemented = 12,
131 * Internal error. Means some invariant expected by the server application or the gRPC library has
134 GRPCErrorCodeInternal = 13,
137 * The server is currently unavailable. This is most likely a transient condition and may be
138 * corrected by retrying with a backoff. Note that it is not always safe to retry
139 * non-idempotent operations.
141 GRPCErrorCodeUnavailable = 14,
143 /** Unrecoverable data loss or corruption. */
144 GRPCErrorCodeDataLoss = 15,
148 * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by
151 extern NSString *const kGRPCHeadersKey;
152 extern NSString *const kGRPCTrailersKey;
154 /** An object can implement this protocol to receive responses from server from a call. */
155 @protocol GRPCResponseHandler<NSObject>
160 * All the responses must be issued to a user-provided dispatch queue. This property specifies the
161 * dispatch queue to be used for issuing the notifications.
163 @property(atomic, readonly) dispatch_queue_t dispatchQueue;
168 * Issued when initial metadata is received from the server.
170 - (void)didReceiveInitialMetadata:(nullable NSDictionary *)initialMetadata;
173 * This method is deprecated and does not work with interceptors. To use GRPCCall2 interface with
174 * interceptor, implement didReceiveData: instead. To implement an interceptor, please leave this
175 * method unimplemented and implement didReceiveData: method instead. If this method and
176 * didReceiveRawMessage are implemented at the same time, implementation of this method will be
179 * Issued when a message is received from the server. The message is the raw data received from the
180 * server, with decompression and without proto deserialization.
182 - (void)didReceiveRawMessage:(nullable NSData *)message;
185 * Issued when a decompressed message is received from the server. The message is decompressed, and
186 * deserialized if a marshaller is provided to the call (marshaller is work in progress).
188 - (void)didReceiveData:(id)data;
191 * Issued when a call finished. If the call finished successfully, \a error is nil and \a
192 * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error
193 * is non-nil and contains the corresponding error information, including gRPC error codes and
194 * error descriptions.
196 - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata
197 error:(nullable NSError *)error;
200 * Issued when flow control is enabled for the call and a message written with writeData: method of
201 * GRPCCall2 is passed to gRPC core with SEND_MESSAGE operation.
203 - (void)didWriteData;
208 * Call related parameters. These parameters are automatically specified by Protobuf. If directly
209 * using the \a GRPCCall2 class, users should specify these parameters manually.
211 @interface GRPCRequestOptions : NSObject<NSCopying>
213 - (instancetype)init NS_UNAVAILABLE;
215 + (instancetype) new NS_UNAVAILABLE;
217 /** Initialize with all properties. */
218 - (instancetype)initWithHost:(NSString *)host
219 path:(NSString *)path
220 safety:(GRPCCallSafety)safety NS_DESIGNATED_INITIALIZER;
222 /** The host serving the RPC service. */
223 @property(copy, readonly) NSString *host;
224 /** The path to the RPC call. */
225 @property(copy, readonly) NSString *path;
227 * Specify whether the call is idempotent or cachable. gRPC may select different HTTP verbs for the
228 * call based on this information. The default verb used by gRPC is POST.
230 @property(readonly) GRPCCallSafety safety;
234 #pragma mark GRPCCall
237 * A \a GRPCCall2 object represents an RPC call.
239 @interface GRPCCall2 : NSObject
241 - (instancetype)init NS_UNAVAILABLE;
243 + (instancetype) new NS_UNAVAILABLE;
246 * Designated initializer for a call.
247 * \param requestOptions Protobuf generated parameters for the call.
248 * \param responseHandler The object to which responses should be issued.
249 * \param callOptions Options for the call.
251 - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions
252 responseHandler:(id<GRPCResponseHandler>)responseHandler
253 callOptions:(nullable GRPCCallOptions *)callOptions
254 NS_DESIGNATED_INITIALIZER;
256 * Convenience initializer for a call that uses default call options (see GRPCCallOptions.m for
257 * the default options).
259 - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions
260 responseHandler:(id<GRPCResponseHandler>)responseHandler;
263 * Starts the call. This function must only be called once for each instance.
268 * Cancel the request of this call at best effort. It attempts to notify the server that the RPC
269 * should be cancelled, and issue didCloseWithTrailingMetadata:error: callback with error code
270 * CANCELED if no other error code has already been issued.
275 * Send a message to the server. The data is subject to marshaller serialization and compression
276 * (marshaller is work in progress).
278 - (void)writeData:(id)data;
281 * Finish the RPC request and half-close the call. The server may still send messages and/or
282 * trailers to the client. The method must only be called once and after start is called.
287 * Tell gRPC to receive the next N gRPC message from gRPC core.
289 * This method should only be used when flow control is enabled. When flow control is not enabled,
290 * this method is a no-op.
292 - (void)receiveNextMessages:(NSUInteger)numberOfMessages;
295 * Get a copy of the original call options.
297 @property(readonly, copy) GRPCCallOptions *callOptions;
299 /** Get a copy of the original request options. */
300 @property(readonly, copy) GRPCRequestOptions *requestOptions;
304 NS_ASSUME_NONNULL_END
306 #pragma clang diagnostic push
307 #pragma clang diagnostic ignored "-Wnullability-completeness"
310 * This interface is deprecated. Please use \a GRPCcall2.
312 * Represents a single gRPC remote call.
314 @interface GRPCCall : GRXWriter
316 - (instancetype)init NS_UNAVAILABLE;
319 * The container of the request headers of an RPC conforms to this protocol, which is a subset of
320 * NSMutableDictionary's interface. It will become a NSMutableDictionary later on.
321 * The keys of this container are the header names, which per the HTTP standard are case-
322 * insensitive. They are stored in lowercase (which is how HTTP/2 mandates them on the wire), and
323 * can only consist of ASCII characters.
324 * A header value is a NSString object (with only ASCII characters), unless the header name has the
325 * suffix "-bin", in which case the value has to be a NSData object.
328 * These HTTP headers will be passed to the server as part of this call. Each HTTP header is a
329 * name-value pair with string names and either string or binary values.
331 * The passed dictionary has to use NSString keys, corresponding to the header names. The value
332 * associated to each can be a NSString object or a NSData object. E.g.:
334 * call.requestHeaders = @{@"authorization": @"Bearer ..."};
336 * call.requestHeaders[@"my-header-bin"] = someData;
338 * After the call is started, trying to modify this property is an error.
340 * The property is initialized to an empty NSMutableDictionary.
342 @property(atomic, readonly) NSMutableDictionary *requestHeaders;
345 * This dictionary is populated with the HTTP headers received from the server. This happens before
346 * any response message is received from the server. It has the same structure as the request
347 * headers dictionary: Keys are NSString header names; names ending with the suffix "-bin" have a
348 * NSData value; the others have a NSString value.
350 * The value of this property is nil until all response headers are received, and will change before
351 * any of -writeValue: or -writesFinishedWithError: are sent to the writeable.
353 @property(atomic, readonly) NSDictionary *responseHeaders;
356 * Same as responseHeaders, but populated with the HTTP trailers received from the server before the
359 * The value of this property is nil until all response trailers are received, and will change
360 * before -writesFinishedWithError: is sent to the writeable.
362 @property(atomic, readonly) NSDictionary *responseTrailers;
365 * The request writer has to write NSData objects into the provided Writeable. The server will
366 * receive each of those separately and in order as distinct messages.
367 * A gRPC call might not complete until the request writer finishes. On the other hand, the request
368 * finishing doesn't necessarily make the call to finish, as the server might continue sending
369 * messages to the response side of the call indefinitely (depending on the semantics of the
370 * specific remote method called).
371 * To finish a call right away, invoke cancel.
372 * host parameter should not contain the scheme (http:// or https://), only the name or IP addr
373 * and the port number, for example @"localhost:5050".
375 - (instancetype)initWithHost:(NSString *)host
376 path:(NSString *)path
377 requestsWriter:(GRXWriter *)requestWriter;
380 * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and
381 * finishes the response side of the call with an error of code CANCELED.
386 * The following methods are deprecated.
388 + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path;
389 @property(atomic, copy, readwrite) NSString *serverName;
390 @property NSTimeInterval timeout;
391 - (void)setResponseDispatchQueue:(dispatch_queue_t)queue;
395 #pragma mark Backwards compatibiity
397 /** This protocol is kept for backwards compatibility with existing code. */
398 DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
399 @protocol GRPCRequestHeaders<NSObject>
400 @property(nonatomic, readonly) NSUInteger count;
402 - (id)objectForKeyedSubscript:(id)key;
403 - (void)setObject:(id)obj forKeyedSubscript:(id)key;
405 - (void)removeAllObjects;
406 - (void)removeObjectForKey:(id)key;
409 #pragma clang diagnostic push
410 #pragma clang diagnostic ignored "-Wdeprecated"
411 /** This is only needed for backwards-compatibility. */
412 @interface NSMutableDictionary (GRPCRequestHeaders)<GRPCRequestHeaders>
414 #pragma clang diagnostic pop
415 #pragma clang diagnostic pop