diff options
author | Muxi Yan <muxi@users.noreply.github.com> | 2016-10-31 18:26:10 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-31 18:26:10 -0700 |
commit | 2a15a3134689a73e3cf6012313bc043015f14b36 (patch) | |
tree | 99750167878c6b74bb8a9d3c1073f95cd650ad1b /src/objective-c/GRPCClient | |
parent | 0df7d349b7ceb510e71481ff6ea707be2db0160a (diff) | |
parent | 411969a67cc34c6ce822c7a76f476698fc4eb353 (diff) |
Merge pull request #8561 from muxi/update-objc-connectivity
Revert format changes in #8441
Diffstat (limited to 'src/objective-c/GRPCClient')
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+ChannelArg.h | 17 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h | 16 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+OAuth2.h | 14 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+Tests.h | 25 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall.h | 189 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall.m | 204 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCCompletionQueue.h | 17 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h | 19 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m | 79 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCHost.m | 81 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 41 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 86 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/NSError+GRPC.h | 7 |
13 files changed, 336 insertions, 459 deletions
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h index c1623a0068..4a3f3fa4a1 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h @@ -40,18 +40,15 @@ @interface GRPCCall (ChannelArg) /** - * Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent - * string for all calls to the specified @c host. + * Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent string for all calls + * to the specified @c host. */ -+ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix - forHost:(nonnull NSString *)host; ++ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix 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)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE( - "The API for this feature is experimental, " - "and might be removed or modified at any " - "time."); ++ (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, " + "and might be removed or modified at any " + "time."); @end diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h index beae0d11a2..ac2a37d75f 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h @@ -33,26 +33,24 @@ #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) /** - * Use the provided @c pemRootCert as the set of trusted root Certificate - * Authorities for @c host. + * Use the provided @c pemRootCert as the set of trusted root Certificate Authorities for @c host. */ + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert 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 - * root Certificate Authorities. If @c pemRootCerts is nil, the default CA - * Certificates bundled with gRPC will be used. + * Configures @c host with TLS/SSL Client Credentials and optionally trusted root Certificate + * Authorities. If @c pemRootCerts is nil, the default CA Certificates bundled with gRPC will be + * used. */ + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain forHost:(nonnull NSString *)host - error:(NSError *_Nullable *_Nullable)errorPtr; + error:(NSError * _Nullable * _Nullable)errorPtr; @end diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.h b/src/objective-c/GRPCClient/GRPCCall+OAuth2.h index 467c6332c1..6b443877e9 100644 --- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.h +++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.h @@ -37,17 +37,15 @@ @interface GRPCCall (OAuth2) /** - * Setting this property is equivalent to setting "Bearer <passed token>" as the - * value of the request header with key "authorization" (the authorization - * header). Setting it to nil removes the authorization header from the request. - * The value obtained by getting the property is the OAuth2 bearer token if the - * authorization header of the request has the form "Bearer <token>", or nil - * otherwise. + * Setting this property is equivalent to setting "Bearer <passed token>" as the value of the + * request header with key "authorization" (the authorization header). Setting it to nil removes the + * authorization header from the request. + * The value obtained by getting the property is the OAuth2 bearer token if the authorization header + * of the request has the form "Bearer <token>", or nil otherwise. */ @property(atomic, copy) NSString *oauth2AccessToken; -/** Returns the value (if any) of the "www-authenticate" response header (the - * challenge header). */ +/** Returns the value (if any) of the "www-authenticate" response header (the challenge header). */ @property(atomic, readonly) NSString *oauth2ChallengeHeader; @end diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.h b/src/objective-c/GRPCClient/GRPCCall+Tests.h index f517f3aac8..184ad09c5c 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.h +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.h @@ -34,36 +34,33 @@ #import "GRPCCall.h" /** - * Methods to let tune down the security of gRPC connections for specific hosts. - * These shouldn't be used in releases, but are sometimes needed for testing. + * Methods to let tune down the security of gRPC connections for specific hosts. These shouldn't be + * used in releases, but are sometimes needed for testing. */ @interface GRPCCall (Tests) /** - * Establish all SSL connections to the provided host using the passed SSL - * target name and the root certificates found in the file at |certsPath|. + * Establish all SSL connections to the provided host using the passed SSL target name and the root + * certificates found in the file at |certsPath|. * - * Must be called before any gRPC call to that host is made. It's illegal to - * pass the same host to more than one invocation of the methods of this - * category. + * Must be called before any gRPC call to that host is made. It's illegal to pass the same host to + * more than one invocation of the methods of this category. */ + (void)useTestCertsPath:(NSString *)certsPath testName:(NSString *)testName forHost:(NSString *)host; /** - * Establish all connections to the provided host using cleartext instead of - * SSL. + * Establish all connections to the provided host using cleartext instead of SSL. * - * Must be called before any gRPC call to that host is made. It's illegal to - * pass the same host to more than one invocation of the methods of this - * category. + * Must be called before any gRPC call to that host is made. It's illegal to pass the same host to + * more than one invocation of the methods of this category. */ + (void)useInsecureConnectionsForHost:(NSString *)host; /** - * Resets all host configurations to their default values, and flushes all - * connections from the cache. + * Resets all host configurations to their default values, and flushes all connections from the + * cache. */ + (void)resetHostSettings; @end diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 5ed160d7a0..7645bb1d34 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -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 diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 85d141aa09..44393f6b99 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -33,9 +33,9 @@ #import "GRPCCall.h" -#import <RxLibrary/GRXConcurrentWriteable.h> #include <grpc/grpc.h> #include <grpc/support/time.h> +#import <RxLibrary/GRXConcurrentWriteable.h> #import "private/GRPCConnectivityMonitor.h" #import "private/GRPCHost.h" @@ -45,11 +45,11 @@ #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" -NSString *const kGRPCHeadersKey = @"io.grpc.HeadersKey"; -NSString *const kGRPCTrailersKey = @"io.grpc.TrailersKey"; +NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey"; +NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; static NSMutableDictionary *callFlags; -@interface GRPCCall ()<GRXWriteable> +@interface GRPCCall () <GRXWriteable> // Make them read-write. @property(atomic, strong) NSDictionary *responseHeaders; @property(atomic, strong) NSDictionary *responseTrailers; @@ -85,21 +85,17 @@ static NSMutableDictionary *callFlags; // correct ordering. GRXConcurrentWriteable *_responseWriteable; - // The network thread wants the requestWriter to resume (when the server is - // ready for more input), or to stop (on errors), concurrently with user - // threads that want to start it, pause it or stop it. Because a writer isn't - // thread-safe, we'll synchronize those operations on it. - // We don't use a dispatch queue for that purpose, because the writer can call - // writeValue: or writesFinishedWithError: on this GRPCCall as part of those - // operations. We want to be able to pause the writer immediately on - // writeValue:, so we need our locking to be recursive. + // The network thread wants the requestWriter to resume (when the server is ready for more input), + // or to stop (on errors), concurrently with user threads that want to start it, pause it or stop + // it. Because a writer isn't thread-safe, we'll synchronize those operations on it. + // We don't use a dispatch queue for that purpose, because the writer can call writeValue: or + // writesFinishedWithError: on this GRPCCall as part of those operations. We want to be able to + // pause the writer immediately on writeValue:, so we need our locking to be recursive. GRXWriter *_requestWriter; // To create a retain cycle when a call is started, up until it finishes. See - // |startWithWriteable:| and |finishWithError:|. This saves users from having - // to retain a - // reference to the call object if all they're interested in is the handler - // being executed when + // |startWithWriteable:| and |finishWithError:|. This saves users from having to retain a + // reference to the call object if all they're interested in is the handler being executed when // the response arrives. GRPCCall *_retainSelf; @@ -108,16 +104,13 @@ static NSMutableDictionary *callFlags; @synthesize state = _state; -// TODO(jcanizales): If grpc_init is idempotent, this should be changed from -// load to initialize. +// TODO(jcanizales): If grpc_init is idempotent, this should be changed from load to initialize. + (void)load { grpc_init(); callFlags = [NSMutableDictionary dictionary]; } -+ (void)setCallSafety:(GRPCCallSafety)callSafety - host:(NSString *)host - path:(NSString *)path { ++ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path { NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; switch (callSafety) { case GRPCCallSafetyDefault: @@ -148,8 +141,7 @@ static NSMutableDictionary *callFlags; path:(NSString *)path requestsWriter:(GRXWriter *)requestWriter { if (!host || !path) { - [NSException raise:NSInvalidArgumentException - format:@"Neither host nor path can be nil."]; + [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } if (requestWriter.state != GRXWriterStateNotStarted) { [NSException raise:NSInvalidArgumentException @@ -199,10 +191,7 @@ static NSMutableDictionary *callFlags; - (void)cancel { [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]]; [self cancelCall]; } @@ -217,18 +206,15 @@ static NSMutableDictionary *callFlags; // Only called from the call queue. // The handler will be called from the network queue. -- (void)startReadWithHandler:(void (^)(grpc_byte_buffer *))handler { +- (void)startReadWithHandler:(void(^)(grpc_byte_buffer *))handler { // TODO(jcanizales): Add error handlers for async failures - [_wrappedCall startBatchWithOperations:@[ [[GRPCOpRecvMessage alloc] - initWithHandler:handler] ]]; + [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMessage alloc] initWithHandler:handler]]]; } // Called initially from the network queue once response headers are received, -// then "recursively" from the responseWriteable queue after each response from -// the +// then "recursively" from the responseWriteable queue after each response from the // server has been written. -// If the call is currently paused, this is a noop. Restarting the call will -// invoke this +// If the call is currently paused, this is a noop. Restarting the call will invoke this // method. // TODO(jcanizales): Rename to readResponseIfNotPaused. - (void)startNextRead { @@ -251,23 +237,15 @@ static NSMutableDictionary *callFlags; // don't want to throw, because the app shouldn't crash for a behavior // that's on the hands of any server to have. Instead we finish and ask // the server to cancel. - [weakSelf - finishWithError:[NSError - errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeResourceExhausted - userInfo:@{ - NSLocalizedDescriptionKey : - @"Client does not have enough " - @"memory to hold the server " - @"response." - }]]; + [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeResourceExhausted + userInfo:@{NSLocalizedDescriptionKey: @"Client does not have enough memory to hold the server response."}]]; [weakSelf cancelCall]; return; } - [weakWriteable enqueueValue:data - completionHandler:^{ - [weakSelf startNextRead]; - }]; + [weakWriteable enqueueValue:data completionHandler:^{ + [weakSelf startNextRead]; + }]; }]; }); } @@ -276,22 +254,19 @@ static NSMutableDictionary *callFlags; - (void)sendHeaders:(NSDictionary *)headers { // TODO(jcanizales): Add error handlers for async failures - [_wrappedCall startBatchWithOperations:@[ - [[GRPCOpSendMetadata alloc] - initWithMetadata:headers - flags:[GRPCCall callFlagsForHost:_host path:_path] - handler:nil] - ]]; + [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers + flags:[GRPCCall callFlagsForHost:_host path:_path] + handler:nil]]]; } #pragma mark GRXWriteable implementation // Only called from the call queue. The error handler will be called from the // network queue if the write didn't succeed. -- (void)writeMessage:(NSData *)message - withErrorHandler:(void (^)())errorHandler { +- (void)writeMessage:(NSData *)message withErrorHandler:(void (^)())errorHandler { + __weak GRPCCall *weakSelf = self; - void (^resumingHandler)(void) = ^{ + void(^resumingHandler)(void) = ^{ // Resume the request writer. GRPCCall *strongSelf = weakSelf; if (strongSelf) { @@ -300,9 +275,8 @@ static NSMutableDictionary *callFlags; } } }; - [_wrappedCall startBatchWithOperations:@[ [[GRPCOpSendMessage alloc] - initWithMessage:message - handler:resumingHandler] ] + [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMessage alloc] initWithMessage:message + handler:resumingHandler]] errorHandler:errorHandler]; } @@ -317,20 +291,18 @@ static NSMutableDictionary *callFlags; __weak GRPCCall *weakSelf = self; dispatch_async(_callQueue, ^{ - [weakSelf writeMessage:value - withErrorHandler:^{ - [weakSelf - finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + [weakSelf writeMessage:value withErrorHandler:^{ + [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeInternal userInfo:nil]]; - }]; + }]; }); } // Only called from the call queue. The error handler will be called from the // network queue if the requests stream couldn't be closed successfully. - (void)finishRequestWithErrorHandler:(void (^)())errorHandler { - [_wrappedCall startBatchWithOperations:@[ [[GRPCOpSendClose alloc] init] ] + [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendClose alloc] init]] errorHandler:errorHandler]; } @@ -351,19 +323,17 @@ static NSMutableDictionary *callFlags; #pragma mark Invoke -// Both handlers will eventually be called, from the network queue. Writes can -// start immediately after this. +// Both handlers will eventually be called, from the network queue. Writes can start immediately +// after this. // The first one (headersHandler), when the response headers are received. // The second one (completionHandler), whenever the RPC finishes for any reason. -- (void)invokeCallWithHeadersHandler:(void (^)(NSDictionary *))headersHandler - completionHandler: - (void (^)(NSError *, NSDictionary *))completionHandler { +- (void)invokeCallWithHeadersHandler:(void(^)(NSDictionary *))headersHandler + completionHandler:(void(^)(NSError *, NSDictionary *))completionHandler { // TODO(jcanizales): Add error handlers for async failures - [_wrappedCall startBatchWithOperations:@[ [[GRPCOpRecvMetadata alloc] - initWithHandler:headersHandler] ]]; - [_wrappedCall - startBatchWithOperations:@[ [[GRPCOpRecvStatus alloc] - initWithHandler:completionHandler] ]]; + [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMetadata alloc] + initWithHandler:headersHandler]]]; + [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvStatus alloc] + initWithHandler:completionHandler]]]; } - (void)invokeCall { @@ -371,31 +341,27 @@ static NSMutableDictionary *callFlags; // Response headers received. self.responseHeaders = headers; [self startNextRead]; - } - completionHandler:^(NSError *error, NSDictionary *trailers) { - self.responseTrailers = trailers; - - if (error) { - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - if (error.userInfo) { - [userInfo addEntriesFromDictionary:error.userInfo]; - } - userInfo[kGRPCTrailersKey] = self.responseTrailers; - // TODO(jcanizales): The C gRPC library doesn't guarantee that the - // headers block will be called before this one, so an error might end - // up with trailers but no headers. We shouldn't call finishWithError - // until ater both blocks are called. It is also when this is done - // that we can provide a merged view of response headers and trailers - // in a thread-safe way. - if (self.responseHeaders) { - userInfo[kGRPCHeadersKey] = self.responseHeaders; - } - error = [NSError errorWithDomain:error.domain - code:error.code - userInfo:userInfo]; - } - [self finishWithError:error]; - }]; + } completionHandler:^(NSError *error, NSDictionary *trailers) { + self.responseTrailers = trailers; + + if (error) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (error.userInfo) { + [userInfo addEntriesFromDictionary:error.userInfo]; + } + userInfo[kGRPCTrailersKey] = self.responseTrailers; + // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be + // called before this one, so an error might end up with trailers but no headers. We + // shouldn't call finishWithError until ater both blocks are called. It is also when this is + // done that we can provide a merged view of response headers and trailers in a thread-safe + // way. + if (self.responseHeaders) { + userInfo[kGRPCHeadersKey] = self.responseHeaders; + } + error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; + } + [self finishWithError:error]; + }]; // Now that the RPC has been initiated, request writes can start. @synchronized(_requestWriter) { [_requestWriter startWithWriteable:self]; @@ -409,16 +375,14 @@ static NSMutableDictionary *callFlags; _state = GRXWriterStateStarted; } - // Create a retain cycle so that this instance lives until the RPC finishes - // (or is cancelled). This makes RPCs in which the call isn't externally - // retained possible (as long as it is started before being autoreleased). - // Care is taken not to retain self strongly in any of the blocks used in this - // implementation, so that the life of the instance is determined by this - // retain cycle. + // Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled). + // This makes RPCs in which the call isn't externally retained possible (as long as it is started + // before being autoreleased). + // Care is taken not to retain self strongly in any of the blocks used in this implementation, so + // that the life of the instance is determined by this retain cycle. _retainSelf = self; - _responseWriteable = - [[GRXConcurrentWriteable alloc] initWithWriteable:writeable]; + _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable]; _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path]; NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?"); @@ -427,37 +391,29 @@ static NSMutableDictionary *callFlags; [self invokeCall]; // TODO(jcanizales): Extract this logic somewhere common. - NSString *host = - [NSURL URLWithString:[@"https://" stringByAppendingString:_host]].host; + NSString *host = [NSURL URLWithString:[@"https://" stringByAppendingString:_host]].host; if (!host) { // TODO(jcanizales): Check this on init. - [NSException raise:NSInvalidArgumentException - format:@"host of %@ is nil", _host]; + [NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", _host]; } __weak typeof(self) weakSelf = self; _connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host]; void (^handler)() = ^{ typeof(self) strongSelf = weakSelf; if (strongSelf) { - [strongSelf - finishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeUnavailable - userInfo:@{ - NSLocalizedDescriptionKey : - @"Connectivity lost." - }]]; + [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeUnavailable + userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]]; } }; [_connectivityMonitor handleLossWithHandler:handler - wifiStatusChangeHandler:^{ - }]; + wifiStatusChangeHandler:nil]; } - (void)setState:(GRXWriterState)newState { @synchronized(self) { // Manual transitions are only allowed from the started or paused states. - if (_state == GRXWriterStateNotStarted || - _state == GRXWriterStateFinished) { + if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) { return; } diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h index c0bbf22c74..fe3b8f39d1 100644 --- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h +++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h @@ -34,19 +34,18 @@ #import <Foundation/Foundation.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 - * the value of the |unmanagedQueue| property of an instance of this class to - * |grpc_channel_create_call|. Then for every |grpc_call_*| method that accepts - * a tag, you can pass a block of type |GRPCQueueCompletionHandler| (remembering - * to cast it using |__bridge_retained|). The block is guaranteed to eventually - * be called, by a concurrent queue, and then released. Each such block is + * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the + * |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for + * every |grpc_call_*| method that accepts a tag, you can pass a block of type + * |GRPCQueueCompletionHandler| (remembering to cast it using |__bridge_retained|). The block is + * guaranteed to eventually be called, by a concurrent queue, and then released. Each such block is * passed a |bool| that tells if the operation was successful. * - * Release the GRPCCompletionQueue object only after you are not going to pass - * any more blocks to the |grpc_call| that's using it. + * Release the GRPCCompletionQueue object only after you are not going to pass any more blocks to + * the |grpc_call| that's using it. */ @interface GRPCCompletionQueue : NSObject @property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue; diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h index 941b596d2c..e341b6ef6c 100644 --- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h +++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h @@ -45,7 +45,7 @@ */ #define GRPC_XMACRO_ITEM(methodName, FlagName) \ - @property(nonatomic, readonly) BOOL methodName; +@property(nonatomic, readonly) BOOL methodName; #include "GRPCReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM @@ -60,19 +60,18 @@ - (nonnull instancetype)init NS_UNAVAILABLE; /** - * Queue on which callbacks will be dispatched. Default is the main queue. Set - * it before calling handleLossWithHandler:. + * Queue on which callbacks will be dispatched. Default is the main queue. Set it before calling + * handleLossWithHandler:. */ // TODO(jcanizales): Default to a serial background queue instead. @property(nonatomic, strong, null_resettable) dispatch_queue_t queue; /** - * Calls handler every time the connectivity to this instance's host is lost. If - * this instance is released before that happens, the handler won't be called. - * Only one handler is active at a time, so if this method is called again - * before the previous handler has been called, it might never be called at all - * (or yes, if it has already been queued). + * Calls handler every time the connectivity to this instance's host is lost. If this instance is + * released before that happens, the handler won't be called. + * Only one handler is active at a time, so if this method is called again before the previous + * handler has been called, it might never be called at all (or yes, if it has already been queued). */ -- (void)handleLossWithHandler:(nonnull void (^)())handler - wifiStatusChangeHandler:(nonnull void (^)())wifiStatusChangeHandler; +- (void)handleLossWithHandler:(nullable void (^)())lossHandler + wifiStatusChangeHandler:(nullable void (^)())wifiStatusChangeHandler; @end diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m index fec6391d39..40afca2d3d 100644 --- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m +++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m @@ -58,20 +58,19 @@ } */ -#define GRPC_XMACRO_ITEM(methodName, FlagName) \ - -(BOOL)methodName { \ - return !!(_flags & kSCNetworkReachabilityFlags##FlagName); \ - } +#define GRPC_XMACRO_ITEM(methodName, FlagName) \ +- (BOOL)methodName { \ + return !!(_flags & kSCNetworkReachabilityFlags ## FlagName); \ +} #include "GRPCReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM - (BOOL)isHostReachable { - // Note: connectionOnDemand means it'll be reachable only if using the - // CFSocketStream API or APIs on top of it. - // connectionRequired means we can't tell until a connection is attempted - // (e.g. for VPN on demand). - return self.reachable && !self.interventionRequired && - !self.connectionOnDemand; + // Note: connectionOnDemand means it'll be reachable only if using the CFSocketStream API or APIs + // on top of it. + // connectionRequired means we can't tell until a connection is attempted (e.g. for VPN on + // demand). + return self.reachable && !self.interventionRequired && !self.connectionOnDemand; } - (NSString *)description { @@ -80,9 +79,9 @@ /* * For each flag, add its name to the array if it's ON. Example: - if (self.isCell) { - [activeOptions addObject:@"isCell"]; - } + if (self.isCell) { + [activeOptions addObject:@"isCell"]; + } */ #define GRPC_XMACRO_ITEM(methodName, FlagName) \ @@ -92,14 +91,12 @@ #include "GRPCReachabilityFlagNames.xmacro.h" #undef GRPC_XMACRO_ITEM - return activeOptions.count == 0 - ? @"(none)" - : [activeOptions componentsJoinedByString:@", "]; + return activeOptions.count == 0 ? @"(none)" : [activeOptions componentsJoinedByString:@", "]; } - (BOOL)isEqual:(id)object { return [object isKindOfClass:[GRPCReachabilityFlags class]] && - _flags == ((GRPCReachabilityFlags *)object)->_flags; + _flags == ((GRPCReachabilityFlags *)object)->_flags; } - (NSUInteger)hash { @@ -109,16 +106,15 @@ #pragma mark Connectivity Monitor -// Assumes the third argument is a block that accepts a GRPCReachabilityFlags -// object, and passes the received ones to it. +// Assumes the third argument is a block that accepts a GRPCReachabilityFlags object, and passes the +// received ones to it. static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) { -#pragma unused(target) - // This can be called many times with the same info. The info is retained by - // SCNetworkReachability while this function is being executed. - void (^handler)(GRPCReachabilityFlags *) = - (__bridge void (^)(GRPCReachabilityFlags *))info; + #pragma unused (target) + // This can be called many times with the same info. The info is retained by SCNetworkReachability + // while this function is being executed. + void (^handler)(GRPCReachabilityFlags *) = (__bridge void (^)(GRPCReachabilityFlags *))info; handler([[GRPCReachabilityFlags alloc] initWithFlags:flags]); } @@ -127,8 +123,7 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target, GRPCReachabilityFlags *_previousReachabilityFlags; } -- (nullable instancetype)initWithReachability: - (nullable SCNetworkReachabilityRef)reachability { +- (nullable instancetype)initWithReachability:(nullable SCNetworkReachabilityRef)reachability { if (!reachability) { return nil; } @@ -149,23 +144,23 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target, SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, hostName); - GRPCConnectivityMonitor *returnValue = - [[self alloc] initWithReachability:reachability]; + GRPCConnectivityMonitor *returnValue = [[self alloc] initWithReachability:reachability]; if (reachability) { CFRelease(reachability); } return returnValue; } -- (void)handleLossWithHandler:(void (^)())handler - wifiStatusChangeHandler:(nonnull void (^)())wifiStatusChangeHandler { +- (void)handleLossWithHandler:(nullable void (^)())lossHandler + wifiStatusChangeHandler:(nullable void (^)())wifiStatusChangeHandler { __weak typeof(self) weakSelf = self; [self startListeningWithHandler:^(GRPCReachabilityFlags *flags) { typeof(self) strongSelf = weakSelf; if (strongSelf) { - if (!flags.reachable) { - handler(); - } else if (strongSelf->_previousReachabilityFlags && + if (lossHandler && !flags.reachable) { + lossHandler(); + } else if (wifiStatusChangeHandler && + strongSelf->_previousReachabilityFlags && (flags.isWWAN ^ strongSelf->_previousReachabilityFlags.isWWAN)) { wifiStatusChangeHandler(); @@ -176,19 +171,17 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target, } - (void)startListeningWithHandler:(void (^)(GRPCReachabilityFlags *))handler { - // Copy to ensure the handler block is in the heap (and so can't be - // deallocated when this method returns). + // Copy to ensure the handler block is in the heap (and so can't be deallocated when this method + // returns). void (^copiedHandler)(GRPCReachabilityFlags *) = [handler copy]; SCNetworkReachabilityContext context = { - .version = 0, - .info = (__bridge void *)copiedHandler, - .retain = CFRetain, - .release = CFRelease, + .version = 0, + .info = (__bridge void *)copiedHandler, + .retain = CFRetain, + .release = CFRelease, }; - // The following will retain context.info, and release it when the callback is - // set to NULL. - SCNetworkReachabilitySetCallback(_reachabilityRef, - PassFlagsToContextInfoBlock, &context); + // The following will retain context.info, and release it when the callback is set to NULL. + SCNetworkReachabilitySetCallback(_reachabilityRef, PassFlagsToContextInfoBlock, &context); SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _queue); } diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index dd0479083d..31065cbf01 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -33,9 +33,9 @@ #import "GRPCHost.h" -#import <GRPCClient/GRPCCall.h> #include <grpc/grpc.h> #include <grpc/grpc_security.h> +#import <GRPCClient/GRPCCall.h> #ifdef GRPC_COMPILE_WITH_CRONET #import <GRPCClient/GRPCCall+ChannelArg.h> #import <GRPCClient/GRPCCall+Cronet.h> @@ -48,8 +48,7 @@ NS_ASSUME_NONNULL_BEGIN -// TODO(jcanizales): Generate the version in a standalone header, from -// templates. Like +// TODO(jcanizales): Generate the version in a standalone header, from templates. Like // templates/src/core/surface/version.c.template . #define GRPC_OBJC_VERSION_STRING @"1.0.1" @@ -62,8 +61,7 @@ static NSMutableDictionary *kHostCache; static GRPCConnectivityMonitor *connectivityMonitor = nil; @implementation GRPCHost { - // TODO(mlumish): Investigate whether caching channels with strong links is a - // good idea. + // TODO(mlumish): Investigate whether caching channels with strong links is a good idea. GRPCChannel *_channel; } @@ -83,13 +81,11 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; return nil; } - // To provide a default port, we try to interpret the address. If it's just a - // host name without scheme and without port, we'll use port 443. If it has a - // scheme, we pass it untouched to the C gRPC library. - // TODO(jcanizales): Add unit tests for the types of addresses we want to let - // pass untouched. - NSURL *hostURL = - [NSURL URLWithString:[@"https://" stringByAppendingString:address]]; + // To provide a default port, we try to interpret the address. If it's just a host name without + // scheme and without port, we'll use port 443. If it has a scheme, we pass it untouched to the C + // gRPC library. + // TODO(jcanizales): Add unit tests for the types of addresses we want to let pass untouched. + NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]]; if (hostURL.host && !hostURL.port) { address = [hostURL.host stringByAppendingString:@":443"]; } @@ -99,7 +95,6 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; dispatch_once(&cacheInitialization, ^{ kHostCache = [NSMutableDictionary dictionary]; }); - @synchronized(kHostCache) { GRPCHost *cachedHost = kHostCache[address]; if (cachedHost) { @@ -137,7 +132,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; } + (void)resetAllHostSettings { - @synchronized(kHostCache) { + @synchronized (kHostCache) { kHostCache = [NSMutableDictionary dictionary]; } } @@ -163,19 +158,16 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; static NSError *kDefaultRootsError; static dispatch_once_t loading; dispatch_once(&loading, ^{ - NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem - // Do not use NSBundle.mainBundle, as it's nil for tests of library - // projects. + NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem + // Do not use NSBundle.mainBundle, as it's nil for tests of library projects. NSBundle *bundle = [NSBundle bundleForClass:self.class]; NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"]; NSError *error; - // Files in PEM format can have non-ASCII characters in their comments (e.g. - // for the name of the issuer). Load them as UTF8 and produce an ASCII - // equivalent. - NSString *contentInUTF8 = - [NSString stringWithContentsOfFile:path - encoding:NSUTF8StringEncoding - error:&error]; + // Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the + // issuer). Load them as UTF8 and produce an ASCII equivalent. + NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path + encoding:NSUTF8StringEncoding + error:&error]; if (contentInUTF8 == nil) { kDefaultRootsError = error; return; @@ -193,15 +185,11 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; if (errorPtr) { *errorPtr = kDefaultRootsError; } - NSAssert(kDefaultRootsASCII, - @"Could not read gRPCCertificates.bundle/roots.pem. This file, " - "with the root certificates, is needed to establish secure " - "(TLS) connections. " - "Because the file is distributed with the gRPC library, this " - "error is usually a sign " - "that the library wasn't configured correctly for your " - "project. Error: %@", - kDefaultRootsError); + NSAssert(kDefaultRootsASCII, @"Could not read gRPCCertificates.bundle/roots.pem. This file, " + "with the root certificates, is needed to establish secure (TLS) connections. " + "Because the file is distributed with the gRPC library, this error is usually a sign " + "that the library wasn't configured correctly for your project. Error: %@", + kDefaultRootsError); return NO; } rootsASCII = kDefaultRootsASCII; @@ -212,12 +200,10 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL); } else { grpc_ssl_pem_key_cert_pair key_cert_pair; - NSData *privateKeyASCII = - [pemPrivateKey dataUsingEncoding:NSASCIIStringEncoding - allowLossyConversion:YES]; - NSData *certChainASCII = - [pemCertChain dataUsingEncoding:NSASCIIStringEncoding - allowLossyConversion:YES]; + NSData *privateKeyASCII = [pemPrivateKey dataUsingEncoding:NSASCIIStringEncoding + allowLossyConversion:YES]; + NSData *certChainASCII = [pemCertChain dataUsingEncoding:NSASCIIStringEncoding + allowLossyConversion:YES]; key_cert_pair.private_key = privateKeyASCII.bytes; key_cert_pair.cert_chain = certChainASCII.bytes; creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL); @@ -237,8 +223,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; NSMutableDictionary *args = [NSMutableDictionary dictionary]; // TODO(jcanizales): Add OS and device information (see - // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents - // ). + // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents ). NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; if (_userAgentPrefix) { userAgent = [_userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; @@ -252,7 +237,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; if (_responseSizeLimitOverride) { args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = _responseSizeLimitOverride; } - // Use 10000ms initial backoff time for correct behavior on bad/slow networks + // Use 10000ms initial backoff time for correct behavior on bad/slow networks args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = @10000; return args; } @@ -266,15 +251,12 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; GRPCChannel *channel; @synchronized(self) { if (_channelCreds == nil) { - [self setTLSPEMRootCerts:nil - withPrivateKey:nil - withCertChain:nil - error:nil]; + [self setTLSPEMRootCerts:nil withPrivateKey:nil withCertChain:nil error:nil]; } #ifdef GRPC_COMPILE_WITH_CRONET if (useCronet) { - channel = - [GRPCChannel secureCronetChannelWithHost:_address channelArgs:args]; + channel = [GRPCChannel secureCronetChannelWithHost:_address + channelArgs:args]; } else #endif { @@ -290,8 +272,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil; } - (NSString *)hostName { - // TODO(jcanizales): Default to nil instead of _address when Issue #2635 is - // clarified. + // TODO(jcanizales): Default to nil instead of _address when Issue #2635 is clarified. return _hostNameOverride ?: _address; } diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index 58c6032e80..c6a03c145e 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -38,10 +38,9 @@ #import "NSDictionary+GRPC.h" // Used by the setter. -static void CheckIsNonNilASCII(NSString *name, NSString *value) { +static void CheckIsNonNilASCII(NSString *name, NSString* value) { if (!value) { - [NSException raise:NSInvalidArgumentException - format:@"%@ cannot be nil", name]; + [NSException raise:NSInvalidArgumentException format:@"%@ cannot be nil", name]; } if (![value canBeConvertedToEncoding:NSASCIIStringEncoding]) { [NSException raise:NSInvalidArgumentException @@ -53,20 +52,15 @@ static void CheckIsNonNilASCII(NSString *name, NSString *value) { static void CheckKeyValuePairIsValid(NSString *key, id value) { if ([key hasSuffix:@"-bin"]) { if (![value isKindOfClass:NSData.class]) { - [NSException - raise:NSInvalidArgumentException - format:@"Expected NSData value for header %@ ending in \"-bin\", " - @"instead got %@", - key, value]; + [NSException raise:NSInvalidArgumentException + format:@"Expected NSData value for header %@ ending in \"-bin\", " + @"instead got %@", key, value]; } } else { if (![value isKindOfClass:NSString.class]) { - [NSException - raise:NSInvalidArgumentException - format: - @"Expected NSString value for header %@ not ending in \"-bin\", " - @"instead got %@", - key, value]; + [NSException raise:NSInvalidArgumentException + format:@"Expected NSString value for header %@ not ending in \"-bin\", " + @"instead got %@", key, value]; } CheckIsNonNilASCII(@"Text header value", (NSString *)value); } @@ -74,10 +68,9 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { @implementation GRPCRequestHeaders { __weak GRPCCall *_call; - // The NSMutableDictionary superclass doesn't hold any storage (so that people - // can implement their own in subclasses). As that's not the reason we're - // subclassing, we just delegate storage to the default NSMutableDictionary - // subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9). + // The NSMutableDictionary superclass doesn't hold any storage (so that people can implement their + // own in subclasses). As that's not the reason we're subclassing, we just delegate storage to the + // default NSMutableDictionary subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9). NSMutableDictionary *_delegate; } @@ -98,8 +91,7 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { } // Designated initializer -- (instancetype)initWithCall:(GRPCCall *)call - storage:(NSMutableDictionary *)storage { +- (instancetype)initWithCall:(GRPCCall *)call storage:(NSMutableDictionary *)storage { // TODO(jcanizales): Throw if call or storage are nil. if ((self = [super init])) { _call = call; @@ -108,10 +100,9 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { return self; } -- (instancetype) -initWithObjects:(const id _Nonnull __unsafe_unretained *)objects - forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys - count:(NSUInteger)cnt { +- (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects + forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys + count:(NSUInteger)cnt { return [self init]; } @@ -143,7 +134,7 @@ initWithObjects:(const id _Nonnull __unsafe_unretained *)objects return _delegate.count; } -- (NSEnumerator *_Nonnull)keyEnumerator { +- (NSEnumerator * _Nonnull)keyEnumerator { return [_delegate keyEnumerator]; } diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index bbda9f2f64..627b6aa86d 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -34,27 +34,27 @@ #import "GRPCWrappedCall.h" #import <Foundation/Foundation.h> -#include <grpc/byte_buffer.h> #include <grpc/grpc.h> +#include <grpc/byte_buffer.h> #include <grpc/support/alloc.h> #import "GRPCCompletionQueue.h" #import "GRPCHost.h" -#import "NSData+GRPC.h" #import "NSDictionary+GRPC.h" +#import "NSData+GRPC.h" #import "NSError+GRPC.h" @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. +@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(^_handler)(); } - (void)finish { if (_handler) { - void (^handler)() = _handler; + void(^handler)() = _handler; _handler = nil; handler(); } @@ -101,8 +101,7 @@ - (instancetype)initWithMessage:(NSData *)message handler:(void (^)())handler { if (!message) { - [NSException raise:NSInvalidArgumentException - format:@"message cannot be nil"]; + [NSException raise:NSInvalidArgumentException format:@"message cannot be nil"]; } if (self = [super init]) { _op.op = GRPC_OP_SEND_MESSAGE; @@ -138,11 +137,11 @@ grpc_metadata_array _headers; } -- (instancetype)init { +- (instancetype) init { return [self initWithHandler:nil]; } -- (instancetype)initWithHandler:(void (^)(NSDictionary *))handler { +- (instancetype) initWithHandler:(void (^)(NSDictionary *))handler { if (self = [super init]) { _op.op = GRPC_OP_RECV_INITIAL_METADATA; grpc_metadata_array_init(&_headers); @@ -153,7 +152,7 @@ _handler = ^{ __strong typeof(self) strongSelf = weakSelf; NSDictionary *metadata = [NSDictionary - grpc_dictionaryFromMetadataArray:strongSelf->_headers]; + grpc_dictionaryFromMetadataArray:strongSelf->_headers]; handler(metadata); }; } @@ -167,7 +166,7 @@ @end -@implementation GRPCOpRecvMessage { +@implementation GRPCOpRecvMessage{ grpc_byte_buffer *_receivedMessage; } @@ -193,18 +192,18 @@ @end -@implementation GRPCOpRecvStatus { +@implementation GRPCOpRecvStatus{ grpc_status_code _statusCode; char *_details; size_t _detailsCapacity; grpc_metadata_array _trailers; } -- (instancetype)init { +- (instancetype) init { return [self initWithHandler:nil]; } -- (instancetype)initWithHandler:(void (^)(NSError *, NSDictionary *))handler { +- (instancetype) initWithHandler:(void (^)(NSError *, NSDictionary *))handler { if (self = [super init]) { _op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; _op.data.recv_status_on_client.status = &_statusCode; @@ -217,11 +216,10 @@ __weak typeof(self) weakSelf = self; _handler = ^{ __strong typeof(self) strongSelf = weakSelf; - NSError *error = - [NSError grpc_errorFromStatusCode:strongSelf->_statusCode - details:strongSelf->_details]; + NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode + details:strongSelf->_details]; NSDictionary *trailers = [NSDictionary - grpc_dictionaryFromMetadataArray:strongSelf->_trailers]; + grpc_dictionaryFromMetadataArray:strongSelf->_trailers]; handler(error, trailers); }; } @@ -247,21 +245,20 @@ return [self initWithHost:nil path:nil]; } -- (instancetype)initWithHost:(NSString *)host path:(NSString *)path { +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path { if (!path || !host) { [NSException raise:NSInvalidArgumentException format:@"path and host cannot be nil."]; } if (self = [super init]) { - // Each completion queue consumes one thread. There's a trade to be made - // between creating and consuming too many threads and having contention of - // multiple calls in a single completion queue. Currently we use a singleton - // queue. + // Each completion queue consumes one thread. There's a trade to be made between creating and + // consuming too many threads and having contention of multiple calls in a single completion + // queue. Currently we use a singleton queue. _queue = [GRPCCompletionQueue completionQueue]; - _call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path - completionQueue:_queue]; + _call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path completionQueue:_queue]; if (_call == NULL) { return nil; } @@ -273,35 +270,32 @@ [self startBatchWithOperations:operations errorHandler:nil]; } -- (void)startBatchWithOperations:(NSArray *)operations - errorHandler:(void (^)())errorHandler { +- (void)startBatchWithOperations:(NSArray *)operations errorHandler:(void (^)())errorHandler { size_t nops = operations.count; grpc_op *ops_array = gpr_malloc(nops * sizeof(grpc_op)); size_t i = 0; 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) { - if (!success) { - if (errorHandler) { - errorHandler(); - } else { - return; - } - } - for (GRPCOperation *operation in operations) { - [operation finish]; - } - }), - NULL); + grpc_call_error error = grpc_call_start_batch(_call, ops_array, nops, + (__bridge_retained void *)(^(bool success){ + if (!success) { + if (errorHandler) { + errorHandler(); + } else { + return; + } + } + for (GRPCOperation *operation in operations) { + [operation finish]; + } + }), NULL); gpr_free(ops_array); if (error != GRPC_CALL_OK) { [NSException raise:NSInternalInconsistencyException - format:@"A precondition for calling grpc_call_start_batch " - @"wasn't met. Error %i", - error]; + 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.h b/src/objective-c/GRPCClient/private/NSError+GRPC.h index a9a321470c..e0c1efc1f9 100644 --- a/src/objective-c/GRPCClient/private/NSError+GRPC.h +++ b/src/objective-c/GRPCClient/private/NSError+GRPC.h @@ -36,9 +36,8 @@ @interface NSError (GRPC) /** - * Returns nil if the status code is OK. Otherwise, a NSError whose code is one - * of |GRPCErrorCode| and whose domain is |kGRPCErrorDomain|. + * Returns nil if the status code is OK. Otherwise, a NSError whose code is one of |GRPCErrorCode| + * and whose domain is |kGRPCErrorDomain|. */ -+ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode - details:(char *)details; ++ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode details:(char *)details; @end |