diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/channel/client_channel.c | 4 | ||||
-rw-r--r-- | src/cpp/client/channel.cc | 40 | ||||
-rw-r--r-- | src/cpp/client/channel.h | 15 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+Tests.h | 11 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+Tests.m | 8 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCHost.m | 39 | ||||
-rw-r--r-- | src/objective-c/tests/GRPCClientTests.m | 7 | ||||
-rw-r--r-- | src/objective-c/tests/InteropTests.h | 2 | ||||
-rw-r--r-- | src/objective-c/tests/InteropTests.m | 10 |
9 files changed, 102 insertions, 34 deletions
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index 2ee260b799..a293c93ec6 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -401,6 +401,7 @@ static void perform_transport_stream_op(grpc_call_element *elem, calld->state = CALL_WAITING_FOR_CONFIG; add_to_lb_policy_wait_queue_locked_state_config(elem); if (!chand->started_resolving && chand->resolver != NULL) { + GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver"); chand->started_resolving = 1; grpc_resolver_next(chand->resolver, &chand->incoming_configuration, @@ -701,11 +702,11 @@ void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack, gpr_mu_lock(&chand->mu_config); GPR_ASSERT(!chand->resolver); chand->resolver = resolver; - GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver"); GRPC_RESOLVER_REF(resolver, "channel"); if (chand->waiting_for_config_closures != NULL || chand->exit_idle_when_lb_policy_arrives) { chand->started_resolving = 1; + GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver"); grpc_resolver_next(resolver, &chand->incoming_configuration, &chand->on_config_changed); } @@ -724,6 +725,7 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state( } else { chand->exit_idle_when_lb_policy_arrives = 1; if (!chand->started_resolving && chand->resolver != NULL) { + GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver"); chand->started_resolving = 1; grpc_resolver_next(chand->resolver, &chand->incoming_configuration, &chand->on_config_changed); diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index 5f54e7fcc1..af7366eb01 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -48,6 +48,7 @@ #include <grpc++/impl/call.h> #include <grpc++/impl/rpc_method.h> #include <grpc++/status.h> +#include <grpc++/time.h> namespace grpc { @@ -95,4 +96,43 @@ void* Channel::RegisterMethod(const char* method) { host_.empty() ? NULL : host_.c_str()); } +grpc_connectivity_state Channel::GetState(bool try_to_connect) { + return grpc_channel_check_connectivity_state(c_channel_, try_to_connect); +} + +namespace { +class TagSaver GRPC_FINAL : public CompletionQueueTag { + public: + explicit TagSaver(void* tag) : tag_(tag) {} + ~TagSaver() GRPC_OVERRIDE {} + bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE { + *tag = tag_; + delete this; + return true; + } + private: + void* tag_; +}; + +} // namespace + +void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline, + CompletionQueue* cq, void* tag) { + TagSaver* tag_saver = new TagSaver(tag); + grpc_channel_watch_connectivity_state(c_channel_, last_observed, deadline, + cq->cq(), tag_saver); +} + +bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline) { + CompletionQueue cq; + bool ok = false; + void* tag = NULL; + NotifyOnStateChangeImpl(last_observed, deadline, &cq, NULL); + cq.Next(&tag, &ok); + GPR_ASSERT(tag == NULL); + return ok; +} + } // namespace grpc diff --git a/src/cpp/client/channel.h b/src/cpp/client/channel.h index 8660146856..cb8e8d98d2 100644 --- a/src/cpp/client/channel.h +++ b/src/cpp/client/channel.h @@ -56,13 +56,22 @@ class Channel GRPC_FINAL : public GrpcLibrary, public ChannelInterface { Channel(const grpc::string& host, grpc_channel* c_channel); ~Channel() GRPC_OVERRIDE; - virtual void* RegisterMethod(const char* method) GRPC_OVERRIDE; - virtual Call CreateCall(const RpcMethod& method, ClientContext* context, + void* RegisterMethod(const char* method) GRPC_OVERRIDE; + Call CreateCall(const RpcMethod& method, ClientContext* context, CompletionQueue* cq) GRPC_OVERRIDE; - virtual void PerformOpsOnCall(CallOpSetInterface* ops, + void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) GRPC_OVERRIDE; + grpc_connectivity_state GetState(bool try_to_connect) GRPC_OVERRIDE; + private: + void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline, CompletionQueue* cq, + void* tag) GRPC_OVERRIDE; + + bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline) GRPC_OVERRIDE; + const grpc::string host_; grpc_channel* const c_channel_; // owned }; diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.h b/src/objective-c/GRPCClient/GRPCCall+Tests.h index 3d617b05d9..cca1614606 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.h +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.h @@ -33,13 +33,22 @@ #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. @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|. -// Must be called before any gRPC call to that host is made. +// +// 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. +// +// 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; @end diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.m b/src/objective-c/GRPCClient/GRPCCall+Tests.m index 7c5b81d661..bade0b2920 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.m +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.m @@ -36,12 +36,18 @@ #import "private/GRPCHost.h" @implementation GRPCCall (Tests) + + (void)useTestCertsPath:(NSString *)certsPath testName:(NSString *)testName forHost:(NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; - hostConfig.secure = YES; hostConfig.pathToCertificates = certsPath; hostConfig.hostNameOverride = testName; } + ++ (void)useInsecureConnectionsForHost:(NSString *)host { + GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; + hostConfig.secure = NO; +} + @end diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 5d9c48a524..6636c48620 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -58,22 +58,14 @@ // Default initializer. - (instancetype)initWithAddress:(NSString *)address { - // Verify and normalize the address, and decide whether to use SSL. - if (![address rangeOfString:@"://"].length) { - // No scheme provided; assume https. - address = [@"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 && !hostURL.port) { + address = [hostURL.host stringByAppendingString:@":443"]; } - NSURL *hostURL = [NSURL URLWithString:address]; - if (!hostURL) { - [NSException raise:NSInvalidArgumentException format:@"Invalid URL: %@", address]; - } - NSString *scheme = hostURL.scheme; - if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) { - [NSException raise:NSInvalidArgumentException format:@"URL scheme %@ isn't supported.", scheme]; - } - // If the user didn't specify a port (hostURL.port is nil), provide a default one. - NSNumber *port = hostURL.port ?: [scheme isEqualToString:@"https"] ? @443 : @80; - address = [@[hostURL.host, port] componentsJoinedByString:@":"]; // Look up the GRPCHost in the cache. static NSMutableDictionary *hostCache; @@ -84,19 +76,15 @@ @synchronized(hostCache) { GRPCHost *cachedHost = hostCache[address]; if (cachedHost) { - // We could verify here that the cached host uses the same protocol that we're expecting. But - // creating non-SSL channels by adding "http://" to the address is going away (to make the use - // of insecure channels less subtle), so it's not worth it now. return cachedHost; } - if ((self = [super init])) { - _address = address; - _secure = [scheme isEqualToString:@"https"]; - hostCache[address] = self; - } - return self; + if ((self = [super init])) { + _address = address; + _secure = YES; + hostCache[address] = self; } + return self; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue { @@ -131,4 +119,7 @@ return _hostNameOverride ?: _address; } +// TODO(jcanizales): Don't let set |secure| to |NO| if |pathToCertificates| or |hostNameOverride| +// have been set. Don't let set either of the latter if |secure| has been set to |NO|. + @end diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 103e5ca3d4..e5d7e43ed9 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -35,6 +35,7 @@ #import <XCTest/XCTest.h> #import <GRPCClient/GRPCCall.h> +#import <GRPCClient/GRPCCall+Tests.h> #import <ProtoRPC/ProtoMethod.h> #import <RemoteTest/Messages.pbobjc.h> #import <RxLibrary/GRXWriteable.h> @@ -43,8 +44,7 @@ // These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall) // rather than a generated proto library on top of it. -// grpc-test.sandbox.google.com -static NSString * const kHostAddress = @"http://localhost:5050"; +static NSString * const kHostAddress = @"localhost:5050"; static NSString * const kPackage = @"grpc.testing"; static NSString * const kService = @"TestService"; @@ -58,6 +58,9 @@ static ProtoMethod *kUnaryCallMethod; @implementation GRPCClientTests - (void)setUp { + // Register test server as non-SSL. + [GRPCCall useInsecureConnectionsForHost:kHostAddress]; + // This method isn't implemented by the remote server. kInexistentMethod = [[ProtoMethod alloc] initWithPackage:kPackage service:kService diff --git a/src/objective-c/tests/InteropTests.h b/src/objective-c/tests/InteropTests.h index c675c8d241..4eb97e9e06 100644 --- a/src/objective-c/tests/InteropTests.h +++ b/src/objective-c/tests/InteropTests.h @@ -37,7 +37,7 @@ // https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md @interface InteropTests : XCTestCase -// Returns @"http://localhost:5050". +// Returns @"localhost:5050". // Override in a subclass to perform the same tests against a different address. // For interop tests, use @"grpc-test.sandbox.google.com". + (NSString *)host; diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index a6611d27be..b61d567464 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -35,6 +35,7 @@ #include <grpc/status.h> +#import <GRPCClient/GRPCCall+Tests.h> #import <ProtoRPC/ProtoRPC.h> #import <RemoteTest/Empty.pbobjc.h> #import <RemoteTest/Messages.pbobjc.h> @@ -75,15 +76,22 @@ } @end +#pragma mark Tests + +static NSString * const kLocalCleartextHost = @"localhost:5050"; + @implementation InteropTests { RMTTestService *_service; } + (NSString *)host { - return @"http://localhost:5050"; + return kLocalCleartextHost; } - (void)setUp { + // Register test server as non-SSL. + [GRPCCall useInsecureConnectionsForHost:kLocalCleartextHost]; + _service = [[RMTTestService alloc] initWithHost:self.class.host]; } |